balanceofsatoshis 23.3.0 → 24.0.1

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,11 @@
1
1
  # Versions
2
2
 
3
+ ## 24.0.1
4
+
5
+ ### Breaking Changes
6
+
7
+ - Remove `change-channel-capacity`, `services`, `triggers`, and `use` commands
8
+
3
9
  ## 23.3.0
4
10
 
5
11
  - `call`: Add `subscribeToMessages` to listen for received onion messages
package/bos CHANGED
@@ -46,7 +46,6 @@ const services = importLazy('./services');
46
46
  const {swapTypes} = commandConstants;
47
47
  const swaps = importLazy('./swaps');
48
48
  const telegram = importLazy('./telegram');
49
- const triggers = importLazy('./triggers');
50
49
  const wallets = importLazy('./wallets');
51
50
  const {version} = importLazy('./package');
52
51
 
@@ -323,48 +322,6 @@ prog
323
322
  });
324
323
  })
325
324
 
326
- // Change the capacity of an existing channel
327
- .command('change-channel-capacity', 'Change the capacity of a channel')
328
- .visible(false)
329
- .help('Remote node must be prepared to receive this type of request')
330
- .help('The remote node should also run this same command after you propose')
331
- .option('--node <node_name>', 'Use saved node details instead of local node')
332
- .action((args, options, logger) => {
333
- return new Promise(async (resolve, reject) => {
334
- try {
335
- const {lnd} = await lndForNode(logger, options.node);
336
-
337
- const saved = await nodes.manageSavedNodes({
338
- logger,
339
- spawn,
340
- ask: await commands.interrogate({}),
341
- fs: {
342
- writeFile,
343
- getDirectoryFiles: readdir,
344
- getFile: readFile,
345
- getFileStatus: lstat,
346
- makeDirectory: mkdir,
347
- removeDirectory: rmdir,
348
- removeFile: unlink,
349
- },
350
- is_including_lnd_api: true,
351
- lock_credentials_to: [],
352
- network: (await lnSync.getNetwork({lnd})).network,
353
- });
354
-
355
- return paidServices.changeChannelCapacity({
356
- lnd,
357
- logger,
358
- ask: await commands.interrogate({}),
359
- nodes: saved.nodes,
360
- },
361
- responses.returnObject({exit, logger, reject, resolve}));
362
- } catch (err) {
363
- return logger.error({err}) && reject();
364
- }
365
- });
366
- })
367
-
368
325
  // Show a chart of chain fees paid
369
326
  .command('chart-chain-fees', 'Get a chart of chain fee expenses')
370
327
  .help('Show chart of mining fee expenditure over time')
@@ -1948,59 +1905,6 @@ prog
1948
1905
  });
1949
1906
  })
1950
1907
 
1951
- // Offer paid services
1952
- .command('services', 'Run a KeySend paid services server')
1953
- .visible(false)
1954
- .help('KeySend services are paid native Lightning Network services')
1955
- .option('--activity-fees', 'Share routing fees earned vs num fwds')
1956
- .option('--activity-volume', 'Share routing total volume amount')
1957
- .option('--connect', 'Enable requesting an inbound peer connection')
1958
- .option('--inbox-email-from', 'Inbox service email from address')
1959
- .option('--inbox-email-postmark-auth', 'Inbox service email to address')
1960
- .option('--inbox-email-to', 'Inbox service to email')
1961
- .option('--inbox-price', 'Required payment amount for inbox')
1962
- .option('--inbox-sms-from', 'Inbox service sms from number')
1963
- .option('--inbox-sms-to', 'Inbox service sms to number')
1964
- .option('--inbox-sms-twilio-sid', 'Inbox service Twilio account sid')
1965
- .option('--inbox-sms-twilio-auth', 'Inbox service Twilio auth token')
1966
- .option('--invoice', 'Enable creating custom invoices on demand')
1967
- .option('--node <node_name>', 'Saved node')
1968
- .option('--payer <pay_with_node_name>', 'Node to pay request responses with')
1969
- .option('--profile <profile>', 'Share a profile with info about your node')
1970
- .option('--profile-link <link>', 'Add a link to your profile', REPEATABLE)
1971
- .option('--network <public_key>', 'Share other service node key', REPEATABLE)
1972
- .option('--relay', 'Enable payments relay service', BOOL)
1973
- .action((args, options, logger) => {
1974
- return new Promise(async (resolve, reject) => {
1975
- try {
1976
- services.servicePaidRequests({
1977
- fetch,
1978
- logger,
1979
- activity_fees: options.activityFees,
1980
- activity_volume: options.activityVolume,
1981
- inbox_email_from: options.inboxEmailFrom,
1982
- inbox_email_to: options.inboxEmailTo,
1983
- inbox_postmark_api_key: options.inboxEmailPostmarkAuth,
1984
- inbox_price: options.inboxPrice,
1985
- inbox_sms_from_number: options.inboxSmsFrom,
1986
- inbox_sms_to_number: options.inboxSmsTo,
1987
- inbox_twilio_account_sid: options.inboxSmsTwilioSid,
1988
- inbox_twilio_auth_token: options.inboxSmsTwilioAuth,
1989
- is_connect_enabled: !!options.connect || undefined,
1990
- is_invoice_enabled: !!options.invoice || undefined,
1991
- is_relay_enabled: !!options.relay || undefined,
1992
- network_nodes: flatten([options.network].filter(n => !!n)),
1993
- node: options.node,
1994
- payer: options.payer || options.node,
1995
- profile: options.profile,
1996
- profile_urls: flatten([options.profileLink].filter(n => !!n)),
1997
- });
1998
- } catch (err) {
1999
- return logger.error({err}) && reject();
2000
- }
2001
- });
2002
- })
2003
-
2004
1908
  // Get a swap API key or inspect an existing one
2005
1909
  .command('swap-api-key', 'Purchase a swap API key or inspect a swap API key')
2006
1910
  .visible(false)
@@ -2226,25 +2130,6 @@ prog
2226
2130
  });
2227
2131
  })
2228
2132
 
2229
- // Manage triggers
2230
- .command('triggers', 'Manage event triggers')
2231
- .option('--node <name>', 'Node to manage triggers on')
2232
- .visible(false)
2233
- .action((args, options, logger) => {
2234
- return new Promise(async (resolve, reject) => {
2235
- try {
2236
- return triggers.manageTriggers({
2237
- logger,
2238
- ask: await commands.interrogate({}),
2239
- lnd: (await lndForNode(logger, options.node)).lnd,
2240
- },
2241
- responses.returnObject({exit, logger, reject, resolve}));
2242
- } catch (err) {
2243
- return logger.error({err}) && reject();
2244
- }
2245
- });
2246
- })
2247
-
2248
2133
  // Unlock wallet
2249
2134
  .command('unlock', 'Unlock wallet if locked')
2250
2135
  .help('Check if the wallet is locked, if so use a password file to unlock')
@@ -2261,33 +2146,6 @@ prog
2261
2146
  });
2262
2147
  })
2263
2148
 
2264
- // Use a paid service
2265
- .command('use', 'Use a paid KeySend service from a services provider')
2266
- .visible(false)
2267
- .help('KeySend services are paid native Lightning Network services')
2268
- .help('All communication with these services uses LN payments')
2269
- .help('Run services using the services command')
2270
- .argument('<server_id>', 'Public key of services-offering node')
2271
- .option('--node <node_name>', 'Saved node')
2272
- .action((args, options, logger) => {
2273
- return new Promise(async (resolve, reject) => {
2274
- try {
2275
- const {lnd} = await lndForNode(logger, options.node);
2276
-
2277
- return await services.usePaidService({
2278
- lnd,
2279
- logger,
2280
- ask: await commands.interrogate({}),
2281
- fs: {getFile: readFile},
2282
- network: (await lnSync.getNetwork({lnd})).network,
2283
- node: args.serverId,
2284
- });
2285
- } catch (err) {
2286
- return logger.error({err}) && reject();
2287
- }
2288
- });
2289
- })
2290
-
2291
2149
  // Get utxos
2292
2150
  .command('utxos', 'Get a list of utxos')
2293
2151
  .option('--confirmed', 'Return only confirmed utxos')
@@ -1,8 +1,9 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncMapSeries = require('async/mapSeries');
3
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
4
+ const {idForTransaction} = require('@alexbosworth/blockchain');
3
5
  const {resolutionType} = require('bolt03');
4
6
  const {returnResult} = require('asyncjs-util');
5
- const {Transaction} = require('bitcoinjs-lib');
6
7
 
7
8
  const {endpoints} = require('./blockstream');
8
9
 
@@ -90,12 +91,10 @@ module.exports = (args, cbk) => {
90
91
  // Decode transactions to derive spends
91
92
  spends: ['validate', ({}, cbk) => {
92
93
  const spends = args.transactions.map(({id, transaction}) => {
93
- return Transaction.fromHex(transaction).ins.map(({hash}, index) => {
94
- return {
95
- id: hash.reverse().toString('hex'),
96
- spent_by: id,
97
- vin: index,
98
- };
94
+ const {inputs} = componentsOfTransaction({transaction});
95
+
96
+ return inputs.map((input, index) => {
97
+ return {id: input.id, spent_by: id, vin: index};
99
98
  });
100
99
  });
101
100
 
@@ -219,11 +218,13 @@ module.exports = (args, cbk) => {
219
218
  return cbk(null, {});
220
219
  }
221
220
 
222
- const tx = Transaction.fromHex(getCommitmentTransaction);
221
+ const tx = componentsOfTransaction({
222
+ transaction: getCommitmentTransaction,
223
+ });
223
224
 
224
225
  const resolutions = getCloseSpends.map(({txid, vin}, i) => {
225
- const {transaction} = getTransactions.find(n => txid === n.id) || {};
226
- const {value} = tx.outs[i];
226
+ const {transaction} = getTransactions.find(n => txid === n.id);
227
+ const value = tx.outputs[i].tokens;
227
228
 
228
229
  if (!transaction) {
229
230
  return {value, type: 'unspent'};
@@ -231,7 +232,7 @@ module.exports = (args, cbk) => {
231
232
 
232
233
  return {
233
234
  value,
234
- transaction_id: Transaction.fromHex(transaction).getId(),
235
+ transaction_id: idForTransaction({transaction}).id,
235
236
  type: resolutionType({vin, transaction}).type,
236
237
  };
237
238
  });
@@ -1,7 +1,7 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncRetry = require('async/retry');
3
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
3
4
  const {returnResult} = require('asyncjs-util');
4
- const {Transaction} = require('bitcoinjs-lib');
5
5
 
6
6
  const {endpoints} = require('./blockstream');
7
7
 
@@ -72,7 +72,7 @@ module.exports = ({id, interval, network, request, retries}, cbk) => {
72
72
  }
73
73
 
74
74
  try {
75
- Transaction.fromHex(transaction);
75
+ componentsOfTransaction({transaction});
76
76
  } catch (err) {
77
77
  return cbk([503, 'ExpectedValidTransactionInResponse']);
78
78
  }
@@ -1,5 +1,6 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncMapSeries = require('async/mapSeries');
3
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
3
4
  const {formatTokens} = require('ln-sync');
4
5
  const {getChainTransactions} = require('ln-service');
5
6
  const {getChannels} = require('ln-service');
@@ -10,12 +11,10 @@ const {getTransactionRecord} = require('ln-sync');
10
11
  const {getUtxos} = require('ln-service');
11
12
  const moment = require('moment');
12
13
  const {returnResult} = require('asyncjs-util');
13
- const {Transaction} = require('bitcoinjs-lib');
14
14
 
15
15
  const describeChan = n => `${n.action} with ${(n.node || '' + n.with).trim()}`;
16
16
  const expiresAt = n => !!n ? moment(n).calendar() : undefined;
17
17
  const flatten = arr => [].concat(...arr);
18
- const {fromHex} = Transaction;
19
18
  const none = 0;
20
19
  const uniq = arr => Array.from(new Set(arr));
21
20
 
@@ -119,7 +118,11 @@ module.exports = (args, cbk) => {
119
118
  return;
120
119
  }
121
120
 
122
- const output = fromHex(tx.transaction).outs[locked.transaction_vout];
121
+ const {outputs} = componentsOfTransaction({
122
+ transaction: tx.transaction,
123
+ });
124
+
125
+ const output = outputs[locked.transaction_vout];
123
126
 
124
127
  // Exit early when the output is not found in the transaction
125
128
  if (!output) {
@@ -130,7 +133,7 @@ module.exports = (args, cbk) => {
130
133
  confirmation_count: tx.confirmation_count,
131
134
  lock_expires_at: locked.lock_expires_at,
132
135
  lock_id: locked.lock_id,
133
- tokens: output.value,
136
+ tokens: output.tokens,
134
137
  transaction_id: locked.transaction_id,
135
138
  transaction_vout: locked.transaction_vout,
136
139
  };
@@ -0,0 +1,7 @@
1
+ {
2
+ "networks": {
3
+ "btc": {"bech32": "bc", "p2pkh": 0, "p2sh": 5},
4
+ "btcregtest": {"bech32": "bcrt", "p2pkh": 111, "p2sh": 196},
5
+ "btctestnet": {"bech32": "tb", "p2pkh": 111, "p2sh": 196}
6
+ }
7
+ }
@@ -1,12 +1,19 @@
1
- const {address} = require('bitcoinjs-lib');
2
- const {networks} = require('bitcoinjs-lib');
1
+ const {decodeBase58Address} = require('@alexbosworth/blockchain');
2
+ const {decodeBech32Address} = require('@alexbosworth/blockchain');
3
+ const {p2pkhOutputScript} = require('@alexbosworth/blockchain');
4
+ const {p2shOutputScript} = require('@alexbosworth/blockchain');
5
+ const {p2trOutputScript} = require('@alexbosworth/blockchain');
6
+ const {p2wpkhOutputScript} = require('@alexbosworth/blockchain');
7
+ const {p2wshOutputScript} = require('@alexbosworth/blockchain');
8
+
9
+ const {networks} = require('./networks');
3
10
 
4
11
  const bufferAsHex = buffer => buffer.toString('hex');
12
+ const byteAsHex = n => n.toString(16).padStart(2, '0');
5
13
  const byteLengthForP2tr = 32;
6
- const {fromBech32} = address;
7
- const names = {btc: 'bitcoin', btcregtest: 'regtest', btctestnet: 'testnet'};
8
- const prefixForP2tr = '5120';
9
- const toOutputScript = (a, n) => address.toOutputScript(a, n).toString('hex');
14
+ const byteLengthForP2wpkh = 20;
15
+ const opVersionOffset = 0x50;
16
+ const versionSegwit = 0;
10
17
  const versionTaproot = 1;
11
18
 
12
19
  /** Get the output script for an address
@@ -25,32 +32,57 @@ const versionTaproot = 1;
25
32
  }
26
33
  */
27
34
  module.exports = ({address, network}) => {
35
+ const params = networks[network];
36
+
37
+ if (!params) {
38
+ throw new Error('UnsupportedNetworkToConvertAddressToOutputScript');
39
+ }
40
+
41
+ // Exit early when the address is a base58 address
28
42
  try {
29
- return {
30
- script: bufferAsHex(toOutputScript(address, networks[names[network]])),
31
- };
43
+ const {hash, version} = decodeBase58Address({address});
44
+
45
+ if (version === params.p2pkh) {
46
+ return {script: bufferAsHex(p2pkhOutputScript({hash}).script)};
47
+ }
48
+
49
+ if (version === params.p2sh) {
50
+ return {script: bufferAsHex(p2shOutputScript({hash}).script)};
51
+ }
52
+
53
+ throw new Error('InvalidNetworkToConvertAddressToOutputScript');
32
54
  } catch (err) {
33
- // Exit early when this is not a bech32 address
34
- try {
35
- fromBech32(address);
36
- } catch (_) {
55
+ // Continue on to bech32 decoding when the address is not base58
56
+ if (err.message === 'InvalidNetworkToConvertAddressToOutputScript') {
37
57
  throw err;
38
58
  }
59
+ }
39
60
 
40
- const {data, prefix, version} = fromBech32(address);
61
+ const {prefix, program, version} = decodeBech32Address({address});
41
62
 
42
- if (prefix !== networks[names[network]].bech32) {
43
- throw new Error('InvalidNetworkToConvertAddressToOutputScript');
44
- }
63
+ if (prefix !== params.bech32) {
64
+ throw new Error('InvalidNetworkToConvertAddressToOutputScript');
65
+ }
45
66
 
46
- if (version !== versionTaproot) {
47
- throw new Error('UnexpectedVersionOfAddressToConverToOutputScript');
48
- }
67
+ if (version === versionSegwit && program.length === byteLengthForP2wpkh) {
68
+ return {script: bufferAsHex(p2wpkhOutputScript({hash: program}).script)};
69
+ }
49
70
 
50
- if (data.length !== byteLengthForP2tr) {
51
- throw new Error('UnexpectedByteLengthForPayToTaprootAddress');
52
- }
71
+ if (version === versionSegwit) {
72
+ return {script: bufferAsHex(p2wshOutputScript({hash: program}).script)};
73
+ }
74
+
75
+ // Future segwit versions are OP_n followed by a push of the program
76
+ if (version !== versionTaproot) {
77
+ const push = byteAsHex(program.length);
78
+ const versionOp = byteAsHex(opVersionOffset + version);
53
79
 
54
- return {script: `${prefixForP2tr}${bufferAsHex(data)}`};
80
+ return {script: `${versionOp}${push}${bufferAsHex(program)}`};
55
81
  }
82
+
83
+ if (program.length !== byteLengthForP2tr) {
84
+ throw new Error('UnexpectedByteLengthForPayToTaprootAddress');
85
+ }
86
+
87
+ return {script: bufferAsHex(p2trOutputScript({hash: program}).script)};
56
88
  };
package/package.json CHANGED
@@ -28,7 +28,6 @@
28
28
  "bech32": "2.0.0",
29
29
  "bip66": "2.0.0",
30
30
  "bitcoinjs-lib": "6.1.7",
31
- "bolt01": "4.0.0",
32
31
  "bolt03": "2.0.0",
33
32
  "bolt04": "1.3.0",
34
33
  "bolt07": "2.0.0",
@@ -85,7 +84,6 @@
85
84
  "swaps",
86
85
  "tags",
87
86
  "telegram",
88
- "triggers",
89
87
  "wallets"
90
88
  ],
91
89
  "keywords": [
@@ -109,5 +107,5 @@
109
107
  "postpublish": "docker buildx build --platform linux/amd64,linux/arm64 -t alexbosworth/balanceofsatoshis -t alexbosworth/balanceofsatoshis:$npm_package_version --push .",
110
108
  "test": "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/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"
111
109
  },
112
- "version": "23.3.0"
110
+ "version": "24.0.1"
113
111
  }
package/services/index.js CHANGED
@@ -1,11 +1,4 @@
1
1
  const advertise = require('./advertise');
2
2
  const openBalancedChannel = require('./open_balanced_channel');
3
- const servicePaidRequests = require('./service_paid_requests');
4
- const usePaidService = require('./use_paid_service');
5
3
 
6
- module.exports = {
7
- advertise,
8
- openBalancedChannel,
9
- servicePaidRequests,
10
- usePaidService,
11
- };
4
+ module.exports = {advertise, openBalancedChannel};
@@ -1,85 +0,0 @@
1
- const {decodeTlvStream} = require('bolt01');
2
-
3
- const base64AsHex = base64 => Buffer.from(base64, 'base64').toString('hex');
4
- const processAfter = () => new Date(Date.now() - (1000*60*60)).toISOString();
5
-
6
- /** Derive key send request arguments from invoice details
7
-
8
- {
9
- [confirmed_at]: <Settled at ISO 8601 Date String>
10
- description: <Invoice Description String>
11
- [description_hash]: <Invoice Description Hash String>
12
- id: <Payment Hash Hex String>
13
- [is_canceled]: <Invoice is Canceled Bool>
14
- is_confirmed: <Invoice is Confirmed Bool>
15
- payments: [{
16
- is_confirmed: <HTLC is Confirmed Bool>
17
- messages: [{
18
- type: <Message Type String>
19
- value: <Hex Encoded Value String>
20
- }]
21
- }]
22
- received: <Tokens Received Rounded Down Number>
23
- secret: <Invoice Preimage Hex String>
24
- tokens: <Invoiced Tokens Rounded Down Number>
25
- }
26
-
27
- @returns
28
- {
29
- [arguments]: {
30
- id: <Payment Hash Hex String>
31
- messages: [{
32
- type: <Message Type String>
33
- value: <Hex Encoded Value String>
34
- }]
35
- received: <Tokens Received Rounded Down Number>
36
- }
37
- }
38
- */
39
- module.exports = (args) => {
40
- const {id} = args;
41
-
42
- // Exit early when there is a simulated keysend invoice
43
- if (!args.is_canceled && args.description_hash === args.secret) {
44
- try {
45
- const encoded = base64AsHex(args.description);
46
-
47
- return {
48
- arguments: {
49
- id,
50
- messages: decodeTlvStream({encoded}).records,
51
- received: args.tokens,
52
- },
53
- };
54
- } catch (err) {
55
- return {};
56
- }
57
- }
58
-
59
- // Exit early when the invoice is not settled
60
- if (!args.is_confirmed) {
61
- return {};
62
- }
63
-
64
- // Exit early when this was confirmed too long ago
65
- if (args.confirmed_at < processAfter()) {
66
- return {};
67
- }
68
-
69
- const htlcs = args.payments.filter(n => !!n.is_confirmed);
70
- const {received} = args;
71
-
72
- // Exit early when the invoice has no confirmed HTLCs
73
- if (!htlcs.length) {
74
- return {};
75
- }
76
-
77
- const [{messages}] = htlcs;
78
-
79
- // Exit early when the first HTLC has no messages
80
- if (!messages.length) {
81
- return {};
82
- }
83
-
84
- return {arguments: {id, messages, received}};
85
- };