@btc-vision/transaction 1.0.2 → 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.
Files changed (83) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/generators/AddressGenerator.d.ts +7 -0
  3. package/browser/generators/builders/DeploymentGenerator.d.ts +1 -0
  4. package/browser/index.js +2 -2
  5. package/browser/keypair/Wallet.d.ts +1 -0
  6. package/browser/opnet.d.ts +2 -0
  7. package/browser/tests/gen.d.ts +1 -0
  8. package/browser/tests/transfer.d.ts +1 -0
  9. package/browser/transaction/builders/TransactionBuilder.d.ts +2 -2
  10. package/browser/verification/TapscriptVerificator.d.ts +17 -0
  11. package/build/_version.d.ts +1 -1
  12. package/build/_version.js +1 -1
  13. package/build/generators/AddressGenerator.d.ts +7 -0
  14. package/build/generators/AddressGenerator.js +21 -0
  15. package/build/generators/OPNetAddressGenerator.d.ts +0 -0
  16. package/build/generators/OPNetAddressGenerator.js +1 -0
  17. package/build/generators/builders/DeploymentGenerator.d.ts +1 -0
  18. package/build/generators/builders/DeploymentGenerator.js +10 -7
  19. package/build/keypair/Wallet.d.ts +1 -0
  20. package/build/keypair/Wallet.js +6 -0
  21. package/build/opnet.d.ts +2 -0
  22. package/build/opnet.js +2 -0
  23. package/build/tests/gen.d.ts +1 -0
  24. package/build/tests/gen.js +15 -0
  25. package/build/tests/test.js +15 -38
  26. package/build/tests/transfer.d.ts +1 -0
  27. package/build/tests/transfer.js +74 -0
  28. package/build/transaction/builders/TransactionBuilder.d.ts +2 -2
  29. package/build/transaction/builders/TransactionBuilder.js +4 -1
  30. package/build/verification/TapscriptVerificator.d.ts +17 -0
  31. package/build/verification/TapscriptVerificator.js +43 -0
  32. package/docs/assets/navigation.js +1 -1
  33. package/docs/assets/search.js +1 -1
  34. package/docs/classes/AddressGenerator.html +178 -0
  35. package/docs/classes/BitcoinUtils.html +182 -182
  36. package/docs/classes/CalldataGenerator.html +210 -210
  37. package/docs/classes/Compressor.html +184 -184
  38. package/docs/classes/ContractBaseMetadata.html +181 -181
  39. package/docs/classes/DeploymentGenerator.html +200 -199
  40. package/docs/classes/EcKeyPair.html +279 -279
  41. package/docs/classes/FundingTransaction.html +315 -315
  42. package/docs/classes/Generator.html +198 -198
  43. package/docs/classes/InteractionTransaction.html +387 -387
  44. package/docs/classes/TapscriptVerificator.html +180 -0
  45. package/docs/classes/TransactionBuilder.html +325 -325
  46. package/docs/classes/TransactionFactory.html +179 -179
  47. package/docs/classes/TweakedSigner.html +180 -180
  48. package/docs/classes/UTXOManager.html +186 -186
  49. package/docs/classes/Wallet.html +192 -190
  50. package/docs/classes/wBTC.html +188 -188
  51. package/docs/enums/TransactionType.html +178 -178
  52. package/docs/interfaces/ContractAddressVerificationParams.html +179 -0
  53. package/docs/interfaces/FetchUTXOParams.html +177 -177
  54. package/docs/interfaces/IFundingTransactionParameters.html +181 -181
  55. package/docs/interfaces/IInteractionParameters.html +184 -184
  56. package/docs/interfaces/ITransactionDataContractDeployment.html +183 -183
  57. package/docs/interfaces/ITransactionDataContractInteractionWrap.html +185 -185
  58. package/docs/interfaces/ITransactionParameters.html +180 -180
  59. package/docs/interfaces/IWallet.html +180 -180
  60. package/docs/interfaces/NetworkInformation.html +175 -175
  61. package/docs/interfaces/PsbtInputExtended.html +193 -193
  62. package/docs/interfaces/PsbtOutputExtendedAddress.html +182 -182
  63. package/docs/interfaces/PsbtOutputExtendedScript.html +182 -182
  64. package/docs/interfaces/RawUTXOResponse.html +177 -177
  65. package/docs/interfaces/TapLeafScript.html +176 -176
  66. package/docs/interfaces/TweakSettings.html +178 -178
  67. package/docs/interfaces/UTXO.html +177 -177
  68. package/docs/interfaces/UpdateInput.html +174 -174
  69. package/docs/modules.html +5 -2
  70. package/docs/types/PsbtOutputExtended.html +173 -173
  71. package/docs/variables/version.html +173 -173
  72. package/package.json +2 -1
  73. package/src/_version.ts +1 -1
  74. package/src/generators/AddressGenerator.ts +29 -0
  75. package/src/generators/builders/DeploymentGenerator.ts +16 -13
  76. package/src/keypair/Wallet.ts +12 -0
  77. package/src/opnet.ts +4 -0
  78. package/src/tests/gen.ts +24 -0
  79. package/src/tests/test.ts +17 -54
  80. package/src/{scripts/test.ts → tests/transfer.ts} +102 -98
  81. package/src/transaction/builders/TransactionBuilder.ts +610 -606
  82. package/src/verification/TapscriptVerificator.ts +89 -0
  83. package/src/scripts/Regtest.ts +0 -19
@@ -13,4 +13,5 @@ export declare class Wallet {
13
13
  get p2wpkh(): Address;
14
14
  get p2tr(): Address;
15
15
  get publicKey(): Buffer;
16
+ get xOnly(): Buffer;
16
17
  }
@@ -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 {};
@@ -7,8 +7,8 @@ import { Address } from '@btc-vision/bsi-binary';
7
7
  import { UTXO } from '../../utxo/interfaces/IUTXO.js';
8
8
  import { Logger } from '@btc-vision/logger';
9
9
  export declare abstract class TransactionBuilder<T extends TransactionType> extends Logger {
10
- protected static readonly LOCK_LEAF_SCRIPT: Buffer;
11
- protected static readonly MINIMUM_DUST: bigint;
10
+ static readonly LOCK_LEAF_SCRIPT: Buffer;
11
+ static readonly MINIMUM_DUST: bigint;
12
12
  abstract readonly type: T;
13
13
  readonly logColor: string;
14
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
+ }
@@ -1 +1 @@
1
- export declare const version = "1.0.2";
1
+ export declare const version = "1.0.3";
package/build/_version.js CHANGED
@@ -1 +1 @@
1
- export const version = '1.0.2';
1
+ export const version = '1.0.3';
@@ -0,0 +1,7 @@
1
+ /// <reference types="node" />
2
+ import { Network } from 'bitcoinjs-lib';
3
+ export declare class AddressGenerator {
4
+ static generatePKSH(sha256Hash: Buffer, network: Network): string;
5
+ private static ripemd160;
6
+ private static toSegwitAddress;
7
+ }
@@ -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
- const asm = [
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
  }
@@ -13,4 +13,5 @@ export declare class Wallet {
13
13
  get p2wpkh(): Address;
14
14
  get p2tr(): Address;
15
15
  get publicKey(): Buffer;
16
+ get xOnly(): Buffer;
16
17
  }
@@ -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';
@@ -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);
@@ -1,27 +1,14 @@
1
- import { wBTC } from '../metadata/contracts/wBTC.js';
2
1
  import { Wallet } from '../keypair/Wallet.js';
3
- import { Testnet } from './Regtest.js';
2
+ import { Regtest } from './Regtest.js';
4
3
  import { UTXOManager } from '../utxo/UTXOManager.js';
5
4
  import { networks } from 'bitcoinjs-lib';
6
- import { TransactionFactory } from '../transaction/TransactionFactory.js';
7
5
  import { BitcoinRPC } from '@btc-vision/bsi-bitcoin-rpc';
8
- import { ABICoder, BinaryWriter } from '@btc-vision/bsi-binary';
9
- const network = networks.testnet;
6
+ import { FundingTransaction } from '../transaction/builders/FundingTransaction.js';
7
+ const network = networks.regtest;
10
8
  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;
9
+ const wallet = new Wallet(Regtest.wallet, network);
10
+ const utxoManager = new UTXOManager('http://localhost:9001');
11
+ const shouldMineBlock = true;
25
12
  async function mineBlock() {
26
13
  const ok = await rpc.generateToAddress(1, wallet.p2wpkh, 'default');
27
14
  if (!ok) {
@@ -31,43 +18,33 @@ async function mineBlock() {
31
18
  return !!ok.length;
32
19
  }
33
20
  (async () => {
34
- await rpc.init(Testnet.config);
21
+ await rpc.init(Regtest.config);
35
22
  const utxoSetting = {
36
23
  address: wallet.p2wpkh,
37
24
  minAmount: 10000n,
38
25
  requestedAmount: 100000n,
39
26
  };
40
27
  const utxos = await utxoManager.fetchUTXO(utxoSetting);
41
- console.log(`UTXOs:`, utxos);
42
28
  if (!utxos) {
43
29
  throw new Error('No UTXOs found');
44
30
  }
45
- const calldata = getTransferToCalldata('tb1pt3ncc5ktfzpry2uvnag06v3jkv4quvmdydf09q8fx6rkgd7f5s8q3aenuk', 5000000n);
46
31
  const interactionParameters = {
47
32
  from: wallet.p2wpkh,
48
- to: wBtc.getAddress(),
33
+ to: 'bcrt1qqvf4gprr05z248ph6gvx54rpg08p8ngq3zh8uh',
49
34
  utxos: utxos,
50
35
  signer: wallet.keypair,
51
36
  network: network,
52
37
  feeRate: 150,
53
- priorityFee: 50000n,
54
- calldata: calldata,
38
+ priorityFee: 1000n,
39
+ childTransactionRequiredFees: 0n,
55
40
  };
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
- }
41
+ const fundingTransaction = new FundingTransaction(interactionParameters);
42
+ const fundingTx = fundingTransaction.signTransaction();
43
+ console.log(fundingTx.toHex());
64
44
  const secondTxBroadcast = await rpc.sendRawTransaction({
65
- hexstring: finalTx[1],
45
+ hexstring: fundingTx.toHex(),
66
46
  });
67
- console.log(`Second transaction broadcasted: ${secondTxBroadcast}`);
68
- if (!secondTxBroadcast) {
69
- throw new Error('Could not broadcast second transaction');
70
- }
47
+ console.log(`Transaction broadcasted: ${secondTxBroadcast}`);
71
48
  if (shouldMineBlock) {
72
49
  await mineBlock();
73
50
  }
@@ -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
+ })();
@@ -7,8 +7,8 @@ import { Address } from '@btc-vision/bsi-binary';
7
7
  import { UTXO } from '../../utxo/interfaces/IUTXO.js';
8
8
  import { Logger } from '@btc-vision/logger';
9
9
  export declare abstract class TransactionBuilder<T extends TransactionType> extends Logger {
10
- protected static readonly LOCK_LEAF_SCRIPT: Buffer;
11
- protected static readonly MINIMUM_DUST: bigint;
10
+ static readonly LOCK_LEAF_SCRIPT: Buffer;
11
+ static readonly MINIMUM_DUST: bigint;
12
12
  abstract readonly type: T;
13
13
  readonly logColor: string;
14
14
  transactionFee: bigint;
@@ -5,7 +5,10 @@ import * as ecc from 'tiny-secp256k1';
5
5
  import { EcKeyPair } from '../../keypair/EcKeyPair.js';
6
6
  import { Logger } from '@btc-vision/logger';
7
7
  export class TransactionBuilder extends Logger {
8
- static LOCK_LEAF_SCRIPT = script.compile([opcodes.OP_0]);
8
+ static LOCK_LEAF_SCRIPT = script.compile([
9
+ opcodes.OP_0,
10
+ opcodes.OP_VERIFY,
11
+ ]);
9
12
  static MINIMUM_DUST = 330n;
10
13
  logColor = '#785def';
11
14
  transactionFee = 0n;
@@ -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,H4sIAAAAAAAACp2V224aMRCG38XXqDRE6YG7kkOF2jQoEKVSlYvJegALr9eyZ0NWVd69ckrBu3YG6O3O/38z9oxnf/0WhM8khmLmwHgoSFVm1lgUPWGBlmIo0NSl73fC75ZUatETK2WkGH566W05I0VFpcwdKe13kEKD9+j7cbTNOBnElHPQWgLBVzTogCqXohIJy6tK69D7LGgb4wmGHBQ0Ao/XSBBS51ipiqNeoNVVU6Ih5qQZEce8LL5hMwGVIW1DnP+qNlKZRdTxFJRqOCJztoNONDaEbjN8XFV5HUeOZKNaaYmZElPNgcQrKKhyDUvcaFjiGmGFcqoWJlteHOY4d7OfN9dgYJGjREGOcQ9aI6X2v98553o0O0994Ss7i0jFMtQ2AQdltFBUaPUcijCLbU0bNzj7EA9SOrevJiR0eTjrYFNFw7gvR1bKwqNyLoDg39rZbYp8or22/0kaVX/vwB6VueM9NP2+Cz2+W93Bjmm54W7bfyCtK7cam3nlSmgvp4iUyjjoxD/S2NiaLp8JjUSZZSaqfcibmiL1FynDv+9NdFZ9XIpp4ZTNX+1bYi7BLazDY79FbyvjMcvtaDjcDOx3hDlTZEvBosImniKRMov8jbYUHCpUnyWEAGu0EghfByLv38WP6+KORo3Ntq7De//548nZIGI+ofOtl/EETsGjRt/fhNqE08HLwx8aM5UwoAoAAA=="
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"
@@ -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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";