@btc-vision/transaction 1.0.92 → 1.0.94

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,6 +1,10 @@
1
- import { IInteractionParameters } from '../interfaces/ITransactionParameters.js';
1
+ import { IDeploymentParameters, IInteractionParameters, IUnwrapParameters, IWrapParameters } from '../interfaces/ITransactionParameters.js';
2
2
  import { UTXO } from '../../utxo/interfaces/IUTXO.js';
3
+ import { DeploymentResult, UnwrapResult, WrapResult } from '../TransactionFactory';
3
4
  export type InteractionParametersWithoutSigner = Omit<IInteractionParameters, 'signer'>;
5
+ export type IWrapParametersWithoutSigner = Omit<IWrapParameters, 'signer'>;
6
+ export type IUnwrapParametersSigner = Omit<IUnwrapParameters, 'signer'>;
7
+ export type IDeploymentParametersWithoutSigner = Omit<IDeploymentParameters, 'signer' | 'network'>;
4
8
  export interface BroadcastTransactionOptions {
5
9
  raw: string;
6
10
  psbt: boolean;
@@ -15,5 +19,8 @@ export interface BroadcastedTransaction {
15
19
  export interface Web3Provider {
16
20
  signInteraction(interactionParameters: InteractionParametersWithoutSigner): Promise<[string, string, UTXO[]]>;
17
21
  signAndBroadcastInteraction(interactionParameters: InteractionParametersWithoutSigner): Promise<[BroadcastedTransaction, BroadcastedTransaction, UTXO[]]>;
22
+ deployContract(params: IDeploymentParametersWithoutSigner): Promise<DeploymentResult>;
18
23
  broadcast(transactions: BroadcastTransactionOptions[]): Promise<BroadcastedTransaction[]>;
24
+ wrap(wrapParameters: IWrapParametersWithoutSigner): Promise<WrapResult>;
25
+ unwrap(unwrapParameters: IUnwrapParametersSigner): Promise<UnwrapResult>;
19
26
  }
@@ -6,6 +6,7 @@ import { Address } from '@btc-vision/bsi-binary';
6
6
  declare global {
7
7
  interface Window {
8
8
  unisat?: Unisat;
9
+ opnet?: Unisat;
9
10
  }
10
11
  }
11
12
  export declare class UnisatSigner extends CustomKeypair {
@@ -8,8 +8,11 @@ export declare enum UnisatNetwork {
8
8
  export declare enum UnisatChainType {
9
9
  BITCOIN_MAINNET = "BITCOIN_MAINNET",
10
10
  BITCOIN_TESTNET = "BITCOIN_TESTNET",
11
+ BITCOIN_TESTNET4 = "BITCOIN_TESTNET4",
12
+ BITCOIN_REGTEST = "BITCOIN_REGTEST",
13
+ BITCOIN_SIGNET = "BITCOIN_SIGNET",
11
14
  FRACTAL_BITCOIN_MAINNET = "FRACTAL_BITCOIN_MAINNET",
12
- BITCOIN_REGTEST = "BITCOIN_REGTEST"
15
+ FRACTAL_BITCOIN_TESTNET = "FRACTAL_BITCOIN_TESTNET"
13
16
  }
14
17
  export interface UnisatChainInfo {
15
18
  readonly enum: UnisatChainType;
@@ -1 +1 @@
1
- export declare const version = "1.0.92";
1
+ export declare const version = "1.0.94";
package/build/_version.js CHANGED
@@ -1 +1 @@
1
- export const version = '1.0.92';
1
+ export const version = '1.0.94';
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import { Network } from 'bitcoinjs-lib';
3
+ import { Generator } from '../Generator.js';
4
+ export declare class DeploymentGeneratorV2 extends Generator {
5
+ static readonly DATA_CHUNK_SIZE: number;
6
+ constructor(senderPubKey: Buffer, contractSaltPubKey: Buffer, network?: Network);
7
+ compile(contractBytecode: Buffer, contractSalt: Buffer): {
8
+ compiled: Buffer;
9
+ chunks: Buffer[];
10
+ };
11
+ protected splitBufferIntoChunks(buffer: Buffer, chunkSize?: number): Array<Buffer[]>;
12
+ private getAsm;
13
+ }
@@ -0,0 +1,57 @@
1
+ import { crypto, networks, opcodes, script } from 'bitcoinjs-lib';
2
+ import { Generator } from '../Generator.js';
3
+ export class DeploymentGeneratorV2 extends Generator {
4
+ static DATA_CHUNK_SIZE = 80;
5
+ constructor(senderPubKey, contractSaltPubKey, network = networks.bitcoin) {
6
+ super(senderPubKey, contractSaltPubKey, network);
7
+ }
8
+ compile(contractBytecode, contractSalt) {
9
+ const dataChunks = this.splitBufferIntoChunks(contractBytecode);
10
+ const asm = this.getAsm(dataChunks, contractSalt);
11
+ const compiled = script.compile(asm);
12
+ const decompiled = script.decompile(compiled);
13
+ if (!decompiled) {
14
+ throw new Error('Failed to decompile script??');
15
+ }
16
+ return {
17
+ compiled,
18
+ chunks: dataChunks.flat(),
19
+ };
20
+ }
21
+ splitBufferIntoChunks(buffer, chunkSize = DeploymentGeneratorV2.DATA_CHUNK_SIZE) {
22
+ const chunks = [];
23
+ for (let i = 0; i < buffer.length; i += chunkSize) {
24
+ const dataLength = Math.min(chunkSize, buffer.length - i);
25
+ const buf2 = Buffer.alloc(dataLength);
26
+ for (let j = 0; j < dataLength; j++) {
27
+ buf2.writeUInt8(buffer[i + j], j);
28
+ }
29
+ chunks.push([buf2]);
30
+ }
31
+ return chunks;
32
+ }
33
+ getAsm(dataChunks, contractSalt) {
34
+ const partA = [
35
+ this.senderPubKey,
36
+ opcodes.OP_CHECKSIGVERIFY,
37
+ this.contractSaltPubKey,
38
+ opcodes.OP_CHECKSIGVERIFY,
39
+ opcodes.OP_HASH160,
40
+ crypto.hash160(this.senderPubKey),
41
+ opcodes.OP_EQUALVERIFY,
42
+ opcodes.OP_HASH256,
43
+ crypto.hash256(contractSalt),
44
+ opcodes.OP_EQUALVERIFY,
45
+ ];
46
+ let i = 1;
47
+ for (const chunk of dataChunks) {
48
+ if (i % 80 === 0 && i !== 0) {
49
+ partA.push(...[opcodes.OP_SHA1, crypto.sha1(chunk[0]), opcodes.OP_EQUALVERIFY]);
50
+ }
51
+ partA.push(...[opcodes.OP_TOALTSTACK]);
52
+ i++;
53
+ }
54
+ partA.push(...[opcodes.OP_1]);
55
+ return partA.flat();
56
+ }
57
+ }
@@ -1,6 +1,10 @@
1
- import { IInteractionParameters } from '../interfaces/ITransactionParameters.js';
1
+ import { IDeploymentParameters, IInteractionParameters, IUnwrapParameters, IWrapParameters } from '../interfaces/ITransactionParameters.js';
2
2
  import { UTXO } from '../../utxo/interfaces/IUTXO.js';
3
+ import { DeploymentResult, UnwrapResult, WrapResult } from '../TransactionFactory';
3
4
  export type InteractionParametersWithoutSigner = Omit<IInteractionParameters, 'signer'>;
5
+ export type IWrapParametersWithoutSigner = Omit<IWrapParameters, 'signer'>;
6
+ export type IUnwrapParametersSigner = Omit<IUnwrapParameters, 'signer'>;
7
+ export type IDeploymentParametersWithoutSigner = Omit<IDeploymentParameters, 'signer' | 'network'>;
4
8
  export interface BroadcastTransactionOptions {
5
9
  raw: string;
6
10
  psbt: boolean;
@@ -15,5 +19,8 @@ export interface BroadcastedTransaction {
15
19
  export interface Web3Provider {
16
20
  signInteraction(interactionParameters: InteractionParametersWithoutSigner): Promise<[string, string, UTXO[]]>;
17
21
  signAndBroadcastInteraction(interactionParameters: InteractionParametersWithoutSigner): Promise<[BroadcastedTransaction, BroadcastedTransaction, UTXO[]]>;
22
+ deployContract(params: IDeploymentParametersWithoutSigner): Promise<DeploymentResult>;
18
23
  broadcast(transactions: BroadcastTransactionOptions[]): Promise<BroadcastedTransaction[]>;
24
+ wrap(wrapParameters: IWrapParametersWithoutSigner): Promise<WrapResult>;
25
+ unwrap(unwrapParameters: IUnwrapParametersSigner): Promise<UnwrapResult>;
19
26
  }
@@ -6,6 +6,7 @@ import { Address } from '@btc-vision/bsi-binary';
6
6
  declare global {
7
7
  interface Window {
8
8
  unisat?: Unisat;
9
+ opnet?: Unisat;
9
10
  }
10
11
  }
11
12
  export declare class UnisatSigner extends CustomKeypair {
@@ -67,7 +67,7 @@ export class UnisatSigner extends CustomKeypair {
67
67
  this._network = networks.regtest;
68
68
  break;
69
69
  default:
70
- throw new Error('Invalid network');
70
+ throw new Error(`Invalid network: ${network}`);
71
71
  }
72
72
  const publicKey = await this.unisat.getPublicKey();
73
73
  this._publicKey = Buffer.from(publicKey, 'hex');
@@ -8,8 +8,11 @@ export declare enum UnisatNetwork {
8
8
  export declare enum UnisatChainType {
9
9
  BITCOIN_MAINNET = "BITCOIN_MAINNET",
10
10
  BITCOIN_TESTNET = "BITCOIN_TESTNET",
11
+ BITCOIN_TESTNET4 = "BITCOIN_TESTNET4",
12
+ BITCOIN_REGTEST = "BITCOIN_REGTEST",
13
+ BITCOIN_SIGNET = "BITCOIN_SIGNET",
11
14
  FRACTAL_BITCOIN_MAINNET = "FRACTAL_BITCOIN_MAINNET",
12
- BITCOIN_REGTEST = "BITCOIN_REGTEST"
15
+ FRACTAL_BITCOIN_TESTNET = "FRACTAL_BITCOIN_TESTNET"
13
16
  }
14
17
  export interface UnisatChainInfo {
15
18
  readonly enum: UnisatChainType;
@@ -8,8 +8,11 @@ export var UnisatChainType;
8
8
  (function (UnisatChainType) {
9
9
  UnisatChainType["BITCOIN_MAINNET"] = "BITCOIN_MAINNET";
10
10
  UnisatChainType["BITCOIN_TESTNET"] = "BITCOIN_TESTNET";
11
- UnisatChainType["FRACTAL_BITCOIN_MAINNET"] = "FRACTAL_BITCOIN_MAINNET";
11
+ UnisatChainType["BITCOIN_TESTNET4"] = "BITCOIN_TESTNET4";
12
12
  UnisatChainType["BITCOIN_REGTEST"] = "BITCOIN_REGTEST";
13
+ UnisatChainType["BITCOIN_SIGNET"] = "BITCOIN_SIGNET";
14
+ UnisatChainType["FRACTAL_BITCOIN_MAINNET"] = "FRACTAL_BITCOIN_MAINNET";
15
+ UnisatChainType["FRACTAL_BITCOIN_TESTNET"] = "FRACTAL_BITCOIN_TESTNET";
13
16
  })(UnisatChainType || (UnisatChainType = {}));
14
17
  export var MessageType;
15
18
  (function (MessageType) {
@@ -0,0 +1,36 @@
1
+ /// <reference types="node" />
2
+ import { TransactionType } from '../enums/TransactionType.js';
3
+ import { IDeploymentParameters } from '../interfaces/ITransactionParameters.js';
4
+ import { Payment, Psbt } from 'bitcoinjs-lib';
5
+ import { TransactionBuilder } from './TransactionBuilder.js';
6
+ import { TapLeafScript } from '../interfaces/Tap.js';
7
+ import { Address } from '@btc-vision/bsi-binary';
8
+ export declare class DeploymentTransactionV2 extends TransactionBuilder<TransactionType.DEPLOYMENT> {
9
+ type: TransactionType.DEPLOYMENT;
10
+ protected readonly _contractAddress: Address;
11
+ protected tapLeafScript: TapLeafScript | null;
12
+ private targetScriptRedeem;
13
+ private leftOverFundsScriptRedeem;
14
+ private readonly compiledTargetScript;
15
+ private readonly scriptTree;
16
+ private deploymentGenerator;
17
+ private readonly contractSeed;
18
+ private readonly bytecode;
19
+ private readonly contractSigner;
20
+ private readonly randomBytes;
21
+ constructor(parameters: IDeploymentParameters);
22
+ get contractAddress(): Address;
23
+ get p2trAddress(): Address;
24
+ getRndBytes(): Buffer;
25
+ protected contractSignerXOnlyPubKey(): Buffer;
26
+ protected buildTransaction(): Promise<void>;
27
+ protected signInputs(transaction: Psbt): Promise<void>;
28
+ protected generateScriptAddress(): Payment;
29
+ protected generateTapData(): Payment;
30
+ private getContractSeed;
31
+ private customFinalizer;
32
+ private getPubKeys;
33
+ private generateRedeemScripts;
34
+ private getLeafScript;
35
+ private getScriptTree;
36
+ }
@@ -0,0 +1,192 @@
1
+ import { TransactionType } from '../enums/TransactionType.js';
2
+ import { crypto as bitCrypto } from 'bitcoinjs-lib';
3
+ import { TransactionBuilder } from './TransactionBuilder.js';
4
+ import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
5
+ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
6
+ import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
7
+ import { Compressor } from '../../bytecode/Compressor.js';
8
+ import { AddressGenerator } from '../../generators/AddressGenerator.js';
9
+ import { DeploymentGeneratorV2 } from '../../generators/builders/DeploymentGeneratorV2.js';
10
+ export class DeploymentTransactionV2 extends TransactionBuilder {
11
+ type = TransactionType.DEPLOYMENT;
12
+ _contractAddress;
13
+ tapLeafScript = null;
14
+ targetScriptRedeem = null;
15
+ leftOverFundsScriptRedeem = null;
16
+ compiledTargetScript;
17
+ scriptTree;
18
+ deploymentGenerator;
19
+ contractSeed;
20
+ bytecode;
21
+ contractSigner;
22
+ randomBytes;
23
+ constructor(parameters) {
24
+ super(parameters);
25
+ this.bytecode = Compressor.compress(parameters.bytecode);
26
+ if (!this.bytecode)
27
+ throw new Error('Bytecode is required');
28
+ this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
29
+ this.contractSeed = this.getContractSeed();
30
+ this.contractSigner = EcKeyPair.fromSeedKeyPair(this.contractSeed, this.network);
31
+ this.deploymentGenerator = new DeploymentGeneratorV2(this.internalPubKeyToXOnly(), this.contractSignerXOnlyPubKey(), this.network);
32
+ this.compiledTargetScript = this.deploymentGenerator.compile(this.bytecode, this.randomBytes);
33
+ this.scriptTree = this.getScriptTree();
34
+ this.internalInit();
35
+ this._contractAddress = AddressGenerator.generatePKSH(this.contractSeed, this.network);
36
+ }
37
+ get contractAddress() {
38
+ return this._contractAddress;
39
+ }
40
+ get p2trAddress() {
41
+ return this.to || this.getScriptAddress();
42
+ }
43
+ getRndBytes() {
44
+ return this.randomBytes;
45
+ }
46
+ contractSignerXOnlyPubKey() {
47
+ return toXOnly(this.contractSigner.publicKey);
48
+ }
49
+ async buildTransaction() {
50
+ if (!this.to) {
51
+ this.to = this.getScriptAddress();
52
+ }
53
+ const selectedRedeem = !!this.contractSigner
54
+ ? this.targetScriptRedeem
55
+ : this.leftOverFundsScriptRedeem;
56
+ if (!selectedRedeem) {
57
+ throw new Error('Left over funds script redeem is required');
58
+ }
59
+ if (!selectedRedeem.redeemVersion) {
60
+ throw new Error('Left over funds script redeem version is required');
61
+ }
62
+ if (!selectedRedeem.output) {
63
+ throw new Error('Left over funds script redeem output is required');
64
+ }
65
+ this.tapLeafScript = {
66
+ leafVersion: selectedRedeem.redeemVersion,
67
+ script: selectedRedeem.output,
68
+ controlBlock: this.getWitness(),
69
+ };
70
+ this.addInputsFromUTXO();
71
+ const amountSpent = this.getTransactionOPNetFee();
72
+ this.addOutput({
73
+ value: Number(amountSpent),
74
+ address: this.to,
75
+ });
76
+ await this.addRefundOutput(amountSpent);
77
+ }
78
+ async signInputs(transaction) {
79
+ if (!this.contractSigner) {
80
+ await super.signInputs(transaction);
81
+ return;
82
+ }
83
+ for (let i = 0; i < transaction.data.inputs.length; i++) {
84
+ if (i === 0) {
85
+ transaction.signInput(0, this.contractSigner);
86
+ transaction.signInput(0, this.getSignerKey());
87
+ transaction.finalizeInput(0, this.customFinalizer);
88
+ }
89
+ else {
90
+ transaction.signInput(i, this.getSignerKey());
91
+ transaction.finalizeInput(i);
92
+ }
93
+ }
94
+ }
95
+ generateScriptAddress() {
96
+ return {
97
+ internalPubkey: this.internalPubKeyToXOnly(),
98
+ network: this.network,
99
+ scriptTree: this.scriptTree,
100
+ };
101
+ }
102
+ generateTapData() {
103
+ const selectedRedeem = !!this.contractSigner
104
+ ? this.targetScriptRedeem
105
+ : this.leftOverFundsScriptRedeem;
106
+ if (!selectedRedeem) {
107
+ throw new Error('Left over funds script redeem is required');
108
+ }
109
+ if (!this.scriptTree) {
110
+ throw new Error('Script tree is required');
111
+ }
112
+ return {
113
+ internalPubkey: this.internalPubKeyToXOnly(),
114
+ network: this.network,
115
+ scriptTree: this.scriptTree,
116
+ redeem: selectedRedeem,
117
+ };
118
+ }
119
+ getContractSeed() {
120
+ if (!this.bytecode) {
121
+ throw new Error('Bytecode is required');
122
+ }
123
+ const deployerPubKey = this.internalPubKeyToXOnly();
124
+ const salt = bitCrypto.hash256(this.randomBytes);
125
+ const sha256OfBytecode = bitCrypto.hash256(this.bytecode);
126
+ const buf = Buffer.concat([deployerPubKey, salt, sha256OfBytecode]);
127
+ return bitCrypto.hash256(buf);
128
+ }
129
+ customFinalizer = (_inputIndex, input) => {
130
+ if (!this.tapLeafScript) {
131
+ throw new Error('Tap leaf script is required');
132
+ }
133
+ if (!input.tapScriptSig) {
134
+ throw new Error('Tap script signature is required');
135
+ }
136
+ const chunks = this.compiledTargetScript.chunks
137
+ .slice(0, this.compiledTargetScript.chunks.length)
138
+ .reverse();
139
+ const scriptSolution = [
140
+ ...chunks,
141
+ this.randomBytes,
142
+ this.internalPubKeyToXOnly(),
143
+ input.tapScriptSig[0].signature,
144
+ input.tapScriptSig[1].signature,
145
+ ];
146
+ console.log('length', scriptSolution.length);
147
+ const witness = scriptSolution
148
+ .concat(this.tapLeafScript.script)
149
+ .concat(this.tapLeafScript.controlBlock);
150
+ return {
151
+ finalScriptWitness: TransactionBuilder.witnessStackToScriptWitness(witness),
152
+ };
153
+ };
154
+ getPubKeys() {
155
+ const pubkeys = [this.signer.publicKey];
156
+ if (this.contractSigner) {
157
+ pubkeys.push(this.contractSigner.publicKey);
158
+ }
159
+ return pubkeys;
160
+ }
161
+ generateRedeemScripts() {
162
+ this.targetScriptRedeem = {
163
+ pubkeys: this.getPubKeys(),
164
+ output: this.compiledTargetScript.compiled,
165
+ redeemVersion: 192,
166
+ };
167
+ this.leftOverFundsScriptRedeem = {
168
+ pubkeys: this.getPubKeys(),
169
+ output: this.getLeafScript(),
170
+ redeemVersion: 192,
171
+ };
172
+ }
173
+ getLeafScript() {
174
+ return TransactionBuilder.LOCK_LEAF_SCRIPT;
175
+ }
176
+ getScriptTree() {
177
+ if (!this.bytecode) {
178
+ throw new Error('Contract bytecode is required');
179
+ }
180
+ this.generateRedeemScripts();
181
+ return [
182
+ {
183
+ output: this.compiledTargetScript.compiled,
184
+ version: 192,
185
+ },
186
+ {
187
+ output: this.getLeafScript(),
188
+ version: 192,
189
+ },
190
+ ];
191
+ }
192
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "module",
3
- "version": "1.0.92",
3
+ "version": "1.0.94",
4
4
  "author": "BlobMaster41",
5
5
  "description": "OPNet transaction library allows you to create and sign transactions for the OPNet network.",
6
6
  "engines": {
@@ -60,7 +60,8 @@
60
60
  "browserBuild": "webpack --mode production",
61
61
  "cjs": "gulp cjs",
62
62
  "docs": "typedoc --out docs --exclude 'src/tests/*.ts' --tsconfig tsconfig.json --readme README.md --name OPNet --plugin typedoc-material-theme --themeColor '#cb9820' --exclude src/tests/test.ts --exclude src/index.ts src",
63
- "postinstall": "gulp && gulp cjs"
63
+ "postinstall": "gulp && gulp cjs",
64
+ "build:dev": "gulp cjs && gulp && npm run browserBuild"
64
65
  },
65
66
  "devDependencies": {
66
67
  "@babel/plugin-proposal-class-properties": "^7.18.6",
@@ -107,7 +108,6 @@
107
108
  "gulp-logger": "^0.0.2",
108
109
  "gulp-typescript": "^6.0.0-alpha.1",
109
110
  "gulplog": "^2.2.0",
110
- "process": "^0.11.10",
111
111
  "ts-loader": "^9.5.1",
112
112
  "ts-node": "^10.9.2"
113
113
  }
package/src/_version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.0.92';
1
+ export const version = '1.0.94';
@@ -1,75 +1,75 @@
1
- import { Network, networks } from 'bitcoinjs-lib';
2
-
3
- /** Bitcoin Script Generator */
4
- export abstract class Generator {
5
- /**
6
- * The maximum size of a data chunk
7
- */
8
- public static readonly DATA_CHUNK_SIZE: number = 512;
9
-
10
- /**
11
- * The magic number of OPNet
12
- */
13
- public static readonly MAGIC: Buffer = Buffer.from('bsi', 'utf-8');
14
-
15
- /**
16
- * The public key of the sender
17
- * @protected
18
- */
19
- protected readonly senderPubKey: Buffer;
20
-
21
- /**
22
- * The public key of the contract salt
23
- * @protected
24
- */
25
- protected readonly contractSaltPubKey: Buffer;
26
-
27
- /**
28
- * The network to use
29
- * @protected
30
- */
31
- protected readonly network: Network = networks.bitcoin;
32
-
33
- protected constructor(
34
- senderPubKey: Buffer,
35
- contractSaltPubKey: Buffer,
36
- network: Network = networks.bitcoin,
37
- ) {
38
- this.senderPubKey = senderPubKey;
39
- this.contractSaltPubKey = contractSaltPubKey;
40
- this.network = network;
41
- }
42
-
43
- /**
44
- * Compile the script
45
- * @param args - The arguments to use when compiling the script
46
- * @returns {Buffer} - The compiled script
47
- */
48
- public abstract compile(...args: unknown[]): Buffer;
49
-
50
- /**
51
- * Split a buffer into chunks
52
- * @param {Buffer} buffer - The buffer to split
53
- * @param {number} chunkSize - The size of each chunk
54
- * @protected
55
- * @returns {Array<Buffer[]>} - The chunks
56
- */
57
- protected splitBufferIntoChunks(
58
- buffer: Buffer,
59
- chunkSize: number = Generator.DATA_CHUNK_SIZE,
60
- ): Array<Buffer[]> {
61
- const chunks: Array<Buffer[]> = [];
62
- for (let i = 0; i < buffer.length; i += chunkSize) {
63
- const dataLength = Math.min(chunkSize, buffer.length - i);
64
-
65
- const buf2 = Buffer.alloc(dataLength);
66
- for (let j = 0; j < dataLength; j++) {
67
- buf2.writeUInt8(buffer[i + j], j);
68
- }
69
-
70
- chunks.push([buf2]);
71
- }
72
-
73
- return chunks;
74
- }
75
- }
1
+ import { Network, networks } from 'bitcoinjs-lib';
2
+
3
+ /** Bitcoin Script Generator */
4
+ export abstract class Generator {
5
+ /**
6
+ * The maximum size of a data chunk
7
+ */
8
+ public static readonly DATA_CHUNK_SIZE: number = 512;
9
+
10
+ /**
11
+ * The magic number of OPNet
12
+ */
13
+ public static readonly MAGIC: Buffer = Buffer.from('bsi', 'utf-8');
14
+
15
+ /**
16
+ * The public key of the sender
17
+ * @protected
18
+ */
19
+ protected readonly senderPubKey: Buffer;
20
+
21
+ /**
22
+ * The public key of the contract salt
23
+ * @protected
24
+ */
25
+ protected readonly contractSaltPubKey: Buffer;
26
+
27
+ /**
28
+ * The network to use
29
+ * @protected
30
+ */
31
+ protected readonly network: Network = networks.bitcoin;
32
+
33
+ protected constructor(
34
+ senderPubKey: Buffer,
35
+ contractSaltPubKey: Buffer,
36
+ network: Network = networks.bitcoin,
37
+ ) {
38
+ this.senderPubKey = senderPubKey;
39
+ this.contractSaltPubKey = contractSaltPubKey;
40
+ this.network = network;
41
+ }
42
+
43
+ /**
44
+ * Compile the script
45
+ * @param args - The arguments to use when compiling the script
46
+ * @returns {Buffer} - The compiled script
47
+ */
48
+ public abstract compile(...args: unknown[]): Buffer;
49
+
50
+ /**
51
+ * Split a buffer into chunks
52
+ * @param {Buffer} buffer - The buffer to split
53
+ * @param {number} chunkSize - The size of each chunk
54
+ * @protected
55
+ * @returns {Array<Buffer[]>} - The chunks
56
+ */
57
+ protected splitBufferIntoChunks(
58
+ buffer: Buffer,
59
+ chunkSize: number = Generator.DATA_CHUNK_SIZE,
60
+ ): Array<Buffer[]> {
61
+ const chunks: Array<Buffer[]> = [];
62
+ for (let i = 0; i < buffer.length; i += chunkSize) {
63
+ const dataLength = Math.min(chunkSize, buffer.length - i);
64
+
65
+ const buf2 = Buffer.alloc(dataLength);
66
+ for (let j = 0; j < dataLength; j++) {
67
+ buf2.writeUInt8(buffer[i + j], j);
68
+ }
69
+
70
+ chunks.push([buf2]);
71
+ }
72
+
73
+ return chunks;
74
+ }
75
+ }