lightning 4.13.3 → 4.14.3
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/lnd_methods/macaroon/subscribe_to_rpc_requests.d.ts +8 -4
- package/lnd_methods/offchain/emit_payment.js +23 -1
- package/lnd_methods/offchain/get_payment.d.ts +54 -0
- package/lnd_methods/offchain/get_payment.js +26 -1
- package/lnd_methods/offchain/subscribe_to_past_payment.d.ts +50 -1
- package/lnd_methods/offchain/subscribe_to_past_payment.js +28 -1
- package/lnd_methods/offchain/subscribe_to_pay.js +57 -2
- package/lnd_methods/offchain/subscribe_to_pay_via_details.js +55 -1
- package/lnd_methods/offchain/subscribe_to_pay_via_request.js +56 -1
- package/lnd_responses/index.js +4 -0
- package/lnd_responses/pending_from_payment.js +145 -0
- package/lnd_responses/routing_failure_from_htlc.js +105 -0
- package/package.json +3 -3
- package/test/lnd_methods/offchain/test_get_payment.js +71 -1
- package/test/lnd_responses/test_pending_from_payment.js +143 -0
- package/test/lnd_responses/test_routing_failure_from_htlc.js +137 -0
package/CHANGELOG.md
CHANGED
|
@@ -21,8 +21,6 @@ export type SubscribeToRpcRequestsResult = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export type SubscribeToRpcRequestsCommonEvent = {
|
|
24
|
-
/** Call Id Number */
|
|
25
|
-
call: number;
|
|
26
24
|
/** Message Id Number */
|
|
27
25
|
id: number;
|
|
28
26
|
/** Base64 Encoded Macaroon String */
|
|
@@ -122,11 +120,17 @@ export type SubscribeToRpcRequestsPayViaRouteRequestEvent =
|
|
|
122
120
|
};
|
|
123
121
|
}>;
|
|
124
122
|
|
|
123
|
+
export type SubscribeToRpcRequestsRequestOrResponseEvent =
|
|
124
|
+
SubscribeToRpcRequestsCommonEvent & {
|
|
125
|
+
/** Call Id Number */
|
|
126
|
+
call: number;
|
|
127
|
+
};
|
|
128
|
+
|
|
125
129
|
export type SubscribeToRpcRequestsRequestEvent =
|
|
126
|
-
|
|
130
|
+
SubscribeToRpcRequestsRequestOrResponseEvent;
|
|
127
131
|
|
|
128
132
|
export type SubscribeToRpcRequestsResponseEvent =
|
|
129
|
-
|
|
133
|
+
SubscribeToRpcRequestsRequestOrResponseEvent;
|
|
130
134
|
|
|
131
135
|
/**
|
|
132
136
|
* Subscribe to RPC requests and their responses
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
const {confirmedFromPayment} = require('./../../lnd_responses');
|
|
2
2
|
const {failureFromPayment} = require('./../../lnd_responses');
|
|
3
|
+
const {pendingFromPayment} = require('./../../lnd_responses');
|
|
4
|
+
const {routingFailureFromHtlc} = require('./../../lnd_responses');
|
|
3
5
|
const {states} = require('./payment_states');
|
|
4
6
|
|
|
7
|
+
const failedStatus = 'FAILED';
|
|
8
|
+
const {isArray} = Array;
|
|
9
|
+
|
|
5
10
|
/** Emit payment from payment event
|
|
6
11
|
|
|
7
12
|
{
|
|
@@ -21,7 +26,24 @@ module.exports = ({data, emitter}) => {
|
|
|
21
26
|
return emitter.emit('failed', failureFromPayment(data));
|
|
22
27
|
|
|
23
28
|
case states.paying:
|
|
24
|
-
|
|
29
|
+
const hasHtlcs = !!data && isArray(data.htlcs) && !!data.htlcs.length;
|
|
30
|
+
|
|
31
|
+
// Exit early when no HTLCs are attached
|
|
32
|
+
if (!hasHtlcs) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Emit routing failures
|
|
37
|
+
data.htlcs.filter(n => n.status === failedStatus).forEach(htlc => {
|
|
38
|
+
return emitter.emit('routing_failure', routingFailureFromHtlc(htlc));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Exit early when the HTLCs have no pending payments
|
|
42
|
+
if (!data.htlcs.find(n => n.status === states.paying)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return emitter.emit('paying', pendingFromPayment(data));
|
|
25
47
|
|
|
26
48
|
default:
|
|
27
49
|
return;
|
|
@@ -105,6 +105,60 @@ export type GetPaymentResult = {
|
|
|
105
105
|
/** Total Tokens Paid */
|
|
106
106
|
tokens: number;
|
|
107
107
|
};
|
|
108
|
+
pending?: {
|
|
109
|
+
/** Created at ISO-8601 Date */
|
|
110
|
+
created_at: string;
|
|
111
|
+
/** Payment Destination Public Key Hex */
|
|
112
|
+
destination: string;
|
|
113
|
+
/** Payment Hash Hex */
|
|
114
|
+
id: string;
|
|
115
|
+
/** Total Millitokens Pending */
|
|
116
|
+
mtokens: string;
|
|
117
|
+
paths: {
|
|
118
|
+
/** Total Path Fee Tokens */
|
|
119
|
+
fee: number;
|
|
120
|
+
/** Total Path Fee Millitokens */
|
|
121
|
+
fee_mtokens: string;
|
|
122
|
+
hops: {
|
|
123
|
+
/** Standard Format Channel Id */
|
|
124
|
+
channel: string;
|
|
125
|
+
/** Channel Capacity Tokens */
|
|
126
|
+
channel_capacity: number;
|
|
127
|
+
/** Routing Fee Tokens */
|
|
128
|
+
fee: number;
|
|
129
|
+
/** Fee Millitokens */
|
|
130
|
+
fee_mtokens: string;
|
|
131
|
+
/** Forwarded Tokens */
|
|
132
|
+
forward: number;
|
|
133
|
+
/** Forward Millitokens */
|
|
134
|
+
forward_mtokens: string;
|
|
135
|
+
/** Public Key Hex */
|
|
136
|
+
public_key: string;
|
|
137
|
+
/** Timeout Block Height */
|
|
138
|
+
timeout: number;
|
|
139
|
+
}[];
|
|
140
|
+
/** Total Path Millitokens Paid */
|
|
141
|
+
mtokens: string;
|
|
142
|
+
/** MPP Payment Identifying Nonce */
|
|
143
|
+
payment: string;
|
|
144
|
+
/** Expiration Block Height */
|
|
145
|
+
timeout: number;
|
|
146
|
+
/** Path Tokens Paid */
|
|
147
|
+
tokens: number;
|
|
148
|
+
/** Total Millitokens Pending */
|
|
149
|
+
total_mtokens: string;
|
|
150
|
+
}[]
|
|
151
|
+
/** BOLT 11 Payment Request */
|
|
152
|
+
request?: string;
|
|
153
|
+
/** Payment Tokens Rounded Up */
|
|
154
|
+
safe_tokens: number;
|
|
155
|
+
/** Payment Preimage Hex */
|
|
156
|
+
secret: string;
|
|
157
|
+
/** Expiration Block Height */
|
|
158
|
+
timeout?: number;
|
|
159
|
+
/** Total Tokens Pending */
|
|
160
|
+
tokens: number;
|
|
161
|
+
};
|
|
108
162
|
};
|
|
109
163
|
|
|
110
164
|
/**
|
|
@@ -67,6 +67,30 @@ const type = 'router';
|
|
|
67
67
|
timeout: <Expiration Block Height Number>
|
|
68
68
|
tokens: <Total Tokens Paid Number>
|
|
69
69
|
}
|
|
70
|
+
[pending]: {
|
|
71
|
+
created_at: <Payment Created At ISO 8601 Date String>
|
|
72
|
+
destination: <Payment Destination Hex String>
|
|
73
|
+
id: <Payment Hash Hex String>
|
|
74
|
+
mtokens: <Total Millitokens Pending String>
|
|
75
|
+
paths: [{
|
|
76
|
+
fee_mtokens: <Total Fee Millitokens Paid String>
|
|
77
|
+
hops: [{
|
|
78
|
+
channel: <Standard Format Channel Id String>
|
|
79
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
80
|
+
fee: <Fee Tokens Rounded Down Number>
|
|
81
|
+
fee_mtokens: <Fee Millitokens String>
|
|
82
|
+
forward: <Forwarded Tokens Number>
|
|
83
|
+
forward_mtokens: <Forward Millitokens String>
|
|
84
|
+
public_key: <Public Key Hex String>
|
|
85
|
+
timeout: <Timeout Block Height Number>
|
|
86
|
+
}]
|
|
87
|
+
mtokens: <Total Millitokens Pending String>
|
|
88
|
+
}]
|
|
89
|
+
[request]: <BOLT 11 Encoded Payment Request String>
|
|
90
|
+
safe_tokens: <Payment Tokens Rounded Up Number>
|
|
91
|
+
[timeout]: <Expiration Block Height Number>
|
|
92
|
+
tokens: <Total Tokens Pending Number>
|
|
93
|
+
}
|
|
70
94
|
}
|
|
71
95
|
*/
|
|
72
96
|
module.exports = ({id, lnd}, cbk) => {
|
|
@@ -102,6 +126,7 @@ module.exports = ({id, lnd}, cbk) => {
|
|
|
102
126
|
is_failed: !!res.failed,
|
|
103
127
|
is_pending: !res.payment && !res.failed,
|
|
104
128
|
payment: res.payment || undefined,
|
|
129
|
+
pending: res.pending || undefined,
|
|
105
130
|
});
|
|
106
131
|
};
|
|
107
132
|
|
|
@@ -109,7 +134,7 @@ module.exports = ({id, lnd}, cbk) => {
|
|
|
109
134
|
sub.once('end', () => cbk([503, 'UnknownStatusOfPayment']));
|
|
110
135
|
sub.once('error', err => finished(err));
|
|
111
136
|
sub.once('failed', failed => finished(null, {failed}));
|
|
112
|
-
sub.once('paying',
|
|
137
|
+
sub.once('paying', pending => finished(null, {pending}));
|
|
113
138
|
|
|
114
139
|
return;
|
|
115
140
|
}],
|
|
@@ -66,7 +66,56 @@ export type SubscribeToPastPaymentFailedEvent = {
|
|
|
66
66
|
is_route_not_found: boolean;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
export type SubscribeToPastPaymentPayingEvent = {
|
|
69
|
+
export type SubscribeToPastPaymentPayingEvent = {
|
|
70
|
+
/** Payment Created At ISO 8601 Date String */
|
|
71
|
+
created_at: string;
|
|
72
|
+
/** Payment Destination Hex String */
|
|
73
|
+
destination: string;
|
|
74
|
+
/** Payment Hash Hex String */
|
|
75
|
+
id: string;
|
|
76
|
+
/** Total Millitokens Pending String */
|
|
77
|
+
mtokens: string;
|
|
78
|
+
paths: {
|
|
79
|
+
/** Total Fee Tokens Pending Number */
|
|
80
|
+
fee: number;
|
|
81
|
+
/** Total Fee Millitokens Pending String */
|
|
82
|
+
fee_mtokens: string;
|
|
83
|
+
hops: {
|
|
84
|
+
/** Standard Format Channel Id String */
|
|
85
|
+
channel: string;
|
|
86
|
+
/** Channel Capacity Tokens Number */
|
|
87
|
+
channel_capacity: number;
|
|
88
|
+
/** Fee Tokens Rounded Down Number */
|
|
89
|
+
fee: number;
|
|
90
|
+
/** Fee Millitokens String */
|
|
91
|
+
fee_mtokens: string;
|
|
92
|
+
/** Forward Tokens Number */
|
|
93
|
+
forward: number;
|
|
94
|
+
/** Forward Millitokens String */
|
|
95
|
+
forward_mtokens: string;
|
|
96
|
+
/** Public Key Hex String */
|
|
97
|
+
public_key: string;
|
|
98
|
+
/** Timeout Block Height Number */
|
|
99
|
+
timeout: number;
|
|
100
|
+
}[];
|
|
101
|
+
/** Total Millitokens Pending String */
|
|
102
|
+
mtokens: string;
|
|
103
|
+
/** Total Fee Tokens Pending Rounded Up Number */
|
|
104
|
+
safe_fee: number;
|
|
105
|
+
/** Total Tokens Pending, Rounded Up Number */
|
|
106
|
+
safe_tokens: number;
|
|
107
|
+
/** Expiration Block Height Number */
|
|
108
|
+
timeout: number;
|
|
109
|
+
}[];
|
|
110
|
+
/** BOLT 11 Encoded Payment Request String */
|
|
111
|
+
request?: string;
|
|
112
|
+
/** Total Tokens Pending, Rounded Up Number */
|
|
113
|
+
safe_tokens: number;
|
|
114
|
+
/** Expiration Block Height Number */
|
|
115
|
+
timeout?: number;
|
|
116
|
+
/** Total Tokens Pending Rounded Down Number */
|
|
117
|
+
tokens: number;
|
|
118
|
+
};
|
|
70
119
|
|
|
71
120
|
/**
|
|
72
121
|
* Subscribe to the status of a past payment
|
|
@@ -82,7 +82,34 @@ const unknownServiceErr = 'unknown service verrpc.Versioner';
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
@event 'paying'
|
|
85
|
-
{
|
|
85
|
+
{
|
|
86
|
+
created_at: <Payment Created At ISO 8601 Date String>
|
|
87
|
+
destination: <Payment Destination Hex String>
|
|
88
|
+
id: <Payment Hash Hex String>
|
|
89
|
+
mtokens: <Total Millitokens Pending String>
|
|
90
|
+
paths: [{
|
|
91
|
+
fee: <Total Fee Tokens Pending Number>
|
|
92
|
+
fee_mtokens: <Total Fee Millitokens Pending String>
|
|
93
|
+
hops: [{
|
|
94
|
+
channel: <Standard Format Channel Id String>
|
|
95
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
96
|
+
fee: <Fee Tokens Rounded Down Number>
|
|
97
|
+
fee_mtokens: <Fee Millitokens String>
|
|
98
|
+
forward: <Forward Tokens Number>
|
|
99
|
+
forward_mtokens: <Forward Millitokens String>
|
|
100
|
+
public_key: <Public Key Hex String>
|
|
101
|
+
timeout: <Timeout Block Height Number>
|
|
102
|
+
}]
|
|
103
|
+
mtokens: <Total Millitokens Pending String>
|
|
104
|
+
safe_fee: <Total Fee Tokens Pending Rounded Up Number>
|
|
105
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
106
|
+
timeout: <Expiration Block Height Number>
|
|
107
|
+
}]
|
|
108
|
+
[request]: <BOLT 11 Encoded Payment Request String>
|
|
109
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
110
|
+
[timeout]: <Expiration Block Height Number>
|
|
111
|
+
tokens: <Total Tokens Pending Rounded Down Number>
|
|
112
|
+
}
|
|
86
113
|
*/
|
|
87
114
|
module.exports = args => {
|
|
88
115
|
if (!isHash(args.id)) {
|
|
@@ -146,7 +146,62 @@ const unknownServiceErr = 'unknown service verrpc.Versioner';
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
@event 'paying'
|
|
149
|
-
{
|
|
149
|
+
{
|
|
150
|
+
created_at: <Payment Created At ISO 8601 Date String>
|
|
151
|
+
destination: <Payment Destination Hex String>
|
|
152
|
+
id: <Payment Hash Hex String>
|
|
153
|
+
mtokens: <Total Millitokens Pending String>
|
|
154
|
+
paths: [{
|
|
155
|
+
fee: <Total Fee Tokens Pending Number>
|
|
156
|
+
fee_mtokens: <Total Fee Millitokens Pending String>
|
|
157
|
+
hops: [{
|
|
158
|
+
channel: <Standard Format Channel Id String>
|
|
159
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
160
|
+
fee: <Fee Tokens Rounded Down Number>
|
|
161
|
+
fee_mtokens: <Fee Millitokens String>
|
|
162
|
+
forward: <Forward Tokens Number>
|
|
163
|
+
forward_mtokens: <Forward Millitokens String>
|
|
164
|
+
public_key: <Public Key Hex String>
|
|
165
|
+
timeout: <Timeout Block Height Number>
|
|
166
|
+
}]
|
|
167
|
+
mtokens: <Total Millitokens Pending String>
|
|
168
|
+
safe_fee: <Total Fee Tokens Pending Rounded Up Number>
|
|
169
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
170
|
+
timeout: <Expiration Block Height Number>
|
|
171
|
+
}]
|
|
172
|
+
[request]: <BOLT 11 Encoded Payment Request String>
|
|
173
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
174
|
+
[timeout]: <Expiration Block Height Number>
|
|
175
|
+
tokens: <Total Tokens Pending Rounded Down Number>
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@event 'routing_failure'
|
|
179
|
+
{
|
|
180
|
+
[channel]: <Standard Format Channel Id String>
|
|
181
|
+
index: <Failure Index Number>
|
|
182
|
+
[mtokens]: <Millitokens String>
|
|
183
|
+
[public_key]: <Public Key Hex String>
|
|
184
|
+
reason: <Failure Reason String>
|
|
185
|
+
route: {
|
|
186
|
+
fee: <Total Route Fee Tokens To Pay Number>
|
|
187
|
+
fee_mtokens: <Total Route Fee Millitokens To Pay String>
|
|
188
|
+
hops: [{
|
|
189
|
+
channel: <Standard Format Channel Id String>
|
|
190
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
191
|
+
fee: <Fee Number>
|
|
192
|
+
fee_mtokens: <Fee Millitokens String>
|
|
193
|
+
forward: <Forward Tokens Number>
|
|
194
|
+
forward_mtokens: <Forward Millitokens String>
|
|
195
|
+
public_key: <Public Key Hex String>
|
|
196
|
+
timeout: <Timeout Block Height Number>
|
|
197
|
+
}]
|
|
198
|
+
mtokens: <Total Route Millitokens String>
|
|
199
|
+
[payment]: <Payment Identifier Hex String>
|
|
200
|
+
timeout: <Expiration Block Height Number>
|
|
201
|
+
tokens: <Total Route Tokens Number>
|
|
202
|
+
[total_mtokens]: <Total Millitokens String>
|
|
203
|
+
}
|
|
204
|
+
}
|
|
150
205
|
*/
|
|
151
206
|
module.exports = args => {
|
|
152
207
|
if (!!args.cltv_delta && !!args.request) {
|
|
@@ -316,7 +371,7 @@ module.exports = args => {
|
|
|
316
371
|
last_hop_pubkey: hexToBuf(args.incoming_peer),
|
|
317
372
|
max_parts: args.max_paths || defaultMaxPaths,
|
|
318
373
|
max_shard_size_msat: args.max_path_mtokens || undefined,
|
|
319
|
-
no_inflight_updates:
|
|
374
|
+
no_inflight_updates: false,
|
|
320
375
|
outgoing_chan_id: !hasOutIds ? singleOut : undefined,
|
|
321
376
|
outgoing_chan_ids: outgoingChannelIds,
|
|
322
377
|
payment_addr: !!args.payment ? hexToBuf(args.payment) : undefined,
|
|
@@ -120,7 +120,61 @@ const type = 'router';
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
@event 'paying'
|
|
123
|
-
{
|
|
123
|
+
{
|
|
124
|
+
created_at: <Payment Created At ISO 8601 Date String>
|
|
125
|
+
destination: <Payment Destination Hex String>
|
|
126
|
+
id: <Payment Hash Hex String>
|
|
127
|
+
mtokens: <Total Millitokens Pending String>
|
|
128
|
+
paths: [{
|
|
129
|
+
fee: <Total Fee Tokens Pending Number>
|
|
130
|
+
fee_mtokens: <Total Fee Millitokens Pending String>
|
|
131
|
+
hops: [{
|
|
132
|
+
channel: <Standard Format Channel Id String>
|
|
133
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
134
|
+
fee: <Fee Tokens Rounded Down Number>
|
|
135
|
+
fee_mtokens: <Fee Millitokens String>
|
|
136
|
+
forward: <Forward Tokens Number>
|
|
137
|
+
forward_mtokens: <Forward Millitokens String>
|
|
138
|
+
public_key: <Public Key Hex String>
|
|
139
|
+
timeout: <Timeout Block Height Number>
|
|
140
|
+
}]
|
|
141
|
+
mtokens: <Total Millitokens Pending String>
|
|
142
|
+
safe_fee: <Total Fee Tokens Pending Rounded Up Number>
|
|
143
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
144
|
+
timeout: <Expiration Block Height Number>
|
|
145
|
+
}]
|
|
146
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
147
|
+
[timeout]: <Expiration Block Height Number>
|
|
148
|
+
tokens: <Total Tokens Pending Rounded Down Number>
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@event 'routing_failure'
|
|
152
|
+
{
|
|
153
|
+
[channel]: <Standard Format Channel Id String>
|
|
154
|
+
index: <Failure Index Number>
|
|
155
|
+
[mtokens]: <Millitokens String>
|
|
156
|
+
[public_key]: <Public Key Hex String>
|
|
157
|
+
reason: <Failure Reason String>
|
|
158
|
+
route: {
|
|
159
|
+
fee: <Total Route Fee Tokens To Pay Number>
|
|
160
|
+
fee_mtokens: <Total Route Fee Millitokens To Pay String>
|
|
161
|
+
hops: [{
|
|
162
|
+
channel: <Standard Format Channel Id String>
|
|
163
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
164
|
+
fee: <Fee Number>
|
|
165
|
+
fee_mtokens: <Fee Millitokens String>
|
|
166
|
+
forward: <Forward Tokens Number>
|
|
167
|
+
forward_mtokens: <Forward Millitokens String>
|
|
168
|
+
public_key: <Public Key Hex String>
|
|
169
|
+
timeout: <Timeout Block Height Number>
|
|
170
|
+
}]
|
|
171
|
+
mtokens: <Total Route Millitokens String>
|
|
172
|
+
[payment]: <Payment Identifier Hex String>
|
|
173
|
+
timeout: <Expiration Block Height Number>
|
|
174
|
+
tokens: <Total Route Tokens Number>
|
|
175
|
+
[total_mtokens]: <Total Millitokens String>
|
|
176
|
+
}
|
|
177
|
+
}
|
|
124
178
|
*/
|
|
125
179
|
module.exports = args => {
|
|
126
180
|
if (!isPublicKey(args.destination)) {
|
|
@@ -100,7 +100,62 @@ const type = 'router';
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
@event 'paying'
|
|
103
|
-
{
|
|
103
|
+
{
|
|
104
|
+
created_at: <Payment Created At ISO 8601 Date String>
|
|
105
|
+
destination: <Payment Destination Hex String>
|
|
106
|
+
id: <Payment Hash Hex String>
|
|
107
|
+
mtokens: <Total Millitokens Pending String>
|
|
108
|
+
paths: [{
|
|
109
|
+
fee: <Total Fee Tokens Pending Number>
|
|
110
|
+
fee_mtokens: <Total Fee Millitokens Pending String>
|
|
111
|
+
hops: [{
|
|
112
|
+
channel: <Standard Format Channel Id String>
|
|
113
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
114
|
+
fee: <Fee Tokens Rounded Down Number>
|
|
115
|
+
fee_mtokens: <Fee Millitokens String>
|
|
116
|
+
forward: <Forward Tokens Number>
|
|
117
|
+
forward_mtokens: <Forward Millitokens String>
|
|
118
|
+
public_key: <Public Key Hex String>
|
|
119
|
+
timeout: <Timeout Block Height Number>
|
|
120
|
+
}]
|
|
121
|
+
mtokens: <Total Millitokens Pending String>
|
|
122
|
+
safe_fee: <Total Fee Tokens Pending Rounded Up Number>
|
|
123
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
124
|
+
timeout: <Expiration Block Height Number>
|
|
125
|
+
}]
|
|
126
|
+
[request]: <BOLT 11 Encoded Payment Request String>
|
|
127
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
128
|
+
[timeout]: <Expiration Block Height Number>
|
|
129
|
+
tokens: <Total Tokens Pending Rounded Down Number>
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@event 'routing_failure'
|
|
133
|
+
{
|
|
134
|
+
[channel]: <Standard Format Channel Id String>
|
|
135
|
+
index: <Failure Index Number>
|
|
136
|
+
[mtokens]: <Millitokens String>
|
|
137
|
+
[public_key]: <Public Key Hex String>
|
|
138
|
+
reason: <Failure Reason String>
|
|
139
|
+
route: {
|
|
140
|
+
fee: <Total Route Fee Tokens To Pay Number>
|
|
141
|
+
fee_mtokens: <Total Route Fee Millitokens To Pay String>
|
|
142
|
+
hops: [{
|
|
143
|
+
channel: <Standard Format Channel Id String>
|
|
144
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
145
|
+
fee: <Fee Number>
|
|
146
|
+
fee_mtokens: <Fee Millitokens String>
|
|
147
|
+
forward: <Forward Tokens Number>
|
|
148
|
+
forward_mtokens: <Forward Millitokens String>
|
|
149
|
+
public_key: <Public Key Hex String>
|
|
150
|
+
timeout: <Timeout Block Height Number>
|
|
151
|
+
}]
|
|
152
|
+
mtokens: <Total Route Millitokens String>
|
|
153
|
+
[payment]: <Payment Identifier Hex String>
|
|
154
|
+
timeout: <Expiration Block Height Number>
|
|
155
|
+
tokens: <Total Route Tokens Number>
|
|
156
|
+
[total_mtokens]: <Total Millitokens String>
|
|
157
|
+
}
|
|
158
|
+
}
|
|
104
159
|
*/
|
|
105
160
|
module.exports = args => {
|
|
106
161
|
if (!args.request) {
|
package/lnd_responses/index.js
CHANGED
|
@@ -11,8 +11,10 @@ const nodeInfoAsNode = require('./node_info_as_node');
|
|
|
11
11
|
const paymentFailure = require('./payment_failure');
|
|
12
12
|
const paymentRequestDetails = require('./payment_request_details');
|
|
13
13
|
const pendingAsPendingChannels = require('./pending_as_pending_channels');
|
|
14
|
+
const pendingFromPayment = require('./pending_from_payment');
|
|
14
15
|
const policyFromChannelUpdate = require('./policy_from_channel_update');
|
|
15
16
|
const routesFromQueryRoutes = require('./routes_from_query_routes');
|
|
17
|
+
const routingFailureFromHtlc = require('./routing_failure_from_htlc');
|
|
16
18
|
const rpcAttemptHtlcAsAttempt = require('./rpc_attempt_htlc_as_attempt');
|
|
17
19
|
const rpcChannelAsChannel = require('./rpc_channel_as_channel');
|
|
18
20
|
const rpcChannelAsOldRpcChannel = require('./rpc_channel_as_old_rpc_channel');
|
|
@@ -53,8 +55,10 @@ module.exports = {
|
|
|
53
55
|
paymentFailure,
|
|
54
56
|
paymentRequestDetails,
|
|
55
57
|
pendingAsPendingChannels,
|
|
58
|
+
pendingFromPayment,
|
|
56
59
|
policyFromChannelUpdate,
|
|
57
60
|
routesFromQueryRoutes,
|
|
61
|
+
routingFailureFromHtlc,
|
|
58
62
|
rpcAttemptHtlcAsAttempt,
|
|
59
63
|
rpcChannelAsChannel,
|
|
60
64
|
rpcChannelAsOldRpcChannel,
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
const {attemptStates} = require('./constants');
|
|
2
|
+
const rpcAttemptHtlcAsAttempt = require('./rpc_attempt_htlc_as_attempt');
|
|
3
|
+
const {safeTokens} = require('./../bolt00');
|
|
4
|
+
|
|
5
|
+
const {isArray} = Array;
|
|
6
|
+
const is256Hex = n => !!n && /^[0-9A-F]{64}$/i.test(n);
|
|
7
|
+
const {max} = Math;
|
|
8
|
+
const mtokensAsTokens = mtokens => safeTokens({mtokens}).tokens;
|
|
9
|
+
const nsAsDate = ns => new Date(Number(BigInt(ns) / BigInt(1e6)));
|
|
10
|
+
|
|
11
|
+
/** Calculate total payment details from RPC payment HTLC elements
|
|
12
|
+
|
|
13
|
+
The `route` attribute only returns the first route, there may be more due to
|
|
14
|
+
payment splitting
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
creation_date: <Creation Date Epoch Time Seconds String>
|
|
18
|
+
creation_time_ns: <Creation Date Epoch Time Nanoseconds String>
|
|
19
|
+
failure_reason: <Payment Failure Reason String>
|
|
20
|
+
fee_msat: <Fee Paid in Millitokens String>
|
|
21
|
+
fee_sat: <Fee Paid in Tokens String>
|
|
22
|
+
htlcs: [{
|
|
23
|
+
attempt_time_ns: <HTLC Sent At Epoch Time Nanoseconds String>
|
|
24
|
+
resolve_time_ns: <HTLC Resolved At Epoch Time Nanoseconds String>
|
|
25
|
+
route: {
|
|
26
|
+
hops: [{
|
|
27
|
+
amt_to_forward: <Tokens to Forward String>
|
|
28
|
+
amt_to_forward_msat: <Millitokens to Forward String>
|
|
29
|
+
chan_id: <Numeric Format Channel Id String>
|
|
30
|
+
chan_capacity: <Channel Capacity Tokens String>
|
|
31
|
+
custom_records: {
|
|
32
|
+
<UInt64 String>: <Record Data Buffer>
|
|
33
|
+
}
|
|
34
|
+
expiry: <Timeout Chain Height Number>
|
|
35
|
+
fee: <Fee in Tokens String>
|
|
36
|
+
fee_msat: <Fee in Millitokens String>
|
|
37
|
+
[mpp_record]: {
|
|
38
|
+
payment_addr: <Payment Identifier Buffer>
|
|
39
|
+
total_amt_msat: <Total Payment Millitokens Amount String>
|
|
40
|
+
}
|
|
41
|
+
[pub_key]: <Next Hop Public Key Hex String>
|
|
42
|
+
tlv_payload: <Has Extra TLV Data Bool>
|
|
43
|
+
}]
|
|
44
|
+
total_amt: <Total Tokens String>
|
|
45
|
+
total_amt_msat: <Route Total Millitokens String>
|
|
46
|
+
total_fees: <Route Fee Tokens String>
|
|
47
|
+
total_fees_msat: <Route Total Fees Millitokens String>
|
|
48
|
+
total_time_lock: <Route Total Timelock Number>
|
|
49
|
+
}
|
|
50
|
+
status: <HTLC Status String>
|
|
51
|
+
}]
|
|
52
|
+
path: [<Hop Public Key Hex String>]
|
|
53
|
+
payment_hash: <Preimage SHA256 Hash Hex String>
|
|
54
|
+
payment_index: <Payment Index String>
|
|
55
|
+
payment_preimage: <Payment Secret Preimage Hex String>
|
|
56
|
+
payment_request: <BOLT 11 Payment Request String>
|
|
57
|
+
status: <Payment State String>
|
|
58
|
+
value: <Tokens String>
|
|
59
|
+
value_msat: <Paid Tokens Without Routing Fees Millitokens String>
|
|
60
|
+
value_sat: <Paid Tokens Without Routing Fees String>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@throws
|
|
64
|
+
<Error>
|
|
65
|
+
|
|
66
|
+
@returns
|
|
67
|
+
{
|
|
68
|
+
created_at: <Payment Created At ISO 8601 Date String>
|
|
69
|
+
destination: <Payment Destination Public Key Hex String>
|
|
70
|
+
id: <Payment Hash Hex String>
|
|
71
|
+
mtokens: <Total Millitokens Pending String>
|
|
72
|
+
paths: [{
|
|
73
|
+
fee: <Total Fee Tokens Pending Number>
|
|
74
|
+
fee_mtokens: <Total Fee Millitokens Pending String>
|
|
75
|
+
hops: [{
|
|
76
|
+
channel: <Standard Format Channel Id String>
|
|
77
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
78
|
+
fee: <Fee Tokens Rounded Down Number>
|
|
79
|
+
fee_mtokens: <Fee Millitokens String>
|
|
80
|
+
forward: <Forward Tokens Number>
|
|
81
|
+
forward_mtokens: <Forward Millitokens String>
|
|
82
|
+
public_key: <Public Key Hex String>
|
|
83
|
+
timeout: <Timeout Block Height Number>
|
|
84
|
+
}]
|
|
85
|
+
mtokens: <Total Millitokens Paid String>
|
|
86
|
+
safe_fee: <Total Fee Tokens Paid Rounded Up Number>
|
|
87
|
+
safe_tokens: <Total Tokens Paid, Rounded Up Number>
|
|
88
|
+
timeout: <Expiration Block Height Number>
|
|
89
|
+
}]
|
|
90
|
+
[request]: <BOLT 11 Encoded Payment Request String>
|
|
91
|
+
safe_tokens: <Total Tokens Pending, Rounded Up Number>
|
|
92
|
+
[timeout]: <Expiration Block Height Number>
|
|
93
|
+
tokens: <Total Tokens Pending Rounded Down Number>
|
|
94
|
+
}
|
|
95
|
+
*/
|
|
96
|
+
module.exports = payment => {
|
|
97
|
+
if (!payment) {
|
|
98
|
+
throw new Error('ExpectedPendingPaymentToDerivePendingDetails');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!payment.creation_time_ns) {
|
|
102
|
+
throw new Error('ExpectedPaymentCreationDateToDerivePendingDetails');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!payment.fee_msat) {
|
|
106
|
+
throw new Error('ExpectedPaymentFeeMillitokensAmountForPendingPayment');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!isArray(payment.htlcs)) {
|
|
110
|
+
throw new Error('ExpectedArrayOfPaymentHtlcsInPendingPayment');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!payment.htlcs.find(n => n.status === attemptStates.pending)) {
|
|
114
|
+
throw new Error('ExpectedPendingHtlcInPendingPayment');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!is256Hex(payment.payment_hash)) {
|
|
118
|
+
throw new Error('ExpectedPaymentHashForPaymentAsPendingPayment');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (mtokensAsTokens(payment.value_msat) !== Number(payment.value_sat)) {
|
|
122
|
+
throw new Error('ExpectedValueOfTokensAndMillitokensToBeConsistent');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const attempts = payment.htlcs.map(htlc => rpcAttemptHtlcAsAttempt(htlc));
|
|
126
|
+
const mtokens = BigInt(payment.value_msat) + BigInt(payment.fee_msat);
|
|
127
|
+
|
|
128
|
+
const pending = attempts.filter(n => n.is_pending);
|
|
129
|
+
|
|
130
|
+
const [first] = pending;
|
|
131
|
+
|
|
132
|
+
const [destination] = first.route.hops.map(n => n.public_key).reverse();
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
destination,
|
|
136
|
+
created_at: nsAsDate(payment.creation_time_ns).toISOString(),
|
|
137
|
+
id: payment.payment_hash,
|
|
138
|
+
mtokens: mtokens.toString(),
|
|
139
|
+
paths: pending.map(n => n.route),
|
|
140
|
+
request: payment.payment_request || undefined,
|
|
141
|
+
safe_tokens: safeTokens({mtokens: mtokens.toString()}).safe,
|
|
142
|
+
timeout: max(...pending.map(n => n.route.timeout).filter(n => !!n)),
|
|
143
|
+
tokens: safeTokens({mtokens: mtokens.toString()}).tokens,
|
|
144
|
+
};
|
|
145
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const paymentFailure = require('./payment_failure');
|
|
2
|
+
const rpcRouteAsRoute = require('./rpc_route_as_route');
|
|
3
|
+
|
|
4
|
+
/** Derive routing failure details from an HTLC
|
|
5
|
+
|
|
6
|
+
{
|
|
7
|
+
attempt_time_ns: <HTLC Sent At Epoch Time Nanoseconds String>
|
|
8
|
+
failure: {
|
|
9
|
+
[channel_update]: {
|
|
10
|
+
base_fee: <Base Fee Millitokens Number>
|
|
11
|
+
chain_hash: <Chain Hash Buffer Object>
|
|
12
|
+
[chan_id]: <Numeric Channel Id String>
|
|
13
|
+
channel_flags: <Channel Flags Number>
|
|
14
|
+
extra_opaque_data: <Extra Opaque Data Buffer Object>
|
|
15
|
+
fee_rate: <Fee Rate Number>
|
|
16
|
+
htlc_maximum_msat: <Maximum HTLC Millitokens Number>
|
|
17
|
+
htlc_minimum_msat: <Minimum HTLC Millitokens Number>
|
|
18
|
+
message_flags: <Message Flags Number>
|
|
19
|
+
signature: <Signature Buffer Object>
|
|
20
|
+
time_lock_delta: <CLTV Delta Number>
|
|
21
|
+
timestamp: <Update Epoch Time Seconds Number>
|
|
22
|
+
}
|
|
23
|
+
code: <Failure Code String>
|
|
24
|
+
[failure_source_index]: <Failed Hop Index Number>
|
|
25
|
+
height: <Height Number>
|
|
26
|
+
htlc_msat: <HTLC Millitokens String>
|
|
27
|
+
}
|
|
28
|
+
resolve_time_ns: <HTLC Resolved At Epoch Time Nanoseconds String>
|
|
29
|
+
route: {
|
|
30
|
+
hops: [{
|
|
31
|
+
amt_to_forward: <Tokens to Forward String>
|
|
32
|
+
amt_to_forward_msat: <Millitokens to Forward String>
|
|
33
|
+
chan_id: <Numeric Format Channel Id String>
|
|
34
|
+
chan_capacity: <Channel Capacity Number>
|
|
35
|
+
expiry: <Timeout Chain Height Number>
|
|
36
|
+
fee: <Fee in Tokens Number>
|
|
37
|
+
fee_msat: <Fee in Millitokens Number>
|
|
38
|
+
[mpp_record]: {
|
|
39
|
+
payment_addr: <Payment Identifier Buffer>
|
|
40
|
+
total_amt_msat: <Total Payment Millitokens Amount String>
|
|
41
|
+
}
|
|
42
|
+
pub_key: <Next Hop Public Key Hex String>
|
|
43
|
+
tlv_payload: <Has Extra TLV Data Bool>
|
|
44
|
+
}]
|
|
45
|
+
total_amt: <Total Tokens String>
|
|
46
|
+
total_amt_msat: <Route Total Millitokens String>
|
|
47
|
+
total_fees: <Route Fee Tokens String>
|
|
48
|
+
total_fees_msat: <Route Total Fees Millitokens String>
|
|
49
|
+
total_time_lock: <Route Total Timelock Number>
|
|
50
|
+
}
|
|
51
|
+
status: <HTLC Status String>
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@throws
|
|
55
|
+
<Error>
|
|
56
|
+
|
|
57
|
+
@returns
|
|
58
|
+
{
|
|
59
|
+
[channel]: <Standard Format Channel Id String>
|
|
60
|
+
index: <Failure Index Number>
|
|
61
|
+
[mtokens]: <Millitokens String>
|
|
62
|
+
[public_key]: <Public Key Hex String>
|
|
63
|
+
reason: <Failure Reason String>
|
|
64
|
+
route: {
|
|
65
|
+
fee: <Total Route Fee Tokens To Pay Number>
|
|
66
|
+
fee_mtokens: <Total Route Fee Millitokens To Pay String>
|
|
67
|
+
hops: [{
|
|
68
|
+
channel: <Standard Format Channel Id String>
|
|
69
|
+
channel_capacity: <Channel Capacity Tokens Number>
|
|
70
|
+
fee: <Fee Number>
|
|
71
|
+
fee_mtokens: <Fee Millitokens String>
|
|
72
|
+
forward: <Forward Tokens Number>
|
|
73
|
+
forward_mtokens: <Forward Millitokens String>
|
|
74
|
+
public_key: <Public Key Hex String>
|
|
75
|
+
timeout: <Timeout Block Height Number>
|
|
76
|
+
}]
|
|
77
|
+
mtokens: <Total Route Millitokens String>
|
|
78
|
+
[payment]: <Payment Identifier Hex String>
|
|
79
|
+
timeout: <Expiration Block Height Number>
|
|
80
|
+
tokens: <Total Route Tokens Number>
|
|
81
|
+
[total_mtokens]: <Total Millitokens String>
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
*/
|
|
85
|
+
module.exports = htlc => {
|
|
86
|
+
const from = htlc.route.hops[htlc.failure.failure_source_index - 1] || {};
|
|
87
|
+
|
|
88
|
+
const failure = paymentFailure({
|
|
89
|
+
channel: htlc.channel,
|
|
90
|
+
failure: htlc.failure,
|
|
91
|
+
index: htlc.index,
|
|
92
|
+
key: from.pub_key,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const route = rpcRouteAsRoute(htlc.route);
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
route,
|
|
99
|
+
channel: failure.details.channel,
|
|
100
|
+
index: failure.details.index,
|
|
101
|
+
mtokens: route.mtokens,
|
|
102
|
+
public_key: from.pub_key,
|
|
103
|
+
reason: failure.message,
|
|
104
|
+
};
|
|
105
|
+
};
|
package/package.json
CHANGED
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
"@types/ws": "8.2.0",
|
|
16
16
|
"async": "3.2.2",
|
|
17
17
|
"asyncjs-util": "1.2.7",
|
|
18
|
-
"bitcoinjs-lib": "
|
|
18
|
+
"bitcoinjs-lib": "6.0.0",
|
|
19
19
|
"bn.js": "5.2.0",
|
|
20
20
|
"body-parser": "1.19.0",
|
|
21
21
|
"bolt07": "1.7.4",
|
|
22
22
|
"bolt09": "0.2.0",
|
|
23
|
-
"cbor": "8.0
|
|
23
|
+
"cbor": "8.1.0",
|
|
24
24
|
"express": "4.17.1",
|
|
25
25
|
"invoices": "2.0.1",
|
|
26
26
|
"psbt": "1.1.10"
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"directory": "test/typescript"
|
|
57
57
|
},
|
|
58
58
|
"types": "index.d.ts",
|
|
59
|
-
"version": "4.
|
|
59
|
+
"version": "4.14.3"
|
|
60
60
|
}
|
|
@@ -8,7 +8,48 @@ const makeLnd = args => {
|
|
|
8
8
|
return {
|
|
9
9
|
router: {
|
|
10
10
|
trackPaymentV2: ({}) => {
|
|
11
|
-
const data = args.data || {
|
|
11
|
+
const data = args.data || {
|
|
12
|
+
creation_date: '1',
|
|
13
|
+
creation_time_ns: '1',
|
|
14
|
+
failure_reason: 'FAILURE_REASON_NONE',
|
|
15
|
+
fee: '1',
|
|
16
|
+
fee_msat: '1000',
|
|
17
|
+
fee_sat: '1',
|
|
18
|
+
htlcs: [{
|
|
19
|
+
attempt_time_ns: '1',
|
|
20
|
+
status: 'IN_FLIGHT',
|
|
21
|
+
resolve_time_ns: '1',
|
|
22
|
+
route: {
|
|
23
|
+
hops: [{
|
|
24
|
+
amt_to_forward: '1',
|
|
25
|
+
amt_to_forward_msat: '1000',
|
|
26
|
+
chan_capacity: '1',
|
|
27
|
+
chan_id: '1',
|
|
28
|
+
custom_records: {'1': Buffer.alloc(1)},
|
|
29
|
+
expiry: 1,
|
|
30
|
+
fee: '1',
|
|
31
|
+
fee_msat: '1000',
|
|
32
|
+
mpp_record: {payment_addr: Buffer.alloc(32), total_amt_msat: '1000'},
|
|
33
|
+
pub_key: Buffer.alloc(33).toString('hex'),
|
|
34
|
+
tlv_payload: true,
|
|
35
|
+
}],
|
|
36
|
+
total_amt: '1',
|
|
37
|
+
total_amt_msat: '1000',
|
|
38
|
+
total_time_lock: 1,
|
|
39
|
+
total_fees: '1',
|
|
40
|
+
total_fees_msat: '1000',
|
|
41
|
+
},
|
|
42
|
+
}],
|
|
43
|
+
path: [Buffer.alloc(33).toString('hex')],
|
|
44
|
+
payment_hash: Buffer.alloc(32).toString('hex'),
|
|
45
|
+
payment_index: '1',
|
|
46
|
+
payment_preimage: Buffer.alloc(32).toString('hex'),
|
|
47
|
+
payment_request: '',
|
|
48
|
+
status: 'IN_FLIGHT',
|
|
49
|
+
value: '1',
|
|
50
|
+
value_msat: '1000',
|
|
51
|
+
value_sat: '1',
|
|
52
|
+
};
|
|
12
53
|
const emitter = new EventEmitter();
|
|
13
54
|
|
|
14
55
|
if (!!args.is_end) {
|
|
@@ -146,6 +187,35 @@ const tests = [
|
|
|
146
187
|
is_failed: false,
|
|
147
188
|
is_pending: true,
|
|
148
189
|
payment: undefined,
|
|
190
|
+
pending: {
|
|
191
|
+
created_at: '1970-01-01T00:00:00.000Z',
|
|
192
|
+
destination: Buffer.alloc(33).toString('hex'),
|
|
193
|
+
id: Buffer.alloc(32).toString('hex'),
|
|
194
|
+
mtokens: '2000',
|
|
195
|
+
paths: [{
|
|
196
|
+
fee: 1,
|
|
197
|
+
fee_mtokens: '1000',
|
|
198
|
+
hops: [{
|
|
199
|
+
channel: '0x0x1',
|
|
200
|
+
channel_capacity: 1,
|
|
201
|
+
fee: 1,
|
|
202
|
+
fee_mtokens: '1000',
|
|
203
|
+
forward: 1,
|
|
204
|
+
forward_mtokens: '1000',
|
|
205
|
+
public_key: Buffer.alloc(33).toString('hex'),
|
|
206
|
+
timeout: 1,
|
|
207
|
+
}],
|
|
208
|
+
mtokens: '1000',
|
|
209
|
+
payment: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
210
|
+
timeout: 1,
|
|
211
|
+
tokens: 1,
|
|
212
|
+
total_mtokens: '1000',
|
|
213
|
+
}],
|
|
214
|
+
request: undefined,
|
|
215
|
+
safe_tokens: 2,
|
|
216
|
+
timeout: 1,
|
|
217
|
+
tokens: 2,
|
|
218
|
+
},
|
|
149
219
|
},
|
|
150
220
|
},
|
|
151
221
|
},
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {pendingFromPayment} = require('./../../lnd_responses');
|
|
4
|
+
|
|
5
|
+
const makeArgs = overrides => {
|
|
6
|
+
const args = {
|
|
7
|
+
creation_date: '1',
|
|
8
|
+
creation_time_ns: '1',
|
|
9
|
+
failure_reason: 'FAILURE_REASON_NONE',
|
|
10
|
+
fee: '1',
|
|
11
|
+
fee_msat: '1000',
|
|
12
|
+
fee_sat: '1',
|
|
13
|
+
htlcs: [{
|
|
14
|
+
attempt_time_ns: '1',
|
|
15
|
+
status: 'IN_FLIGHT',
|
|
16
|
+
resolve_time_ns: '1',
|
|
17
|
+
route: {
|
|
18
|
+
hops: [{
|
|
19
|
+
amt_to_forward: '1',
|
|
20
|
+
amt_to_forward_msat: '1000',
|
|
21
|
+
chan_capacity: '1',
|
|
22
|
+
chan_id: '1',
|
|
23
|
+
custom_records: {'1': Buffer.alloc(1)},
|
|
24
|
+
expiry: 1,
|
|
25
|
+
fee: '1',
|
|
26
|
+
fee_msat: '1000',
|
|
27
|
+
mpp_record: {payment_addr: Buffer.alloc(32), total_amt_msat: '1000'},
|
|
28
|
+
pub_key: Buffer.alloc(33).toString('hex'),
|
|
29
|
+
tlv_payload: true,
|
|
30
|
+
}],
|
|
31
|
+
total_amt: '1',
|
|
32
|
+
total_amt_msat: '1000',
|
|
33
|
+
total_time_lock: 1,
|
|
34
|
+
total_fees: '1',
|
|
35
|
+
total_fees_msat: '1000',
|
|
36
|
+
},
|
|
37
|
+
}],
|
|
38
|
+
path: [Buffer.alloc(33).toString('hex')],
|
|
39
|
+
payment_hash: Buffer.alloc(32).toString('hex'),
|
|
40
|
+
payment_index: '1',
|
|
41
|
+
payment_preimage: Buffer.alloc(32).toString('hex'),
|
|
42
|
+
payment_request: '',
|
|
43
|
+
status: 'IN_FLIGHT',
|
|
44
|
+
value: '1',
|
|
45
|
+
value_msat: '1000',
|
|
46
|
+
value_sat: '1',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
50
|
+
|
|
51
|
+
return args;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const makeExpected = overrides => {
|
|
55
|
+
const expected = {
|
|
56
|
+
created_at: '1970-01-01T00:00:00.000Z',
|
|
57
|
+
destination: Buffer.alloc(33).toString('hex'),
|
|
58
|
+
id: Buffer.alloc(32).toString('hex'),
|
|
59
|
+
mtokens: '2000',
|
|
60
|
+
paths: [{
|
|
61
|
+
fee: 1,
|
|
62
|
+
fee_mtokens: '1000',
|
|
63
|
+
hops: [{
|
|
64
|
+
channel: '0x0x1',
|
|
65
|
+
channel_capacity: 1,
|
|
66
|
+
fee: 1,
|
|
67
|
+
fee_mtokens: '1000',
|
|
68
|
+
forward: 1,
|
|
69
|
+
forward_mtokens: '1000',
|
|
70
|
+
public_key: Buffer.alloc(33).toString('hex'),
|
|
71
|
+
timeout: 1,
|
|
72
|
+
}],
|
|
73
|
+
mtokens: '1000',
|
|
74
|
+
payment: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
75
|
+
timeout: 1,
|
|
76
|
+
tokens: 1,
|
|
77
|
+
total_mtokens: '1000',
|
|
78
|
+
}],
|
|
79
|
+
request: undefined,
|
|
80
|
+
safe_tokens: 2,
|
|
81
|
+
timeout: 1,
|
|
82
|
+
tokens: 2,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
Object.keys(overrides).forEach(k => expected[k] = overrides[k]);
|
|
86
|
+
|
|
87
|
+
return expected;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const tests = [
|
|
91
|
+
{
|
|
92
|
+
args: undefined,
|
|
93
|
+
description: 'A payment is expected',
|
|
94
|
+
error: 'ExpectedPendingPaymentToDerivePendingDetails',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
args: makeArgs({creation_time_ns: undefined}),
|
|
98
|
+
description: 'Creation time is expected',
|
|
99
|
+
error: 'ExpectedPaymentCreationDateToDerivePendingDetails',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
args: makeArgs({fee_msat: undefined}),
|
|
103
|
+
description: 'Fee millitokens are expected',
|
|
104
|
+
error: 'ExpectedPaymentFeeMillitokensAmountForPendingPayment',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
args: makeArgs({htlcs: undefined}),
|
|
108
|
+
description: 'HTLCs are expected',
|
|
109
|
+
error: 'ExpectedArrayOfPaymentHtlcsInPendingPayment',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
args: makeArgs({htlcs: [{}]}),
|
|
113
|
+
description: 'A successful HTLC is expected',
|
|
114
|
+
error: 'ExpectedPendingHtlcInPendingPayment',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
args: makeArgs({payment_hash: undefined}),
|
|
118
|
+
description: 'A payment hash is expected',
|
|
119
|
+
error: 'ExpectedPaymentHashForPaymentAsPendingPayment',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
args: makeArgs({value_sat: '1', value_msat: '0'}),
|
|
123
|
+
description: 'Values are expected to agree',
|
|
124
|
+
error: 'ExpectedValueOfTokensAndMillitokensToBeConsistent',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
args: makeArgs({}),
|
|
128
|
+
description: 'Payment is mapped to confirmed payment details',
|
|
129
|
+
expected: makeExpected({}),
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
134
|
+
return test(description, ({end, strictSame, throws}) => {
|
|
135
|
+
if (!!error) {
|
|
136
|
+
throws(() => pendingFromPayment(args), new Error(error), 'Err');
|
|
137
|
+
} else {
|
|
138
|
+
strictSame(pendingFromPayment(args), expected, 'Mapped');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return end();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {routingFailureFromHtlc} = require('./../../lnd_responses');
|
|
4
|
+
|
|
5
|
+
const makeHtlc = overrides => {
|
|
6
|
+
const htlc = {
|
|
7
|
+
attempt_time_ns: '1',
|
|
8
|
+
failure: {
|
|
9
|
+
channel_update: {
|
|
10
|
+
base_fee: 1,
|
|
11
|
+
chain_hash: Buffer.alloc(32),
|
|
12
|
+
chan_id: '1',
|
|
13
|
+
channel_flags: 1,
|
|
14
|
+
extra_opaque_data: Buffer.alloc(0),
|
|
15
|
+
fee_rate: 1,
|
|
16
|
+
htlc_maximum_msat: 1,
|
|
17
|
+
htlc_minimum_msat: 1,
|
|
18
|
+
message_flags: 1,
|
|
19
|
+
signature: Buffer.alloc(0),
|
|
20
|
+
time_lock_delta: 1,
|
|
21
|
+
timestamp: 1,
|
|
22
|
+
},
|
|
23
|
+
code: 'TEMPORARY_CHANNEL_FAILURE',
|
|
24
|
+
failure_source_index: 0,
|
|
25
|
+
height: 1,
|
|
26
|
+
htlc_msat: '1000',
|
|
27
|
+
},
|
|
28
|
+
resolve_time_ns: '1',
|
|
29
|
+
route: {
|
|
30
|
+
hops: [{
|
|
31
|
+
amt_to_forward: '1',
|
|
32
|
+
amt_to_forward_msat: '1000',
|
|
33
|
+
chan_id: '1',
|
|
34
|
+
chan_capacity: 1,
|
|
35
|
+
expiry: 1,
|
|
36
|
+
fee: 0,
|
|
37
|
+
fee_msat: '0',
|
|
38
|
+
pub_key: Buffer.alloc(33, 3).toString('hex'),
|
|
39
|
+
tlv_payload: true,
|
|
40
|
+
}],
|
|
41
|
+
total_amt: '1',
|
|
42
|
+
total_amt_msat: '1000',
|
|
43
|
+
total_fees: 0,
|
|
44
|
+
total_fees_msat: '0',
|
|
45
|
+
total_time_lock: 1,
|
|
46
|
+
},
|
|
47
|
+
status: 'FAILED',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
Object.keys(overrides || {}).forEach(k => htlc[k] = overrides[k]);
|
|
51
|
+
|
|
52
|
+
return htlc;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const makeExpected = overrides => {
|
|
56
|
+
const expected = {
|
|
57
|
+
route: {
|
|
58
|
+
fee: 0,
|
|
59
|
+
fee_mtokens: '0',
|
|
60
|
+
hops: [
|
|
61
|
+
{
|
|
62
|
+
channel: '0x0x1',
|
|
63
|
+
channel_capacity: 1,
|
|
64
|
+
fee: 0,
|
|
65
|
+
fee_mtokens: '0',
|
|
66
|
+
forward: 1,
|
|
67
|
+
forward_mtokens: '1000',
|
|
68
|
+
public_key: '030303030303030303030303030303030303030303030303030303030303030303',
|
|
69
|
+
timeout: 1,
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
mtokens: '1000',
|
|
73
|
+
payment: undefined,
|
|
74
|
+
timeout: 1,
|
|
75
|
+
tokens: 1,
|
|
76
|
+
total_mtokens: undefined,
|
|
77
|
+
},
|
|
78
|
+
channel: '0x0x1',
|
|
79
|
+
index: 0,
|
|
80
|
+
mtokens: '1000',
|
|
81
|
+
public_key: undefined,
|
|
82
|
+
reason: 'TemporaryChannelFailure',
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
Object.keys(overrides || {}).forEach(key => expected[key] = overrides[key]);
|
|
86
|
+
|
|
87
|
+
return expected;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const tests = [
|
|
91
|
+
{
|
|
92
|
+
args: makeHtlc({}),
|
|
93
|
+
description: 'HTLC is mapped to a routing failure',
|
|
94
|
+
expected: makeExpected({}),
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
args: makeHtlc({
|
|
98
|
+
failure: {
|
|
99
|
+
channel_update: {
|
|
100
|
+
base_fee: 1,
|
|
101
|
+
chain_hash: Buffer.alloc(32),
|
|
102
|
+
chan_id: '1',
|
|
103
|
+
channel_flags: 1,
|
|
104
|
+
extra_opaque_data: Buffer.alloc(0),
|
|
105
|
+
fee_rate: 1,
|
|
106
|
+
htlc_maximum_msat: 1,
|
|
107
|
+
htlc_minimum_msat: 1,
|
|
108
|
+
message_flags: 1,
|
|
109
|
+
signature: Buffer.alloc(0),
|
|
110
|
+
time_lock_delta: 1,
|
|
111
|
+
timestamp: 1,
|
|
112
|
+
},
|
|
113
|
+
code: 'TEMPORARY_CHANNEL_FAILURE',
|
|
114
|
+
failure_source_index: 1,
|
|
115
|
+
height: 1,
|
|
116
|
+
htlc_msat: '1000',
|
|
117
|
+
},
|
|
118
|
+
}),
|
|
119
|
+
description: 'HTLC is mapped to a routing failure with key',
|
|
120
|
+
expected: makeExpected({
|
|
121
|
+
index: 1,
|
|
122
|
+
public_key: Buffer.alloc(33, 3).toString('hex'),
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
128
|
+
return test(description, ({end, strictSame, throws}) => {
|
|
129
|
+
if (!!error) {
|
|
130
|
+
throws(() => routingFailureFromHtlc(args), new Error(error), 'Got err');
|
|
131
|
+
} else {
|
|
132
|
+
strictSame(routingFailureFromHtlc(args), expected, 'HTLC mapped');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return end();
|
|
136
|
+
});
|
|
137
|
+
});
|