@btc-vision/transaction 1.3.4 → 1.3.6

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 (46) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/generators/Features.d.ts +9 -4
  3. package/browser/generators/Generator.d.ts +5 -2
  4. package/browser/generators/builders/CalldataGenerator.d.ts +2 -2
  5. package/browser/generators/builders/LegacyCalldataGenerator.d.ts +2 -2
  6. package/browser/index.js +1 -1
  7. package/browser/opnet.d.ts +7 -0
  8. package/browser/transaction/TransactionFactory.d.ts +2 -0
  9. package/browser/transaction/browser/extensions/UnisatSigner.d.ts +3 -5
  10. package/browser/transaction/builders/InteractionTransaction.d.ts +1 -0
  11. package/browser/transaction/interfaces/ITransactionParameters.d.ts +4 -0
  12. package/build/_version.d.ts +1 -1
  13. package/build/_version.js +1 -1
  14. package/build/generators/Features.d.ts +9 -4
  15. package/build/generators/Features.js +1 -5
  16. package/build/generators/Generator.d.ts +5 -2
  17. package/build/generators/Generator.js +40 -5
  18. package/build/generators/builders/CalldataGenerator.d.ts +2 -2
  19. package/build/generators/builders/CalldataGenerator.js +10 -4
  20. package/build/generators/builders/DeploymentGenerator.js +13 -2
  21. package/build/generators/builders/LegacyCalldataGenerator.d.ts +2 -2
  22. package/build/generators/builders/LegacyCalldataGenerator.js +10 -4
  23. package/build/opnet.d.ts +7 -0
  24. package/build/transaction/TransactionFactory.d.ts +2 -0
  25. package/build/transaction/TransactionFactory.js +65 -18
  26. package/build/transaction/browser/extensions/UnisatSigner.d.ts +3 -5
  27. package/build/transaction/builders/DeploymentTransaction.js +12 -2
  28. package/build/transaction/builders/InteractionTransaction.d.ts +1 -0
  29. package/build/transaction/builders/InteractionTransaction.js +12 -1
  30. package/build/transaction/interfaces/ITransactionParameters.d.ts +4 -0
  31. package/build/transaction/shared/TweakedTransaction.js +3 -3
  32. package/eslint.config.js +1 -0
  33. package/package.json +1 -1
  34. package/src/_version.ts +1 -1
  35. package/src/generators/Features.ts +10 -5
  36. package/src/generators/Generator.ts +54 -5
  37. package/src/generators/builders/CalldataGenerator.ts +16 -9
  38. package/src/generators/builders/DeploymentGenerator.ts +17 -1
  39. package/src/generators/builders/LegacyCalldataGenerator.ts +14 -6
  40. package/src/opnet.ts +9 -0
  41. package/src/transaction/TransactionFactory.ts +95 -31
  42. package/src/transaction/browser/extensions/UnisatSigner.ts +4 -6
  43. package/src/transaction/builders/DeploymentTransaction.ts +12 -3
  44. package/src/transaction/builders/InteractionTransaction.ts +15 -0
  45. package/src/transaction/interfaces/ITransactionParameters.ts +7 -1
  46. package/src/transaction/shared/TweakedTransaction.ts +3 -4
@@ -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;
@@ -10,4 +10,5 @@ export declare class InteractionTransaction extends SharedInteractionTransaction
10
10
  protected tapLeafScript: TapLeafScript | null;
11
11
  protected readonly contractSecret: Buffer;
12
12
  constructor(parameters: IInteractionParameters);
13
+ private generateFeatures;
13
14
  }
@@ -2,6 +2,9 @@ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
2
2
  import { ITweakedTransactionData } from '../shared/TweakedTransaction.js';
3
3
  import { ChainId } from '../../network/ChainId.js';
4
4
  import { PsbtOutputExtended } from '@btc-vision/bitcoin';
5
+ export interface LoadedStorage {
6
+ [key: string]: string[];
7
+ }
5
8
  export interface ITransactionParameters extends ITweakedTransactionData {
6
9
  readonly from?: string;
7
10
  readonly to?: string;
@@ -28,6 +31,7 @@ export interface SharedInteractionParameters extends ITransactionParameters {
28
31
  disableAutoRefund?: boolean;
29
32
  readonly preimage: Buffer;
30
33
  readonly randomBytes?: Buffer;
34
+ readonly loadedStorage?: LoadedStorage;
31
35
  }
32
36
  export interface IInteractionParameters extends SharedInteractionParameters {
33
37
  readonly calldata: Buffer;
@@ -1 +1 @@
1
- export declare const version = "1.3.3";
1
+ export declare const version = "1.3.6";
package/build/_version.js CHANGED
@@ -1 +1 @@
1
- export const version = '1.3.3';
1
+ export const version = '1.3.6';
@@ -1,6 +1,11 @@
1
+ import { LoadedStorage } from '../transaction/interfaces/ITransactionParameters.js';
1
2
  export declare enum Features {
2
- UNWRAP = 0
3
+ ACCESS_LIST = 1
4
+ }
5
+ export interface Feature<T extends Features> {
6
+ opcode: T;
7
+ data: unknown;
8
+ }
9
+ export interface AccessListFeature extends Feature<Features.ACCESS_LIST> {
10
+ data: LoadedStorage;
3
11
  }
4
- export declare const FeatureOpCodes: {
5
- [key: number]: number;
6
- };
@@ -1,8 +1,4 @@
1
- import { opcodes } from '@btc-vision/bitcoin';
2
1
  export var Features;
3
2
  (function (Features) {
4
- Features[Features["UNWRAP"] = 0] = "UNWRAP";
3
+ Features[Features["ACCESS_LIST"] = 1] = "ACCESS_LIST";
5
4
  })(Features || (Features = {}));
6
- export const FeatureOpCodes = {
7
- [Features.UNWRAP]: opcodes.OP_16,
8
- };
@@ -1,4 +1,5 @@
1
1
  import { Network } from '@btc-vision/bitcoin';
2
+ import { Feature, Features } from './Features.js';
2
3
  export declare abstract class Generator {
3
4
  static readonly DATA_CHUNK_SIZE: number;
4
5
  static readonly MAGIC: Buffer;
@@ -7,8 +8,10 @@ export declare abstract class Generator {
7
8
  protected readonly contractSaltPubKey?: Buffer;
8
9
  protected readonly network: Network;
9
10
  protected constructor(senderPubKey: Buffer, contractSaltPubKey?: Buffer, network?: Network);
10
- get senderFirstByte(): Buffer;
11
- getHeader(maxPriority: bigint): Buffer;
11
+ buildHeader(features: Features[]): Buffer;
12
+ getHeader(maxPriority: bigint, features?: Features[]): Buffer;
12
13
  abstract compile(...args: unknown[]): Buffer;
13
14
  protected splitBufferIntoChunks(buffer: Buffer, chunkSize?: number): Array<Buffer[]>;
15
+ protected encodeFeature(feature: Feature<Features>): Buffer[][];
16
+ private encodeAccessListFeature;
14
17
  }
@@ -1,5 +1,8 @@
1
1
  import { networks, toXOnly } from '@btc-vision/bitcoin';
2
2
  import { BinaryWriter } from '../buffer/BinaryWriter.js';
3
+ import { Features } from './Features.js';
4
+ import { Address } from '../keypair/Address.js';
5
+ import { Compressor } from '../bytecode/Compressor.js';
3
6
  export class Generator {
4
7
  constructor(senderPubKey, contractSaltPubKey, network = networks.bitcoin) {
5
8
  this.network = networks.bitcoin;
@@ -8,12 +11,18 @@ export class Generator {
8
11
  this.network = network;
9
12
  this.xSenderPubKey = toXOnly(senderPubKey);
10
13
  }
11
- get senderFirstByte() {
12
- return Buffer.from([this.senderPubKey[0], 0, 0, 0]);
14
+ buildHeader(features) {
15
+ let flags = 0;
16
+ for (const feature of features) {
17
+ flags |= feature;
18
+ }
19
+ const bytesU24 = Buffer.alloc(3);
20
+ bytesU24.writeUIntBE(flags, 0, 3);
21
+ return Buffer.from([this.senderPubKey[0], ...bytesU24]);
13
22
  }
14
- getHeader(maxPriority) {
15
- const writer = new BinaryWriter(8 + 4);
16
- writer.writeBytes(this.senderFirstByte);
23
+ getHeader(maxPriority, features = []) {
24
+ const writer = new BinaryWriter(12);
25
+ writer.writeBytes(this.buildHeader(features));
17
26
  writer.writeU64(maxPriority);
18
27
  return Buffer.from(writer.getBuffer());
19
28
  }
@@ -29,6 +38,32 @@ export class Generator {
29
38
  }
30
39
  return chunks;
31
40
  }
41
+ encodeFeature(feature) {
42
+ switch (feature.opcode) {
43
+ case Features.ACCESS_LIST:
44
+ return this.splitBufferIntoChunks(this.encodeAccessListFeature(feature));
45
+ default:
46
+ throw new Error(`Unknown feature type: ${feature.opcode}`);
47
+ }
48
+ }
49
+ encodeAccessListFeature(feature) {
50
+ const writer = new BinaryWriter();
51
+ writer.writeU16(Object.keys(feature.data).length);
52
+ for (const contract in feature.data) {
53
+ const parsedContract = Address.fromString(contract);
54
+ const data = feature.data[contract];
55
+ writer.writeAddress(parsedContract);
56
+ writer.writeU32(data.length);
57
+ for (const pointer of data) {
58
+ const pointerBuffer = Buffer.from(pointer, 'base64');
59
+ if (pointerBuffer.length !== 32) {
60
+ throw new Error(`Invalid pointer length: ${pointerBuffer.length}`);
61
+ }
62
+ writer.writeBytes(pointerBuffer);
63
+ }
64
+ }
65
+ return Compressor.compress(Buffer.from(writer.getBuffer()));
66
+ }
32
67
  }
33
68
  Generator.DATA_CHUNK_SIZE = 512;
34
69
  Generator.MAGIC = Buffer.from('op', 'utf-8');
@@ -1,8 +1,8 @@
1
1
  import { Network } from '@btc-vision/bitcoin';
2
- import { Features } from '../Features.js';
2
+ import { Feature, Features } from '../Features.js';
3
3
  import { Generator } from '../Generator.js';
4
4
  export declare class CalldataGenerator extends Generator {
5
5
  constructor(senderPubKey: Buffer, contractSaltPubKey: Buffer, network?: Network);
6
6
  static getPubKeyAsBuffer(witnessKeys: Buffer[], network: Network): Buffer;
7
- compile(calldata: Buffer, contractSecret: Buffer, preimage: Buffer, maxPriority: bigint, features?: Features[]): Buffer;
7
+ compile(calldata: Buffer, contractSecret: Buffer, preimage: Buffer, maxPriority: bigint, features?: Feature<Features>[]): Buffer;
8
8
  }
@@ -1,7 +1,6 @@
1
1
  import { crypto, networks, opcodes, script } from '@btc-vision/bitcoin';
2
2
  import { Compressor } from '../../bytecode/Compressor.js';
3
3
  import { EcKeyPair } from '../../keypair/EcKeyPair.js';
4
- import { FeatureOpCodes } from '../Features.js';
5
4
  import { Generator } from '../Generator.js';
6
5
  export class CalldataGenerator extends Generator {
7
6
  constructor(senderPubKey, contractSaltPubKey, network = networks.bitcoin) {
@@ -31,8 +30,16 @@ export class CalldataGenerator extends Generator {
31
30
  const dataChunks = this.splitBufferIntoChunks(calldata);
32
31
  if (!dataChunks.length)
33
32
  throw new Error('No data chunks found');
33
+ const featuresList = [];
34
+ const featureData = [];
35
+ for (let i = 0; i < features.length; i++) {
36
+ const feature = features[i];
37
+ featuresList.push(feature.opcode);
38
+ const data = this.encodeFeature(feature);
39
+ featureData.push(...data);
40
+ }
34
41
  let compiledData = [
35
- this.getHeader(maxPriority),
42
+ this.getHeader(maxPriority, featuresList),
36
43
  opcodes.OP_TOALTSTACK,
37
44
  preimage,
38
45
  opcodes.OP_TOALTSTACK,
@@ -53,8 +60,7 @@ export class CalldataGenerator extends Generator {
53
60
  opcodes.OP_IF,
54
61
  Generator.MAGIC,
55
62
  ];
56
- const featureOpcodes = features.map((feature) => FeatureOpCodes[feature]);
57
- compiledData = compiledData.concat(...featureOpcodes, ...[opcodes.OP_1NEGATE, ...dataChunks, opcodes.OP_ELSE, opcodes.OP_1, opcodes.OP_ENDIF]);
63
+ compiledData = compiledData.concat(...featureData, ...[opcodes.OP_1NEGATE, ...dataChunks, opcodes.OP_ELSE, opcodes.OP_1, opcodes.OP_ENDIF]);
58
64
  const asm = compiledData.flat();
59
65
  const compiled = script.compile(asm);
60
66
  const decompiled = script.decompile(compiled);
@@ -13,13 +13,23 @@ export class DeploymentGenerator extends Generator {
13
13
  }
14
14
  return compiled;
15
15
  }
16
- getAsm(contractBytecode, contractSalt, preimage, maxPriority, calldata) {
16
+ getAsm(contractBytecode, contractSalt, preimage, maxPriority, calldata, features) {
17
17
  if (!this.contractSaltPubKey)
18
18
  throw new Error('Contract salt public key not set');
19
19
  const dataChunks = this.splitBufferIntoChunks(contractBytecode);
20
20
  const calldataChunks = calldata ? this.splitBufferIntoChunks(calldata) : [];
21
+ const featuresList = [];
22
+ const featureData = [];
23
+ if (features) {
24
+ for (let i = 0; i < features.length; i++) {
25
+ const feature = features[i];
26
+ featuresList.push(feature.opcode);
27
+ const data = this.encodeFeature(feature);
28
+ featureData.push(...data);
29
+ }
30
+ }
21
31
  const compiledData = [
22
- this.getHeader(maxPriority),
32
+ this.getHeader(maxPriority, featuresList),
23
33
  opcodes.OP_TOALTSTACK,
24
34
  preimage,
25
35
  opcodes.OP_TOALTSTACK,
@@ -39,6 +49,7 @@ export class DeploymentGenerator extends Generator {
39
49
  opcodes.OP_NUMEQUAL,
40
50
  opcodes.OP_IF,
41
51
  Generator.MAGIC,
52
+ ...featureData,
42
53
  opcodes.OP_0,
43
54
  ...calldataChunks,
44
55
  opcodes.OP_1NEGATE,
@@ -1,8 +1,8 @@
1
1
  import { Network } from '@btc-vision/bitcoin';
2
- import { Features } from '../Features.js';
3
2
  import { Generator } from '../Generator.js';
3
+ import { Feature, Features } from '../Features.js';
4
4
  export declare class LegacyCalldataGenerator extends Generator {
5
5
  constructor(senderPubKey: Buffer, network?: Network);
6
6
  static getPubKeyAsBuffer(witnessKeys: Buffer[], network: Network): Buffer;
7
- compile(calldata: Buffer, contractSecret: Buffer, preimage: Buffer, maxPriority: bigint, features?: Features[]): Buffer;
7
+ compile(calldata: Buffer, contractSecret: Buffer, preimage: Buffer, maxPriority: bigint, features?: Feature<Features>[]): Buffer;
8
8
  }
@@ -1,7 +1,6 @@
1
1
  import { crypto, networks, opcodes, script } from '@btc-vision/bitcoin';
2
2
  import { Compressor } from '../../bytecode/Compressor.js';
3
3
  import { EcKeyPair } from '../../keypair/EcKeyPair.js';
4
- import { FeatureOpCodes } from '../Features.js';
5
4
  import { Generator } from '../Generator.js';
6
5
  export class LegacyCalldataGenerator extends Generator {
7
6
  constructor(senderPubKey, network = networks.bitcoin) {
@@ -29,8 +28,16 @@ export class LegacyCalldataGenerator extends Generator {
29
28
  const dataChunks = this.splitBufferIntoChunks(calldata);
30
29
  if (!dataChunks.length)
31
30
  throw new Error('No data chunks found');
31
+ const featuresList = [];
32
+ const featureData = [];
33
+ for (let i = 0; i < features.length; i++) {
34
+ const feature = features[i];
35
+ featuresList.push(feature.opcode);
36
+ const data = this.encodeFeature(feature);
37
+ featureData.push(...data);
38
+ }
32
39
  let compiledData = [
33
- this.getHeader(maxPriority),
40
+ this.getHeader(maxPriority, featuresList),
34
41
  opcodes.OP_TOALTSTACK,
35
42
  preimage,
36
43
  opcodes.OP_TOALTSTACK,
@@ -48,8 +55,7 @@ export class LegacyCalldataGenerator extends Generator {
48
55
  opcodes.OP_IF,
49
56
  Generator.MAGIC,
50
57
  ];
51
- const featureOpcodes = features.map((feature) => FeatureOpCodes[feature]);
52
- compiledData = compiledData.concat(...featureOpcodes, ...[opcodes.OP_1NEGATE, ...dataChunks, opcodes.OP_ELSE, opcodes.OP_1, opcodes.OP_ENDIF]);
58
+ compiledData = compiledData.concat(...featureData, ...[opcodes.OP_1NEGATE, ...dataChunks, opcodes.OP_ELSE, opcodes.OP_1, opcodes.OP_ENDIF]);
53
59
  const asm = compiledData.flat();
54
60
  const compiled = script.compile(asm);
55
61
  const decompiled = script.decompile(compiled);
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
  }
@@ -10,4 +10,5 @@ export declare class InteractionTransaction extends SharedInteractionTransaction
10
10
  protected tapLeafScript: TapLeafScript | null;
11
11
  protected readonly contractSecret: Buffer;
12
12
  constructor(parameters: IInteractionParameters);
13
+ private generateFeatures;
13
14
  }
@@ -1,13 +1,24 @@
1
1
  import { TransactionType } from '../enums/TransactionType.js';
2
2
  import { SharedInteractionTransaction } from './SharedInteractionTransaction.js';
3
+ import { Features } from '../../generators/Features.js';
3
4
  export class InteractionTransaction extends SharedInteractionTransaction {
4
5
  constructor(parameters) {
5
6
  super(parameters);
6
7
  this.type = TransactionType.INTERACTION;
7
8
  this.tapLeafScript = null;
8
9
  this.contractSecret = this.generateSecret();
9
- this.compiledTargetScript = this.calldataGenerator.compile(this.calldata, this.contractSecret, this.preimage, this.priorityFee);
10
+ this.compiledTargetScript = this.calldataGenerator.compile(this.calldata, this.contractSecret, this.preimage, this.priorityFee, this.generateFeatures(parameters));
10
11
  this.scriptTree = this.getScriptTree();
11
12
  this.internalInit();
12
13
  }
14
+ generateFeatures(parameters) {
15
+ const features = [];
16
+ if (parameters.loadedStorage) {
17
+ features.push({
18
+ opcode: Features.ACCESS_LIST,
19
+ data: parameters.loadedStorage,
20
+ });
21
+ }
22
+ return features;
23
+ }
13
24
  }
@@ -2,6 +2,9 @@ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
2
2
  import { ITweakedTransactionData } from '../shared/TweakedTransaction.js';
3
3
  import { ChainId } from '../../network/ChainId.js';
4
4
  import { PsbtOutputExtended } from '@btc-vision/bitcoin';
5
+ export interface LoadedStorage {
6
+ [key: string]: string[];
7
+ }
5
8
  export interface ITransactionParameters extends ITweakedTransactionData {
6
9
  readonly from?: string;
7
10
  readonly to?: string;
@@ -28,6 +31,7 @@ export interface SharedInteractionParameters extends ITransactionParameters {
28
31
  disableAutoRefund?: boolean;
29
32
  readonly preimage: Buffer;
30
33
  readonly randomBytes?: Buffer;
34
+ readonly loadedStorage?: LoadedStorage;
31
35
  }
32
36
  export interface IInteractionParameters extends SharedInteractionParameters {
33
37
  readonly calldata: Buffer;
@@ -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/eslint.config.js CHANGED
@@ -29,6 +29,7 @@ export default tseslint.config(
29
29
  '@typescript-eslint/no-duplicate-enum-values': 'off',
30
30
  'prefer-spread': 'off',
31
31
  '@typescript-eslint/no-empty-object-type': 'off',
32
+ '@typescript-eslint/prefer-literal-enum-member': 'off'
32
33
  },
33
34
  },
34
35
  {
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.6",
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.6';
@@ -1,9 +1,14 @@
1
- import { opcodes } from '@btc-vision/bitcoin';
1
+ import { LoadedStorage } from '../transaction/interfaces/ITransactionParameters.js';
2
2
 
3
3
  export enum Features {
4
- UNWRAP = 0, // random number just to set the first value
4
+ ACCESS_LIST = 1,
5
5
  }
6
6
 
7
- export const FeatureOpCodes: { [key: number]: number } = {
8
- [Features.UNWRAP]: opcodes.OP_16,
9
- };
7
+ export interface Feature<T extends Features> {
8
+ opcode: T;
9
+ data: unknown;
10
+ }
11
+
12
+ export interface AccessListFeature extends Feature<Features.ACCESS_LIST> {
13
+ data: LoadedStorage;
14
+ }