@btc-vision/transaction 1.3.3 → 1.3.5

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 (29) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/index.js +1 -1
  3. package/browser/opnet.d.ts +7 -0
  4. package/browser/transaction/TransactionFactory.d.ts +2 -0
  5. package/browser/transaction/browser/extensions/UnisatSigner.d.ts +3 -5
  6. package/browser/transaction/builders/SharedInteractionTransaction.d.ts +1 -1
  7. package/browser/transaction/shared/TweakedTransaction.d.ts +2 -1
  8. package/build/_version.d.ts +1 -1
  9. package/build/_version.js +1 -1
  10. package/build/opnet.d.ts +7 -0
  11. package/build/transaction/TransactionFactory.d.ts +2 -0
  12. package/build/transaction/TransactionFactory.js +70 -7
  13. package/build/transaction/browser/extensions/UnisatSigner.d.ts +3 -5
  14. package/build/transaction/browser/extensions/UnisatSigner.js +2 -0
  15. package/build/transaction/builders/DeploymentTransaction.js +12 -2
  16. package/build/transaction/builders/SharedInteractionTransaction.d.ts +1 -1
  17. package/build/transaction/builders/SharedInteractionTransaction.js +24 -14
  18. package/build/transaction/builders/TransactionBuilder.js +3 -3
  19. package/build/transaction/shared/TweakedTransaction.d.ts +2 -1
  20. package/build/transaction/shared/TweakedTransaction.js +21 -7
  21. package/package.json +1 -1
  22. package/src/_version.ts +1 -1
  23. package/src/opnet.ts +9 -0
  24. package/src/transaction/TransactionFactory.ts +101 -12
  25. package/src/transaction/browser/extensions/UnisatSigner.ts +6 -6
  26. package/src/transaction/builders/DeploymentTransaction.ts +12 -3
  27. package/src/transaction/builders/SharedInteractionTransaction.ts +31 -28
  28. package/src/transaction/builders/TransactionBuilder.ts +7 -3
  29. package/src/transaction/shared/TweakedTransaction.ts +40 -9
@@ -1,3 +1,4 @@
1
+ import { Unisat } from './transaction/browser/types/Unisat.js';
1
2
  export { version } from './_version.js';
2
3
  export * from './bytecode/Compressor.js';
3
4
  export * from './generators/builders/CalldataGenerator.js';
@@ -63,3 +64,9 @@ export * from './metadata/tokens.js';
63
64
  export * from './transaction/browser/Web3Provider.js';
64
65
  export * from './keypair/Secp256k1PointDeriver.js';
65
66
  export * from './transaction/ContractAddress.js';
67
+ declare global {
68
+ interface Window {
69
+ unisat?: Unisat;
70
+ opnet?: Unisat;
71
+ }
72
+ }
@@ -52,7 +52,9 @@ export declare class TransactionFactory {
52
52
  createBTCTransfer(parameters: IFundingTransactionParameters): Promise<BitcoinTransferResponse>;
53
53
  createChallengeSolution(parameters: IChallengeSolutionTransactionParameters): Promise<ChallengeSolution>;
54
54
  getAllNewUTXOs(original: TransactionBuilder<TransactionType>, tx: Transaction, to: string): UTXO[];
55
+ private parseOptionalInputs;
55
56
  private detectInteractionOPWallet;
57
+ private detectDeploymentOPWallet;
56
58
  private _createChallengeSolution;
57
59
  private createFundTransaction;
58
60
  private writePSBTHeader;
@@ -1,11 +1,9 @@
1
1
  import { Network, Psbt } from '@btc-vision/bitcoin';
2
2
  import { CustomKeypair } from '../BrowserSignerBase.js';
3
3
  import { SignatureType, Unisat } from '../types/Unisat.js';
4
- declare global {
5
- interface Window {
6
- unisat?: Unisat;
7
- opnet?: Unisat;
8
- }
4
+ export interface WindowWithWallets {
5
+ unisat?: Unisat;
6
+ opnet?: Unisat;
9
7
  }
10
8
  export declare class UnisatSigner extends CustomKeypair {
11
9
  private isInitialized;
@@ -36,8 +36,8 @@ export declare abstract class SharedInteractionTransaction<T extends Transaction
36
36
  finalScriptWitness: Buffer<ArrayBufferLike>;
37
37
  };
38
38
  protected signInputsWalletBased(transaction: Psbt): Promise<void>;
39
+ protected signInputsNonWalletBased(transaction: Psbt): Promise<void>;
39
40
  private createMineableRewardOutputs;
40
- private signInputsNonWalletBased;
41
41
  private getPubKeys;
42
42
  private generateRedeemScripts;
43
43
  }
@@ -51,6 +51,7 @@ export declare abstract class TweakedTransaction extends Logger {
51
51
  protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean, errored?: boolean): Promise<void>;
52
52
  protected splitArray<T>(arr: T[], chunkSize: number): T[][];
53
53
  protected signInputs(transaction: Psbt): Promise<void>;
54
+ protected signInputsNonWalletBased(transaction: Psbt): Promise<void>;
54
55
  protected internalPubKeyToXOnly(): Buffer;
55
56
  protected internalInit(): void;
56
57
  protected tweakSigner(): void;
@@ -64,7 +65,7 @@ export declare abstract class TweakedTransaction extends Logger {
64
65
  redeemScript: Buffer;
65
66
  outputScript: Buffer;
66
67
  } | undefined;
67
- protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended;
68
+ protected generatePsbtInputExtended(utxo: UTXO, i: number, extra?: boolean): PsbtInputExtended;
68
69
  protected customFinalizerP2SH: (inputIndex: number, input: PsbtInput, scriptA: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean) => {
69
70
  finalScriptSig: Buffer | undefined;
70
71
  finalScriptWitness: Buffer | undefined;
@@ -1 +1 @@
1
- export declare const version = "1.3.3";
1
+ export declare const version = "1.3.5";
package/build/_version.js CHANGED
@@ -1 +1 @@
1
- export const version = '1.3.3';
1
+ export const version = '1.3.5';
package/build/opnet.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Unisat } from './transaction/browser/types/Unisat.js';
1
2
  export { version } from './_version.js';
2
3
  export * from './bytecode/Compressor.js';
3
4
  export * from './generators/builders/CalldataGenerator.js';
@@ -63,3 +64,9 @@ export * from './metadata/tokens.js';
63
64
  export * from './transaction/browser/Web3Provider.js';
64
65
  export * from './keypair/Secp256k1PointDeriver.js';
65
66
  export * from './transaction/ContractAddress.js';
67
+ declare global {
68
+ interface Window {
69
+ unisat?: Unisat;
70
+ opnet?: Unisat;
71
+ }
72
+ }
@@ -52,7 +52,9 @@ export declare class TransactionFactory {
52
52
  createBTCTransfer(parameters: IFundingTransactionParameters): Promise<BitcoinTransferResponse>;
53
53
  createChallengeSolution(parameters: IChallengeSolutionTransactionParameters): Promise<ChallengeSolution>;
54
54
  getAllNewUTXOs(original: TransactionBuilder<TransactionType>, tx: Transaction, to: string): UTXO[];
55
+ private parseOptionalInputs;
55
56
  private detectInteractionOPWallet;
57
+ private detectDeploymentOPWallet;
56
58
  private _createChallengeSolution;
57
59
  private createFundTransaction;
58
60
  private writePSBTHeader;
@@ -70,9 +70,11 @@ export class TransactionFactory {
70
70
  if (!('signer' in interactionParameters)) {
71
71
  throw new Error('Field "signer" not provided, OP_WALLET not detected.');
72
72
  }
73
+ const inputs = this.parseOptionalInputs(interactionParameters.optionalInputs);
73
74
  const preTransaction = new InteractionTransaction({
74
75
  ...interactionParameters,
75
76
  utxos: [interactionParameters.utxos[0]],
77
+ optionalInputs: inputs,
76
78
  });
77
79
  await preTransaction.generateTransactionMinimalSignatures();
78
80
  const parameters = await preTransaction.getFundingTransactionParameters();
@@ -101,11 +103,14 @@ export class TransactionFactory {
101
103
  interactionParameters.utxos = this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.to, 0);
102
104
  const newParams = {
103
105
  ...interactionParameters,
104
- utxos: this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.to, 0),
106
+ utxos: [
107
+ ...this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.to, 0),
108
+ ],
105
109
  randomBytes: preTransaction.getRndBytes(),
106
110
  preimage: preTransaction.getPreimage(),
107
111
  nonWitnessUtxo: signedTransaction.tx.toBuffer(),
108
112
  estimatedFees: preTransaction.estimatedFees,
113
+ optionalInputs: inputs,
109
114
  };
110
115
  const finalTransaction = new InteractionTransaction(newParams);
111
116
  const outTx = await finalTransaction.signTransaction();
@@ -118,13 +123,35 @@ export class TransactionFactory {
118
123
  };
119
124
  }
120
125
  async signDeployment(deploymentParameters) {
121
- const preTransaction = new DeploymentTransaction(deploymentParameters);
122
- await preTransaction.signTransaction();
126
+ const opWalletDeployment = await this.detectDeploymentOPWallet(deploymentParameters);
127
+ if (opWalletDeployment) {
128
+ return opWalletDeployment;
129
+ }
130
+ if (!('signer' in deploymentParameters)) {
131
+ throw new Error('Field "signer" not provided, OP_WALLET not detected.');
132
+ }
133
+ const inputs = this.parseOptionalInputs(deploymentParameters.optionalInputs);
134
+ const preTransaction = new DeploymentTransaction({
135
+ ...deploymentParameters,
136
+ utxos: [deploymentParameters.utxos[0]],
137
+ optionalInputs: inputs,
138
+ });
139
+ await preTransaction.generateTransactionMinimalSignatures();
123
140
  const parameters = await preTransaction.getFundingTransactionParameters();
141
+ parameters.utxos = deploymentParameters.utxos;
124
142
  parameters.amount =
125
143
  (await preTransaction.estimateTransactionFees()) +
126
144
  this.getPriorityFee(deploymentParameters) +
127
145
  preTransaction.getOptionalOutputValue();
146
+ const feeEstimationFundingTransaction = await this.createFundTransaction({
147
+ ...parameters,
148
+ optionalOutputs: [],
149
+ optionalInputs: [],
150
+ });
151
+ if (!feeEstimationFundingTransaction) {
152
+ throw new Error('Could not sign funding transaction.');
153
+ }
154
+ parameters.estimatedFees = feeEstimationFundingTransaction.estimatedFees;
128
155
  const fundingTransaction = new FundingTransaction({
129
156
  ...parameters,
130
157
  optionalInputs: [],
@@ -150,8 +177,8 @@ export class TransactionFactory {
150
177
  randomBytes: preTransaction.getRndBytes(),
151
178
  preimage: preTransaction.getPreimage(),
152
179
  nonWitnessUtxo: signedTransaction.toBuffer(),
153
- optionalOutputs: [],
154
- optionalInputs: [],
180
+ estimatedFees: preTransaction.estimatedFees,
181
+ optionalInputs: inputs,
155
182
  };
156
183
  const finalTransaction = new DeploymentTransaction(newParams);
157
184
  const outTx = await finalTransaction.signTransaction();
@@ -214,11 +241,29 @@ export class TransactionFactory {
214
241
  }
215
242
  return utxos;
216
243
  }
244
+ parseOptionalInputs(optionalInputs) {
245
+ return (optionalInputs || []).map((input) => {
246
+ let nonWitness = input.nonWitnessUtxo;
247
+ if (nonWitness &&
248
+ !(nonWitness instanceof Uint8Array) &&
249
+ typeof nonWitness === 'object') {
250
+ nonWitness = Buffer.from(Uint8Array.from(Object.values(input.nonWitnessUtxo)));
251
+ }
252
+ return {
253
+ ...input,
254
+ nonWitnessUtxo: nonWitness,
255
+ };
256
+ });
257
+ }
217
258
  async detectInteractionOPWallet(interactionParameters) {
218
- if (typeof window === 'undefined' || !window.opnet || !window.opnet.web3) {
259
+ if (typeof window === 'undefined') {
219
260
  return null;
220
261
  }
221
- const opnet = window.opnet.web3;
262
+ const _window = window;
263
+ if (!_window || !_window.opnet || !_window.opnet.web3) {
264
+ return null;
265
+ }
266
+ const opnet = _window.opnet.web3;
222
267
  const interaction = await opnet.signInteraction({
223
268
  ...interactionParameters,
224
269
  signer: undefined,
@@ -228,6 +273,24 @@ export class TransactionFactory {
228
273
  }
229
274
  return interaction;
230
275
  }
276
+ async detectDeploymentOPWallet(deploymentParameters) {
277
+ if (typeof window === 'undefined') {
278
+ return null;
279
+ }
280
+ const _window = window;
281
+ if (!_window || !_window.opnet || !_window.opnet.web3) {
282
+ return null;
283
+ }
284
+ const opnet = _window.opnet.web3;
285
+ const deployment = await opnet.deployContract({
286
+ ...deploymentParameters,
287
+ signer: undefined,
288
+ });
289
+ if (!deployment) {
290
+ throw new Error('Could not sign interaction transaction.');
291
+ }
292
+ return deployment;
293
+ }
231
294
  async _createChallengeSolution(parameters) {
232
295
  if (!parameters.to)
233
296
  throw new Error('Field "to" not provided.');
@@ -1,11 +1,9 @@
1
1
  import { Network, Psbt } from '@btc-vision/bitcoin';
2
2
  import { CustomKeypair } from '../BrowserSignerBase.js';
3
3
  import { SignatureType, Unisat } from '../types/Unisat.js';
4
- declare global {
5
- interface Window {
6
- unisat?: Unisat;
7
- opnet?: Unisat;
8
- }
4
+ export interface WindowWithWallets {
5
+ unisat?: Unisat;
6
+ opnet?: Unisat;
9
7
  }
10
8
  export declare class UnisatSigner extends CustomKeypair {
11
9
  private isInitialized;
@@ -42,6 +42,8 @@ export class UnisatSigner extends CustomKeypair {
42
42
  return this._network;
43
43
  }
44
44
  get unisat() {
45
+ if (!window)
46
+ throw new Error('Window not found');
45
47
  const module = window.unisat;
46
48
  if (!module) {
47
49
  throw new Error('Unisat extension not found');
@@ -125,7 +125,12 @@ export class DeploymentTransaction extends TransactionBuilder {
125
125
  transaction.finalizeInput(i, this.customFinalizer);
126
126
  }
127
127
  else {
128
- transaction.finalizeInput(i);
128
+ try {
129
+ transaction.finalizeInput(i, this.customFinalizerP2SH);
130
+ }
131
+ catch (e) {
132
+ transaction.finalizeInput(i);
133
+ }
129
134
  }
130
135
  }
131
136
  }
@@ -146,7 +151,12 @@ export class DeploymentTransaction extends TransactionBuilder {
146
151
  }
147
152
  else {
148
153
  transaction.signInput(i, this.getSignerKey());
149
- transaction.finalizeInput(i);
154
+ try {
155
+ transaction.finalizeInput(i, this.customFinalizerP2SH);
156
+ }
157
+ catch (e) {
158
+ transaction.finalizeInput(i);
159
+ }
150
160
  }
151
161
  }
152
162
  }
@@ -36,8 +36,8 @@ export declare abstract class SharedInteractionTransaction<T extends Transaction
36
36
  finalScriptWitness: Buffer<ArrayBufferLike>;
37
37
  };
38
38
  protected signInputsWalletBased(transaction: Psbt): Promise<void>;
39
+ protected signInputsNonWalletBased(transaction: Psbt): Promise<void>;
39
40
  private createMineableRewardOutputs;
40
- private signInputsNonWalletBased;
41
41
  private getPubKeys;
42
42
  private generateRedeemScripts;
43
43
  }
@@ -156,7 +156,30 @@ export class SharedInteractionTransaction extends TransactionBuilder {
156
156
  transaction.finalizeInput(i, this.customFinalizer);
157
157
  }
158
158
  else {
159
- transaction.finalizeInput(i);
159
+ try {
160
+ transaction.finalizeInput(i, this.customFinalizerP2SH);
161
+ }
162
+ catch (e) {
163
+ transaction.finalizeInput(i);
164
+ }
165
+ }
166
+ }
167
+ }
168
+ async signInputsNonWalletBased(transaction) {
169
+ for (let i = 0; i < transaction.data.inputs.length; i++) {
170
+ if (i === 0) {
171
+ await this.signInput(transaction, transaction.data.inputs[i], i, this.scriptSigner);
172
+ await this.signInput(transaction, transaction.data.inputs[i], i, this.getSignerKey());
173
+ transaction.finalizeInput(0, this.customFinalizer);
174
+ }
175
+ else {
176
+ await this.signInput(transaction, transaction.data.inputs[i], i, this.signer);
177
+ try {
178
+ transaction.finalizeInput(i, this.customFinalizerP2SH);
179
+ }
180
+ catch (e) {
181
+ transaction.finalizeInput(i);
182
+ }
160
183
  }
161
184
  }
162
185
  }
@@ -187,19 +210,6 @@ export class SharedInteractionTransaction extends TransactionBuilder {
187
210
  await this.addRefundOutput(amountSpent + amount);
188
211
  }
189
212
  }
190
- async signInputsNonWalletBased(transaction) {
191
- for (let i = 0; i < transaction.data.inputs.length; i++) {
192
- if (i === 0) {
193
- await this.signInput(transaction, transaction.data.inputs[i], i, this.scriptSigner);
194
- await this.signInput(transaction, transaction.data.inputs[i], i, this.getSignerKey());
195
- transaction.finalizeInput(i, this.customFinalizer);
196
- }
197
- else {
198
- await this.signInput(transaction, transaction.data.inputs[i], i, this.getSignerKey());
199
- transaction.finalizeInput(i);
200
- }
201
- }
202
- }
203
213
  getPubKeys() {
204
214
  const pubKeys = [Buffer.from(this.signer.publicKey)];
205
215
  if (this.scriptSigner) {
@@ -293,9 +293,9 @@ export class TransactionBuilder extends TweakedTransaction {
293
293
  }
294
294
  }
295
295
  if (this.optionalInputs) {
296
- for (let i = 0; i < this.optionalInputs.length; i++) {
297
- const utxo = this.optionalInputs[i];
298
- const input = this.generatePsbtInputExtended(utxo, i);
296
+ for (let i = this.utxos.length; i < this.optionalInputs.length + this.utxos.length; i++) {
297
+ const utxo = this.optionalInputs[i - this.utxos.length];
298
+ const input = this.generatePsbtInputExtended(utxo, i, true);
299
299
  this.addInput(input);
300
300
  }
301
301
  }
@@ -51,6 +51,7 @@ export declare abstract class TweakedTransaction extends Logger {
51
51
  protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean, errored?: boolean): Promise<void>;
52
52
  protected splitArray<T>(arr: T[], chunkSize: number): T[][];
53
53
  protected signInputs(transaction: Psbt): Promise<void>;
54
+ protected signInputsNonWalletBased(transaction: Psbt): Promise<void>;
54
55
  protected internalPubKeyToXOnly(): Buffer;
55
56
  protected internalInit(): void;
56
57
  protected tweakSigner(): void;
@@ -64,7 +65,7 @@ export declare abstract class TweakedTransaction extends Logger {
64
65
  redeemScript: Buffer;
65
66
  outputScript: Buffer;
66
67
  } | undefined;
67
- protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended;
68
+ protected generatePsbtInputExtended(utxo: UTXO, i: number, extra?: boolean): PsbtInputExtended;
68
69
  protected customFinalizerP2SH: (inputIndex: number, input: PsbtInput, scriptA: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean) => {
69
70
  finalScriptSig: Buffer | undefined;
70
71
  finalScriptWitness: Buffer | undefined;
@@ -208,6 +208,9 @@ export class TweakedTransaction extends Logger {
208
208
  await this.signInputsWalletBased(transaction);
209
209
  return;
210
210
  }
211
+ await this.signInputsNonWalletBased(transaction);
212
+ }
213
+ async signInputsNonWalletBased(transaction) {
211
214
  const txs = transaction.data.inputs;
212
215
  const batchSize = 20;
213
216
  const batches = this.splitArray(txs, batchSize);
@@ -324,7 +327,7 @@ export class TweakedTransaction extends Logger {
324
327
  }
325
328
  return;
326
329
  }
327
- generatePsbtInputExtended(utxo, i) {
330
+ generatePsbtInputExtended(utxo, i, extra = false) {
328
331
  const script = Buffer.from(utxo.scriptPubKey.hex, 'hex');
329
332
  const input = {
330
333
  hash: utxo.transactionId,
@@ -421,11 +424,13 @@ export class TweakedTransaction extends Logger {
421
424
  else {
422
425
  this.error(`Unknown or unsupported script type for output: ${utxo.scriptPubKey.hex}`);
423
426
  }
424
- if (this.tapLeafScript) {
425
- input.tapLeafScript = [this.tapLeafScript];
426
- }
427
- if (i === 0 && this.nonWitnessUtxo) {
428
- input.nonWitnessUtxo = this.nonWitnessUtxo;
427
+ if (i === 0) {
428
+ if (this.tapLeafScript) {
429
+ input.tapLeafScript = [this.tapLeafScript];
430
+ }
431
+ if (this.nonWitnessUtxo) {
432
+ input.nonWitnessUtxo = this.nonWitnessUtxo;
433
+ }
429
434
  }
430
435
  return input;
431
436
  }
@@ -453,7 +458,16 @@ export class TweakedTransaction extends Logger {
453
458
  tweakedSigner = this.tweakedSigner;
454
459
  }
455
460
  if (tweakedSigner) {
456
- await this.signTaprootInput(tweakedSigner, transaction, i);
461
+ try {
462
+ await this.signTaprootInput(tweakedSigner, transaction, i);
463
+ }
464
+ catch (e) {
465
+ tweakedSigner = this.getTweakedSigner(false, this.signer);
466
+ if (!tweakedSigner) {
467
+ throw new Error(`Failed to obtain tweaked signer for input ${i}.`);
468
+ }
469
+ await this.signTaprootInput(tweakedSigner, transaction, i);
470
+ }
457
471
  }
458
472
  else {
459
473
  this.error(`Failed to obtain tweaked signer for input ${i}.`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@btc-vision/transaction",
3
3
  "type": "module",
4
- "version": "1.3.3",
4
+ "version": "1.3.5",
5
5
  "author": "BlobMaster41",
6
6
  "description": "OPNet transaction library allows you to create and sign transactions for the OPNet network.",
7
7
  "engines": {
package/src/_version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.3.3';
1
+ export const version = '1.3.5';
package/src/opnet.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Unisat } from './transaction/browser/types/Unisat.js';
2
+
1
3
  export { version } from './_version.js';
2
4
 
3
5
  /** Bytecode */
@@ -97,3 +99,10 @@ export * from './transaction/browser/Web3Provider.js';
97
99
 
98
100
  export * from './keypair/Secp256k1PointDeriver.js';
99
101
  export * from './transaction/ContractAddress.js';
102
+
103
+ declare global {
104
+ interface Window {
105
+ unisat?: Unisat;
106
+ opnet?: Unisat;
107
+ }
108
+ }