-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.html
276 lines (248 loc) · 11.8 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
<html>
<head>
<title>TLV shop - buy stickers atomically over the Lightning Network</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body class="bg-light">
<div class="container">
<div class="py-5">
<div class="text-center">
<h1>Welcome to <a href="https://tlvshop.com">tlvshop.com</a>!</h1>
<p class="lead">
Buy stickers atomically over the Lightning Network
<br/><br/>
<span style="color: red">
<strong>Update April 15 2020</strong>:
This was an interesting experiment, thanks to everyone who participated. We ran out of stickers and
have now disabled the shop. While this website still works, you won't be able to order stickers
anymore.<br/><br/>
All successfully placed orders have been fulfilled.
</span>
</p>
</div>
<div class="mb-5"></div>
<p>
This is not an ordinary webshop. There is no browser, no shopping
cart, no checkout page and no credit card required. What is it then?
It is a 100% pure Lightning shop, possibly one of the first of its
kind.
<br/><br/>
Pure Lightning means that the only communication between buyer and us is a
Lightning payment. Since the introduction of custom tlv records
(hence the name <a href="https://tlvshop.com">tlvshop.com</a>), it
is possible to attach arbitrary data to a payment. You can use this new
functionality to attach a delivery address to the payment.
<br/><br/>
Users of <code>LND</code> are able to order, pay for and get stickers delivered
with just a single <code>lncli</code>
command. The same privacy guarantees that apply to a Lightning
payment will also apply to your order details.
<br/><br/>
The current offering is rather limited. In fact the only article that we
currently sell is a set of three cool "RUN LND" stickers:<br/>
</p>
<div class="text-center">
<img src="runlnd.png" alt="RUN LND" width="300" style="margin: 15px"><br/>
<small>
Sticker design by
<a href="https://twitter.com/send_bitcoins">@send_bitcoins</a>/<a href="https://sendbitcoin.lol">sendbitcoin.lol</a>,
inspired by <a href="https://github.com/wbobeirne/run-lnd-store">github.com/wbobeirne/run-lnd-store</a>
</small>
</div>
<br/>
<p>
We don't advertize a price for the set of stickers. We could
announce a price right here on this page, but that would go against
the idea of pure Lightning. Ideally a price list would be obtainable
through Lightning, but that is difficult to realize with the
protocol as it is today. As a workaround you can use trial and error
to discover the current price. Payments with an insufficient amount
will be cancelled back instantly.
<br/><br/>
To make it easy to place an order, an <code>lncli</code> command line generator
is provided below. Please note that none of what you enter there is sent out from this webpage directly.
You could download this page and run it offline to be sure.
<br/><br/>
Also, make sure you enter your address correctly. If you leave the
email field blank, we won't be able to contact you.
<br/><br/>
Happy buying!
</p>
</div>
<div class="row">
<div class="col-md-12">
<h4 class="mb-3">Delivery address</h4>
<form class="needs-validation" novalidate id="orderform">
<div class="row">
<div class="col-md-6 mb-3">
<label for="firstName">First name</label>
<input type="text" class="form-control" id="firstName" required>
<div class="invalid-feedback">
Valid first name is required.
</div>
</div>
<div class="col-md-6 mb-3">
<label for="lastName">Last name</label>
<input type="text" class="form-control" id="lastName" required>
<div class="invalid-feedback">
Valid last name is required.
</div>
</div>
</div>
<div class="mb-3">
<label for="address">Address</label>
<input type="text" class="form-control" id="address" placeholder="1234 Main St" required>
<div class="invalid-feedback">
Please enter your shipping address.
</div>
</div>
<div class="mb-3">
<label for="address2">Address 2 <span class="text-muted">(Optional)</span></label>
<input type="text" class="form-control" id="address2" placeholder="Apartment or suite">
</div>
<div class="row">
<div class="col-md-5 mb-3">
<label for="country">Country</label>
<select class="custom-select d-block w-100" id="country" required>
<option value="">Choose...</option>
</select>
<div class="invalid-feedback">
Please select a valid country.
</div>
</div>
<div class="col-md-4 mb-3">
<label for="state">State</label>
<select class="custom-select d-block w-100" id="state" required>
<option value="">Choose...</option>
</select>
<div class="invalid-feedback">
Please provide a valid state.
</div>
</div>
<div class="col-md-3 mb-3">
<label for="zip">Zip</label>
<input type="text" class="form-control" id="zip" required>
<div class="invalid-feedback">
Zip code required.
</div>
</div>
</div>
<div class="mb-3">
<label for="city">City</label>
<input type="text" class="form-control" id="city">
<div class="invalid-feedback">
Please enter a valid city.
</div>
</div>
<div class="mb-3">
<label for="amount">Amount (sats)</label>
<input type="number" class="form-control" id="amount" placeholder="find out">
<div class="invalid-feedback">
Please enter a valid amount in satoshis.
</div>
</div>
<div class="mb-3">
<label for="email">Email <span class="text-muted">(Optional)</span></label>
<input type="email" class="form-control" id="email" placeholder="[email protected]">
<div class="invalid-feedback">
Please enter a valid email address for shipping updates.
</div>
</div>
</form>
</div>
<div class="col-md-12">
<h4 class="mb-3">The command to run</h4>
<div class="mb-3">
<label for="data">This is the raw order data that will be sent along with the payment:</label>
<input type="text" class="form-control" id="data" disabled aria-disabled="true">
</div>
<p>
All you need to do is to run the following command which will send a "keysend" payment with the order
data encoded in hex. If the payment succeeds, the order is submitted.
If not, try a different price and/or make sure you are able to pay on mainnet.
</p>
<kbd id="command"></kbd>
<textarea id="command-hidden" class="sr-only"></textarea>
<div class="pb-5"></div>
<button class="btn btn-secondary" id="copy">Copy command to clipboard</button>
<div class="pb-5"></div>
Build your own TLV shop by <a href="https://github.com/joostjager/tlvshop.com">forking this code on
GitHub</a>.
<div class="pb-5"></div>
<div class="pb-5"></div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
<script src="countries.js"></script>
<script>
const dataTypeShippingAddress = 98117121;
const destinationPubkey = "<node_pubkey>";
const command = `lncli sendpayment --keysend --dest ${destinationPubkey}`;
// country/state script by IshanDemon, visit github.com/IshanDemon
populateCountries("country", "state");
$(document).ready(function () {
update();
$('#orderform input,select').keyup(update).change(update);
$('#copy').click(function () {
const cmdEl = document.getElementById('command-hidden');
cmdEl.select();
cmdEl.setSelectionRange(0, 99999);
document.execCommand('copy');
});
});
function update() {
let firstName = $('#firstName').val();
let lastName = $('#lastName').val();
let address = $('#address').val();
let address2 = $('#address2').val();
let zip = $('#zip').val();
let state = $('#state').val();
let country = $('#country').val();
let city = $('#city').val();
let email = $('#email').val();
let addr = [
`${firstName} ${lastName}`,
address, address2,
`${state} ${zip} ${city}`,
country,
email
].join('|');
let amount = $('#amount').val();
$('#data').val(addr);
let cmd = '';
if (!firstName || !lastName || !address || !zip || !amount || !country || !city) {
cmd = '<please fill in all required fields first>';
} else {
cmd = `${command} --data ${dataTypeShippingAddress}=${toHex(addr)} --amt ${amount}`;
}
$('#command').text(cmd);
$('#command-hidden').text(cmd);
}
function toHex(str) {
let hex = '';
try {
hex = unescape(encodeURIComponent(str))
.split('').map(function (v) {
return v.charCodeAt(0).toString(16)
}).join('')
} catch (e) {
hex = str;
console.log('invalid text input: ' + str)
}
return hex
}
</script>
</body>
</html>