@btc-vision/transaction 1.2.5 → 1.2.7

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 (62) hide show
  1. package/README.md +4 -19
  2. package/browser/_version.d.ts +1 -1
  3. package/browser/generators/Generator.d.ts +1 -0
  4. package/browser/generators/builders/CalldataGenerator.d.ts +1 -1
  5. package/browser/generators/builders/DeploymentGenerator.d.ts +1 -1
  6. package/browser/generators/builders/LegacyCalldataGenerator.d.ts +1 -1
  7. package/browser/index.js +1 -1
  8. package/browser/transaction/browser/extensions/UnisatSigner.d.ts +2 -1
  9. package/browser/transaction/browser/extensions/XverseSigner.d.ts +2 -1
  10. package/browser/transaction/browser/types/Unisat.d.ts +5 -0
  11. package/browser/transaction/browser/types/Xverse.d.ts +10 -6
  12. package/browser/transaction/builders/MultiSignTransaction.d.ts +1 -1
  13. package/browser/transaction/builders/TransactionBuilder.d.ts +1 -0
  14. package/browser/transaction/interfaces/ITransactionParameters.d.ts +1 -0
  15. package/browser/verification/TapscriptVerificator.d.ts +1 -0
  16. package/build/_version.d.ts +1 -1
  17. package/build/_version.js +1 -1
  18. package/build/generators/Generator.d.ts +1 -0
  19. package/build/generators/Generator.js +7 -0
  20. package/build/generators/builders/CalldataGenerator.d.ts +1 -1
  21. package/build/generators/builders/CalldataGenerator.js +2 -2
  22. package/build/generators/builders/DeploymentGenerator.d.ts +1 -1
  23. package/build/generators/builders/DeploymentGenerator.js +4 -4
  24. package/build/generators/builders/LegacyCalldataGenerator.d.ts +1 -1
  25. package/build/generators/builders/LegacyCalldataGenerator.js +5 -23
  26. package/build/transaction/TransactionFactory.js +7 -3
  27. package/build/transaction/browser/extensions/UnisatSigner.d.ts +2 -1
  28. package/build/transaction/browser/extensions/UnisatSigner.js +6 -1
  29. package/build/transaction/browser/extensions/XverseSigner.d.ts +2 -1
  30. package/build/transaction/browser/extensions/XverseSigner.js +17 -0
  31. package/build/transaction/browser/types/Unisat.d.ts +5 -0
  32. package/build/transaction/browser/types/Unisat.js +5 -0
  33. package/build/transaction/browser/types/Xverse.d.ts +10 -6
  34. package/build/transaction/browser/types/Xverse.js +5 -0
  35. package/build/transaction/builders/DeploymentTransaction.js +1 -1
  36. package/build/transaction/builders/InteractionTransaction.js +1 -1
  37. package/build/transaction/builders/MultiSignTransaction.d.ts +1 -1
  38. package/build/transaction/builders/MultiSignTransaction.js +1 -0
  39. package/build/transaction/builders/TransactionBuilder.d.ts +1 -0
  40. package/build/transaction/builders/TransactionBuilder.js +5 -2
  41. package/build/transaction/interfaces/ITransactionParameters.d.ts +1 -0
  42. package/build/utxo/OPNetLimitedProvider.js +2 -1
  43. package/build/verification/TapscriptVerificator.d.ts +1 -0
  44. package/build/verification/TapscriptVerificator.js +2 -2
  45. package/package.json +2 -2
  46. package/src/_version.ts +1 -1
  47. package/src/generators/Generator.ts +9 -0
  48. package/src/generators/builders/CalldataGenerator.ts +4 -1
  49. package/src/generators/builders/DeploymentGenerator.ts +6 -3
  50. package/src/generators/builders/LegacyCalldataGenerator.ts +11 -40
  51. package/src/transaction/TransactionFactory.ts +10 -3
  52. package/src/transaction/browser/extensions/UnisatSigner.ts +9 -2
  53. package/src/transaction/browser/extensions/XverseSigner.ts +31 -1
  54. package/src/transaction/browser/types/Unisat.ts +8 -1
  55. package/src/transaction/browser/types/Xverse.ts +23 -13
  56. package/src/transaction/builders/DeploymentTransaction.ts +1 -0
  57. package/src/transaction/builders/InteractionTransaction.ts +1 -0
  58. package/src/transaction/builders/MultiSignTransaction.ts +2 -1
  59. package/src/transaction/builders/TransactionBuilder.ts +6 -2
  60. package/src/transaction/interfaces/ITransactionParameters.ts +1 -0
  61. package/src/utxo/OPNetLimitedProvider.ts +2 -1
  62. package/src/verification/TapscriptVerificator.ts +3 -0
@@ -4,6 +4,7 @@ import { Compressor } from '../../bytecode/Compressor.js';
4
4
  import { EcKeyPair } from '../../keypair/EcKeyPair.js';
5
5
  import { FeatureOpCodes, Features } from '../Features.js';
6
6
  import { Generator } from '../Generator.js';
7
+ import { BinaryWriter } from '../../buffer/BinaryWriter.js';
7
8
 
8
9
  /**
9
10
  * Class to generate bitcoin script for interaction transactions
@@ -57,6 +58,7 @@ export class CalldataGenerator extends Generator {
57
58
  * @param {Buffer} calldata - The calldata to use
58
59
  * @param {Buffer} contractSecret - The contract secret
59
60
  * @param preimage
61
+ * @param maxPriority - Amount of satoshis to spend max on priority fee
60
62
  * @param {number[]} [features=[]] - The features to use (optional)
61
63
  * @returns {Buffer} - The compiled script
62
64
  * @throws {Error} - If something goes wrong
@@ -65,6 +67,7 @@ export class CalldataGenerator extends Generator {
65
67
  calldata: Buffer,
66
68
  contractSecret: Buffer,
67
69
  preimage: Buffer,
70
+ maxPriority: bigint,
68
71
  features: Features[] = [],
69
72
  ): Buffer {
70
73
  if (!this.contractSaltPubKey) throw new Error('Contract salt public key not set');
@@ -73,7 +76,7 @@ export class CalldataGenerator extends Generator {
73
76
  if (!dataChunks.length) throw new Error('No data chunks found');
74
77
 
75
78
  let compiledData = [
76
- this.senderFirstByte,
79
+ this.getHeader(maxPriority),
77
80
  opcodes.OP_TOALTSTACK,
78
81
 
79
82
  // CHALLENGE PREIMAGE FOR REWARD,
@@ -15,6 +15,7 @@ export class DeploymentGenerator extends Generator {
15
15
  * @param {Buffer} contractBytecode - The contract bytecode
16
16
  * @param {Buffer} contractSalt - The contract salt
17
17
  * @param {Buffer} preimage - The preimage for reward
18
+ * @param {bigint} maxPriority - The maximum priority for the contract
18
19
  * @param {Buffer} [calldata] - The calldata to be passed to the contract
19
20
  * @returns {Buffer} - The compiled script
20
21
  */
@@ -22,9 +23,10 @@ export class DeploymentGenerator extends Generator {
22
23
  contractBytecode: Buffer,
23
24
  contractSalt: Buffer,
24
25
  preimage: Buffer,
26
+ maxPriority: bigint,
25
27
  calldata?: Buffer,
26
28
  ): Buffer {
27
- const asm = this.getAsm(contractBytecode, contractSalt, preimage, calldata);
29
+ const asm = this.getAsm(contractBytecode, contractSalt, preimage, maxPriority, calldata);
28
30
  const compiled = script.compile(asm);
29
31
 
30
32
  /**
@@ -42,15 +44,16 @@ export class DeploymentGenerator extends Generator {
42
44
  contractBytecode: Buffer,
43
45
  contractSalt: Buffer,
44
46
  preimage: Buffer,
47
+ maxPriority: bigint,
45
48
  calldata?: Buffer,
46
49
  ): (number | Buffer)[] {
47
50
  if (!this.contractSaltPubKey) throw new Error('Contract salt public key not set');
48
51
 
49
52
  const dataChunks: Buffer[][] = this.splitBufferIntoChunks(contractBytecode);
50
53
  const calldataChunks: Buffer[][] = calldata ? this.splitBufferIntoChunks(calldata) : [];
51
-
54
+
52
55
  const compiledData = [
53
- this.senderFirstByte,
56
+ this.getHeader(maxPriority),
54
57
  opcodes.OP_TOALTSTACK,
55
58
 
56
59
  // CHALLENGE PREIMAGE FOR REWARD,
@@ -52,23 +52,30 @@ export class LegacyCalldataGenerator extends Generator {
52
52
  * Compile an interaction bitcoin script
53
53
  * @param {Buffer} calldata - The calldata to use
54
54
  * @param {Buffer} contractSecret - The contract secret
55
+ * @param {Buffer} preimage - The preimage to use
56
+ * @param {bigint} maxPriority - The maximum priority
55
57
  * @param {number[]} [features=[]] - The features to use (optional)
56
- * @param {Buffer[]} [vaultPublicKeys=[]] - The public keys of the vault (optional)
57
- * @param {number} [minimumSignatures=0] - The minimum number of signatures (optional)
58
58
  * @returns {Buffer} - The compiled script
59
59
  * @throws {Error} - If something goes wrong
60
60
  */
61
61
  public compile(
62
62
  calldata: Buffer,
63
63
  contractSecret: Buffer,
64
+ preimage: Buffer,
65
+ maxPriority: bigint,
64
66
  features: Features[] = [],
65
- vaultPublicKeys: Buffer[] = [],
66
- minimumSignatures: number = 0,
67
67
  ): Buffer {
68
68
  const dataChunks: Buffer[][] = this.splitBufferIntoChunks(calldata);
69
69
  if (!dataChunks.length) throw new Error('No data chunks found');
70
70
 
71
71
  let compiledData = [
72
+ this.getHeader(maxPriority),
73
+ opcodes.OP_TOALTSTACK,
74
+
75
+ // CHALLENGE PREIMAGE FOR REWARD,
76
+ preimage,
77
+ opcodes.OP_TOALTSTACK,
78
+
72
79
  this.senderPubKey,
73
80
  opcodes.OP_DUP,
74
81
  opcodes.OP_HASH256,
@@ -87,42 +94,6 @@ export class LegacyCalldataGenerator extends Generator {
87
94
  Generator.MAGIC,
88
95
  ];
89
96
 
90
- // write pub keys, when requested.
91
- if (vaultPublicKeys.length > 0) {
92
- const pubKeyBuffer = LegacyCalldataGenerator.getPubKeyAsBuffer(
93
- vaultPublicKeys,
94
- this.network,
95
- );
96
- const pubKeyDataChunks: Buffer[][] = this.splitBufferIntoChunks(pubKeyBuffer);
97
-
98
- compiledData = compiledData.concat(
99
- ...[
100
- opcodes.OP_0, // provide opnet public keys
101
- ...pubKeyDataChunks,
102
- ],
103
- );
104
-
105
- if (minimumSignatures) {
106
- // verify that the minimum is not greater than 255
107
- if (minimumSignatures > 255) {
108
- throw new Error('Minimum signatures cannot exceed 255');
109
- }
110
-
111
- // we use a 2 bytes buffer even if we limit to 255 so it does not use an opcode for the number
112
- const minSigBuffer = Buffer.alloc(2);
113
- minSigBuffer.writeUint16LE(minimumSignatures, 0);
114
-
115
- compiledData = compiledData.concat(
116
- ...[
117
- opcodes.OP_1, // provide minimum signatures
118
- minSigBuffer,
119
- ],
120
- );
121
- } else {
122
- throw new Error('Minimum signatures must be provided');
123
- }
124
- }
125
-
126
97
  const featureOpcodes = features.map((feature) => FeatureOpCodes[feature]); // Get the opcodes for the features
127
98
 
128
99
  // Write calldata
@@ -397,7 +397,13 @@ export class TransactionFactory {
397
397
  }
398
398
 
399
399
  const opnet = window.opnet.web3;
400
- const interaction = await opnet.signInteraction(interactionParameters);
400
+ const interaction = await opnet.signInteraction({
401
+ ...interactionParameters,
402
+
403
+ // @ts-expect-error no, this is ok
404
+ signer: undefined,
405
+ });
406
+
401
407
  if (!interaction) {
402
408
  throw new Error('Could not sign interaction transaction.');
403
409
  }
@@ -456,11 +462,12 @@ export class TransactionFactory {
456
462
  }
457
463
 
458
464
  private getPriorityFee(params: ITransactionParameters): bigint {
459
- if (params.priorityFee < TransactionBuilder.MINIMUM_DUST) {
465
+ const totalFee = params.priorityFee + params.gasSatFee;
466
+ if (totalFee < TransactionBuilder.MINIMUM_DUST) {
460
467
  return TransactionBuilder.MINIMUM_DUST;
461
468
  }
462
469
 
463
- return params.priorityFee;
470
+ return totalFee;
464
471
  }
465
472
 
466
473
  private getUTXOAsTransaction(tx: Transaction, to: string, index: number): UTXO[] {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  crypto as bitCrypto,
3
- script as bitScript,
4
3
  Network,
5
4
  networks,
6
5
  Psbt,
6
+ script as bitScript,
7
7
  TapScriptSig,
8
8
  toXOnly,
9
9
  } from '@btc-vision/bitcoin';
@@ -12,7 +12,7 @@ import { ECPairInterface } from 'ecpair';
12
12
  import { EcKeyPair } from '../../../keypair/EcKeyPair.js';
13
13
  import { canSignNonTaprootInput, isTaprootInput } from '../../../signer/SignerUtils.js';
14
14
  import { CustomKeypair } from '../BrowserSignerBase.js';
15
- import { PsbtSignatureOptions, Unisat, UnisatNetwork } from '../types/Unisat.js';
15
+ import { PsbtSignatureOptions, SignatureType, Unisat, UnisatNetwork } from '../types/Unisat.js';
16
16
 
17
17
  declare global {
18
18
  interface Window {
@@ -91,6 +91,13 @@ export class UnisatSigner extends CustomKeypair {
91
91
  return module;
92
92
  }
93
93
 
94
+ public async signData(data: Buffer, type: SignatureType): Promise<Buffer> {
95
+ const str = data.toString('hex');
96
+ const signature = await this.unisat.signData(str, type);
97
+
98
+ return Buffer.from(signature, 'hex');
99
+ }
100
+
94
101
  public async init(): Promise<void> {
95
102
  if (this.isInitialized) {
96
103
  return;
@@ -9,7 +9,7 @@ import {
9
9
  } from '../../../signer/SignerUtils.js';
10
10
  import { CustomKeypair } from '../BrowserSignerBase.js';
11
11
  import { PsbtSignatureOptions } from '../types/Unisat.js';
12
- import { Xverse } from '../types/Xverse.js';
12
+ import { SigningProtocol, Xverse } from '../types/Xverse.js';
13
13
 
14
14
  declare global {
15
15
  interface Window {
@@ -123,6 +123,36 @@ export class XverseSigner extends CustomKeypair {
123
123
  this.isInitialized = true;
124
124
  }
125
125
 
126
+ public async signData(
127
+ data: Buffer,
128
+ address: string,
129
+ protocol: SigningProtocol,
130
+ ): Promise<Buffer> {
131
+ if (!this.isInitialized) {
132
+ throw new Error('UnisatSigner not initialized');
133
+ }
134
+
135
+ const callSign = await this.BitcoinProvider.request('signMessage', {
136
+ address,
137
+ message: data.toString(),
138
+ protocol,
139
+ });
140
+
141
+ if ('error' in callSign) throw new Error(callSign.error.message);
142
+
143
+ const res = callSign.result as {
144
+ signature: string;
145
+ messageHash: string;
146
+ address: string;
147
+ };
148
+
149
+ if (!res.signature) {
150
+ throw new Error('Signature not found');
151
+ }
152
+
153
+ return Buffer.from(res.signature, 'hex');
154
+ }
155
+
126
156
  public getPublicKey(): Buffer {
127
157
  if (!this.isInitialized) {
128
158
  throw new Error('UnisatSigner not initialized');
@@ -33,6 +33,11 @@ export enum MessageType {
33
33
  bip322 = 'bip322-simple',
34
34
  }
35
35
 
36
+ export enum SignatureType {
37
+ ecdsa = 'ecdsa',
38
+ schnorr = 'schnorr',
39
+ }
40
+
36
41
  interface ToSignInputBase {
37
42
  readonly index: number;
38
43
  readonly sighashTypes?: number[];
@@ -56,7 +61,7 @@ export interface PsbtSignatureOptions {
56
61
 
57
62
  export interface Unisat {
58
63
  web3?: Web3Provider;
59
-
64
+
60
65
  disconnect: () => void;
61
66
  connect: () => void;
62
67
 
@@ -82,6 +87,8 @@ export interface Unisat {
82
87
 
83
88
  signMessage(message: string, type?: MessageType): Promise<string>;
84
89
 
90
+ signData(hex: string, type?: SignatureType): Promise<string>;
91
+
85
92
  pushTx(options: { rawtx: string }): Promise<string>;
86
93
 
87
94
  signPsbt(psbtHex: string, psbtOptions: PsbtSignatureOptions): Promise<string>;
@@ -93,26 +93,36 @@ interface SignedTransactionResult {
93
93
  raw: string;
94
94
  }
95
95
 
96
- export interface Xverse {
97
- request(method: string, params: unknown): Promise<XverseRPCResponse>;
98
- request(
99
- method: 'wallet_connect' | 'wallet_getAccount',
100
- params: null,
101
- ): Promise<XverseRPCGetAccountResponse>;
102
- request(method: 'wallet_disconnect', params: null): Promise<XverseRPCResponse<null>>;
103
- request(method: 'getBalance', params: null): Promise<XverseRPCGetBalanceResponse>;
104
- request(method: 'signPsbt', params: XVersePSBTInput): Promise<XverseRPCSignPsbtResponse>;
96
+ export enum SigningProtocol {
97
+ ECDSA = 'ECDSA',
98
+ BIP322 = 'BIP322',
99
+ }
105
100
 
101
+ export interface Xverse {
106
102
  addListener: (event: string, callback: (...args: unknown[]) => void) => void;
107
-
108
103
  createInscription: (data: InscriptionData) => Promise<InscriptionResult>;
109
104
  createRepeatInscriptions: (data: RepeatInscriptionsData) => Promise<InscriptionResult[]>;
110
-
111
105
  sendBtcTransaction: (transaction: BtcTransaction) => Promise<TransactionResult>;
112
-
113
- signMessage: (message: string) => Promise<SignedMessageResult>;
106
+ signMessage: (
107
+ address: string,
108
+ message: string,
109
+ protocol: SigningProtocol,
110
+ ) => Promise<SignedMessageResult>;
114
111
  signMultipleTransactions: (
115
112
  transactions: BtcTransaction[],
116
113
  ) => Promise<SignedTransactionResult[]>;
117
114
  signTransaction: (transaction: BtcTransaction) => Promise<SignedTransactionResult>;
115
+
116
+ request(method: string, params: unknown): Promise<XverseRPCResponse>;
117
+
118
+ request(
119
+ method: 'wallet_connect' | 'wallet_getAccount',
120
+ params: null,
121
+ ): Promise<XverseRPCGetAccountResponse>;
122
+
123
+ request(method: 'wallet_disconnect', params: null): Promise<XverseRPCResponse<null>>;
124
+
125
+ request(method: 'getBalance', params: null): Promise<XverseRPCGetBalanceResponse>;
126
+
127
+ request(method: 'signPsbt', params: XVersePSBTInput): Promise<XverseRPCSignPsbtResponse>;
118
128
  }
@@ -139,6 +139,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
139
139
  this.bytecode,
140
140
  this.randomBytes,
141
141
  this.preimage,
142
+ this.priorityFee,
142
143
  this.calldata,
143
144
  );
144
145
 
@@ -31,6 +31,7 @@ export class InteractionTransaction extends SharedInteractionTransaction<Transac
31
31
  this.calldata,
32
32
  this.contractSecret,
33
33
  this.preimage,
34
+ this.priorityFee,
34
35
  );
35
36
 
36
37
  this.scriptTree = this.getScriptTree();
@@ -21,7 +21,7 @@ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
21
21
  import { ECPairInterface } from 'ecpair';
22
22
 
23
23
  export interface MultiSignParameters
24
- extends Omit<ITransactionParameters, 'priorityFee' | 'signer'> {
24
+ extends Omit<ITransactionParameters, 'gasSatFee' | 'priorityFee' | 'signer'> {
25
25
  readonly pubkeys: Buffer[];
26
26
  readonly minimumSignatures: number;
27
27
  readonly from?: undefined;
@@ -97,6 +97,7 @@ export class MultiSignTransaction extends TransactionBuilder<TransactionType.MUL
97
97
  bitcoinCrypto.sha256(Buffer.from('aaaaaaaa', 'utf-8')),
98
98
  ),
99
99
  priorityFee: 0n,
100
+ gasSatFee: 0n,
100
101
  });
101
102
 
102
103
  if (!parameters.pubkeys) {
@@ -111,6 +111,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
111
111
  * @description The opnet priority fee of the transaction
112
112
  */
113
113
  protected priorityFee: bigint;
114
+ protected gasSatFee: bigint;
114
115
 
115
116
  /**
116
117
  * @description The utxos used in the transaction
@@ -151,6 +152,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
151
152
  this.network = parameters.network;
152
153
  this.feeRate = parameters.feeRate;
153
154
  this.priorityFee = parameters.priorityFee ?? 0n;
155
+ this.gasSatFee = parameters.gasSatFee ?? 0n;
154
156
  this.utxos = parameters.utxos;
155
157
  this.to = parameters.to || undefined;
156
158
 
@@ -230,6 +232,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
230
232
  network: this.network,
231
233
  feeRate: this.feeRate,
232
234
  priorityFee: this.priorityFee ?? 0n,
235
+ gasSatFee: this.gasSatFee ?? 0n,
233
236
  from: this.from,
234
237
  amount: this.estimatedFees,
235
238
  optionalOutputs: this.optionalOutputs,
@@ -530,8 +533,9 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
530
533
  * @returns {bigint}
531
534
  */
532
535
  protected getTransactionOPNetFee(): bigint {
533
- if (this.priorityFee > TransactionBuilder.MINIMUM_DUST) {
534
- return this.priorityFee;
536
+ const totalFee = this.priorityFee + this.gasSatFee;
537
+ if (totalFee > TransactionBuilder.MINIMUM_DUST) {
538
+ return totalFee;
535
539
  }
536
540
 
537
541
  return TransactionBuilder.MINIMUM_DUST;
@@ -18,6 +18,7 @@ export interface ITransactionParameters extends ITweakedTransactionData {
18
18
 
19
19
  readonly feeRate: number;
20
20
  readonly priorityFee: bigint;
21
+ readonly gasSatFee: bigint;
21
22
  }
22
23
 
23
24
  export interface IFundingTransactionParameters extends ITransactionParameters {
@@ -211,7 +211,8 @@ export class OPNetLimitedProvider {
211
211
  network,
212
212
  to: wallet.p2tr,
213
213
  splitInputsInto,
214
- priorityFee: 330n,
214
+ priorityFee: 0n,
215
+ gasSatFee: 330n,
215
216
  };
216
217
 
217
218
  const transactionFactory = new TransactionFactory();
@@ -16,6 +16,7 @@ export interface ContractAddressVerificationParams {
16
16
  readonly originalSalt: Buffer;
17
17
  readonly bytecode: Buffer;
18
18
  readonly preimage: Buffer;
19
+ readonly priorityFee: bigint;
19
20
  readonly calldata?: Buffer;
20
21
  readonly network?: Network;
21
22
  }
@@ -37,6 +38,7 @@ export class TapscriptVerificator {
37
38
  params.bytecode,
38
39
  params.originalSalt,
39
40
  params.preimage,
41
+ params.priorityFee,
40
42
  params.calldata,
41
43
  );
42
44
 
@@ -69,6 +71,7 @@ export class TapscriptVerificator {
69
71
  params.bytecode,
70
72
  params.originalSalt,
71
73
  params.preimage,
74
+ params.priorityFee,
72
75
  params.calldata,
73
76
  );
74
77