UNPKG

balanceofsatoshis

Version:
136 lines (110 loc) 3.8 kB
const asyncAuto = require('async/auto'); const {createInvoice} = require('ln-service'); const {getChannel} = require('ln-service'); const {getChannels} = require('ln-service'); const {getWalletInfo} = require('ln-service'); const {parsePaymentRequest} = require('ln-service'); const {payViaRoutes} = require('ln-service'); const {returnResult} = require('asyncjs-util'); const {channelForGift} = require('./../routing'); const giftCallbackError = require('./gift_callback_error'); const {giftRoute} = require('./../routing'); /** Send a gift of some tokens to a peer. { lnd: <Authenticated LND gRPC API Object> to: <To Node Public Key Hex string> tokens: <Tokens to Gift Number> } @returns via cbk or Promise { gave_tokens: <Gave Tokens Number> } */ module.exports = ({lnd, to, tokens}, cbk) => { return new Promise((resolve, reject) => { return asyncAuto({ // Check arguments validate: cbk => { if (!lnd) { return cbk([400, 'ExpectedLndToSendGiftWith']); } if (!to) { return cbk([400, 'ExpectedPeerToSendGiftTo']); } if (!tokens) { return cbk([400, 'ExpectedTokensToGiftToPeer']); } return cbk(); }, // Get channels getChannels: ['validate', ({}, cbk) => getChannels({lnd}, cbk)], // Peer channel peerChannel: ['getChannels', ({getChannels}, cbk) => { try { const {channels} = getChannels; const {id} = channelForGift({channels, to, tokens}); return cbk(null, id); } catch (err) { return cbk(giftCallbackError({err})); } }], // Get channel policy info getChannel: ['peerChannel', ({peerChannel}, cbk) => { return getChannel({lnd, id: peerChannel}, cbk); }], // Create invoice createInvoice: ['getChannel', ({l}, cbk) => createInvoice({lnd}, cbk)], // Get wallet getWallet: ['getChannel', ({}, cbk) => getWalletInfo({lnd}, cbk)], // Route route: [ 'createInvoice', 'getChannel', 'getWallet', ({createInvoice, getChannel, getWallet}, cbk) => { const {request} = createInvoice; try { const {route} = giftRoute({ tokens, channel: getChannel, delta: parsePaymentRequest({request}).cltv_delta, destination: getWallet.public_key, height: getWallet.current_block_height, payment: createInvoice.payment, }); return cbk(null, route); } catch (err) { const {message} = err; switch (message) { case 'GiftAmountTooLowToSend': case 'OwnPolicyTooLowToCompleteForward': case 'PeerPolicyTooLowToCompleteForward': return cbk([400, 'AmountTooLowToCompleteGiftSend']); default: return cbk([500, 'FailedToConstructGiftRoute', {err}]); } } }], // Send the gift pay: ['createInvoice', 'route', ({createInvoice, route}, cbk) => { const {id} = createInvoice; return payViaRoutes({id, lnd, routes: [route]}, (err, res) => { if (!!err) { const [errCode, errMessage] = err; switch (errMessage) { case 'RejectedUnacceptableFee': return cbk([400, 'GiftTokensAmountTooLowToSend']); default: return cbk([503, 'UnexpectedErrorSendingGiftTokens', {err}]); } } return cbk(null, {gave_tokens: res.fee}); }); }], // Done paying paid: ['pay', ({pay}, cbk) => cbk(null, {gave_tokens: pay.gave_tokens})], }, returnResult({reject, resolve, of: 'paid'}, cbk)); }); };