balanceofsatoshis 11.18.1 → 11.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +3 -0
- package/bos +6 -9
- package/network/pay.js +4 -0
- package/network/probe_destination.js +14 -2
- package/network/push_payment.js +39 -12
- package/package.json +5 -5
- package/telegram/start_telegram_bot.js +41 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## 11.20.2
|
|
4
|
+
|
|
5
|
+
- `change-channel-capacity`: Increase RBF fee buffer when increasing capacity
|
|
6
|
+
- `telegram`: Redesign /invoice user interface to be button based
|
|
7
|
+
|
|
8
|
+
## 11.20.1
|
|
9
|
+
|
|
10
|
+
- `fees`: Correct issue where fee rate could not be set to zero
|
|
11
|
+
|
|
12
|
+
## 11.20.0
|
|
13
|
+
|
|
14
|
+
- `send`: Add support for paying to zero-amount BOLT 11 payment requests
|
|
15
|
+
|
|
16
|
+
## 11.19.0
|
|
17
|
+
|
|
18
|
+
- `change-channel-capacity`: Allow changing private/public status of channel
|
|
19
|
+
|
|
3
20
|
## 11.18.1
|
|
4
21
|
|
|
5
22
|
This release fixes an important issue with the experimental
|
package/README.md
CHANGED
|
@@ -89,6 +89,9 @@ bos chart-fees-paid
|
|
|
89
89
|
# Show a chart of payments received
|
|
90
90
|
bos chart-payments-received
|
|
91
91
|
|
|
92
|
+
# Remove old failed payment data for probes and other failed payments
|
|
93
|
+
bos clean-failed-payments
|
|
94
|
+
|
|
92
95
|
# See details on how closed channels resolved on-chain
|
|
93
96
|
bos closed
|
|
94
97
|
|
package/bos
CHANGED
|
@@ -1390,11 +1390,11 @@ prog
|
|
|
1390
1390
|
})
|
|
1391
1391
|
|
|
1392
1392
|
// Send funds to a destination
|
|
1393
|
-
.command('send', 'Send funds to a node')
|
|
1393
|
+
.command('send', 'Send funds to a node off-chain')
|
|
1394
1394
|
.help('Formulas supported in amount, and N*USD or N*EUR')
|
|
1395
1395
|
.help('Also supported in formulas: LIQUIDITY, INBOUND, OUTBOUND (with peer)')
|
|
1396
1396
|
.help('OUT_INBOUND, OUT_OUTBOUND (when specifying outbound peer)')
|
|
1397
|
-
.argument('<to>', 'Send to node with public key')
|
|
1397
|
+
.argument('<to>', 'Send to node with public key, or zero amount pay request')
|
|
1398
1398
|
.option('--amount <amount>', 'Amount to send to destination', STRING, '1')
|
|
1399
1399
|
.option('--avoid <avoid>', 'Avoid forwarding via node/chan/tag', REPEATABLE)
|
|
1400
1400
|
.option('--dryrun', 'Avoid actually sending funds')
|
|
@@ -1409,20 +1409,16 @@ prog
|
|
|
1409
1409
|
.action((args, options, logger) => {
|
|
1410
1410
|
return new Promise(async (resolve, reject) => {
|
|
1411
1411
|
try {
|
|
1412
|
-
const {lnd} = await lndForNode(logger, options.node);
|
|
1413
|
-
|
|
1414
|
-
const destination = await lnSync.findKey({lnd, query: args.to});
|
|
1415
|
-
|
|
1416
1412
|
return network.pushPayment({
|
|
1417
|
-
lnd,
|
|
1418
1413
|
logger,
|
|
1419
1414
|
amount: options.amount,
|
|
1420
1415
|
avoid: flatten([options.avoid].filter(n => !!n)),
|
|
1421
|
-
destination:
|
|
1416
|
+
destination: args.to,
|
|
1422
1417
|
fs: {getFile: readFile},
|
|
1423
1418
|
in_through: options.in,
|
|
1424
1419
|
is_dry_run: options.dryrun,
|
|
1425
1420
|
is_omitting_message_from: options.messageOmitFromKey,
|
|
1421
|
+
lnd: (await lndForNode(logger, options.node)).lnd,
|
|
1426
1422
|
max_fee: options.maxFee,
|
|
1427
1423
|
message: options.message,
|
|
1428
1424
|
quiz_answers: flatten([options.quiz].filter(n => !!n)),
|
|
@@ -1587,6 +1583,7 @@ prog
|
|
|
1587
1583
|
.help('Connect to a Telegram bot. Create bot: tg://resolve?domain=botfather')
|
|
1588
1584
|
.help('After creating the bot start chatting with the bot for connect code')
|
|
1589
1585
|
.help('Supported updates: forwards, received payments, etc')
|
|
1586
|
+
.help('Multiple nodes are supported by repeating the `--node` flag')
|
|
1590
1587
|
.help('See README for info on persisting the bot through Docker/nohup')
|
|
1591
1588
|
.option('--budget <amount>', 'Spending amount to allow', INT, Number())
|
|
1592
1589
|
.option('--connect <connect_code>', 'Connection code', INT)
|
|
@@ -1639,7 +1636,7 @@ prog
|
|
|
1639
1636
|
})
|
|
1640
1637
|
|
|
1641
1638
|
// Transfer funds between own nodes
|
|
1642
|
-
.command('transfer', 'Send funds to a saved node')
|
|
1639
|
+
.command('transfer', 'Send funds off-chain to a saved node')
|
|
1643
1640
|
.argument('<to>', 'Saved node name')
|
|
1644
1641
|
.argument('[amount]', 'Amount to transfer', STRING, '1')
|
|
1645
1642
|
.help('Formulas are supported in amount')
|
package/network/pay.js
CHANGED
|
@@ -82,6 +82,10 @@ module.exports = (args, cbk) => {
|
|
|
82
82
|
return cbk([400, 'PaymentRequestExpired']);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
if (!BigInt(parsePaymentRequest({request: args.request}).mtokens)) {
|
|
86
|
+
return cbk([400, 'UseSendToPayZeroAmountPaymentRequests']);
|
|
87
|
+
}
|
|
88
|
+
|
|
85
89
|
return cbk();
|
|
86
90
|
},
|
|
87
91
|
|
|
@@ -157,6 +157,20 @@ module.exports = (args, cbk) => {
|
|
|
157
157
|
return cbk([400, 'InvoiceIsExpired']);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
// Exit early when tokens are specified for a request
|
|
161
|
+
if (!!args.tokens) {
|
|
162
|
+
return cbk(null, {
|
|
163
|
+
cltv_delta: details.cltv_delta,
|
|
164
|
+
destination: details.destination,
|
|
165
|
+
features: details.features,
|
|
166
|
+
id: details.id,
|
|
167
|
+
mtokens: tokAsMtok(args.tokens),
|
|
168
|
+
payment: details.payment,
|
|
169
|
+
routes: details.routes,
|
|
170
|
+
tokens: args.tokens,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
160
174
|
args.logger.info({
|
|
161
175
|
description: details.description || undefined,
|
|
162
176
|
destination: details.destination,
|
|
@@ -175,8 +189,6 @@ module.exports = (args, cbk) => {
|
|
|
175
189
|
routes: details.routes,
|
|
176
190
|
tokens: details.tokens,
|
|
177
191
|
});
|
|
178
|
-
|
|
179
|
-
return cbk(null, parsePaymentRequest({request: args.request}));
|
|
180
192
|
} catch (err) {
|
|
181
193
|
return cbk([400, 'FailedToDecodePaymentRequest', {err}]);
|
|
182
194
|
}
|
package/network/push_payment.js
CHANGED
|
@@ -6,6 +6,7 @@ const {getIdentity} = require('ln-service');
|
|
|
6
6
|
const {getNetwork} = require('ln-sync');
|
|
7
7
|
const {getPeerLiquidity} = require('ln-sync');
|
|
8
8
|
const {getPrices} = require('@alexbosworth/fiat');
|
|
9
|
+
const {parsePaymentRequest} = require('ln-service');
|
|
9
10
|
const {returnResult} = require('asyncjs-util');
|
|
10
11
|
|
|
11
12
|
const {getIgnores} = require('./../routing');
|
|
@@ -64,10 +65,6 @@ module.exports = (args, cbk) => {
|
|
|
64
65
|
return cbk([400, 'ExpectedArrayOfAvoidDirectivesToSendPushPayment']);
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
if (!isPublicKey(args.destination)) {
|
|
68
|
-
return cbk([400, 'ExpectedDestinationToPushPaymentTo']);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
68
|
if (!args.fs) {
|
|
72
69
|
return cbk([400, 'ExpectedFileSystemMethodsToPushPayment']);
|
|
73
70
|
}
|
|
@@ -150,6 +147,33 @@ module.exports = (args, cbk) => {
|
|
|
150
147
|
// Get tags for figuring out avoid flags
|
|
151
148
|
getTags: ['validate', ({}, cbk) => getTags({fs: args.fs}, cbk)],
|
|
152
149
|
|
|
150
|
+
// Payment details
|
|
151
|
+
payment: ['validate', ({}, cbk) => {
|
|
152
|
+
try {
|
|
153
|
+
const {destination, mtokens} = parsePaymentRequest({
|
|
154
|
+
request: args.destination,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
if (!!BigInt(mtokens)) {
|
|
158
|
+
return cbk([400, 'ExpectedZeroAmountPayRequestToSendFunds']);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return cbk(null, {destination, request: args.destination});
|
|
162
|
+
} catch (_) {
|
|
163
|
+
return findKey({
|
|
164
|
+
lnd: args.lnd,
|
|
165
|
+
query: args.destination,
|
|
166
|
+
},
|
|
167
|
+
(err, res) => {
|
|
168
|
+
if (!!err) {
|
|
169
|
+
return cbk(err);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return cbk(null, {destination: res.public_key, is_push: true});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}],
|
|
176
|
+
|
|
153
177
|
// Get ignores
|
|
154
178
|
getIgnores: [
|
|
155
179
|
'getChannels',
|
|
@@ -241,11 +265,12 @@ module.exports = (args, cbk) => {
|
|
|
241
265
|
'getChannels',
|
|
242
266
|
'getNetwork',
|
|
243
267
|
'getOutKey',
|
|
244
|
-
|
|
268
|
+
'payment',
|
|
269
|
+
({fiatRates, getChannels, getNetwork, getOutKey, payment}, cbk) =>
|
|
245
270
|
{
|
|
246
271
|
// Total remote balance including pending if pending fails
|
|
247
272
|
const inbound = getChannels.channels
|
|
248
|
-
.filter(n => n.partner_public_key ===
|
|
273
|
+
.filter(n => n.partner_public_key === payment.destination)
|
|
249
274
|
.reduce((sum, chan) => {
|
|
250
275
|
// Treat incoming payment as if they were still remote balance
|
|
251
276
|
const inbound = chan.pending_payments.filter(n => !n.is_outgoing);
|
|
@@ -285,7 +310,7 @@ module.exports = (args, cbk) => {
|
|
|
285
310
|
|
|
286
311
|
// Total local balance including pending if pending fails
|
|
287
312
|
const outbound = getChannels.channels
|
|
288
|
-
.filter(n => n.partner_public_key ===
|
|
313
|
+
.filter(n => n.partner_public_key === payment.destination)
|
|
289
314
|
.reduce((sum, chan) => {
|
|
290
315
|
// Treat outgoing payment as if they were still local balance
|
|
291
316
|
const outbound = chan.pending_payments
|
|
@@ -307,7 +332,7 @@ module.exports = (args, cbk) => {
|
|
|
307
332
|
eur: !!eur ? eur.unit : undefined,
|
|
308
333
|
liquidity: sumOf(
|
|
309
334
|
getChannels.channels
|
|
310
|
-
.filter(n => n.partner_public_key ===
|
|
335
|
+
.filter(n => n.partner_public_key === payment.destination)
|
|
311
336
|
.map(n => n.capacity)
|
|
312
337
|
),
|
|
313
338
|
out_inbound: outInbound,
|
|
@@ -333,7 +358,8 @@ module.exports = (args, cbk) => {
|
|
|
333
358
|
'getInKey',
|
|
334
359
|
'getOutKey',
|
|
335
360
|
'parseAmount',
|
|
336
|
-
|
|
361
|
+
'payment',
|
|
362
|
+
({getIgnores, getInKey, getOutKey, parseAmount, payment}, cbk) =>
|
|
337
363
|
{
|
|
338
364
|
if (parseAmount.tokens < minTokens) {
|
|
339
365
|
return cbk([400, 'ExpectedNonZeroAmountToPushPayment']);
|
|
@@ -341,7 +367,7 @@ module.exports = (args, cbk) => {
|
|
|
341
367
|
|
|
342
368
|
args.logger.info({
|
|
343
369
|
paying: formatTokens({tokens: parseAmount.tokens}).display,
|
|
344
|
-
to:
|
|
370
|
+
to: payment.destination,
|
|
345
371
|
});
|
|
346
372
|
|
|
347
373
|
if (!!args.is_dry_run) {
|
|
@@ -349,14 +375,14 @@ module.exports = (args, cbk) => {
|
|
|
349
375
|
}
|
|
350
376
|
|
|
351
377
|
return probeDestination({
|
|
352
|
-
destination:
|
|
378
|
+
destination: payment.destination,
|
|
353
379
|
fs: args.fs,
|
|
354
380
|
ignore: getIgnores.ignore,
|
|
355
381
|
lnd: args.lnd,
|
|
356
382
|
logger: args.logger,
|
|
357
383
|
in_through: getInKey,
|
|
358
384
|
is_omitting_message_from: args.is_omitting_message_from,
|
|
359
|
-
is_push:
|
|
385
|
+
is_push: payment.is_push,
|
|
360
386
|
is_real_payment: true,
|
|
361
387
|
max_fee: args.max_fee,
|
|
362
388
|
message: args.message,
|
|
@@ -365,6 +391,7 @@ module.exports = (args, cbk) => {
|
|
|
365
391
|
value: utf8AsHex(answer),
|
|
366
392
|
})),
|
|
367
393
|
out_through: getOutKey,
|
|
394
|
+
request: payment.request,
|
|
368
395
|
timeout_minutes: args.timeout_minutes,
|
|
369
396
|
tokens: parseAmount.tokens,
|
|
370
397
|
},
|
package/package.json
CHANGED
|
@@ -36,15 +36,15 @@
|
|
|
36
36
|
"invoices": "2.0.2",
|
|
37
37
|
"ln-accounting": "5.0.5",
|
|
38
38
|
"ln-service": "53.2.0",
|
|
39
|
-
"ln-sync": "3.6.
|
|
40
|
-
"ln-telegram": "3.
|
|
39
|
+
"ln-sync": "3.6.1",
|
|
40
|
+
"ln-telegram": "3.5.0",
|
|
41
41
|
"moment": "2.29.1",
|
|
42
|
-
"paid-services": "3.
|
|
42
|
+
"paid-services": "3.5.1",
|
|
43
43
|
"probing": "2.0.1",
|
|
44
44
|
"psbt": "1.1.10",
|
|
45
45
|
"qrcode-terminal": "0.12.0",
|
|
46
46
|
"sanitize-filename": "1.6.3",
|
|
47
|
-
"table": "6.
|
|
47
|
+
"table": "6.8.0",
|
|
48
48
|
"update-notifier": "5.1.0",
|
|
49
49
|
"window-size": "1.1.1"
|
|
50
50
|
},
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis --push .",
|
|
81
81
|
"test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -t 60 test/arrays/*.js test/balances/*.js test/chain/*.js test/display/*.js test/encryption/*.js test/lnd/*.js test/network/*.js test/nodes/*.js test/peers/*.js test/responses/*.js test/routing/*.js test/services/*.js test/swaps/*.js test/tags/*.js test/wallets/*.js"
|
|
82
82
|
},
|
|
83
|
-
"version": "11.
|
|
83
|
+
"version": "11.20.2"
|
|
84
84
|
}
|
|
@@ -12,6 +12,7 @@ const {getTransactionRecord} = require('ln-sync');
|
|
|
12
12
|
const {getWalletInfo} = require('ln-service');
|
|
13
13
|
const {handleBackupCommand} = require('ln-telegram');
|
|
14
14
|
const {handleBlocknotifyCommand} = require('ln-telegram');
|
|
15
|
+
const {handleButtonPush} = require('ln-telegram');
|
|
15
16
|
const {handleConnectCommand} = require('ln-telegram');
|
|
16
17
|
const {handleCostsCommand} = require('ln-telegram');
|
|
17
18
|
const {handleEarningsCommand} = require('ln-telegram');
|
|
@@ -23,6 +24,7 @@ const {handlePendingCommand} = require('ln-telegram');
|
|
|
23
24
|
const {handleVersionCommand} = require('ln-telegram');
|
|
24
25
|
const {InputFile} = require('grammy');
|
|
25
26
|
const inquirer = require('inquirer');
|
|
27
|
+
const {isMessageReplyToInvoice} = require('ln-telegram');
|
|
26
28
|
const {notifyOfForwards} = require('ln-telegram');
|
|
27
29
|
const {postChainTransaction} = require('ln-telegram');
|
|
28
30
|
const {postClosedMessage} = require('ln-telegram');
|
|
@@ -38,6 +40,7 @@ const {subscribeToChannels} = require('ln-service');
|
|
|
38
40
|
const {subscribeToInvoices} = require('ln-service');
|
|
39
41
|
const {subscribeToPastPayments} = require('ln-service');
|
|
40
42
|
const {subscribeToTransactions} = require('ln-service');
|
|
43
|
+
const {updateInvoiceFromReply} = require('ln-telegram');
|
|
41
44
|
|
|
42
45
|
const interaction = require('./interaction');
|
|
43
46
|
const markdown = {parse_mode: 'Markdown'};
|
|
@@ -298,19 +301,17 @@ module.exports = ({fs, id, limits, lnds, logger, payments, request}, cbk) => {
|
|
|
298
301
|
return;
|
|
299
302
|
});
|
|
300
303
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
return;
|
|
304
|
+
// Handle creation of an invoice
|
|
305
|
+
bot.command('invoice', async ctx => {
|
|
306
|
+
try {
|
|
307
|
+
await handleInvoiceCommand({
|
|
308
|
+
ctx,
|
|
309
|
+
id: connectedId,
|
|
310
|
+
nodes: getNodes,
|
|
311
|
+
});
|
|
312
|
+
} catch (err) {
|
|
313
|
+
logger.error({err});
|
|
314
|
+
}
|
|
314
315
|
});
|
|
315
316
|
|
|
316
317
|
bot.command('mempool', async ctx => {
|
|
@@ -425,7 +426,7 @@ module.exports = ({fs, id, limits, lnds, logger, payments, request}, cbk) => {
|
|
|
425
426
|
'/connect - Connect bot',
|
|
426
427
|
'/costs - View costs over the past week',
|
|
427
428
|
'/earnings - View earnings over the past week',
|
|
428
|
-
'/invoice - Make an invoice',
|
|
429
|
+
'/invoice [amount] [memo] - Make an invoice',
|
|
429
430
|
'/liquidity [with] - View node liquidity',
|
|
430
431
|
'/mempool - BTC mempool report',
|
|
431
432
|
'/pay - Pay an invoice',
|
|
@@ -441,6 +442,32 @@ module.exports = ({fs, id, limits, lnds, logger, payments, request}, cbk) => {
|
|
|
441
442
|
}
|
|
442
443
|
});
|
|
443
444
|
|
|
445
|
+
// Handle button push type commands
|
|
446
|
+
bot.on('callback_query:data', async ctx => {
|
|
447
|
+
try {
|
|
448
|
+
await handleButtonPush({ctx, id: connectedId, nodes: getNodes});
|
|
449
|
+
} catch (err) {
|
|
450
|
+
logger.error({err});
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Listen for replies to created invoice messages
|
|
455
|
+
bot.on('message').filter(
|
|
456
|
+
ctx => isMessageReplyToInvoice({ctx, nodes: getNodes}),
|
|
457
|
+
async ctx => {
|
|
458
|
+
try {
|
|
459
|
+
return await updateInvoiceFromReply({
|
|
460
|
+
ctx,
|
|
461
|
+
api: bot.api,
|
|
462
|
+
id: connectedId,
|
|
463
|
+
nodes: getNodes,
|
|
464
|
+
});
|
|
465
|
+
} catch (err) {
|
|
466
|
+
logger.error({err});
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
);
|
|
470
|
+
|
|
444
471
|
bot.start();
|
|
445
472
|
|
|
446
473
|
return cbk();
|