@btc-vision/transaction 1.0.110 → 1.0.112

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.
Files changed (43) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/generators/Generator.d.ts +2 -0
  3. package/browser/generators/builders/DeploymentGenerator.d.ts +1 -1
  4. package/browser/index.js +1 -1
  5. package/browser/keypair/EcKeyPair.d.ts +2 -0
  6. package/browser/transaction/builders/DeploymentTransaction.d.ts +3 -0
  7. package/browser/transaction/builders/SharedInteractionTransaction.d.ts +1 -0
  8. package/browser/transaction/builders/TransactionBuilder.d.ts +1 -0
  9. package/browser/transaction/interfaces/ITransactionParameters.d.ts +1 -0
  10. package/browser/verification/TapscriptVerificator.d.ts +2 -1
  11. package/build/_version.d.ts +1 -1
  12. package/build/_version.js +1 -1
  13. package/build/generators/Generator.d.ts +2 -0
  14. package/build/generators/Generator.js +5 -0
  15. package/build/generators/builders/CalldataGenerator.js +4 -2
  16. package/build/generators/builders/DeploymentGenerator.d.ts +1 -1
  17. package/build/generators/builders/DeploymentGenerator.js +13 -7
  18. package/build/keypair/EcKeyPair.d.ts +2 -0
  19. package/build/keypair/EcKeyPair.js +17 -0
  20. package/build/transaction/builders/DeploymentTransaction.d.ts +3 -0
  21. package/build/transaction/builders/DeploymentTransaction.js +21 -6
  22. package/build/transaction/builders/FundingTransaction.js +18 -4
  23. package/build/transaction/builders/SharedInteractionTransaction.d.ts +1 -0
  24. package/build/transaction/builders/SharedInteractionTransaction.js +2 -1
  25. package/build/transaction/builders/TransactionBuilder.d.ts +1 -0
  26. package/build/transaction/builders/TransactionBuilder.js +7 -2
  27. package/build/transaction/builders/UnwrapTransaction.js +1 -1
  28. package/build/transaction/interfaces/ITransactionParameters.d.ts +1 -0
  29. package/build/verification/TapscriptVerificator.d.ts +2 -1
  30. package/build/verification/TapscriptVerificator.js +3 -3
  31. package/package.json +1 -1
  32. package/src/_version.ts +1 -1
  33. package/src/generators/Generator.ts +12 -0
  34. package/src/generators/builders/CalldataGenerator.ts +6 -3
  35. package/src/generators/builders/DeploymentGenerator.ts +21 -8
  36. package/src/keypair/EcKeyPair.ts +40 -1
  37. package/src/transaction/builders/DeploymentTransaction.ts +31 -4
  38. package/src/transaction/builders/FundingTransaction.ts +16 -4
  39. package/src/transaction/builders/SharedInteractionTransaction.ts +3 -1
  40. package/src/transaction/builders/TransactionBuilder.ts +18 -2
  41. package/src/transaction/builders/UnwrapTransaction.ts +1 -1
  42. package/src/transaction/interfaces/ITransactionParameters.ts +2 -0
  43. package/src/verification/TapscriptVerificator.ts +5 -3
@@ -181,6 +181,28 @@ export class EcKeyPair {
181
181
  return !!address.toOutputScript(contractAddress, network);
182
182
  }
183
183
 
184
+ /**
185
+ * Get the legacy segwit address from a keypair
186
+ * @param {ECPairInterface} keyPair - The keypair to get the address for
187
+ * @param {Network} network - The network to use
188
+ * @returns {Address} - The legacy address
189
+ */
190
+ public static getLegacySegwitAddress(
191
+ keyPair: ECPairInterface,
192
+ network: Network = networks.bitcoin,
193
+ ): Address {
194
+ const wallet = payments.p2sh({
195
+ redeem: payments.p2wpkh({ pubkey: keyPair.publicKey, network: network }),
196
+ network: network,
197
+ });
198
+
199
+ if (!wallet.address) {
200
+ throw new Error('Failed to generate wallet');
201
+ }
202
+
203
+ return wallet.address;
204
+ }
205
+
184
206
  /**
185
207
  * Get the legacy address from a keypair
186
208
  * @param {ECPairInterface} keyPair - The keypair to get the address for
@@ -192,7 +214,6 @@ export class EcKeyPair {
192
214
  network: Network = networks.bitcoin,
193
215
  ): Address {
194
216
  const wallet = payments.p2pkh({ pubkey: keyPair.publicKey, network: network });
195
-
196
217
  if (!wallet.address) {
197
218
  throw new Error('Failed to generate wallet');
198
219
  }
@@ -200,6 +221,24 @@ export class EcKeyPair {
200
221
  return wallet.address;
201
222
  }
202
223
 
224
+ /**
225
+ * Get the legacy address from a keypair
226
+ * @param {ECPairInterface} keyPair - The keypair to get the address for
227
+ * @param {Network} network - The network to use
228
+ * @returns {Address} - The legacy address
229
+ */
230
+ public static getP2PKAddress(
231
+ keyPair: ECPairInterface,
232
+ network: Network = networks.bitcoin,
233
+ ): Address {
234
+ const wallet = payments.p2pk({ pubkey: keyPair.publicKey, network: network });
235
+ if (!wallet.output) {
236
+ throw new Error('Failed to generate wallet');
237
+ }
238
+
239
+ return '0x' + wallet.output.toString('hex');
240
+ }
241
+
203
242
  /**
204
243
  * Generate a random keypair
205
244
  * @param {Network} network - The network to use
@@ -12,6 +12,7 @@ import { PsbtInput } from 'bip174/src/lib/interfaces.js';
12
12
  import { Compressor } from '../../bytecode/Compressor.js';
13
13
  import { AddressGenerator } from '../../generators/AddressGenerator.js';
14
14
  import { Address } from '@btc-vision/bsi-binary';
15
+ import { SharedInteractionTransaction } from './SharedInteractionTransaction.js';
15
16
 
16
17
  export class DeploymentTransaction extends TransactionBuilder<TransactionType.DEPLOYMENT> {
17
18
  public static readonly MAXIMUM_CONTRACT_SIZE = 128 * 1024;
@@ -64,6 +65,12 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
64
65
  */
65
66
  private readonly bytecode: Buffer;
66
67
 
68
+ /**
69
+ * Constructor calldata
70
+ * @private
71
+ */
72
+ private readonly calldata?: Buffer;
73
+
67
74
  /**
68
75
  * The contract signer
69
76
  * @private
@@ -80,10 +87,12 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
80
87
  super(parameters);
81
88
 
82
89
  this.bytecode = Compressor.compress(parameters.bytecode);
83
- if (!this.bytecode) throw new Error('Bytecode is required');
90
+ this.verifyBytecode();
84
91
 
85
- if (this.bytecode.length > DeploymentTransaction.MAXIMUM_CONTRACT_SIZE)
86
- throw new Error('Contract size overflow.');
92
+ if (parameters.calldata) {
93
+ this.calldata = parameters.calldata;
94
+ this.verifyCalldata();
95
+ }
87
96
 
88
97
  this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
89
98
 
@@ -91,7 +100,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
91
100
  this.contractSigner = EcKeyPair.fromSeedKeyPair(this.contractSeed, this.network);
92
101
 
93
102
  this.deploymentGenerator = new DeploymentGenerator(
94
- this.internalPubKeyToXOnly(),
103
+ this.signer.publicKey,
95
104
  this.contractSignerXOnlyPubKey(),
96
105
  this.network,
97
106
  );
@@ -99,6 +108,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
99
108
  this.compiledTargetScript = this.deploymentGenerator.compile(
100
109
  this.bytecode,
101
110
  this.randomBytes,
111
+ this.calldata,
102
112
  );
103
113
 
104
114
  this.scriptTree = this.getScriptTree();
@@ -243,6 +253,23 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
243
253
  };
244
254
  }
245
255
 
256
+ private verifyCalldata(): void {
257
+ if (
258
+ this.calldata &&
259
+ this.calldata.length > SharedInteractionTransaction.MAXIMUM_CALLDATA_SIZE
260
+ ) {
261
+ throw new Error('Calldata size overflow.');
262
+ }
263
+ }
264
+
265
+ private verifyBytecode(): void {
266
+ if (!this.bytecode) throw new Error('Bytecode is required');
267
+
268
+ if (this.bytecode.length > DeploymentTransaction.MAXIMUM_CONTRACT_SIZE) {
269
+ throw new Error('Contract size overflow.');
270
+ }
271
+ }
272
+
246
273
  /**
247
274
  * Generate the contract seed for the deployment
248
275
  * @private
@@ -27,6 +27,11 @@ export class FundingTransaction extends TransactionBuilder<TransactionType.FUNDI
27
27
 
28
28
  if (this.splitInputsInto > 1) {
29
29
  this.splitInputs(this.amount);
30
+ } else if (this.isPubKeyDestination) {
31
+ this.addOutput({
32
+ value: Number(this.amount),
33
+ script: Buffer.from(this.to.slice(2), 'hex'),
34
+ });
30
35
  } else {
31
36
  this.addOutput({
32
37
  value: Number(this.amount),
@@ -45,10 +50,17 @@ export class FundingTransaction extends TransactionBuilder<TransactionType.FUNDI
45
50
  const splitAmount = amountSpent / BigInt(this.splitInputsInto);
46
51
 
47
52
  for (let i = 0; i < this.splitInputsInto; i++) {
48
- this.addOutput({
49
- value: Number(splitAmount),
50
- address: this.to,
51
- });
53
+ if (this.isPubKeyDestination) {
54
+ this.addOutput({
55
+ value: Number(splitAmount),
56
+ script: Buffer.from(this.to.slice(2), 'hex'),
57
+ });
58
+ } else {
59
+ this.addOutput({
60
+ value: Number(splitAmount),
61
+ address: this.to,
62
+ });
63
+ }
52
64
  }
53
65
  }
54
66
 
@@ -18,6 +18,8 @@ import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
18
18
  export abstract class SharedInteractionTransaction<
19
19
  T extends TransactionType,
20
20
  > extends TransactionBuilder<T> {
21
+ public static readonly MAXIMUM_CALLDATA_SIZE = 1024 * 1024; // 1MB
22
+
21
23
  /**
22
24
  * Random salt for the interaction
23
25
  * @type {Buffer}
@@ -71,7 +73,7 @@ export abstract class SharedInteractionTransaction<
71
73
  this.scriptSigner = this.generateKeyPairFromSeed();
72
74
 
73
75
  this.calldataGenerator = new CalldataGenerator(
74
- this.internalPubKeyToXOnly(),
76
+ this.signer.publicKey,
75
77
  this.scriptSignerXOnlyPubKey(),
76
78
  this.network,
77
79
  );
@@ -107,6 +107,12 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
107
107
  */
108
108
  protected _maximumFeeRate: number = 100000000;
109
109
 
110
+ /**
111
+ * @description Is the destionation P2PK
112
+ * @protected
113
+ */
114
+ protected isPubKeyDestination: boolean;
115
+
110
116
  protected constructor(parameters: ITransactionParameters) {
111
117
  super(parameters);
112
118
 
@@ -121,6 +127,8 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
121
127
  this.utxos = parameters.utxos;
122
128
  this.to = parameters.to || undefined;
123
129
 
130
+ this.isPubKeyDestination = this.to ? this.to.startsWith('0x') : false;
131
+
124
132
  this.optionalOutputs = parameters.optionalOutputs;
125
133
 
126
134
  this.from = TransactionBuilder.getFrom(
@@ -231,7 +239,11 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
231
239
  throw new Error('No UTXOs specified');
232
240
  }
233
241
 
234
- if (this.to && !EcKeyPair.verifyContractAddress(this.to, this.network)) {
242
+ if (
243
+ this.to &&
244
+ !this.isPubKeyDestination &&
245
+ !EcKeyPair.verifyContractAddress(this.to, this.network)
246
+ ) {
235
247
  throw new Error(
236
248
  'Invalid contract address. The contract address must be a taproot address.',
237
249
  );
@@ -261,7 +273,11 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
261
273
  public async generateTransactionMinimalSignatures(
262
274
  checkPartialSigs: boolean = false,
263
275
  ): Promise<void> {
264
- if (this.to && !EcKeyPair.verifyContractAddress(this.to, this.network)) {
276
+ if (
277
+ this.to &&
278
+ !this.isPubKeyDestination &&
279
+ !EcKeyPair.verifyContractAddress(this.to, this.network)
280
+ ) {
265
281
  throw new Error(
266
282
  'Invalid contract address. The contract address must be a taproot address.',
267
283
  );
@@ -109,7 +109,7 @@ export class UnwrapTransaction extends SharedInteractionTransaction<TransactionT
109
109
  this.contractSecret = this.generateSecret();
110
110
 
111
111
  this.calldataGenerator = new CalldataGenerator(
112
- toXOnly(this.signer.publicKey),
112
+ this.signer.publicKey,
113
113
  this.scriptSignerXOnlyPubKey(),
114
114
  this.network,
115
115
  );
@@ -5,6 +5,7 @@ import { ITweakedTransactionData } from '../shared/TweakedTransaction.js';
5
5
  import { VaultUTXOs } from '../processor/PsbtTransaction.js';
6
6
  import { ChainId } from '../../network/ChainId.js';
7
7
  import { PsbtOutputExtended } from './Tap.js';
8
+
8
9
  export interface ITransactionParameters extends ITweakedTransactionData {
9
10
  readonly from?: Address;
10
11
  readonly to?: Address;
@@ -58,6 +59,7 @@ export interface IUnwrapParameters extends Omit<SharedInteractionParameters, 'op
58
59
 
59
60
  export interface IDeploymentParameters extends Omit<ITransactionParameters, 'to'> {
60
61
  readonly bytecode: Buffer;
62
+ readonly calldata?: Buffer;
61
63
 
62
64
  readonly randomBytes?: Buffer;
63
65
  }
@@ -6,10 +6,11 @@ import { TransactionBuilder } from '../transaction/builders/TransactionBuilder.j
6
6
  import { AddressGenerator } from '../generators/AddressGenerator.js';
7
7
 
8
8
  export interface ContractAddressVerificationParams {
9
- readonly deployerPubKeyXOnly: Buffer;
9
+ readonly deployerPubKey: Buffer;
10
10
  readonly contractSaltPubKey: Buffer;
11
11
  readonly originalSalt: Buffer;
12
12
  readonly bytecode: Buffer;
13
+ readonly calldata?: Buffer;
13
14
  readonly network?: Network;
14
15
  }
15
16
 
@@ -21,7 +22,7 @@ export class TapscriptVerificator {
21
22
  ): string | undefined {
22
23
  const network = params.network || networks.bitcoin;
23
24
  const scriptBuilder: DeploymentGenerator = new DeploymentGenerator(
24
- params.deployerPubKeyXOnly,
25
+ params.deployerPubKey,
25
26
  toXOnly(params.contractSaltPubKey),
26
27
  network,
27
28
  );
@@ -29,6 +30,7 @@ export class TapscriptVerificator {
29
30
  const compiledTargetScript: Buffer = scriptBuilder.compile(
30
31
  params.bytecode,
31
32
  params.originalSalt,
33
+ params.calldata,
32
34
  );
33
35
 
34
36
  const scriptTree: Taptree = [
@@ -78,7 +80,7 @@ export class TapscriptVerificator {
78
80
  const network = params.network || networks.bitcoin;
79
81
 
80
82
  const transactionData: Payment = {
81
- internalPubkey: params.deployerPubKeyXOnly,
83
+ internalPubkey: toXOnly(params.deployerPubKey),
82
84
  network: network,
83
85
  scriptTree: scriptTree,
84
86
  };