balanceofsatoshis 17.1.2 → 17.3.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,13 @@
1
1
  # Versions
2
2
 
3
+ ## 17.3.0
4
+
5
+ - `open`: Add `commitment` flag to allow specifying a simplified_taproot type
6
+
7
+ ## 17.2.0
8
+
9
+ - `telegram`: Add `--use-rounded-units` to format amounts as rounded amounts
10
+
3
11
  ## 17.1.2
4
12
 
5
13
  - `recover-p2pk`: Fix recovering funds not sent to index 0
package/bos CHANGED
@@ -1241,9 +1241,11 @@ prog
1241
1241
  .help('Skip external option by specifying --internal-fund-at-fee-rate')
1242
1242
  .help('For trusted funding specify --type as private-trusted/public-trusted')
1243
1243
  .help('Trusted channel funding is not supported in LND 0.15.0 and below')
1244
+ .help('Simplified Taproot channels are not supported in LND 0.17.0 & below')
1244
1245
  .argument('<peer_public_keys...>', 'With nodes with public keys')
1245
1246
  .option('--amount <channel_capacity>', 'Capacities to open', REPEATABLE)
1246
1247
  .option('--avoid-broadcast', 'Avoid broadcasting channel open transaction')
1248
+ .option('--commitment <type>', 'default or simplified_taproot', REPEATABLE)
1247
1249
  .option('--coop-close-address <addr>', 'Coop-close address', REPEATABLE)
1248
1250
  .option('--external-funding', 'Use external funds for the channel open')
1249
1251
  .option('--give <give_amount>', 'Amount to gift to peer', REPEATABLE)
@@ -1260,6 +1262,7 @@ prog
1260
1262
  logger,
1261
1263
  ask: await commands.interrogate({}),
1262
1264
  capacities: collect(options.amount),
1265
+ commitments: collect(options.commitment),
1263
1266
  cooperative_close_addresses: collect(options.coopCloseAddress),
1264
1267
  fs: {getFile: readFile},
1265
1268
  gives: collect(options.give),
@@ -1922,6 +1925,7 @@ prog
1922
1925
  .option('--node <node_name>', 'Node to connect to Telegram', REPEATABLE)
1923
1926
  .option('--reset-api-key', 'Reset the Telegram API key')
1924
1927
  .option('--use-proxy <path>', 'Proxy agent to connect to Telegram')
1928
+ .option('--use-rounded-units', 'No leading zeros or fractions on amounts')
1925
1929
  .option('--use-small-units', 'Avoid showing leading zeros on amounts')
1926
1930
  .action((args, options, logger) => {
1927
1931
  return new Promise(async (resolve, reject) => {
@@ -1937,6 +1941,7 @@ prog
1937
1941
  makeDirectory: mkdir,
1938
1942
  },
1939
1943
  id: options.connect,
1944
+ is_rounded_units: options.useRoundedUnits || undefined,
1940
1945
  is_small_units: options.useSmallUnits || undefined,
1941
1946
  min_forward_tokens: options.ignoreForwardsBelow || undefined,
1942
1947
  min_rebalance_tokens: options.ignoreRebalancesBelow || undefined,
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "@alexbosworth/node-fetch": "2.6.2",
18
18
  "abort-controller": "3.0.0",
19
19
  "asciichart": "1.5.25",
20
- "async": "3.2.4",
20
+ "async": "3.2.5",
21
21
  "asyncjs-util": "1.2.12",
22
22
  "bech32": "2.0.0",
23
23
  "bip66": "1.1.5",
@@ -37,9 +37,9 @@
37
37
  "ini": "4.1.1",
38
38
  "inquirer": "9.2.11",
39
39
  "ln-accounting": "7.0.2",
40
- "ln-service": "57.0.1",
41
- "ln-sync": "5.2.3",
42
- "ln-telegram": "5.0.0",
40
+ "ln-service": "57.1.0",
41
+ "ln-sync": "6.0.0",
42
+ "ln-telegram": "6.0.0",
43
43
  "moment": "2.29.4",
44
44
  "paid-services": "5.0.5",
45
45
  "probing": "4.0.0",
@@ -54,7 +54,7 @@
54
54
  "description": "Lightning balance CLI",
55
55
  "devDependencies": {
56
56
  "invoices": "3.0.0",
57
- "ln-docker-daemons": "6.0.2",
57
+ "ln-docker-daemons": "6.0.3",
58
58
  "mock-lnd": "1.4.4"
59
59
  },
60
60
  "engines": {
@@ -82,5 +82,5 @@
82
82
  "postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis -t alexbosworth/balanceofsatoshis:$npm_package_version --push .",
83
83
  "test": "npx nyc@15.1.0 node --experimental-test-coverage --test test/arrays/*.js test/balances/*.js test/chain/*.js test/display/*.js test/encryption/*.js test/lnd/*.js test/network/*.js test/nodes/*.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"
84
84
  },
85
- "version": "17.1.2"
85
+ "version": "17.3.0"
86
86
  }
@@ -1,5 +1,6 @@
1
1
  const defaultChannelCapacity = 5e6;
2
2
  const defaultChannelDescription = 'bos open';
3
+ const isSimpleP2tr = (arr, i) => !!arr[i] && arr[i] === 'simplified_taproot';
3
4
  const isTrusted = type => ['private-trusted', 'public-trusted'].includes(type);
4
5
  const numericFeeRate = n => !!n && /^\d+$/.test(n) ? Number(n) : undefined;
5
6
  const privateTypes = ['private', 'private-trusted'];
@@ -11,6 +12,7 @@ const uniq = arr => Array.from(new Set(arr));
11
12
  {
12
13
  addresses: [<Address String>]
13
14
  capacities: [<Channel Capacity Tokens Number>]
15
+ commitments: [<Channel Commitment Types String>]
14
16
  gives: [<Give Tokens String>]
15
17
  nodes: [<Channel Partner Node Identity Public Key Hex String>]
16
18
  rates: [<Set Fee Rate String>]
@@ -27,6 +29,7 @@ const uniq = arr => Array.from(new Set(arr));
27
29
  description: <Channel Description String>
28
30
  [give_tokens]: <Give Tokens Number>
29
31
  is_private: <Channel Is Private Bool>
32
+ is_simplified_taproot: <Channel Is Taproot Bool>
30
33
  partner_public_key: <Channel Partner Identity Public Key Hex String>
31
34
  [rate]: <Set Fee Rate String>
32
35
  }]
@@ -43,6 +46,7 @@ module.exports = args => {
43
46
  fee_rate: numericFeeRate(args.rates[i]),
44
47
  give_tokens: !!args.gives[i] ? Number(args.gives[i]) : undefined,
45
48
  is_private: !!args.types[i] && privateTypes.includes(args.types[i]),
49
+ is_simplified_taproot: isSimpleP2tr(args.commitments, i),
46
50
  is_trusted_funding: !!args.types[i] && isTrusted(args.types[i]),
47
51
  node: args.saved[i] || undefined,
48
52
  partner_public_key: key,
@@ -48,6 +48,8 @@ const {fromHex} = Transaction;
48
48
  const interval = 1000;
49
49
  const {isArray} = Array;
50
50
  const isPublicKey = n => !!n && /^0[2-3][0-9A-F]{64}$/i.test(n);
51
+ const isUnknown = (a1, a2) => a1.findIndex(n => !a2.includes(n)) !== -1;
52
+ const knownCommits = ['default', 'simplified_taproot'];
51
53
  const knownTypes = ['private', 'private-trusted', 'public', 'public-trusted'];
52
54
  const lineBreak = '\n';
53
55
  const noInternalFundingVersions = ['0.11.0-beta', '0.11.1-beta'];
@@ -68,6 +70,7 @@ const utxoPollingTimes = 20;
68
70
  {
69
71
  ask: <Ask For Input Function>
70
72
  capacities: [<New Channel Capacity Tokens String>]
73
+ commitments: [<Channel Commitment Types String>]
71
74
  cooperative_close_addresses: [<Cooperative Close Address>]
72
75
  fs: {
73
76
  getFile: <Read File Contents Function> (path, cbk) => {}
@@ -103,6 +106,10 @@ module.exports = (args, cbk) => {
103
106
  return cbk([400, 'ExpectedChannelCapacitiesToOpenChannels']);
104
107
  }
105
108
 
109
+ if (!isArray(args.commitments)) {
110
+ return cbk([400, 'ExpectedArrayOfChannelOutputTypesToOpenChannels']);
111
+ }
112
+
106
113
  if (!isArray(args.cooperative_close_addresses)) {
107
114
  return cbk([400, 'ExpectedCooperativeCloseAddressesArray']);
108
115
  }
@@ -133,6 +140,7 @@ module.exports = (args, cbk) => {
133
140
 
134
141
  const closeAddrCount = args.cooperative_close_addresses.length;
135
142
  const hasCapacities = !!args.capacities.length;
143
+ const hasCommitments = !!args.commitments.length;
136
144
  const hasGives = !!args.gives.length;
137
145
  const hasFeeRates = !!args.set_fee_rates.length;
138
146
  const hasNodes = !!args.opening_nodes.length;
@@ -142,6 +150,10 @@ module.exports = (args, cbk) => {
142
150
  return cbk([400, 'CapacitiesMustBeSpecifiedForEveryPublicKey']);
143
151
  }
144
152
 
153
+ if (!!hasCommitments && publicKeysLength !== args.commitments.length) {
154
+ return cbk([400, 'CommitmentTypesMustBeSpecifiedForEveryPublicKey']);
155
+ }
156
+
145
157
  if (!!closeAddrCount && publicKeysLength !== closeAddrCount) {
146
158
  return cbk([400, 'MustSetCoopClosingAddressForEveryPublicKey']);
147
159
  }
@@ -174,6 +186,10 @@ module.exports = (args, cbk) => {
174
186
  return cbk([400, 'UnknownChannelType', {channel_types: knownTypes}]);
175
187
  }
176
188
 
189
+ if (isUnknown(args.commitments, knownCommits)) {
190
+ return cbk([400, 'UnknownCommitment', {commitments: knownCommits}]);
191
+ }
192
+
177
193
  if (!!args.types.length && args.types.length !== publicKeysLength) {
178
194
  return cbk([400, 'ChannelTypesMustBeSpecifiedForEveryPublicKey']);
179
195
  }
@@ -263,6 +279,7 @@ module.exports = (args, cbk) => {
263
279
  const {opens} = channelsFromArguments({
264
280
  capacities,
265
281
  addresses: args.cooperative_close_addresses,
282
+ commitments: args.commitments,
266
283
  gives: args.gives,
267
284
  nodes: args.public_keys,
268
285
  rates: args.set_fee_rates,
@@ -445,6 +462,7 @@ module.exports = (args, cbk) => {
445
462
  cooperative_close_address: channel.cooperative_close_address,
446
463
  give_tokens: channel.give_tokens,
447
464
  is_private: channel.is_private,
465
+ is_simplified_taproot: channel.is_simplified_taproot,
448
466
  is_trusted_funding: channel.is_trusted_funding,
449
467
  lnd: getLnds.find(n => n.node === node).lnd,
450
468
  partner_public_key: channel.partner_public_key,
@@ -457,6 +475,7 @@ module.exports = (args, cbk) => {
457
475
  cooperative_close_address: test.cooperative_close_address,
458
476
  give_tokens: test.give_tokens,
459
477
  is_private: test.is_private,
478
+ is_simplified_taproot: test.is_simplified_taproot,
460
479
  is_trusted_funding: test.is_trusted_funding,
461
480
  lnd: test.lnd,
462
481
  partner_public_key: test.partner_public_key,
@@ -12,6 +12,7 @@ const runTelegramBot = require('./run_telegram_bot');
12
12
  const defaultPaymentsBudget = 0;
13
13
  const isNumber = n => !isNaN(n);
14
14
  const restartDelayMs = 1000 * 60 * 3;
15
+ const roundedUnitsType = 'rounded';
15
16
  const smallUnitsType = 'full';
16
17
 
17
18
  /** Connect nodes to Telegram
@@ -25,7 +26,8 @@ const smallUnitsType = 'full';
25
26
  writeFile: <Write File Function>
26
27
  }
27
28
  [id]: <Authorized User Id Number>
28
- is_small_units: <Formatting Should Use Small Units Bool>
29
+ [is_rounded_units]: <Formatting Should Use Rounded Units Bool>
30
+ [is_small_units]: <Formatting Should Use Small Units Bool>
29
31
  logger: <Winston Logger Object>
30
32
  [min_forward_tokens]: <Minimum Forward Tokens Number>
31
33
  [min_rebalance_tokens]: <Minimum Rebalance Tokens Number>
@@ -103,12 +105,15 @@ module.exports = (args, cbk) => {
103
105
 
104
106
  // Set the units formatting
105
107
  setUnits: ['validate', ({}, cbk) => {
106
- // Exit early when using default units formatting
107
- if (!args.is_small_units) {
108
- return cbk();
108
+ // Set rounded value formatting type
109
+ if (!!args.is_rounded_units) {
110
+ process.env.PREFERRED_TOKENS_TYPE = roundedUnitsType;
109
111
  }
110
112
 
111
- process.env.PREFERRED_TOKENS_TYPE = smallUnitsType;
113
+ // Set small units value formatting type
114
+ if (!!args.is_small_units) {
115
+ process.env.PREFERRED_TOKENS_TYPE = smallUnitsType;
116
+ }
112
117
 
113
118
  return cbk();
114
119
  }],
@@ -79,6 +79,7 @@ test(`Open channels`, async () => {
79
79
  throw new Error('UnrecognizedParameter');
80
80
  },
81
81
  capacities: ['6*m'],
82
+ commitments: [],
82
83
  cooperative_close_addresses: [address],
83
84
  fs: {getFile: () => {}},
84
85
  gives: [1e5],
@@ -0,0 +1,132 @@
1
+ const {equal} = require('node:assert').strict;
2
+ const test = require('node:test');
3
+
4
+ const {addPeer} = require('ln-service');
5
+ const asyncAuto = require('async/auto');
6
+ const asyncEach = require('async/each');
7
+ const asyncRetry = require('async/retry');
8
+ const {createChainAddress} = require('ln-service');
9
+ const {fundPsbt} = require('ln-service');
10
+ const {getChannels} = require('ln-service');
11
+ const {getPendingChannels} = require('ln-service');
12
+ const {getWalletInfo} = require('ln-service');
13
+ const {openChannel} = require('ln-service');
14
+ const {signPsbt} = require('ln-service');
15
+ const {spawnLightningCluster} = require('ln-docker-daemons');
16
+ const {Transaction} = require('bitcoinjs-lib');
17
+
18
+ const {openChannels} = require('./../../peers');
19
+
20
+ const count = 100;
21
+ const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
22
+ const interval = 200;
23
+ const log = () => {};
24
+ const size = 2;
25
+ const times = 1000;
26
+
27
+ // Opening taproot channels should open channels with specified nodes
28
+ test(`Open taproot channels`, async () => {
29
+ const {kill, nodes} = await spawnLightningCluster({
30
+ size,
31
+ lnd_configuration: [
32
+ '--maxpendingchannels=10',
33
+ '--protocol.option-scid-alias',
34
+ '--protocol.simple-taproot-chans',
35
+ ],
36
+ });
37
+
38
+ const [{generate, id, lnd}, target] = nodes;
39
+
40
+ try {
41
+ await generate({count});
42
+
43
+ await asyncRetry({interval, times}, async () => {
44
+ await addPeer({lnd, public_key: target.id, socket: target.socket});
45
+
46
+ await asyncEach(nodes, async ({lnd}) => {
47
+ const chain = await getWalletInfo({lnd});
48
+
49
+ if (!chain.is_synced_to_chain || !chain.is_synced_to_graph) {
50
+ throw new Error('WaitingForSync');
51
+ }
52
+ });
53
+ });
54
+
55
+ const {address} = await asyncRetry({interval, times}, async () => {
56
+ return await createChainAddress({lnd});
57
+ });
58
+
59
+ // Propose a taproot channel
60
+ await asyncAuto({
61
+ // Propose the taproot channel to target
62
+ propose: async () => {
63
+ return asyncRetry({interval, times}, async () => {
64
+ await addPeer({lnd, public_key: target.id, socket: target.socket});
65
+
66
+ await openChannels({
67
+ lnd,
68
+ ask: async (args, cbk) => {
69
+ if (args.name === 'internal') {
70
+ return cbk({internal: false});
71
+ }
72
+
73
+ if (args.name === 'fund') {
74
+ const address = args.message.split(' ')[9];
75
+ const amount = args.message.split(' ')[7];
76
+
77
+ // Provide funding
78
+ const {psbt} = await fundPsbt({
79
+ lnd,
80
+ outputs: [{address, tokens: amount * 1e8}],
81
+ });
82
+
83
+ const signed = await signPsbt({lnd, psbt});
84
+
85
+ return cbk({fund: signed.psbt});
86
+ }
87
+
88
+ throw new Error('UnrecognizedParameter');
89
+ },
90
+ capacities: [],
91
+ cooperative_close_addresses: [],
92
+ commitments: ['simplified_taproot'],
93
+ fs: {getFile: () => {}},
94
+ gives: [],
95
+ logger: {info: log, error: log},
96
+ opening_nodes: [],
97
+ public_keys: [target.id],
98
+ request: () => {},
99
+ set_fee_rates: [],
100
+ types: ['private'],
101
+ });
102
+ });
103
+ },
104
+
105
+ // Generate blocks until the channel confirms
106
+ generate: async () => {
107
+ return await asyncRetry({interval, times}, async () => {
108
+ await generate({});
109
+
110
+ const {channels} = await getChannels({lnd});
111
+
112
+ if (!channels.length) {
113
+ throw new Error('Expected Channels');
114
+ }
115
+
116
+ const [channel] = channels;
117
+
118
+ equal(channel.type, 'simplified_taproot', 'Taproot channel opened');
119
+ });
120
+ },
121
+
122
+ // Stop the target node
123
+ finish: ['generate', 'propose', async ({}) => {
124
+ await target.kill({});
125
+ }],
126
+ });
127
+ } catch (err) {
128
+ equal(err, null, 'Expected no error');
129
+ }
130
+
131
+ await kill({});
132
+ });
@@ -106,6 +106,7 @@ test(`Open channels`, async () => {
106
106
  },
107
107
  capacities: [],
108
108
  cooperative_close_addresses: [],
109
+ commitments: [],
109
110
  fs: {getFile: () => {}},
110
111
  gives: [],
111
112
  logger: {info: log, error: log},
@@ -8,6 +8,7 @@ const makeArgs = overrides => {
8
8
  const args = {
9
9
  addresses: ['address'],
10
10
  capacities: [2],
11
+ commitments: [],
11
12
  gives: ['1'],
12
13
  nodes: [Buffer.alloc(33, 3).toString('hex')],
13
14
  rates: [],
@@ -33,6 +34,7 @@ const tests = [
33
34
  fee_rate: undefined,
34
35
  give_tokens: 1,
35
36
  is_private: true,
37
+ is_simplified_taproot: false,
36
38
  is_trusted_funding: false,
37
39
  node: undefined,
38
40
  partner_public_key: Buffer.alloc(33, 3).toString('hex'),
@@ -58,6 +60,7 @@ const tests = [
58
60
  fee_rate: undefined,
59
61
  give_tokens: undefined,
60
62
  is_private: false,
63
+ is_simplified_taproot: false,
61
64
  is_trusted_funding: false,
62
65
  node: undefined,
63
66
  partner_public_key: Buffer.alloc(33, 3).toString('hex'),
@@ -87,6 +90,7 @@ const tests = [
87
90
  fee_rate: 1,
88
91
  give_tokens: 3,
89
92
  is_private: true,
93
+ is_simplified_taproot: false,
90
94
  is_trusted_funding: false,
91
95
  node: 'savedA',
92
96
  partner_public_key: 'remoteNodeA',
@@ -102,6 +106,7 @@ const tests = [
102
106
  fee_rate: 2,
103
107
  give_tokens: 4,
104
108
  is_private: false,
109
+ is_simplified_taproot: false,
105
110
  is_trusted_funding: false,
106
111
  node: 'savedB',
107
112
  partner_public_key: 'remoteNodeB',