@btc-vision/transaction 1.0.111 → 1.0.113
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/browser/_version.d.ts +1 -1
- package/browser/generators/Generator.d.ts +2 -0
- package/browser/index.js +1 -1
- package/browser/keypair/AddressVerificator.d.ts +15 -3
- package/browser/keypair/EcKeyPair.d.ts +9 -4
- package/browser/keypair/Wallet.d.ts +1 -0
- package/browser/signer/TweakedSigner.d.ts +2 -2
- package/browser/transaction/builders/FundingTransaction.d.ts +2 -1
- package/browser/transaction/builders/MultiSignTransaction.d.ts +2 -1
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +1 -1
- package/browser/transaction/builders/TransactionBuilder.d.ts +3 -2
- package/browser/transaction/shared/TweakedTransaction.d.ts +8 -7
- package/browser/verification/TapscriptVerificator.d.ts +1 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/generators/Generator.d.ts +2 -0
- package/build/generators/Generator.js +5 -0
- package/build/generators/builders/CalldataGenerator.js +4 -2
- package/build/generators/builders/DeploymentGenerator.js +7 -4
- package/build/keypair/AddressVerificator.d.ts +15 -3
- package/build/keypair/AddressVerificator.js +74 -3
- package/build/keypair/EcKeyPair.d.ts +9 -4
- package/build/keypair/EcKeyPair.js +69 -7
- package/build/keypair/Wallet.d.ts +1 -0
- package/build/keypair/Wallet.js +5 -4
- package/build/signer/TweakedSigner.d.ts +2 -2
- package/build/signer/TweakedSigner.js +1 -1
- package/build/transaction/builders/CustomScriptTransaction.js +3 -3
- package/build/transaction/builders/DeploymentTransaction.js +4 -4
- package/build/transaction/builders/FundingTransaction.d.ts +2 -1
- package/build/transaction/builders/FundingTransaction.js +18 -4
- package/build/transaction/builders/MultiSignTransaction.d.ts +2 -1
- package/build/transaction/builders/SharedInteractionTransaction.d.ts +1 -1
- package/build/transaction/builders/SharedInteractionTransaction.js +4 -4
- package/build/transaction/builders/TransactionBuilder.d.ts +3 -2
- package/build/transaction/builders/TransactionBuilder.js +7 -2
- package/build/transaction/builders/UnwrapTransaction.js +2 -2
- package/build/transaction/shared/TweakedTransaction.d.ts +8 -7
- package/build/transaction/shared/TweakedTransaction.js +1 -1
- package/build/verification/TapscriptVerificator.d.ts +1 -1
- package/build/verification/TapscriptVerificator.js +2 -2
- package/package.json +2 -1
- package/src/_version.ts +1 -1
- package/src/generators/Generator.ts +12 -0
- package/src/generators/builders/CalldataGenerator.ts +6 -3
- package/src/generators/builders/DeploymentGenerator.ts +9 -4
- package/src/keypair/AddressVerificator.ts +144 -5
- package/src/keypair/EcKeyPair.ts +149 -13
- package/src/keypair/Wallet.ts +11 -3
- package/src/signer/TweakedSigner.ts +3 -2
- package/src/transaction/builders/CustomScriptTransaction.ts +6 -5
- package/src/transaction/builders/DeploymentTransaction.ts +6 -5
- package/src/transaction/builders/FundingTransaction.ts +18 -5
- package/src/transaction/builders/MultiSignTransaction.ts +6 -2
- package/src/transaction/builders/SharedInteractionTransaction.ts +5 -5
- package/src/transaction/builders/TransactionBuilder.ts +36 -10
- package/src/transaction/builders/UnwrapSegwitTransaction.ts +7 -3
- package/src/transaction/builders/UnwrapTransaction.ts +2 -2
- package/src/transaction/builders/WrapTransaction.ts +1 -6
- package/src/transaction/shared/TweakedTransaction.ts +12 -12
- package/src/verification/TapscriptVerificator.ts +3 -3
package/src/keypair/EcKeyPair.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as ecc from '@bitcoinerlab/secp256k1';
|
|
2
2
|
import { Address } from '@btc-vision/bsi-binary';
|
|
3
3
|
import bip32, { BIP32API, BIP32Factory, BIP32Interface } from 'bip32';
|
|
4
|
-
import { address, initEccLib, Network, networks, payments } from 'bitcoinjs-lib';
|
|
4
|
+
import { address, initEccLib, Network, networks, payments, Signer } from 'bitcoinjs-lib';
|
|
5
5
|
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
6
6
|
import { ECPairAPI, ECPairFactory, ECPairInterface } from 'ecpair';
|
|
7
7
|
import { IWallet } from './interfaces/IWallet.js';
|
|
8
|
+
import { CURVE, Point, utils } from '@noble/secp256k1';
|
|
9
|
+
import { taggedHash } from 'bitcoinjs-lib/src/crypto.js';
|
|
8
10
|
|
|
9
11
|
initEccLib(ecc);
|
|
10
12
|
|
|
@@ -42,23 +44,28 @@ export class EcKeyPair {
|
|
|
42
44
|
* @returns {ECPairInterface} - The generated keypair
|
|
43
45
|
*/
|
|
44
46
|
public static fromPrivateKey(
|
|
45
|
-
privateKey: Buffer,
|
|
47
|
+
privateKey: Buffer | Uint8Array,
|
|
46
48
|
network: Network = networks.bitcoin,
|
|
47
49
|
): ECPairInterface {
|
|
48
|
-
return this.ECPair.fromPrivateKey(
|
|
50
|
+
return this.ECPair.fromPrivateKey(
|
|
51
|
+
!Buffer.isBuffer(privateKey) ? Buffer.from(privateKey) : privateKey,
|
|
52
|
+
{ network },
|
|
53
|
+
);
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
/**
|
|
52
57
|
* Generate a keypair from a public key
|
|
53
|
-
* @param {Buffer} publicKey - The public key to use
|
|
58
|
+
* @param {Buffer | Uint8Array} publicKey - The public key to use
|
|
54
59
|
* @param {Network} network - The network to use
|
|
55
60
|
* @returns {ECPairInterface} - The generated keypair
|
|
56
61
|
*/
|
|
57
62
|
public static fromPublicKey(
|
|
58
|
-
publicKey: Buffer,
|
|
63
|
+
publicKey: Buffer | Uint8Array,
|
|
59
64
|
network: Network = networks.bitcoin,
|
|
60
65
|
): ECPairInterface {
|
|
61
|
-
|
|
66
|
+
const buf = !Buffer.isBuffer(publicKey) ? Buffer.from(publicKey) : publicKey;
|
|
67
|
+
|
|
68
|
+
return this.ECPair.fromPublicKey(buf, { network });
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
/**
|
|
@@ -122,7 +129,7 @@ export class EcKeyPair {
|
|
|
122
129
|
throw new Error('Failed to regenerate key');
|
|
123
130
|
}
|
|
124
131
|
|
|
125
|
-
return key.publicKey;
|
|
132
|
+
return Buffer.from(key.publicKey);
|
|
126
133
|
});
|
|
127
134
|
}
|
|
128
135
|
|
|
@@ -136,7 +143,7 @@ export class EcKeyPair {
|
|
|
136
143
|
keyPair: ECPairInterface,
|
|
137
144
|
network: Network = networks.bitcoin,
|
|
138
145
|
): Address {
|
|
139
|
-
const res = payments.p2wpkh({ pubkey: keyPair.publicKey, network: network });
|
|
146
|
+
const res = payments.p2wpkh({ pubkey: Buffer.from(keyPair.publicKey), network: network });
|
|
140
147
|
|
|
141
148
|
if (!res.address) {
|
|
142
149
|
throw new Error('Failed to generate wallet');
|
|
@@ -145,6 +152,96 @@ export class EcKeyPair {
|
|
|
145
152
|
return res.address;
|
|
146
153
|
}
|
|
147
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Get the address of a tweaked public key
|
|
157
|
+
* @param {string} tweakedPubKeyHex - The tweaked public key hex string
|
|
158
|
+
* @param {Network} network - The network to use
|
|
159
|
+
* @returns {Address} - The address
|
|
160
|
+
* @throws {Error} - If the address cannot be generated
|
|
161
|
+
*/
|
|
162
|
+
public static tweakedPubKeyToAddress(tweakedPubKeyHex: string, network: Network): string {
|
|
163
|
+
if (tweakedPubKeyHex.startsWith('0x')) {
|
|
164
|
+
tweakedPubKeyHex = tweakedPubKeyHex.slice(2);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Convert the tweaked public key hex string to a Buffer
|
|
168
|
+
const tweakedPubKeyBuffer = Buffer.from(tweakedPubKeyHex, 'hex');
|
|
169
|
+
|
|
170
|
+
// Generate the Taproot address using the p2tr payment method
|
|
171
|
+
const { address } = payments.p2tr({
|
|
172
|
+
pubkey: toXOnly(tweakedPubKeyBuffer),
|
|
173
|
+
network: network,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (!address) {
|
|
177
|
+
throw new Error('Failed to generate Taproot address');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return address;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get the address of a xOnly tweaked public key
|
|
185
|
+
* @param {string} tweakedPubKeyHex - The xOnly tweaked public key hex string
|
|
186
|
+
* @param {Network} network - The network to use
|
|
187
|
+
* @returns {Address} - The address
|
|
188
|
+
* @throws {Error} - If the address cannot be generated
|
|
189
|
+
*/
|
|
190
|
+
public static xOnlyTweakedPubKeyToAddress(tweakedPubKeyHex: string, network: Network): string {
|
|
191
|
+
if (tweakedPubKeyHex.startsWith('0x')) {
|
|
192
|
+
tweakedPubKeyHex = tweakedPubKeyHex.slice(2);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Convert the tweaked public key hex string to a Buffer
|
|
196
|
+
const tweakedPubKeyBuffer = Buffer.from(tweakedPubKeyHex, 'hex');
|
|
197
|
+
|
|
198
|
+
// Generate the Taproot address using the p2tr payment method
|
|
199
|
+
const { address } = payments.p2tr({
|
|
200
|
+
pubkey: tweakedPubKeyBuffer,
|
|
201
|
+
network: network,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (!address) {
|
|
205
|
+
throw new Error('Failed to generate Taproot address');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return address;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Tweak a public key
|
|
213
|
+
* @param {string} compressedPubKeyHex - The compressed public key hex string
|
|
214
|
+
* @returns {string} - The tweaked public key hex string
|
|
215
|
+
* @throws {Error} - If the public key cannot be tweaked
|
|
216
|
+
*/
|
|
217
|
+
public static tweakPublicKey(compressedPubKeyHex: string): string {
|
|
218
|
+
if (compressedPubKeyHex.startsWith('0x')) {
|
|
219
|
+
compressedPubKeyHex = compressedPubKeyHex.slice(2);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Convert the compressed public key hex string to a Point on the curve
|
|
223
|
+
let P = Point.fromHex(compressedPubKeyHex);
|
|
224
|
+
|
|
225
|
+
// Ensure the point has an even y-coordinate
|
|
226
|
+
if (!P.hasEvenY()) {
|
|
227
|
+
// Negate the point to get an even y-coordinate
|
|
228
|
+
P = P.negate();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Get the x-coordinate (32 bytes) of the point
|
|
232
|
+
const x = P.toRawBytes(true).slice(1); // Remove the prefix byte
|
|
233
|
+
|
|
234
|
+
// Compute the tweak t = H_tapTweak(x)
|
|
235
|
+
const tHash = taggedHash('TapTweak', Buffer.from(x));
|
|
236
|
+
const t = utils.mod(BigInt('0x' + Buffer.from(tHash).toString('hex')), CURVE.n);
|
|
237
|
+
|
|
238
|
+
// Compute Q = P + t*G (where G is the generator point)
|
|
239
|
+
const Q = P.add(Point.BASE.multiply(t));
|
|
240
|
+
|
|
241
|
+
// Return the tweaked public key in compressed form (hex string)
|
|
242
|
+
return Q.toHex(true);
|
|
243
|
+
}
|
|
244
|
+
|
|
148
245
|
/**
|
|
149
246
|
* Generate a random wallet
|
|
150
247
|
* @param {Network} network - The network to use
|
|
@@ -164,7 +261,7 @@ export class EcKeyPair {
|
|
|
164
261
|
return {
|
|
165
262
|
address: wallet,
|
|
166
263
|
privateKey: keyPair.toWIF(),
|
|
167
|
-
publicKey: keyPair.publicKey.toString('hex'),
|
|
264
|
+
publicKey: Buffer.from(keyPair.publicKey).toString('hex'),
|
|
168
265
|
};
|
|
169
266
|
}
|
|
170
267
|
|
|
@@ -181,6 +278,28 @@ export class EcKeyPair {
|
|
|
181
278
|
return !!address.toOutputScript(contractAddress, network);
|
|
182
279
|
}
|
|
183
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Get the legacy segwit address from a keypair
|
|
283
|
+
* @param {ECPairInterface} keyPair - The keypair to get the address for
|
|
284
|
+
* @param {Network} network - The network to use
|
|
285
|
+
* @returns {Address} - The legacy address
|
|
286
|
+
*/
|
|
287
|
+
public static getLegacySegwitAddress(
|
|
288
|
+
keyPair: ECPairInterface,
|
|
289
|
+
network: Network = networks.bitcoin,
|
|
290
|
+
): Address {
|
|
291
|
+
const wallet = payments.p2sh({
|
|
292
|
+
redeem: payments.p2wpkh({ pubkey: Buffer.from(keyPair.publicKey), network: network }),
|
|
293
|
+
network: network,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
if (!wallet.address) {
|
|
297
|
+
throw new Error('Failed to generate wallet');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return wallet.address;
|
|
301
|
+
}
|
|
302
|
+
|
|
184
303
|
/**
|
|
185
304
|
* Get the legacy address from a keypair
|
|
186
305
|
* @param {ECPairInterface} keyPair - The keypair to get the address for
|
|
@@ -191,8 +310,7 @@ export class EcKeyPair {
|
|
|
191
310
|
keyPair: ECPairInterface,
|
|
192
311
|
network: Network = networks.bitcoin,
|
|
193
312
|
): Address {
|
|
194
|
-
const wallet = payments.p2pkh({ pubkey: keyPair.publicKey, network: network });
|
|
195
|
-
|
|
313
|
+
const wallet = payments.p2pkh({ pubkey: Buffer.from(keyPair.publicKey), network: network });
|
|
196
314
|
if (!wallet.address) {
|
|
197
315
|
throw new Error('Failed to generate wallet');
|
|
198
316
|
}
|
|
@@ -200,6 +318,24 @@ export class EcKeyPair {
|
|
|
200
318
|
return wallet.address;
|
|
201
319
|
}
|
|
202
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Get the legacy address from a keypair
|
|
323
|
+
* @param {ECPairInterface} keyPair - The keypair to get the address for
|
|
324
|
+
* @param {Network} network - The network to use
|
|
325
|
+
* @returns {Address} - The legacy address
|
|
326
|
+
*/
|
|
327
|
+
public static getP2PKAddress(
|
|
328
|
+
keyPair: ECPairInterface,
|
|
329
|
+
network: Network = networks.bitcoin,
|
|
330
|
+
): Address {
|
|
331
|
+
const wallet = payments.p2pk({ pubkey: Buffer.from(keyPair.publicKey), network: network });
|
|
332
|
+
if (!wallet.output) {
|
|
333
|
+
throw new Error('Failed to generate wallet');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return '0x' + wallet.output.toString('hex');
|
|
337
|
+
}
|
|
338
|
+
|
|
203
339
|
/**
|
|
204
340
|
* Generate a random keypair
|
|
205
341
|
* @param {Network} network - The network to use
|
|
@@ -228,11 +364,11 @@ export class EcKeyPair {
|
|
|
228
364
|
* @returns {Address} - The taproot address
|
|
229
365
|
*/
|
|
230
366
|
public static getTaprootAddress(
|
|
231
|
-
keyPair: ECPairInterface,
|
|
367
|
+
keyPair: ECPairInterface | Signer,
|
|
232
368
|
network: Network = networks.bitcoin,
|
|
233
369
|
): Address {
|
|
234
370
|
const { address } = payments.p2tr({
|
|
235
|
-
internalPubkey: toXOnly(keyPair.publicKey),
|
|
371
|
+
internalPubkey: toXOnly(Buffer.from(keyPair.publicKey)),
|
|
236
372
|
network: network,
|
|
237
373
|
});
|
|
238
374
|
|
package/src/keypair/Wallet.ts
CHANGED
|
@@ -33,6 +33,12 @@ export class Wallet {
|
|
|
33
33
|
*/
|
|
34
34
|
private readonly _legacy: Address;
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Buffer public key
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
private readonly _bufferPubKey: Buffer;
|
|
41
|
+
|
|
36
42
|
constructor(
|
|
37
43
|
wallet: IWallet,
|
|
38
44
|
public readonly network: Network = networks.bitcoin,
|
|
@@ -42,6 +48,8 @@ export class Wallet {
|
|
|
42
48
|
this._p2wpkh = EcKeyPair.getP2WPKHAddress(this._keypair, this.network);
|
|
43
49
|
this._p2tr = EcKeyPair.getTaprootAddress(this._keypair, this.network);
|
|
44
50
|
this._legacy = EcKeyPair.getLegacyAddress(this._keypair, this.network);
|
|
51
|
+
|
|
52
|
+
this._bufferPubKey = Buffer.from(wallet.publicKey, 'hex');
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
/**
|
|
@@ -92,9 +100,9 @@ export class Wallet {
|
|
|
92
100
|
* @returns {Buffer}
|
|
93
101
|
*/
|
|
94
102
|
public get publicKey(): Buffer {
|
|
95
|
-
if (!this.
|
|
103
|
+
if (!this._bufferPubKey) throw new Error('Public key not set');
|
|
96
104
|
|
|
97
|
-
return this.
|
|
105
|
+
return this._bufferPubKey;
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
/**
|
|
@@ -105,7 +113,7 @@ export class Wallet {
|
|
|
105
113
|
public get xOnly(): Buffer {
|
|
106
114
|
if (!this.keypair) throw new Error('Keypair not set');
|
|
107
115
|
|
|
108
|
-
return toXOnly(this.
|
|
116
|
+
return toXOnly(this._bufferPubKey);
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
/**
|
|
@@ -31,8 +31,9 @@ export class TweakedSigner {
|
|
|
31
31
|
* Tweak a signer
|
|
32
32
|
* @param {Signer} signer - The signer to tweak
|
|
33
33
|
* @param {TweakSettings} opts - The tweak settings
|
|
34
|
+
* @returns {ECPairInterface} - The tweaked signer
|
|
34
35
|
*/
|
|
35
|
-
public static tweakSigner(signer: ECPairInterface, opts: TweakSettings = {}):
|
|
36
|
+
public static tweakSigner(signer: ECPairInterface, opts: TweakSettings = {}): ECPairInterface {
|
|
36
37
|
let privateKey: Uint8Array | undefined = signer.privateKey;
|
|
37
38
|
if (!privateKey) {
|
|
38
39
|
throw new Error('Private key is required for tweaking signer!');
|
|
@@ -44,7 +45,7 @@ export class TweakedSigner {
|
|
|
44
45
|
|
|
45
46
|
const tweakedPrivateKey = ecc.privateAdd(
|
|
46
47
|
privateKey,
|
|
47
|
-
tapTweakHash(toXOnly(signer.publicKey), opts.tweakHash),
|
|
48
|
+
tapTweakHash(toXOnly(Buffer.from(signer.publicKey)), opts.tweakHash),
|
|
48
49
|
);
|
|
49
50
|
|
|
50
51
|
if (!tweakedPrivateKey) {
|
|
@@ -11,6 +11,7 @@ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
|
11
11
|
import { AddressGenerator } from '../../generators/AddressGenerator.js';
|
|
12
12
|
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
13
13
|
import { PsbtInput } from 'bip174/src/lib/interfaces.js';
|
|
14
|
+
import { ECPairInterface } from 'ecpair';
|
|
14
15
|
|
|
15
16
|
export interface ICustomTransactionParameters extends SharedInteractionParameters {
|
|
16
17
|
readonly script: (Buffer | Stack)[];
|
|
@@ -72,7 +73,7 @@ export class CustomScriptTransaction extends TransactionBuilder<TransactionType.
|
|
|
72
73
|
* The contract signer
|
|
73
74
|
* @private
|
|
74
75
|
*/
|
|
75
|
-
private readonly contractSigner: Signer;
|
|
76
|
+
private readonly contractSigner: Signer | ECPairInterface;
|
|
76
77
|
|
|
77
78
|
/**
|
|
78
79
|
* The contract salt random bytes
|
|
@@ -136,7 +137,7 @@ export class CustomScriptTransaction extends TransactionBuilder<TransactionType.
|
|
|
136
137
|
* @protected
|
|
137
138
|
*/
|
|
138
139
|
protected contractSignerXOnlyPubKey(): Buffer {
|
|
139
|
-
return toXOnly(this.contractSigner.publicKey);
|
|
140
|
+
return toXOnly(Buffer.from(this.contractSigner.publicKey));
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
/**
|
|
@@ -261,7 +262,7 @@ export class CustomScriptTransaction extends TransactionBuilder<TransactionType.
|
|
|
261
262
|
if (!this.tapLeafScript) {
|
|
262
263
|
throw new Error('Tap leaf script is required');
|
|
263
264
|
}
|
|
264
|
-
|
|
265
|
+
|
|
265
266
|
const scriptSolution = this.witnesses;
|
|
266
267
|
const witness = scriptSolution
|
|
267
268
|
.concat(this.tapLeafScript.script)
|
|
@@ -277,10 +278,10 @@ export class CustomScriptTransaction extends TransactionBuilder<TransactionType.
|
|
|
277
278
|
* @private
|
|
278
279
|
*/
|
|
279
280
|
private getPubKeys(): Buffer[] {
|
|
280
|
-
const pubkeys = [this.signer.publicKey];
|
|
281
|
+
const pubkeys = [Buffer.from(this.signer.publicKey)];
|
|
281
282
|
|
|
282
283
|
if (this.contractSigner) {
|
|
283
|
-
pubkeys.push(this.contractSigner.publicKey);
|
|
284
|
+
pubkeys.push(Buffer.from(this.contractSigner.publicKey));
|
|
284
285
|
}
|
|
285
286
|
|
|
286
287
|
return pubkeys;
|
|
@@ -13,6 +13,7 @@ import { Compressor } from '../../bytecode/Compressor.js';
|
|
|
13
13
|
import { AddressGenerator } from '../../generators/AddressGenerator.js';
|
|
14
14
|
import { Address } from '@btc-vision/bsi-binary';
|
|
15
15
|
import { SharedInteractionTransaction } from './SharedInteractionTransaction.js';
|
|
16
|
+
import { ECPairInterface } from 'ecpair';
|
|
16
17
|
|
|
17
18
|
export class DeploymentTransaction extends TransactionBuilder<TransactionType.DEPLOYMENT> {
|
|
18
19
|
public static readonly MAXIMUM_CONTRACT_SIZE = 128 * 1024;
|
|
@@ -75,7 +76,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
75
76
|
* The contract signer
|
|
76
77
|
* @private
|
|
77
78
|
*/
|
|
78
|
-
private readonly contractSigner: Signer;
|
|
79
|
+
private readonly contractSigner: Signer | ECPairInterface;
|
|
79
80
|
|
|
80
81
|
/**
|
|
81
82
|
* The contract salt random bytes
|
|
@@ -100,7 +101,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
100
101
|
this.contractSigner = EcKeyPair.fromSeedKeyPair(this.contractSeed, this.network);
|
|
101
102
|
|
|
102
103
|
this.deploymentGenerator = new DeploymentGenerator(
|
|
103
|
-
this.
|
|
104
|
+
Buffer.from(this.signer.publicKey),
|
|
104
105
|
this.contractSignerXOnlyPubKey(),
|
|
105
106
|
this.network,
|
|
106
107
|
);
|
|
@@ -145,7 +146,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
145
146
|
* @protected
|
|
146
147
|
*/
|
|
147
148
|
protected contractSignerXOnlyPubKey(): Buffer {
|
|
148
|
-
return toXOnly(this.contractSigner.publicKey);
|
|
149
|
+
return toXOnly(Buffer.from(this.contractSigner.publicKey));
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
/**
|
|
@@ -323,10 +324,10 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
323
324
|
* @private
|
|
324
325
|
*/
|
|
325
326
|
private getPubKeys(): Buffer[] {
|
|
326
|
-
const pubkeys = [this.signer.publicKey];
|
|
327
|
+
const pubkeys = [Buffer.from(this.signer.publicKey)];
|
|
327
328
|
|
|
328
329
|
if (this.contractSigner) {
|
|
329
|
-
pubkeys.push(this.contractSigner.publicKey);
|
|
330
|
+
pubkeys.push(Buffer.from(this.contractSigner.publicKey));
|
|
330
331
|
}
|
|
331
332
|
|
|
332
333
|
return pubkeys;
|
|
@@ -2,6 +2,7 @@ import { TransactionType } from '../enums/TransactionType.js';
|
|
|
2
2
|
import { IFundingTransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
3
3
|
import { Signer } from 'bitcoinjs-lib';
|
|
4
4
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
5
|
+
import { ECPairInterface } from 'ecpair';
|
|
5
6
|
|
|
6
7
|
export class FundingTransaction extends TransactionBuilder<TransactionType.FUNDING> {
|
|
7
8
|
public readonly type: TransactionType.FUNDING = TransactionType.FUNDING;
|
|
@@ -27,6 +28,11 @@ export class FundingTransaction extends TransactionBuilder<TransactionType.FUNDI
|
|
|
27
28
|
|
|
28
29
|
if (this.splitInputsInto > 1) {
|
|
29
30
|
this.splitInputs(this.amount);
|
|
31
|
+
} else if (this.isPubKeyDestination) {
|
|
32
|
+
this.addOutput({
|
|
33
|
+
value: Number(this.amount),
|
|
34
|
+
script: Buffer.from(this.to.slice(2), 'hex'),
|
|
35
|
+
});
|
|
30
36
|
} else {
|
|
31
37
|
this.addOutput({
|
|
32
38
|
value: Number(this.amount),
|
|
@@ -45,14 +51,21 @@ export class FundingTransaction extends TransactionBuilder<TransactionType.FUNDI
|
|
|
45
51
|
const splitAmount = amountSpent / BigInt(this.splitInputsInto);
|
|
46
52
|
|
|
47
53
|
for (let i = 0; i < this.splitInputsInto; i++) {
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
if (this.isPubKeyDestination) {
|
|
55
|
+
this.addOutput({
|
|
56
|
+
value: Number(splitAmount),
|
|
57
|
+
script: Buffer.from(this.to.slice(2), 'hex'),
|
|
58
|
+
});
|
|
59
|
+
} else {
|
|
60
|
+
this.addOutput({
|
|
61
|
+
value: Number(splitAmount),
|
|
62
|
+
address: this.to,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
52
65
|
}
|
|
53
66
|
}
|
|
54
67
|
|
|
55
|
-
protected override getSignerKey(): Signer {
|
|
68
|
+
protected override getSignerKey(): Signer | ECPairInterface {
|
|
56
69
|
return this.signer;
|
|
57
70
|
}
|
|
58
71
|
}
|
|
@@ -10,6 +10,7 @@ import { Address } from '@btc-vision/bsi-binary';
|
|
|
10
10
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
11
11
|
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
12
12
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
13
|
+
import { ECPairInterface } from 'ecpair';
|
|
13
14
|
|
|
14
15
|
export interface MultiSignParameters
|
|
15
16
|
extends Omit<ITransactionParameters, 'priorityFee' | 'signer'> {
|
|
@@ -172,7 +173,7 @@ export class MultiSignTransaction extends TransactionBuilder<TransactionType.MUL
|
|
|
172
173
|
*/
|
|
173
174
|
public static signPartial(
|
|
174
175
|
psbt: Psbt,
|
|
175
|
-
signer: Signer,
|
|
176
|
+
signer: Signer | ECPairInterface,
|
|
176
177
|
originalInputCount: number,
|
|
177
178
|
minimums: number[],
|
|
178
179
|
): {
|
|
@@ -498,7 +499,10 @@ export class MultiSignTransaction extends TransactionBuilder<TransactionType.MUL
|
|
|
498
499
|
* @returns {Promise<boolean>}
|
|
499
500
|
* @throws {Error} - If something went wrong while building the transaction
|
|
500
501
|
*/
|
|
501
|
-
protected override async internalBuildTransaction(
|
|
502
|
+
protected override async internalBuildTransaction(
|
|
503
|
+
transaction: Psbt,
|
|
504
|
+
checkPartialSigs: boolean = false,
|
|
505
|
+
): Promise<boolean> {
|
|
502
506
|
const inputs: PsbtInputExtended[] = this.getInputs();
|
|
503
507
|
const outputs: PsbtOutputExtended[] = this.getOutputs();
|
|
504
508
|
|
|
@@ -50,7 +50,7 @@ export abstract class SharedInteractionTransaction<
|
|
|
50
50
|
* Script signer for the interaction
|
|
51
51
|
* @protected
|
|
52
52
|
*/
|
|
53
|
-
protected readonly scriptSigner: Signer;
|
|
53
|
+
protected readonly scriptSigner: Signer | ECPairInterface;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Disable auto refund
|
|
@@ -73,7 +73,7 @@ export abstract class SharedInteractionTransaction<
|
|
|
73
73
|
this.scriptSigner = this.generateKeyPairFromSeed();
|
|
74
74
|
|
|
75
75
|
this.calldataGenerator = new CalldataGenerator(
|
|
76
|
-
this.
|
|
76
|
+
Buffer.from(this.signer.publicKey),
|
|
77
77
|
this.scriptSignerXOnlyPubKey(),
|
|
78
78
|
this.network,
|
|
79
79
|
);
|
|
@@ -113,7 +113,7 @@ export abstract class SharedInteractionTransaction<
|
|
|
113
113
|
* @returns {Buffer} The internal pubkey as an x-only key
|
|
114
114
|
*/
|
|
115
115
|
protected scriptSignerXOnlyPubKey(): Buffer {
|
|
116
|
-
return toXOnly(this.scriptSigner.publicKey);
|
|
116
|
+
return toXOnly(Buffer.from(this.scriptSigner.publicKey));
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
/**
|
|
@@ -362,10 +362,10 @@ export abstract class SharedInteractionTransaction<
|
|
|
362
362
|
* @returns {Buffer[]} The public keys
|
|
363
363
|
*/
|
|
364
364
|
private getPubKeys(): Buffer[] {
|
|
365
|
-
const pubkeys = [this.signer.publicKey];
|
|
365
|
+
const pubkeys = [Buffer.from(this.signer.publicKey)];
|
|
366
366
|
|
|
367
367
|
if (this.scriptSigner) {
|
|
368
|
-
pubkeys.push(this.scriptSigner.publicKey);
|
|
368
|
+
pubkeys.push(Buffer.from(this.scriptSigner.publicKey));
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
return pubkeys;
|
|
@@ -43,70 +43,90 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
43
43
|
* @description Cost in satoshis of the transaction fee
|
|
44
44
|
*/
|
|
45
45
|
public transactionFee: bigint = 0n;
|
|
46
|
+
|
|
46
47
|
/**
|
|
47
48
|
* @description The estimated fees of the transaction
|
|
48
49
|
*/
|
|
49
50
|
public estimatedFees: bigint = 0n;
|
|
51
|
+
|
|
50
52
|
/**
|
|
51
53
|
* @param {ITransactionParameters} parameters - The transaction parameters
|
|
52
54
|
*/
|
|
53
|
-
|
|
54
55
|
public optionalOutputs: PsbtOutputExtended[] | undefined;
|
|
56
|
+
|
|
55
57
|
/**
|
|
56
58
|
* @description The transaction itself.
|
|
57
59
|
*/
|
|
58
60
|
protected transaction: Psbt;
|
|
61
|
+
|
|
59
62
|
/**
|
|
60
63
|
* @description Inputs to update later on.
|
|
61
64
|
*/
|
|
62
65
|
protected readonly updateInputs: UpdateInput[] = [];
|
|
66
|
+
|
|
63
67
|
/**
|
|
64
68
|
* @description The outputs of the transaction
|
|
65
69
|
*/
|
|
66
70
|
protected readonly outputs: PsbtOutputExtended[] = [];
|
|
71
|
+
|
|
67
72
|
/**
|
|
68
73
|
* @description Output that will be used to pay the fees
|
|
69
74
|
*/
|
|
70
75
|
protected feeOutput: PsbtOutputExtended | null = null;
|
|
76
|
+
|
|
71
77
|
/**
|
|
72
78
|
* @description The total amount of satoshis in the inputs
|
|
73
79
|
*/
|
|
74
80
|
protected totalInputAmount: bigint;
|
|
81
|
+
|
|
75
82
|
/**
|
|
76
83
|
* @description The signer of the transaction
|
|
77
84
|
*/
|
|
78
|
-
protected readonly signer: Signer;
|
|
85
|
+
protected readonly signer: Signer | ECPairInterface;
|
|
86
|
+
|
|
79
87
|
/**
|
|
80
88
|
* @description The network where the transaction will be broadcasted
|
|
81
89
|
*/
|
|
82
90
|
protected readonly network: Network;
|
|
91
|
+
|
|
83
92
|
/**
|
|
84
93
|
* @description The fee rate of the transaction
|
|
85
94
|
*/
|
|
86
95
|
protected readonly feeRate: number;
|
|
96
|
+
|
|
87
97
|
/**
|
|
88
98
|
* @description The opnet priority fee of the transaction
|
|
89
99
|
*/
|
|
90
100
|
protected priorityFee: bigint;
|
|
101
|
+
|
|
91
102
|
/**
|
|
92
103
|
* @description The utxos used in the transaction
|
|
93
104
|
*/
|
|
94
105
|
protected utxos: UTXO[];
|
|
106
|
+
|
|
95
107
|
/**
|
|
96
108
|
* @description The address where the transaction is sent to
|
|
97
109
|
* @protected
|
|
98
110
|
*/
|
|
99
111
|
protected to: Address | undefined;
|
|
112
|
+
|
|
100
113
|
/**
|
|
101
114
|
* @description The address where the transaction is sent from
|
|
102
115
|
* @protected
|
|
103
116
|
*/
|
|
104
117
|
protected from: Address;
|
|
118
|
+
|
|
105
119
|
/**
|
|
106
120
|
* @description The maximum fee rate of the transaction
|
|
107
121
|
*/
|
|
108
122
|
protected _maximumFeeRate: number = 100000000;
|
|
109
123
|
|
|
124
|
+
/**
|
|
125
|
+
* @description Is the destionation P2PK
|
|
126
|
+
* @protected
|
|
127
|
+
*/
|
|
128
|
+
protected isPubKeyDestination: boolean;
|
|
129
|
+
|
|
110
130
|
protected constructor(parameters: ITransactionParameters) {
|
|
111
131
|
super(parameters);
|
|
112
132
|
|
|
@@ -121,13 +141,11 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
121
141
|
this.utxos = parameters.utxos;
|
|
122
142
|
this.to = parameters.to || undefined;
|
|
123
143
|
|
|
144
|
+
this.isPubKeyDestination = this.to ? this.to.startsWith('0x') : false;
|
|
145
|
+
|
|
124
146
|
this.optionalOutputs = parameters.optionalOutputs;
|
|
125
147
|
|
|
126
|
-
this.from = TransactionBuilder.getFrom(
|
|
127
|
-
parameters.from,
|
|
128
|
-
this.signer as ECPairInterface,
|
|
129
|
-
this.network,
|
|
130
|
-
);
|
|
148
|
+
this.from = TransactionBuilder.getFrom(parameters.from, this.signer, this.network);
|
|
131
149
|
|
|
132
150
|
this.totalInputAmount = this.calculateTotalUTXOAmount();
|
|
133
151
|
|
|
@@ -143,7 +161,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
143
161
|
|
|
144
162
|
public static getFrom(
|
|
145
163
|
from: string | undefined,
|
|
146
|
-
keypair: ECPairInterface,
|
|
164
|
+
keypair: ECPairInterface | Signer,
|
|
147
165
|
network: Network,
|
|
148
166
|
): Address {
|
|
149
167
|
return from || EcKeyPair.getTaprootAddress(keypair, network);
|
|
@@ -231,7 +249,11 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
231
249
|
throw new Error('No UTXOs specified');
|
|
232
250
|
}
|
|
233
251
|
|
|
234
|
-
if (
|
|
252
|
+
if (
|
|
253
|
+
this.to &&
|
|
254
|
+
!this.isPubKeyDestination &&
|
|
255
|
+
!EcKeyPair.verifyContractAddress(this.to, this.network)
|
|
256
|
+
) {
|
|
235
257
|
throw new Error(
|
|
236
258
|
'Invalid contract address. The contract address must be a taproot address.',
|
|
237
259
|
);
|
|
@@ -261,7 +283,11 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
261
283
|
public async generateTransactionMinimalSignatures(
|
|
262
284
|
checkPartialSigs: boolean = false,
|
|
263
285
|
): Promise<void> {
|
|
264
|
-
if (
|
|
286
|
+
if (
|
|
287
|
+
this.to &&
|
|
288
|
+
!this.isPubKeyDestination &&
|
|
289
|
+
!EcKeyPair.verifyContractAddress(this.to, this.network)
|
|
290
|
+
) {
|
|
265
291
|
throw new Error(
|
|
266
292
|
'Invalid contract address. The contract address must be a taproot address.',
|
|
267
293
|
);
|