-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import {AuthenticatedLnd} from '../../lnd_grpc'; | ||
import { | ||
AuthenticatedLightningArgs, | ||
AuthenticatedLightningMethod | ||
} from '../../typescript'; | ||
|
||
export type RouteFeeRequest = AuthenticatedLightningArgs<{ | ||
lnd: AuthenticatedLnd; | ||
/** BOLT 11 Encoded Payment Request */ | ||
request: string; | ||
/** Optional Timeout in Milliseconds */ | ||
timeout: number; | ||
}>; | ||
|
||
export type RouteFeeResponse = { | ||
/** Millitokens (Routing Fee Msat) */ | ||
mtoken: number; | ||
/** Timeout (Time Lock Delay) */ | ||
timeout: number; | ||
}; | ||
|
||
/** | ||
* 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 | ||
>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
const asyncAuto = require('async/auto'); | ||
const {returnResult} = require('asyncjs-util'); | ||
|
||
/** | ||
* Estimate routing fees based on an invoice. | ||
* | ||
* Requires `offchain:read` permission | ||
* | ||
* This method is not supported before LND 0.18.4 | ||
* | ||
* | ||
@argument | ||
{ | ||
lnd: <Authenticated LND API Object> | ||
request: <BOLT 11 Payment Request String> | ||
timeout: <Optional Timeout in Milliseconds Number> | ||
} | ||
@returns via cbk or Promise | ||
{ | ||
mtoken: <Route Fee Millitokens String> | ||
timeout: <Time Lock Block Height Delay String> | ||
} | ||
*/ | ||
module.exports = ({lnd, request, timeout}, cbk) => { | ||
return new Promise((resolve, reject) => { | ||
return asyncAuto({ | ||
// Check arguments | ||
validate: cbk => { | ||
if (!lnd || !lnd.router) { | ||
return cbk([400, 'ExpectedAuthenticatedLndForRouteFeeEstimate']); | ||
} | ||
|
||
if (!request) { | ||
return cbk([400, 'ExpectedPaymentRequestStringForRouteFeeEstimate']); | ||
} | ||
|
||
if (timeout > 86400000) { | ||
return cbk([400, 'ExpectedTimeoutLessThanOneDayForRouteFeeEstimate']); | ||
} | ||
|
||
if (timeout < 1) { | ||
return cbk([400, 'ExpectedTimeoutGreaterThanZeroForRouteFeeEstimate']); | ||
} | ||
|
||
timeout = !timeout ? 60 : timeout / 1000; | ||
|
||
return cbk(); | ||
}, | ||
|
||
// Estimate route fee and return a successful routing fee and timeout or failure reason | ||
estimateRouteFee: ['validate', ({}, cbk) => { | ||
return lnd.router.estimateRouteFee({request, timeout}, | ||
(err, res) => { | ||
console.log('cbk', err, res) | ||
|
||
if (err) { | ||
return cbk([503, 'UnexpectedEstimateRouteFeeError', {err}]); | ||
} | ||
|
||
if (!res) { | ||
return cbk([503, 'ExpectedRouteFeeResponse']); | ||
} | ||
|
||
if (!res.mtokens) { | ||
return cbk([503, 'ExpectedRoutingFeeMtokensInRouteFeeResponse']); | ||
} | ||
|
||
if (!res.timeout) { | ||
return cbk([503, 'ExpectedTimeLockDelayInRouteFeeResponse']); | ||
} | ||
|
||
if (res.failure_reason !== 'FAILURE_REASON_NONE') { | ||
return cbk([404, 'EstimateRouteFindingFailed', {failure: res.failure_reason}]) | ||
} | ||
|
||
return cbk(null, {mtokens: res.mtokens, timeout: res.timeout}); | ||
}); | ||
}], | ||
}, | ||
returnResult({reject, resolve, of: 'estimateRouteFee'}, cbk)); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
const {rejects, deepStrictEqual} = require('node:assert').strict; | ||
const test = require('node:test'); | ||
const estimateRouteFee = require('./../../../lnd_methods/offchain/estimate_route_fee'); | ||
|
||
const request = 'lnbcrt500u1pnh3r5dpp57cppte59jvmxnaunh03ecy6wchq8e0zh70n0nzsamaxztqxevcusdqqcqzzsxqyz5vqsp587ua488ttsts8cs97ekt9axdla3jmq4mj2h7xj7g6rw37fu65yqs9qxpqysgql27u5p9m2xv0r0pjykzvcgs88azzfkywzw2xw5q6u86qnwzrut94mks86zxelhltdtn6vnqgd8hay433wwq7uvple709gp7pmwmtzwcqakyevc'; | ||
|
||
/** Function */ | ||
const makeLnd = ({err, res}) => { | ||
const response = { | ||
mtokens: '1050', | ||
timeout: '3520', | ||
failure_reason: 'FAILURE_REASON_NONE' | ||
}; | ||
return { | ||
router: { | ||
estimateRouteFee: ({}, cbk) => cbk(err, res !== undefined ? res : response), | ||
} | ||
}; | ||
}; | ||
|
||
const makeArgs = override => { | ||
const args = {request, timeout: 60000, lnd: makeLnd({})}; | ||
Object.keys(override || {}).forEach(key => args[key] = override[key]); | ||
return args; | ||
}; | ||
|
||
const tests = [ | ||
{ | ||
args: makeArgs({lnd: undefined}), | ||
description: 'LND is required', | ||
error: [400, 'ExpectedAuthenticatedLndForRouteFeeEstimate'], | ||
}, | ||
{ | ||
args: makeArgs({request: undefined}), | ||
description: 'Request is required', | ||
error: [400, 'ExpectedPaymentRequestStringForRouteFeeEstimate'], | ||
}, | ||
{ | ||
args: makeArgs({timeout: 86400001}), | ||
description: 'Timeout must be less than or equal to 86400000', | ||
error: [400, 'ExpectedTimeoutLessThanOneDayForRouteFeeEstimate'], | ||
}, | ||
{ | ||
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' | ||
} | ||
} | ||
]; | ||
|
||
tests.forEach(({args, description, error, expected}) => { | ||
return test(description, async () => { | ||
if (!!error) { | ||
await rejects(estimateRouteFee(args), error, 'Got expected error'); | ||
} else { | ||
deepStrictEqual(await estimateRouteFee(args), expected, 'Got result'); | ||
} | ||
|
||
return; | ||
}); | ||
}); |