UNPKG

lightning

Version:
219 lines (197 loc) 7.82 kB
const asyncAuto = require('async/auto'); const {returnResult} = require('asyncjs-util'); const {isLnd} = require('./../../lnd_requests'); const {rpcPaymentAsPayment} = require('./../../lnd_responses'); const {sortBy} = require('./../../arrays'); const asStart = n => !!n ? Math.floor(new Date(n).getTime() / 1e3) : undefined; const asEnd = n => !!n ? Math.ceil(new Date(n).getTime() / 1e3) : undefined; const defaultLimit = 250; const {isArray} = Array; const isFailed = payment => !!payment && payment.status === 'FAILED'; const isPending = payment => !!payment && payment.status === 'IN_FLIGHT'; const lastPageFirstIndexOffset = 1; const method = 'listPayments'; const {parse} = JSON; const {stringify} = JSON; const type = 'default'; /** Fetch payments { [created_after]: <Creation Date After or Equal to ISO 8601 Date String> [created_before]: <Creation Date Before or Equal to ISO 8601 Date String> [is_failed]: <Fetch Failed Payments Bool> [is_pending]: <Fetch Pending Payments Bool> [limit]: <Page Result Limit Number> lnd: <Authenticated LND API Object> [token]: <Opaque Paging Token String> } @returns via cbk or Promise { payments: [{ attempts: [{ [failure]: { code: <Error Type Code Number> [details]: { [channel]: <Standard Format Channel Id String> [height]: <Error Associated Block Height Number> [index]: <Failed Hop Index Number> [mtokens]: <Error Millitokens String> [policy]: { base_fee_mtokens: <Base Fee Millitokens String> cltv_delta: <Locktime Delta Number> fee_rate: <Fees Charged in Millitokens Per Million Number> [is_disabled]: <Channel is Disabled Bool> max_htlc_mtokens: <Maximum HLTC Millitokens Value String> min_htlc_mtokens: <Minimum HTLC Millitokens Value String> updated_at: <Updated At ISO 8601 Date String> } [timeout_height]: <Error CLTV Timeout Height Number> [update]: { chain: <Chain Id Hex String> channel_flags: <Channel Flags Number> extra_opaque_data: <Extra Opaque Data Hex String> message_flags: <Message Flags Number> signature: <Channel Update Signature Hex String> } } message: <Error Message String> } [index]: <Payment Add Index Number> [confirmed_at]: <Payment Attempt Succeeded At ISO 8601 Date String> created_at: <Attempt Was Started At ISO 8601 Date String> [failed_at]: <Payment Attempt Failed At ISO 8601 Date String> is_confirmed: <Payment Attempt Succeeded Bool> is_failed: <Payment Attempt Failed Bool> is_pending: <Payment Attempt is Waiting For Resolution Bool> route: { fee: <Route Fee Tokens Number> fee_mtokens: <Route Fee Millitokens String> hops: [{ channel: <Standard Format Channel Id String> channel_capacity: <Channel Capacity Tokens Number> fee: <Fee Number> fee_mtokens: <Fee Millitokens String> forward: <Forward Tokens Number> forward_mtokens: <Forward Millitokens String> [public_key]: <Forward Edge Public Key Hex String> [timeout]: <Timeout Block Height Number> }] mtokens: <Total Fee-Inclusive Millitokens String> [payment]: <Payment Identifier Hex String> timeout: <Timeout Block Height Number> tokens: <Total Fee-Inclusive Tokens Number> [total_mtokens]: <Total Millitokens String> } }] confirmed_at: <Payment Confirmed At ISO 8601 Date String> created_at: <Payment at ISO-8601 Date String> destination: <Destination Node Public Key Hex String> fee: <Paid Routing Fee Rounded Down Tokens Number> fee_mtokens: <Paid Routing Fee in Millitokens String> hops: [<First Route Hop Public Key Hex String>] id: <Payment Preimage Hash String> [index]: <Payment Add Index Number> is_confirmed: <Payment is Confirmed Bool> is_outgoing: <Transaction Is Outgoing Bool> mtokens: <Millitokens Sent to Destination String> [request]: <BOLT 11 Payment Request String> safe_fee: <Payment Forwarding Fee Rounded Up Tokens Number> safe_tokens: <Payment Tokens Rounded Up Number> secret: <Payment Preimage Hex String> tokens: <Rounded Down Tokens Sent to Destination Number> }] [next]: <Next Opaque Paging Token String> } */ module.exports = (args, cbk) => { return new Promise((resolve, reject) => { return asyncAuto({ // Check arguments validate: cbk => { if (!!args.is_failed && !!args.is_pending) { return cbk([400, 'EitherFailedOrPendingPaymentsIsSupportedNotBoth']); } return cbk(); }, // Get all payments listPayments: ['validate', ({}, cbk) => { let after = asStart(args.created_after); let before = asEnd(args.created_before); let limit = args.limit || defaultLimit; let offset; if (!!args.token) { try { const pagingToken = parse(args.token); after = pagingToken.after; before = pagingToken.before; limit = pagingToken.limit; offset = pagingToken.offset; } catch (err) { return cbk([400, 'ExpectedValidPagingTokenForPaymentReq', {err}]); } } return args.lnd[type][method]({ creation_date_start: after, creation_date_end: before, include_incomplete: !!args.is_failed || !!args.is_pending, index_offset: offset || Number(), max_payments: limit, reversed: true, }, (err, res) => { if (!!err) { return cbk([503, 'UnexpectedGetPaymentsError', {err}]); } if (!res || !isArray(res.payments)) { return cbk([503, 'ExpectedPaymentsInListPaymentsResponse']); } if (typeof res.last_index_offset !== 'string') { return cbk([503, 'ExpectedLastIndexOffsetWhenRequestingPayments']); } const offset = Number(res.first_index_offset); const token = stringify({before, after, limit, offset}); return cbk(null, { payments: res.payments, token: offset <= lastPageFirstIndexOffset ? undefined : token, }); }); }], // Check and map payments foundPayments: ['listPayments', ({listPayments}, cbk) => { try { const payments = listPayments.payments .filter(payment => { // Exit early when looking for failed payments only if (!!args.is_failed) { return isFailed(payment); } // Exit early when looking for pending payments only if (!!args.is_pending) { return isPending(payment); } return true; }) .map(rpcPaymentAsPayment); return cbk(null, payments); } catch (err) { return cbk([503, err.message]); } }], // Final found payments payments: [ 'foundPayments', 'listPayments', ({foundPayments, listPayments}, cbk) => { const payments = sortBy({ array: foundPayments, attribute: 'created_at', }); return cbk(null, { next: listPayments.token || undefined, payments: payments.sorted.reverse(), }); }], }, returnResult({reject, resolve, of: 'payments'}, cbk)); }); };