javascript – Find out how to signal a PSBT with BitcoinerLAB?

0
76


Initially, We’re utilizing bitcoinerLab.

Example

From the seed, we generate the Grasp Key, and with the trail, we create the kid key 0 (the father or mother’s) and youngster key 1 (the kid’s). Now, from these keys, we get hold of the Grandchild keys with which we are going to generate infinite addresses containing the next coverage:

or(pk(@dadKey),and(pk(@sonKey),after(20)))

What we would like is that by way of a Grandchild deal with, which may have funds locked by the earlier coverage, we’d like both the father or mother or the kid to attempt to create a transaction and unlock these funds.

Within the descriptor that I create, I move the GrandChildKey’s public key.

var publickeydad=masterNode.derivePath(`m${ORIGIN_PATH}${KEY_PATH}/0`).publicKey;

    const wshDescriptor = new Descriptor({
        expression: wshExpression,
        community,
        signersPubKeys: [publickeydad] 
    });

Now, the problem arises when signing the PSBT. We need to signal it with ChildKey 0, which can correspond to ‘dadKey’ in our coverage. The error happens proper right here within the ‘masterNode’ attribute. How ought to we signal it?

descriptors.signers.signBIP32({ psbt, masterNode: descriptors.keyExpressionBIP32({
        masterNode: masterNode,
        originPath: ORIGIN_PATH,
        keyPath: `${KEY_PATH}`
    })});

In abstract, we need to generate infinite GrandChild addresses with the beforehand described coverage, and we need to signal transactions both with ChildKey0 or ChildKey1 to unlock the funds within the GrandChild addresses:

The total code:


import * as bitcoin from "bitcoinjs-lib";
import { Psbt, networks } from 'bitcoinjs-lib';
import * as ecpair from "ecpair";
import * as secp from "tiny-secp256k1";
const ECPair = ecpair.ECPairFactory(secp);
import * as fs from 'fs';
import * as secp256k1 from '@bitcoinerlab/secp256k1';
import * as descriptors from '@bitcoinerlab/descriptors';
import { compilePolicy } from '@bitcoinerlab/miniscript';
import { generateMnemonic, mnemonicToSeedSync } from 'bip39';
import { encode as afterEncode } from 'bip65';

const ORIGIN_PATH = `/69420'/1'/0'`; 
const KEY_PATH = `/0/0`; 
const community = networks.testnet;
const { Descriptor, BIP32, ECPair2 } = descriptors.DescriptorsFactory(secp256k1);
var coverage =`or(pk(@dadKey),and(pk(@sonKey),after(20)))`;


async operate send_tx(){
    const toAddress="mqCMd6LtWXLqKgCiPyVzzhKQvb1AKixgtu"
    const community = networks.testnet;
    const EXPLORER = 'https://blockstream.data/testnet';

    const masterNode = BIP32.fromSeed(mnemonicToSeedSync('uncle trade hospital amused when paper timber precise accuse unique squeeze vote'),community); 
    const wshAddress="tb1q8rnzmm5ttrl8fc94y94vpyzf62e69cq85v7dwvve33h3ta85xlpqe7wdhl"
    const utxo = await (
    await fetch(`${EXPLORER}/api/deal with/${wshAddress}/utxo`)
    ).json();

    if (utxo?.[0]) {
        const txHex = await (
        await fetch(`${EXPLORER}/api/tx/${utxo?.[0].txid}/hex`)
    ).textual content();
    const inputValue = utxo[0].worth;
    const psbt = new Psbt({ community });
    
    const wshExpression = "wsh(andor(pk([57836ab7/69420'/1'/0']tpubDDLpvA16cXnaKBY4r8sy7fmZV5ATP9a2ik7kycRKn3twfEFngNGPk8u2CYfR2yrLqLJFdHjh2Pm3YWHTFoepVaFeewHaqoSmFUbxbbLzhfa/0/1/0),after(20),pk([57836ab7/69420'/1'/0']tpubDDLpvA16cXnaKBY4r8sy7fmZV5ATP9a2ik7kycRKn3twfEFngNGPk8u2CYfR2yrLqLJFdHjh2Pm3YWHTFoepVaFeewHaqoSmFUbxbbLzhfa/0/0/0)))"

    // La clave publica del GRANDchild del padre
    var publickeydad=masterNode.derivePath(`m${ORIGIN_PATH}${KEY_PATH}/0`).publicKey;

    const wshDescriptor = new Descriptor({
        expression: wshExpression,
        community,
        signersPubKeys: [publickeydad] 
    });
    
    wshDescriptor.updatePsbt({ psbt, txHex, vout: utxo[0].vout });
   
    psbt.addOutput({
        deal with: toAddress,
        worth: inputValue - 1000
    });

    descriptors.signers.signBIP32({ psbt, masterNode: descriptors.keyExpressionBIP32({
        masterNode: masterNode,
        originPath: ORIGIN_PATH,
        keyPath: `${KEY_PATH}`
    })});
    

    wshDescriptor.finalizePsbtInput({ index: 0, psbt });
    const spendTx = psbt.extractTransaction();
    const spendTxPushResult = await (
        await fetch(`${EXPLORER}/api/tx`, {
        technique: 'POST',
        physique: spendTx.toHex()
        })
    ).textual content();
    console.log(`Pushing: ${spendTx.toHex()}`);
    console.log(`Tx pushed with outcome: ${spendTxPushResult}`);

    }


}


send_tx()

LEAVE A REPLY

Please enter your comment!
Please enter your name here