balanceofsatoshis 13.7.2 → 13.9.0
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 +8 -0
- package/bos +15 -6
- package/offchain/create_invoice.js +124 -9
- package/offchain/sign_payment_request.js +74 -10
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## 13.9.0
|
|
4
|
+
|
|
5
|
+
- `create-channel-group`: Add `--allow` to order and allow only specific nodes
|
|
6
|
+
|
|
7
|
+
## 13.8.0
|
|
8
|
+
|
|
9
|
+
- `invoice`: Add `--virtual` and `--virtual-fee-rate` to use virtual channel
|
|
10
|
+
|
|
3
11
|
## 13.7.2
|
|
4
12
|
|
|
5
13
|
- `invoice`: Fix payment encoding to include invoice feature bits
|
package/bos
CHANGED
|
@@ -524,9 +524,11 @@ prog
|
|
|
524
524
|
})
|
|
525
525
|
|
|
526
526
|
// Coordinate a new group channel
|
|
527
|
-
.command('create-group
|
|
528
|
-
.
|
|
529
|
-
.help('
|
|
527
|
+
.command('create-channel-group', 'Coordinate balanced channels group')
|
|
528
|
+
.help('Other nodes can join the group using join-channel-group')
|
|
529
|
+
.help('When using --allow, all joining nodes must be identified')
|
|
530
|
+
.help('To specify order of group pairings, order using --allow ordering')
|
|
531
|
+
.option('--allow <public_key>', 'Only allow these nodes to join', REPEATABLE)
|
|
530
532
|
.option('--capacity <channel_capacity>', 'Channel capacity', INT, 5e6)
|
|
531
533
|
.option('--fee-rate <per_vbyte>', 'Chain fee rate for open', INT)
|
|
532
534
|
.option('--node <node_name>', 'Use saved node to create channels group')
|
|
@@ -543,6 +545,7 @@ prog
|
|
|
543
545
|
logger,
|
|
544
546
|
capacity: options.capacity,
|
|
545
547
|
count: options.size,
|
|
548
|
+
members: flatten([options.allow].filter(n => !!n)),
|
|
546
549
|
rate: options.feeRate || floor(defaultRate.tokens_per_vbyte),
|
|
547
550
|
},
|
|
548
551
|
responses.returnObject({exit, logger, reject, resolve}));
|
|
@@ -1057,24 +1060,31 @@ prog
|
|
|
1057
1060
|
.help('Amount can take m/k variables: 5*m for 5 million, 250*k = 0.0025')
|
|
1058
1061
|
.help('Fiat conversion is supported in amount, N*USD or N*EUR')
|
|
1059
1062
|
.help(`Fiat rate providers: ${priceProviders.join(', ')}`)
|
|
1063
|
+
.help('--virtual invoices cannot be used with payers who probe before pay')
|
|
1064
|
+
.help('Only one --virtual invoice can be active at a time')
|
|
1060
1065
|
.argument('[amount]', 'Amount for invoice', STRING, '0')
|
|
1061
1066
|
.option('--for <description>', 'What is the invoice requesting payment for')
|
|
1062
1067
|
.option('--include-hints', 'Include the default set of hop hint channels')
|
|
1063
1068
|
.option('--node <node_name>', 'Use saved node to create invoice')
|
|
1064
1069
|
.option('--rate-provider <rate_provider>', 'Rate provider', priceProviders)
|
|
1065
1070
|
.option('--select-hints', 'Select hop hints to be added to the request')
|
|
1071
|
+
.option('--virtual', 'Request payment over a virtual channel')
|
|
1072
|
+
.option('--virtual-fee-rate <pm>', 'Fee rate to use on virtual channel', INT)
|
|
1066
1073
|
.action((args, options, logger) => {
|
|
1067
1074
|
return new Promise(async (resolve, reject) => {
|
|
1068
1075
|
try {
|
|
1069
1076
|
return await offchain.createInvoice({
|
|
1077
|
+
logger,
|
|
1070
1078
|
amount: args.amount,
|
|
1071
1079
|
ask: await commands.interrogate({}),
|
|
1072
1080
|
description: options.for,
|
|
1073
1081
|
is_hinting: options.includeHints || undefined,
|
|
1074
1082
|
is_selecting_hops: options.selectHints || undefined,
|
|
1083
|
+
is_virtual: options.virtual || undefined,
|
|
1075
1084
|
lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
|
|
1076
1085
|
rate_provider: options.rateProvider || undefined,
|
|
1077
1086
|
request: commands.simpleRequest,
|
|
1087
|
+
virtual_fee_rate: options.virtualFeeRate,
|
|
1078
1088
|
},
|
|
1079
1089
|
responses.returnObject({exit, logger, reject, resolve}));
|
|
1080
1090
|
} catch (err) {
|
|
@@ -1084,9 +1094,8 @@ prog
|
|
|
1084
1094
|
})
|
|
1085
1095
|
|
|
1086
1096
|
// Join a group channel open
|
|
1087
|
-
.command('join-group
|
|
1088
|
-
.
|
|
1089
|
-
.help('Another node should have run create-group-channel to create group')
|
|
1097
|
+
.command('join-channel-group', 'Join a balanced channels group')
|
|
1098
|
+
.help('Another node should have run create-channel-group to create group')
|
|
1090
1099
|
.argument('<code>', 'Invite code to join group', STRING)
|
|
1091
1100
|
.option('--max-fee-rate <per_vbyte>', 'Maximum fee/vbyte for open', INT)
|
|
1092
1101
|
.option('--node <node_name>', 'Use saved node to join group')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const asyncAuto = require('async/auto');
|
|
2
2
|
const asyncMap = require('async/map');
|
|
3
|
+
const asyncRetry = require('async/retry');
|
|
3
4
|
const {createInvoice} = require('ln-service');
|
|
4
5
|
const {getChannels} = require('ln-service');
|
|
5
6
|
const {getChannel} = require('ln-service');
|
|
@@ -10,6 +11,7 @@ const {getPrices} = require('@alexbosworth/fiat');
|
|
|
10
11
|
const {parseAmount} = require('ln-accounting');
|
|
11
12
|
const {parsePaymentRequest} = require('ln-service');
|
|
12
13
|
const {returnResult} = require('asyncjs-util');
|
|
14
|
+
const {subscribeToForwardRequests} = require('ln-service');
|
|
13
15
|
|
|
14
16
|
const signPaymentRequest = require('./sign_payment_request');
|
|
15
17
|
|
|
@@ -18,12 +20,15 @@ const defaultFiatRateProvider = 'coinbase';
|
|
|
18
20
|
const defaultInvoiceDescription = '';
|
|
19
21
|
const fiats = ['EUR', 'USD'];
|
|
20
22
|
const hasFiat = n => /(eur|usd)/gim.test(n);
|
|
23
|
+
const interval = 3000;
|
|
21
24
|
const {isArray} = Array;
|
|
22
25
|
const {isInteger} = Number;
|
|
23
26
|
const isNumber = n => !isNaN(n);
|
|
27
|
+
const mtokensAsBigUnit = n => (Number(n / BigInt(1000)) / 1e8).toFixed(8);
|
|
24
28
|
const networks = {btc: 'BTC', btctestnet: 'BTC', btcregtest: 'BTC'};
|
|
25
29
|
const parseRequest = request => parsePaymentRequest({request});
|
|
26
30
|
const rateAsTokens = rate => 1e10 / rate;
|
|
31
|
+
const times = 20 * 60 * 24;
|
|
27
32
|
const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
|
|
28
33
|
const uniq = arr => Array.from(new Set(arr));
|
|
29
34
|
|
|
@@ -35,6 +40,7 @@ const uniq = arr => Array.from(new Set(arr));
|
|
|
35
40
|
[description]: <Invoice Description String>
|
|
36
41
|
[is_hinting]: <Include Private Channels Bool>
|
|
37
42
|
[is_selecting_hops]: <Is Selecting Hops Bool>
|
|
43
|
+
[is_virtual]: <Is Using Virtual Channel for Invoice Bool>
|
|
38
44
|
lnd: <Authenticated LND API Object>
|
|
39
45
|
[rate_provider]: <Fiat Rate Provider String>
|
|
40
46
|
request: <Request Function>
|
|
@@ -42,8 +48,9 @@ const uniq = arr => Array.from(new Set(arr));
|
|
|
42
48
|
|
|
43
49
|
@returns via cbk or Promise
|
|
44
50
|
{
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
[is_settled]: <Invoice Was Paid Bool>
|
|
52
|
+
[request]: <BOLT 11 Payment Request String>
|
|
53
|
+
[tokens]: <Invoice Amount Number>
|
|
47
54
|
}
|
|
48
55
|
*/
|
|
49
56
|
module.exports = (args, cbk) => {
|
|
@@ -67,10 +74,22 @@ module.exports = (args, cbk) => {
|
|
|
67
74
|
return cbk([400, 'CannotUseDefaultHintsAndAlsoSelectHints']);
|
|
68
75
|
}
|
|
69
76
|
|
|
77
|
+
if (!!args.is_virtual && !!args.is_hinting) {
|
|
78
|
+
return cbk([400, 'UsingHopHintsIsUnsupportedWithVirtualChannels']);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!!args.is_virtual && !!args.is_selecting_hops) {
|
|
82
|
+
return cbk([400, 'ChoosingHopHintsUnsupportedWithVirtualChannels']);
|
|
83
|
+
}
|
|
84
|
+
|
|
70
85
|
if (!args.lnd) {
|
|
71
86
|
return cbk([400, 'ExpectedAuthenticatedLndToCreateNewInvoice']);
|
|
72
87
|
}
|
|
73
88
|
|
|
89
|
+
if (!args.logger) {
|
|
90
|
+
return cbk([400, 'ExpectedWinstonLoggerObjectToCreateNewInvoice']);
|
|
91
|
+
}
|
|
92
|
+
|
|
74
93
|
if (!args.request) {
|
|
75
94
|
return cbk([400, 'ExpectedRequestFunctionToCreateNewInvoice']);
|
|
76
95
|
}
|
|
@@ -127,7 +146,7 @@ module.exports = (args, cbk) => {
|
|
|
127
146
|
getNetwork: ['validate', ({}, cbk) => getNetwork({lnd: args.lnd}, cbk)],
|
|
128
147
|
|
|
129
148
|
// Get wallet info
|
|
130
|
-
|
|
149
|
+
getId: ['validate', ({}, cbk) => getIdentity({lnd: args.lnd}, cbk)],
|
|
131
150
|
|
|
132
151
|
// Fiat rates
|
|
133
152
|
rates: [
|
|
@@ -185,6 +204,7 @@ module.exports = (args, cbk) => {
|
|
|
185
204
|
return cbk();
|
|
186
205
|
}
|
|
187
206
|
|
|
207
|
+
// Make sure there are some channels to select
|
|
188
208
|
if (!getChannels.channels.length) {
|
|
189
209
|
return cbk([400, 'NoRelevantChannelsToSelectAsHints']);
|
|
190
210
|
}
|
|
@@ -217,6 +237,7 @@ module.exports = (args, cbk) => {
|
|
|
217
237
|
getPolicies: ['selectChannels', ({selectChannels}, cbk) => {
|
|
218
238
|
return asyncMap(selectChannels, (channel, cbk) => {
|
|
219
239
|
return getChannel({id: channel, lnd: args.lnd}, (err, res) => {
|
|
240
|
+
// Exit early when the channel isn't found
|
|
220
241
|
if (isArray(err) && err.slice().shift() === 404) {
|
|
221
242
|
return cbk();
|
|
222
243
|
}
|
|
@@ -247,24 +268,100 @@ module.exports = (args, cbk) => {
|
|
|
247
268
|
cbk);
|
|
248
269
|
}],
|
|
249
270
|
|
|
271
|
+
// Intercept virtual invoice forwards
|
|
272
|
+
interceptVirtualInvoice: ['addInvoice', ({addInvoice}, cbk) => {
|
|
273
|
+
// Exit early when not intercepting the virtual forward
|
|
274
|
+
if (!args.is_virtual) {
|
|
275
|
+
return cbk();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
args.logger.info({listening_for_virtual_channel_payment: true});
|
|
279
|
+
|
|
280
|
+
const sub = subscribeToForwardRequests({lnd: args.lnd});
|
|
281
|
+
|
|
282
|
+
// Stop listening for the HTLC when the invoice expires
|
|
283
|
+
const timeout = setTimeout(() => {
|
|
284
|
+
sub.removeAllListeners();
|
|
285
|
+
|
|
286
|
+
return cbk([408, 'TimedOutWaitingForPayment']);
|
|
287
|
+
},
|
|
288
|
+
new Date(parseRequest(addInvoice.request).expires_at) - new Date());
|
|
289
|
+
|
|
290
|
+
const finished = (err, res) => {
|
|
291
|
+
clearTimeout(timeout);
|
|
292
|
+
|
|
293
|
+
sub.removeAllListeners();
|
|
294
|
+
|
|
295
|
+
return cbk(err, res);
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// Listen for a payment to the virtual channel invoice
|
|
299
|
+
sub.on('forward_request', async forward => {
|
|
300
|
+
// Exit early and accept requests that are not for this invoice
|
|
301
|
+
if (forward.hash !== addInvoice.id) {
|
|
302
|
+
return forward.accept({});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
args.logger.info({accepting_payment: true});
|
|
306
|
+
|
|
307
|
+
forward.settle({secret: addInvoice.secret});
|
|
308
|
+
|
|
309
|
+
// Listen for an error on the requests subscription
|
|
310
|
+
sub.on('error', err => {
|
|
311
|
+
args.logger.error({err});
|
|
312
|
+
|
|
313
|
+
return finished(err);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Wait until the payment is no longer pending
|
|
317
|
+
await asyncRetry({interval, times}, async () => {
|
|
318
|
+
const {channels} = await getChannels({lnd: args.lnd});
|
|
319
|
+
|
|
320
|
+
const channel = channels.find(n => n.id === forward.in_channel);
|
|
321
|
+
|
|
322
|
+
if (!channel) {
|
|
323
|
+
throw new Error('FailedToFindForwardChannel');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const pending = channel.pending_payments.find(({payment}) => {
|
|
327
|
+
return payment === forward.in_channel;
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
if (!!pending) {
|
|
331
|
+
throw new Error('PaymentIsStillPending');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return;
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
const got = BigInt(forward.mtokens) + BigInt(forward.fee_mtokens);
|
|
338
|
+
|
|
339
|
+
args.logger.info({received: mtokensAsBigUnit(got)});
|
|
340
|
+
|
|
341
|
+
return finished();
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
return;
|
|
345
|
+
}],
|
|
346
|
+
|
|
250
347
|
// Create the final signed public payment request
|
|
251
348
|
publicRequest: [
|
|
252
349
|
'addInvoice',
|
|
253
|
-
'
|
|
350
|
+
'getId',
|
|
254
351
|
'getNetwork',
|
|
255
352
|
'getPolicies',
|
|
256
353
|
'parseAmount',
|
|
257
354
|
({
|
|
258
355
|
addInvoice,
|
|
259
|
-
|
|
356
|
+
getId,
|
|
260
357
|
getNetwork,
|
|
261
358
|
getPolicies,
|
|
262
359
|
parseAmount,
|
|
263
360
|
},
|
|
264
361
|
cbk) =>
|
|
265
362
|
{
|
|
266
|
-
// Exit early if not
|
|
267
|
-
if (!args.is_selecting_hops) {
|
|
363
|
+
// Exit early if not using custom hop hints
|
|
364
|
+
if (!args.is_selecting_hops && !args.is_virtual) {
|
|
268
365
|
return cbk(null, {
|
|
269
366
|
request: addInvoice.request,
|
|
270
367
|
tokens: addInvoice.tokens,
|
|
@@ -275,17 +372,35 @@ module.exports = (args, cbk) => {
|
|
|
275
372
|
channels: getPolicies,
|
|
276
373
|
cltv_delta: parseRequest(addInvoice.request).cltv_delta,
|
|
277
374
|
description: args.description || defaultInvoiceDescription,
|
|
278
|
-
destination:
|
|
375
|
+
destination: getId.public_key,
|
|
279
376
|
features: parseRequest(addInvoice.request).features,
|
|
280
377
|
id: addInvoice.id,
|
|
378
|
+
is_virtual: args.is_virtual,
|
|
281
379
|
lnd: args.lnd,
|
|
282
380
|
network: getNetwork.bitcoinjs,
|
|
283
381
|
payment: addInvoice.payment,
|
|
284
382
|
tokens: parseAmount.tokens,
|
|
383
|
+
virtual_fee_rate: args.virtual_fee_rate,
|
|
285
384
|
},
|
|
286
385
|
cbk);
|
|
287
386
|
}],
|
|
387
|
+
|
|
388
|
+
// Log the virtual channel payment request
|
|
389
|
+
logRequest: ['publicRequest', ({publicRequest}, cbk) => {
|
|
390
|
+
// Exit early when not using a virtual channel
|
|
391
|
+
if (!args.is_virtual) {
|
|
392
|
+
return cbk(null, publicRequest);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
args.logger.info({
|
|
396
|
+
request: publicRequest.request,
|
|
397
|
+
tokens: parseRequest(publicRequest.request).tokens,
|
|
398
|
+
virtual_fee_rate: args.virtual_fee_rate || undefined,
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
return cbk(null, {is_settled: true});
|
|
402
|
+
}],
|
|
288
403
|
},
|
|
289
|
-
returnResult({reject, resolve, of: '
|
|
404
|
+
returnResult({reject, resolve, of: 'logRequest'}, cbk));
|
|
290
405
|
});
|
|
291
406
|
};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
const {randomBytes} = require('crypto');
|
|
2
|
+
|
|
1
3
|
const asyncAuto = require('async/auto');
|
|
2
4
|
const {createSignedRequest} = require('ln-service');
|
|
3
5
|
const {createUnsignedRequest} = require('ln-service');
|
|
4
6
|
const {decode} = require('bip66');
|
|
5
7
|
const {returnResult} = require('asyncjs-util');
|
|
8
|
+
const secp256k1 = require('secp256k1');
|
|
6
9
|
const {signBytes} = require('ln-service');
|
|
10
|
+
const tinysecp256k1 = require('tiny-secp256k1');
|
|
7
11
|
|
|
8
12
|
const bufferAsHex = buffer => buffer.toString('hex');
|
|
9
13
|
const {concat} = Buffer;
|
|
@@ -14,7 +18,11 @@ const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
|
14
18
|
const {isArray} = Array;
|
|
15
19
|
const keyFamilyIdentity = 6;
|
|
16
20
|
const keyIndexIdentity = 0;
|
|
21
|
+
const makePrivateKey = () => randomBytes(32);
|
|
22
|
+
const minimalCltvDelta = 18;
|
|
17
23
|
const rValue = r => r.length === 33 ? r.slice(1) : r;
|
|
24
|
+
const unit8AsHex = n => Buffer.from(n).toString('hex');
|
|
25
|
+
const virtualChannelId = '805x805x805';
|
|
18
26
|
|
|
19
27
|
/** Create a signed BOLT 11 payment request
|
|
20
28
|
|
|
@@ -95,8 +103,38 @@ module.exports = (args, cbk) => {
|
|
|
95
103
|
return cbk();
|
|
96
104
|
},
|
|
97
105
|
|
|
106
|
+
// Create a key pair for a virtual channel invoice
|
|
107
|
+
getKeyPair: ['validate', ({}, cbk) => {
|
|
108
|
+
// Exit early when not using a virtual channel
|
|
109
|
+
if (!args.is_virtual) {
|
|
110
|
+
return cbk();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const privateKey = makePrivateKey();
|
|
114
|
+
|
|
115
|
+
const publicKey = unit8AsHex(secp256k1.publicKeyCreate(privateKey));
|
|
116
|
+
|
|
117
|
+
return cbk(null, {private_key: privateKey, public_key: publicKey});
|
|
118
|
+
}],
|
|
119
|
+
|
|
98
120
|
// Assemble the hop hints from the chosen hint channels
|
|
99
|
-
hints: ['
|
|
121
|
+
hints: ['getKeyPair', ({getKeyPair}, cbk) => {
|
|
122
|
+
// Exit early when using a virtual channel
|
|
123
|
+
if (!!args.is_virtual) {
|
|
124
|
+
return cbk(null, [[
|
|
125
|
+
{
|
|
126
|
+
public_key: args.destination,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
base_fee_mtokens: Number().toString(),
|
|
130
|
+
channel: virtualChannelId,
|
|
131
|
+
cltv_delta: minimalCltvDelta,
|
|
132
|
+
fee_rate: args.virtual_fee_rate || Number(),
|
|
133
|
+
public_key: getKeyPair.public_key,
|
|
134
|
+
},
|
|
135
|
+
]]);
|
|
136
|
+
}
|
|
137
|
+
|
|
100
138
|
const routes = args.channels.map(({id, policies}) => {
|
|
101
139
|
const peerPolicy = policies.find(policy => {
|
|
102
140
|
return policy.public_key !== args.destination;
|
|
@@ -121,11 +159,13 @@ module.exports = (args, cbk) => {
|
|
|
121
159
|
|
|
122
160
|
// Create the unsigned payment request
|
|
123
161
|
unsigned: ['hints', ({hints}, cbk) => {
|
|
162
|
+
const [destination] = hints.slice().reverse();
|
|
163
|
+
|
|
124
164
|
try {
|
|
125
165
|
const unsigned = createUnsignedRequest({
|
|
126
166
|
cltv_delta: args.cltv_delta,
|
|
127
167
|
description: args.description,
|
|
128
|
-
destination:
|
|
168
|
+
destination: destination.public_key,
|
|
129
169
|
features: args.features,
|
|
130
170
|
id: args.id,
|
|
131
171
|
network: args.network,
|
|
@@ -141,28 +181,52 @@ module.exports = (args, cbk) => {
|
|
|
141
181
|
}],
|
|
142
182
|
|
|
143
183
|
// Sign the unsigned payment request
|
|
144
|
-
sign: ['unsigned', ({unsigned}, cbk) => {
|
|
184
|
+
sign: ['getKeyPair', 'unsigned', ({getKeyPair, unsigned}, cbk) => {
|
|
185
|
+
// Exit early when signing using the virtual key
|
|
186
|
+
if (!!args.is_virtual) {
|
|
187
|
+
const signature = tinysecp256k1.sign(
|
|
188
|
+
hexAsBuffer(unsigned.hash),
|
|
189
|
+
getKeyPair.private_key
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
return cbk(null, {
|
|
193
|
+
destination: getKeyPair.public_key,
|
|
194
|
+
signature: unit8AsHex(signature),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Sign the modified payment request using the identity public key
|
|
145
199
|
return signBytes({
|
|
146
200
|
key_family: keyFamilyIdentity,
|
|
147
201
|
key_index: keyIndexIdentity,
|
|
148
202
|
lnd: args.lnd,
|
|
149
203
|
preimage: unsigned.preimage,
|
|
150
204
|
},
|
|
151
|
-
|
|
205
|
+
(err, res) => {
|
|
206
|
+
if (!!err) {
|
|
207
|
+
return cbk(err);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Convert the signature format
|
|
211
|
+
const {r, s} = decode(hexAsBuffer(res.signature));
|
|
212
|
+
|
|
213
|
+
return cbk(null, {
|
|
214
|
+
destination: args.destination,
|
|
215
|
+
signature: bufferAsHex(concat([rValue(r), s])),
|
|
216
|
+
});
|
|
217
|
+
});
|
|
152
218
|
}],
|
|
153
219
|
|
|
154
|
-
// Assemble the signed request
|
|
220
|
+
// Assemble the full signed request
|
|
155
221
|
request: ['sign', 'unsigned', ({sign, unsigned}, cbk) => {
|
|
156
222
|
try {
|
|
157
|
-
const {r, s} = decode(hexAsBuffer(sign.signature));
|
|
158
|
-
|
|
159
223
|
const {request} = createSignedRequest({
|
|
160
|
-
destination:
|
|
224
|
+
destination: sign.destination,
|
|
161
225
|
hrp: unsigned.hrp,
|
|
162
|
-
signature:
|
|
226
|
+
signature: sign.signature,
|
|
163
227
|
tags: unsigned.tags,
|
|
164
228
|
});
|
|
165
|
-
|
|
229
|
+
|
|
166
230
|
return cbk(null, {request, tokens: args.tokens});
|
|
167
231
|
} catch (err) {
|
|
168
232
|
return cbk([503, 'UnexpectedErrorSigningRequest', {err}]);
|
package/package.json
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"ln-sync": "4.0.5",
|
|
41
41
|
"ln-telegram": "4.2.0",
|
|
42
42
|
"moment": "2.29.4",
|
|
43
|
-
"paid-services": "4.0
|
|
43
|
+
"paid-services": "4.1.0",
|
|
44
44
|
"probing": "3.0.0",
|
|
45
45
|
"psbt": "2.7.1",
|
|
46
46
|
"qrcode-terminal": "0.12.0",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis --push .",
|
|
84
84
|
"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/telegram/*.js test/wallets/*.js"
|
|
85
85
|
},
|
|
86
|
-
"version": "13.
|
|
86
|
+
"version": "13.9.0"
|
|
87
87
|
}
|