Skip to content

Commit

Permalink
tests passing
Browse files Browse the repository at this point in the history
  • Loading branch information
bnonni committed Jan 4, 2025
1 parent 8bc019f commit ddd75a0
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 76 deletions.
2 changes: 2 additions & 0 deletions lnd_methods/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const {diffieHellmanComputeSecret} = require('./signer');
const {disableChannel} = require('./offchain');
const {disconnectWatchtower} = require('./offchain');
const {enableChannel} = require('./offchain');
const {estimateRouteFee} = require('./offchain');
const {endGroupSigningSession} = require('./signer');
const {fundPendingChannels} = require('./onchain');
const {fundPsbt} = require('./onchain');
Expand Down Expand Up @@ -186,6 +187,7 @@ module.exports = {
disableChannel,
disconnectWatchtower,
enableChannel,
estimateRouteFee,
endGroupSigningSession,
fundPendingChannels,
fundPsbt,
Expand Down
42 changes: 24 additions & 18 deletions lnd_methods/offchain/estimate_route_fee.d.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
import {AuthenticatedLnd} from '../../lnd_grpc';
import {AuthenticatedLightningMethod} from '../../typescript';
import {
AuthenticatedLightningArgs,
AuthenticatedLightningMethod
} from '../../typescript';

export type RouteFeeRequest = {
export type RouteFeeRequest = AuthenticatedLightningArgs<{
lnd: AuthenticatedLnd;
payment_request: string;
/** BOLT 11 Encoded Payment Request */
request: string;
/** Optional Timeout in Milliseconds */
timeout: number;
};
}>;

export type RouteFeeResponse = {
routing_fee_msat: number;
time_lock_delay: number;
failure_reason: PaymentFailureReason;
/** Millitokens (Routing Fee Msat) */
mtoken: number;
/** Timeout (Time Lock Delay) */
timeout: number;
};

export enum PaymentFailureReason {
FAILURE_REASON_NONE = 0,
FAILURE_REASON_TIMEOUT = 1,
FAILURE_REASON_NO_ROUTE = 2,
FAILURE_REASON_ERROR = 3,
FAILURE_REASON_INCORRECT_PAYMENT_DETAILS = 4,
FAILURE_REASON_INSUFFICIENT_BALANCE = 5,
FAILURE_REASON_CANCELED = 6,
}

export const estimateRouteFee: AuthenticatedLightningMethod<RouteFeeRequest, RouteFeeResponse>;
/**
* Estimate routing fees based on an invoice.
*
* Requires `offchain:read` permission
*
* This method is not supported before LND 0.18.4
*/
export const estimateRouteFee: AuthenticatedLightningMethod<
RouteFeeRequest,
RouteFeeResponse
>;
21 changes: 10 additions & 11 deletions lnd_methods/offchain/estimate_route_fee.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const asyncAuto = require('async/auto');
const {returnResult} = require('asyncjs-util');

/**
* Estimate routing fees based on an invoice.
*
Expand Down Expand Up @@ -35,11 +36,11 @@ module.exports = ({lnd, request, timeout}, cbk) => {
}

if (timeout > 86400000) {
return cbk([400, 'ExpectedDeadlinLessThanOneDayForRouteFeeEstimate']);
return cbk([400, 'ExpectedTimeoutLessThanOneDayForRouteFeeEstimate']);
}

if (timeout < 1) {
return cbk([400, 'ExpectedDeadlinGreaterThanZeroForRouteFeeEstimate']);
return cbk([400, 'ExpectedTimeoutGreaterThanZeroForRouteFeeEstimate']);
}

timeout = !timeout ? 60 : timeout / 1000;
Expand All @@ -51,34 +52,32 @@ module.exports = ({lnd, request, timeout}, cbk) => {
estimateRouteFee: ['validate', ({}, cbk) => {
return lnd.router.estimateRouteFee({request, timeout},
(err, res) => {
if (!!err) {
console.log('cbk', err, res)

if (err) {
return cbk([503, 'UnexpectedEstimateRouteFeeError', {err}]);
}

if (!res) {
return cbk([503, 'ExpectedRouteFeeResponse']);
}

if (!res.mtoken) {
return cbk([503, 'ExpectedRoutingFeeMsatInRouteFeeResponse']);
if (!res.mtokens) {
return cbk([503, 'ExpectedRoutingFeeMtokensInRouteFeeResponse']);
}

if (!res.timeout) {
return cbk([503, 'ExpectedTimeLockDelayInRouteFeeResponse']);
}

if (!res.failure_reason) {
return cbk([503, 'ExpectedFailureReasonInRouteFeeResponse']);
}

if (res.failure_reason !== 'FAILURE_REASON_NONE') {
return cbk([404, 'EstimateRouteFindingFailed', {failure: res.failure_reason}])
}

return cbk(null, {mtoken: res.mtoken, timeout: res.timeout});
return cbk(null, {mtokens: res.mtokens, timeout: res.timeout});
});
}],
},
returnResult({reject, resolve, of: 'estimateRouteFee'}, cbk));
returnResult({reject, resolve, of: 'estimateRouteFee'}, cbk));
});
};
79 changes: 32 additions & 47 deletions test/lnd_methods/offchain/test_estimate_route_fee.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
const {rejects} = require('node:assert').strict;
const {rejects, deepStrictEqual} = require('node:assert').strict;
const test = require('node:test');
const estimateRouteFee = require('./../../../lnd_methods/offchain/estimate_route_fee');

const {estimateRouteFee, createInvoice} = require('./../../../lnd_methods');
const request = 'lnbcrt500u1pnh3r5dpp57cppte59jvmxnaunh03ecy6wchq8e0zh70n0nzsamaxztqxevcusdqqcqzzsxqyz5vqsp587ua488ttsts8cs97ekt9axdla3jmq4mj2h7xj7g6rw37fu65yqs9qxpqysgql27u5p9m2xv0r0pjykzvcgs88azzfkywzw2xw5q6u86qnwzrut94mks86zxelhltdtn6vnqgd8hay433wwq7uvple709gp7pmwmtzwcqakyevc';

const preimage = () => Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString('hex');

const makeLnd = args => {
/** Function */
const makeLnd = ({err, res}) => {
const response = {
mtokens: '1050',
timeout: '3520',
failure_reason: 'FAILURE_REASON_NONE'
};
return {
router: {
estimateRouteFee: ({ }, cbk) => cbk(null, {
routing_fee_msat: args.routing_fee_msat || '1',
time_lock_delay: args.time_lock_delay || '1',
})
estimateRouteFee: ({}, cbk) => cbk(err, res !== undefined ? res : response),
}
};
};

let request;
createInvoice({
secret: preimage(),
expires_at: 86400,
tokens: 50000,
routes: [],
})
.then(invoice => request = invoice.request)
.catch(console.error);

const makeArgs = async override => {
const args = {
lnd: makeLnd(),
request,
timeout: 1,
};

const makeArgs = override => {
const args = {request, timeout: 60000, lnd: makeLnd({})};
Object.keys(override || {}).forEach(key => args[key] = override[key]);

return args;
};

Expand All @@ -46,23 +32,8 @@ const tests = [
},
{
args: makeArgs({request: undefined}),
description: 'Payment request is required',
error: [400, 'ExpectedChannelFundingTxIdToEnableChannel'],
},
{
args: makeArgs({request: String('some string object')}),
description: 'Payment request must be string literal',
error: [400, 'ExpectedChannelFundingTxIdToEnableChannel'],
},
{
args: makeArgs({timeout: undefined}),
description: 'Timeout is required',
error: [400, 'ExpectedTimeoutNumberForRouteFeeEstimate'],
},
{
args: makeArgs({timeout: '1000'}),
description: 'Timeout must be a number',
error: [400, 'ExpectedTimeoutNumberForRouteFeeEstimate'],
description: 'Request is required',
error: [400, 'ExpectedPaymentRequestStringForRouteFeeEstimate'],
},
{
args: makeArgs({timeout: 86400001}),
Expand All @@ -73,6 +44,22 @@ const tests = [
args: makeArgs({timeout: 0}),
description: 'Timeout must be greater than 0',
error: [400, 'ExpectedTimeoutGreaterThanZeroForRouteFeeEstimate'],
},
{
args: makeArgs({request, lnd: makeLnd({})}),
description: 'A route fee millitokens is expected for default timeout 60000ms',
expected: {
mtokens: '1050',
timeout: '3520'
}
},
{
args: makeArgs({request, timeout: 86400000, lnd: makeLnd({})}),
description: 'A route fee millitokens is expected for timeout 86400000ms',
expected: {
mtokens: '1050',
timeout: '3520'
}
}
];

Expand All @@ -81,9 +68,7 @@ tests.forEach(({args, description, error, expected}) => {
if (!!error) {
await rejects(estimateRouteFee(args), error, 'Got expected error');
} else {
await estimateRouteFee(args);

deepStrictEqual(res, expected, 'Got expected result');
deepStrictEqual(await estimateRouteFee(args), expected, 'Got result');
}

return;
Expand Down

0 comments on commit ddd75a0

Please sign in to comment.