@btc-vision/transaction 1.3.4 → 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.
@@ -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;
@@ -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,18 +70,7 @@ 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 = (interactionParameters.optionalInputs || []).map((input) => {
74
- let nonWitness = input.nonWitnessUtxo;
75
- if (nonWitness &&
76
- !(nonWitness instanceof Uint8Array) &&
77
- typeof nonWitness === 'object') {
78
- nonWitness = Buffer.from(Uint8Array.from(Object.values(input.nonWitnessUtxo)));
79
- }
80
- return {
81
- ...input,
82
- nonWitnessUtxo: nonWitness,
83
- };
84
- });
73
+ const inputs = this.parseOptionalInputs(interactionParameters.optionalInputs);
85
74
  const preTransaction = new InteractionTransaction({
86
75
  ...interactionParameters,
87
76
  utxos: [interactionParameters.utxos[0]],
@@ -134,13 +123,35 @@ export class TransactionFactory {
134
123
  };
135
124
  }
136
125
  async signDeployment(deploymentParameters) {
137
- const preTransaction = new DeploymentTransaction(deploymentParameters);
138
- 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();
139
140
  const parameters = await preTransaction.getFundingTransactionParameters();
141
+ parameters.utxos = deploymentParameters.utxos;
140
142
  parameters.amount =
141
143
  (await preTransaction.estimateTransactionFees()) +
142
144
  this.getPriorityFee(deploymentParameters) +
143
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;
144
155
  const fundingTransaction = new FundingTransaction({
145
156
  ...parameters,
146
157
  optionalInputs: [],
@@ -166,8 +177,8 @@ export class TransactionFactory {
166
177
  randomBytes: preTransaction.getRndBytes(),
167
178
  preimage: preTransaction.getPreimage(),
168
179
  nonWitnessUtxo: signedTransaction.toBuffer(),
169
- optionalOutputs: [],
170
- optionalInputs: [],
180
+ estimatedFees: preTransaction.estimatedFees,
181
+ optionalInputs: inputs,
171
182
  };
172
183
  const finalTransaction = new DeploymentTransaction(newParams);
173
184
  const outTx = await finalTransaction.signTransaction();
@@ -230,11 +241,29 @@ export class TransactionFactory {
230
241
  }
231
242
  return utxos;
232
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
+ }
233
258
  async detectInteractionOPWallet(interactionParameters) {
234
- if (typeof window === 'undefined' || !window || !window.opnet || !window.opnet.web3) {
259
+ if (typeof window === 'undefined') {
260
+ return null;
261
+ }
262
+ const _window = window;
263
+ if (!_window || !_window.opnet || !_window.opnet.web3) {
235
264
  return null;
236
265
  }
237
- const opnet = window.opnet.web3;
266
+ const opnet = _window.opnet.web3;
238
267
  const interaction = await opnet.signInteraction({
239
268
  ...interactionParameters,
240
269
  signer: undefined,
@@ -244,6 +273,24 @@ export class TransactionFactory {
244
273
  }
245
274
  return interaction;
246
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
+ }
247
294
  async _createChallengeSolution(parameters) {
248
295
  if (!parameters.to)
249
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;
@@ -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
  }
@@ -428,9 +428,9 @@ export class TweakedTransaction extends Logger {
428
428
  if (this.tapLeafScript) {
429
429
  input.tapLeafScript = [this.tapLeafScript];
430
430
  }
431
- }
432
- if (i === 0 && this.nonWitnessUtxo) {
433
- input.nonWitnessUtxo = this.nonWitnessUtxo;
431
+ if (this.nonWitnessUtxo) {
432
+ input.nonWitnessUtxo = this.nonWitnessUtxo;
433
+ }
434
434
  }
435
435
  return input;
436
436
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@btc-vision/transaction",
3
3
  "type": "module",
4
- "version": "1.3.4",
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
+ }
@@ -19,7 +19,11 @@ import {
19
19
  } from './interfaces/ITransactionParameters.js';
20
20
  import { PSBTTypes } from './psbt/PSBTTypes.js';
21
21
  import { ChallengeSolutionTransaction } from './builders/ChallengeSolutionTransaction.js';
22
- import { InteractionParametersWithoutSigner } from './browser/Web3Provider.js';
22
+ import {
23
+ IDeploymentParametersWithoutSigner,
24
+ InteractionParametersWithoutSigner,
25
+ } from './browser/Web3Provider.js';
26
+ import { WindowWithWallets } from './browser/extensions/UnisatSigner.js';
23
27
 
24
28
  export interface DeploymentResult {
25
29
  readonly transaction: [string, string];
@@ -174,26 +178,7 @@ export class TransactionFactory {
174
178
  throw new Error('Field "signer" not provided, OP_WALLET not detected.');
175
179
  }
176
180
 
177
- const inputs = (interactionParameters.optionalInputs || []).map((input) => {
178
- let nonWitness = input.nonWitnessUtxo;
179
- if (
180
- nonWitness &&
181
- !(nonWitness instanceof Uint8Array) &&
182
- typeof nonWitness === 'object'
183
- ) {
184
- nonWitness = Buffer.from(
185
- Uint8Array.from(
186
- Object.values(input.nonWitnessUtxo as unknown as Record<number, number>),
187
- ),
188
- );
189
- }
190
-
191
- return {
192
- ...input,
193
- nonWitnessUtxo: nonWitness,
194
- };
195
- });
196
-
181
+ const inputs = this.parseOptionalInputs(interactionParameters.optionalInputs);
197
182
  const preTransaction: InteractionTransaction = new InteractionTransaction({
198
183
  ...interactionParameters,
199
184
  utxos: [interactionParameters.utxos[0]], // we simulate one input here.
@@ -277,21 +262,46 @@ export class TransactionFactory {
277
262
  public async signDeployment(
278
263
  deploymentParameters: IDeploymentParameters,
279
264
  ): Promise<DeploymentResult> {
280
- const preTransaction: DeploymentTransaction = new DeploymentTransaction(
281
- deploymentParameters,
282
- );
265
+ const opWalletDeployment = await this.detectDeploymentOPWallet(deploymentParameters);
266
+ if (opWalletDeployment) {
267
+ return opWalletDeployment;
268
+ }
283
269
 
284
- // Initial generation
285
- await preTransaction.signTransaction();
270
+ if (!('signer' in deploymentParameters)) {
271
+ throw new Error('Field "signer" not provided, OP_WALLET not detected.');
272
+ }
273
+
274
+ const inputs = this.parseOptionalInputs(deploymentParameters.optionalInputs);
275
+ const preTransaction: DeploymentTransaction = new DeploymentTransaction({
276
+ ...deploymentParameters,
277
+ utxos: [deploymentParameters.utxos[0]], // we simulate one input here.
278
+ optionalInputs: inputs,
279
+ });
280
+
281
+ // we don't sign that transaction, we just need the parameters.
282
+ await preTransaction.generateTransactionMinimalSignatures();
286
283
 
287
284
  const parameters: IFundingTransactionParameters =
288
285
  await preTransaction.getFundingTransactionParameters();
289
286
 
287
+ parameters.utxos = deploymentParameters.utxos;
290
288
  parameters.amount =
291
289
  (await preTransaction.estimateTransactionFees()) +
292
290
  this.getPriorityFee(deploymentParameters) +
293
291
  preTransaction.getOptionalOutputValue();
294
292
 
293
+ const feeEstimationFundingTransaction = await this.createFundTransaction({
294
+ ...parameters,
295
+ optionalOutputs: [],
296
+ optionalInputs: [],
297
+ });
298
+
299
+ if (!feeEstimationFundingTransaction) {
300
+ throw new Error('Could not sign funding transaction.');
301
+ }
302
+
303
+ parameters.estimatedFees = feeEstimationFundingTransaction.estimatedFees;
304
+
295
305
  const fundingTransaction: FundingTransaction = new FundingTransaction({
296
306
  ...parameters,
297
307
  optionalInputs: [],
@@ -316,12 +326,12 @@ export class TransactionFactory {
316
326
 
317
327
  const newParams: IDeploymentParameters = {
318
328
  ...deploymentParameters,
319
- utxos: [newUtxo],
329
+ utxos: [newUtxo], // always 0
320
330
  randomBytes: preTransaction.getRndBytes(),
321
331
  preimage: preTransaction.getPreimage(),
322
332
  nonWitnessUtxo: signedTransaction.toBuffer(),
323
- optionalOutputs: [],
324
- optionalInputs: [],
333
+ estimatedFees: preTransaction.estimatedFees,
334
+ optionalInputs: inputs,
325
335
  };
326
336
 
327
337
  const finalTransaction: DeploymentTransaction = new DeploymentTransaction(newParams);
@@ -420,14 +430,41 @@ export class TransactionFactory {
420
430
  return utxos;
421
431
  }
422
432
 
433
+ private parseOptionalInputs(optionalInputs?: UTXO[]): UTXO[] {
434
+ return (optionalInputs || []).map((input) => {
435
+ let nonWitness = input.nonWitnessUtxo;
436
+ if (
437
+ nonWitness &&
438
+ !(nonWitness instanceof Uint8Array) &&
439
+ typeof nonWitness === 'object'
440
+ ) {
441
+ nonWitness = Buffer.from(
442
+ Uint8Array.from(
443
+ Object.values(input.nonWitnessUtxo as unknown as Record<number, number>),
444
+ ),
445
+ );
446
+ }
447
+
448
+ return {
449
+ ...input,
450
+ nonWitnessUtxo: nonWitness,
451
+ };
452
+ });
453
+ }
454
+
423
455
  private async detectInteractionOPWallet(
424
456
  interactionParameters: IInteractionParameters | InteractionParametersWithoutSigner,
425
457
  ): Promise<InteractionResponse | null> {
426
- if (typeof window === 'undefined' || !window || !window.opnet || !window.opnet.web3) {
458
+ if (typeof window === 'undefined') {
459
+ return null;
460
+ }
461
+
462
+ const _window = window as WindowWithWallets;
463
+ if (!_window || !_window.opnet || !_window.opnet.web3) {
427
464
  return null;
428
465
  }
429
466
 
430
- const opnet = window.opnet.web3;
467
+ const opnet = _window.opnet.web3;
431
468
  const interaction = await opnet.signInteraction({
432
469
  ...interactionParameters,
433
470
 
@@ -442,6 +479,33 @@ export class TransactionFactory {
442
479
  return interaction;
443
480
  }
444
481
 
482
+ private async detectDeploymentOPWallet(
483
+ deploymentParameters: IDeploymentParameters | IDeploymentParametersWithoutSigner,
484
+ ): Promise<DeploymentResult | null> {
485
+ if (typeof window === 'undefined') {
486
+ return null;
487
+ }
488
+
489
+ const _window = window as WindowWithWallets;
490
+ if (!_window || !_window.opnet || !_window.opnet.web3) {
491
+ return null;
492
+ }
493
+
494
+ const opnet = _window.opnet.web3;
495
+ const deployment = await opnet.deployContract({
496
+ ...deploymentParameters,
497
+
498
+ // @ts-expect-error no, this is ok
499
+ signer: undefined,
500
+ });
501
+
502
+ if (!deployment) {
503
+ throw new Error('Could not sign interaction transaction.');
504
+ }
505
+
506
+ return deployment;
507
+ }
508
+
445
509
  private async _createChallengeSolution(
446
510
  parameters: IChallengeSolutionTransactionParameters,
447
511
  ): Promise<ChallengeSolutionResponse> {
@@ -14,11 +14,9 @@ import { canSignNonTaprootInput, isTaprootInput } from '../../../signer/SignerUt
14
14
  import { CustomKeypair } from '../BrowserSignerBase.js';
15
15
  import { PsbtSignatureOptions, SignatureType, Unisat, UnisatNetwork } from '../types/Unisat.js';
16
16
 
17
- declare global {
18
- interface Window {
19
- unisat?: Unisat;
20
- opnet?: Unisat;
21
- }
17
+ export interface WindowWithWallets {
18
+ unisat?: Unisat;
19
+ opnet?: Unisat;
22
20
  }
23
21
 
24
22
  export class UnisatSigner extends CustomKeypair {
@@ -85,7 +83,7 @@ export class UnisatSigner extends CustomKeypair {
85
83
  public get unisat(): Unisat {
86
84
  if (!window) throw new Error('Window not found');
87
85
 
88
- const module = window.unisat;
86
+ const module = (window as WindowWithWallets).unisat;
89
87
  if (!module) {
90
88
  throw new Error('Unisat extension not found');
91
89
  }
@@ -118,7 +118,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
118
118
  this.verifyCalldata();
119
119
  }
120
120
 
121
- if(!parameters.preimage) throw new Error('Preimage is required');
121
+ if (!parameters.preimage) throw new Error('Preimage is required');
122
122
 
123
123
  this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
124
124
  this.preimage = parameters.preimage;
@@ -274,7 +274,11 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
274
274
  if (i === 0) {
275
275
  transaction.finalizeInput(i, this.customFinalizer);
276
276
  } else {
277
- transaction.finalizeInput(i);
277
+ try {
278
+ transaction.finalizeInput(i, this.customFinalizerP2SH);
279
+ } catch (e) {
280
+ transaction.finalizeInput(i);
281
+ }
278
282
  }
279
283
  }
280
284
  }
@@ -305,7 +309,12 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
305
309
  transaction.finalizeInput(0, this.customFinalizer);
306
310
  } else {
307
311
  transaction.signInput(i, this.getSignerKey());
308
- transaction.finalizeInput(i);
312
+
313
+ try {
314
+ transaction.finalizeInput(i, this.customFinalizerP2SH);
315
+ } catch (e) {
316
+ transaction.finalizeInput(i);
317
+ }
309
318
  }
310
319
  }
311
320
  }
@@ -802,11 +802,10 @@ export abstract class TweakedTransaction extends Logger {
802
802
  if (this.tapLeafScript) {
803
803
  input.tapLeafScript = [this.tapLeafScript];
804
804
  }
805
- }
806
805
 
807
- // If the first input and we have a global nonWitnessUtxo not yet set
808
- if (i === 0 && this.nonWitnessUtxo) {
809
- input.nonWitnessUtxo = this.nonWitnessUtxo;
806
+ if (this.nonWitnessUtxo) {
807
+ input.nonWitnessUtxo = this.nonWitnessUtxo;
808
+ }
810
809
  }
811
810
 
812
811
  /*if (utxo.nonWitnessUtxo && extra) {