ln-accounting 5.0.7 → 6.1.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 +10 -0
- package/README.md +19 -0
- package/fiat/get_coingecko_historic_rate.js +17 -1
- package/fiat/get_fiat_values.js +1 -0
- package/fiat/get_historic_rate.js +7 -2
- package/index.js +7 -1
- package/package.json +9 -8
- package/report/index.js +2 -1
- package/report/parse_amount.js +76 -0
- package/test/fiat/test_get_coingecko_historic_rate.js +30 -29
- package/test/fiat/test_get_historic_rate.js +26 -18
- package/test/records/test_get_all_invoices.js +1 -0
- package/test/records/test_get_all_payments.js +49 -22
- package/test/report/test_parse_amount.js +55 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## Version 6.1.0
|
|
4
|
+
|
|
5
|
+
- `parseAmount`: Add method to parse a human readable amount into tokens
|
|
6
|
+
|
|
7
|
+
## Version 6.0.0
|
|
8
|
+
|
|
9
|
+
### Breaking Changes
|
|
10
|
+
|
|
11
|
+
- Node.js 14 or higher is now required
|
|
12
|
+
|
|
3
13
|
## Version 5.0.7
|
|
4
14
|
|
|
5
15
|
- `getChainTransactions`: Add mempool space tx data lookup method
|
package/README.md
CHANGED
|
@@ -119,6 +119,25 @@ Get chain transactions, including sweep fees
|
|
|
119
119
|
}]
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
## parseAmount
|
|
123
|
+
|
|
124
|
+
Parse a described amount into tokens
|
|
125
|
+
|
|
126
|
+
{
|
|
127
|
+
amount: <Amount String>
|
|
128
|
+
[variables]: {
|
|
129
|
+
<Name String>: <Amount Number>
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@throws
|
|
134
|
+
<Error>
|
|
135
|
+
|
|
136
|
+
@returns
|
|
137
|
+
{
|
|
138
|
+
tokens: <Tokens Number>
|
|
139
|
+
}
|
|
140
|
+
|
|
122
141
|
## rateProviders
|
|
123
142
|
|
|
124
143
|
Rate provider source options
|
|
@@ -4,6 +4,7 @@ const {returnResult} = require('asyncjs-util');
|
|
|
4
4
|
const asCoingeckoDate = yyyymmdd => yyyymmdd.split('-').reverse().join('-');
|
|
5
5
|
const centsPerDollar = 100;
|
|
6
6
|
const dateComponents = date => date.substring(0, 'yyyy-mm-dd'.length);
|
|
7
|
+
const {keys} = Object;
|
|
7
8
|
const remoteServiceTimeoutMs = 30 * 1000;
|
|
8
9
|
const url = 'https://api.coingecko.com/api/v3/coins/bitcoin/history';
|
|
9
10
|
|
|
@@ -13,6 +14,7 @@ const url = 'https://api.coingecko.com/api/v3/coins/bitcoin/history';
|
|
|
13
14
|
currency: <Currency Type String>
|
|
14
15
|
date: <ISO 8601 Date String>
|
|
15
16
|
fiat: <Fiat Type String>
|
|
17
|
+
rates: <Known Rates Object>
|
|
16
18
|
request: <Request Function>
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -21,7 +23,7 @@ const url = 'https://api.coingecko.com/api/v3/coins/bitcoin/history';
|
|
|
21
23
|
cents: <Cents Per Token Number>
|
|
22
24
|
}
|
|
23
25
|
*/
|
|
24
|
-
module.exports = ({currency, date, fiat, request}, cbk) => {
|
|
26
|
+
module.exports = ({currency, date, fiat, rates, request}, cbk) => {
|
|
25
27
|
return new Promise((resolve, reject) => {
|
|
26
28
|
return asyncAuto({
|
|
27
29
|
// Check arguments
|
|
@@ -38,6 +40,10 @@ module.exports = ({currency, date, fiat, request}, cbk) => {
|
|
|
38
40
|
return cbk([400, 'UnsupportedFiatTypeForCoingeckoFiatRateLookup']);
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
if (!rates) {
|
|
44
|
+
return cbk([400, 'ExpectedKnownRatesForCoingeckoFiatRateLookup']);
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
if (!request) {
|
|
42
48
|
return cbk([400, 'ExpectedRequestMethodForCoingeckoFiatRateLookup']);
|
|
43
49
|
}
|
|
@@ -47,6 +53,16 @@ module.exports = ({currency, date, fiat, request}, cbk) => {
|
|
|
47
53
|
|
|
48
54
|
// Get rate
|
|
49
55
|
getRate: ['validate', ({}, cbk) => {
|
|
56
|
+
// Look for an existing rate lookup
|
|
57
|
+
const matching = keys(rates).find(key => {
|
|
58
|
+
return dateComponents(key) === dateComponents(date);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Exit early when there is a cached result
|
|
62
|
+
if (!!rates[matching]) {
|
|
63
|
+
return cbk(null, {cents: rates[matching]});
|
|
64
|
+
}
|
|
65
|
+
|
|
50
66
|
return request({
|
|
51
67
|
url,
|
|
52
68
|
json: true,
|
package/fiat/get_fiat_values.js
CHANGED
|
@@ -19,6 +19,7 @@ const times = 10;
|
|
|
19
19
|
date: <ISO 8601 Date String>
|
|
20
20
|
fiat: <Fiat Type String>
|
|
21
21
|
[provider]: <Historic Rate Source Type String>
|
|
22
|
+
rates: <Known Rates Object>
|
|
22
23
|
request: <Request Function>
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -27,7 +28,7 @@ const times = 10;
|
|
|
27
28
|
cents: <Cents Per Token Number>
|
|
28
29
|
}
|
|
29
30
|
*/
|
|
30
|
-
module.exports = ({currency, date, fiat, provider, request}, cbk) => {
|
|
31
|
+
module.exports = ({currency, date, fiat, provider, rates, request}, cbk) => {
|
|
31
32
|
return new Promise((resolve, reject) => {
|
|
32
33
|
return asyncAuto({
|
|
33
34
|
// Check arguments
|
|
@@ -44,6 +45,10 @@ module.exports = ({currency, date, fiat, provider, request}, cbk) => {
|
|
|
44
45
|
return cbk([400, 'ExpectedFiatToGetHistoricRate']);
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
if (!rates) {
|
|
49
|
+
return cbk([400, 'ExpectedRatesToGetHistoricRate']);
|
|
50
|
+
}
|
|
51
|
+
|
|
47
52
|
if (!request) {
|
|
48
53
|
return cbk([400, 'ExpectedRequestFunctionToGetHistoricRate']);
|
|
49
54
|
}
|
|
@@ -66,7 +71,7 @@ module.exports = ({currency, date, fiat, provider, request}, cbk) => {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
return asyncRetry({interval, times}, cbk => {
|
|
69
|
-
return source({currency, date, fiat, request}, cbk);
|
|
74
|
+
return source({currency, date, fiat, rates, request}, cbk);
|
|
70
75
|
},
|
|
71
76
|
cbk);
|
|
72
77
|
}],
|
package/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
const {getAccountingReport} = require('./report');
|
|
2
2
|
const {getChainTransactions} = require('./records');
|
|
3
|
+
const {parseAmount} = require('./report');
|
|
3
4
|
const {rateProviders} = require('./fiat');
|
|
4
5
|
|
|
5
|
-
module.exports = {
|
|
6
|
+
module.exports = {
|
|
7
|
+
getAccountingReport,
|
|
8
|
+
getChainTransactions,
|
|
9
|
+
parseAmount,
|
|
10
|
+
rateProviders,
|
|
11
|
+
};
|
package/package.json
CHANGED
|
@@ -7,19 +7,20 @@
|
|
|
7
7
|
"url": "https://github.com/alexbosworth/ln-accounting/issues"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"async": "3.2.
|
|
11
|
-
"asyncjs-util": "1.2.
|
|
12
|
-
"bitcoinjs-lib": "6.0.
|
|
13
|
-
"goldengate": "11.
|
|
10
|
+
"async": "3.2.4",
|
|
11
|
+
"asyncjs-util": "1.2.10",
|
|
12
|
+
"bitcoinjs-lib": "6.0.2",
|
|
13
|
+
"goldengate": "11.4.0",
|
|
14
|
+
"hot-formula-parser": "4.0.0",
|
|
14
15
|
"json2csv": "5.0.7",
|
|
15
|
-
"ln-service": "
|
|
16
|
+
"ln-service": "54.2.3"
|
|
16
17
|
},
|
|
17
18
|
"description": "lnd accounting reports",
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@alexbosworth/tap": "15.0.11"
|
|
20
21
|
},
|
|
21
22
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
23
|
+
"node": ">=14"
|
|
23
24
|
},
|
|
24
25
|
"keywords": [
|
|
25
26
|
"accounting",
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"url": "https://github.com/alexbosworth/ln-accounting.git"
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
|
-
"test": "tap --branches=1 --functions=1 --lines=1 --statements=1 test/blockstream/*.js test/fiat/*.js test/harmony/*.js test/records/*.js"
|
|
37
|
+
"test": "tap --branches=1 --functions=1 --lines=1 --statements=1 test/blockstream/*.js test/fiat/*.js test/harmony/*.js test/records/*.js test/report/*.js"
|
|
37
38
|
},
|
|
38
|
-
"version": "
|
|
39
|
+
"version": "6.1.0"
|
|
39
40
|
}
|
package/report/index.js
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const {Parser} = require('hot-formula-parser');
|
|
2
|
+
|
|
3
|
+
const {ceil} = Math;
|
|
4
|
+
const {isArray} = Array;
|
|
5
|
+
const {keys} = Object;
|
|
6
|
+
const {round} = Math;
|
|
7
|
+
|
|
8
|
+
/** Parse a described amount into tokens
|
|
9
|
+
|
|
10
|
+
{
|
|
11
|
+
amount: <Amount String>
|
|
12
|
+
[variables]: {
|
|
13
|
+
<Name String>: <Amount Number>
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@throws
|
|
18
|
+
<Error>
|
|
19
|
+
|
|
20
|
+
@returns
|
|
21
|
+
{
|
|
22
|
+
tokens: <Tokens Number>
|
|
23
|
+
}
|
|
24
|
+
*/
|
|
25
|
+
module.exports = ({amount, variables}) => {
|
|
26
|
+
if (isArray(amount)) {
|
|
27
|
+
throw new Error('CannotParseMultipleAmounts');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const parser = new Parser();
|
|
31
|
+
|
|
32
|
+
keys(variables || {}).forEach(key => {
|
|
33
|
+
parser.setVariable(key.toLowerCase(), variables[key]);
|
|
34
|
+
parser.setVariable(key.toUpperCase(), variables[key]);
|
|
35
|
+
|
|
36
|
+
return;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
parser.setVariable('BTC', 1e8);
|
|
40
|
+
parser.setVariable('btc', 1e8);
|
|
41
|
+
parser.setVariable('m', 1e6);
|
|
42
|
+
parser.setVariable('M', 1e6);
|
|
43
|
+
parser.setVariable('mm', 1e6);
|
|
44
|
+
parser.setVariable('MM', 1e6);
|
|
45
|
+
parser.setVariable('k', 1e3);
|
|
46
|
+
parser.setVariable('K', 1e3);
|
|
47
|
+
|
|
48
|
+
const parsed = parser.parse(amount);
|
|
49
|
+
|
|
50
|
+
switch (parsed.error) {
|
|
51
|
+
case '#DIV/0!':
|
|
52
|
+
throw new Error('CannotDivideByZeroInSpecifiedAmount');
|
|
53
|
+
|
|
54
|
+
case '#ERROR!':
|
|
55
|
+
throw new Error('FailedToParseSpecifiedAmount');
|
|
56
|
+
|
|
57
|
+
case '#N/A':
|
|
58
|
+
case '#NAME?':
|
|
59
|
+
throw new Error('UnrecognizedVariableOrFunctionInSpecifiedAmount');
|
|
60
|
+
|
|
61
|
+
case '#NUM!':
|
|
62
|
+
throw new Error('InvalidNumberFoundInSpecifiedAmount');
|
|
63
|
+
|
|
64
|
+
case '#VALUE!':
|
|
65
|
+
throw new Error('UnexpectedValueTypeInSpecifiedAmount');
|
|
66
|
+
|
|
67
|
+
default:
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!!parsed.error) {
|
|
72
|
+
throw new Error(parsed.error);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {tokens: round(parsed.result)};
|
|
76
|
+
};
|
|
@@ -2,71 +2,72 @@ const {test} = require('@alexbosworth/tap');
|
|
|
2
2
|
|
|
3
3
|
const method = require('./../../fiat/get_coingecko_historic_rate');
|
|
4
4
|
|
|
5
|
+
const makeArgs = overrides => {
|
|
6
|
+
const args = {
|
|
7
|
+
date: new Date().toISOString(),
|
|
8
|
+
currency: 'BTC',
|
|
9
|
+
fiat: 'USD',
|
|
10
|
+
rates: {},
|
|
11
|
+
request: ({qs}, cbk) => api({qs}, cbk),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
15
|
+
|
|
16
|
+
return args;
|
|
17
|
+
};
|
|
18
|
+
|
|
5
19
|
const api = ({qs}, cbk) => {
|
|
6
20
|
return cbk(null, null, {market_data: {current_price: {usd: 12.34}}});
|
|
7
21
|
};
|
|
8
22
|
|
|
9
23
|
const tests = [
|
|
10
24
|
{
|
|
11
|
-
args: {},
|
|
25
|
+
args: makeArgs({currency: undefined}),
|
|
12
26
|
description: 'A currency is required',
|
|
13
27
|
error: [400, 'UnsupportedCurrencyForCoingeckoFiatRateLookup'],
|
|
14
28
|
},
|
|
15
29
|
{
|
|
16
|
-
args: {
|
|
30
|
+
args: makeArgs({date: undefined}),
|
|
17
31
|
description: 'A date is required',
|
|
18
32
|
error: [400, 'ExpectedDateForCoingeckoRateLookup'],
|
|
19
33
|
},
|
|
20
34
|
{
|
|
21
|
-
args: {
|
|
22
|
-
description: 'A
|
|
35
|
+
args: makeArgs({fiat: undefined}),
|
|
36
|
+
description: 'A fiat type is required',
|
|
23
37
|
error: [400, 'UnsupportedFiatTypeForCoingeckoFiatRateLookup'],
|
|
24
38
|
},
|
|
25
39
|
{
|
|
26
|
-
args: {
|
|
40
|
+
args: makeArgs({rates: undefined}),
|
|
41
|
+
description: 'A rates object is required',
|
|
42
|
+
error: [400, 'ExpectedKnownRatesForCoingeckoFiatRateLookup'],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
args: makeArgs({request: undefined}),
|
|
27
46
|
description: 'A request method is required',
|
|
28
47
|
error: [400, 'ExpectedRequestMethodForCoingeckoFiatRateLookup'],
|
|
29
48
|
},
|
|
30
49
|
{
|
|
31
|
-
args: {
|
|
32
|
-
date: new Date().toISOString(),
|
|
33
|
-
currency: 'BTC',
|
|
34
|
-
fiat: 'USD',
|
|
35
|
-
request: ({}, cbk) => cbk('err'),
|
|
36
|
-
},
|
|
50
|
+
args: makeArgs({request: ({}, cbk) => cbk('err')}),
|
|
37
51
|
description: 'Errors returned from request',
|
|
38
52
|
error: [503, 'UnexpectedErrGettingCoingeckoPastRate', {err: 'err'}],
|
|
39
53
|
},
|
|
40
54
|
{
|
|
41
|
-
args: {
|
|
42
|
-
date: new Date().toISOString(),
|
|
43
|
-
currency: 'BTC',
|
|
44
|
-
fiat: 'USD',
|
|
45
|
-
request: ({}, cbk) => cbk(),
|
|
46
|
-
},
|
|
55
|
+
args: makeArgs({request: ({}, cbk) => cbk()}),
|
|
47
56
|
description: 'A body is expected in response',
|
|
48
57
|
error: [503, 'UnexpectedResponseInCoingeckoPastRateResponse'],
|
|
49
58
|
},
|
|
50
59
|
{
|
|
51
|
-
args: {
|
|
52
|
-
date: new Date().toISOString(),
|
|
53
|
-
currency: 'BTC',
|
|
54
|
-
fiat: 'USD',
|
|
60
|
+
args: makeArgs({
|
|
55
61
|
request: ({}, cbk) => cbk(null, null, {
|
|
56
62
|
market_data: {current_price: {}},
|
|
57
63
|
}),
|
|
58
|
-
},
|
|
64
|
+
}),
|
|
59
65
|
description: 'A price is expected in response',
|
|
60
66
|
error: [503, 'ExpectedCoingeckoCurrentPriceForFiat'],
|
|
61
67
|
},
|
|
62
68
|
{
|
|
63
|
-
args: {
|
|
64
|
-
|
|
65
|
-
currency: 'BTC',
|
|
66
|
-
fiat: 'USD',
|
|
67
|
-
request: ({qs}, cbk) => api({qs}, cbk),
|
|
68
|
-
},
|
|
69
|
-
description: 'Get coindesk historic rate',
|
|
69
|
+
args: makeArgs({}),
|
|
70
|
+
description: 'Get coingecko historic rate',
|
|
70
71
|
expected: {cents: 1234},
|
|
71
72
|
},
|
|
72
73
|
];
|
|
@@ -8,45 +8,53 @@ const api = ({}, cbk) => {
|
|
|
8
8
|
return cbk(null, null, {market_data: {current_price: {usd: 12.34}}});
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
const makeArgs = overrides => {
|
|
12
|
+
const args = {
|
|
13
|
+
date: new Date().toISOString(),
|
|
14
|
+
currency: 'BTC',
|
|
15
|
+
fiat: 'USD',
|
|
16
|
+
rates: {},
|
|
17
|
+
request: ({qs}, cbk) => api({qs}, cbk),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
Object.keys(overrides).forEach(k => args[k] = overrides[k]);
|
|
21
|
+
|
|
22
|
+
return args;
|
|
23
|
+
};
|
|
24
|
+
|
|
11
25
|
const tests = [
|
|
12
26
|
{
|
|
13
|
-
args: {},
|
|
27
|
+
args: makeArgs({currency: undefined}),
|
|
14
28
|
description: 'A currency code is required',
|
|
15
29
|
error: [400, 'ExpectedCurrencyToGetHistoricRate'],
|
|
16
30
|
},
|
|
17
31
|
{
|
|
18
|
-
args: {
|
|
32
|
+
args: makeArgs({date: undefined}),
|
|
19
33
|
description: 'A date is required',
|
|
20
34
|
error: [400, 'ExpectedDateToGetHistoricRate'],
|
|
21
35
|
},
|
|
22
36
|
{
|
|
23
|
-
args: {
|
|
37
|
+
args: makeArgs({fiat: undefined}),
|
|
24
38
|
description: 'A fiat type is required to get historic rate',
|
|
25
39
|
error: [400, 'ExpectedFiatToGetHistoricRate'],
|
|
26
40
|
},
|
|
27
41
|
{
|
|
28
|
-
args: {
|
|
42
|
+
args: makeArgs({rates: undefined}),
|
|
43
|
+
description: 'Past rates are required to get historic rate',
|
|
44
|
+
error: [400, 'ExpectedRatesToGetHistoricRate'],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
args: makeArgs({request: undefined}),
|
|
29
48
|
description: 'A request function is required to get historic rate',
|
|
30
49
|
error: [400, 'ExpectedRequestFunctionToGetHistoricRate'],
|
|
31
50
|
},
|
|
32
51
|
{
|
|
33
|
-
args: {
|
|
34
|
-
|
|
35
|
-
currency: 'BTC',
|
|
36
|
-
fiat: 'USD',
|
|
37
|
-
provider: 'provider',
|
|
38
|
-
request: () => {},
|
|
39
|
-
},
|
|
40
|
-
description: 'A request function is required to get historic rate',
|
|
52
|
+
args: makeArgs({provider: 'provider'}),
|
|
53
|
+
description: 'A known rate provider is required to get historic rate',
|
|
41
54
|
error: [400, 'ExpectedKnownRateProviderToGetHistoricRate'],
|
|
42
55
|
},
|
|
43
56
|
{
|
|
44
|
-
args: {
|
|
45
|
-
date,
|
|
46
|
-
currency: 'BTC',
|
|
47
|
-
fiat: 'USD',
|
|
48
|
-
request: ({qs}, cbk) => api({qs}, cbk),
|
|
49
|
-
},
|
|
57
|
+
args: makeArgs({}),
|
|
50
58
|
description: 'Get historic fiat rates',
|
|
51
59
|
expected: {cents: 1234},
|
|
52
60
|
},
|
|
@@ -58,19 +58,34 @@ const tests = [
|
|
|
58
58
|
},
|
|
59
59
|
resolve_time_ns: '1000000',
|
|
60
60
|
route: {
|
|
61
|
-
hops: [
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
hops: [
|
|
62
|
+
{
|
|
63
|
+
amt_to_forward_msat: '1000',
|
|
64
|
+
chan_id: '1',
|
|
65
|
+
chan_capacity: 1,
|
|
66
|
+
expiry: 1,
|
|
67
|
+
fee_msat: '1000',
|
|
68
|
+
mpp_record: {
|
|
69
|
+
payment_addr: Buffer.alloc(32),
|
|
70
|
+
total_amt_msat: '1000',
|
|
71
|
+
},
|
|
72
|
+
pub_key: Buffer.alloc(33).toString('hex'),
|
|
73
|
+
tlv_payload: true,
|
|
70
74
|
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
{
|
|
76
|
+
amt_to_forward_msat: '1000',
|
|
77
|
+
chan_id: '1',
|
|
78
|
+
chan_capacity: 1,
|
|
79
|
+
expiry: 1,
|
|
80
|
+
fee_msat: '1000',
|
|
81
|
+
mpp_record: {
|
|
82
|
+
payment_addr: Buffer.alloc(32),
|
|
83
|
+
total_amt_msat: '1000',
|
|
84
|
+
},
|
|
85
|
+
pub_key: Buffer.alloc(33).toString('hex'),
|
|
86
|
+
tlv_payload: true,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
74
89
|
total_amt: '1',
|
|
75
90
|
total_amt_msat: '1000',
|
|
76
91
|
total_fees: '1',
|
|
@@ -108,16 +123,28 @@ const tests = [
|
|
|
108
123
|
route: {
|
|
109
124
|
fee: 1,
|
|
110
125
|
fee_mtokens: '1000',
|
|
111
|
-
hops: [
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
126
|
+
hops: [
|
|
127
|
+
{
|
|
128
|
+
channel: '0x0x1',
|
|
129
|
+
channel_capacity: 1,
|
|
130
|
+
fee: 1,
|
|
131
|
+
fee_mtokens: '1000',
|
|
132
|
+
forward: 1,
|
|
133
|
+
forward_mtokens: '1000',
|
|
134
|
+
public_key: Buffer.alloc(33).toString('hex'),
|
|
135
|
+
timeout: 1,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
channel: '0x0x1',
|
|
139
|
+
channel_capacity: 1,
|
|
140
|
+
fee: 1,
|
|
141
|
+
fee_mtokens: '1000',
|
|
142
|
+
forward: 1,
|
|
143
|
+
forward_mtokens: '1000',
|
|
144
|
+
public_key: Buffer.alloc(33).toString('hex'),
|
|
145
|
+
timeout: 1,
|
|
146
|
+
},
|
|
147
|
+
],
|
|
121
148
|
mtokens: '1000',
|
|
122
149
|
payment: Buffer.alloc(32).toString('hex'),
|
|
123
150
|
timeout: 1,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const {test} = require('@alexbosworth/tap');
|
|
2
|
+
|
|
3
|
+
const {parseAmount} = require('./../../');
|
|
4
|
+
|
|
5
|
+
const tests = [
|
|
6
|
+
{
|
|
7
|
+
args: {amount: 'amount'},
|
|
8
|
+
description: 'A value is required',
|
|
9
|
+
error: 'UnrecognizedVariableOrFunctionInSpecifiedAmount',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
args: {amount: '1/0'},
|
|
13
|
+
description: 'Dividing by zero is not allowed',
|
|
14
|
+
error: 'CannotDivideByZeroInSpecifiedAmount',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
args: {amount: '0.0.0'},
|
|
18
|
+
description: 'A generic invalid amount is rejected',
|
|
19
|
+
error: 'FailedToParseSpecifiedAmount',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
args: {amount: 'OCT2DEC()'},
|
|
23
|
+
description: 'Invalid numbers are rejected',
|
|
24
|
+
error: 'InvalidNumberFoundInSpecifiedAmount',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
args: {amount: '"string" + 1'},
|
|
28
|
+
description: 'Invalid formulas are rejected',
|
|
29
|
+
error: 'UnexpectedValueTypeInSpecifiedAmount',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
args: {amount: '1.20969468*btc', variables: {variable: 'value'}},
|
|
33
|
+
description: 'A long precision BTC value is parsed',
|
|
34
|
+
expected: {tokens: 120969468},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
args: {amount: '1.20969465*btc'},
|
|
38
|
+
description: 'A long precision BTC value that rounds down is parsed',
|
|
39
|
+
expected: {tokens: 120969465},
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
44
|
+
return test(description, ({end, equal, throws}) => {
|
|
45
|
+
if (!!error) {
|
|
46
|
+
throws(() => parseAmount(args), new Error(error), 'Got expected error');
|
|
47
|
+
} else {
|
|
48
|
+
const {tokens} = parseAmount(args);
|
|
49
|
+
|
|
50
|
+
equal(tokens, expected.tokens, 'Got expected output');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return end();
|
|
54
|
+
});
|
|
55
|
+
});
|