Estoy intentando hacer un script de transferencia, para transferir bitcoin desde la dirección a otra
He dado mi script completo a continuación
import * as bitcoin from "bitcoinjs-lib";
import * as tinysecp from "tiny-secp256k1";
import axios from "axios";
import ECPairFactory from "ecpair";
const ECPair = ECPairFactory(tinysecp);
bitcoin.initEccLib(tinysecp);
const NETWORK = bitcoin.networks.testnet;
const MEMPOOL_API = "https://mempool.area/testnet/api";
// Helper perform to validate UTXO
perform validateUtxo(utxo: any): void {
if (
!utxo.txid ||
typeof utxo.vout !== "quantity" ||
typeof utxo.worth !== "quantity"
) {
throw new Error("Invalid UTXO construction");
}
if (!/^(a-fA-F0-9){64}$/.check(utxo.txid)) {
throw new Error("Invalid UTXO txid format");
}
}
export async perform sendBTC_P2TR({
wif,
recipient,
amountSats,
}: {
wif: string;
recipient: string;
amountSats: quantity;
}): Promise<{ success: boolean; message: string; txId?: string }> {
attempt {
console.log("🏁 Beginning transaction course of...");
// Enter validation
if (!wif || !recipient || !amountSats) {
throw new Error("Lacking required parameters");
}
if (typeof amountSats !== "quantity" || amountSats <= 0) {
throw new Error("Invalid quantity");
}
if (!recipient.startsWith("tb1p")) {
throw new Error("Recipient should be a Taproot testnet deal with");
}
// Key derivation
const keyPair = ECPair.fromWIF(wif, NETWORK);
if (!keyPair.privateKey) throw new Error("No non-public key derived from WIF");
const privateKey = keyPair.privateKey;
const internalPubkey = Buffer.from(
tinysecp.pointFromScalar(privateKey, true)!.slice(1)
);
const p2tr = bitcoin.funds.p2tr({ internalPubkey, community: NETWORK });
const deal with = p2tr.deal with!;
const scriptPubKey = p2tr.output!;
console.log("📬 Sender Taproot deal with:", deal with);
// Fetch UTXOs
const { information: utxos } = await axios.get(
`${MEMPOOL_API}/deal with/${deal with}/utxo`
);
if (!utxos.size) return { success: false, message: "No UTXOs discovered" };
// Estimate charge
const { information: charges } = await axios.get(
`${MEMPOOL_API}/v1/charges/really helpful`
);
const feeRate = Math.max(charges.hourFee || 1, 2);
const charge = Math.ceil(feeRate * 110); // Estimated vsize for P2TR
// Choose UTXO
const utxo = utxos.discover((u: any) => u.worth >= amountSats + charge);
if (!utxo)
return {
success: false,
message: `No appropriate UTXO discovered (wanted ${amountSats + charge} sats)`,
};
// Key tweaking
const tweak = bitcoin.crypto.taggedHash("TapTweak", internalPubkey);
let tweakedPrivKey = tinysecp.privateAdd(privateKey, tweak);
if (!tweakedPrivKey) throw new Error("Didn't tweak non-public key");
// Construct PSBT
const psbt = new bitcoin.Psbt({ community: NETWORK });
psbt.addInput({
hash: utxo.txid,
index: utxo.vout,
witnessUtxo: { script: scriptPubKey, worth: utxo.worth },
tapInternalKey: internalPubkey,
});
psbt.addOutput({ deal with: recipient, worth: amountSats });
const change = utxo.worth - amountSats - charge;
if (change > 294) {
// Mud restrict
psbt.addOutput({ deal with, worth: change });
}
// Signing (fastened method)
const tx = (psbt as any).__CACHE.__TX as bitcoin.Transaction;
const hash = tx.hashForWitnessV1(0, (scriptPubKey), (utxo.worth), 0x00);
const signature = Buffer.from(tinysecp.signSchnorr(hash, tweakedPrivKey));
// Replace with correct signature format
psbt.updateInput(0, {
tapKeySig: signature,
});
// Closing verification
const validator = (pubkey: Buffer, msghash: Buffer, sig: Buffer) => {
return tinysecp.verifySchnorr(msghash, pubkey, sig);
};
psbt.validateSignaturesOfInput(0, validator);
psbt.finalizeAllInputs();
const txHex = psbt.extractTransaction().toHex();
// Broadcast
const { information: txId } = await axios.put up(`${MEMPOOL_API}/tx`, txHex, {
headers: { "Content material-Sort": "textual content/plain" },
});
return { success: true, message: "Transaction broadcasted", txId };
} catch (error: any) {
console.error("Transaction failed:", error.message);
return "Unknown error",
;
}
}
Pero me enfrento a un error que no puedo entender por qué
Transaction failed: Request failed with standing code 400
❌ Transaction failed: sendrawtransaction RPC error: {"code":-26,"message":"mandatory-script-verify-flag-failed (Invalid Schnorr signature)"}
Estoy intentando hacer un script de transferencia, para transferir bitcoin desde la dirección a otra
He dado mi script completo a continuación
import * as bitcoin from "bitcoinjs-lib";
import * as tinysecp from "tiny-secp256k1";
import axios from "axios";
import ECPairFactory from "ecpair";
const ECPair = ECPairFactory(tinysecp);
bitcoin.initEccLib(tinysecp);
const NETWORK = bitcoin.networks.testnet;
const MEMPOOL_API = "https://mempool.area/testnet/api";
// Helper perform to validate UTXO
perform validateUtxo(utxo: any): void {
if (
!utxo.txid ||
typeof utxo.vout !== "quantity" ||
typeof utxo.worth !== "quantity"
) {
throw new Error("Invalid UTXO construction");
}
if (!/^(a-fA-F0-9){64}$/.check(utxo.txid)) {
throw new Error("Invalid UTXO txid format");
}
}
export async perform sendBTC_P2TR({
wif,
recipient,
amountSats,
}: {
wif: string;
recipient: string;
amountSats: quantity;
}): Promise<{ success: boolean; message: string; txId?: string }> {
attempt {
console.log("🏁 Beginning transaction course of...");
// Enter validation
if (!wif || !recipient || !amountSats) {
throw new Error("Lacking required parameters");
}
if (typeof amountSats !== "quantity" || amountSats <= 0) {
throw new Error("Invalid quantity");
}
if (!recipient.startsWith("tb1p")) {
throw new Error("Recipient should be a Taproot testnet deal with");
}
// Key derivation
const keyPair = ECPair.fromWIF(wif, NETWORK);
if (!keyPair.privateKey) throw new Error("No non-public key derived from WIF");
const privateKey = keyPair.privateKey;
const internalPubkey = Buffer.from(
tinysecp.pointFromScalar(privateKey, true)!.slice(1)
);
const p2tr = bitcoin.funds.p2tr({ internalPubkey, community: NETWORK });
const deal with = p2tr.deal with!;
const scriptPubKey = p2tr.output!;
console.log("📬 Sender Taproot deal with:", deal with);
// Fetch UTXOs
const { information: utxos } = await axios.get(
`${MEMPOOL_API}/deal with/${deal with}/utxo`
);
if (!utxos.size) return { success: false, message: "No UTXOs discovered" };
// Estimate charge
const { information: charges } = await axios.get(
`${MEMPOOL_API}/v1/charges/really helpful`
);
const feeRate = Math.max(charges.hourFee || 1, 2);
const charge = Math.ceil(feeRate * 110); // Estimated vsize for P2TR
// Choose UTXO
const utxo = utxos.discover((u: any) => u.worth >= amountSats + charge);
if (!utxo)
return {
success: false,
message: `No appropriate UTXO discovered (wanted ${amountSats + charge} sats)`,
};
// Key tweaking
const tweak = bitcoin.crypto.taggedHash("TapTweak", internalPubkey);
let tweakedPrivKey = tinysecp.privateAdd(privateKey, tweak);
if (!tweakedPrivKey) throw new Error("Didn't tweak non-public key");
// Construct PSBT
const psbt = new bitcoin.Psbt({ community: NETWORK });
psbt.addInput({
hash: utxo.txid,
index: utxo.vout,
witnessUtxo: { script: scriptPubKey, worth: utxo.worth },
tapInternalKey: internalPubkey,
});
psbt.addOutput({ deal with: recipient, worth: amountSats });
const change = utxo.worth - amountSats - charge;
if (change > 294) {
// Mud restrict
psbt.addOutput({ deal with, worth: change });
}
// Signing (fastened method)
const tx = (psbt as any).__CACHE.__TX as bitcoin.Transaction;
const hash = tx.hashForWitnessV1(0, (scriptPubKey), (utxo.worth), 0x00);
const signature = Buffer.from(tinysecp.signSchnorr(hash, tweakedPrivKey));
// Replace with correct signature format
psbt.updateInput(0, {
tapKeySig: signature,
});
// Closing verification
const validator = (pubkey: Buffer, msghash: Buffer, sig: Buffer) => {
return tinysecp.verifySchnorr(msghash, pubkey, sig);
};
psbt.validateSignaturesOfInput(0, validator);
psbt.finalizeAllInputs();
const txHex = psbt.extractTransaction().toHex();
// Broadcast
const { information: txId } = await axios.put up(`${MEMPOOL_API}/tx`, txHex, {
headers: { "Content material-Sort": "textual content/plain" },
});
return { success: true, message: "Transaction broadcasted", txId };
} catch (error: any) {
console.error("Transaction failed:", error.message);
return "Unknown error",
;
}
}
Pero me enfrento a un error que no puedo entender por qué
Transaction failed: Request failed with standing code 400
❌ Transaction failed: sendrawtransaction RPC error: {"code":-26,"message":"mandatory-script-verify-flag-failed (Invalid Schnorr signature)"}