@btc-vision/transaction 1.0.1 → 1.0.3
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/AddressGenerator.d.ts +7 -0
- package/browser/generators/builders/DeploymentGenerator.d.ts +1 -0
- package/browser/index.js +1 -1
- package/browser/keypair/Wallet.d.ts +1 -0
- package/browser/opnet.d.ts +2 -0
- package/browser/tests/Regtest.d.ts +3 -0
- package/browser/tests/gen.d.ts +1 -0
- package/browser/tests/test.d.ts +1 -0
- package/browser/tests/transfer.d.ts +1 -0
- package/browser/transaction/builders/TransactionBuilder.d.ts +4 -3
- package/browser/verification/TapscriptVerificator.d.ts +17 -0
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/generators/AddressGenerator.d.ts +7 -0
- package/build/generators/AddressGenerator.js +21 -0
- package/build/generators/OPNetAddressGenerator.d.ts +0 -0
- package/build/generators/OPNetAddressGenerator.js +1 -0
- package/build/generators/builders/DeploymentGenerator.d.ts +1 -0
- package/build/generators/builders/DeploymentGenerator.js +10 -7
- package/build/keypair/Wallet.d.ts +1 -0
- package/build/keypair/Wallet.js +6 -0
- package/build/opnet.d.ts +2 -0
- package/build/opnet.js +2 -0
- package/build/scripts/Regtest.d.ts +0 -1
- package/build/scripts/Regtest.js +0 -14
- package/build/scripts/test.js +7 -7
- package/build/tests/gen.d.ts +1 -0
- package/build/tests/gen.js +15 -0
- package/build/tests/test.d.ts +1 -0
- package/build/tests/test.js +51 -1
- package/build/tests/transfer.d.ts +1 -0
- package/build/tests/transfer.js +74 -0
- package/build/transaction/builders/TransactionBuilder.d.ts +4 -3
- package/build/transaction/builders/TransactionBuilder.js +9 -4
- package/build/verification/TapscriptVerificator.d.ts +17 -0
- package/build/verification/TapscriptVerificator.js +43 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/AddressGenerator.html +178 -0
- package/docs/classes/BitcoinUtils.html +3 -3
- package/docs/classes/CalldataGenerator.html +10 -10
- package/docs/classes/Compressor.html +4 -4
- package/docs/classes/ContractBaseMetadata.html +4 -4
- package/docs/classes/DeploymentGenerator.html +10 -9
- package/docs/classes/EcKeyPair.html +16 -16
- package/docs/classes/FundingTransaction.html +73 -50
- package/docs/classes/Generator.html +9 -9
- package/docs/classes/InteractionTransaction.html +94 -71
- package/docs/classes/TapscriptVerificator.html +180 -0
- package/docs/classes/TransactionBuilder.html +76 -53
- package/docs/classes/TransactionFactory.html +2 -2
- package/docs/classes/TweakedSigner.html +2 -2
- package/docs/classes/UTXOManager.html +3 -3
- package/docs/classes/Wallet.html +11 -9
- package/docs/classes/wBTC.html +7 -7
- package/docs/enums/TransactionType.html +2 -2
- package/docs/interfaces/ContractAddressVerificationParams.html +179 -0
- package/docs/interfaces/FetchUTXOParams.html +2 -2
- package/docs/interfaces/IFundingTransactionParameters.html +2 -2
- package/docs/interfaces/IInteractionParameters.html +2 -2
- package/docs/interfaces/ITransactionDataContractDeployment.html +2 -2
- package/docs/interfaces/ITransactionDataContractInteractionWrap.html +2 -2
- package/docs/interfaces/ITransactionParameters.html +2 -2
- package/docs/interfaces/IWallet.html +4 -4
- package/docs/interfaces/NetworkInformation.html +2 -2
- package/docs/interfaces/PsbtInputExtended.html +1 -1
- package/docs/interfaces/PsbtOutputExtendedAddress.html +2 -2
- package/docs/interfaces/PsbtOutputExtendedScript.html +2 -2
- package/docs/interfaces/RawUTXOResponse.html +2 -2
- package/docs/interfaces/TapLeafScript.html +2 -2
- package/docs/interfaces/TweakSettings.html +3 -3
- package/docs/interfaces/UTXO.html +2 -2
- package/docs/interfaces/UpdateInput.html +2 -2
- package/docs/modules.html +5 -2
- package/docs/types/PsbtOutputExtended.html +1 -1
- package/docs/variables/version.html +1 -1
- package/package.json +2 -1
- package/src/_version.ts +1 -1
- package/src/generators/AddressGenerator.ts +29 -0
- package/src/generators/builders/DeploymentGenerator.ts +16 -13
- package/src/keypair/Wallet.ts +12 -0
- package/src/opnet.ts +4 -0
- package/src/tests/gen.ts +24 -0
- package/src/tests/test.ts +17 -54
- package/src/tests/transfer.ts +102 -0
- package/src/transaction/builders/TransactionBuilder.ts +12 -5
- package/src/verification/TapscriptVerificator.ts +89 -0
- package/tests/TransactionBuilder.test.ts +58 -58
- package/tsconfig.webpack.json +8 -0
package/browser/opnet.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export * from './bytecode/Compressor.js';
|
|
|
3
3
|
export * from './generators/Generator.js';
|
|
4
4
|
export * from './generators/builders/CalldataGenerator.js';
|
|
5
5
|
export * from './generators/builders/DeploymentGenerator.js';
|
|
6
|
+
export * from './generators/AddressGenerator.js';
|
|
7
|
+
export * from './verification/TapscriptVerificator.js';
|
|
6
8
|
export * from './keypair/EcKeyPair.js';
|
|
7
9
|
export * from './keypair/Wallet.js';
|
|
8
10
|
export * from './keypair/interfaces/IWallet.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -5,9 +5,10 @@ import { TransactionType } from '../enums/TransactionType.js';
|
|
|
5
5
|
import { IFundingTransactionParameters, ITransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
6
6
|
import { Address } from '@btc-vision/bsi-binary';
|
|
7
7
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import { Logger } from '@btc-vision/logger';
|
|
9
|
+
export declare abstract class TransactionBuilder<T extends TransactionType> extends Logger {
|
|
10
|
+
static readonly LOCK_LEAF_SCRIPT: Buffer;
|
|
11
|
+
static readonly MINIMUM_DUST: bigint;
|
|
11
12
|
abstract readonly type: T;
|
|
12
13
|
readonly logColor: string;
|
|
13
14
|
transactionFee: bigint;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Network } from 'bitcoinjs-lib';
|
|
3
|
+
import { Taptree } from 'bitcoinjs-lib/src/types.js';
|
|
4
|
+
export interface ContractAddressVerificationParams {
|
|
5
|
+
readonly deployerPubKeyXOnly: Buffer;
|
|
6
|
+
readonly contractSaltPubKey: Buffer;
|
|
7
|
+
readonly originalSalt: Buffer;
|
|
8
|
+
readonly bytecode: Buffer;
|
|
9
|
+
readonly network?: Network;
|
|
10
|
+
}
|
|
11
|
+
export declare class TapscriptVerificator {
|
|
12
|
+
private static readonly TAP_SCRIPT_VERSION;
|
|
13
|
+
static getContractAddress(params: ContractAddressVerificationParams): string | undefined;
|
|
14
|
+
static getContractSeed(deployerPubKey: Buffer, bytecode: Buffer, saltHash: Buffer): Buffer;
|
|
15
|
+
static generateContractVirtualAddress(deployerPubKey: Buffer, bytecode: Buffer, saltHash: Buffer, network?: Network): string;
|
|
16
|
+
static generateAddressFromScript(params: ContractAddressVerificationParams, scriptTree: Taptree): string | undefined;
|
|
17
|
+
}
|
package/build/_version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "1.0.
|
|
1
|
+
export declare const version = "1.0.3";
|
package/build/_version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.0.
|
|
1
|
+
export const version = '1.0.3';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { bech32 } from 'bech32';
|
|
3
|
+
import { initEccLib } from 'bitcoinjs-lib';
|
|
4
|
+
import * as ecc from 'tiny-secp256k1';
|
|
5
|
+
initEccLib(ecc);
|
|
6
|
+
export class AddressGenerator {
|
|
7
|
+
static generatePKSH(sha256Hash, network) {
|
|
8
|
+
if (sha256Hash.length !== 32)
|
|
9
|
+
throw new Error('Invalid hash length');
|
|
10
|
+
const pkh = this.ripemd160(sha256Hash);
|
|
11
|
+
return this.toSegwitAddress(pkh, network);
|
|
12
|
+
}
|
|
13
|
+
static ripemd160(data) {
|
|
14
|
+
return createHash('ripemd160').update(data).digest();
|
|
15
|
+
}
|
|
16
|
+
static toSegwitAddress(pkh, network) {
|
|
17
|
+
const words = bech32.toWords(pkh);
|
|
18
|
+
words.unshift(0x00);
|
|
19
|
+
return bech32.encode(network.bech32, words);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -4,4 +4,5 @@ import { Generator } from '../Generator.js';
|
|
|
4
4
|
export declare class DeploymentGenerator extends Generator {
|
|
5
5
|
constructor(senderPubKey: Buffer, contractSaltPubKey: Buffer, network?: Network);
|
|
6
6
|
compile(contractBytecode: Buffer, contractSalt: Buffer): Buffer;
|
|
7
|
+
private getAsm;
|
|
7
8
|
}
|
|
@@ -5,8 +5,17 @@ export class DeploymentGenerator extends Generator {
|
|
|
5
5
|
super(senderPubKey, contractSaltPubKey, network);
|
|
6
6
|
}
|
|
7
7
|
compile(contractBytecode, contractSalt) {
|
|
8
|
+
const asm = this.getAsm(contractBytecode, contractSalt);
|
|
9
|
+
const compiled = script.compile(asm);
|
|
10
|
+
const decompiled = script.decompile(compiled);
|
|
11
|
+
if (!decompiled) {
|
|
12
|
+
throw new Error('Failed to decompile script??');
|
|
13
|
+
}
|
|
14
|
+
return compiled;
|
|
15
|
+
}
|
|
16
|
+
getAsm(contractBytecode, contractSalt) {
|
|
8
17
|
const dataChunks = this.splitBufferIntoChunks(contractBytecode);
|
|
9
|
-
|
|
18
|
+
return [
|
|
10
19
|
this.senderPubKey,
|
|
11
20
|
opcodes.OP_CHECKSIGVERIFY,
|
|
12
21
|
this.contractSaltPubKey,
|
|
@@ -28,11 +37,5 @@ export class DeploymentGenerator extends Generator {
|
|
|
28
37
|
opcodes.OP_1,
|
|
29
38
|
opcodes.OP_ENDIF,
|
|
30
39
|
].flat();
|
|
31
|
-
const compiled = script.compile(asm);
|
|
32
|
-
const decompiled = script.decompile(compiled);
|
|
33
|
-
if (!decompiled) {
|
|
34
|
-
throw new Error('Failed to decompile script??');
|
|
35
|
-
}
|
|
36
|
-
return compiled;
|
|
37
40
|
}
|
|
38
41
|
}
|
package/build/keypair/Wallet.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EcKeyPair } from './EcKeyPair.js';
|
|
2
2
|
import { networks } from 'bitcoinjs-lib';
|
|
3
|
+
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
3
4
|
export class Wallet {
|
|
4
5
|
network;
|
|
5
6
|
_keypair;
|
|
@@ -27,4 +28,9 @@ export class Wallet {
|
|
|
27
28
|
throw new Error('Keypair not set');
|
|
28
29
|
return this.keypair.publicKey;
|
|
29
30
|
}
|
|
31
|
+
get xOnly() {
|
|
32
|
+
if (!this.keypair)
|
|
33
|
+
throw new Error('Keypair not set');
|
|
34
|
+
return toXOnly(this.keypair.publicKey);
|
|
35
|
+
}
|
|
30
36
|
}
|
package/build/opnet.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export * from './bytecode/Compressor.js';
|
|
|
3
3
|
export * from './generators/Generator.js';
|
|
4
4
|
export * from './generators/builders/CalldataGenerator.js';
|
|
5
5
|
export * from './generators/builders/DeploymentGenerator.js';
|
|
6
|
+
export * from './generators/AddressGenerator.js';
|
|
7
|
+
export * from './verification/TapscriptVerificator.js';
|
|
6
8
|
export * from './keypair/EcKeyPair.js';
|
|
7
9
|
export * from './keypair/Wallet.js';
|
|
8
10
|
export * from './keypair/interfaces/IWallet.js';
|
package/build/opnet.js
CHANGED
|
@@ -3,6 +3,8 @@ export * from './bytecode/Compressor.js';
|
|
|
3
3
|
export * from './generators/Generator.js';
|
|
4
4
|
export * from './generators/builders/CalldataGenerator.js';
|
|
5
5
|
export * from './generators/builders/DeploymentGenerator.js';
|
|
6
|
+
export * from './generators/AddressGenerator.js';
|
|
7
|
+
export * from './verification/TapscriptVerificator.js';
|
|
6
8
|
export * from './keypair/EcKeyPair.js';
|
|
7
9
|
export * from './keypair/Wallet.js';
|
|
8
10
|
export * from './keypair/interfaces/IWallet.js';
|
package/build/scripts/Regtest.js
CHANGED
|
@@ -13,17 +13,3 @@ export const Regtest = {
|
|
|
13
13
|
BITCOIND_PASSWORD: 'YHEFHSDJ23JOIhjjef2ied9u290efu2930u90U',
|
|
14
14
|
},
|
|
15
15
|
};
|
|
16
|
-
export const Testnet = {
|
|
17
|
-
wallet: {
|
|
18
|
-
address: 'tb1qcfszz8dcvsz9mcp70ezw5zy2r3ydr0cfz60d3t',
|
|
19
|
-
privateKey: 'cSZU2QB9aUYvaL6ukU9d3DKq7QaxTRms1BCQnx5vqXbxBk4bdBc4',
|
|
20
|
-
publicKey: '026764d622f083d78f47c2f2a007ab08e96edf398de74acc0251a7bba202ffb92b',
|
|
21
|
-
},
|
|
22
|
-
config: {
|
|
23
|
-
BITCOIND_NETWORK: BitcoinNetwork.TestNet,
|
|
24
|
-
BITCOIND_HOST: '51.81.67.34',
|
|
25
|
-
BITCOIND_PORT: 9237,
|
|
26
|
-
BITCOIND_USERNAME: 'HJSiowseujhs',
|
|
27
|
-
BITCOIND_PASSWORD: 'YHEFHSDJ23JOIhjjef2ied9u290efu2930u90U',
|
|
28
|
-
},
|
|
29
|
-
};
|
package/build/scripts/test.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { wBTC } from '../metadata/contracts/wBTC.js';
|
|
2
2
|
import { Wallet } from '../keypair/Wallet.js';
|
|
3
|
-
import {
|
|
3
|
+
import { Regtest } from './Regtest.js';
|
|
4
4
|
import { UTXOManager } from '../utxo/UTXOManager.js';
|
|
5
5
|
import { networks } from 'bitcoinjs-lib';
|
|
6
6
|
import { TransactionFactory } from '../transaction/TransactionFactory.js';
|
|
7
7
|
import { BitcoinRPC } from '@btc-vision/bsi-bitcoin-rpc';
|
|
8
8
|
import { ABICoder, BinaryWriter } from '@btc-vision/bsi-binary';
|
|
9
|
-
const network = networks.
|
|
9
|
+
const network = networks.regtest;
|
|
10
10
|
const rpc = new BitcoinRPC();
|
|
11
11
|
const wBtc = new wBTC(network);
|
|
12
|
-
const wallet = new Wallet(
|
|
13
|
-
const utxoManager = new UTXOManager('
|
|
12
|
+
const wallet = new Wallet(Regtest.wallet, network);
|
|
13
|
+
const utxoManager = new UTXOManager('http://localhost:9001');
|
|
14
14
|
const factory = new TransactionFactory();
|
|
15
15
|
const abiCoder = new ABICoder();
|
|
16
16
|
const transferSelector = Number(`0x` + abiCoder.encodeSelector('transfer'));
|
|
@@ -21,7 +21,7 @@ function getTransferToCalldata(to, amount) {
|
|
|
21
21
|
addCalldata.writeU256(amount);
|
|
22
22
|
return Buffer.from(addCalldata.getBuffer());
|
|
23
23
|
}
|
|
24
|
-
const shouldMineBlock =
|
|
24
|
+
const shouldMineBlock = true;
|
|
25
25
|
async function mineBlock() {
|
|
26
26
|
const ok = await rpc.generateToAddress(1, wallet.p2wpkh, 'default');
|
|
27
27
|
if (!ok) {
|
|
@@ -31,7 +31,7 @@ async function mineBlock() {
|
|
|
31
31
|
return !!ok.length;
|
|
32
32
|
}
|
|
33
33
|
(async () => {
|
|
34
|
-
await rpc.init(
|
|
34
|
+
await rpc.init(Regtest.config);
|
|
35
35
|
const utxoSetting = {
|
|
36
36
|
address: wallet.p2wpkh,
|
|
37
37
|
minAmount: 10000n,
|
|
@@ -42,7 +42,7 @@ async function mineBlock() {
|
|
|
42
42
|
if (!utxos) {
|
|
43
43
|
throw new Error('No UTXOs found');
|
|
44
44
|
}
|
|
45
|
-
const calldata = getTransferToCalldata(
|
|
45
|
+
const calldata = getTransferToCalldata(wBtc.getAddress(), 5000000n);
|
|
46
46
|
const interactionParameters = {
|
|
47
47
|
from: wallet.p2wpkh,
|
|
48
48
|
to: wBtc.getAddress(),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TapscriptVerificator } from '../verification/TapscriptVerificator.js';
|
|
2
|
+
import { networks } from 'bitcoinjs-lib';
|
|
3
|
+
import { Regtest } from './Regtest.js';
|
|
4
|
+
import { Wallet } from '../keypair/Wallet.js';
|
|
5
|
+
const wallet = new Wallet(Regtest.wallet, networks.regtest);
|
|
6
|
+
const params = {
|
|
7
|
+
bytecode: Buffer.from('deadbeef', 'hex'),
|
|
8
|
+
contractSaltPubKey: Buffer.from('deadbeef', 'hex'),
|
|
9
|
+
deployerPubKeyXOnly: wallet.xOnly,
|
|
10
|
+
originalSalt: Buffer.from('deadbeef', 'hex'),
|
|
11
|
+
network: networks.regtest,
|
|
12
|
+
};
|
|
13
|
+
const contractAddress = TapscriptVerificator.getContractAddress(params);
|
|
14
|
+
const virtualAddress = TapscriptVerificator.generateContractVirtualAddress(params.deployerPubKeyXOnly, params.bytecode, params.originalSalt, networks.regtest);
|
|
15
|
+
console.log('contract sewgit address', virtualAddress, '\ncontract p2tr address', contractAddress);
|
package/build/tests/test.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/build/tests/test.js
CHANGED
|
@@ -1 +1,51 @@
|
|
|
1
|
-
|
|
1
|
+
import { Wallet } from '../keypair/Wallet.js';
|
|
2
|
+
import { Regtest } from './Regtest.js';
|
|
3
|
+
import { UTXOManager } from '../utxo/UTXOManager.js';
|
|
4
|
+
import { networks } from 'bitcoinjs-lib';
|
|
5
|
+
import { BitcoinRPC } from '@btc-vision/bsi-bitcoin-rpc';
|
|
6
|
+
import { FundingTransaction } from '../transaction/builders/FundingTransaction.js';
|
|
7
|
+
const network = networks.regtest;
|
|
8
|
+
const rpc = new BitcoinRPC();
|
|
9
|
+
const wallet = new Wallet(Regtest.wallet, network);
|
|
10
|
+
const utxoManager = new UTXOManager('http://localhost:9001');
|
|
11
|
+
const shouldMineBlock = true;
|
|
12
|
+
async function mineBlock() {
|
|
13
|
+
const ok = await rpc.generateToAddress(1, wallet.p2wpkh, 'default');
|
|
14
|
+
if (!ok) {
|
|
15
|
+
throw new Error('Could not mine block');
|
|
16
|
+
}
|
|
17
|
+
console.log(`Mined block`, ok);
|
|
18
|
+
return !!ok.length;
|
|
19
|
+
}
|
|
20
|
+
(async () => {
|
|
21
|
+
await rpc.init(Regtest.config);
|
|
22
|
+
const utxoSetting = {
|
|
23
|
+
address: wallet.p2wpkh,
|
|
24
|
+
minAmount: 10000n,
|
|
25
|
+
requestedAmount: 100000n,
|
|
26
|
+
};
|
|
27
|
+
const utxos = await utxoManager.fetchUTXO(utxoSetting);
|
|
28
|
+
if (!utxos) {
|
|
29
|
+
throw new Error('No UTXOs found');
|
|
30
|
+
}
|
|
31
|
+
const interactionParameters = {
|
|
32
|
+
from: wallet.p2wpkh,
|
|
33
|
+
to: 'bcrt1qqvf4gprr05z248ph6gvx54rpg08p8ngq3zh8uh',
|
|
34
|
+
utxos: utxos,
|
|
35
|
+
signer: wallet.keypair,
|
|
36
|
+
network: network,
|
|
37
|
+
feeRate: 150,
|
|
38
|
+
priorityFee: 1000n,
|
|
39
|
+
childTransactionRequiredFees: 0n,
|
|
40
|
+
};
|
|
41
|
+
const fundingTransaction = new FundingTransaction(interactionParameters);
|
|
42
|
+
const fundingTx = fundingTransaction.signTransaction();
|
|
43
|
+
console.log(fundingTx.toHex());
|
|
44
|
+
const secondTxBroadcast = await rpc.sendRawTransaction({
|
|
45
|
+
hexstring: fundingTx.toHex(),
|
|
46
|
+
});
|
|
47
|
+
console.log(`Transaction broadcasted: ${secondTxBroadcast}`);
|
|
48
|
+
if (shouldMineBlock) {
|
|
49
|
+
await mineBlock();
|
|
50
|
+
}
|
|
51
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { wBTC } from '../metadata/contracts/wBTC.js';
|
|
2
|
+
import { Wallet } from '../keypair/Wallet.js';
|
|
3
|
+
import { Testnet } from './Regtest.js';
|
|
4
|
+
import { UTXOManager } from '../utxo/UTXOManager.js';
|
|
5
|
+
import { networks } from 'bitcoinjs-lib';
|
|
6
|
+
import { TransactionFactory } from '../transaction/TransactionFactory.js';
|
|
7
|
+
import { BitcoinRPC } from '@btc-vision/bsi-bitcoin-rpc';
|
|
8
|
+
import { ABICoder, BinaryWriter } from '@btc-vision/bsi-binary';
|
|
9
|
+
const network = networks.testnet;
|
|
10
|
+
const rpc = new BitcoinRPC();
|
|
11
|
+
const wBtc = new wBTC(network);
|
|
12
|
+
const wallet = new Wallet(Testnet.wallet, network);
|
|
13
|
+
const utxoManager = new UTXOManager('https://testnet.opnet.org');
|
|
14
|
+
const factory = new TransactionFactory();
|
|
15
|
+
const abiCoder = new ABICoder();
|
|
16
|
+
const transferSelector = Number(`0x` + abiCoder.encodeSelector('transfer'));
|
|
17
|
+
function getTransferToCalldata(to, amount) {
|
|
18
|
+
const addCalldata = new BinaryWriter();
|
|
19
|
+
addCalldata.writeSelector(transferSelector);
|
|
20
|
+
addCalldata.writeAddress(to);
|
|
21
|
+
addCalldata.writeU256(amount);
|
|
22
|
+
return Buffer.from(addCalldata.getBuffer());
|
|
23
|
+
}
|
|
24
|
+
const shouldMineBlock = false;
|
|
25
|
+
async function mineBlock() {
|
|
26
|
+
const ok = await rpc.generateToAddress(1, wallet.p2wpkh, 'default');
|
|
27
|
+
if (!ok) {
|
|
28
|
+
throw new Error('Could not mine block');
|
|
29
|
+
}
|
|
30
|
+
console.log(`Mined block`, ok);
|
|
31
|
+
return !!ok.length;
|
|
32
|
+
}
|
|
33
|
+
(async () => {
|
|
34
|
+
await rpc.init(Testnet.config);
|
|
35
|
+
const utxoSetting = {
|
|
36
|
+
address: wallet.p2wpkh,
|
|
37
|
+
minAmount: 10000n,
|
|
38
|
+
requestedAmount: 100000n,
|
|
39
|
+
};
|
|
40
|
+
const utxos = await utxoManager.fetchUTXO(utxoSetting);
|
|
41
|
+
console.log(`UTXOs:`, utxos);
|
|
42
|
+
if (!utxos) {
|
|
43
|
+
throw new Error('No UTXOs found');
|
|
44
|
+
}
|
|
45
|
+
const calldata = getTransferToCalldata('tb1pt3ncc5ktfzpry2uvnag06v3jkv4quvmdydf09q8fx6rkgd7f5s8q3aenuk', 5000000n);
|
|
46
|
+
const interactionParameters = {
|
|
47
|
+
from: wallet.p2wpkh,
|
|
48
|
+
to: wBtc.getAddress(),
|
|
49
|
+
utxos: utxos,
|
|
50
|
+
signer: wallet.keypair,
|
|
51
|
+
network: network,
|
|
52
|
+
feeRate: 150,
|
|
53
|
+
priorityFee: 50000n,
|
|
54
|
+
calldata: calldata,
|
|
55
|
+
};
|
|
56
|
+
const finalTx = factory.signInteraction(interactionParameters);
|
|
57
|
+
const firstTxBroadcast = await rpc.sendRawTransaction({
|
|
58
|
+
hexstring: finalTx[0],
|
|
59
|
+
});
|
|
60
|
+
console.log(`First transaction broadcasted: ${firstTxBroadcast}`);
|
|
61
|
+
if (!firstTxBroadcast) {
|
|
62
|
+
throw new Error('Could not broadcast first transaction');
|
|
63
|
+
}
|
|
64
|
+
const secondTxBroadcast = await rpc.sendRawTransaction({
|
|
65
|
+
hexstring: finalTx[1],
|
|
66
|
+
});
|
|
67
|
+
console.log(`Second transaction broadcasted: ${secondTxBroadcast}`);
|
|
68
|
+
if (!secondTxBroadcast) {
|
|
69
|
+
throw new Error('Could not broadcast second transaction');
|
|
70
|
+
}
|
|
71
|
+
if (shouldMineBlock) {
|
|
72
|
+
await mineBlock();
|
|
73
|
+
}
|
|
74
|
+
})();
|
|
@@ -5,9 +5,10 @@ import { TransactionType } from '../enums/TransactionType.js';
|
|
|
5
5
|
import { IFundingTransactionParameters, ITransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
6
6
|
import { Address } from '@btc-vision/bsi-binary';
|
|
7
7
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import { Logger } from '@btc-vision/logger';
|
|
9
|
+
export declare abstract class TransactionBuilder<T extends TransactionType> extends Logger {
|
|
10
|
+
static readonly LOCK_LEAF_SCRIPT: Buffer;
|
|
11
|
+
static readonly MINIMUM_DUST: bigint;
|
|
11
12
|
abstract readonly type: T;
|
|
12
13
|
readonly logColor: string;
|
|
13
14
|
transactionFee: bigint;
|
|
@@ -3,8 +3,12 @@ import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
|
|
|
3
3
|
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
4
4
|
import * as ecc from 'tiny-secp256k1';
|
|
5
5
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import { Logger } from '@btc-vision/logger';
|
|
7
|
+
export class TransactionBuilder extends Logger {
|
|
8
|
+
static LOCK_LEAF_SCRIPT = script.compile([
|
|
9
|
+
opcodes.OP_0,
|
|
10
|
+
opcodes.OP_VERIFY,
|
|
11
|
+
]);
|
|
8
12
|
static MINIMUM_DUST = 330n;
|
|
9
13
|
logColor = '#785def';
|
|
10
14
|
transactionFee = 0n;
|
|
@@ -26,6 +30,7 @@ export class TransactionBuilder {
|
|
|
26
30
|
from;
|
|
27
31
|
_maximumFeeRate = 100000000;
|
|
28
32
|
constructor(parameters) {
|
|
33
|
+
super();
|
|
29
34
|
this.signer = parameters.signer;
|
|
30
35
|
this.network = parameters.network;
|
|
31
36
|
this.feeRate = parameters.feeRate;
|
|
@@ -121,7 +126,7 @@ export class TransactionBuilder {
|
|
|
121
126
|
});
|
|
122
127
|
return;
|
|
123
128
|
}
|
|
124
|
-
|
|
129
|
+
this.warn(`Amount to send back is less than the minimum dust, will be consumed in fees instead.`);
|
|
125
130
|
}
|
|
126
131
|
getTransactionOPNetFee() {
|
|
127
132
|
if (this.priorityFee > TransactionBuilder.MINIMUM_DUST) {
|
|
@@ -265,7 +270,7 @@ export class TransactionBuilder {
|
|
|
265
270
|
}
|
|
266
271
|
catch (e) {
|
|
267
272
|
const err = e;
|
|
268
|
-
|
|
273
|
+
this.error(`[internalBuildTransaction] Something went wrong while getting building the transaction: ${err.stack}`);
|
|
269
274
|
}
|
|
270
275
|
return false;
|
|
271
276
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Network } from 'bitcoinjs-lib';
|
|
3
|
+
import { Taptree } from 'bitcoinjs-lib/src/types.js';
|
|
4
|
+
export interface ContractAddressVerificationParams {
|
|
5
|
+
readonly deployerPubKeyXOnly: Buffer;
|
|
6
|
+
readonly contractSaltPubKey: Buffer;
|
|
7
|
+
readonly originalSalt: Buffer;
|
|
8
|
+
readonly bytecode: Buffer;
|
|
9
|
+
readonly network?: Network;
|
|
10
|
+
}
|
|
11
|
+
export declare class TapscriptVerificator {
|
|
12
|
+
private static readonly TAP_SCRIPT_VERSION;
|
|
13
|
+
static getContractAddress(params: ContractAddressVerificationParams): string | undefined;
|
|
14
|
+
static getContractSeed(deployerPubKey: Buffer, bytecode: Buffer, saltHash: Buffer): Buffer;
|
|
15
|
+
static generateContractVirtualAddress(deployerPubKey: Buffer, bytecode: Buffer, saltHash: Buffer, network?: Network): string;
|
|
16
|
+
static generateAddressFromScript(params: ContractAddressVerificationParams, scriptTree: Taptree): string | undefined;
|
|
17
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import bitcoin, { networks, payments } from 'bitcoinjs-lib';
|
|
2
|
+
import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
|
|
3
|
+
import { DeploymentGenerator } from '../generators/builders/DeploymentGenerator.js';
|
|
4
|
+
import { TransactionBuilder } from '../transaction/builders/TransactionBuilder.js';
|
|
5
|
+
import { AddressGenerator } from '../generators/AddressGenerator.js';
|
|
6
|
+
export class TapscriptVerificator {
|
|
7
|
+
static TAP_SCRIPT_VERSION = 192;
|
|
8
|
+
static getContractAddress(params) {
|
|
9
|
+
const network = params.network || networks.bitcoin;
|
|
10
|
+
const scriptBuilder = new DeploymentGenerator(params.deployerPubKeyXOnly, toXOnly(params.contractSaltPubKey), network);
|
|
11
|
+
const compiledTargetScript = scriptBuilder.compile(params.bytecode, params.originalSalt);
|
|
12
|
+
const scriptTree = [
|
|
13
|
+
{
|
|
14
|
+
output: compiledTargetScript,
|
|
15
|
+
version: TapscriptVerificator.TAP_SCRIPT_VERSION,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
output: TransactionBuilder.LOCK_LEAF_SCRIPT,
|
|
19
|
+
version: TapscriptVerificator.TAP_SCRIPT_VERSION,
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
return TapscriptVerificator.generateAddressFromScript(params, scriptTree);
|
|
23
|
+
}
|
|
24
|
+
static getContractSeed(deployerPubKey, bytecode, saltHash) {
|
|
25
|
+
const sha256OfBytecode = bitcoin.crypto.hash256(bytecode);
|
|
26
|
+
const buf = Buffer.concat([deployerPubKey, saltHash, sha256OfBytecode]);
|
|
27
|
+
return bitcoin.crypto.hash256(buf);
|
|
28
|
+
}
|
|
29
|
+
static generateContractVirtualAddress(deployerPubKey, bytecode, saltHash, network = networks.bitcoin) {
|
|
30
|
+
const virtualAddress = TapscriptVerificator.getContractSeed(deployerPubKey, bytecode, saltHash);
|
|
31
|
+
return AddressGenerator.generatePKSH(virtualAddress, network);
|
|
32
|
+
}
|
|
33
|
+
static generateAddressFromScript(params, scriptTree) {
|
|
34
|
+
const network = params.network || networks.bitcoin;
|
|
35
|
+
const transactionData = {
|
|
36
|
+
internalPubkey: params.deployerPubKeyXOnly,
|
|
37
|
+
network: network,
|
|
38
|
+
scriptTree: scriptTree,
|
|
39
|
+
};
|
|
40
|
+
const tx = payments.p2tr(transactionData);
|
|
41
|
+
return tx.address;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.navigationData = "data:application/octet-stream;base64,
|
|
1
|
+
window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAACp2VW2/aQBCF/4ufUWmo0gtvJZcKtWlQcJpKUR4m9gAr7PVqdxxiVfnvlYmL197JAH31nPOd2cus7/9EhM8UjaPYgnaQkCp0XBmMBpEBWkXjCHWZu2Gv/G5FeRYNorXSaTT+/DLYcb6mqUXnvqFGC1TYFpRk4By6YV/RZZ2MfNpEUVIofUsqcyHJr0qUM8iyFAiEpgKJyCtyUy+BBe1qMkGThYQm4PAKCepojhWqJOo5mqyoctQkrJQRScyL5DtWM1AMaVeS/JelTpVeevcnBIUaiSis7aAVTTWhba6y1BWvk8gxGJdYZegXWrVQCd8kpxKpbfikVFmKHDPQHEi8hIQKW4nERiMSNwhrTOdqqdn2/LLEuY1/X1+BhiVH8YoS4w6yDCm0v36XnJtJfBb66q+HzHLzru1OVRV6BhZy7+FS9ZVaQOLN9puubuTo9KM/VEjJqt4OIaCnkXDTcAC3JiS0PFx0iFHeVO3LYKUi3GvnHAj+7XH75PFBe23/E+p1f2fBHJXc8x4av29Djz+t/iz5NG6euvafSJvCrqd6Udgcuq+sRwplEnTmHmmqTUkXz4Q6xZRlBqp9yOuSPHUzlW+iWfVxEfPtP+DAhFexFHADm3rYb9CZQjtkuT2NhIvB/EBYCE12FCKqfvznSKT0kt/RjkJC1d2zhLogGk0KhNsLwfvb+nGn2NKoMuzR9Xjvv3w6OR15zCe0rjMZT2AVPGbohk2pS/gwenn4C/vJ5J23CwAA"
|
package/docs/assets/search.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
window.searchData = "data:application/octet-stream;base64,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";
|
|
1
|
+
window.searchData = "data:application/octet-stream;base64,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";
|