balanceofsatoshis 25.3.1 → 25.5.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +17 -3
  3. package/balances/constants.json +14 -1
  4. package/balances/get_accounting_report.js +95 -10
  5. package/balances/get_historic_rate.js +75 -0
  6. package/balances/get_record_rate.js +77 -0
  7. package/balances/guard_chain_rate.js +50 -0
  8. package/bos +10 -0
  9. package/chain/fund_transaction.js +10 -9
  10. package/chain/get_block_transactions.js +6 -5
  11. package/chain/recover_p2pk.js +5 -4
  12. package/chain/split_utxos.js +5 -4
  13. package/commands/constants.json +1 -1
  14. package/commands/fetch_request.js +32 -24
  15. package/commands/simple_request.js +48 -13
  16. package/display/get_icons.js +33 -22
  17. package/encryption/cbor_item_head.js +45 -0
  18. package/encryption/decode_cbor.js +35 -0
  19. package/encryption/decode_cbor_item.js +169 -0
  20. package/encryption/decrypt_with_node.js +21 -18
  21. package/encryption/decrypt_with_secret.js +5 -4
  22. package/encryption/encode_as_cbor.js +21 -0
  23. package/encryption/encode_cbor_item.js +90 -0
  24. package/encryption/encrypt_to_secret.js +6 -4
  25. package/encryption/index.js +4 -0
  26. package/lnd/get_credentials.js +2 -2
  27. package/lnd/get_socket.js +11 -10
  28. package/lnurl/auth.js +6 -5
  29. package/network/get_peers.js +9 -4
  30. package/network/probe.js +2 -0
  31. package/network/probe_destination.js +97 -68
  32. package/network/push_payment.js +42 -17
  33. package/network/send_gift.js +10 -9
  34. package/network/transfer_funds.js +6 -6
  35. package/nodes/register_node.js +34 -30
  36. package/offchain/create_invoice.js +21 -16
  37. package/offchain/get_invoice_amount.js +5 -4
  38. package/offchain/sign_payment_request.js +10 -9
  39. package/package.json +10 -11
  40. package/peers/detect_open_rule_violation.js +6 -5
  41. package/routing/get_chain_fees_chart.js +3 -2
  42. package/routing/get_fees_paid.js +30 -12
  43. package/services/initiate_balanced_channel.js +13 -7
  44. package/swaps/append_failing_edge.js +6 -5
  45. package/swaps/decode_swap_api_key.js +29 -25
  46. package/swaps/get_paid_service.js +46 -23
  47. package/swaps/get_routes_for_funding.js +52 -11
  48. package/swaps/get_swap_service.js +5 -4
  49. package/swaps/rebalance.js +78 -63
  50. package/swaps/swap_api_key.js +2 -2
  51. package/swaps/swap_in.js +36 -26
  52. package/tags/get_tags.js +26 -15
  53. package/telegram/connect_to_telegram.js +17 -12
  54. package/telegram/get_socks_proxy.js +12 -13
  55. package/telegram/get_telegram_bot.js +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Versions
2
2
 
3
+ ## 25.5.0
4
+
5
+ - `probe`: Add `--ignore-expiry` to probe expired payment requests
6
+
7
+ ## 25.4.0
8
+
9
+ - `accounting`: After 2021-10-19 derive USD prices from chain payments data
10
+ - `accounting`: Add `--rate-provider coinbase`
11
+ - `telegram`: Reduce telegram linkification in messages
12
+
3
13
  ## 25.3.1
4
14
 
5
15
  - `closed`: Avoid using external chain data lookups to derive resolution info
package/README.md CHANGED
@@ -7,12 +7,12 @@ Commands for working with LND balances.
7
7
 
8
8
  Supported LND versions:
9
9
 
10
- - v0.21.0-beta to v0.21.4-beta
11
- - v0.20.0-beta to v0.20.5-beta
10
+ - v0.21.0-beta to v0.21.5-beta
11
+ - v0.20.0-beta to v0.20.6-beta
12
12
 
13
13
  ## Install
14
14
 
15
- - Requires an [installation of Node v20+][nodejs-install-guide]
15
+ - Requires an [installation of Node.js v22+][nodejs-install-guide]
16
16
 
17
17
  ```shell
18
18
  npm install -g balanceofsatoshis
@@ -298,6 +298,20 @@ If that is set, it will use that node if no node is specified.
298
298
  You can also add a JSON file to your .bos directory: config.json, add
299
299
  `{"default_saved_node": "nodename"}` to set the default via a file instead
300
300
 
301
+ ## Files in `~/.bos`
302
+
303
+ `bos` keeps its files in `~/.bos`, or in `BOS_DATA_PATH` when that is set:
304
+
305
+ - `chain_prices.json`: USD prices of BTC that `bos accounting` derived from
306
+ chain data, kept so that a day is only derived once. Prices are derived
307
+ this way when no `--rate-provider` is given, and the prices of the days
308
+ up to the release of `bos` come with it rather than being written here.
309
+ The file can be deleted, prices are then derived again when needed
310
+ - `config.json`: settings you add, like a default saved node
311
+ - `tags.json`: the tags made with `bos tags`
312
+ - `telegram_bot_api_key`: the bot API key that `bos telegram` asked for
313
+ - `YOUR_NODE_NAME/credentials.json`: the credentials of a saved node
314
+
301
315
  ## Linux Fu
302
316
 
303
317
  Some commands are designed to return outputs that can be piped or used in other CLI programs.
@@ -1,6 +1,11 @@
1
1
  {
2
+ "chainPricesFile": "chain_prices.json",
3
+ "coinbaseProvider": "coinbase",
2
4
  "defaultCurrency": "BTC",
3
5
  "defaultFiat": "USD",
6
+ "failedRequestErrors": ["UnexpectedErrorGettingCoinbaseCandles"],
7
+ "fsMethods": ["getFile", "makeDirectory", "renameFile", "writeFile"],
8
+ "mainnet": "btc",
4
9
  "notFoundIndex": -1,
5
10
  "monthNumbers": [
6
11
  "01",
@@ -25,5 +30,13 @@
25
30
  "11",
26
31
  "12"
27
32
  ],
28
- "monthOffset": 1
33
+ "monthOffset": 1,
34
+ "pricesFileErrors": [
35
+ "ExpectedPricesObjectInPricesFile",
36
+ "FailedToParsePricesFile",
37
+ "FailedToReadPricesFile",
38
+ "FailedToReplacePricesFile",
39
+ "FailedToWritePricesFile",
40
+ "UnsupportedPricesFileVersion"
41
+ ]
29
42
  }
@@ -1,11 +1,19 @@
1
1
  const asyncAuto = require('async/auto');
2
+ const {chainRates} = require('@alexbosworth/fiat');
2
3
  const {getAccountingReport} = require('ln-accounting');
3
4
  const {getNetwork} = require('ln-sync');
4
5
  const {returnResult} = require('asyncjs-util');
5
6
 
6
7
  const categories = require('./accounting_categories');
8
+ const {chainPricesFile} = require('./constants');
9
+ const {coinbaseProvider} = require('./constants');
7
10
  const {defaultCurrency} = require('./constants');
8
11
  const {defaultFiat} = require('./constants');
12
+ const {fsMethods} = require('./constants');
13
+ const getRecordRate = require('./get_record_rate');
14
+ const guardChainRate = require('./guard_chain_rate');
15
+ const {homePath} = require('./../storage');
16
+ const {mainnet} = require('./constants');
9
17
  const {monthNumbers} = require('./constants');
10
18
  const {monthOffset} = require('./constants');
11
19
  const {notFoundIndex} = require('./constants');
@@ -26,9 +34,16 @@ const summaryHeadings = ['Total', 'Asset', 'Report Date', 'Total Fiat'];
26
34
  [currency]: <Currency Label String>
27
35
  [date]: <Day of Month String>
28
36
  [fiat]: <Fiat Type String>
37
+ [fs]: {
38
+ getFile: <Read File Contents Function> (path, cbk) => {}
39
+ makeDirectory: <Make Directory Function> (path, cbk) => {}
40
+ renameFile: <Rename File Function> (from, to, cbk) => {}
41
+ writeFile: <Write File Contents Function> (path, contents, cbk) => {}
42
+ }
29
43
  [is_csv]: <Return CSV Output Bool>
30
44
  [is_fiat_disabled]: <Omit Fiat Conversion Bool>
31
45
  lnd: <Authenticated LND API Object>
46
+ [logger]: <Winston Logger Object>
32
47
  [month]: <Month for Report String>
33
48
  [node]: <Node Name String>
34
49
  [rate_provider]: <Rate Provider String>
@@ -47,6 +62,8 @@ module.exports = (args, cbk) => {
47
62
  return asyncAuto({
48
63
  // Validate
49
64
  validate: cbk => {
65
+ const {fs} = args;
66
+
50
67
  if (!args.category || !categories[args.category]) {
51
68
  return cbk([400, 'ExpectedKnownAccountingRecordsCategory']);
52
69
  }
@@ -55,6 +72,10 @@ module.exports = (args, cbk) => {
55
72
  return cbk([400, 'ExpectedMonthForDateToGetAccountingReport']);
56
73
  }
57
74
 
75
+ if (!!fs && !fsMethods.every(n => typeof fs[n] === 'function')) {
76
+ return cbk([400, 'ExpectedFileSystemMethodsToGetAccountingReport']);
77
+ }
78
+
58
79
  if (!args.lnd) {
59
80
  return cbk([400, 'ExpectedAuthenticatedLndToGetAccountingReport']);
60
81
  }
@@ -68,25 +89,88 @@ module.exports = (args, cbk) => {
68
89
 
69
90
  // Get date range
70
91
  dateRange: ['validate', ({}, cbk) => {
71
- try {
72
- return cbk(null, rangeForDate({
73
- date: args.date,
74
- month: args.month,
75
- year: args.year,
76
- }));
77
- } catch (err) {
78
- return cbk([400, err.message]);
92
+ const range = (() => {
93
+ try {
94
+ return {
95
+ value: rangeForDate({
96
+ date: args.date,
97
+ month: args.month,
98
+ year: args.year,
99
+ }),
100
+ };
101
+ } catch (err) {
102
+ return {err};
103
+ }
104
+ })();
105
+
106
+ // Exit early when the date range cannot be determined
107
+ if (!!range.err) {
108
+ return cbk([400, range.err.message]);
79
109
  }
110
+
111
+ return cbk(null, range.value);
80
112
  }],
81
113
 
82
114
  // Get the network name
83
115
  getNetwork: ['validate', ({}, cbk) => getNetwork({lnd: args.lnd}, cbk)],
84
116
 
117
+ // Make the method that gets chain prices, used without a rate provider
118
+ chain: ['getNetwork', ({getNetwork}, cbk) => {
119
+ // Exit early when fiat is disabled or a rate provider is specified
120
+ if (!!args.is_fiat_disabled || !!args.rate_provider) {
121
+ return cbk();
122
+ }
123
+
124
+ // Exit early when there are no chain prices for the network or no
125
+ // file system to keep them in
126
+ if (!args.fs || getNetwork.network !== mainnet) {
127
+ return cbk();
128
+ }
129
+
130
+ // Progress is only logged when it cannot end up in CSV output
131
+ const logger = !args.is_csv ? args.logger : undefined;
132
+
133
+ const {getChainRate} = chainRates({
134
+ logger,
135
+ fs: args.fs,
136
+ lnd: args.lnd,
137
+ path: homePath({file: chainPricesFile}).path,
138
+ });
139
+
140
+ return cbk(null, guardChainRate({getChainRate}));
141
+ }],
142
+
143
+ // Without a rate provider, records are valued with chain prices, and
144
+ // at their hour on Coinbase Exchange when chain prices cannot value them
145
+ rate: ['chain', ({chain}, cbk) => {
146
+ // Exit early when fiat is disabled
147
+ if (!!args.is_fiat_disabled) {
148
+ return cbk();
149
+ }
150
+
151
+ // Exit early when a rate provider other than Coinbase is specified
152
+ if (!!args.rate_provider && args.rate_provider !== coinbaseProvider) {
153
+ return cbk();
154
+ }
155
+
156
+ return cbk(null, {
157
+ rate: (record, cbk) => getRecordRate({
158
+ currency: record.currency,
159
+ date: record.date,
160
+ fiat: record.fiat,
161
+ get_chain_rate: !!chain ? chain.getChainRate : undefined,
162
+ request: args.request,
163
+ },
164
+ cbk),
165
+ });
166
+ }],
167
+
85
168
  // Get accounting info
86
169
  getAccounting: [
87
170
  'dateRange',
88
171
  'getNetwork',
89
- ({dateRange, getNetwork}, cbk) =>
172
+ 'rate',
173
+ ({dateRange, getNetwork, rate}, cbk) =>
90
174
  {
91
175
  return getAccountingReport({
92
176
  after: dateRange.after,
@@ -96,7 +180,8 @@ module.exports = (args, cbk) => {
96
180
  fiat: !args.is_fiat_disabled ? (args.fiat || defaultFiat) : null,
97
181
  lnd: args.lnd,
98
182
  network: getNetwork.network,
99
- rate_provider: args.rate_provider || undefined,
183
+ rate: !!rate ? rate.rate : undefined,
184
+ rate_provider: !rate ? args.rate_provider : undefined,
100
185
  request: args.request,
101
186
  },
102
187
  cbk);
@@ -0,0 +1,75 @@
1
+ const asyncAuto = require('async/auto');
2
+ const asyncRetry = require('async/retry');
3
+ const {getPrices} = require('@alexbosworth/fiat');
4
+ const {returnResult} = require('asyncjs-util');
5
+
6
+ const {failedRequestErrors} = require('./constants');
7
+
8
+ const isFailedRequest = err => !!err && failedRequestErrors.includes(err[1]);
9
+ const retryDelaysMs = [1000, 2000];
10
+ const supportedCurrency = 'BTC';
11
+
12
+ /** Get the fiat rate of BTC at the hour of a date from a rate provider
13
+
14
+ {
15
+ currency: <Currency Type String>
16
+ date: <ISO 8601 Date String>
17
+ fiat: <Fiat Type String>
18
+ from: <Rate Provider String>
19
+ request: <Request Function>
20
+ }
21
+
22
+ @returns via cbk or Promise
23
+ {
24
+ cents: <Cents Per BTC Number>
25
+ }
26
+ */
27
+ module.exports = ({currency, date, fiat, from, request}, cbk) => {
28
+ return new Promise((resolve, reject) => {
29
+ return asyncAuto({
30
+ // Check arguments
31
+ validate: cbk => {
32
+ if (currency !== supportedCurrency) {
33
+ return cbk([400, 'UnsupportedCurrencyToGetHistoricRate']);
34
+ }
35
+
36
+ if (!date) {
37
+ return cbk([400, 'ExpectedDateToGetHistoricRate']);
38
+ }
39
+
40
+ if (!fiat) {
41
+ return cbk([400, 'ExpectedFiatToGetHistoricRate']);
42
+ }
43
+
44
+ if (!from) {
45
+ return cbk([400, 'ExpectedRateProviderToGetHistoricRate']);
46
+ }
47
+
48
+ if (!request) {
49
+ return cbk([400, 'ExpectedRequestFunctionToGetHistoricRate']);
50
+ }
51
+
52
+ return cbk();
53
+ },
54
+
55
+ // Get the price at the hour of the date, trying a failed request again
56
+ getPrice: ['validate', ({}, cbk) => {
57
+ return asyncRetry({
58
+ errorFilter: isFailedRequest,
59
+ interval: count => retryDelaysMs[count - 1],
60
+ times: retryDelaysMs.length + 1,
61
+ },
62
+ cbk => getPrices({date, from, request, symbols: [fiat]}, cbk),
63
+ cbk);
64
+ }],
65
+
66
+ // The rate of the fiat
67
+ rate: ['getPrice', ({getPrice}, cbk) => {
68
+ const [ticker] = getPrice.tickers;
69
+
70
+ return cbk(null, {cents: ticker.rate});
71
+ }],
72
+ },
73
+ returnResult({reject, resolve, of: 'rate'}, cbk));
74
+ });
75
+ };
@@ -0,0 +1,77 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const {coinbaseProvider} = require('./constants');
5
+ const getHistoricRate = require('./get_historic_rate');
6
+
7
+ /** Get the fiat rate of BTC for an accounting record
8
+
9
+ {
10
+ currency: <Currency Type String>
11
+ date: <Record ISO 8601 Date String>
12
+ fiat: <Fiat Type String>
13
+ [get_chain_rate]: <Get Chain Rate Function>
14
+ request: <Request Function>
15
+ }
16
+
17
+ @returns via cbk or Promise
18
+ {
19
+ cents: <Cents Per BTC Number>
20
+ }
21
+ */
22
+ module.exports = (args, cbk) => {
23
+ return new Promise((resolve, reject) => {
24
+ return asyncAuto({
25
+ // Check arguments
26
+ validate: cbk => {
27
+ if (!args.request) {
28
+ return cbk([400, 'ExpectedRequestFunctionToGetRecordRate']);
29
+ }
30
+
31
+ return cbk();
32
+ },
33
+
34
+ // Get the price derived from chain data
35
+ getChainRate: ['validate', ({}, cbk) => {
36
+ // Exit early when there are no chain prices
37
+ if (!args.get_chain_rate) {
38
+ return cbk();
39
+ }
40
+
41
+ return args.get_chain_rate({
42
+ currency: args.currency,
43
+ date: args.date,
44
+ fiat: args.fiat,
45
+ },
46
+ cbk);
47
+ }],
48
+
49
+ // Get the price at the hour of the record on Coinbase Exchange
50
+ getCoinbaseRate: ['getChainRate', ({getChainRate}, cbk) => {
51
+ // Exit early when the record has a chain price
52
+ if (!!getChainRate) {
53
+ return cbk();
54
+ }
55
+
56
+ return getHistoricRate({
57
+ currency: args.currency,
58
+ date: args.date,
59
+ fiat: args.fiat,
60
+ from: coinbaseProvider,
61
+ request: args.request,
62
+ },
63
+ cbk);
64
+ }],
65
+
66
+ // The rate of the record
67
+ rate: [
68
+ 'getChainRate',
69
+ 'getCoinbaseRate',
70
+ ({getChainRate, getCoinbaseRate}, cbk) =>
71
+ {
72
+ return cbk(null, {cents: (getChainRate || getCoinbaseRate).cents});
73
+ }],
74
+ },
75
+ returnResult({reject, resolve, of: 'rate'}, cbk));
76
+ });
77
+ };
@@ -0,0 +1,50 @@
1
+ const {pricesFileErrors} = require('./constants');
2
+
3
+ const isFileError = err => !!err && pricesFileErrors.includes(err[1]);
4
+
5
+ /** Make a chain rate lookup that only fails on prices file errors
6
+
7
+ {
8
+ getChainRate: <Get Chain Rate Function>
9
+ }
10
+
11
+ @returns
12
+ {
13
+ getChainRate: <Get Chain Rate Method> ({
14
+ currency: <Currency To Price String>
15
+ date: <Date To Price ISO 8601 Date String>
16
+ fiat: <Fiat Currency To Price In String>
17
+ }, cbk) => (err, [{
18
+ cents: <US Cents Per BTC Number>
19
+ }])
20
+ }
21
+ */
22
+ module.exports = ({getChainRate}) => {
23
+ const failure = {};
24
+
25
+ return {
26
+ getChainRate: (args, cbk) => {
27
+ // Exit early when the prices file failed, since it would fail again
28
+ if (!!failure.err) {
29
+ return cbk(failure.err);
30
+ }
31
+
32
+ return getChainRate(args, (err, res) => {
33
+ // Exit early when there is a chain price
34
+ if (!err) {
35
+ return cbk(null, res);
36
+ }
37
+
38
+ // Exit early without a price when chain prices cannot value the date
39
+ if (!isFileError(err)) {
40
+ return cbk();
41
+ }
42
+
43
+ // A prices file error is kept, as trying again cannot fix the file
44
+ failure.err = err;
45
+
46
+ return cbk(err);
47
+ });
48
+ },
49
+ };
50
+ };
package/bos CHANGED
@@ -70,6 +70,7 @@ prog
70
70
  .argument('<category>', 'Report category', keys(accountingCategories))
71
71
  .help(`Categories: ${keys(accountingCategories).join(', ')}`)
72
72
  .help(`Rate providers: ${rateProviders.join(', ')}`)
73
+ .help('By default fiat rates after 2021-10-19 use chain data derived rates')
73
74
  .help('Privacy note: this requests tx related data from third parties')
74
75
  .option('--csv', 'Output a CSV')
75
76
  .option('--date <day>', 'Show only records for specific date')
@@ -84,8 +85,15 @@ prog
84
85
  return new Promise(async (resolve, reject) => {
85
86
  try {
86
87
  return balances.getAccountingReport({
88
+ logger,
87
89
  category: args.category,
88
90
  date: options.date,
91
+ fs: {
92
+ writeFile,
93
+ getFile: readFile,
94
+ makeDirectory: mkdir,
95
+ renameFile: rename,
96
+ },
89
97
  is_csv: !!options.csv,
90
98
  is_fiat_disabled: options.disableFiat,
91
99
  lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
@@ -1649,6 +1657,7 @@ prog
1649
1657
  .option('--avoid <avoid>', 'Avoid forwarding via node/chan/tag', REPEATABLE)
1650
1658
  .option('--avoid-high-fee-routes', 'Avoid evaluating too-high fee routes')
1651
1659
  .option('--find-max', 'Find the maximum routeable amount on success route')
1660
+ .option('--ignore-expiry', 'Probe even when the request has expired')
1652
1661
  .option('--in <public_key>', 'Route through specific peer of destination')
1653
1662
  .option('--max-fee <max_fee>', 'Max expected fee for route', INT, 1337)
1654
1663
  .option('--max-paths <max>', 'Maximum paths to use for find-max', INT, 1)
@@ -1671,6 +1680,7 @@ prog
1671
1680
  find_max: !!options.findMax ? 16777215 : undefined,
1672
1681
  fs: {getFile: readFile},
1673
1682
  in_through: inThrough.public_key,
1683
+ is_ignoring_expiry: !!options.ignoreExpiry,
1674
1684
  is_strict_max_fee: !!options.avoidHighFeeRoutes,
1675
1685
  max_fee: options.maxFee,
1676
1686
  max_paths: options.maxPaths,
@@ -1,5 +1,6 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncEach = require('async/each');
3
+ const asyncify = require('async/asyncify');
3
4
  const {broadcastTransaction} = require('ln-sync');
4
5
  const {componentsOfTransaction} = require('@alexbosworth/blockchain');
5
6
  const {formatTokens} = require('ln-sync');
@@ -112,10 +113,10 @@ module.exports = (args, cbk) => {
112
113
  getNetwork: ['validate', ({}, cbk) => getNetwork({lnd: args.lnd}, cbk)],
113
114
 
114
115
  // Derive a list of outputs to guide input selection
115
- outputs: ['validate', ({}, cbk) => {
116
+ outputs: ['validate', asyncify(() => {
116
117
  // Exit early when the amount is open ended and thus depends on inputs
117
118
  if (hasMaxAmount(args.amounts)) {
118
- return cbk();
119
+ return;
119
120
  }
120
121
 
121
122
  try {
@@ -125,11 +126,11 @@ module.exports = (args, cbk) => {
125
126
  return {address, tokens};
126
127
  });
127
128
 
128
- return cbk(null, outputs);
129
+ return outputs;
129
130
  } catch (err) {
130
- return cbk([400, err.message]);
131
+ throw [400, err.message];
131
132
  }
132
- }],
133
+ })],
133
134
 
134
135
  // Get UTXOs to use for input selection and final fee rate calculation
135
136
  getUtxos: ['validate', ({}, cbk) => getUtxos({lnd: args.lnd}, cbk)],
@@ -238,7 +239,7 @@ module.exports = (args, cbk) => {
238
239
  }],
239
240
 
240
241
  // Parse amounts and put together the final set of outputs
241
- finalOutputs: ['getMax', ({getMax}, cbk) => {
242
+ finalOutputs: ['getMax', asyncify(({getMax}) => {
242
243
  try {
243
244
  const outputs = args.addresses.map((address, i) => {
244
245
  const amount = args.amounts[i];
@@ -252,11 +253,11 @@ module.exports = (args, cbk) => {
252
253
  return {address, tokens: parseAmount({amount, variables}).tokens};
253
254
  });
254
255
 
255
- return cbk(null, outputs);
256
+ return outputs;
256
257
  } catch (err) {
257
- return cbk([400, err.message]);
258
+ throw [400, err.message];
258
259
  }
259
- }],
260
+ })],
260
261
 
261
262
  // Create a funded PSBT
262
263
  fund: [
@@ -1,4 +1,5 @@
1
1
  const asyncAuto = require('async/auto');
2
+ const asyncify = require('async/asyncify');
2
3
  const {getBlock} = require('ln-service');
3
4
  const {queryTransactions} = require('@alexbosworth/blockchain');
4
5
  const {returnResult} = require('asyncjs-util');
@@ -77,10 +78,10 @@ module.exports = (args, cbk) => {
77
78
  }],
78
79
 
79
80
  // Find the transactions in the block
80
- transactions: ['getBlock', ({getBlock}, cbk) => {
81
+ transactions: ['getBlock', asyncify(({getBlock}) => {
81
82
  // Exit early when there is no block to look through
82
83
  if (!getBlock.block) {
83
- return cbk(null, {transactions: []});
84
+ return {transactions: []};
84
85
  }
85
86
 
86
87
  try {
@@ -89,11 +90,11 @@ module.exports = (args, cbk) => {
89
90
  ids: args.ids,
90
91
  });
91
92
 
92
- return cbk(null, {transactions});
93
+ return {transactions};
93
94
  } catch (err) {
94
- return cbk([503, 'UnexpectedErrorParsingBlockTransactions', {err}]);
95
+ throw [503, 'UnexpectedErrorParsingBlockTransactions', {err}];
95
96
  }
96
- }],
97
+ })],
97
98
  },
98
99
  returnResult({reject, resolve, of: 'transactions'}, cbk));
99
100
  });
@@ -1,6 +1,7 @@
1
1
  const {createHash} = require('crypto');
2
2
 
3
3
  const asyncAuto = require('async/auto');
4
+ const asyncify = require('async/asyncify');
4
5
  const {broadcastChainTransaction} = require('ln-service');
5
6
  const {componentsOfTransaction} = require('@alexbosworth/blockchain');
6
7
  const {createChainAddress} = require('ln-service');
@@ -135,7 +136,7 @@ module.exports = ({id, lnd, request, vout}, cbk) => {
135
136
  recoveryScript: [
136
137
  'createAddress',
137
138
  'getNetwork',
138
- ({createAddress, getNetwork}, cbk) =>
139
+ asyncify(({createAddress, getNetwork}) =>
139
140
  {
140
141
  try {
141
142
  const {script} = outputScriptForAddress({
@@ -143,11 +144,11 @@ module.exports = ({id, lnd, request, vout}, cbk) => {
143
144
  network: getNetwork.network,
144
145
  });
145
146
 
146
- return cbk(null, {script});
147
+ return {script};
147
148
  } catch (err) {
148
- return cbk([503, 'FailedToParseRecoveryAddress', {err}]);
149
+ throw [503, 'FailedToParseRecoveryAddress', {err}];
149
150
  }
150
- }],
151
+ })],
151
152
 
152
153
  // Derive the sweep output, less the amount needed to pay for chain fees
153
154
  sweep: [
@@ -1,5 +1,6 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncEach = require('async/each');
3
+ const asyncify = require('async/asyncify');
3
4
  const asyncMapSeries = require('async/mapSeries');
4
5
  const asyncReflect = require('async/reflect');
5
6
  const {broadcastChainTransaction} = require('ln-service');
@@ -85,7 +86,7 @@ module.exports = (args, cbk) => {
85
86
  getUtxos: ['validate', ({}, cbk) => getUtxos({lnd: args.lnd}, cbk)],
86
87
 
87
88
  // Select the inputs and the count of outputs that reach the count
88
- plan: ['feeRate', 'getUtxos', ({feeRate, getUtxos}, cbk) => {
89
+ plan: ['feeRate', 'getUtxos', asyncify(({feeRate, getUtxos}) => {
89
90
  try {
90
91
  const plan = utxoSplitPlan({
91
92
  count: args.count,
@@ -95,11 +96,11 @@ module.exports = (args, cbk) => {
95
96
  utxos: getUtxos.utxos,
96
97
  });
97
98
 
98
- return cbk(null, plan);
99
+ return plan;
99
100
  } catch (err) {
100
- return cbk([400, err.message]);
101
+ throw [400, err.message];
101
102
  }
102
- }],
103
+ })],
103
104
 
104
105
  // Generate addresses
105
106
  getAddresses: ['plan', ({plan}, cbk) => {
@@ -25,6 +25,6 @@
25
25
  ],
26
26
  "priceProviders": ["coinbase", "coindesk", "coingecko"],
27
27
  "process": "bos",
28
- "rateProviders": ["coindesk", "coingecko"],
28
+ "rateProviders": ["coinbase", "coindesk", "coingecko"],
29
29
  "swapTypes": ["inbound", "outbound"]
30
30
  }