ln-accounting 6.0.0 → 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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Versions
2
2
 
3
+ ## Version 6.1.0
4
+
5
+ - `parseAmount`: Add method to parse a human readable amount into tokens
6
+
3
7
  ## Version 6.0.0
4
8
 
5
9
  ### Breaking Changes
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
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 = {getAccountingReport, getChainTransactions, rateProviders};
6
+ module.exports = {
7
+ getAccountingReport,
8
+ getChainTransactions,
9
+ parseAmount,
10
+ rateProviders,
11
+ };
package/package.json CHANGED
@@ -11,8 +11,9 @@
11
11
  "asyncjs-util": "1.2.10",
12
12
  "bitcoinjs-lib": "6.0.2",
13
13
  "goldengate": "11.4.0",
14
+ "hot-formula-parser": "4.0.0",
14
15
  "json2csv": "5.0.7",
15
- "ln-service": "54.2.0"
16
+ "ln-service": "54.2.3"
16
17
  },
17
18
  "description": "lnd accounting reports",
18
19
  "devDependencies": {
@@ -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": "6.0.0"
39
+ "version": "6.1.0"
39
40
  }
package/report/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  const getAccountingReport = require('./get_accounting_report');
2
+ const parseAmount = require('./parse_amount');
2
3
 
3
- module.exports = {getAccountingReport};
4
+ module.exports = {getAccountingReport, parseAmount};
@@ -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
+ };
@@ -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
+ });