@btc-vision/transaction 1.0.99 → 1.0.101
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/generators/Generator.d.ts +2 -2
- package/browser/generators/builders/CustomGenerator.d.ts +6 -0
- package/browser/index.js +1 -1
- package/browser/opnet.d.ts +5 -3
- package/browser/transaction/TransactionFactory.d.ts +2 -0
- package/browser/transaction/builders/CustomScriptTransaction.d.ts +40 -0
- package/browser/transaction/enums/TransactionType.d.ts +2 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/generators/Generator.d.ts +2 -2
- package/build/generators/builders/CalldataGenerator.js +2 -0
- package/build/generators/builders/CustomGenerator.d.ts +6 -0
- package/build/generators/builders/CustomGenerator.js +16 -0
- package/build/generators/builders/DeploymentGenerator.js +2 -0
- package/build/metadata/tokens.js +5 -5
- package/build/opnet.d.ts +5 -3
- package/build/opnet.js +5 -3
- package/build/transaction/TransactionFactory.d.ts +2 -0
- package/build/transaction/TransactionFactory.js +42 -3
- package/build/transaction/builders/CustomScriptTransaction.d.ts +40 -0
- package/build/transaction/builders/CustomScriptTransaction.js +165 -0
- package/build/transaction/enums/TransactionType.d.ts +2 -1
- package/build/transaction/enums/TransactionType.js +1 -0
- package/eslint.config.js +30 -0
- package/package.json +10 -9
- package/src/_version.ts +1 -1
- package/src/generators/Generator.ts +2 -2
- package/src/generators/builders/CalldataGenerator.ts +2 -0
- package/src/generators/builders/CustomGenerator.ts +30 -0
- package/src/generators/builders/DeploymentGenerator.ts +2 -0
- package/src/metadata/tokens.ts +5 -5
- package/src/opnet.ts +5 -5
- package/src/transaction/TransactionFactory.ts +72 -14
- package/src/transaction/builders/CustomScriptTransaction.ts +337 -0
- package/src/transaction/enums/TransactionType.ts +1 -0
- package/docs/.nojekyll +0 -1
- package/docs/assets/highlight.css +0 -43
- package/docs/assets/icons.js +0 -15
- package/docs/assets/icons.svg +0 -1
- package/docs/assets/main.js +0 -59
- package/docs/assets/material-style.css +0 -247
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1412
- package/docs/classes/AddressGenerator.html +0 -177
- package/docs/classes/AddressVerificator.html +0 -177
- package/docs/classes/BitcoinUtils.html +0 -196
- package/docs/classes/CalldataGenerator.html +0 -213
- package/docs/classes/Compressor.html +0 -185
- package/docs/classes/ContractBaseMetadata.html +0 -182
- package/docs/classes/CustomKeypair.html +0 -189
- package/docs/classes/DeploymentGenerator.html +0 -201
- package/docs/classes/DeploymentTransaction.html +0 -465
- package/docs/classes/EcKeyPair.html +0 -280
- package/docs/classes/FundingTransaction.html +0 -425
- package/docs/classes/Generator.html +0 -199
- package/docs/classes/InteractionTransaction.html +0 -467
- package/docs/classes/MultiSignGenerator.html +0 -178
- package/docs/classes/MultiSignTransaction.html +0 -490
- package/docs/classes/OPNetLimitedProvider.html +0 -225
- package/docs/classes/OPNetTokenAddressManager.html +0 -182
- package/docs/classes/P2TR_MS.html +0 -186
- package/docs/classes/PsbtTransaction.html +0 -320
- package/docs/classes/SharedInteractionTransaction.html +0 -477
- package/docs/classes/TapscriptVerificator.html +0 -180
- package/docs/classes/TransactionBuilder.html +0 -423
- package/docs/classes/TransactionFactory.html +0 -230
- package/docs/classes/TweakedSigner.html +0 -181
- package/docs/classes/TweakedTransaction.html +0 -301
- package/docs/classes/UnisatSigner.html +0 -199
- package/docs/classes/UnwrapGeneration.html +0 -177
- package/docs/classes/UnwrapTransaction.html +0 -518
- package/docs/classes/Wallet.html +0 -204
- package/docs/classes/WrapTransaction.html +0 -509
- package/docs/classes/WrappedGeneration.html +0 -187
- package/docs/classes/wBTC.html +0 -190
- package/docs/enums/ChainId.html +0 -176
- package/docs/enums/Consensus.html +0 -204
- package/docs/enums/Features.html +0 -175
- package/docs/enums/MessageType.html +0 -176
- package/docs/enums/OPNetNetwork.html +0 -177
- package/docs/enums/PSBTTypes.html +0 -175
- package/docs/enums/TransactionSequence.html +0 -177
- package/docs/enums/TransactionType.html +0 -181
- package/docs/enums/UnisatChainType.html +0 -181
- package/docs/enums/UnisatNetwork.html +0 -177
- package/docs/hierarchy.html +0 -174
- package/docs/index.html +0 -215
- package/docs/interfaces/Balance.html +0 -177
- package/docs/interfaces/BitcoinTransferResponse.html +0 -178
- package/docs/interfaces/BroadcastResponse.html +0 -181
- package/docs/interfaces/BroadcastTransactionOptions.html +0 -176
- package/docs/interfaces/BroadcastedTransaction.html +0 -184
- package/docs/interfaces/ConsensusConfig.html +0 -182
- package/docs/interfaces/ContractAddressVerificationParams.html +0 -179
- package/docs/interfaces/DeploymentResult.html +0 -178
- package/docs/interfaces/FetchUTXOParams.html +0 -178
- package/docs/interfaces/FetchUTXOParamsMultiAddress.html +0 -178
- package/docs/interfaces/FundingTransactionResponse.html +0 -178
- package/docs/interfaces/GenerationConstraints.html +0 -182
- package/docs/interfaces/IDeploymentParameters.html +0 -186
- package/docs/interfaces/IFundingTransactionParameters.html +0 -186
- package/docs/interfaces/IInteractionParameters.html +0 -187
- package/docs/interfaces/ITransactionParameters.html +0 -184
- package/docs/interfaces/ITweakedTransactionData.html +0 -178
- package/docs/interfaces/IUnwrapParameters.html +0 -189
- package/docs/interfaces/IWBTCUTXODocument.html +0 -180
- package/docs/interfaces/IWallet.html +0 -181
- package/docs/interfaces/IWrapParameters.html +0 -190
- package/docs/interfaces/MultiSignFromBase64Params.html +0 -188
- package/docs/interfaces/MultiSignParameters.html +0 -188
- package/docs/interfaces/OPNetTokenMetadata.html +0 -179
- package/docs/interfaces/PsbtInputExtended.html +0 -194
- package/docs/interfaces/PsbtOutputExtendedAddress.html +0 -183
- package/docs/interfaces/PsbtOutputExtendedScript.html +0 -183
- package/docs/interfaces/PsbtSignatureOptions.html +0 -176
- package/docs/interfaces/PsbtTransactionData.html +0 -179
- package/docs/interfaces/RawUTXOResponse.html +0 -178
- package/docs/interfaces/SharedInteractionParameters.html +0 -187
- package/docs/interfaces/TapLeafScript.html +0 -177
- package/docs/interfaces/ToSignInputAddress.html +0 -178
- package/docs/interfaces/ToSignInputPublicKey.html +0 -178
- package/docs/interfaces/TweakSettings.html +0 -179
- package/docs/interfaces/UTXO.html +0 -178
- package/docs/interfaces/Unisat.html +0 -190
- package/docs/interfaces/UnisatChainInfo.html +0 -177
- package/docs/interfaces/UnwrapResult.html +0 -181
- package/docs/interfaces/UnwrappedGenerationParameters.html +0 -178
- package/docs/interfaces/UpdateInput.html +0 -175
- package/docs/interfaces/VaultUTXOs.html +0 -178
- package/docs/interfaces/Web3Provider.html +0 -180
- package/docs/interfaces/WrapResult.html +0 -179
- package/docs/interfaces/WrappedGenerationParameters.html +0 -184
- package/docs/modules.html +0 -289
- package/docs/types/FromBase64Params.html +0 -174
- package/docs/types/IDeploymentParametersWithoutSigner.html +0 -174
- package/docs/types/IUnwrapParametersWithoutSigner.html +0 -174
- package/docs/types/IWrapParametersWithoutSigner.html +0 -174
- package/docs/types/InteractionParametersWithoutSigner.html +0 -174
- package/docs/types/PsbtOutputExtended.html +0 -174
- package/docs/types/ToSignInput.html +0 -174
- package/docs/variables/FACTORY_ADDRESS_FRACTAL.html +0 -174
- package/docs/variables/FACTORY_ADDRESS_REGTEST.html +0 -174
- package/docs/variables/FACTORY_ADDRESS_TESTNET.html +0 -174
- package/docs/variables/MOTO_ADDRESS_FRACTAL.html +0 -174
- package/docs/variables/MOTO_ADDRESS_REGTEST.html +0 -174
- package/docs/variables/MOTO_ADDRESS_TESTNET.html +0 -174
- package/docs/variables/OPNetConsensusConfig.html +0 -174
- package/docs/variables/OPNetMetadata.html +0 -174
- package/docs/variables/POOL_ADDRESS_FRACTAL.html +0 -174
- package/docs/variables/POOL_ADDRESS_REGTEST.html +0 -174
- package/docs/variables/POOL_ADDRESS_TESTNET.html +0 -174
- package/docs/variables/ROUTER_ADDRESS_FRACTAL.html +0 -174
- package/docs/variables/ROUTER_ADDRESS_REGTEST.html +0 -174
- package/docs/variables/ROUTER_ADDRESS_TESTNET.html +0 -174
- package/docs/variables/RoswellConsensus.html +0 -174
- package/docs/variables/WBTC_ADDRESS_FRACTAL.html +0 -174
- package/docs/variables/WBTC_ADDRESS_REGTEST.html +0 -174
- package/docs/variables/WBTC_ADDRESS_TESTNET.html +0 -174
- package/docs/variables/currentConsensus.html +0 -174
- package/docs/variables/currentConsensusConfig.html +0 -174
- package/docs/variables/version.html +0 -174
|
@@ -22,7 +22,7 @@ export abstract class Generator {
|
|
|
22
22
|
* The public key of the contract salt
|
|
23
23
|
* @protected
|
|
24
24
|
*/
|
|
25
|
-
protected readonly contractSaltPubKey
|
|
25
|
+
protected readonly contractSaltPubKey?: Buffer;
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* The network to use
|
|
@@ -32,7 +32,7 @@ export abstract class Generator {
|
|
|
32
32
|
|
|
33
33
|
protected constructor(
|
|
34
34
|
senderPubKey: Buffer,
|
|
35
|
-
contractSaltPubKey
|
|
35
|
+
contractSaltPubKey?: Buffer,
|
|
36
36
|
network: Network = networks.bitcoin,
|
|
37
37
|
) {
|
|
38
38
|
this.senderPubKey = senderPubKey;
|
|
@@ -69,6 +69,8 @@ export class CalldataGenerator extends Generator {
|
|
|
69
69
|
vaultPublicKeys: Buffer[] = [],
|
|
70
70
|
minimumSignatures: number = 0,
|
|
71
71
|
): Buffer {
|
|
72
|
+
if (!this.contractSaltPubKey) throw new Error('Contract salt public key not set');
|
|
73
|
+
|
|
72
74
|
const dataChunks: Buffer[][] = this.splitBufferIntoChunks(calldata);
|
|
73
75
|
if (!dataChunks.length) throw new Error('No data chunks found');
|
|
74
76
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Network, networks, script, Stack } from 'bitcoinjs-lib';
|
|
2
|
+
import { Generator } from '../Generator.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Class to generate bitcoin script for interaction transactions
|
|
6
|
+
*/
|
|
7
|
+
export class CustomGenerator extends Generator {
|
|
8
|
+
constructor(senderPubKey: Buffer, network: Network = networks.bitcoin) {
|
|
9
|
+
super(senderPubKey, undefined, network);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Compile an interaction bitcoin script
|
|
14
|
+
* @param compiledData - The compiled data
|
|
15
|
+
* @returns {Buffer} - The compiled script
|
|
16
|
+
* @throws {Error} - If something goes wrong
|
|
17
|
+
*/
|
|
18
|
+
public compile(compiledData: (Buffer | Stack)[]): Buffer {
|
|
19
|
+
const asm = compiledData.flat();
|
|
20
|
+
const compiled = script.compile(asm);
|
|
21
|
+
|
|
22
|
+
/** Verify the validity of the script */
|
|
23
|
+
const decompiled = script.decompile(compiled);
|
|
24
|
+
if (!decompiled) {
|
|
25
|
+
throw new Error('Failed to decompile script??');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return compiled;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -32,6 +32,8 @@ export class DeploymentGenerator extends Generator {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
private getAsm(contractBytecode: Buffer, contractSalt: Buffer): (number | Buffer)[] {
|
|
35
|
+
if (!this.contractSaltPubKey) throw new Error('Contract salt public key not set');
|
|
36
|
+
|
|
35
37
|
const dataChunks = this.splitBufferIntoChunks(contractBytecode);
|
|
36
38
|
|
|
37
39
|
return [
|
package/src/metadata/tokens.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { Address } from '@btc-vision/bsi-binary';
|
|
|
2
2
|
import { ChainId } from '../network/ChainId.js';
|
|
3
3
|
|
|
4
4
|
// Addresses Regtest
|
|
5
|
-
export const FACTORY_ADDRESS_REGTEST: Address = '
|
|
6
|
-
export const POOL_ADDRESS_REGTEST: Address = '
|
|
7
|
-
export const WBTC_ADDRESS_REGTEST: Address = '
|
|
8
|
-
export const MOTO_ADDRESS_REGTEST: Address = '
|
|
9
|
-
export const ROUTER_ADDRESS_REGTEST: Address = '
|
|
5
|
+
export const FACTORY_ADDRESS_REGTEST: Address = 'bcrt1q9pf9fnpch9z2qrp5e3dgr2avzu3mypq3km2k40';
|
|
6
|
+
export const POOL_ADDRESS_REGTEST: Address = 'bcrt1qg87nx9v9ln3qyadcn0llekzjn0hx8js46ztwky';
|
|
7
|
+
export const WBTC_ADDRESS_REGTEST: Address = 'bcrt1qy44f5630m4ap4mvmgqc44qh4vndaees9y30t0m';
|
|
8
|
+
export const MOTO_ADDRESS_REGTEST: Address = 'bcrt1q5txqpm5sy0s2xsprvce4ddj0088nlq8lazkd6n';
|
|
9
|
+
export const ROUTER_ADDRESS_REGTEST: Address = 'bcrt1q9yd6mk324k0q4krmlxjky0pk65ul6hkf4u35e6';
|
|
10
10
|
|
|
11
11
|
// Addresses Testnet
|
|
12
12
|
export const FACTORY_ADDRESS_TESTNET: Address = 'tb1qgev5kldhp5zvg6j8t9vl6x4phkrwn8nk9felxh';
|
package/src/opnet.ts
CHANGED
|
@@ -7,6 +7,8 @@ export * from './bytecode/Compressor.js';
|
|
|
7
7
|
export * from './generators/Generator.js';
|
|
8
8
|
export * from './generators/builders/CalldataGenerator.js';
|
|
9
9
|
export * from './generators/builders/DeploymentGenerator.js';
|
|
10
|
+
export * from './generators/builders/CustomGenerator.js';
|
|
11
|
+
export * from './generators/builders/MultiSignGenerator.js';
|
|
10
12
|
export * from './generators/Features.js';
|
|
11
13
|
|
|
12
14
|
/** Address */
|
|
@@ -39,6 +41,9 @@ export * from './transaction/builders/TransactionBuilder.js';
|
|
|
39
41
|
export * from './transaction/builders/WrapTransaction.js';
|
|
40
42
|
export * from './transaction/builders/SharedInteractionTransaction.js';
|
|
41
43
|
export * from './transaction/builders/DeploymentTransaction.js';
|
|
44
|
+
export * from './transaction/builders/UnwrapTransaction.js';
|
|
45
|
+
export * from './transaction/builders/CustomScriptTransaction.js';
|
|
46
|
+
export * from './transaction/builders/MultiSignTransaction.js';
|
|
42
47
|
|
|
43
48
|
/** wBTC */
|
|
44
49
|
export * from './wbtc/WrappedGenerationParameters.js';
|
|
@@ -60,12 +65,7 @@ export * from './transaction/shared/TweakedTransaction.js';
|
|
|
60
65
|
export * from './utxo/interfaces/BroadcastResponse.js';
|
|
61
66
|
export * from './transaction/psbt/PSBTTypes.js';
|
|
62
67
|
|
|
63
|
-
export * from './transaction/builders/MultiSignTransaction.js';
|
|
64
|
-
export * from './generators/builders/MultiSignGenerator.js';
|
|
65
|
-
|
|
66
68
|
export * from './transaction/shared/P2TR_MS.js';
|
|
67
|
-
export * from './transaction/builders/UnwrapTransaction.js';
|
|
68
|
-
|
|
69
69
|
export * from './wbtc/UnwrapGeneration.js';
|
|
70
70
|
|
|
71
71
|
/** Consensus */
|
|
@@ -21,6 +21,10 @@ import { UnwrapTransaction } from './builders/UnwrapTransaction.js';
|
|
|
21
21
|
import { currentConsensus, currentConsensusConfig } from '../consensus/ConsensusConfig.js';
|
|
22
22
|
import { TransactionBuilder } from './builders/TransactionBuilder.js';
|
|
23
23
|
import { TransactionType } from './enums/TransactionType.js';
|
|
24
|
+
import {
|
|
25
|
+
CustomScriptTransaction,
|
|
26
|
+
ICustomTransactionParameters,
|
|
27
|
+
} from './builders/CustomScriptTransaction.js';
|
|
24
28
|
|
|
25
29
|
export interface DeploymentResult {
|
|
26
30
|
readonly transaction: [string, string];
|
|
@@ -71,6 +75,74 @@ export interface UnwrapResult {
|
|
|
71
75
|
export class TransactionFactory {
|
|
72
76
|
constructor() {}
|
|
73
77
|
|
|
78
|
+
/**
|
|
79
|
+
* @description Generate a transaction with a custom script.
|
|
80
|
+
* @returns {Promise<[string, string]>} - The signed transaction
|
|
81
|
+
*/
|
|
82
|
+
public async createCustomScriptTransaction(
|
|
83
|
+
interactionParameters: ICustomTransactionParameters,
|
|
84
|
+
): Promise<[string, string, UTXO[]]> {
|
|
85
|
+
if (!interactionParameters.to) {
|
|
86
|
+
throw new Error('Field "to" not provided.');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!interactionParameters.from) {
|
|
90
|
+
throw new Error('Field "from" not provided.');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const preTransaction: CustomScriptTransaction = new CustomScriptTransaction({
|
|
94
|
+
...interactionParameters,
|
|
95
|
+
utxos: [interactionParameters.utxos[0]], // we simulate one input here.
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// we don't sign that transaction, we just need the parameters.
|
|
99
|
+
|
|
100
|
+
await preTransaction.generateTransactionMinimalSignatures();
|
|
101
|
+
|
|
102
|
+
const parameters: IFundingTransactionParameters =
|
|
103
|
+
await preTransaction.getFundingTransactionParameters();
|
|
104
|
+
|
|
105
|
+
parameters.utxos = interactionParameters.utxos;
|
|
106
|
+
parameters.amount =
|
|
107
|
+
(await preTransaction.estimateTransactionFees()) + interactionParameters.priorityFee;
|
|
108
|
+
|
|
109
|
+
const feeEstimationFundingTransaction = await this.createFundTransaction({ ...parameters });
|
|
110
|
+
if (!feeEstimationFundingTransaction) {
|
|
111
|
+
throw new Error('Could not sign funding transaction.');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
parameters.estimatedFees = feeEstimationFundingTransaction.estimatedFees;
|
|
115
|
+
|
|
116
|
+
const signedTransaction = await this.createFundTransaction(parameters);
|
|
117
|
+
if (!signedTransaction) {
|
|
118
|
+
throw new Error('Could not sign funding transaction.');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interactionParameters.utxos = this.getUTXOAsTransaction(
|
|
122
|
+
signedTransaction.tx,
|
|
123
|
+
interactionParameters.to,
|
|
124
|
+
0,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const newParams: ICustomTransactionParameters = {
|
|
128
|
+
...interactionParameters,
|
|
129
|
+
utxos: this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.to, 0), // always 0
|
|
130
|
+
randomBytes: preTransaction.getRndBytes(),
|
|
131
|
+
nonWitnessUtxo: signedTransaction.tx.toBuffer(),
|
|
132
|
+
estimatedFees: preTransaction.estimatedFees,
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const finalTransaction: CustomScriptTransaction = new CustomScriptTransaction(newParams);
|
|
136
|
+
|
|
137
|
+
// We have to regenerate using the new utxo
|
|
138
|
+
const outTx: Transaction = await finalTransaction.signTransaction();
|
|
139
|
+
return [
|
|
140
|
+
signedTransaction.tx.toHex(),
|
|
141
|
+
outTx.toHex(),
|
|
142
|
+
this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.from, 1), // always 1
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
|
|
74
146
|
/**
|
|
75
147
|
* @description Generates the required transactions.
|
|
76
148
|
* @returns {Promise<[string, string]>} - The signed transaction
|
|
@@ -132,7 +204,6 @@ export class TransactionFactory {
|
|
|
132
204
|
|
|
133
205
|
// We have to regenerate using the new utxo
|
|
134
206
|
const outTx: Transaction = await finalTransaction.signTransaction();
|
|
135
|
-
|
|
136
207
|
return [
|
|
137
208
|
signedTransaction.tx.toHex(),
|
|
138
209
|
outTx.toHex(),
|
|
@@ -243,8 +314,6 @@ export class TransactionFactory {
|
|
|
243
314
|
const parameters: IFundingTransactionParameters =
|
|
244
315
|
await preTransaction.getFundingTransactionParameters();
|
|
245
316
|
|
|
246
|
-
console.log('wrap parameters', parameters);
|
|
247
|
-
|
|
248
317
|
// We add the amount
|
|
249
318
|
parameters.amount += childTransactionRequiredValue;
|
|
250
319
|
parameters.utxos = fundingParameters.utxos;
|
|
@@ -300,15 +369,6 @@ export class TransactionFactory {
|
|
|
300
369
|
this.maxPubKeySize(unwrapParameters.unwrapUTXOs),
|
|
301
370
|
);
|
|
302
371
|
|
|
303
|
-
console.log(
|
|
304
|
-
'estimatedFees',
|
|
305
|
-
estimatedFees,
|
|
306
|
-
'estimatedGas',
|
|
307
|
-
estimatedGas,
|
|
308
|
-
'priority',
|
|
309
|
-
unwrapParameters.priorityFee,
|
|
310
|
-
);
|
|
311
|
-
|
|
312
372
|
const fundingParameters: IFundingTransactionParameters = {
|
|
313
373
|
...unwrapParameters,
|
|
314
374
|
amount: estimatedGas + estimatedFees,
|
|
@@ -402,8 +462,6 @@ export class TransactionFactory {
|
|
|
402
462
|
parameters.amount =
|
|
403
463
|
(await preTransaction.estimateTransactionFees()) + unwrapParameters.priorityFee;
|
|
404
464
|
|
|
405
|
-
console.log('parameters', parameters);
|
|
406
|
-
|
|
407
465
|
const signedTransaction = await this.createFundTransaction(parameters);
|
|
408
466
|
if (!signedTransaction) {
|
|
409
467
|
throw new Error('Could not sign funding transaction.');
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { Taptree } from 'bitcoinjs-lib/src/types.js';
|
|
2
|
+
import { TransactionType } from '../enums/TransactionType.js';
|
|
3
|
+
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
4
|
+
import { SharedInteractionParameters } from '../interfaces/ITransactionParameters.js';
|
|
5
|
+
import { Address } from '@btc-vision/bsi-binary';
|
|
6
|
+
import { crypto as bitCrypto, Payment, Psbt, Signer, Stack } from 'bitcoinjs-lib';
|
|
7
|
+
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
8
|
+
import { CustomGenerator } from '../../generators/builders/CustomGenerator.js';
|
|
9
|
+
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
10
|
+
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
11
|
+
import { AddressGenerator } from '../../generators/AddressGenerator.js';
|
|
12
|
+
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
13
|
+
import { PsbtInput } from 'bip174/src/lib/interfaces.js';
|
|
14
|
+
|
|
15
|
+
export interface ICustomTransactionParameters extends SharedInteractionParameters {
|
|
16
|
+
readonly script: (Buffer | Stack)[];
|
|
17
|
+
readonly witnesses: Buffer[];
|
|
18
|
+
|
|
19
|
+
readonly to: Address;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Class for interaction transactions
|
|
24
|
+
* @class CustomScriptTransaction
|
|
25
|
+
*/
|
|
26
|
+
export class CustomScriptTransaction extends TransactionBuilder<TransactionType.CUSTOM_CODE> {
|
|
27
|
+
public type: TransactionType.CUSTOM_CODE = TransactionType.CUSTOM_CODE;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The contract address
|
|
31
|
+
* @protected
|
|
32
|
+
*/
|
|
33
|
+
protected readonly _scriptAddress: Address;
|
|
34
|
+
/**
|
|
35
|
+
* The tap leaf script
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
protected tapLeafScript: TapLeafScript | null = null;
|
|
39
|
+
/**
|
|
40
|
+
* The target script redeem
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
private targetScriptRedeem: Payment | null = null;
|
|
44
|
+
/**
|
|
45
|
+
* The left over funds script redeem
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
private leftOverFundsScriptRedeem: Payment | null = null;
|
|
49
|
+
/**
|
|
50
|
+
* The compiled target script
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
private readonly compiledTargetScript: Buffer;
|
|
54
|
+
/**
|
|
55
|
+
* The script tree
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
private readonly scriptTree: Taptree;
|
|
59
|
+
/**
|
|
60
|
+
* The deployment bitcoin generator
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
private generator: CustomGenerator;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The contract seed
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
private readonly scriptSeed: Buffer;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The contract signer
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
private readonly contractSigner: Signer;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The contract salt random bytes
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
private readonly randomBytes: Buffer;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The witnesses
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
private readonly witnesses: Buffer[];
|
|
88
|
+
|
|
89
|
+
public constructor(parameters: ICustomTransactionParameters) {
|
|
90
|
+
super(parameters);
|
|
91
|
+
|
|
92
|
+
if (!parameters.script) throw new Error('Bitcoin script is required');
|
|
93
|
+
if (!parameters.witnesses) throw new Error('Witness(es) are required');
|
|
94
|
+
|
|
95
|
+
this.witnesses = parameters.witnesses;
|
|
96
|
+
this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
|
|
97
|
+
|
|
98
|
+
this.scriptSeed = this.getContractSeed();
|
|
99
|
+
this.contractSigner = EcKeyPair.fromSeedKeyPair(this.scriptSeed, this.network);
|
|
100
|
+
|
|
101
|
+
this.generator = new CustomGenerator(this.internalPubKeyToXOnly(), this.network);
|
|
102
|
+
|
|
103
|
+
this.compiledTargetScript = this.generator.compile(parameters.script);
|
|
104
|
+
|
|
105
|
+
this.scriptTree = this.getScriptTree();
|
|
106
|
+
|
|
107
|
+
this.internalInit();
|
|
108
|
+
|
|
109
|
+
this._scriptAddress = AddressGenerator.generatePKSH(this.scriptSeed, this.network);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @description Get the contract address (PKSH)
|
|
114
|
+
*/
|
|
115
|
+
public get scriptAddress(): Address {
|
|
116
|
+
return this._scriptAddress;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @description Get the P2TR address
|
|
121
|
+
*/
|
|
122
|
+
public get p2trAddress(): Address {
|
|
123
|
+
return this.to || this.getScriptAddress();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get the random bytes used for the interaction
|
|
128
|
+
* @returns {Buffer} The random bytes
|
|
129
|
+
*/
|
|
130
|
+
public getRndBytes(): Buffer {
|
|
131
|
+
return this.randomBytes;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get the contract signer public key
|
|
136
|
+
* @protected
|
|
137
|
+
*/
|
|
138
|
+
protected contractSignerXOnlyPubKey(): Buffer {
|
|
139
|
+
return toXOnly(this.contractSigner.publicKey);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Build the transaction
|
|
144
|
+
* @protected
|
|
145
|
+
*/
|
|
146
|
+
protected override async buildTransaction(): Promise<void> {
|
|
147
|
+
if (!this.to) {
|
|
148
|
+
this.to = this.getScriptAddress();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const selectedRedeem = !!this.contractSigner
|
|
152
|
+
? this.targetScriptRedeem
|
|
153
|
+
: this.leftOverFundsScriptRedeem;
|
|
154
|
+
|
|
155
|
+
if (!selectedRedeem) {
|
|
156
|
+
throw new Error('Left over funds script redeem is required');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!selectedRedeem.redeemVersion) {
|
|
160
|
+
throw new Error('Left over funds script redeem version is required');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!selectedRedeem.output) {
|
|
164
|
+
throw new Error('Left over funds script redeem output is required');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.tapLeafScript = {
|
|
168
|
+
leafVersion: selectedRedeem.redeemVersion,
|
|
169
|
+
script: selectedRedeem.output,
|
|
170
|
+
controlBlock: this.getWitness(),
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
this.addInputsFromUTXO();
|
|
174
|
+
|
|
175
|
+
const amountSpent: bigint = this.getTransactionOPNetFee();
|
|
176
|
+
this.addOutput({
|
|
177
|
+
value: Number(amountSpent),
|
|
178
|
+
address: this.to,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
await this.addRefundOutput(amountSpent);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Sign the inputs
|
|
186
|
+
* @param {Psbt} transaction The transaction to sign
|
|
187
|
+
* @protected
|
|
188
|
+
*/
|
|
189
|
+
protected async signInputs(transaction: Psbt): Promise<void> {
|
|
190
|
+
if (!this.contractSigner) {
|
|
191
|
+
await super.signInputs(transaction);
|
|
192
|
+
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
for (let i = 0; i < transaction.data.inputs.length; i++) {
|
|
197
|
+
if (i === 0) {
|
|
198
|
+
// multi sig input
|
|
199
|
+
transaction.signInput(0, this.contractSigner);
|
|
200
|
+
transaction.signInput(0, this.getSignerKey());
|
|
201
|
+
|
|
202
|
+
transaction.finalizeInput(0, this.customFinalizer);
|
|
203
|
+
} else {
|
|
204
|
+
transaction.signInput(i, this.getSignerKey());
|
|
205
|
+
transaction.finalizeInput(i);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Get the tap output
|
|
212
|
+
* @protected
|
|
213
|
+
*/
|
|
214
|
+
protected override generateScriptAddress(): Payment {
|
|
215
|
+
return {
|
|
216
|
+
internalPubkey: this.internalPubKeyToXOnly(),
|
|
217
|
+
network: this.network,
|
|
218
|
+
scriptTree: this.scriptTree,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Generate the tap data
|
|
224
|
+
* @protected
|
|
225
|
+
*/
|
|
226
|
+
protected override generateTapData(): Payment {
|
|
227
|
+
const selectedRedeem = !!this.contractSigner
|
|
228
|
+
? this.targetScriptRedeem
|
|
229
|
+
: this.leftOverFundsScriptRedeem;
|
|
230
|
+
|
|
231
|
+
if (!selectedRedeem) {
|
|
232
|
+
throw new Error('Left over funds script redeem is required');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (!this.scriptTree) {
|
|
236
|
+
throw new Error('Script tree is required');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
internalPubkey: this.internalPubKeyToXOnly(),
|
|
241
|
+
network: this.network,
|
|
242
|
+
scriptTree: this.scriptTree,
|
|
243
|
+
redeem: selectedRedeem,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Generate the contract seed for the deployment
|
|
249
|
+
* @private
|
|
250
|
+
*/
|
|
251
|
+
private getContractSeed(): Buffer {
|
|
252
|
+
return bitCrypto.hash256(this.randomBytes);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Finalize the transaction
|
|
257
|
+
* @param _inputIndex
|
|
258
|
+
* @param input
|
|
259
|
+
*/
|
|
260
|
+
private customFinalizer = (_inputIndex: number, input: PsbtInput) => {
|
|
261
|
+
if (!this.tapLeafScript) {
|
|
262
|
+
throw new Error('Tap leaf script is required');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!input.tapScriptSig) {
|
|
266
|
+
throw new Error('Tap script signature is required');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const scriptSolution = this.witnesses;
|
|
270
|
+
const witness = scriptSolution
|
|
271
|
+
.concat(this.tapLeafScript.script)
|
|
272
|
+
.concat(this.tapLeafScript.controlBlock);
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
finalScriptWitness: TransactionBuilder.witnessStackToScriptWitness(witness),
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Get the public keys for the redeem scripts
|
|
281
|
+
* @private
|
|
282
|
+
*/
|
|
283
|
+
private getPubKeys(): Buffer[] {
|
|
284
|
+
const pubkeys = [this.signer.publicKey];
|
|
285
|
+
|
|
286
|
+
if (this.contractSigner) {
|
|
287
|
+
pubkeys.push(this.contractSigner.publicKey);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return pubkeys;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Generate the redeem scripts
|
|
295
|
+
* @private
|
|
296
|
+
*/
|
|
297
|
+
private generateRedeemScripts(): void {
|
|
298
|
+
this.targetScriptRedeem = {
|
|
299
|
+
pubkeys: this.getPubKeys(),
|
|
300
|
+
output: this.compiledTargetScript,
|
|
301
|
+
redeemVersion: 192,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
this.leftOverFundsScriptRedeem = {
|
|
305
|
+
pubkeys: this.getPubKeys(),
|
|
306
|
+
output: this.getLeafScript(),
|
|
307
|
+
redeemVersion: 192,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Get the second leaf script
|
|
313
|
+
* @private
|
|
314
|
+
*/
|
|
315
|
+
private getLeafScript(): Buffer {
|
|
316
|
+
return TransactionBuilder.LOCK_LEAF_SCRIPT;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Get the script tree
|
|
321
|
+
* @private
|
|
322
|
+
*/
|
|
323
|
+
private getScriptTree(): Taptree {
|
|
324
|
+
this.generateRedeemScripts();
|
|
325
|
+
|
|
326
|
+
return [
|
|
327
|
+
{
|
|
328
|
+
output: this.compiledTargetScript,
|
|
329
|
+
version: 192,
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
output: this.getLeafScript(),
|
|
333
|
+
version: 192,
|
|
334
|
+
},
|
|
335
|
+
];
|
|
336
|
+
}
|
|
337
|
+
}
|
package/docs/.nojekyll
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
--light-hl-0: #795E26;
|
|
3
|
-
--dark-hl-0: #DCDCAA;
|
|
4
|
-
--light-hl-1: #000000;
|
|
5
|
-
--dark-hl-1: #D4D4D4;
|
|
6
|
-
--light-hl-2: #A31515;
|
|
7
|
-
--dark-hl-2: #CE9178;
|
|
8
|
-
--light-code-background: #FFFFFF;
|
|
9
|
-
--dark-code-background: #1E1E1E;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
@media (prefers-color-scheme: light) { :root {
|
|
13
|
-
--hl-0: var(--light-hl-0);
|
|
14
|
-
--hl-1: var(--light-hl-1);
|
|
15
|
-
--hl-2: var(--light-hl-2);
|
|
16
|
-
--code-background: var(--light-code-background);
|
|
17
|
-
} }
|
|
18
|
-
|
|
19
|
-
@media (prefers-color-scheme: dark) { :root {
|
|
20
|
-
--hl-0: var(--dark-hl-0);
|
|
21
|
-
--hl-1: var(--dark-hl-1);
|
|
22
|
-
--hl-2: var(--dark-hl-2);
|
|
23
|
-
--code-background: var(--dark-code-background);
|
|
24
|
-
} }
|
|
25
|
-
|
|
26
|
-
:root[data-theme='light'] {
|
|
27
|
-
--hl-0: var(--light-hl-0);
|
|
28
|
-
--hl-1: var(--light-hl-1);
|
|
29
|
-
--hl-2: var(--light-hl-2);
|
|
30
|
-
--code-background: var(--light-code-background);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
:root[data-theme='dark'] {
|
|
34
|
-
--hl-0: var(--dark-hl-0);
|
|
35
|
-
--hl-1: var(--dark-hl-1);
|
|
36
|
-
--hl-2: var(--dark-hl-2);
|
|
37
|
-
--code-background: var(--dark-code-background);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.hl-0 { color: var(--hl-0); }
|
|
41
|
-
.hl-1 { color: var(--hl-1); }
|
|
42
|
-
.hl-2 { color: var(--hl-2); }
|
|
43
|
-
pre, code { background: var(--code-background); }
|