balanceofsatoshis 13.6.0 → 13.7.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 +4 -0
- package/bos +32 -0
- package/offchain/create_invoice.js +290 -0
- package/offchain/index.js +3 -0
- package/offchain/sign_payment_request.js +166 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
package/bos
CHANGED
|
@@ -32,6 +32,7 @@ const lnurl = importLazy('./lnurl');
|
|
|
32
32
|
const {lnurlFunctions} = commandConstants;
|
|
33
33
|
const network = importLazy('./network');
|
|
34
34
|
const nodes = importLazy('./nodes');
|
|
35
|
+
const offchain = importLazy('./offchain');
|
|
35
36
|
const {peerSortOptions} = commandConstants;
|
|
36
37
|
const peers = importLazy('./peers');
|
|
37
38
|
const {priceProviders} = commandConstants;
|
|
@@ -1051,6 +1052,37 @@ prog
|
|
|
1051
1052
|
});
|
|
1052
1053
|
})
|
|
1053
1054
|
|
|
1055
|
+
// Create an invoice
|
|
1056
|
+
.command('invoice', 'Create an invoice and get a BOLT 11 payment request')
|
|
1057
|
+
.help('Amount can take m/k variables: 5*m for 5 million, 250*k = 0.0025')
|
|
1058
|
+
.help('Fiat conversion is supported in amount, N*USD or N*EUR')
|
|
1059
|
+
.help(`Fiat rate providers: ${priceProviders.join(', ')}`)
|
|
1060
|
+
.argument('[amount]', 'Amount for invoice', STRING, '0')
|
|
1061
|
+
.option('--for <description>', 'What is the invoice requesting payment for')
|
|
1062
|
+
.option('--include-hints', 'Include the default set of hop hint channels')
|
|
1063
|
+
.option('--node <node_name>', 'Use saved node to create invoice')
|
|
1064
|
+
.option('--rate-provider <rate_provider>', 'Rate provider', priceProviders)
|
|
1065
|
+
.option('--select-hints', 'Select hop hints to be added to the request')
|
|
1066
|
+
.action((args, options, logger) => {
|
|
1067
|
+
return new Promise(async (resolve, reject) => {
|
|
1068
|
+
try {
|
|
1069
|
+
return await offchain.createInvoice({
|
|
1070
|
+
amount: args.amount,
|
|
1071
|
+
ask: await commands.interrogate({}),
|
|
1072
|
+
description: options.for,
|
|
1073
|
+
is_hinting: options.includeHints || undefined,
|
|
1074
|
+
is_selecting_hops: options.selectHints || undefined,
|
|
1075
|
+
lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
|
|
1076
|
+
rate_provider: options.rateProvider || undefined,
|
|
1077
|
+
request: commands.simpleRequest,
|
|
1078
|
+
},
|
|
1079
|
+
responses.returnObject({exit, logger, reject, resolve}));
|
|
1080
|
+
} catch (err) {
|
|
1081
|
+
return logger.error({err}) && reject();
|
|
1082
|
+
}
|
|
1083
|
+
});
|
|
1084
|
+
})
|
|
1085
|
+
|
|
1054
1086
|
// Join a group channel open
|
|
1055
1087
|
.command('join-group-channel', 'Join a balanced channels group')
|
|
1056
1088
|
.visible(false)
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const asyncMap = require('async/map');
|
|
3
|
+
const {createInvoice} = require('ln-service');
|
|
4
|
+
const {getChannels} = require('ln-service');
|
|
5
|
+
const {getChannel} = require('ln-service');
|
|
6
|
+
const {getIdentity} = require('ln-service');
|
|
7
|
+
const {getNetwork} = require('ln-sync');
|
|
8
|
+
const {getNodeAlias} = require('ln-sync');
|
|
9
|
+
const {getPrices} = require('@alexbosworth/fiat');
|
|
10
|
+
const {parseAmount} = require('ln-accounting');
|
|
11
|
+
const {parsePaymentRequest} = require('ln-service');
|
|
12
|
+
const {returnResult} = require('asyncjs-util');
|
|
13
|
+
|
|
14
|
+
const signPaymentRequest = require('./sign_payment_request');
|
|
15
|
+
|
|
16
|
+
const coins = ['BTC'];
|
|
17
|
+
const defaultFiatRateProvider = 'coinbase';
|
|
18
|
+
const defaultInvoiceDescription = '';
|
|
19
|
+
const fiats = ['EUR', 'USD'];
|
|
20
|
+
const hasFiat = n => /(eur|usd)/gim.test(n);
|
|
21
|
+
const {isArray} = Array;
|
|
22
|
+
const {isInteger} = Number;
|
|
23
|
+
const isNumber = n => !isNaN(n);
|
|
24
|
+
const networks = {btc: 'BTC', btctestnet: 'BTC', btcregtest: 'BTC'};
|
|
25
|
+
const parseRequest = request => parsePaymentRequest({request});
|
|
26
|
+
const rateAsTokens = rate => 1e10 / rate;
|
|
27
|
+
const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
|
|
28
|
+
const uniq = arr => Array.from(new Set(arr));
|
|
29
|
+
|
|
30
|
+
/** Create an invoice for a requested amount
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
amount: <Invoice Amount String>
|
|
34
|
+
ask: <Inquirer Function>
|
|
35
|
+
[description]: <Invoice Description String>
|
|
36
|
+
[is_hinting]: <Include Private Channels Bool>
|
|
37
|
+
[is_selecting_hops]: <Is Selecting Hops Bool>
|
|
38
|
+
lnd: <Authenticated LND API Object>
|
|
39
|
+
[rate_provider]: <Fiat Rate Provider String>
|
|
40
|
+
request: <Request Function>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@returns via cbk or Promise
|
|
44
|
+
{
|
|
45
|
+
request: <BOLT 11 Payment Request String>
|
|
46
|
+
tokens: <Invoice Amount Number>
|
|
47
|
+
}
|
|
48
|
+
*/
|
|
49
|
+
module.exports = (args, cbk) => {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
return asyncAuto({
|
|
52
|
+
// Check arguments
|
|
53
|
+
validate: cbk => {
|
|
54
|
+
if (!args.amount) {
|
|
55
|
+
return cbk([400, 'ExpectedInvoiceAmountToCreateNewInvoice']);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (isNumber(args.amount) && !isInteger(Number(args.amount))) {
|
|
59
|
+
return cbk([400, 'ExpectedIntegerAmountToInvoice']);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!args.ask) {
|
|
63
|
+
return cbk([400, 'ExpectedAskFunctionToCreateNewInvoice']);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!!args.is_hinting && !!args.is_selecting_hops) {
|
|
67
|
+
return cbk([400, 'CannotUseDefaultHintsAndAlsoSelectHints']);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!args.lnd) {
|
|
71
|
+
return cbk([400, 'ExpectedAuthenticatedLndToCreateNewInvoice']);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!args.request) {
|
|
75
|
+
return cbk([400, 'ExpectedRequestFunctionToCreateNewInvoice']);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return cbk();
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
// Get the current price of BTC in USD/EUR
|
|
82
|
+
getFiatPrice: ['validate', ({}, cbk) => {
|
|
83
|
+
// Exit early when no fiat is referenced
|
|
84
|
+
if (!hasFiat(args.amount)) {
|
|
85
|
+
return cbk();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return getPrices({
|
|
89
|
+
from: args.rate_provider || defaultFiatRateProvider,
|
|
90
|
+
request: args.request,
|
|
91
|
+
symbols: [].concat(fiats),
|
|
92
|
+
},
|
|
93
|
+
cbk);
|
|
94
|
+
}],
|
|
95
|
+
|
|
96
|
+
// Get channels to allow for selecting individual hop hints
|
|
97
|
+
getChannels: ['validate', ({}, cbk) => {
|
|
98
|
+
// Exit early when not selecting hop hints
|
|
99
|
+
if (!args.is_selecting_hops) {
|
|
100
|
+
return cbk();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return getChannels({
|
|
104
|
+
is_active: true,
|
|
105
|
+
is_private: true,
|
|
106
|
+
lnd: args.lnd,
|
|
107
|
+
},
|
|
108
|
+
cbk);
|
|
109
|
+
}],
|
|
110
|
+
|
|
111
|
+
// Get node aliases for channels for selecting hop hints
|
|
112
|
+
getAliases: ['getChannels', ({getChannels}, cbk) => {
|
|
113
|
+
// Exit early when not selecting hop hints
|
|
114
|
+
if (!args.is_selecting_hops) {
|
|
115
|
+
return cbk();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const ids = uniq(getChannels.channels.map(n => n.partner_public_key));
|
|
119
|
+
|
|
120
|
+
return asyncMap(ids, (id, cbk) => {
|
|
121
|
+
return getNodeAlias({id, lnd: args.lnd}, cbk);
|
|
122
|
+
},
|
|
123
|
+
cbk);
|
|
124
|
+
}],
|
|
125
|
+
|
|
126
|
+
// Get network name
|
|
127
|
+
getNetwork: ['validate', ({}, cbk) => getNetwork({lnd: args.lnd}, cbk)],
|
|
128
|
+
|
|
129
|
+
// Get wallet info
|
|
130
|
+
getIdentity: ['validate', ({}, cbk) => getIdentity({lnd: args.lnd}, cbk)],
|
|
131
|
+
|
|
132
|
+
// Fiat rates
|
|
133
|
+
rates: [
|
|
134
|
+
'getFiatPrice',
|
|
135
|
+
'getNetwork',
|
|
136
|
+
({getFiatPrice, getNetwork}, cbk) =>
|
|
137
|
+
{
|
|
138
|
+
// Exit early when there is no fiat
|
|
139
|
+
if (!getFiatPrice) {
|
|
140
|
+
return cbk();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!networks[getNetwork.network]) {
|
|
144
|
+
return cbk([400, 'UnsupportedNetworkForFiatPriceConversion']);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const rates = fiats.map(fiat => {
|
|
148
|
+
const {rate} = getFiatPrice.tickers.find(n => n.ticker === fiat);
|
|
149
|
+
|
|
150
|
+
return {fiat, unit: rateAsTokens(rate)};
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return cbk(null, rates);
|
|
154
|
+
}],
|
|
155
|
+
|
|
156
|
+
// Parse the amount
|
|
157
|
+
parseAmount: ['rates', ({rates}, cbk) => {
|
|
158
|
+
const eur = !!rates ? rates.find(n => n.fiat === 'EUR') : null;
|
|
159
|
+
const usd = !!rates ? rates.find(n => n.fiat === 'USD') : null;
|
|
160
|
+
|
|
161
|
+
// Variables to use in amount
|
|
162
|
+
const variables = {
|
|
163
|
+
eur: !!eur ? eur.unit : undefined,
|
|
164
|
+
usd: !!usd ? usd.unit : undefined,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const {tokens} = parseAmount({variables, amount: args.amount});
|
|
169
|
+
|
|
170
|
+
return cbk(null, {tokens});
|
|
171
|
+
} catch (err) {
|
|
172
|
+
return cbk([400, 'FailedToParseAmount', {err}]);
|
|
173
|
+
}
|
|
174
|
+
}],
|
|
175
|
+
|
|
176
|
+
// Select hop hint channels
|
|
177
|
+
selectChannels: [
|
|
178
|
+
'getAliases',
|
|
179
|
+
'getChannels',
|
|
180
|
+
'parseAmount',
|
|
181
|
+
({getAliases, getChannels}, cbk) =>
|
|
182
|
+
{
|
|
183
|
+
// Exit early if not selecting channels
|
|
184
|
+
if (!args.is_selecting_hops) {
|
|
185
|
+
return cbk();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!getChannels.channels.length) {
|
|
189
|
+
return cbk([400, 'NoRelevantChannelsToSelectAsHints']);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return args.ask({
|
|
193
|
+
choices: getChannels.channels.map(channel => {
|
|
194
|
+
const node = getAliases.find(({id}) => {
|
|
195
|
+
return id === channel.partner_public_key
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const value = channel.id;
|
|
199
|
+
const inbound = `in: ${tokensAsBigUnit(channel.remote_balance)}`;
|
|
200
|
+
const outbound = `out: ${tokensAsBigUnit(channel.local_balance)}`;
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
value,
|
|
204
|
+
name: `${value} ${node.alias}: ${inbound} | ${outbound}.`,
|
|
205
|
+
};
|
|
206
|
+
}),
|
|
207
|
+
loop: false,
|
|
208
|
+
message: `Channels to include as hints in the invoice?`,
|
|
209
|
+
name: 'id',
|
|
210
|
+
type: 'checkbox',
|
|
211
|
+
validate: input => !!input.length,
|
|
212
|
+
},
|
|
213
|
+
({id}) => cbk(null, id));
|
|
214
|
+
}],
|
|
215
|
+
|
|
216
|
+
// Get the policies of selected channels
|
|
217
|
+
getPolicies: ['selectChannels', ({selectChannels}, cbk) => {
|
|
218
|
+
return asyncMap(selectChannels, (channel, cbk) => {
|
|
219
|
+
return getChannel({id: channel, lnd: args.lnd}, (err, res) => {
|
|
220
|
+
if (isArray(err) && err.slice().shift() === 404) {
|
|
221
|
+
return cbk();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (!!err) {
|
|
225
|
+
return cbk(err);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Exit early when the channel policies are not defined
|
|
229
|
+
if (!!res.policies.find(n => n.cltv_delta === undefined)) {
|
|
230
|
+
return cbk();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return cbk(null, res);
|
|
234
|
+
});
|
|
235
|
+
},
|
|
236
|
+
cbk);
|
|
237
|
+
}],
|
|
238
|
+
|
|
239
|
+
// Create the invoice in the LND database
|
|
240
|
+
addInvoice: ['getPolicies', 'parseAmount', ({parseAmount}, cbk) => {
|
|
241
|
+
return createInvoice({
|
|
242
|
+
description: args.description || defaultInvoiceDescription,
|
|
243
|
+
is_including_private_channels: args.is_hinting || undefined,
|
|
244
|
+
lnd: args.lnd,
|
|
245
|
+
tokens: parseAmount.tokens,
|
|
246
|
+
},
|
|
247
|
+
cbk);
|
|
248
|
+
}],
|
|
249
|
+
|
|
250
|
+
// Create the final signed public payment request
|
|
251
|
+
publicRequest: [
|
|
252
|
+
'addInvoice',
|
|
253
|
+
'getIdentity',
|
|
254
|
+
'getNetwork',
|
|
255
|
+
'getPolicies',
|
|
256
|
+
'parseAmount',
|
|
257
|
+
({
|
|
258
|
+
addInvoice,
|
|
259
|
+
getIdentity,
|
|
260
|
+
getNetwork,
|
|
261
|
+
getPolicies,
|
|
262
|
+
parseAmount,
|
|
263
|
+
},
|
|
264
|
+
cbk) =>
|
|
265
|
+
{
|
|
266
|
+
// Exit early if not selecting custom hop hints
|
|
267
|
+
if (!args.is_selecting_hops) {
|
|
268
|
+
return cbk(null, {
|
|
269
|
+
request: addInvoice.request,
|
|
270
|
+
tokens: addInvoice.tokens,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return signPaymentRequest({
|
|
275
|
+
channels: getPolicies,
|
|
276
|
+
cltv_delta: parseRequest(addInvoice.request).cltv_delta,
|
|
277
|
+
description: args.description || defaultInvoiceDescription,
|
|
278
|
+
destination: getIdentity.public_key,
|
|
279
|
+
id: addInvoice.id,
|
|
280
|
+
lnd: args.lnd,
|
|
281
|
+
network: getNetwork.bitcoinjs,
|
|
282
|
+
payment: addInvoice.payment,
|
|
283
|
+
tokens: parseAmount.tokens,
|
|
284
|
+
},
|
|
285
|
+
cbk);
|
|
286
|
+
}],
|
|
287
|
+
},
|
|
288
|
+
returnResult({reject, resolve, of: 'publicRequest'}, cbk));
|
|
289
|
+
});
|
|
290
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const {createSignedRequest} = require('ln-service');
|
|
3
|
+
const {createUnsignedRequest} = require('ln-service');
|
|
4
|
+
const {decode} = require('bip66');
|
|
5
|
+
const {returnResult} = require('asyncjs-util');
|
|
6
|
+
const {signBytes} = require('ln-service');
|
|
7
|
+
|
|
8
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
9
|
+
const {concat} = Buffer;
|
|
10
|
+
const defaultBaseFee = '1000';
|
|
11
|
+
const defaultCltvDelta = 144;
|
|
12
|
+
const defaultFeeRate = '1';
|
|
13
|
+
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
14
|
+
const {isArray} = Array;
|
|
15
|
+
const keyFamilyIdentity = 6;
|
|
16
|
+
const keyIndexIdentity = 0;
|
|
17
|
+
const rValue = r => r.length === 33 ? r.slice(1) : r;
|
|
18
|
+
|
|
19
|
+
/** Create a signed BOLT 11 payment request
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
channels: [{
|
|
23
|
+
id: <Channel Id String>
|
|
24
|
+
policies: [{
|
|
25
|
+
[base_fee_mtokens]: <Base Routing Fee Millitokens String>
|
|
26
|
+
[cltv_delta]: <Routing CLTV Delta Number>
|
|
27
|
+
[fee_rate]: <Routing PPM Fee Rate Number>
|
|
28
|
+
public_key: <Node Identity Public Key Hex String>
|
|
29
|
+
}]
|
|
30
|
+
}]
|
|
31
|
+
cltv_delta: <Invoice Final CLTV Delta Number>
|
|
32
|
+
description: <Invoice Description String>
|
|
33
|
+
destination: <Destination Public Key Hex String>
|
|
34
|
+
id: <Payment Hash Hex String>
|
|
35
|
+
lnd: <Authenticated LND API Object>
|
|
36
|
+
network: <BitcoinJs Network Name String>
|
|
37
|
+
payment: <Payment Nonce Hex String>
|
|
38
|
+
tokens: <Invoiced Amount Tokens Number>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@returns via cbk or Promise
|
|
42
|
+
{
|
|
43
|
+
request: <BOLT 11 Payment Request String>
|
|
44
|
+
tokens: <Invoiced Tokens Number>
|
|
45
|
+
}
|
|
46
|
+
*/
|
|
47
|
+
module.exports = (args, cbk) => {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
return asyncAuto({
|
|
50
|
+
// Check arguments
|
|
51
|
+
validate: cbk => {
|
|
52
|
+
if (!isArray(args.channels)) {
|
|
53
|
+
return cbk([400, 'ExpectedArrayOfChannelsToSignPaymentRequest']);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!args.cltv_delta) {
|
|
57
|
+
return cbk([400, 'ExpectedFinalCltvDeltaToSignPaymentRequest']);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (args.description === undefined) {
|
|
61
|
+
return cbk([400, 'ExpectedInvoiceDescriptionToSignPaymentRequest']);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!args.destination) {
|
|
65
|
+
return cbk([400, 'ExpectedDestinationNodeIdToSignPaymentRequest']);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!args.id) {
|
|
69
|
+
return cbk([400, 'ExpectedPaymentHashToSignPaymentRequest']);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!args.lnd) {
|
|
73
|
+
return cbk([400, 'ExpectedAuthenticatedLndToSignPaymentRequest']);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!args.network) {
|
|
77
|
+
return cbk([400, 'ExpectedNetworkNameToSignPaymentRequest']);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!args.payment) {
|
|
81
|
+
return cbk([400, 'ExpectedPaymentNonceToSignPaymentRequest']);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (args.tokens === undefined) {
|
|
85
|
+
return cbk([400, 'ExpectedTokensToInvoiceToSignPaymentRequest']);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return cbk();
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
// Assemble the hop hints from the chosen hint channels
|
|
92
|
+
hints: ['validate', ({}, cbk) => {
|
|
93
|
+
const routes = args.channels.map(({id, policies}) => {
|
|
94
|
+
const peerPolicy = policies.find(policy => {
|
|
95
|
+
return policy.public_key !== args.destination;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return [
|
|
99
|
+
{
|
|
100
|
+
public_key: peerPolicy.public_key,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
base_fee_mtokens: peerPolicy.base_fee_mtokens || defaultBaseFee,
|
|
104
|
+
channel: id,
|
|
105
|
+
cltv_delta: peerPolicy.cltv_delta || defaultCltvDelta,
|
|
106
|
+
fee_rate: peerPolicy.fee_rate || defaultFeeRate,
|
|
107
|
+
public_key: args.destination,
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return cbk(null, routes);
|
|
113
|
+
}],
|
|
114
|
+
|
|
115
|
+
// Create the unsigned payment request
|
|
116
|
+
unsigned: ['hints', ({hints}, cbk) => {
|
|
117
|
+
try {
|
|
118
|
+
const unsigned = createUnsignedRequest({
|
|
119
|
+
cltv_delta: args.cltv_delta,
|
|
120
|
+
description: args.description,
|
|
121
|
+
destination: args.destination,
|
|
122
|
+
id: args.id,
|
|
123
|
+
network: args.network,
|
|
124
|
+
payment: args.payment,
|
|
125
|
+
routes: !!hints.length ? hints : undefined,
|
|
126
|
+
tokens: args.tokens,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return cbk(null, unsigned);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
return cbk([500, 'UnexpectedErrorCreatingUnsignedRequest', {err}]);
|
|
132
|
+
}
|
|
133
|
+
}],
|
|
134
|
+
|
|
135
|
+
// Sign the unsigned payment request
|
|
136
|
+
sign: ['unsigned', ({unsigned}, cbk) => {
|
|
137
|
+
return signBytes({
|
|
138
|
+
key_family: keyFamilyIdentity,
|
|
139
|
+
key_index: keyIndexIdentity,
|
|
140
|
+
lnd: args.lnd,
|
|
141
|
+
preimage: unsigned.preimage,
|
|
142
|
+
},
|
|
143
|
+
cbk);
|
|
144
|
+
}],
|
|
145
|
+
|
|
146
|
+
// Assemble the signed request
|
|
147
|
+
request: ['sign', 'unsigned', ({sign, unsigned}, cbk) => {
|
|
148
|
+
try {
|
|
149
|
+
const {r, s} = decode(hexAsBuffer(sign.signature));
|
|
150
|
+
|
|
151
|
+
const {request} = createSignedRequest({
|
|
152
|
+
destination: args.destination,
|
|
153
|
+
hrp: unsigned.hrp,
|
|
154
|
+
signature: bufferAsHex(concat([rValue(r), s])),
|
|
155
|
+
tags: unsigned.tags,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return cbk(null, {request, tokens: args.tokens});
|
|
159
|
+
} catch (err) {
|
|
160
|
+
return cbk([503, 'UnexpectedErrorSigningRequest', {err}]);
|
|
161
|
+
}
|
|
162
|
+
}],
|
|
163
|
+
},
|
|
164
|
+
returnResult({reject, resolve, of: 'request'}, cbk));
|
|
165
|
+
});
|
|
166
|
+
};
|
package/package.json
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"ini": "3.0.1",
|
|
37
37
|
"inquirer": "9.1.4",
|
|
38
38
|
"ln-accounting": "6.1.1",
|
|
39
|
-
"ln-service": "54.
|
|
39
|
+
"ln-service": "54.3.0",
|
|
40
40
|
"ln-sync": "4.0.5",
|
|
41
41
|
"ln-telegram": "4.2.0",
|
|
42
42
|
"moment": "2.29.4",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"description": "Lightning balance CLI",
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@alexbosworth/tap": "15.0.11",
|
|
56
|
-
"invoices": "2.2.
|
|
57
|
-
"ln-docker-daemons": "3.1.
|
|
56
|
+
"invoices": "2.2.1",
|
|
57
|
+
"ln-docker-daemons": "3.1.5",
|
|
58
58
|
"mock-lnd": "1.4.4",
|
|
59
59
|
"tiny-secp256k1": "2.2.1"
|
|
60
60
|
},
|
|
@@ -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.7.0"
|
|
87
87
|
}
|