paid-services 10.3.2 → 10.3.3

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,6 +1,6 @@
1
1
  # Versions
2
2
 
3
- ## Version 10.3.2
3
+ ## Version 10.3.3
4
4
 
5
5
  - `getOfferInvoice`: Add support for offer paths that start at the payer
6
6
  - `serviceSupportOffer`: Add support for reply paths that start at the node
@@ -0,0 +1,7 @@
1
+ {
2
+ "btc": "bc",
3
+ "btcregtest": "bcrt",
4
+ "btcsignet": "tb",
5
+ "btctestnet": "tb",
6
+ "btctestnet4": "tb"
7
+ }
package/config/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ const bech32Prefixes = require('./bech32_prefixes');
1
2
  const invoiceNetwork = require('./invoice_network');
2
3
  const isActivityEnabled = require('./is_activity_enabled');
3
4
  const isConnectEnabled = require('./is_connect_enabled');
@@ -8,6 +9,7 @@ const isSmsConfigured = require('./is_sms_configured');
8
9
  const validateServerConfig = require('./validate_server_config');
9
10
 
10
11
  module.exports = {
12
+ bech32Prefixes,
11
13
  invoiceNetwork,
12
14
  isActivityEnabled,
13
15
  isConnectEnabled,
@@ -6,7 +6,7 @@ const {combinePsbts} = require('psbt');
6
6
  const {decodePsbt} = require('psbt');
7
7
  const {extractTransaction} = require('psbt');
8
8
  const {finalizePsbt} = require('psbt');
9
- const {Transaction} = require('bitcoinjs-lib');
9
+ const {idForTransaction} = require('@alexbosworth/blockchain');
10
10
 
11
11
  const {confirmIncomingChannel} = require('./funding');
12
12
  const {coordinateGroup} = require('./assemble');
@@ -15,7 +15,6 @@ const {proposeGroupChannel} = require('./funding');
15
15
  const {signAndFundGroupChannel} = require('./funding');
16
16
  const transactionFeeRate = require('./transaction_fee_rate');
17
17
 
18
- const {fromHex} = Transaction;
19
18
  const interval = 500;
20
19
  const minGroupCount = 2;
21
20
  const times = 2 * 60 * 10;
@@ -176,7 +175,7 @@ module.exports = ({capacity, count, identity, lnd, members, rate}) => {
176
175
  capacity,
177
176
  lnd,
178
177
  from: coordinator.partners(identity).inbound,
179
- id: fromHex(basePsbt.unsigned_transaction).getId(),
178
+ id: idForTransaction({transaction: basePsbt.unsigned_transaction}).id,
180
179
  to: coordinator.partners(identity).outbound || undefined,
181
180
  });
182
181
  });
@@ -1,10 +1,12 @@
1
- const {Transaction} = require('bitcoinjs-lib');
1
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
2
+ const {sizeOfTransaction} = require('@alexbosworth/blockchain');
3
+ const {transactionFromComponents} = require('@alexbosworth/blockchain');
2
4
 
3
- const {fromHex} = Transaction;
5
+ const bufferAsHex = buffer => buffer.toString('hex');
4
6
  const isUtxoP2wpkh = utxo => utxo.witness_utxo.script_pub.startsWith('0014');
5
7
  const sumTokens = arr => arr.reduce((sum, n) => sum + n.tokens, 0);
6
- const dummyP2wpkh = [Buffer.alloc(33), Buffer.alloc(72)];
7
- const dummyP2tr = [Buffer.alloc(64)];
8
+ const dummyP2wpkh = [Buffer.alloc(33), Buffer.alloc(72)].map(bufferAsHex);
9
+ const dummyP2tr = [Buffer.alloc(64)].map(bufferAsHex);
8
10
 
9
11
  /** Assuming large ECDSA signatures, determine a chain fee rate for a PSBT
10
12
 
@@ -28,11 +30,21 @@ const dummyP2tr = [Buffer.alloc(64)];
28
30
  */
29
31
  module.exports = ({inputs, outputs, unsigned}) => {
30
32
  const fee = sumTokens(inputs.map(n => n.witness_utxo)) - sumTokens(outputs);
31
- const tx = fromHex(unsigned);
33
+ const tx = componentsOfTransaction({transaction: unsigned});
32
34
 
33
- inputs.forEach((input, index) => {
34
- return tx.setWitness(index, isUtxoP2wpkh(input) ? dummyP2wpkh : dummyP2tr);
35
+ // Add dummy witnesses to the inputs to estimate the final signed size
36
+ const {transaction} = transactionFromComponents({
37
+ inputs: tx.inputs.map((input, index) => ({
38
+ id: input.id,
39
+ script: input.script,
40
+ sequence: input.sequence,
41
+ vout: input.vout,
42
+ witness: isUtxoP2wpkh(inputs[index]) ? dummyP2wpkh : dummyP2tr,
43
+ })),
44
+ locktime: tx.locktime,
45
+ outputs: tx.outputs,
46
+ version: tx.version,
35
47
  });
36
48
 
37
- return {rate: fee / tx.virtualSize()};
49
+ return {rate: fee / sizeOfTransaction({transaction}).vsize};
38
50
  };
@@ -2,14 +2,13 @@ const EventEmitter = require('events');
2
2
 
3
3
  const asyncAuto = require('async/auto');
4
4
  const {decodePsbt} = require('psbt');
5
- const {Transaction} = require('bitcoinjs-lib');
5
+ const {idForTransaction} = require('@alexbosworth/blockchain');
6
6
 
7
7
  const getFanoutFunding = require('./get_fanout_funding');
8
8
  const {registerGroupConnected} = require('./../p2p');
9
9
  const {registerFanoutProposal} = require('./../p2p');
10
10
  const {registerFanoutSigned} = require('./../p2p');
11
11
 
12
- const {fromHex} = Transaction;
13
12
  const {isArray} = Array;
14
13
  const isNumber = n => !isNaN(n);
15
14
 
@@ -128,9 +127,9 @@ module.exports = (args, cbk) => {
128
127
  transaction: ['register', ({register}, cbk) => {
129
128
  const psbt = decodePsbt({psbt: register.psbt});
130
129
 
131
- const tx = fromHex(psbt.unsigned_transaction);
130
+ const {id} = idForTransaction({transaction: psbt.unsigned_transaction});
132
131
 
133
- return cbk(null, {id: tx.getId(), raw: psbt.unsigned_transaction});
132
+ return cbk(null, {id, raw: psbt.unsigned_transaction});
134
133
  }],
135
134
 
136
135
  // Publish the partial funding signatures to coordinator
@@ -1,15 +1,17 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncEach = require('async/each');
3
3
  const {connectPeer} = require('ln-sync');
4
+ const {encodeBech32Address} = require('@alexbosworth/blockchain');
4
5
  const {fundPsbtDisallowingInputs} = require('ln-sync');
5
6
  const {getNetwork} = require('ln-sync');
6
7
  const {getUtxos} = require('ln-service');
7
8
  const {openChannels} = require('ln-service');
8
- const {networks} = require('bitcoinjs-lib');
9
- const {payments} = require('bitcoinjs-lib');
9
+ const {p2msScript} = require('@alexbosworth/blockchain');
10
10
  const {returnResult} = require('asyncjs-util');
11
11
  const {unlockUtxo} = require('ln-service');
12
12
 
13
+ const {bech32Prefixes} = require('./../../config');
14
+
13
15
  const dummyKeys = () => ([Buffer.alloc(33, 2), Buffer.alloc(33, 3)]);
14
16
  const fuzzSize = 1;
15
17
  const halfOf = n => n / 2;
@@ -17,6 +19,7 @@ const isEven = n => !(n % 2);
17
19
  const minGroupCount = 2;
18
20
  const nestedSegWitAddressFormat = 'np2wpkh';
19
21
  const nestedSegWitPath = "m/49'/";
22
+ const witnessVersionSegWit = 0;
20
23
 
21
24
  /** Fund and propose a group channel to a peer
22
25
 
@@ -101,13 +104,15 @@ module.exports = ({capacity, count, lnd, rate, to}, cbk) => {
101
104
 
102
105
  // Exit early when there is a shared proposal due to a pair group
103
106
  if (!to) {
104
- const {address} = payments.p2wsh({
105
- network: networks[getNetwork.bitcoinjs],
106
- redeem: payments.p2ms({
107
- m: dummyKeys().length,
108
- network: networks[getNetwork.bitcoinjs],
109
- pubkeys: dummyKeys(),
110
- }),
107
+ const {hash} = p2msScript({
108
+ keys: dummyKeys(),
109
+ required: dummyKeys().length,
110
+ });
111
+
112
+ const {address} = encodeBech32Address({
113
+ prefix: bech32Prefixes[getNetwork.network],
114
+ program: hash,
115
+ version: witnessVersionSegWit,
111
116
  });
112
117
 
113
118
  // Pretend we are opening a channel when there is no outbound target
@@ -3,11 +3,10 @@ const asyncRetry = require('async/retry');
3
3
  const {decodePsbt} = require('psbt');
4
4
  const {fundPendingChannels} = require('ln-service');
5
5
  const {getPendingChannels} = require('ln-service');
6
+ const {idForTransaction} = require('@alexbosworth/blockchain');
6
7
  const {returnResult} = require('asyncjs-util');
7
8
  const {signAndFundPsbt} = require('ln-sync');
8
- const {Transaction} = require('bitcoinjs-lib');
9
9
 
10
- const {fromHex} = Transaction;
11
10
  const interval = 10;
12
11
  const {isArray} = Array;
13
12
  const times = 500;
@@ -88,7 +87,9 @@ module.exports = ({id, lnd, psbt, utxos}, cbk) => {
88
87
  return cbk();
89
88
  }
90
89
 
91
- const tx = fromHex(decodePsbt({psbt}).unsigned_transaction);
90
+ const unsigned = decodePsbt({psbt}).unsigned_transaction;
91
+
92
+ const txId = idForTransaction({transaction: unsigned}).id;
92
93
 
93
94
  // Wait for the outgoing pending channel to be present
94
95
  return asyncRetry({interval, times}, cbk => {
@@ -99,7 +100,7 @@ module.exports = ({id, lnd, psbt, utxos}, cbk) => {
99
100
 
100
101
  const ids = res.pending_channels.map(n => n.transaction_id);
101
102
 
102
- if (!ids.includes(tx.getId())) {
103
+ if (!ids.includes(txId)) {
103
104
  return cbk([503, 'FailedToFindPendingChannelForGroupOpen']);
104
105
  }
105
106
 
@@ -3,9 +3,10 @@ const EventEmitter = require('events');
3
3
  const asyncAuto = require('async/auto');
4
4
  const asyncReflect = require('async/reflect');
5
5
  const asyncRetry = require('async/retry');
6
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
6
7
  const {decodePsbt} = require('psbt');
7
8
  const {deletePendingChannel} = require('ln-service');
8
- const {Transaction} = require('bitcoinjs-lib');
9
+ const {idForTransaction} = require('@alexbosworth/blockchain');
9
10
 
10
11
  const {confirmIncomingChannel} = require('./funding');
11
12
  const {findGroupPartners} = require('./p2p');
@@ -15,8 +16,6 @@ const {registerGroupConnected} = require('./p2p');
15
16
  const {registerPendingOpen} = require('./p2p');
16
17
  const {registerSignedOpen} = require('./p2p');
17
18
 
18
- const {fromHex} = Transaction;
19
- const hexAsBuffer = hex => Buffer.from(hex, 'hex');
20
19
  const interval = 1000;
21
20
  const times = 60 * 10;
22
21
 
@@ -148,15 +147,16 @@ module.exports = ({capacity, coordinator, count, id, lnd, rate}, cbk) => {
148
147
  'register',
149
148
  ({propose, register}, cbk) =>
150
149
  {
151
- const funding = hexAsBuffer(propose.funding);
152
150
  const psbt = decodePsbt({psbt: register.psbt});
153
151
 
154
- const tx = fromHex(psbt.unsigned_transaction);
152
+ const transaction = psbt.unsigned_transaction;
153
+
154
+ const {outputs} = componentsOfTransaction({transaction});
155
155
 
156
156
  return cbk(null, {
157
- id: tx.getId(),
158
- raw: psbt.unsigned_transaction,
159
- vout: tx.outs.findIndex(n => n.script.equals(funding)),
157
+ id: idForTransaction({transaction}).id,
158
+ raw: transaction,
159
+ vout: outputs.findIndex(n => n.script === propose.funding),
160
160
  });
161
161
  }],
162
162
 
@@ -1,9 +1,8 @@
1
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
1
2
  const {decodeBigSize} = require('bolt01');
2
3
  const {decodeTlvStream} = require('bolt01');
3
- const {Transaction} = require('bitcoinjs-lib');
4
4
 
5
5
  const findRecord = (records, type) => records.find(n => n.type === type);
6
- const {fromHex} = Transaction;
7
6
 
8
7
  const expectedTxIdHexLength = 64;
9
8
  const isP2tr = n => n.startsWith('5120') && n.length === 68;
@@ -61,7 +60,7 @@ module.exports = ({encoded}) => {
61
60
 
62
61
  if (!!nonWitnessUtxo) {
63
62
  try {
64
- fromHex(nonWitnessUtxo.value);
63
+ componentsOfTransaction({transaction: nonWitnessUtxo.value});
65
64
  } catch (err) {
66
65
  throw new Error('ExpectedValidTransactionInPendingWitnessUtxo');
67
66
  }
@@ -1,11 +1,11 @@
1
1
  const asyncAuto = require('async/auto');
2
2
  const asyncReflect = require('async/reflect');
3
3
  const asyncRetry = require('async/retry');
4
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
4
5
  const {connectPeer} = require('ln-sync');
5
6
  const {decodePsbt} = require('psbt');
6
7
  const {returnResult} = require('asyncjs-util');
7
8
  const {signAndFundPsbt} = require('ln-sync');
8
- const {Transaction} = require('bitcoinjs-lib');
9
9
 
10
10
  const {decodeUnsignedFunding} = require('./../messages');
11
11
  const {encodeFanoutProposal} = require('./../messages');
@@ -13,12 +13,9 @@ const estimateFeeRate = require('./../estimate_fee_rate');
13
13
  const {makePeerRequest} = require('./../../p2p');
14
14
  const {serviceTypeRegisterPendingFanout} = require('./../../service_types')
15
15
 
16
- const bufferAsHex = buffer => buffer.toString('hex');
17
16
  const defaultIntervalMs = 500;
18
17
  const defaultPollTimes = 2 * 60 * 30;
19
18
  const defaultRequestTimeoutMs = 1000 * 60;
20
- const {fromHex} = Transaction;
21
- const hexAsBuffer = hex => Buffer.from(hex, 'hex');
22
19
  const {isArray} = Array;
23
20
  const missingGroupPartners = 'NoGroupPartnersFound';
24
21
 
@@ -159,11 +156,13 @@ module.exports = (args, cbk) => {
159
156
  return cbk([503, 'ExpectedAllFanoutInputsSpendingWitnessUtxos']);
160
157
  }
161
158
 
162
- const tx = fromHex(psbt.unsigned_transaction);
159
+ const tx = componentsOfTransaction({
160
+ transaction: psbt.unsigned_transaction,
161
+ });
163
162
 
164
163
  const estimated = estimateFeeRate({
165
164
  inputs: psbt.inputs,
166
- outputs: tx.outs.map(n => ({tokens: n.value})),
165
+ outputs: tx.outputs.map(n => ({tokens: n.tokens})),
167
166
  unsigned: psbt.unsigned_transaction,
168
167
  });
169
168
 
@@ -173,20 +172,17 @@ module.exports = (args, cbk) => {
173
172
 
174
173
  // All the specified utxos should be represented in the PSBT
175
174
  const missingInput = args.utxos.find(utxo => {
176
- const hash = hexAsBuffer(utxo.transaction_id).reverse();
175
+ const id = utxo.transaction_id;
177
176
  const vout = utxo.transaction_vout;
178
177
 
179
- return !tx.ins.find(n => n.hash.equals(hash) && n.index === vout);
178
+ return !tx.inputs.find(n => n.id === id && n.vout === vout);
180
179
  });
181
180
 
182
181
  if (!!missingInput) {
183
182
  return cbk([503, 'ExpectedAllInputsRepresentedInFanoutGroupPsbt']);
184
183
  }
185
184
 
186
- const outputs = tx.outs.map(({script, value}) => ({
187
- script: bufferAsHex(script),
188
- tokens: value,
189
- }));
185
+ const {outputs} = tx;
190
186
 
191
187
  const change = outputs.find(n => n.script === args.change);
192
188
  const funding = outputs.filter(n => args.funding.includes(n.script));
@@ -2,10 +2,10 @@ const asyncAuto = require('async/auto');
2
2
  const asyncReflect = require('async/reflect');
3
3
  const asyncRetry = require('async/retry');
4
4
  const {cancelPendingChannel} = require('ln-service');
5
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
5
6
  const {connectPeer} = require('ln-sync');
6
7
  const {decodePsbt} = require('psbt');
7
8
  const {returnResult} = require('asyncjs-util');
8
- const {Transaction} = require('bitcoinjs-lib');
9
9
 
10
10
  const {decodeUnsignedFunding} = require('./../messages');
11
11
  const {encodePendingProposal} = require('./../messages');
@@ -14,12 +14,9 @@ const {makePeerRequest} = require('./../../p2p');
14
14
  const {serviceTypeRegisterPendingOpen} = require('./../../service_types');
15
15
  const {signAndFundGroupChannel} = require('./../funding');
16
16
 
17
- const bufferAsHex = buffer => buffer.toString('hex');
18
17
  const defaultIntervalMs = 500;
19
18
  const defaultPollTimes = 2 * 60 * 30;
20
19
  const defaultRequestTimeoutMs = 1000 * 60;
21
- const {fromHex} = Transaction;
22
- const hexAsBuffer = hex => Buffer.from(hex, 'hex');
23
20
  const {isArray} = Array;
24
21
  const missingGroupPartners = 'NoGroupPartnersFound';
25
22
 
@@ -183,30 +180,29 @@ module.exports = (args, cbk) => {
183
180
  return cbk([503, 'ExpectedAllGroupInputsSpendingWitnessUtxos']);
184
181
  }
185
182
 
186
- const tx = fromHex(psbt.unsigned_transaction);
183
+ const tx = componentsOfTransaction({
184
+ transaction: psbt.unsigned_transaction,
185
+ });
187
186
 
188
187
  const estimated = estimateFeeRate({
189
188
  inputs: psbt.inputs,
190
- outputs: tx.outs.map(n => ({tokens: n.value})),
189
+ outputs: tx.outputs.map(n => ({tokens: n.tokens})),
191
190
  unsigned: psbt.unsigned_transaction,
192
191
  });
193
192
 
194
193
  // The utxos should be represented in the PSBT
195
194
  const missing = args.utxos.find(utxo => {
196
- const hash = hexAsBuffer(utxo.transaction_id).reverse();
195
+ const id = utxo.transaction_id;
197
196
  const vout = utxo.transaction_vout;
198
197
 
199
- return !tx.ins.find(n => n.hash.equals(hash) && n.index === vout);
198
+ return !tx.inputs.find(n => n.id === id && n.vout === vout);
200
199
  });
201
200
 
202
201
  if (!!missing) {
203
202
  return cbk([503, 'ExpectedAllInputsRepresentedInGroupChannelPsbt']);
204
203
  }
205
204
 
206
- const outputs = tx.outs.map(({script, value}) => ({
207
- script: bufferAsHex(script),
208
- tokens: value,
209
- }));
205
+ const {outputs} = tx;
210
206
 
211
207
  const change = outputs.find(n => n.script === args.change);
212
208
  const funding = outputs.find(n => n.script === args.funding);
@@ -1,6 +1,6 @@
1
- const {Transaction} = require('bitcoinjs-lib');
1
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
2
+ const {sizeOfTransaction} = require('@alexbosworth/blockchain');
2
3
 
3
- const {fromHex} = Transaction;
4
4
  const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
5
5
 
6
6
  /** Given a transaction and inputs metadata, derive transaction chain fee rate
@@ -21,9 +21,9 @@ const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
21
21
  */
22
22
  module.exports = ({inputs, transaction}) => {
23
23
  const inputsValue = sumOf(inputs.map(n => n.witness_utxo.tokens));
24
- const tx = fromHex(transaction);
24
+ const {outputs} = componentsOfTransaction({transaction});
25
25
 
26
- const fee = inputsValue - sumOf(tx.outs.map(n => n.value));
26
+ const fee = inputsValue - sumOf(outputs.map(n => n.tokens));
27
27
 
28
- return {rate: fee / tx.virtualSize()};
28
+ return {rate: fee / sizeOfTransaction({transaction}).vsize};
29
29
  };
package/package.json CHANGED
@@ -16,22 +16,21 @@
16
16
  "@alexbosworth/fiat": "2.0.0",
17
17
  "async": "3.2.6",
18
18
  "asyncjs-util": "1.2.12",
19
- "bitcoinjs-lib": "6.1.7",
20
19
  "bolt01": "4.0.1",
21
20
  "bolt04": "1.3.0",
22
21
  "bolt07": "2.0.0",
23
22
  "goldengate": "16.0.9",
24
23
  "invoices": "6.3.0",
25
24
  "ln-service": "60.1.6",
26
- "ln-sync": "8.0.8",
25
+ "ln-sync": "8.0.9",
27
26
  "psbt": "7.0.0",
28
27
  "p2tr": "3.0.0",
29
28
  "tiny-secp256k1": "2.2.4"
30
29
  },
31
30
  "description": "Lightning Paid Services library",
32
31
  "devDependencies": {
33
- "ln-docker-daemons": "8.1.2",
34
- "mock-lnd": "4.0.0"
32
+ "ln-docker-daemons": "8.1.3",
33
+ "mock-lnd": "4.0.1"
35
34
  },
36
35
  "engines": {
37
36
  "node": ">=22"
@@ -73,5 +72,5 @@
73
72
  "integration-tests": "node test/integration",
74
73
  "test": "node --experimental-test-coverage --test test/actions/*.js test/balanced/*.js test/client/*.js test/config/*.js test/network/*.js test/offers/*.js test/p2p/*.js test/records/*.js test/respond/*.js test/server/*.js test/service_records/*.js test/swaps/*.js test/services/*.js test/support/*.js test/trades/*.js"
75
74
  },
76
- "version": "10.3.2"
75
+ "version": "10.3.3"
77
76
  }
@@ -10,6 +10,7 @@ const asyncTimeout = require('async/timeout');
10
10
  const {beginGroupSigningSession} = require('ln-service');
11
11
  const {broadcastChainTransaction} = require('ln-service');
12
12
  const {cancelSwapOut} = require('goldengate');
13
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
13
14
  const {confirmationFee} = require('goldengate');
14
15
  const {controlBlock} = require('p2tr');
15
16
  const {createChainAddress} = require('ln-service');
@@ -25,9 +26,9 @@ const {getNetwork} = require('ln-sync');
25
26
  const {getPayment} = require('ln-service');
26
27
  const {getPublicKey} = require('ln-service');
27
28
  const {hashForTree} = require('p2tr');
29
+ const {idForTransaction} = require('@alexbosworth/blockchain');
28
30
  const {lightningLabsSwapAuth} = require('goldengate');
29
31
  const {lightningLabsSwapService} = require('goldengate');
30
- const {networks} = require('bitcoinjs-lib');
31
32
  const {parsePaymentRequest} = require('ln-service');
32
33
  const {pay} = require('ln-service');
33
34
  const {payViaPaymentDetails} = require('ln-service');
@@ -36,25 +37,28 @@ const {pointFromScalar} = require('tiny-secp256k1');
36
37
  const {privateAdd} = require('tiny-secp256k1');
37
38
  const {releaseSwapOutSecret} = require('goldengate');
38
39
  const {returnResult} = require('asyncjs-util');
39
- const {script} = require('bitcoinjs-lib');
40
+ const {scriptAsScriptElements} = require('@alexbosworth/blockchain');
40
41
  const {signTransaction} = require('ln-service');
42
+ const {sizeOfTransaction} = require('@alexbosworth/blockchain');
41
43
  const {subscribeToBlocks} = require('ln-service');
42
44
  const {subscribeToPastPayment} = require('ln-service');
43
45
  const {subscribeToSpend} = require('goldengate');
44
46
  const {swapScriptBranches} = require('goldengate');
45
47
  const {taprootClaimTransaction} = require('goldengate');
46
48
  const {taprootCoopTransaction} = require('goldengate');
47
- const {Transaction} = require('bitcoinjs-lib');
49
+ const {transactionFromComponents} = require('@alexbosworth/blockchain');
48
50
  const {v1OutputScript} = require('p2tr');
49
51
 
52
+ const {bech32Prefixes} = require('./../config');
50
53
  const decodeLoopResponse = require('./decode_loop_response');
51
54
  const decodeOffToOnRecovery = require('./decode_off_to_on_recovery');
52
55
  const decodeOffToOnResponse = require('./decode_off_to_on_response');
56
+ const {invoiceNetworks} = require('./constants');
53
57
  const {typePayMetadata} = require('./swap_field_types');
54
58
 
55
59
  const bufferAsHex = buffer => buffer.toString('hex');
56
60
  const {ceil} = Math;
57
- const decompileOutputScript = hex => script.decompile(Buffer.from(hex, 'hex'));
61
+ const decompileScript = script => scriptAsScriptElements({script}).elements;
58
62
  const defaultConfsCount = 1;
59
63
  const defaultDepositSettleTimeoutMs = 1000 * 60 * 10;
60
64
  const defaultMaxFeeMultiplier = 1000;
@@ -66,7 +70,6 @@ const family = 805;
66
70
  const {floor} = Math;
67
71
  const format = 'p2tr';
68
72
  const {from} = Buffer;
69
- const {fromHex} = Transaction;
70
73
  const fuzzBlocks = 100;
71
74
  const fuzzTimelock = 1;
72
75
  const getLoopCoopSignedTransaction = asyncTimeout(getCoopSignedTx, 1000 * 30);
@@ -86,7 +89,7 @@ const pubKeyAsInternalKey = key => Buffer.from(key).slice(1).toString('hex');
86
89
  const publicKeyFor = key => Buffer.from(pointFromScalar(key, isCompressed));
87
90
  const pushSecret = asyncTimeout(releaseSwapOutSecret, 1000 * 30);
88
91
  const sha256 = preimage => createHash('sha256').update(preimage).digest('hex');
89
- const sighash = Transaction.SIGHASH_DEFAULT;
92
+ const sighashDefault = 0;
90
93
  const slowConfs = 144 * 7;
91
94
  const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
92
95
  const sweepInputIndex = 0;
@@ -220,7 +223,7 @@ module.exports = (args, cbk) => {
220
223
  if (!!args.is_loop_service) {
221
224
  try {
222
225
  const details = decodeLoopResponse({
223
- network: getNetwork.bitcoinjs,
226
+ network: invoiceNetworks[getNetwork.network],
224
227
  response: args.response,
225
228
  });
226
229
 
@@ -243,7 +246,7 @@ module.exports = (args, cbk) => {
243
246
  try {
244
247
  // Decode the response
245
248
  const decoded = decodeOffToOnResponse({
246
- network: getNetwork.bitcoinjs,
249
+ network: invoiceNetworks[getNetwork.network],
247
250
  response: args.response,
248
251
  });
249
252
 
@@ -680,9 +683,9 @@ module.exports = (args, cbk) => {
680
683
  'swap',
681
684
  ({deadline, getNetwork, requestDetails, startHeight, swap}, cbk) =>
682
685
  {
683
- const [, key] = decompileOutputScript(swap.output_script);
686
+ const [, key] = decompileScript(swap.output_script);
684
687
  const outputScript = swap.output_script;
685
- const prefix = networks[getNetwork.bitcoinjs].bech32;
688
+ const prefix = bech32Prefixes[getNetwork.network];
686
689
 
687
690
  const {address} = encodeBech32Address({
688
691
  prefix,
@@ -840,11 +843,11 @@ module.exports = (args, cbk) => {
840
843
  return signTransaction({
841
844
  transaction,
842
845
  inputs: [{
843
- sighash,
844
846
  key_family: family,
845
847
  key_index: requestDetails.key_index,
846
848
  output_script: swap.output_script,
847
849
  output_tokens: requestDetails.tokens,
850
+ sighash: sighashDefault,
848
851
  vin: sweepInputIndex,
849
852
  witness_script: swap.claim_script,
850
853
  }],
@@ -871,14 +874,23 @@ module.exports = (args, cbk) => {
871
874
  block,
872
875
  ];
873
876
 
874
- const tx = fromHex(transaction);
877
+ const tx = componentsOfTransaction({transaction});
875
878
 
876
879
  // Add the signature to the sweep
877
- tx.ins.forEach((input, vin) => {
878
- return tx.setWitness(vin, witness.map(hexAsBuffer));
880
+ const signed = transactionFromComponents({
881
+ inputs: tx.inputs.map(input => ({
882
+ witness,
883
+ id: input.id,
884
+ script: input.script,
885
+ sequence: input.sequence,
886
+ vout: input.vout,
887
+ })),
888
+ locktime: tx.locktime,
889
+ outputs: tx.outputs,
890
+ version: tx.version,
879
891
  });
880
892
 
881
- return cbk(null, {height, transaction: tx.toHex()});
893
+ return cbk(null, {height, transaction: signed.transaction});
882
894
  });
883
895
  },
884
896
  cbk);
@@ -1229,15 +1241,15 @@ module.exports = (args, cbk) => {
1229
1241
 
1230
1242
  const [{transaction}] = broadcast.reverse();
1231
1243
 
1232
- const tx = fromHex(transaction);
1244
+ const {outputs} = componentsOfTransaction({transaction});
1233
1245
 
1234
- const fee = requestDetails.tokens - sumOf(tx.outs.map(n => n.value));
1246
+ const fee = requestDetails.tokens - sumOf(outputs.map(n => n.tokens));
1235
1247
 
1236
1248
  args.emitter.emit('update', {
1237
1249
  blocks_until_potential_funds_forfeit: swap.timeout - block.height,
1238
- broadcasting_fee_rate: fee / tx.virtualSize(),
1250
+ broadcasting_fee_rate: fee / sizeOfTransaction({transaction}).vsize,
1239
1251
  broadcasting_tx_to_resolve_swap: transaction,
1240
- broadcasting_tx_id: tx.getId(),
1252
+ broadcasting_tx_id: idForTransaction({transaction}).id,
1241
1253
  });
1242
1254
 
1243
1255
  return broadcastChainTransaction({
@@ -1251,11 +1263,13 @@ module.exports = (args, cbk) => {
1251
1263
 
1252
1264
  // Look for the sweep to confirm
1253
1265
  subSpend.on('confirmation', ({transaction}) => {
1254
- const tx = fromHex(transaction);
1266
+ const {outputs} = componentsOfTransaction({transaction});
1255
1267
 
1256
- const fee = requestDetails.tokens - sumOf(tx.outs.map(n => n.value));
1268
+ const fee = requestDetails.tokens - sumOf(outputs.map(n => n.tokens));
1257
1269
 
1258
- return done(null, {fee: fee, rate: fee / tx.virtualSize()});
1270
+ const {vsize} = sizeOfTransaction({transaction});
1271
+
1272
+ return done(null, {fee: fee, rate: fee / vsize});
1259
1273
  });
1260
1274
 
1261
1275
  subSpend.on('error', err => done(err));
@@ -5,6 +5,7 @@ const asyncMap = require('async/map');
5
5
  const asyncReflect = require('async/reflect');
6
6
  const {broadcastChainTransaction} = require('ln-service');
7
7
  const {cancelHodlInvoice} = require('ln-service');
8
+ const {componentsOfTransaction} = require('@alexbosworth/blockchain');
8
9
  const {confirmationFee} = require('goldengate');
9
10
  const {controlBlock} = require('p2tr');
10
11
  const {createChainAddress} = require('ln-service');
@@ -21,6 +22,7 @@ const {getInvoice} = require('ln-service');
21
22
  const {getNetwork} = require('ln-sync');
22
23
  const {getPublicKey} = require('ln-service');
23
24
  const {hashForTree} = require('p2tr');
25
+ const {idForTransaction} = require('@alexbosworth/blockchain');
24
26
  const {pointAdd} = require('tiny-secp256k1');
25
27
  const {pointFromScalar} = require('tiny-secp256k1');
26
28
  const {returnResult} = require('asyncjs-util');
@@ -33,7 +35,7 @@ const {subscribeToInvoice} = require('ln-service');
33
35
  const {subscribeToSpend} = require('goldengate');
34
36
  const {swapScriptBranches} = require('goldengate');
35
37
  const {taprootRefundTransaction} = require('goldengate');
36
- const {Transaction} = require('bitcoinjs-lib');
38
+ const {transactionFromComponents} = require('@alexbosworth/blockchain');
37
39
  const {v1OutputScript} = require('p2tr');
38
40
 
39
41
  const decodeOnToOffRecovery = require('./decode_on_to_off_recovery');
@@ -48,13 +50,13 @@ const flatten = arr => [].concat(...arr);
48
50
  const {floor} = Math;
49
51
  const format = 'p2tr';
50
52
  const {from} = Buffer;
51
- const {fromHex} = Transaction;
52
53
  const fuzzBlocks = 100;
53
54
  const hexAsBase64 = hex => Buffer.from(hex, 'hex').toString('base64');
54
55
  const hexAsBuffer = hex => Buffer.from(hex, 'hex');
55
56
  const historicBlocksRange = 144 * 30;
56
- const isAnnex = element => element[0] === 0x50;
57
+ const isAnnex = element => element.startsWith('50');
57
58
  const isCompressed = true;
59
+ const locktimeOf = tx => componentsOfTransaction({transaction: tx}).locktime;
58
60
  const maxRefundMultiple = (r, t) => Math.min(100, ((1000 + t) / 150) / r);
59
61
  const {min} = Math;
60
62
  const minBlocks = 50;
@@ -64,7 +66,7 @@ const pubKeyAsSecret = hexPublicKey => hexPublicKey.slice(2);
64
66
  const publicKeyFor = key => Buffer.from(pointFromScalar(key, isCompressed));
65
67
  const removeAnnex = stack => stack.slice(0, -1);
66
68
  const sha256 = preimage => createHash('sha256').update(preimage).digest('hex');
67
- const sighash = Transaction.SIGHASH_DEFAULT;
69
+ const sighashDefault = 0;
68
70
  const slowTarget = 144 * 7;
69
71
  const sweepInputIndex = 0;
70
72
  const times = n => Array(n).fill(null).map((_, i) => i);
@@ -404,11 +406,11 @@ module.exports = (args, cbk) => {
404
406
  return signTransaction({
405
407
  transaction,
406
408
  inputs: [{
407
- sighash,
408
409
  key_family: family,
409
410
  key_index: recoveryDetails.key_index,
410
411
  output_script: swap.output_script,
411
412
  output_tokens: recoveryDetails.tokens,
413
+ sighash: sighashDefault,
412
414
  vin: sweepInputIndex,
413
415
  witness_script: swap.refund_script,
414
416
  }],
@@ -430,14 +432,23 @@ module.exports = (args, cbk) => {
430
432
 
431
433
  const witness = [signature, swap.refund_script, block];
432
434
 
433
- const tx = fromHex(transaction);
435
+ const tx = componentsOfTransaction({transaction});
434
436
 
435
437
  // Add the signature to the sweep
436
- tx.ins.forEach((input, vin) => {
437
- return tx.setWitness(vin, witness.map(hexAsBuffer));
438
+ const signed = transactionFromComponents({
439
+ inputs: tx.inputs.map(input => ({
440
+ witness,
441
+ id: input.id,
442
+ script: input.script,
443
+ sequence: input.sequence,
444
+ vout: input.vout,
445
+ })),
446
+ locktime: tx.locktime,
447
+ outputs: tx.outputs,
448
+ version: tx.version,
438
449
  });
439
450
 
440
- return cbk(null, tx.toHex());
451
+ return cbk(null, signed.transaction);
441
452
  });
442
453
  },
443
454
  cbk);
@@ -525,12 +536,18 @@ module.exports = (args, cbk) => {
525
536
  ({getTransactions, swap}, cbk) =>
526
537
  {
527
538
  const tx = getTransactions.transactions.find(({transaction}) => {
528
- return !!transaction && !!fromHex(transaction).outs.find(output => {
529
- if (output.value !== swap.tokens) {
539
+ if (!transaction) {
540
+ return false;
541
+ }
542
+
543
+ const {outputs} = componentsOfTransaction({transaction});
544
+
545
+ return !!outputs.find(output => {
546
+ if (output.tokens !== swap.tokens) {
530
547
  return false;
531
548
  }
532
549
 
533
- return bufferAsHex(output.script) === swap.output_script;
550
+ return output.script === swap.output_script;
534
551
  });
535
552
  });
536
553
 
@@ -567,11 +584,12 @@ module.exports = (args, cbk) => {
567
584
 
568
585
  // Output funding the swap on chain
569
586
  outpoint: ['signFunding', 'swap', ({signFunding, swap}, cbk) => {
570
- const tx = fromHex(signFunding.transaction);
571
- const script = hexAsBuffer(swap.output_script);
587
+ const {transaction} = signFunding;
588
+
589
+ const {outputs} = componentsOfTransaction({transaction});
572
590
 
573
- const id = tx.getId();
574
- const vout = tx.outs.findIndex(n => n.script.equals(script));
591
+ const {id} = idForTransaction({transaction});
592
+ const vout = outputs.findIndex(n => n.script === swap.output_script);
575
593
 
576
594
  args.emitter.emit('update', {
577
595
  funding_transaction: signFunding.transaction,
@@ -592,7 +610,7 @@ module.exports = (args, cbk) => {
592
610
 
593
611
  args.emitter.emit('update', {
594
612
  refund_transaction: refund,
595
- refund_valid_at: fromHex(refund).locktime,
613
+ refund_valid_at: locktimeOf(refund),
596
614
  });
597
615
 
598
616
  // Exit early when the transaction was already published
@@ -682,12 +700,10 @@ module.exports = (args, cbk) => {
682
700
 
683
701
  // Look for the preimage to be used on-chain in a sweep
684
702
  subSpend.on('confirmation', ({transaction}) => {
685
- const spend = fromHex(transaction).ins.find(input => {
686
- if (!input.hash.equals(hexAsBuffer(outpoint.id).reverse())) {
687
- return false;
688
- }
703
+ const {inputs} = componentsOfTransaction({transaction});
689
704
 
690
- return input.index === outpoint.vout;
705
+ const spend = inputs.find(input => {
706
+ return input.id === outpoint.id && input.vout === outpoint.vout;
691
707
  });
692
708
 
693
709
  const [lastElement, nextToLast] = spend.witness.slice().reverse();
@@ -722,7 +738,7 @@ module.exports = (args, cbk) => {
722
738
 
723
739
  const [secret] = stack;
724
740
 
725
- return done(null, {secret: bufferAsHex(secret)});
741
+ return done(null, {secret});
726
742
  });
727
743
 
728
744
  subSpend.on('error', err => done(err));
@@ -739,7 +755,7 @@ module.exports = (args, cbk) => {
739
755
  // Find the latest valid refund transaction
740
756
  const [transaction] = signRefunds
741
757
  .filter(transaction => {
742
- return fromHex(transaction).locktime <= block.height;
758
+ return locktimeOf(transaction) <= block.height;
743
759
  })
744
760
  .reverse();
745
761
 
@@ -0,0 +1,16 @@
1
+ {
2
+ "invoiceNetworks": {
3
+ "btc": "bitcoin",
4
+ "btcregtest": "regtest",
5
+ "btcsignet": "signet",
6
+ "btctestnet": "testnet",
7
+ "btctestnet4": "testnet"
8
+ },
9
+ "minConfirmations": {
10
+ "btc": 2,
11
+ "btcregtest": 3,
12
+ "btcsignet": 1,
13
+ "btctestnet": 1,
14
+ "btctestnet4": 1
15
+ }
16
+ }
@@ -1,4 +1,3 @@
1
- const {address} = require('bitcoinjs-lib');
2
1
  const asyncAuto = require('async/auto');
3
2
  const asyncMap = require('async/map');
4
3
  const {findKey} = require('ln-sync');
@@ -7,13 +6,13 @@ const {getAllInvoices} = require('ln-sync');
7
6
  const {getInvoice} = require('ln-service');
8
7
  const {getNetwork} = require('ln-sync');
9
8
  const {getNodeAlias} = require('ln-sync');
10
- const {networks} = require('bitcoinjs-lib');
9
+ const {outputScriptForAddress} = require('@alexbosworth/blockchain');
11
10
  const {returnResult} = require('asyncjs-util');
12
11
 
13
12
  const decodeOffToOnRequest = require('./decode_off_to_on_request');
14
13
  const decodeOffToOnRestart = require('./decode_off_to_on_restart');
15
14
  const {decodeTrade} = require('./../trades');
16
- const outputScriptForAddress = require('./output_script_for_address');
15
+ const {minConfirmations} = require('./constants');
17
16
  const recoverResponseToSwapOut = require('./recover_response_to_swap_out');
18
17
  const requestSwapOut = require('./request_swap_out');
19
18
  const respondToSwapOutRequest = require('./respond_to_swap_out_request');
@@ -24,14 +23,12 @@ const actionRestartRequest = 'restart-request';
24
23
  const allowedNetwork = 'btctestnet';
25
24
  const bip86Path = `m/86'/0'/0'`;
26
25
  const flatten = arr => [].concat(...arr);
27
- const minConfirmations = {btc: 2, btcregtest: 3, btctestnet: 1};
28
26
  const niceId = id => id.substring(0, 8);
29
27
  const niceName = node => `${node.alias} ${node.id.substring(0, 8)}`.trim();
30
28
  const pushesReceivedAfter = () => new Date(Date.now() - 1000 * 60 * 60 * 24);
31
29
  const recoverRespondAction = 'recover-response';
32
30
  const requestAction = 'request';
33
31
  const respondAction = 'respond';
34
- const {toOutputScript} = address;
35
32
  const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
36
33
  const typeKeySendTrade = '805805';
37
34
 
@@ -314,7 +311,7 @@ module.exports = (args, cbk) => {
314
311
  try {
315
312
  return !!outputScriptForAddress({
316
313
  address: input,
317
- network: getNetwork.bitcoinjs,
314
+ network: getNetwork.network,
318
315
  });
319
316
  } catch (err) {
320
317
  return 'Unsupported on-chain address format';
@@ -20,6 +20,7 @@ const decodeOffToOnRequest = require('./decode_off_to_on_request');
20
20
  const decodeOffToOnResponse = require('./decode_off_to_on_response');
21
21
  const encodeOffToOnRestart = require('./encode_off_to_on_restart');
22
22
  const {encodeTrade} = require('./../trades');
23
+ const {invoiceNetworks} = require('./constants');
23
24
  const makeRequest = require('./start_off_to_on_swap');
24
25
  const {pushTypes} = require('./swap_field_types');
25
26
  const requestLoopOut = require('./request_loop_out');
@@ -251,7 +252,10 @@ module.exports = (args, cbk) => {
251
252
 
252
253
  // Check the swap response is valid
253
254
  try {
254
- decodeOffToOnResponse({response, network: getNetwork.bitcoinjs});
255
+ decodeOffToOnResponse({
256
+ response,
257
+ network: invoiceNetworks[getNetwork.network],
258
+ });
255
259
  } catch (err) {
256
260
  return res.failure([400, err.message]);
257
261
  }
@@ -373,7 +377,10 @@ module.exports = (args, cbk) => {
373
377
  }
374
378
 
375
379
  try {
376
- decodeOffToOnResponse({response, network: getNetwork.bitcoinjs});
380
+ decodeOffToOnResponse({
381
+ response,
382
+ network: invoiceNetworks[getNetwork.network],
383
+ });
377
384
  } catch (err) {
378
385
  return 'Failed parse this response, check input?';
379
386
  }
@@ -395,7 +402,7 @@ module.exports = (args, cbk) => {
395
402
  // Exit early when the request is to Lightning Loop
396
403
  if (!!args.is_loop_service) {
397
404
  const details = decodeLoopResponse({
398
- network: getNetwork.bitcoinjs,
405
+ network: invoiceNetworks[getNetwork.network],
399
406
  response: getResponse,
400
407
  });
401
408
 
@@ -414,7 +421,7 @@ module.exports = (args, cbk) => {
414
421
  }
415
422
 
416
423
  const response = decodeOffToOnResponse({
417
- network: getNetwork.bitcoinjs,
424
+ network: invoiceNetworks[getNetwork.network],
418
425
  response: getResponse,
419
426
  });
420
427
 
@@ -6,11 +6,11 @@ const {diffieHellmanComputeSecret} = require('ln-service');
6
6
  const {getIdentity} = require('ln-service');
7
7
  const {getNetwork} = require('ln-sync');
8
8
  const {getPublicKey} = require('ln-service');
9
- const {networks} = require('bitcoinjs-lib');
10
9
  const {pointFromScalar} = require('tiny-secp256k1');
11
10
  const {returnResult} = require('asyncjs-util');
12
11
 
13
12
  const encodeOffToOnRequest = require('./encode_off_to_on_request');
13
+ const {invoiceNetworks} = require('./constants');
14
14
  const makePrivateKey = require('./make_private_key');
15
15
 
16
16
  const bufferAsHex = buffer => buffer.toString('hex');
@@ -77,15 +77,13 @@ module.exports = (args, cbk) => {
77
77
  // Get the network name for creating the private key
78
78
  getNetwork: ['validate', ({}, cbk) => getNetwork({lnd: args.lnd}, cbk)],
79
79
 
80
- // Bitcoinjs network details
80
+ // Check that the network is supported
81
81
  network: ['getNetwork', ({getNetwork}, cbk) => {
82
- const network = networks[getNetwork.bitcoinjs];
83
-
84
- if (!network) {
82
+ if (!invoiceNetworks[getNetwork.network]) {
85
83
  return cbk([400, 'UnsupportedNetworkToStartOffToOnSwapOn']);
86
84
  }
87
85
 
88
- return cbk(null, network);
86
+ return cbk(null, getNetwork.network);
89
87
  }],
90
88
 
91
89
  // Generate the claim coop key
@@ -7,13 +7,13 @@ const {getHeight} = require('ln-service');
7
7
  const {getIdentity} = require('ln-service');
8
8
  const {getNetwork} = require('ln-sync');
9
9
  const {getPublicKey} = require('ln-service');
10
- const {networks} = require('bitcoinjs-lib');
11
10
  const {parsePaymentRequest} = require('ln-service');
12
11
  const {pointFromScalar} = require('tiny-secp256k1');
13
12
  const {returnResult} = require('asyncjs-util');
14
13
 
15
14
  const decodeOffToOnRequest = require('./decode_off_to_on_request');
16
15
  const encodeOffToOnResponse = require('./encode_off_to_on_response');
16
+ const {invoiceNetworks} = require('./constants');
17
17
  const makePrivateKey = require('./make_private_key');
18
18
 
19
19
  const bufferAsHex = buffer => buffer.toString('hex');
@@ -107,15 +107,13 @@ module.exports = (args, cbk) => {
107
107
  });
108
108
  }],
109
109
 
110
- // Bitcoinjs network name
110
+ // Check that the network is supported
111
111
  network: ['getNetwork', ({getNetwork}, cbk) => {
112
- const network = networks[getNetwork.bitcoinjs];
113
-
114
- if (!network) {
112
+ if (!invoiceNetworks[getNetwork.network]) {
115
113
  return cbk([400, 'UnsupportedNetworkForOnToOffSwap']);
116
114
  }
117
115
 
118
- return cbk(null, network);
116
+ return cbk(null, getNetwork.network);
119
117
  }],
120
118
 
121
119
  // Generate the refund coop key
@@ -1,55 +0,0 @@
1
- const {address} = require('bitcoinjs-lib');
2
- const {networks} = require('bitcoinjs-lib');
3
-
4
- const bufferAsHex = buffer => buffer.toString('hex');
5
- const byteLengthForP2tr = 32;
6
- const {fromBech32} = address;
7
- const prefixForP2tr = '5120';
8
- const toOutputScript = (a, n) => address.toOutputScript(a, n).toString('hex');
9
- const versionTaproot = 1;
10
-
11
- /** Get the output script for an address
12
-
13
- {
14
- address: <Address String>
15
- network: <BitcoinJs Network Name String>
16
- }
17
-
18
- @throws
19
- <Error>
20
-
21
- @returns
22
- {
23
- script: <Output Script Hex String>
24
- }
25
- */
26
- module.exports = ({address, network}) => {
27
- try {
28
- return {
29
- script: bufferAsHex(toOutputScript(address, networks[network])),
30
- };
31
- } catch (err) {
32
- // Exit early when this is not a bech32 address
33
- try {
34
- fromBech32(address);
35
- } catch (_) {
36
- throw err;
37
- }
38
-
39
- const {data, prefix, version} = fromBech32(address);
40
-
41
- if (prefix !== networks[network].bech32) {
42
- throw new Error('InvalidNetworkToConvertAddressToOutputScript');
43
- }
44
-
45
- if (version !== versionTaproot) {
46
- throw new Error('UnexpectedVersionOfAddressToConverToOutputScript');
47
- }
48
-
49
- if (data.length !== byteLengthForP2tr) {
50
- throw new Error('UnexpectedByteLengthForPayToTaprootAddress');
51
- }
52
-
53
- return {script: `${prefixForP2tr}${bufferAsHex(data)}`};
54
- }
55
- };