lightning 4.10.4 → 4.10.5
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 +1 -1
- package/lnd_methods/index.js +2 -0
- package/lnd_methods/macaroon/methods.json +4 -0
- package/lnd_methods/offchain/get_failed_payments.js +190 -0
- package/lnd_methods/offchain/get_payments.js +1 -3
- package/lnd_methods/offchain/index.js +2 -0
- package/lnd_responses/rpc_payment_as_payment.js +71 -21
- package/package.json +1 -1
- package/test/lnd_methods/offchain/test_get_failed_payments.js +160 -0
- package/test/lnd_methods/offchain/test_get_payments.js +2 -2
- package/test/lnd_responses/test_rpc_payment_as_payment.js +43 -8
package/CHANGELOG.md
CHANGED
package/lnd_methods/index.js
CHANGED
|
@@ -35,6 +35,7 @@ const {getChannelBalance} = require('./offchain');
|
|
|
35
35
|
const {getChannels} = require('./offchain');
|
|
36
36
|
const {getClosedChannels} = require('./offchain');
|
|
37
37
|
const {getConnectedWatchtowers} = require('./offchain');
|
|
38
|
+
const {getFailedPayments} = require('./offchain');
|
|
38
39
|
const {getFeeRates} = require('./offchain');
|
|
39
40
|
const {getForwardingConfidence} = require('./offchain');
|
|
40
41
|
const {getForwardingReputations} = require('./offchain');
|
|
@@ -164,6 +165,7 @@ module.exports = {
|
|
|
164
165
|
getChannels,
|
|
165
166
|
getClosedChannels,
|
|
166
167
|
getConnectedWatchtowers,
|
|
168
|
+
getFailedPayments,
|
|
167
169
|
getFeeRates,
|
|
168
170
|
getForwardingConfidence,
|
|
169
171
|
getForwardingReputations,
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const {returnResult} = require('asyncjs-util');
|
|
3
|
+
|
|
4
|
+
const {isLnd} = require('./../../lnd_requests');
|
|
5
|
+
const {rpcPaymentAsPayment} = require('./../../lnd_responses');
|
|
6
|
+
const {sortBy} = require('./../../arrays');
|
|
7
|
+
|
|
8
|
+
const defaultLimit = 250;
|
|
9
|
+
const {isArray} = Array;
|
|
10
|
+
const isFailed = payment => !!payment && payment.status === 'FAILED';
|
|
11
|
+
const lastPageFirstIndexOffset = 1;
|
|
12
|
+
const method = 'listPayments';
|
|
13
|
+
const {parse} = JSON;
|
|
14
|
+
const {stringify} = JSON;
|
|
15
|
+
const type = 'default';
|
|
16
|
+
|
|
17
|
+
/** Get failed payments made through channels.
|
|
18
|
+
|
|
19
|
+
Requires `offchain:read` permission
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
[limit]: <Page Result Limit Number>
|
|
23
|
+
lnd: <Authenticated LND API Object>
|
|
24
|
+
[token]: <Opaque Paging Token String>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@returns via cbk or Promise
|
|
28
|
+
{
|
|
29
|
+
payments: [{
|
|
30
|
+
attempts: [{
|
|
31
|
+
[failure]: {
|
|
32
|
+
code: <Error Type Code Number>
|
|
33
|
+
[details]: {
|
|
34
|
+
[channel]: <Standard Format Channel Id String>
|
|
35
|
+
[height]: <Error Associated Block Height Number>
|
|
36
|
+
[index]: <Failed Hop Index Number>
|
|
37
|
+
[mtokens]: <Error Millitokens String>
|
|
38
|
+
[policy]: {
|
|
39
|
+
base_fee_mtokens: <Base Fee Millitokens String>
|
|
40
|
+
cltv_delta: <Locktime Delta Number>
|
|
41
|
+
fee_rate: <Fees Charged in Millitokens Per Million Number>
|
|
42
|
+
[is_disabled]: <Channel is Disabled Bool>
|
|
43
|
+
max_htlc_mtokens: <Maximum HLTC Millitokens Value String>
|
|
44
|
+
min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
|
|
45
|
+
updated_at: <Updated At ISO 8601 Date String>
|
|
46
|
+
}
|
|
47
|
+
[timeout_height]: <Error CLTV Timeout Height Number>
|
|
48
|
+
[update]: {
|
|
49
|
+
chain: <Chain Id Hex String>
|
|
50
|
+
channel_flags: <Channel Flags Number>
|
|
51
|
+
extra_opaque_data: <Extra Opaque Data Hex String>
|
|
52
|
+
message_flags: <Message Flags Number>
|
|
53
|
+
signature: <Channel Update Signature Hex String>
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
message: <Error Message String>
|
|
57
|
+
}
|
|
58
|
+
[index]: <Payment Add Index Number>
|
|
59
|
+
[confirmed_at]: <Payment Confirmed At ISO 8601 Date String>
|
|
60
|
+
is_confirmed: <Payment Attempt Succeeded Bool>
|
|
61
|
+
is_failed: <Payment Attempt Failed Bool>
|
|
62
|
+
is_pending: <Payment Attempt is Waiting For Resolution Bool>
|
|
63
|
+
route: {
|
|
64
|
+
fee: <Route Fee Tokens Number>
|
|
65
|
+
fee_mtokens: <Route Fee Millitokens String>
|
|
66
|
+
hops: [{
|
|
67
|
+
channel: <Standard Format Channel Id String>
|
|
68
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
69
|
+
fee: <Fee Number>
|
|
70
|
+
fee_mtokens: <Fee Millitokens String>
|
|
71
|
+
forward: <Forward Tokens Number>
|
|
72
|
+
forward_mtokens: <Forward Millitokens String>
|
|
73
|
+
[public_key]: <Forward Edge Public Key Hex String>
|
|
74
|
+
[timeout]: <Timeout Block Height Number>
|
|
75
|
+
}]
|
|
76
|
+
mtokens: <Total Fee-Inclusive Millitokens String>
|
|
77
|
+
[payment]: <Payment Identifier Hex String>
|
|
78
|
+
timeout: <Timeout Block Height Number>
|
|
79
|
+
tokens: <Total Fee-Inclusive Tokens Number>
|
|
80
|
+
[total_mtokens]: <Total Millitokens String>
|
|
81
|
+
}
|
|
82
|
+
}]
|
|
83
|
+
created_at: <Payment at ISO-8601 Date String>
|
|
84
|
+
[destination]: <Destination Node Public Key Hex String>
|
|
85
|
+
id: <Payment Preimage Hash String>
|
|
86
|
+
[index]: <Payment Add Index Number>
|
|
87
|
+
is_confirmed: <Payment is Confirmed Bool>
|
|
88
|
+
is_outgoing: <Transaction Is Outgoing Bool>
|
|
89
|
+
mtokens: <Millitokens Attempted to Pay to Destination String>
|
|
90
|
+
[request]: <BOLT 11 Payment Request String>
|
|
91
|
+
safe_tokens: <Payment Tokens Attempted to Pay Rounded Up Number>
|
|
92
|
+
tokens: <Rounded Down Tokens Attempted to Pay to Destination Number>
|
|
93
|
+
}]
|
|
94
|
+
[next]: <Next Opaque Paging Token String>
|
|
95
|
+
}
|
|
96
|
+
*/
|
|
97
|
+
module.exports = ({limit, lnd, token}, cbk) => {
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
return asyncAuto({
|
|
100
|
+
// Check arguments
|
|
101
|
+
validate: cbk => {
|
|
102
|
+
if (!!limit && !!token) {
|
|
103
|
+
return cbk([400, 'ExpectedNoLimitWhenPagingPayFailuresWithToken']);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!isLnd({lnd, method, type})) {
|
|
107
|
+
return cbk([400, 'ExpectedLndForGetFailedPaymentsRequest']);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return cbk();
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
// Get all payments
|
|
114
|
+
listPayments: ['validate', ({}, cbk) => {
|
|
115
|
+
let offset;
|
|
116
|
+
let resultsLimit = limit || defaultLimit;
|
|
117
|
+
|
|
118
|
+
if (!!token) {
|
|
119
|
+
try {
|
|
120
|
+
const pagingToken = parse(token);
|
|
121
|
+
|
|
122
|
+
offset = pagingToken.offset;
|
|
123
|
+
resultsLimit = pagingToken.limit;
|
|
124
|
+
} catch (err) {
|
|
125
|
+
return cbk([400, 'ExpectedValidPagingTokenForGetFailed', {err}]);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return lnd[type][method]({
|
|
130
|
+
include_incomplete: true,
|
|
131
|
+
index_offset: offset || Number(),
|
|
132
|
+
max_payments: resultsLimit,
|
|
133
|
+
reversed: true,
|
|
134
|
+
},
|
|
135
|
+
(err, res) => {
|
|
136
|
+
if (!!err) {
|
|
137
|
+
return cbk([503, 'UnexpectedGetFailedPaymentsError', {err}]);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!res || !isArray(res.payments)) {
|
|
141
|
+
return cbk([503, 'ExpectedFailedPaymentsInListPaymentsResponse']);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (typeof res.last_index_offset !== 'string') {
|
|
145
|
+
return cbk([503, 'ExpectedLastIndexOffsetWhenRequestingFailed']);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const lastOffset = Number(res.last_index_offset);
|
|
149
|
+
const offset = Number(res.first_index_offset);
|
|
150
|
+
|
|
151
|
+
const token = stringify({offset, limit: resultsLimit});
|
|
152
|
+
|
|
153
|
+
return cbk(null, {
|
|
154
|
+
payments: res.payments.filter(isFailed),
|
|
155
|
+
token: offset === lastPageFirstIndexOffset ? undefined : token,
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}],
|
|
159
|
+
|
|
160
|
+
// Check and map payments
|
|
161
|
+
foundPayments: ['listPayments', ({listPayments}, cbk) => {
|
|
162
|
+
try {
|
|
163
|
+
const payments = listPayments.payments.map(rpcPaymentAsPayment);
|
|
164
|
+
|
|
165
|
+
return cbk(null, payments);
|
|
166
|
+
} catch (err) {
|
|
167
|
+
return cbk([503, err.message]);
|
|
168
|
+
}
|
|
169
|
+
}],
|
|
170
|
+
|
|
171
|
+
// Final found failed payments
|
|
172
|
+
payments: [
|
|
173
|
+
'foundPayments',
|
|
174
|
+
'listPayments',
|
|
175
|
+
({foundPayments, listPayments}, cbk) =>
|
|
176
|
+
{
|
|
177
|
+
const payments = sortBy({
|
|
178
|
+
array: foundPayments,
|
|
179
|
+
attribute: 'created_at',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return cbk(null, {
|
|
183
|
+
next: listPayments.token || undefined,
|
|
184
|
+
payments: payments.sorted.reverse(),
|
|
185
|
+
});
|
|
186
|
+
}],
|
|
187
|
+
},
|
|
188
|
+
returnResult({reject, resolve, of: 'payments'}, cbk));
|
|
189
|
+
});
|
|
190
|
+
};
|
|
@@ -131,8 +131,6 @@ module.exports = ({limit, lnd, token}, cbk) => {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
const start = Date.now();
|
|
135
|
-
|
|
136
134
|
return lnd[type][method]({
|
|
137
135
|
include_incomplete: false,
|
|
138
136
|
index_offset: offset || Number(),
|
|
@@ -187,8 +185,8 @@ module.exports = ({limit, lnd, token}, cbk) => {
|
|
|
187
185
|
});
|
|
188
186
|
|
|
189
187
|
return cbk(null, {
|
|
190
|
-
payments: payments.sorted.reverse(),
|
|
191
188
|
next: !!foundPayments.length ? listPayments.token : undefined,
|
|
189
|
+
payments: payments.sorted.reverse(),
|
|
192
190
|
});
|
|
193
191
|
}],
|
|
194
192
|
},
|
|
@@ -14,6 +14,7 @@ const getChannelBalance = require('./get_channel_balance');
|
|
|
14
14
|
const getChannels = require('./get_channels');
|
|
15
15
|
const getClosedChannels = require('./get_closed_channels');
|
|
16
16
|
const getConnectedWatchtowers = require('./get_connected_watchtowers');
|
|
17
|
+
const getFailedPayments = require('./get_failed_payments');
|
|
17
18
|
const getFeeRates = require('./get_fee_rates');
|
|
18
19
|
const getForwardingConfidence = require('./get_forwarding_confidence');
|
|
19
20
|
const getForwardingReputations = require('./get_forwarding_reputations');
|
|
@@ -65,6 +66,7 @@ module.exports = {
|
|
|
65
66
|
getChannels,
|
|
66
67
|
getClosedChannels,
|
|
67
68
|
getConnectedWatchtowers,
|
|
69
|
+
getFailedPayments,
|
|
68
70
|
getFeeRates,
|
|
69
71
|
getForwardingConfidence,
|
|
70
72
|
getForwardingReputations,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
const {parsePaymentRequest} = require('invoices');
|
|
2
|
+
|
|
1
3
|
const rpcAttemptHtlcAsAttempt = require('./rpc_attempt_htlc_as_attempt');
|
|
2
4
|
const {safeTokens} = require('./../bolt00');
|
|
3
5
|
|
|
6
|
+
const emptyHash = Buffer.alloc(32).toString('hex');
|
|
4
7
|
const {isArray} = Array;
|
|
5
8
|
const msPerSecond = 1e3;
|
|
6
9
|
const nanoSecsPerMillisecond = BigInt(1e6);
|
|
@@ -129,9 +132,9 @@ const routePublicKeys = route => route.hops.map(n => n.public_key);
|
|
|
129
132
|
}
|
|
130
133
|
}]
|
|
131
134
|
created_at: <Payment at ISO-8601 Date String>
|
|
132
|
-
destination: <Destination Node Public Key Hex String>
|
|
133
|
-
fee: <Paid Routing Fee Rounded Down Tokens Number>
|
|
134
|
-
fee_mtokens: <Paid Routing Fee in Millitokens String>
|
|
135
|
+
[destination]: <Destination Node Public Key Hex String>
|
|
136
|
+
[fee]: <Paid Routing Fee Rounded Down Tokens Number>
|
|
137
|
+
[fee_mtokens]: <Paid Routing Fee in Millitokens String>
|
|
135
138
|
hops: [<First Route Hop Public Key Hex String>]
|
|
136
139
|
id: <Payment Preimage Hash String>
|
|
137
140
|
[index]: <Payment Add Index Number>
|
|
@@ -139,9 +142,9 @@ const routePublicKeys = route => route.hops.map(n => n.public_key);
|
|
|
139
142
|
is_outgoing: <Transaction Is Outgoing Bool>
|
|
140
143
|
mtokens: <Millitokens Sent to Destination String>
|
|
141
144
|
[request]: <BOLT 11 Payment Request String>
|
|
142
|
-
safe_fee: <Payment Forwarding Fee Rounded Up Tokens Number>
|
|
143
|
-
safe_tokens: <Payment Tokens Rounded Up Number>
|
|
144
|
-
secret: <Payment Preimage Hex String>
|
|
145
|
+
[safe_fee]: <Payment Forwarding Fee Rounded Up Tokens Number>
|
|
146
|
+
safe_tokens: <Payment Tokens Sent to Destination Rounded Up Number>
|
|
147
|
+
[secret]: <Payment Preimage Hex String>
|
|
145
148
|
tokens: <Rounded Down Tokens Sent to Destination Number>
|
|
146
149
|
}
|
|
147
150
|
*/
|
|
@@ -186,13 +189,46 @@ module.exports = payment => {
|
|
|
186
189
|
throw new Error('ExpectedPaymentValueInRpcPaymentDetails');
|
|
187
190
|
}
|
|
188
191
|
|
|
192
|
+
const creationDateEpochMs = (() => {
|
|
193
|
+
// Exit early when creation time nanoseconds is not defined
|
|
194
|
+
if (payment.creation_time_ns === Number().toString()) {
|
|
195
|
+
return Number(payment.creation_date) * msPerSecond;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return Number(BigInt(payment.creation_time_ns) / nanoSecsPerMillisecond);
|
|
199
|
+
})();
|
|
200
|
+
|
|
189
201
|
const attempts = payment.htlcs.map(htlc => rpcAttemptHtlcAsAttempt(htlc));
|
|
202
|
+
const index = Number(payment.payment_index) || undefined;
|
|
203
|
+
const request = payment.payment_request || undefined;
|
|
204
|
+
|
|
205
|
+
// Exit early when there were no attempts
|
|
206
|
+
if (!attempts.length) {
|
|
207
|
+
const {destination} = !!request ? parsePaymentRequest({request}) : {};
|
|
190
208
|
|
|
191
|
-
|
|
192
|
-
|
|
209
|
+
return {
|
|
210
|
+
attempts,
|
|
211
|
+
destination,
|
|
212
|
+
index,
|
|
213
|
+
request,
|
|
214
|
+
confirmed_at: undefined,
|
|
215
|
+
created_at: new Date(creationDateEpochMs).toISOString(),
|
|
216
|
+
fee: undefined,
|
|
217
|
+
fee_mtokens: undefined,
|
|
218
|
+
hops: [],
|
|
219
|
+
id: payment.payment_hash,
|
|
220
|
+
is_confirmed: false,
|
|
221
|
+
is_outgoing: true,
|
|
222
|
+
mtokens: payment.value_msat,
|
|
223
|
+
safe_fee: undefined,
|
|
224
|
+
safe_tokens: safeTokens({mtokens: payment.value_msat}).safe,
|
|
225
|
+
secret: undefined,
|
|
226
|
+
tokens: safeTokens({mtokens: payment.value_msat}).tokens,
|
|
227
|
+
};
|
|
193
228
|
}
|
|
194
229
|
|
|
195
230
|
const hasPath = !!payment.path.length;
|
|
231
|
+
const hasPreimage = payment.payment_preimage !== emptyHash;
|
|
196
232
|
const [attempt] = attempts;
|
|
197
233
|
const successes = attempts.filter(n => n.is_confirmed);
|
|
198
234
|
|
|
@@ -201,32 +237,46 @@ module.exports = payment => {
|
|
|
201
237
|
|
|
202
238
|
const [destination, ...hops] = path.reverse();
|
|
203
239
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
240
|
+
// Exit early when the payment was never settled
|
|
241
|
+
if (!hasPreimage) {
|
|
242
|
+
return {
|
|
243
|
+
attempts,
|
|
244
|
+
destination,
|
|
245
|
+
index,
|
|
246
|
+
request,
|
|
247
|
+
confirmed_at: undefined,
|
|
248
|
+
created_at: new Date(creationDateEpochMs).toISOString(),
|
|
249
|
+
fee: undefined,
|
|
250
|
+
fee_mtokens: undefined,
|
|
251
|
+
hops: hops.reverse(),
|
|
252
|
+
id: payment.payment_hash,
|
|
253
|
+
is_confirmed: false,
|
|
254
|
+
is_outgoing: true,
|
|
255
|
+
mtokens: payment.value_msat,
|
|
256
|
+
safe_fee: undefined,
|
|
257
|
+
safe_tokens: safeTokens({mtokens: payment.value_msat}).safe,
|
|
258
|
+
secret: undefined,
|
|
259
|
+
tokens: safeTokens({mtokens: payment.value_msat}).tokens,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
212
262
|
|
|
213
263
|
return {
|
|
264
|
+
attempts,
|
|
214
265
|
destination,
|
|
215
|
-
|
|
266
|
+
index,
|
|
267
|
+
request,
|
|
216
268
|
confirmed_at: confirmedAt || undefined,
|
|
217
269
|
created_at: new Date(creationDateEpochMs).toISOString(),
|
|
218
270
|
fee: safeTokens({mtokens: payment.fee_msat}).tokens,
|
|
219
271
|
fee_mtokens: payment.fee_msat,
|
|
220
272
|
hops: hops.reverse(),
|
|
221
273
|
id: payment.payment_hash,
|
|
222
|
-
|
|
223
|
-
is_confirmed: payment.value_msat !== Number().toString(),
|
|
274
|
+
is_confirmed: true,
|
|
224
275
|
is_outgoing: true,
|
|
225
276
|
mtokens: payment.value_msat,
|
|
226
|
-
request: payment.payment_request || undefined,
|
|
227
|
-
secret: payment.payment_preimage,
|
|
228
277
|
safe_fee: safeTokens({mtokens: payment.fee_msat}).safe,
|
|
229
278
|
safe_tokens: safeTokens({mtokens: payment.value_msat}).safe,
|
|
279
|
+
secret: payment.payment_preimage,
|
|
230
280
|
tokens: safeTokens({mtokens: payment.value_msat}).tokens,
|
|
231
281
|
};
|
|
232
282
|
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {getPayments} = require('./../../../');
|
|
4
|
+
|
|
5
|
+
const makeLnd = args => {
|
|
6
|
+
return {
|
|
7
|
+
default: {
|
|
8
|
+
listPayments: ({}, cbk) => cbk(null, {
|
|
9
|
+
first_index_offset: args.first_index_offset || '1',
|
|
10
|
+
payments: [{
|
|
11
|
+
creation_date: '1',
|
|
12
|
+
creation_time_ns: '1',
|
|
13
|
+
failure_reason: '',
|
|
14
|
+
fee_msat: '1000',
|
|
15
|
+
fee_sat: '1',
|
|
16
|
+
htlcs: [],
|
|
17
|
+
path: [Buffer.alloc(33, 2).toString('hex')],
|
|
18
|
+
payment_hash: Buffer.alloc(32).toString('hex'),
|
|
19
|
+
payment_index: '1',
|
|
20
|
+
payment_preimage: Buffer.alloc(32).toString('hex'),
|
|
21
|
+
payment_request: '',
|
|
22
|
+
status: 'FAILED',
|
|
23
|
+
value: '1',
|
|
24
|
+
value_msat: '1000',
|
|
25
|
+
value_sat: '1',
|
|
26
|
+
}],
|
|
27
|
+
last_index_offset: args.last_index_offset || '1',
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const makeArgs = overrides => {
|
|
34
|
+
const args = {lnd: makeLnd({})};
|
|
35
|
+
|
|
36
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
37
|
+
|
|
38
|
+
return args;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const makeExpectedPayment = ({}) => {
|
|
42
|
+
return {
|
|
43
|
+
destination: undefined,
|
|
44
|
+
attempts: [],
|
|
45
|
+
confirmed_at: undefined,
|
|
46
|
+
created_at: '1970-01-01T00:00:00.000Z',
|
|
47
|
+
fee: undefined,
|
|
48
|
+
fee_mtokens: undefined,
|
|
49
|
+
hops: [],
|
|
50
|
+
id: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
51
|
+
index: 1,
|
|
52
|
+
is_confirmed: false,
|
|
53
|
+
is_outgoing: true,
|
|
54
|
+
mtokens: '1000',
|
|
55
|
+
request: undefined,
|
|
56
|
+
secret: undefined,
|
|
57
|
+
safe_fee: undefined,
|
|
58
|
+
safe_tokens: 1,
|
|
59
|
+
tokens: 1,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const tests = [
|
|
64
|
+
{
|
|
65
|
+
args: makeArgs({limit: 1, token: 'token'}),
|
|
66
|
+
description: 'A limit cannot be passed with a token',
|
|
67
|
+
error: [400, 'UnexpectedLimitWhenPagingPaymentsWithToken'],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
args: makeArgs({lnd: undefined}),
|
|
71
|
+
description: 'LND is required',
|
|
72
|
+
error: [400, 'ExpectedLndForGetPaymentsRequest'],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
args: makeArgs({token: 'token'}),
|
|
76
|
+
description: 'A valid token is required',
|
|
77
|
+
error: [400, 'ExpectedValidPagingTokenForPaymentReq'],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
args: makeArgs({lnd: {default: {listPayments: ({}, cbk) => cbk('err')}}}),
|
|
81
|
+
description: 'Errors from LND are passed back',
|
|
82
|
+
error: [503, 'UnexpectedGetPaymentsError', {err: 'err'}],
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
args: makeArgs({lnd: {default: {listPayments: ({}, cbk) => cbk()}}}),
|
|
86
|
+
description: 'A response is expected from LND',
|
|
87
|
+
error: [503, 'ExpectedPaymentsInListPaymentsResponse'],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
args: makeArgs({
|
|
91
|
+
lnd: {default: {listPayments: ({}, cbk) => cbk(null, {})}},
|
|
92
|
+
}),
|
|
93
|
+
description: 'A response with payments is expected from LND',
|
|
94
|
+
error: [503, 'ExpectedPaymentsInListPaymentsResponse'],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
args: makeArgs({
|
|
98
|
+
lnd: {default: {listPayments: ({}, cbk) => cbk(null, {payments: []})}},
|
|
99
|
+
}),
|
|
100
|
+
description: 'A response with payments and last index is expected',
|
|
101
|
+
error: [503, 'ExpectedLastIndexOffsetWhenRequestingPayments'],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
args: makeArgs({
|
|
105
|
+
lnd: {
|
|
106
|
+
default: {
|
|
107
|
+
listPayments: ({}, cbk) => cbk(null, {
|
|
108
|
+
last_index_offset: '1',
|
|
109
|
+
payments: [{}],
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
description: 'A response with valid payments is expected',
|
|
115
|
+
error: [503, 'ExpectedCreationDateInRpcPaymentDetails'],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
args: makeArgs({}),
|
|
119
|
+
description: 'A payment is returned',
|
|
120
|
+
expected: {payment: makeExpectedPayment({})},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
args: makeArgs({
|
|
124
|
+
lnd: {
|
|
125
|
+
default: {
|
|
126
|
+
listPayments: ({}, cbk) => cbk(null, {
|
|
127
|
+
last_index_offset: '1',
|
|
128
|
+
payments: [],
|
|
129
|
+
}),
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
}),
|
|
133
|
+
description: 'No payments are returned',
|
|
134
|
+
expected: {},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
args: makeArgs({
|
|
138
|
+
lnd: makeLnd({first_index_offset: '2'}),
|
|
139
|
+
token: JSON.stringify({limit: 1, offset: 1})
|
|
140
|
+
}),
|
|
141
|
+
description: 'A payment is returned when a token is specified',
|
|
142
|
+
expected: {payment: makeExpectedPayment({})},
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
147
|
+
return test(description, async ({end, rejects, strictSame}) => {
|
|
148
|
+
if (!!error) {
|
|
149
|
+
await rejects(() => getPayments(args), error, 'Got expected error');
|
|
150
|
+
} else {
|
|
151
|
+
const {payments} = await getPayments(args);
|
|
152
|
+
|
|
153
|
+
const [payment] = payments;
|
|
154
|
+
|
|
155
|
+
strictSame(payment, expected.payment, 'Got expected payment');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return end();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -39,7 +39,7 @@ const makeLnd = args => {
|
|
|
39
39
|
path: [Buffer.alloc(33, 2).toString('hex')],
|
|
40
40
|
payment_hash: Buffer.alloc(32).toString('hex'),
|
|
41
41
|
payment_index: '1',
|
|
42
|
-
payment_preimage: Buffer.alloc(32).toString('hex'),
|
|
42
|
+
payment_preimage: Buffer.alloc(32, 1).toString('hex'),
|
|
43
43
|
payment_request: '',
|
|
44
44
|
status: 'SETTLED',
|
|
45
45
|
value: '1',
|
|
@@ -99,7 +99,7 @@ const makeExpectedPayment = ({}) => {
|
|
|
99
99
|
is_outgoing: true,
|
|
100
100
|
mtokens: '1000',
|
|
101
101
|
request: undefined,
|
|
102
|
-
secret: '
|
|
102
|
+
secret: Buffer.alloc(32, 1).toString('hex'),
|
|
103
103
|
safe_fee: 1,
|
|
104
104
|
safe_tokens: 1,
|
|
105
105
|
tokens: 1,
|
|
@@ -57,9 +57,9 @@ const makeArgs = overrides => {
|
|
|
57
57
|
path: [Buffer.alloc(33).toString('hex'), Buffer.alloc(33).toString('hex')],
|
|
58
58
|
payment_hash: Buffer.alloc(32).toString('hex'),
|
|
59
59
|
payment_index: '1',
|
|
60
|
-
payment_preimage: Buffer.alloc(32).toString('hex'),
|
|
60
|
+
payment_preimage: Buffer.alloc(32, 1).toString('hex'),
|
|
61
61
|
payment_request: 'lntb1500n1pdn4czkpp5ugdqer05qrrxuchrzkcue94th9w2xzasp9qm7d0yxcgp4uh4kn4qdpa2fjkzep6yprkcmmzv9kzqsmj09c8gmmrw4e8yetwvdujq5n9va6kcct5d9hkucqzysdlghdpua7uvjjkcfj49psxtlqzkp5pdncffdfk2cp3mp76thrl29qhqgzufm503pjj96586n5w6edgw3n66j4rxxs707y4zdjuhyt6qqe5weu4',
|
|
62
|
-
status: '
|
|
62
|
+
status: 'SETTLED',
|
|
63
63
|
value: '1',
|
|
64
64
|
value_msat: '1000',
|
|
65
65
|
value_sat: '1',
|
|
@@ -111,7 +111,7 @@ const makeExpected = overrides => {
|
|
|
111
111
|
request: 'lntb1500n1pdn4czkpp5ugdqer05qrrxuchrzkcue94th9w2xzasp9qm7d0yxcgp4uh4kn4qdpa2fjkzep6yprkcmmzv9kzqsmj09c8gmmrw4e8yetwvdujq5n9va6kcct5d9hkucqzysdlghdpua7uvjjkcfj49psxtlqzkp5pdncffdfk2cp3mp76thrl29qhqgzufm503pjj96586n5w6edgw3n66j4rxxs707y4zdjuhyt6qqe5weu4',
|
|
112
112
|
safe_fee: 1,
|
|
113
113
|
safe_tokens: 1,
|
|
114
|
-
secret: Buffer.alloc(32).toString('hex'),
|
|
114
|
+
secret: Buffer.alloc(32, 1).toString('hex'),
|
|
115
115
|
tokens: 1,
|
|
116
116
|
};
|
|
117
117
|
|
|
@@ -141,11 +141,6 @@ const tests = [
|
|
|
141
141
|
description: 'HTLC array is expected to be present',
|
|
142
142
|
error: 'ExpectedHtlcsArrayInRpcPaymentDetails',
|
|
143
143
|
},
|
|
144
|
-
{
|
|
145
|
-
args: makeArgs({htlcs: [], path: []}),
|
|
146
|
-
description: 'HTLC or path array is expected to be filled',
|
|
147
|
-
error: 'ExpectedAttemptInPaymentDetails',
|
|
148
|
-
},
|
|
149
144
|
{
|
|
150
145
|
args: makeArgs({path: undefined}),
|
|
151
146
|
description: 'A path is expected to be present',
|
|
@@ -186,6 +181,46 @@ const tests = [
|
|
|
186
181
|
description: 'A payment request is optional',
|
|
187
182
|
expected: makeExpected({request: undefined}),
|
|
188
183
|
},
|
|
184
|
+
{
|
|
185
|
+
args: makeArgs({htlcs: []}),
|
|
186
|
+
description: 'Attempts are optional',
|
|
187
|
+
expected: makeExpected({
|
|
188
|
+
attempts: [],
|
|
189
|
+
destination: '02212d3ec887188b284dbb7b2e6eb40629a6e14fb049673f22d2a0aa05f902090e',
|
|
190
|
+
fee: undefined,
|
|
191
|
+
fee_mtokens: undefined,
|
|
192
|
+
hops: [],
|
|
193
|
+
is_confirmed: false,
|
|
194
|
+
safe_fee: undefined,
|
|
195
|
+
secret: undefined,
|
|
196
|
+
}),
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
args: makeArgs({htlcs: [], payment_request: ''}),
|
|
200
|
+
description: 'Payment requests are optional when there are no attempts',
|
|
201
|
+
expected: makeExpected({
|
|
202
|
+
attempts: [],
|
|
203
|
+
destination: undefined,
|
|
204
|
+
fee: undefined,
|
|
205
|
+
fee_mtokens: undefined,
|
|
206
|
+
hops: [],
|
|
207
|
+
is_confirmed: false,
|
|
208
|
+
request: undefined,
|
|
209
|
+
safe_fee: undefined,
|
|
210
|
+
secret: undefined,
|
|
211
|
+
}),
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
args: makeArgs({payment_preimage: Buffer.alloc(32).toString('hex')}),
|
|
215
|
+
description: 'Empty preimage means not settled',
|
|
216
|
+
expected: makeExpected({
|
|
217
|
+
fee: undefined,
|
|
218
|
+
fee_mtokens: undefined,
|
|
219
|
+
is_confirmed: false,
|
|
220
|
+
safe_fee: undefined,
|
|
221
|
+
secret: undefined,
|
|
222
|
+
}),
|
|
223
|
+
},
|
|
189
224
|
{
|
|
190
225
|
args: makeArgs({
|
|
191
226
|
creation_date: '1587410235',
|