import { ECPairFactory, ECPairInterface } from 'ecpair';
import { initEccLib, networks, payments, Psbt, Transaction, address, script, opcodes, crypto, Network } from 'bitcoinjs-lib';
import * as ecc from 'tiny-secp256k1';
import axios from 'axios';
initEccLib(ecc);
const ECPair = ECPairFactory(ecc);
const network = networks.bitcoin
function tweakSigner(signer: ECPairInterface, opts: any = {}): any {
let privateKey: Buffer | undefined = signer.privateKey;
if (!privateKey) {
throw new Error('Private key is required for tweaking signer');
}
const publicKey = toXOnly(signer.publicKey);
const tweakedPrivateKey = ecc.privateAdd(
privateKey,
tapTweakHash(publicKey, opts.tweakHash)
);
if (!tweakedPrivateKey) {
throw new Error('Invalid tweaked private key');
}
return ECPair.fromPrivateKey(Buffer.from(tweakedPrivateKey), {
network: opts.network,
});
}
function tapTweakHash(pubKey: Buffer, h: Buffer | undefined): Buffer {
return crypto.taggedHash(
'TapTweak',
Buffer.concat(h ? [pubKey, h] : [pubKey])
);
}
function toXOnly(pubkey: Buffer): Buffer {
return pubkey.slice(1, 33);
}
async function getUTXOs(address: string) {
const response = await axios.get(`https://mempool-testnet.fractalbitcoin.io/api/address/${address}/utxo`);
const utxos = response.data
let availableUTXO = utxos.filter((k: any) => (k?.status.confirmed && k.value > 546))
availableUTXO = availableUTXO.sort((a: any, b: any) => b.value - a.value);
return availableUTXO;
}
export async function main() {
const private_key = 'L5Pe2yFCjshJrXoJHkXe8xEQofYHXvNKcxGS6XqNiiS7XzETRVPF' // setting private key
const keyPair = ECPair.fromWIF(private_key, network);
const mainWallet = payments.p2tr({
internalPubkey: toXOnly(keyPair.publicKey),
network: network
});
const utxos = await getUTXOs(String(mainWallet.address))
console.log(utxos)
const utxo = utxos[0]
const finalPsbt = new Psbt({ network });
const tweakedSigner = tweakSigner(keyPair, { network });
finalPsbt.addInput({
hash: utxo.txid,
index: utxo.vout,
witnessUtxo: {
script: mainWallet.output!,
value: utxo.value,
},
tapInternalKey: toXOnly(keyPair.publicKey)
});
finalPsbt.addOutput({
address: mainWallet.address!,
value: 10000,
});
finalPsbt.signInput(0, tweakedSigner); // this will get error
}
main();
Then I got error: Error: Can not sign for input #0 with the key 03c3f349586717e8707ef8e0d74
I think the possible reason is utxo
vout is 0
How to fix this? Thanks.
This can online edit : codesandbox online test