@btc-vision/transaction 1.0.93 → 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.
- package/browser/_version.d.ts +1 -1
- package/browser/index.js +1 -1
- package/browser/transaction/browser/Web3Provider.d.ts +8 -1
- package/browser/transaction/browser/extensions/UnisatSigner.d.ts +1 -0
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/generators/builders/DeploymentGeneratorV2.d.ts +13 -0
- package/build/generators/builders/DeploymentGeneratorV2.js +57 -0
- package/build/transaction/browser/Web3Provider.d.ts +8 -1
- package/build/transaction/browser/extensions/UnisatSigner.d.ts +1 -0
- package/build/transaction/browser/extensions/UnisatSigner.js +1 -1
- package/build/transaction/builders/DeploymentTransactionV2.d.ts +36 -0
- package/build/transaction/builders/DeploymentTransactionV2.js +192 -0
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/generators/Generator.ts +75 -75
- package/src/transaction/TransactionFactory.ts +544 -544
- package/src/transaction/browser/Web3Provider.ts +17 -2
- package/src/transaction/browser/extensions/UnisatSigner.ts +2 -1
|
@@ -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
|
}
|
package/build/_version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "1.0.
|
|
1
|
+
export declare const version = "1.0.94";
|
package/build/_version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.0.
|
|
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
|
}
|
|
@@ -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(
|
|
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');
|
|
@@ -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
package/src/_version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.0.
|
|
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
|
+
}
|