balanceofsatoshis 25.7.0 → 26.0.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 +27 -0
- package/README.md +26 -3
- package/balances/constants.json +10 -0
- package/balances/get_accounting_report.js +20 -6
- package/bos +68 -72
- package/package.json +11 -6
- package/routing/get_chain_fees_chart.js +0 -6
- package/swaps/cancel_unsigned_swap_in.js +94 -0
- package/swaps/constants.json +23 -10
- package/swaps/decode_swap_in_recovery.js +122 -0
- package/swaps/encode_swap_in_recovery.js +115 -0
- package/swaps/get_paid_service.js +41 -72
- package/swaps/get_swap_cost.js +3 -0
- package/swaps/subscribe_to_swap_in.js +147 -0
- package/swaps/swap_api_key.js +4 -2
- package/swaps/swap_in.js +1132 -493
- package/swaps/swap_out.js +366 -765
- package/swaps/wait_for_swap_in_payment.js +254 -0
- package/swaps/get_raw_recoveries.js +0 -154
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## 26.0.0
|
|
4
|
+
|
|
5
|
+
- `swap-api-key`: Add `--max-fee` to limit what is paid for an API key
|
|
6
|
+
- `swap-in`: Use the shared address swap in protocol of the swap service,
|
|
7
|
+
swapping in a deposit of the exact amount once it has 3 confirmations
|
|
8
|
+
- `swap-in`: Add `--max-fee-rate` to limit the swap fee in parts per million
|
|
9
|
+
- `swap-in`, `swap-out`: Add `--max-api-key-fee` to limit what is paid for a
|
|
10
|
+
swap service API key
|
|
11
|
+
- `swap-out`: Use the Taproot MuSig2 swap out protocol of the swap service,
|
|
12
|
+
like `swap` does
|
|
13
|
+
- `swap-out`: Add `--out` to select the peer or tag to increase inbound
|
|
14
|
+
liquidity from, with `--out-filter` formulas like `rebalance`
|
|
15
|
+
|
|
16
|
+
### Breaking Changes
|
|
17
|
+
|
|
18
|
+
- `increase-inbound-liquidity`: Rename command to `swap-out`
|
|
19
|
+
- `swap-in`: `--recovery` takes a shared address secret, not old recovery codes
|
|
20
|
+
- `swap-in`: `--refund-address` with `--recovery` refunds expired deposits
|
|
21
|
+
and unpaid swaps that timed out
|
|
22
|
+
- `swap-in`: Remove `--test-refund`
|
|
23
|
+
- `swap-in`: Use 25.7.0 to refund swaps in started with earlier versions
|
|
24
|
+
- `swap-out`: `--recovery` takes the restart code of the new swap protocol,
|
|
25
|
+
which `swap` also accepts, not the previous recovery code
|
|
26
|
+
- `swap-out`: Remove `--max-hours`, `--show-raw-recovery`, `--spend-address`
|
|
27
|
+
and `--spend-amount`
|
|
28
|
+
- `swap-out`: Rename `--with` to `--out`
|
|
29
|
+
|
|
3
30
|
## 25.7.0
|
|
4
31
|
|
|
5
32
|
- `accounting`: Add `lightning-fees` category to report the routing fees paid
|
package/README.md
CHANGED
|
@@ -123,9 +123,6 @@ bos inbound-liquidity
|
|
|
123
123
|
# Enforce rules on inbound channels
|
|
124
124
|
bos inbound-channel-rules
|
|
125
125
|
|
|
126
|
-
# Increase inbound liquidity to the node
|
|
127
|
-
bos increase-inbound-liquidity
|
|
128
|
-
|
|
129
126
|
# Increase the outbound liquidity of the node
|
|
130
127
|
bos increase-outbound-liquidity
|
|
131
128
|
|
|
@@ -171,6 +168,12 @@ bos server
|
|
|
171
168
|
# Stream a payment to a lnurl or lightning address in a series of payments
|
|
172
169
|
bos stream "amount" --lnurl "lnurl/lightning_address"
|
|
173
170
|
|
|
171
|
+
# Trade on-chain funds for off-chain funds to increase outbound liquidity
|
|
172
|
+
bos swap-in
|
|
173
|
+
|
|
174
|
+
# Trade off-chain funds for on-chain funds to increase inbound liquidity
|
|
175
|
+
bos swap-out
|
|
176
|
+
|
|
174
177
|
# Connect up to a Telegram bot
|
|
175
178
|
bos telegram
|
|
176
179
|
|
|
@@ -617,6 +620,7 @@ Formula amounts are supported in the following commands:
|
|
|
617
620
|
- `probe`
|
|
618
621
|
- `rebalance`
|
|
619
622
|
- `send`
|
|
623
|
+
- `swap-out`
|
|
620
624
|
|
|
621
625
|
When passing an amount you can pass a formula expression, and the following variables are
|
|
622
626
|
defined:
|
|
@@ -676,6 +680,25 @@ Example:
|
|
|
676
680
|
bos send <key> --amount "1*usd"
|
|
677
681
|
```
|
|
678
682
|
|
|
683
|
+
#### `swap-out`
|
|
684
|
+
|
|
685
|
+
Swap out defines variables for `--out-filter`:
|
|
686
|
+
|
|
687
|
+
- `capacity`: The total capacity with the peer
|
|
688
|
+
- `heights`: The set of heights of the channels with the peer
|
|
689
|
+
- `inbound_base_fee`: The base fee the peer is charging
|
|
690
|
+
- `inbound_fee_rate`: The fee rate the peer is charging
|
|
691
|
+
- `inbound_liquidity`: The inbound liquidity with the peer
|
|
692
|
+
- `outbound_liquidity`: The outbound liquidity with the peer
|
|
693
|
+
- `pending_payments`: The number of pending payments
|
|
694
|
+
|
|
695
|
+
Example:
|
|
696
|
+
|
|
697
|
+
```shell
|
|
698
|
+
// Swap out 1,000,000 with a peer of the tag that has under 2,000,000 inbound
|
|
699
|
+
bos swap-out --amount "1*m" --out "tag" --out-filter "inbound_liquidity < 2*m"
|
|
700
|
+
```
|
|
701
|
+
|
|
679
702
|
#### `transfer`
|
|
680
703
|
|
|
681
704
|
Transfer variables:
|
package/balances/constants.json
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"chainPricesFile": "chain_prices.json",
|
|
10
10
|
"coinbaseProvider": "coinbase",
|
|
11
|
+
"dayFormat": "YYYY-MM-DD",
|
|
11
12
|
"defaultCurrency": "BTC",
|
|
12
13
|
"defaultFiat": "USD",
|
|
13
14
|
"failedRequestErrors": ["UnexpectedErrorGettingCoinbaseCandles"],
|
|
@@ -45,5 +46,14 @@
|
|
|
45
46
|
"FailedToReplacePricesFile",
|
|
46
47
|
"FailedToWritePricesFile",
|
|
47
48
|
"UnsupportedPricesFileVersion"
|
|
49
|
+
],
|
|
50
|
+
"summaryHeadings": [
|
|
51
|
+
"Total",
|
|
52
|
+
"Asset",
|
|
53
|
+
"Report Date",
|
|
54
|
+
"Total Fiat",
|
|
55
|
+
"Category",
|
|
56
|
+
"Start Date",
|
|
57
|
+
"End Date"
|
|
48
58
|
]
|
|
49
59
|
}
|
|
@@ -6,6 +6,7 @@ const {chainRates} = require('@alexbosworth/fiat');
|
|
|
6
6
|
const {getAccountingReport} = require('ln-accounting');
|
|
7
7
|
const {getNetwork} = require('ln-sync');
|
|
8
8
|
const {harmonize} = require('ln-accounting');
|
|
9
|
+
const moment = require('moment');
|
|
9
10
|
const {returnResult} = require('asyncjs-util');
|
|
10
11
|
|
|
11
12
|
const categories = require('./accounting_categories');
|
|
@@ -13,6 +14,7 @@ const {chainBlocksFile} = require('./constants');
|
|
|
13
14
|
const {chainPricesFile} = require('./constants');
|
|
14
15
|
const chainPricesLogger = require('./chain_prices_logger');
|
|
15
16
|
const {coinbaseProvider} = require('./constants');
|
|
17
|
+
const {dayFormat} = require('./constants');
|
|
16
18
|
const {defaultCurrency} = require('./constants');
|
|
17
19
|
const {defaultFiat} = require('./constants');
|
|
18
20
|
const {fsMethods} = require('./constants');
|
|
@@ -20,21 +22,20 @@ const getRecordRate = require('./get_record_rate');
|
|
|
20
22
|
const guardChainRate = require('./guard_chain_rate');
|
|
21
23
|
const {homePath} = require('./../storage');
|
|
22
24
|
const {mainnet} = require('./constants');
|
|
23
|
-
const {monthNumbers} = require('./constants');
|
|
24
|
-
const {monthOffset} = require('./constants');
|
|
25
|
-
const {notFoundIndex} = require('./constants');
|
|
26
25
|
const rangeForDate = require('./range_for_date');
|
|
27
26
|
const {sortBy} = require('./../arrays');
|
|
27
|
+
const {summaryHeadings} = require('./constants');
|
|
28
28
|
const tableRowsFromCsv = require('./table_rows_from_csv');
|
|
29
29
|
|
|
30
30
|
const assetType = 'BTC';
|
|
31
|
+
const dayOf = n => moment.utc(n).format(dayFormat);
|
|
31
32
|
const empty = '';
|
|
32
33
|
const flatten = arr => [].concat(...arr);
|
|
33
34
|
const {isArray} = Array;
|
|
34
35
|
const {keys} = Object;
|
|
36
|
+
const lastDayBefore = n => moment.utc(n).subtract(1, 'ms').format(dayFormat);
|
|
35
37
|
const round = n => parseFloat(n).toFixed(2);
|
|
36
38
|
const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
|
|
37
|
-
const summaryHeadings = ['Total', 'Asset', 'Report Date', 'Total Fiat'];
|
|
38
39
|
|
|
39
40
|
/** Get an accounting report
|
|
40
41
|
|
|
@@ -254,7 +255,12 @@ module.exports = (args, cbk) => {
|
|
|
254
255
|
}],
|
|
255
256
|
|
|
256
257
|
// Clean rows for display if necessary
|
|
257
|
-
report: [
|
|
258
|
+
report: [
|
|
259
|
+
'accounting',
|
|
260
|
+
'dateRange',
|
|
261
|
+
'total',
|
|
262
|
+
({accounting, dateRange, total}, cbk) =>
|
|
263
|
+
{
|
|
258
264
|
// Exit early when there is no cleaning necessary
|
|
259
265
|
if (!!args.is_csv) {
|
|
260
266
|
return cbk(null, accounting);
|
|
@@ -280,7 +286,15 @@ module.exports = (args, cbk) => {
|
|
|
280
286
|
|
|
281
287
|
const summary = [
|
|
282
288
|
summaryHeadings,
|
|
283
|
-
[
|
|
289
|
+
[
|
|
290
|
+
total.tokens,
|
|
291
|
+
assetType,
|
|
292
|
+
new Date().toISOString(),
|
|
293
|
+
total.fiat,
|
|
294
|
+
args.category,
|
|
295
|
+
!dateRange.after ? empty : dayOf(dateRange.after),
|
|
296
|
+
!dateRange.before ? empty : lastDayBefore(dateRange.before),
|
|
297
|
+
],
|
|
284
298
|
];
|
|
285
299
|
|
|
286
300
|
return cbk(null, {rows, rows_summary: summary});
|
package/bos
CHANGED
|
@@ -72,7 +72,7 @@ prog
|
|
|
72
72
|
.help(`Rate providers: ${rateProviders.join(', ')}`)
|
|
73
73
|
.help('By default fiat rates after 2021-10-19 use chain data derived rates')
|
|
74
74
|
.help('Multiple --node arguments are supported to report on nodes together')
|
|
75
|
-
.help('Privacy note:
|
|
75
|
+
.help('Privacy note: other rates are looked up from third parties by time')
|
|
76
76
|
.option('--csv', 'Output a CSV')
|
|
77
77
|
.option('--date <day>', 'Show only records for specific date')
|
|
78
78
|
.option('--disable-fiat', 'Avoid looking up fiat conversions for records')
|
|
@@ -331,7 +331,6 @@ prog
|
|
|
331
331
|
// Show a chart of chain fees paid
|
|
332
332
|
.command('chart-chain-fees', 'Get a chart of chain fee expenses')
|
|
333
333
|
.help('Show chart of mining fee expenditure over time')
|
|
334
|
-
.help('Privacy note: this requests tx data from third parties')
|
|
335
334
|
.option('--days <days>', 'Chart over the past number of days', INT)
|
|
336
335
|
.option('--end <end_date>', 'End date for chart as YYYY-MM-DD', STRING)
|
|
337
336
|
.option('--no-color', 'Disable colors')
|
|
@@ -345,7 +344,6 @@ prog
|
|
|
345
344
|
end_date: options.end,
|
|
346
345
|
is_monochrome: !!options.noColor,
|
|
347
346
|
lnds: (await lnd.getLnds({logger, nodes: options.node})).lnds,
|
|
348
|
-
request: commands.simpleRequest,
|
|
349
347
|
start_date: options.start,
|
|
350
348
|
},
|
|
351
349
|
responses.returnChart({logger, reject, resolve, data: 'data'}));
|
|
@@ -1013,66 +1011,6 @@ prog
|
|
|
1013
1011
|
});
|
|
1014
1012
|
})
|
|
1015
1013
|
|
|
1016
|
-
// Increase inbound liquidity
|
|
1017
|
-
.command('increase-inbound-liquidity', 'Increase node inbound liquidity')
|
|
1018
|
-
.help('Spend down a channel to get inbound. Fee is an estimate, may be more')
|
|
1019
|
-
.help('If you want to control chain fee increases, use show-raw-recoveries')
|
|
1020
|
-
.help('Formulas supported for --amount like 5*m or 0.05*BTC for 5 million')
|
|
1021
|
-
.option('--address <out_address>', 'Out chain address to send funds out to')
|
|
1022
|
-
.option('--api-key <api_key>', 'Pre-paid API key to use')
|
|
1023
|
-
.option('--amount <amount>', 'Amount to increase inbound', STRING, '500*k')
|
|
1024
|
-
.option('--avoid <pubkey/chan/tag>', 'Avoid forwarding through', REPEATABLE)
|
|
1025
|
-
.option('--confs <confs>', 'Confs to consider reorg safe', INT, 1)
|
|
1026
|
-
.option('--dryrun', 'Only show cost estimate for increase')
|
|
1027
|
-
.option('--fast', 'Request swap server avoid batching delay')
|
|
1028
|
-
.option('--max-deposit <max_deposit>', 'Maximum deposit amount', INT, 5e4)
|
|
1029
|
-
.option('--max-fee <max_fee>', 'Maximum estimated fee tokens', INT, 3e4)
|
|
1030
|
-
.option('--max-hours <max_hours>', 'Maximum hours to wait', INT, 65)
|
|
1031
|
-
.option('--max-paths <max_paths>', 'Maximum paths to attempt', INT, 1)
|
|
1032
|
-
.option('--no-color', 'Mute all colors')
|
|
1033
|
-
.option('--node <node_name>', 'Increase inbound liquidity on saved node')
|
|
1034
|
-
.option('--recovery <recovery>', 'Recover in-progress swap')
|
|
1035
|
-
.option('--service-socket', 'Specify a custom swap service address')
|
|
1036
|
-
.option('--spend-address', 'Send an exact amount to a specific address')
|
|
1037
|
-
.option('--spend-amount', 'Exact amount to send to a specific address')
|
|
1038
|
-
.option('--show-raw-recovery', 'Show raw recovery transactions')
|
|
1039
|
-
.option('--with <peer>', 'Public key of peer to increase liquidity from')
|
|
1040
|
-
.action((args, options, logger) => {
|
|
1041
|
-
return new Promise(async (resolve, reject) => {
|
|
1042
|
-
try {
|
|
1043
|
-
return swaps.swapOut({
|
|
1044
|
-
fetch,
|
|
1045
|
-
logger,
|
|
1046
|
-
api_key: options.apiKey || undefined,
|
|
1047
|
-
avoid: flatten([options.avoid].filter(n => !!n)),
|
|
1048
|
-
confs: options.confs,
|
|
1049
|
-
fs: {getFile: readFile},
|
|
1050
|
-
is_fast: options.fast || false,
|
|
1051
|
-
is_raw_recovery_shown: options.showRawRecovery || undefined,
|
|
1052
|
-
is_dry_run: options.dryrun || false,
|
|
1053
|
-
lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
|
|
1054
|
-
max_deposit: options.maxDeposit,
|
|
1055
|
-
max_fee: options.maxFee,
|
|
1056
|
-
max_paths: options.maxPaths || undefined,
|
|
1057
|
-
max_wait_blocks: Math.ceil((options.maxHours) * 60 / 10),
|
|
1058
|
-
node: options.node || undefined,
|
|
1059
|
-
out_address: options.address || undefined,
|
|
1060
|
-
peer: options.with || undefined,
|
|
1061
|
-
recovery: options.recovery,
|
|
1062
|
-
request: commands.fetchRequest({fetch}),
|
|
1063
|
-
socket: options.serviceSocket || undefined,
|
|
1064
|
-
spend_address: options.spendAddress || undefined,
|
|
1065
|
-
spend_tokens: options.spendAmount || undefined,
|
|
1066
|
-
timeout: 1000 * 60 * 60 * 10,
|
|
1067
|
-
tokens: accounting.parseAmount({amount: options.amount}).tokens,
|
|
1068
|
-
},
|
|
1069
|
-
responses.returnObject({exit, logger, reject, resolve}));
|
|
1070
|
-
} catch (err) {
|
|
1071
|
-
return logger.error({err}) && reject();
|
|
1072
|
-
}
|
|
1073
|
-
});
|
|
1074
|
-
})
|
|
1075
|
-
|
|
1076
1014
|
// Increase outbound liquidity
|
|
1077
1015
|
.command('increase-outbound-liquidity', 'Move on-chain funds off-chain')
|
|
1078
1016
|
.help('Open a new channel to add more off-chain liquidity')
|
|
@@ -1264,7 +1202,7 @@ prog
|
|
|
1264
1202
|
.option('--above <tokens>', 'Return amount above watermark', INT)
|
|
1265
1203
|
.option('--fast', 'Avoid any server batching wait time')
|
|
1266
1204
|
.option('--node <node_name>', 'Node to get liquidity cost')
|
|
1267
|
-
.option('--service-socket', 'Specify a custom swap service address')
|
|
1205
|
+
.option('--service-socket <socket>', 'Specify a custom swap service address')
|
|
1268
1206
|
.action((args, options, logger) => {
|
|
1269
1207
|
return new Promise(async (resolve, reject) => {
|
|
1270
1208
|
try {
|
|
@@ -2008,10 +1946,11 @@ prog
|
|
|
2008
1946
|
.command('swap-api-key', 'Purchase a swap API key or inspect a swap API key')
|
|
2009
1947
|
.visible(false)
|
|
2010
1948
|
.option('--api-key <api_key>', 'Hex encoded full swap API key')
|
|
2011
|
-
.option('--purchase', 'Purchase a new swap API key')
|
|
2012
1949
|
.option('--macaroon <macaroon>', 'Hex encoded macaroon of swap API key')
|
|
1950
|
+
.option('--max-fee <max_fee>', 'Max tokens to pay for the API key', INT)
|
|
2013
1951
|
.option('--node <node_name>', 'Node to use to pay for API key')
|
|
2014
1952
|
.option('--preimage <preimage>', 'Hex encoded preimage of swap API key')
|
|
1953
|
+
.option('--purchase', 'Purchase a new swap API key')
|
|
2015
1954
|
.option('--service-socket <swap_service_socket>', 'host:port for service')
|
|
2016
1955
|
.action((args, options, logger) => {
|
|
2017
1956
|
return new Promise(async (resolve, reject) => {
|
|
@@ -2023,6 +1962,7 @@ prog
|
|
|
2023
1962
|
is_purchase: options.purchase,
|
|
2024
1963
|
lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
|
|
2025
1964
|
macaroon: options.macaroon,
|
|
1965
|
+
max_fee: options.maxFee,
|
|
2026
1966
|
node: options.node,
|
|
2027
1967
|
preimage: options.preimage,
|
|
2028
1968
|
socket: options.serviceSocket,
|
|
@@ -2056,15 +1996,17 @@ prog
|
|
|
2056
1996
|
// Create submarine swap to convert on-chain funds to off-chain
|
|
2057
1997
|
.command('swap-in', 'Trade on-chain coins for off-chain via submarine swap')
|
|
2058
1998
|
.argument('[amount]', 'Amount to receive', INT, 1e6)
|
|
1999
|
+
.help('Use the recovery secret of a swap with --refund-address to refund it')
|
|
2059
2000
|
.option('--api-key <api_key>', 'Pre-paid API key to use', hexMatch)
|
|
2060
2001
|
.option('--in <peer>', 'Request receiving through a specific peer')
|
|
2002
|
+
.option('--max-api-key-fee <fee>', 'Max tokens to pay for API key', INT)
|
|
2061
2003
|
.option('--max-fee <max_fee>', 'Max fee in tokens to pay', INT, 4000)
|
|
2004
|
+
.option('--max-fee-rate <ppm>', 'Max fee rate in parts per million', INT)
|
|
2062
2005
|
.option('--no-color', 'Mute all colors')
|
|
2063
2006
|
.option('--node <node_name>', 'Node to receive funds on')
|
|
2064
|
-
.option('--recovery <
|
|
2065
|
-
.option('--refund-address <
|
|
2007
|
+
.option('--recovery <recovery>', 'Reuse the shared address', hexMatch)
|
|
2008
|
+
.option('--refund-address <address>', 'Refund expired deposits/unpaid swaps')
|
|
2066
2009
|
.option('--service-socket <swap_service_socket>', 'host:port for service')
|
|
2067
|
-
.option('--test-refund', 'Reduce refund timeout height to test refund')
|
|
2068
2010
|
.action((args, options, logger) => {
|
|
2069
2011
|
return new Promise(async (resolve, reject) => {
|
|
2070
2012
|
try {
|
|
@@ -2072,15 +2014,13 @@ prog
|
|
|
2072
2014
|
fetch,
|
|
2073
2015
|
logger,
|
|
2074
2016
|
api_key: options.apiKey || undefined,
|
|
2075
|
-
fs: {getFile: readFile},
|
|
2076
2017
|
in_through: options.in || undefined,
|
|
2077
|
-
is_refund_test: options.testRefund,
|
|
2078
2018
|
lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
|
|
2019
|
+
max_api_key_fee: options.maxApiKeyFee,
|
|
2079
2020
|
max_fee: options.maxFee,
|
|
2080
|
-
|
|
2021
|
+
max_fee_rate: options.maxFeeRate,
|
|
2081
2022
|
recovery: options.recovery,
|
|
2082
2023
|
refund_address: options.refundAddress,
|
|
2083
|
-
request: commands.simpleRequest,
|
|
2084
2024
|
socket: options.serviceSocket || undefined,
|
|
2085
2025
|
tokens: args.amount,
|
|
2086
2026
|
},
|
|
@@ -2091,6 +2031,62 @@ prog
|
|
|
2091
2031
|
});
|
|
2092
2032
|
})
|
|
2093
2033
|
|
|
2034
|
+
// Trade off-chain funds for on-chain funds through a swap out
|
|
2035
|
+
.command('swap-out', 'Trade off-chain coins for on-chain with swap service')
|
|
2036
|
+
.help('Spend down a channel to get inbound. Fee is an estimate, may be more')
|
|
2037
|
+
.help('Formulas supported for --amount like 5*m or 0.05*BTC for 5 million')
|
|
2038
|
+
.help('--out can take a tag, --out-filter narrows the peers of the tag')
|
|
2039
|
+
.help('--out-filter vars: CAPACITY/HEIGHTS/INBOUND_LIQUIDITY')
|
|
2040
|
+
.help('--out-filter vars: OUTBOUND_LIQUIDITY/PENDING_PAYMENTS')
|
|
2041
|
+
.help('--out-filter vars: INBOUND_BASE_FEE/INBOUND_FEE_RATE')
|
|
2042
|
+
.option('--address <out_address>', 'Out chain address to send funds out to')
|
|
2043
|
+
.option('--amount <amount>', 'Amount to increase inbound', STRING, '500*k')
|
|
2044
|
+
.option('--api-key <api_key>', 'Pre-paid API key to use')
|
|
2045
|
+
.option('--avoid <pubkey/chan/tag>', 'Avoid forwarding through', REPEATABLE)
|
|
2046
|
+
.option('--confs <confs>', 'Confs to consider reorg safe', INT, 1)
|
|
2047
|
+
.option('--dryrun', 'Only show cost estimate for increase')
|
|
2048
|
+
.option('--fast', 'Request swap server avoid batching delay')
|
|
2049
|
+
.option('--max-api-key-fee <fee>', 'Max tokens to pay for API key', INT)
|
|
2050
|
+
.option('--max-deposit <max_deposit>', 'Maximum deposit amount', INT, 5e4)
|
|
2051
|
+
.option('--max-fee <max_fee>', 'Maximum estimated fee tokens', INT, 3e4)
|
|
2052
|
+
.option('--max-paths <max_paths>', 'Maximum paths to attempt', INT, 1)
|
|
2053
|
+
.option('--no-color', 'Mute all colors')
|
|
2054
|
+
.option('--node <node_name>', 'Increase inbound liquidity on saved node')
|
|
2055
|
+
.option('--out <peer>', 'Peer or tag to increase inbound liquidity from')
|
|
2056
|
+
.option('--out-filter <out_filter>', 'Filter outbound peer/tag', REPEATABLE)
|
|
2057
|
+
.option('--recovery <recovery>', 'Recover in-progress swap')
|
|
2058
|
+
.option('--service-socket <socket>', 'Specify a custom swap service address')
|
|
2059
|
+
.action((args, options, logger) => {
|
|
2060
|
+
return new Promise(async (resolve, reject) => {
|
|
2061
|
+
try {
|
|
2062
|
+
return swaps.swapOut({
|
|
2063
|
+
fetch,
|
|
2064
|
+
logger,
|
|
2065
|
+
api_key: options.apiKey || undefined,
|
|
2066
|
+
avoid: flatten([options.avoid].filter(n => !!n)),
|
|
2067
|
+
confs: options.confs,
|
|
2068
|
+
fs: {getFile: readFile},
|
|
2069
|
+
is_dry_run: options.dryrun || false,
|
|
2070
|
+
is_fast: options.fast || false,
|
|
2071
|
+
lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
|
|
2072
|
+
max_api_key_fee: options.maxApiKeyFee,
|
|
2073
|
+
max_deposit: options.maxDeposit,
|
|
2074
|
+
max_fee: options.maxFee,
|
|
2075
|
+
max_paths: options.maxPaths || undefined,
|
|
2076
|
+
out_address: options.address || undefined,
|
|
2077
|
+
out_filters: flatten([options.outFilter].filter(n => !!n)),
|
|
2078
|
+
peer: options.out || undefined,
|
|
2079
|
+
recovery: options.recovery,
|
|
2080
|
+
socket: options.serviceSocket || undefined,
|
|
2081
|
+
tokens: accounting.parseAmount({amount: options.amount}).tokens,
|
|
2082
|
+
},
|
|
2083
|
+
responses.returnObject({exit, logger, reject, resolve}));
|
|
2084
|
+
} catch (err) {
|
|
2085
|
+
return logger.error({err}) && reject();
|
|
2086
|
+
}
|
|
2087
|
+
});
|
|
2088
|
+
})
|
|
2089
|
+
|
|
2094
2090
|
// Adjust the set of tagged nodes
|
|
2095
2091
|
.command('tags', 'View or adjust the set of tagged nodes')
|
|
2096
2092
|
.help('Tags can be used in other commands via --tag and --avoid options')
|
package/package.json
CHANGED
|
@@ -29,20 +29,20 @@
|
|
|
29
29
|
"bolt07": "2.0.0",
|
|
30
30
|
"colorette": "2.0.20",
|
|
31
31
|
"csv-parse": "7.0.3",
|
|
32
|
-
"goldengate": "
|
|
32
|
+
"goldengate": "17.0.0",
|
|
33
33
|
"grammy": "1.46.0",
|
|
34
34
|
"import-lazy": "4.0.0",
|
|
35
35
|
"ini": "7.0.0",
|
|
36
|
-
"inquirer": "14.
|
|
36
|
+
"inquirer": "14.3.0",
|
|
37
37
|
"ln-accounting": "11.0.0",
|
|
38
38
|
"ln-service": "60.3.0",
|
|
39
39
|
"ln-sync": "8.1.0",
|
|
40
40
|
"ln-telegram": "8.2.0",
|
|
41
41
|
"moment": "2.31.0",
|
|
42
|
-
"paid-services": "
|
|
42
|
+
"paid-services": "11.0.0",
|
|
43
43
|
"probing": "7.1.0",
|
|
44
44
|
"qrcode-terminal": "0.12.0",
|
|
45
|
-
"sanitize-filename": "1.6.
|
|
45
|
+
"sanitize-filename": "1.6.5",
|
|
46
46
|
"socks-proxy-agent": "10.1.0",
|
|
47
47
|
"table": "6.10.1",
|
|
48
48
|
"tiny-secp256k1": "2.2.5",
|
|
@@ -50,8 +50,13 @@
|
|
|
50
50
|
},
|
|
51
51
|
"description": "Lightning balance CLI",
|
|
52
52
|
"devDependencies": {
|
|
53
|
+
"@grpc/grpc-js": "1.14.7",
|
|
54
|
+
"@grpc/proto-loader": "0.8.1",
|
|
53
55
|
"invoices": "6.3.3",
|
|
54
|
-
"ln-docker-daemons": "8.1.4"
|
|
56
|
+
"ln-docker-daemons": "8.1.4",
|
|
57
|
+
"macaroon": "3.0.4",
|
|
58
|
+
"p2tr": "3.0.0",
|
|
59
|
+
"psbt": "7.0.1"
|
|
55
60
|
},
|
|
56
61
|
"engines": {
|
|
57
62
|
"node": ">=22"
|
|
@@ -103,5 +108,5 @@
|
|
|
103
108
|
"reinstall-dependencies": "rm -rf node_modules package-lock.json && npm i",
|
|
104
109
|
"test": "node --experimental-test-coverage --test test/arrays/*.js test/balances/*.js test/chain/*.js test/commands/*.js test/display/*.js test/encryption/*.js test/lnd/*.js test/lnurl/*.js test/network/*.js test/nodes/*.js test/offchain/*.js test/peers/*.js test/responses/*.js test/routing/*.js test/services/*.js test/swaps/*.js test/tags/*.js test/telegram/*.js test/wallets/*.js"
|
|
105
110
|
},
|
|
106
|
-
"version": "
|
|
111
|
+
"version": "26.0.0"
|
|
107
112
|
}
|
|
@@ -30,7 +30,6 @@ const parseDate = n => Date.parse(n);
|
|
|
30
30
|
[end_date]: <End Date YYYY-MM-DD String>
|
|
31
31
|
is_monochrome: <Omit Colors Bool>
|
|
32
32
|
lnds: [<Authenticated LND API Object>]
|
|
33
|
-
request: <Request Function>
|
|
34
33
|
[start_date]: <Start Date YYYY-MM-DD String>
|
|
35
34
|
}
|
|
36
35
|
|
|
@@ -50,10 +49,6 @@ module.exports = (args, cbk) => {
|
|
|
50
49
|
return cbk([400, 'ExpectedLndToGetChainFeesChart']);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
if (!args.request) {
|
|
54
|
-
return cbk([400, 'ExpectedRequestFunctionToGetChainFees']);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
52
|
// Exit early when there is no end date and no start date
|
|
58
53
|
if (!args.end_date && !args.start_date) {
|
|
59
54
|
return cbk();
|
|
@@ -154,7 +149,6 @@ module.exports = (args, cbk) => {
|
|
|
154
149
|
lnd,
|
|
155
150
|
after: start.toISOString(),
|
|
156
151
|
network: res.network,
|
|
157
|
-
request: args.request,
|
|
158
152
|
},
|
|
159
153
|
cbk);
|
|
160
154
|
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const asyncAuto = require('async/auto');
|
|
2
|
+
const asyncReflect = require('async/reflect');
|
|
3
|
+
const {cancelHodlInvoice} = require('ln-service');
|
|
4
|
+
const {cancelSwapIn} = require('goldengate');
|
|
5
|
+
const {returnResult} = require('asyncjs-util');
|
|
6
|
+
|
|
7
|
+
const isHash = n => !!n && /^[0-9A-F]{64}$/i.test(n);
|
|
8
|
+
|
|
9
|
+
/** Cancel a swap in that is not signed yet, along with its swap invoice
|
|
10
|
+
|
|
11
|
+
{
|
|
12
|
+
id: <Swap Hash Hex String>
|
|
13
|
+
lnd: <Authenticated LND API Object>
|
|
14
|
+
logger: <Winston Logger Object>
|
|
15
|
+
metadata: <Authentication Metadata Object>
|
|
16
|
+
service: <Swap Service Object>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@returns via cbk or Promise
|
|
20
|
+
*/
|
|
21
|
+
module.exports = (args, cbk) => {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
return asyncAuto({
|
|
24
|
+
// Check arguments
|
|
25
|
+
validate: cbk => {
|
|
26
|
+
if (!isHash(args.id)) {
|
|
27
|
+
return cbk([400, 'ExpectedSwapHashToCancelUnsignedSwapIn']);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!args.lnd) {
|
|
31
|
+
return cbk([400, 'ExpectedLndToCancelUnsignedSwapIn']);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!args.logger) {
|
|
35
|
+
return cbk([400, 'ExpectedLoggerToCancelUnsignedSwapIn']);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!args.metadata) {
|
|
39
|
+
return cbk([400, 'ExpectedAuthMetadataToCancelUnsignedSwapIn']);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!args.service) {
|
|
43
|
+
return cbk([400, 'ExpectedServiceToCancelUnsignedSwapIn']);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return cbk();
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Cancel the swap with the service, releasing its deposits
|
|
50
|
+
cancelSwap: ['validate', asyncReflect(({}, cbk) => {
|
|
51
|
+
return cancelSwapIn({
|
|
52
|
+
id: args.id,
|
|
53
|
+
metadata: args.metadata,
|
|
54
|
+
service: args.service,
|
|
55
|
+
},
|
|
56
|
+
cbk);
|
|
57
|
+
})],
|
|
58
|
+
|
|
59
|
+
// Cancel the swap invoice so that it can no longer be paid
|
|
60
|
+
cancelInvoice: ['cancelSwap', asyncReflect(({}, cbk) => {
|
|
61
|
+
return cancelHodlInvoice({id: args.id, lnd: args.lnd}, cbk);
|
|
62
|
+
})],
|
|
63
|
+
|
|
64
|
+
// Report the cancel of the swap
|
|
65
|
+
reportSwap: ['cancelSwap', ({cancelSwap}, cbk) => {
|
|
66
|
+
// Exit early when the swap could not be canceled
|
|
67
|
+
if (!!cancelSwap.error) {
|
|
68
|
+
args.logger.error({failed_to_cancel_swap_in: cancelSwap.error});
|
|
69
|
+
|
|
70
|
+
return cbk();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
args.logger.info({canceled_swap_in: args.id});
|
|
74
|
+
|
|
75
|
+
return cbk();
|
|
76
|
+
}],
|
|
77
|
+
|
|
78
|
+
// Report a failure to cancel the swap invoice
|
|
79
|
+
reportInvoice: ['cancelInvoice', ({cancelInvoice}, cbk) => {
|
|
80
|
+
// Exit early when the swap invoice was canceled
|
|
81
|
+
if (!cancelInvoice.error) {
|
|
82
|
+
return cbk();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
args.logger.error({
|
|
86
|
+
failed_to_cancel_swap_in_invoice: cancelInvoice.error,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return cbk();
|
|
90
|
+
}],
|
|
91
|
+
},
|
|
92
|
+
returnResult({reject, resolve}, cbk));
|
|
93
|
+
});
|
|
94
|
+
};
|
package/swaps/constants.json
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"cltvDeltaBuffer": 3,
|
|
3
3
|
"estimatedSweepVbytes": 153,
|
|
4
|
+
"externalPayUpdates": [
|
|
5
|
+
"external_funding_pay_to_fund_swap_offchain",
|
|
6
|
+
"external_pay_deposit_request"
|
|
7
|
+
],
|
|
4
8
|
"fastDelayMinutes": 1,
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
"invoiceNetworks": {
|
|
10
|
+
"btc": "bitcoin",
|
|
11
|
+
"btcregtest": "regtest",
|
|
12
|
+
"btcsignet": "signet",
|
|
13
|
+
"btctestnet": "testnet",
|
|
14
|
+
"btctestnet4": "testnet"
|
|
15
|
+
},
|
|
8
16
|
"maxDepositTokens": 50000,
|
|
9
17
|
"maxExecutionFeeTokens": 1000,
|
|
10
|
-
"maxFeeMultiplier": 1000,
|
|
11
18
|
"maxFeeRate": 0.06,
|
|
12
19
|
"maxPathfindingMs": 1200000,
|
|
13
|
-
"maxRouteFailProbability": 1000000,
|
|
14
20
|
"maxRoutingFeeDenominator": 100,
|
|
15
|
-
"minCltvDelta": 16,
|
|
16
21
|
"minConfs": 1,
|
|
17
|
-
"minSweepConfs": 1,
|
|
18
22
|
"minutesPerBlock": 10,
|
|
19
|
-
"
|
|
23
|
+
"sharedAddressKeyFamily": 42060,
|
|
20
24
|
"slowDelayMinutes": 30,
|
|
21
|
-
"
|
|
22
|
-
"
|
|
25
|
+
"swapInCosignQuietMs": 30000,
|
|
26
|
+
"swapInDepositConfs": 3,
|
|
27
|
+
"swapInEventsMinAliveMs": 60000,
|
|
28
|
+
"swapInEventsRetryMs": 10000,
|
|
29
|
+
"swapInEventsRetryStepMs": 1000,
|
|
30
|
+
"swapInMaxTimeoutBlocks": 2016,
|
|
31
|
+
"swapInPaymentTimeoutSeconds": 60,
|
|
32
|
+
"swapInRefundConfTarget": 6,
|
|
33
|
+
"swapInSweepRequestsWaitMs": 180000,
|
|
34
|
+
"swapInUtxosCount": 1,
|
|
35
|
+
"swapTypes": ["inbound", "outbound"]
|
|
23
36
|
}
|