lightning 6.4.1 → 6.5.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Versions
2
2
 
3
+ ## 6.5.0
4
+
5
+ - `getFailedPayments`, `getInvoices`, `getPayments`, `getPendingPayments`: add
6
+ support for date based filtering with `created_after` and `created_before`
7
+ arguments
8
+
3
9
  ## 6.4.1
4
10
 
5
11
  - `subscribeToRpcRequests`: `open_channel_request` add support for
@@ -3351,7 +3351,7 @@ message Invoice {
3351
3351
  int64 value_msat = 23;
3352
3352
 
3353
3353
  /*
3354
- Whether this invoice has been fulfilled
3354
+ Whether this invoice has been fulfilled.
3355
3355
 
3356
3356
  The field is deprecated. Use the state field instead (compare to SETTLED).
3357
3357
  */
@@ -3359,12 +3359,14 @@ message Invoice {
3359
3359
 
3360
3360
  /*
3361
3361
  When this invoice was created.
3362
+ Measured in seconds since the unix epoch.
3362
3363
  Note: Output only, don't specify for creating an invoice.
3363
3364
  */
3364
3365
  int64 creation_date = 7;
3365
3366
 
3366
3367
  /*
3367
3368
  When this invoice was settled.
3369
+ Measured in seconds since the unix epoch.
3368
3370
  Note: Output only, don't specify for creating an invoice.
3369
3371
  */
3370
3372
  int64 settle_date = 8;
@@ -3631,7 +3633,16 @@ message ListInvoiceRequest {
3631
3633
  specified index offset. This can be used to paginate backwards.
3632
3634
  */
3633
3635
  bool reversed = 6;
3636
+
3637
+ // If set, returns all invoices with a creation date greater than or equal
3638
+ // to it. Measured in seconds since the unix epoch.
3639
+ uint64 creation_date_start = 7;
3640
+
3641
+ // If set, returns all invoices with a creation date less than or equal to
3642
+ // it. Measured in seconds since the unix epoch.
3643
+ uint64 creation_date_end = 8;
3634
3644
  }
3645
+
3635
3646
  message ListInvoiceResponse {
3636
3647
  /*
3637
3648
  A list of invoices from the time slice of the time series specified in the
@@ -3830,6 +3841,14 @@ message ListPaymentsRequest {
3830
3841
  of payments, as all of them have to be iterated through to be counted.
3831
3842
  */
3832
3843
  bool count_total_payments = 5;
3844
+
3845
+ // If set, returns all invoices with a creation date greater than or equal
3846
+ // to it. Measured in seconds since the unix epoch.
3847
+ uint64 creation_date_start = 6;
3848
+
3849
+ // If set, returns all invoices with a creation date less than or equal to
3850
+ // it. Measured in seconds since the unix epoch.
3851
+ uint64 creation_date_end = 7;
3833
3852
  }
3834
3853
 
3835
3854
  message ListPaymentsResponse {
@@ -1,5 +1,3 @@
1
- const {createHash} = require('crypto');
2
-
3
1
  const asyncAuto = require('async/auto');
4
2
  const asyncRetry = require('async/retry');
5
3
  const {returnResult} = require('asyncjs-util');
@@ -9,6 +7,8 @@ const {isLnd} = require('./../../lnd_requests');
9
7
  const {rpcInvoiceAsInvoice} = require('./../../lnd_responses');
10
8
  const {sortBy} = require('./../../arrays');
11
9
 
10
+ const asStart = n => !!n ? Math.floor(new Date(n).getTime() / 1e3) : undefined;
11
+ const asEnd = n => !!n ? Math.ceil(new Date(n).getTime() / 1e3) : undefined;
12
12
  const createdAtSort = array => sortBy({array, attribute: 'created_at'});
13
13
  const defaultLimit = 100;
14
14
  const {isArray} = Array;
@@ -27,7 +27,12 @@ const type = 'default';
27
27
 
28
28
  Invoice `payment` is not supported on LND 0.11.1 and below
29
29
 
30
+ `created_after` is not supported on LND 0.15.5 and below
31
+ `created_before` is not supported on LND 0.15.5 and below
32
+
30
33
  {
34
+ [created_after]: <Creation Date After or Equal to ISO 8601 Date String>
35
+ [created_before]: <Creation Date Before or Equal to ISO 8601 Date String>
31
36
  [is_unconfirmed]: <Omit Canceled and Settled Invoices Bool>
32
37
  [limit]: <Page Result Limit Number>
33
38
  lnd: <Authenticated LND API Object>
@@ -106,16 +111,20 @@ module.exports = (args, cbk) => {
106
111
 
107
112
  // Get the list of invoices
108
113
  listInvoices: ['validate', ({}, cbk) => {
114
+ let after = asStart(args.created_after);
115
+ let before = asEnd(args.created_before);
116
+ let limit = args.limit || defaultLimit;
109
117
  let offset;
110
- let resultsLimit = args.limit || defaultLimit;
111
118
 
112
119
  // When there is a token, parse it out into an offset and a limit
113
120
  if (!!args.token) {
114
121
  try {
115
122
  const pagingToken = parse(args.token);
116
123
 
124
+ after = pagingToken.after;
125
+ before = pagingToken.before;
117
126
  offset = pagingToken.offset;
118
- resultsLimit = pagingToken.limit;
127
+ limit = pagingToken.limit;
119
128
  } catch (err) {
120
129
  return cbk([400, 'ExpectedValidPagingTokenForInvoicesReq', {err}]);
121
130
  }
@@ -123,8 +132,10 @@ module.exports = (args, cbk) => {
123
132
 
124
133
  return asyncRetry({}, cbk => {
125
134
  return args.lnd[type][method]({
135
+ creation_date_start: after,
136
+ creation_date_end: before,
126
137
  index_offset: offset || Number(),
127
- num_max_invoices: resultsLimit,
138
+ num_max_invoices: limit,
128
139
  pending_only: args.is_unconfirmed === true || undefined,
129
140
  reversed: true,
130
141
  },
@@ -151,7 +162,7 @@ module.exports = (args, cbk) => {
151
162
 
152
163
  const offset = Number(res.first_index_offset);
153
164
 
154
- const token = stringify({offset, limit: resultsLimit});
165
+ const token = stringify({after, before, limit, offset});
155
166
 
156
167
  return cbk(null, {
157
168
  invoices: res.invoices,
@@ -2,23 +2,21 @@ const asyncAuto = require('async/auto');
2
2
  const {returnResult} = require('asyncjs-util');
3
3
 
4
4
  const {isLnd} = require('./../../lnd_requests');
5
- const {rpcPaymentAsPayment} = require('./../../lnd_responses');
6
- const {sortBy} = require('./../../arrays');
5
+ const listPayments = require('./list_payments');
7
6
 
8
- const defaultLimit = 250;
9
- const {isArray} = Array;
10
- const isFailed = payment => !!payment && payment.status === 'FAILED';
11
- const lastPageFirstIndexOffset = 1;
12
7
  const method = 'listPayments';
13
- const {parse} = JSON;
14
- const {stringify} = JSON;
15
8
  const type = 'default';
16
9
 
17
10
  /** Get failed payments made through channels.
18
11
 
19
12
  Requires `offchain:read` permission
20
13
 
14
+ `created_after` is not supported on LND 0.15.5 and below
15
+ `created_before` is not supported on LND 0.15.5 and below
16
+
21
17
  {
18
+ [created_after]: <Creation Date After or Equal to ISO 8601 Date String>
19
+ [created_before]: <Creation Date Before or Equal to ISO 8601 Date String>
22
20
  [limit]: <Page Result Limit Number>
23
21
  lnd: <Authenticated LND API Object>
24
22
  [token]: <Opaque Paging Token String>
@@ -96,16 +94,16 @@ const type = 'default';
96
94
  [next]: <Next Opaque Paging Token String>
97
95
  }
98
96
  */
99
- module.exports = ({limit, lnd, token}, cbk) => {
97
+ module.exports = (args, cbk) => {
100
98
  return new Promise((resolve, reject) => {
101
99
  return asyncAuto({
102
100
  // Check arguments
103
101
  validate: cbk => {
104
- if (!!limit && !!token) {
102
+ if (!!args.limit && !!args.token) {
105
103
  return cbk([400, 'ExpectedNoLimitWhenPagingPayFailuresWithToken']);
106
104
  }
107
105
 
108
- if (!isLnd({lnd, method, type})) {
106
+ if (!isLnd({method, type, lnd: args.lnd})) {
109
107
  return cbk([400, 'ExpectedLndForGetFailedPaymentsRequest']);
110
108
  }
111
109
 
@@ -114,79 +112,17 @@ module.exports = ({limit, lnd, token}, cbk) => {
114
112
 
115
113
  // Get all payments
116
114
  listPayments: ['validate', ({}, cbk) => {
117
- let offset;
118
- let resultsLimit = limit || defaultLimit;
119
-
120
- if (!!token) {
121
- try {
122
- const pagingToken = parse(token);
123
-
124
- offset = pagingToken.offset;
125
- resultsLimit = pagingToken.limit;
126
- } catch (err) {
127
- return cbk([400, 'ExpectedValidPagingTokenForGetFailed', {err}]);
128
- }
129
- }
130
-
131
- return lnd[type][method]({
132
- include_incomplete: true,
133
- index_offset: offset || Number(),
134
- max_payments: resultsLimit,
135
- reversed: true,
115
+ return listPayments({
116
+ created_after: args.created_after,
117
+ created_before: args.created_before,
118
+ is_failed: true,
119
+ limit: args.limit,
120
+ lnd: args.lnd,
121
+ token: args.token,
136
122
  },
137
- (err, res) => {
138
- if (!!err) {
139
- return cbk([503, 'UnexpectedGetFailedPaymentsError', {err}]);
140
- }
141
-
142
- if (!res || !isArray(res.payments)) {
143
- return cbk([503, 'ExpectedFailedPaymentsInListPaymentsResponse']);
144
- }
145
-
146
- if (typeof res.last_index_offset !== 'string') {
147
- return cbk([503, 'ExpectedLastIndexOffsetWhenRequestingFailed']);
148
- }
149
-
150
- const lastOffset = Number(res.last_index_offset);
151
- const offset = Number(res.first_index_offset);
152
-
153
- const token = stringify({offset, limit: resultsLimit});
154
-
155
- return cbk(null, {
156
- payments: res.payments.filter(isFailed),
157
- token: offset <= lastPageFirstIndexOffset ? undefined : token,
158
- });
159
- });
160
- }],
161
-
162
- // Check and map payments
163
- foundPayments: ['listPayments', ({listPayments}, cbk) => {
164
- try {
165
- const payments = listPayments.payments.map(rpcPaymentAsPayment);
166
-
167
- return cbk(null, payments);
168
- } catch (err) {
169
- return cbk([503, err.message]);
170
- }
171
- }],
172
-
173
- // Final found failed payments
174
- payments: [
175
- 'foundPayments',
176
- 'listPayments',
177
- ({foundPayments, listPayments}, cbk) =>
178
- {
179
- const payments = sortBy({
180
- array: foundPayments,
181
- attribute: 'created_at',
182
- });
183
-
184
- return cbk(null, {
185
- next: listPayments.token || undefined,
186
- payments: payments.sorted.reverse(),
187
- });
123
+ cbk);
188
124
  }],
189
125
  },
190
- returnResult({reject, resolve, of: 'payments'}, cbk));
126
+ returnResult({reject, resolve, of: 'listPayments'}, cbk));
191
127
  });
192
128
  };
@@ -2,22 +2,21 @@ const asyncAuto = require('async/auto');
2
2
  const {returnResult} = require('asyncjs-util');
3
3
 
4
4
  const {isLnd} = require('./../../lnd_requests');
5
- const {rpcPaymentAsPayment} = require('./../../lnd_responses');
6
- const {sortBy} = require('./../../arrays');
5
+ const listPayments = require('./list_payments');
7
6
 
8
- const defaultLimit = 250;
9
- const {isArray} = Array;
10
- const lastPageFirstIndexOffset = 1;
11
7
  const method = 'listPayments';
12
- const {parse} = JSON;
13
- const {stringify} = JSON;
14
8
  const type = 'default';
15
9
 
16
10
  /** Get payments made through channels.
17
11
 
18
12
  Requires `offchain:read` permission
19
13
 
14
+ `created_after` is not supported on LND 0.15.5 and below
15
+ `created_before` is not supported on LND 0.15.5 and below
16
+
20
17
  {
18
+ [created_after]: <Creation Date After or Equal to ISO 8601 Date String>
19
+ [created_before]: <Creation Date Before or Equal to ISO 8601 Date String>
21
20
  [limit]: <Page Result Limit Number>
22
21
  lnd: <Authenticated LND API Object>
23
22
  [token]: <Opaque Paging Token String>
@@ -101,16 +100,16 @@ const type = 'default';
101
100
  [next]: <Next Opaque Paging Token String>
102
101
  }
103
102
  */
104
- module.exports = ({limit, lnd, token}, cbk) => {
103
+ module.exports = (args, cbk) => {
105
104
  return new Promise((resolve, reject) => {
106
105
  return asyncAuto({
107
106
  // Check arguments
108
107
  validate: cbk => {
109
- if (!!limit && !!token) {
108
+ if (!!args.limit && !!args.token) {
110
109
  return cbk([400, 'UnexpectedLimitWhenPagingPaymentsWithToken']);
111
110
  }
112
111
 
113
- if (!isLnd({lnd, method, type})) {
112
+ if (!isLnd({method, type, lnd: args.lnd})) {
114
113
  return cbk([400, 'ExpectedLndForGetPaymentsRequest']);
115
114
  }
116
115
 
@@ -119,79 +118,16 @@ module.exports = ({limit, lnd, token}, cbk) => {
119
118
 
120
119
  // Get all payments
121
120
  listPayments: ['validate', ({}, cbk) => {
122
- let offset;
123
- let resultsLimit = limit || defaultLimit;
124
-
125
- if (!!token) {
126
- try {
127
- const pagingToken = parse(token);
128
-
129
- offset = pagingToken.offset;
130
- resultsLimit = pagingToken.limit;
131
- } catch (err) {
132
- return cbk([400, 'ExpectedValidPagingTokenForPaymentReq', {err}]);
133
- }
134
- }
135
-
136
- return lnd[type][method]({
137
- include_incomplete: false,
138
- index_offset: offset || Number(),
139
- max_payments: resultsLimit,
140
- reversed: true,
121
+ return listPayments({
122
+ created_after: args.created_after,
123
+ created_before: args.created_before,
124
+ limit: args.limit,
125
+ lnd: args.lnd,
126
+ token: args.token,
141
127
  },
142
- (err, res) => {
143
- if (!!err) {
144
- return cbk([503, 'UnexpectedGetPaymentsError', {err}]);
145
- }
146
-
147
- if (!res || !isArray(res.payments)) {
148
- return cbk([503, 'ExpectedPaymentsInListPaymentsResponse']);
149
- }
150
-
151
- if (typeof res.last_index_offset !== 'string') {
152
- return cbk([503, 'ExpectedLastIndexOffsetWhenRequestingPayments']);
153
- }
154
-
155
- const lastOffset = Number(res.last_index_offset);
156
- const offset = Number(res.first_index_offset);
157
-
158
- const token = stringify({offset, limit: resultsLimit});
159
-
160
- return cbk(null, {
161
- payments: res.payments,
162
- token: offset <= lastPageFirstIndexOffset ? undefined : token,
163
- });
164
- });
165
- }],
166
-
167
- // Check and map payments
168
- foundPayments: ['listPayments', ({listPayments}, cbk) => {
169
- try {
170
- const payments = listPayments.payments.map(rpcPaymentAsPayment);
171
-
172
- return cbk(null, payments);
173
- } catch (err) {
174
- return cbk([503, err.message]);
175
- }
176
- }],
177
-
178
- // Final found payments
179
- payments: [
180
- 'foundPayments',
181
- 'listPayments',
182
- ({foundPayments, listPayments}, cbk) =>
183
- {
184
- const payments = sortBy({
185
- array: foundPayments,
186
- attribute: 'created_at',
187
- });
188
-
189
- return cbk(null, {
190
- next: listPayments.token || undefined,
191
- payments: payments.sorted.reverse(),
192
- });
128
+ cbk);
193
129
  }],
194
130
  },
195
- returnResult({reject, resolve, of: 'payments'}, cbk));
131
+ returnResult({reject, resolve, of: 'listPayments'}, cbk));
196
132
  });
197
133
  };
@@ -2,23 +2,21 @@ const asyncAuto = require('async/auto');
2
2
  const {returnResult} = require('asyncjs-util');
3
3
 
4
4
  const {isLnd} = require('./../../lnd_requests');
5
- const {rpcPaymentAsPayment} = require('./../../lnd_responses');
6
- const {sortBy} = require('./../../arrays');
5
+ const listPayments = require('./list_payments');
7
6
 
8
- const defaultLimit = 250;
9
- const {isArray} = Array;
10
- const isPending = payment => !!payment && payment.status === 'IN_FLIGHT';
11
- const lastPageFirstIndexOffset = 1;
12
7
  const method = 'listPayments';
13
- const {parse} = JSON;
14
- const {stringify} = JSON;
15
8
  const type = 'default';
16
9
 
17
10
  /** Get pending payments made through channels.
18
11
 
19
12
  Requires `offchain:read` permission
20
13
 
14
+ `created_after` is not supported on LND 0.15.5 and below
15
+ `created_before` is not supported on LND 0.15.5 and below
16
+
21
17
  {
18
+ [created_after]: <Creation Date After or Equal to ISO 8601 Date String>
19
+ [created_before]: <Creation Date Before or Equal to ISO 8601 Date String>
22
20
  [limit]: <Page Result Limit Number>
23
21
  lnd: <Authenticated LND API Object>
24
22
  [token]: <Opaque Paging Token String>
@@ -96,16 +94,16 @@ const type = 'default';
96
94
  [next]: <Next Opaque Paging Token String>
97
95
  }
98
96
  */
99
- module.exports = ({limit, lnd, token}, cbk) => {
97
+ module.exports = (args, cbk) => {
100
98
  return new Promise((resolve, reject) => {
101
99
  return asyncAuto({
102
100
  // Check arguments
103
101
  validate: cbk => {
104
- if (!!limit && !!token) {
102
+ if (!!args.limit && !!args.token) {
105
103
  return cbk([400, 'ExpectedNoLimitPagingPendingPaymentsWithToken']);
106
104
  }
107
105
 
108
- if (!isLnd({lnd, method, type})) {
106
+ if (!isLnd({method, type, lnd: args.lnd})) {
109
107
  return cbk([400, 'ExpectedLndForGetPendingPaymentsRequest']);
110
108
  }
111
109
 
@@ -114,79 +112,17 @@ module.exports = ({limit, lnd, token}, cbk) => {
114
112
 
115
113
  // Get all payments
116
114
  listPayments: ['validate', ({}, cbk) => {
117
- let offset;
118
- let resultsLimit = limit || defaultLimit;
119
-
120
- if (!!token) {
121
- try {
122
- const pagingToken = parse(token);
123
-
124
- offset = pagingToken.offset;
125
- resultsLimit = pagingToken.limit;
126
- } catch (err) {
127
- return cbk([400, 'ExpectedValidPagingTokenForGetPending', {err}]);
128
- }
129
- }
130
-
131
- return lnd[type][method]({
132
- include_incomplete: true,
133
- index_offset: offset || Number(),
134
- max_payments: resultsLimit,
135
- reversed: true,
115
+ return listPayments({
116
+ created_after: args.created_after,
117
+ created_before: args.created_before,
118
+ is_pending: true,
119
+ limit: args.limit,
120
+ lnd: args.lnd,
121
+ token: args.token,
136
122
  },
137
- (err, res) => {
138
- if (!!err) {
139
- return cbk([503, 'UnexpectedGetPendingPaymentsError', {err}]);
140
- }
141
-
142
- if (!res || !isArray(res.payments)) {
143
- return cbk([503, 'ExpectedPendingPaymentsInListPaymentsResponse']);
144
- }
145
-
146
- if (typeof res.last_index_offset !== 'string') {
147
- return cbk([503, 'ExpectedLastIndexOffsetWhenRequestingPending']);
148
- }
149
-
150
- const lastOffset = Number(res.last_index_offset);
151
- const offset = Number(res.first_index_offset);
152
-
153
- const token = stringify({offset, limit: resultsLimit});
154
-
155
- return cbk(null, {
156
- payments: res.payments.filter(isPending),
157
- token: offset <= lastPageFirstIndexOffset ? undefined : token,
158
- });
159
- });
160
- }],
161
-
162
- // Check and map payments
163
- foundPayments: ['listPayments', ({listPayments}, cbk) => {
164
- try {
165
- const payments = listPayments.payments.map(rpcPaymentAsPayment);
166
-
167
- return cbk(null, payments);
168
- } catch (err) {
169
- return cbk([503, err.message]);
170
- }
171
- }],
172
-
173
- // Final found pending payments
174
- payments: [
175
- 'foundPayments',
176
- 'listPayments',
177
- ({foundPayments, listPayments}, cbk) =>
178
- {
179
- const payments = sortBy({
180
- array: foundPayments,
181
- attribute: 'created_at',
182
- });
183
-
184
- return cbk(null, {
185
- next: listPayments.token || undefined,
186
- payments: payments.sorted.reverse(),
187
- });
123
+ cbk);
188
124
  }],
189
125
  },
190
- returnResult({reject, resolve, of: 'payments'}, cbk));
126
+ returnResult({reject, resolve, of: 'listPayments'}, cbk));
191
127
  });
192
128
  };
@@ -0,0 +1,218 @@
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 asStart = n => !!n ? Math.floor(new Date(n).getTime() / 1e3) : undefined;
9
+ const asEnd = n => !!n ? Math.ceil(new Date(n).getTime() / 1e3) : undefined;
10
+ const defaultLimit = 250;
11
+ const {isArray} = Array;
12
+ const isFailed = payment => !!payment && payment.status === 'FAILED';
13
+ const isPending = payment => !!payment && payment.status === 'IN_FLIGHT';
14
+ const lastPageFirstIndexOffset = 1;
15
+ const method = 'listPayments';
16
+ const {parse} = JSON;
17
+ const {stringify} = JSON;
18
+ const type = 'default';
19
+
20
+ /** Fetch payments
21
+
22
+ {
23
+ [created_after]: <Creation Date After or Equal to ISO 8601 Date String>
24
+ [created_before]: <Creation Date Before or Equal to ISO 8601 Date String>
25
+ [is_failed]: <Fetch Failed Payments Bool>
26
+ [is_pending]: <Fetch Pending Payments Bool>
27
+ [limit]: <Page Result Limit Number>
28
+ lnd: <Authenticated LND API Object>
29
+ [token]: <Opaque Paging Token String>
30
+ }
31
+
32
+ @returns via cbk or Promise
33
+ {
34
+ payments: [{
35
+ attempts: [{
36
+ [failure]: {
37
+ code: <Error Type Code Number>
38
+ [details]: {
39
+ [channel]: <Standard Format Channel Id String>
40
+ [height]: <Error Associated Block Height Number>
41
+ [index]: <Failed Hop Index Number>
42
+ [mtokens]: <Error Millitokens String>
43
+ [policy]: {
44
+ base_fee_mtokens: <Base Fee Millitokens String>
45
+ cltv_delta: <Locktime Delta Number>
46
+ fee_rate: <Fees Charged in Millitokens Per Million Number>
47
+ [is_disabled]: <Channel is Disabled Bool>
48
+ max_htlc_mtokens: <Maximum HLTC Millitokens Value String>
49
+ min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
50
+ updated_at: <Updated At ISO 8601 Date String>
51
+ }
52
+ [timeout_height]: <Error CLTV Timeout Height Number>
53
+ [update]: {
54
+ chain: <Chain Id Hex String>
55
+ channel_flags: <Channel Flags Number>
56
+ extra_opaque_data: <Extra Opaque Data Hex String>
57
+ message_flags: <Message Flags Number>
58
+ signature: <Channel Update Signature Hex String>
59
+ }
60
+ }
61
+ message: <Error Message String>
62
+ }
63
+ [index]: <Payment Add Index Number>
64
+ [confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String>
65
+ created_at: <Attempt Was Started At ISO 8601 Date String>
66
+ [failed_at]: <Payment Attempt Failed At ISO 8601 Date String>
67
+ is_confirmed: <Payment Attempt Succeeded Bool>
68
+ is_failed: <Payment Attempt Failed Bool>
69
+ is_pending: <Payment Attempt is Waiting For Resolution Bool>
70
+ route: {
71
+ fee: <Route Fee Tokens Number>
72
+ fee_mtokens: <Route Fee Millitokens String>
73
+ hops: [{
74
+ channel: <Standard Format Channel Id String>
75
+ channel_capacity: <Channel Capacity Tokens Number>
76
+ fee: <Fee Number>
77
+ fee_mtokens: <Fee Millitokens String>
78
+ forward: <Forward Tokens Number>
79
+ forward_mtokens: <Forward Millitokens String>
80
+ [public_key]: <Forward Edge Public Key Hex String>
81
+ [timeout]: <Timeout Block Height Number>
82
+ }]
83
+ mtokens: <Total Fee-Inclusive Millitokens String>
84
+ [payment]: <Payment Identifier Hex String>
85
+ timeout: <Timeout Block Height Number>
86
+ tokens: <Total Fee-Inclusive Tokens Number>
87
+ [total_mtokens]: <Total Millitokens String>
88
+ }
89
+ }]
90
+ confirmed_at: <Payment Confirmed At ISO 8601 Date String>
91
+ created_at: <Payment at ISO-8601 Date String>
92
+ destination: <Destination Node Public Key Hex String>
93
+ fee: <Paid Routing Fee Rounded Down Tokens Number>
94
+ fee_mtokens: <Paid Routing Fee in Millitokens String>
95
+ hops: [<First Route Hop Public Key Hex String>]
96
+ id: <Payment Preimage Hash String>
97
+ [index]: <Payment Add Index Number>
98
+ is_confirmed: <Payment is Confirmed Bool>
99
+ is_outgoing: <Transaction Is Outgoing Bool>
100
+ mtokens: <Millitokens Sent to Destination String>
101
+ [request]: <BOLT 11 Payment Request String>
102
+ safe_fee: <Payment Forwarding Fee Rounded Up Tokens Number>
103
+ safe_tokens: <Payment Tokens Rounded Up Number>
104
+ secret: <Payment Preimage Hex String>
105
+ tokens: <Rounded Down Tokens Sent to Destination Number>
106
+ }]
107
+ [next]: <Next Opaque Paging Token String>
108
+ }
109
+ */
110
+ module.exports = (args, cbk) => {
111
+ return new Promise((resolve, reject) => {
112
+ return asyncAuto({
113
+ // Check arguments
114
+ validate: cbk => {
115
+ if (!!args.is_failed && !!args.is_pending) {
116
+ return cbk([400, 'EitherFailedOrPendingPaymentsIsSupportedNotBoth']);
117
+ }
118
+
119
+ return cbk();
120
+ },
121
+
122
+ // Get all payments
123
+ listPayments: ['validate', ({}, cbk) => {
124
+ let after = asStart(args.created_after);
125
+ let before = asEnd(args.created_before);
126
+ let limit = args.limit || defaultLimit;
127
+ let offset;
128
+
129
+ if (!!args.token) {
130
+ try {
131
+ const pagingToken = parse(args.token);
132
+
133
+ after = pagingToken.after;
134
+ before = pagingToken.before;
135
+ limit = pagingToken.limit;
136
+ offset = pagingToken.offset;
137
+ } catch (err) {
138
+ return cbk([400, 'ExpectedValidPagingTokenForPaymentReq', {err}]);
139
+ }
140
+ }
141
+
142
+ return args.lnd[type][method]({
143
+ creation_date_start: after,
144
+ creation_date_end: before,
145
+ include_incomplete: !!args.is_failed || !!args.is_pending,
146
+ index_offset: offset || Number(),
147
+ max_payments: limit,
148
+ reversed: true,
149
+ },
150
+ (err, res) => {
151
+ if (!!err) {
152
+ return cbk([503, 'UnexpectedGetPaymentsError', {err}]);
153
+ }
154
+
155
+ if (!res || !isArray(res.payments)) {
156
+ return cbk([503, 'ExpectedPaymentsInListPaymentsResponse']);
157
+ }
158
+
159
+ if (typeof res.last_index_offset !== 'string') {
160
+ return cbk([503, 'ExpectedLastIndexOffsetWhenRequestingPayments']);
161
+ }
162
+
163
+ const offset = Number(res.first_index_offset);
164
+
165
+ const token = stringify({before, after, limit, offset});
166
+
167
+ return cbk(null, {
168
+ payments: res.payments,
169
+ token: offset <= lastPageFirstIndexOffset ? undefined : token,
170
+ });
171
+ });
172
+ }],
173
+
174
+ // Check and map payments
175
+ foundPayments: ['listPayments', ({listPayments}, cbk) => {
176
+ try {
177
+ const payments = listPayments.payments
178
+ .filter(payment => {
179
+ // Exit early when looking for failed payments only
180
+ if (!!args.is_failed) {
181
+ return isFailed(payment);
182
+ }
183
+
184
+ // Exit early when looking for pending payments only
185
+ if (!!args.is_pending) {
186
+ return isPending(payment);
187
+ }
188
+
189
+ return true;
190
+ })
191
+ .map(rpcPaymentAsPayment);
192
+
193
+ return cbk(null, payments);
194
+ } catch (err) {
195
+ return cbk([503, err.message]);
196
+ }
197
+ }],
198
+
199
+ // Final found payments
200
+ payments: [
201
+ 'foundPayments',
202
+ 'listPayments',
203
+ ({foundPayments, listPayments}, cbk) =>
204
+ {
205
+ const payments = sortBy({
206
+ array: foundPayments,
207
+ attribute: 'created_at',
208
+ });
209
+
210
+ return cbk(null, {
211
+ next: listPayments.token || undefined,
212
+ payments: payments.sorted.reverse(),
213
+ });
214
+ }],
215
+ },
216
+ returnResult({reject, resolve, of: 'payments'}, cbk));
217
+ });
218
+ };
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "@grpc/grpc-js": "1.8.0",
11
11
  "@grpc/proto-loader": "0.7.4",
12
12
  "@types/express": "4.17.14",
13
- "@types/node": "18.11.12",
13
+ "@types/node": "18.11.13",
14
14
  "@types/request": "2.48.8",
15
15
  "@types/ws": "8.5.3",
16
16
  "async": "3.2.4",
@@ -59,5 +59,5 @@
59
59
  "directory": "test/typescript"
60
60
  },
61
61
  "types": "index.d.ts",
62
- "version": "6.4.1"
62
+ "version": "6.5.0"
63
63
  }
@@ -114,7 +114,7 @@ const tests = [
114
114
  secret: '0000000000000000000000000000000000000000000000000000000000000000',
115
115
  tokens: 1,
116
116
  }],
117
- next: '{"offset":2,"limit":100}',
117
+ next: '{"limit":100,"offset":2}',
118
118
  },
119
119
  },
120
120
  {
@@ -132,6 +132,23 @@ const tests = [
132
132
  description: 'Empty invoices are returned',
133
133
  expected: {invoices: [], next: undefined},
134
134
  },
135
+ {
136
+ args: {
137
+ created_after: new Date().toISOString(),
138
+ created_before: new Date().toISOString(),
139
+ lnd: {
140
+ default: {
141
+ listInvoices: ({}, cbk) => cbk(null, {
142
+ first_index_offset: '2',
143
+ invoices: [],
144
+ last_index_offset: '2',
145
+ }),
146
+ },
147
+ },
148
+ },
149
+ description: 'A date range is supported',
150
+ expected: {invoices: [], next: undefined},
151
+ },
135
152
  ];
136
153
 
137
154
  tests.forEach(({args, description, error, expected}) => {
@@ -74,31 +74,31 @@ const tests = [
74
74
  {
75
75
  args: makeArgs({token: 'token'}),
76
76
  description: 'A valid token is required',
77
- error: [400, 'ExpectedValidPagingTokenForGetFailed'],
77
+ error: [400, 'ExpectedValidPagingTokenForPaymentReq'],
78
78
  },
79
79
  {
80
80
  args: makeArgs({lnd: {default: {listPayments: ({}, cbk) => cbk('err')}}}),
81
81
  description: 'Errors from LND are passed back',
82
- error: [503, 'UnexpectedGetFailedPaymentsError', {err: 'err'}],
82
+ error: [503, 'UnexpectedGetPaymentsError', {err: 'err'}],
83
83
  },
84
84
  {
85
85
  args: makeArgs({lnd: {default: {listPayments: ({}, cbk) => cbk()}}}),
86
86
  description: 'A response is expected from LND',
87
- error: [503, 'ExpectedFailedPaymentsInListPaymentsResponse'],
87
+ error: [503, 'ExpectedPaymentsInListPaymentsResponse'],
88
88
  },
89
89
  {
90
90
  args: makeArgs({
91
91
  lnd: {default: {listPayments: ({}, cbk) => cbk(null, {})}},
92
92
  }),
93
93
  description: 'A response with payments is expected from LND',
94
- error: [503, 'ExpectedFailedPaymentsInListPaymentsResponse'],
94
+ error: [503, 'ExpectedPaymentsInListPaymentsResponse'],
95
95
  },
96
96
  {
97
97
  args: makeArgs({
98
98
  lnd: {default: {listPayments: ({}, cbk) => cbk(null, {payments: []})}},
99
99
  }),
100
100
  description: 'A response with payments and last index is expected',
101
- error: [503, 'ExpectedLastIndexOffsetWhenRequestingFailed'],
101
+ error: [503, 'ExpectedLastIndexOffsetWhenRequestingPayments'],
102
102
  },
103
103
  {
104
104
  args: makeArgs({
@@ -189,6 +189,15 @@ const tests = [
189
189
  description: 'A payment is returned when a token is specified',
190
190
  expected: {payment: makeExpectedPayment({})},
191
191
  },
192
+ {
193
+ args: makeArgs({
194
+ created_after: new Date().toISOString(),
195
+ created_before: new Date().toISOString(),
196
+ lnd: makeLnd({first_index_offset: '2'}),
197
+ }),
198
+ description: 'Date range can be passed',
199
+ expected: {payment: makeExpectedPayment({})},
200
+ },
192
201
  ];
193
202
 
194
203
  tests.forEach(({args, description, error, expected}) => {
@@ -74,31 +74,31 @@ const tests = [
74
74
  {
75
75
  args: makeArgs({token: 'token'}),
76
76
  description: 'A valid token is required',
77
- error: [400, 'ExpectedValidPagingTokenForGetPending'],
77
+ error: [400, 'ExpectedValidPagingTokenForPaymentReq'],
78
78
  },
79
79
  {
80
80
  args: makeArgs({lnd: {default: {listPayments: ({}, cbk) => cbk('err')}}}),
81
81
  description: 'Errors from LND are passed back',
82
- error: [503, 'UnexpectedGetPendingPaymentsError', {err: 'err'}],
82
+ error: [503, 'UnexpectedGetPaymentsError', {err: 'err'}],
83
83
  },
84
84
  {
85
85
  args: makeArgs({lnd: {default: {listPayments: ({}, cbk) => cbk()}}}),
86
86
  description: 'A response is expected from LND',
87
- error: [503, 'ExpectedPendingPaymentsInListPaymentsResponse'],
87
+ error: [503, 'ExpectedPaymentsInListPaymentsResponse'],
88
88
  },
89
89
  {
90
90
  args: makeArgs({
91
91
  lnd: {default: {listPayments: ({}, cbk) => cbk(null, {})}},
92
92
  }),
93
93
  description: 'A response with payments is expected from LND',
94
- error: [503, 'ExpectedPendingPaymentsInListPaymentsResponse'],
94
+ error: [503, 'ExpectedPaymentsInListPaymentsResponse'],
95
95
  },
96
96
  {
97
97
  args: makeArgs({
98
98
  lnd: {default: {listPayments: ({}, cbk) => cbk(null, {payments: []})}},
99
99
  }),
100
100
  description: 'A response with payments and last index is expected',
101
- error: [503, 'ExpectedLastIndexOffsetWhenRequestingPending'],
101
+ error: [503, 'ExpectedLastIndexOffsetWhenRequestingPayments'],
102
102
  },
103
103
  {
104
104
  args: makeArgs({
@@ -0,0 +1,45 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+
3
+ const listPayments = require('./../../../lnd_methods/offchain/list_payments');
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
+ last_index_offset: args.last_index_offset || '1',
12
+ }),
13
+ },
14
+ };
15
+ };
16
+
17
+ const makeArgs = overrides => {
18
+ const args = {lnd: makeLnd({})};
19
+
20
+ Object.keys(overrides).forEach(k => args[k] = overrides[k]);
21
+
22
+ return args;
23
+ };
24
+
25
+ const tests = [
26
+ {
27
+ args: makeArgs({is_failed: true, is_pending: true}),
28
+ description: 'Both failed and pending cannot be set',
29
+ error: [400, 'EitherFailedOrPendingPaymentsIsSupportedNotBoth'],
30
+ },
31
+ ];
32
+
33
+ tests.forEach(({args, description, error, expected}) => {
34
+ return test(description, async ({end, rejects, strictSame}) => {
35
+ if (!!error) {
36
+ await rejects(() => listPayments(args), error, 'Got expected error');
37
+ } else {
38
+ const res = await listPayments(args);
39
+
40
+ strictSame(res, expected, 'Got expected result');
41
+ }
42
+
43
+ return end();
44
+ });
45
+ });