P2TR – Earlybirds Invest https://earlybirdsinvest.com Latest Crypto News Fri, 08 Aug 2025 02:51:20 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.8 https://i0.wp.com/earlybirdsinvest.com/wp-content/uploads/2024/12/cropped-New-Project-2024-12-17T235703.455.png?fit=32%2C32&ssl=1 P2TR – Earlybirds Invest https://earlybirdsinvest.com 32 32 240146708 Create a forwarding script using TapRoot address P2TR https://earlybirdsinvest.com/create-a-forwarding-script-using-taproot-address-p2tr/ https://earlybirdsinvest.com/create-a-forwarding-script-using-taproot-address-p2tr/#respond Fri, 08 Aug 2025 02:51:20 +0000 https://earlybirdsinvest.com/create-a-forwarding-script-using-taproot-address-p2tr/

I’m trying to create a transfer script.

The entire script was provided below

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.space/testnet/api";

// Helper function to validate UTXO
function validateUtxo(utxo: any): void {
  if (
    !utxo.txid ||
    typeof utxo.vout !== "number" ||
    typeof utxo.value !== "number"
  ) {
    throw new Error("Invalid UTXO structure");
  }
  if (!/^(a-fA-F0-9){64}$/.test(utxo.txid)) {
    throw new Error("Invalid UTXO txid format");
  }
}

export async function sendBTC_P2TR({
  wif,
  recipient,
  amountSats,
}: {
  wif: string;
  recipient: string;
  amountSats: number;
}): Promise<{ success: boolean; message: string; txId?: string }> {
  try {
    console.log("🏁 Starting transaction process...");

    // Input validation
    if (!wif || !recipient || !amountSats) {
      throw new Error("Missing required parameters");
    }
    if (typeof amountSats !== "number" || amountSats <= 0) {
      throw new Error("Invalid amount");
    }
    if (!recipient.startsWith("tb1p")) {
      throw new Error("Recipient must be a Taproot testnet address");
    }

    // Key derivation
    const keyPair = ECPair.fromWIF(wif, NETWORK);
    if (!keyPair.privateKey) throw new Error("No private key derived from WIF");

    const privateKey = keyPair.privateKey;
    const internalPubkey = Buffer.from(
      tinysecp.pointFromScalar(privateKey, true)!.slice(1)
    );

    const p2tr = bitcoin.payments.p2tr({ internalPubkey, network: NETWORK });
    const address = p2tr.address!;
    const scriptPubKey = p2tr.output!;

    console.log("📬 Sender Taproot address:", address);

    // Fetch UTXOs
    const { data: utxos } = await axios.get(
      `${MEMPOOL_API}/address/${address}/utxo`
    );
    if (!utxos.length) return { success: false, message: "No UTXOs found" };

    // Estimate fee
    const { data: fees } = await axios.get(
      `${MEMPOOL_API}/v1/fees/recommended`
    );
    const feeRate = Math.max(fees.hourFee || 1, 2);
    const fee = Math.ceil(feeRate * 110); // Estimated vsize for P2TR

    // Select UTXO
    const utxo = utxos.find((u: any) => u.value >= amountSats + fee);
    if (!utxo)
      return {
        success: false,
        message: `No suitable UTXO found (needed ${amountSats + fee} sats)`,
      };

    // Key tweaking
    const tweak = bitcoin.crypto.taggedHash("TapTweak", internalPubkey);
    let tweakedPrivKey = tinysecp.privateAdd(privateKey, tweak);
    if (!tweakedPrivKey) throw new Error("Failed to tweak private key");

    // Build PSBT
    const psbt = new bitcoin.Psbt({ network: NETWORK });
    psbt.addInput({
      hash: utxo.txid,
      index: utxo.vout,
      witnessUtxo: { script: scriptPubKey, value: utxo.value },
      tapInternalKey: internalPubkey,
    });

    psbt.addOutput({ address: recipient, value: amountSats });
    const change = utxo.value - amountSats - fee;
    if (change > 294) {
      // Dust limit
      psbt.addOutput({ address, value: change });
    }

    // Signing (fixed approach)
    const tx = (psbt as any).__CACHE.__TX as bitcoin.Transaction;
    const hash = tx.hashForWitnessV1(0, (scriptPubKey), (utxo.value), 0x00);
    const signature = Buffer.from(tinysecp.signSchnorr(hash, tweakedPrivKey));

    // Update with proper signature format
    psbt.updateInput(0, {
      tapKeySig: signature,
    });

    // Final 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 { data: txId } = await axios.post(`${MEMPOOL_API}/tx`, txHex, {
      headers: { "Content-Type": "text/plain" },
    });

    return { success: true, message: "Transaction broadcasted", txId };
  } catch (error: any) {
    console.error("Transaction failed:", error.message);
    return {
      success: false,
      message: error?.response?.data || error?.message || "Unknown error",
    };
  }
}

However, I’m facing an error that I can’t understand why

Transaction failed: Request failed with status code 400
❌ Transaction failed: sendrawtransaction RPC error: {"code":-26,"message":"mandatory-script-verify-flag-failed (Invalid Schnorr signature)"}

]]>
https://earlybirdsinvest.com/create-a-forwarding-script-using-taproot-address-p2tr/feed/ 0 52071
Is it possible to create a multi-party calculation (MPC) P2TR custom spending script? https://earlybirdsinvest.com/is-it-possible-to-create-a-multi-party-calculation-mpc-p2tr-custom-spending-script/ https://earlybirdsinvest.com/is-it-possible-to-create-a-multi-party-calculation-mpc-p2tr-custom-spending-script/#respond Thu, 10 Apr 2025 12:21:43 +0000 https://earlybirdsinvest.com/is-it-possible-to-create-a-multi-party-calculation-mpc-p2tr-custom-spending-script/

I’m working on designing custom spending scripts UTXO I use A P2TR (Pay-to-Taproot) Output. Expense terms require signatures from a multi-party calculation (MPC) wallet that is verified upon spending. In my research I found OP_CHECKMULTISIGsupports multi-sig wallets, but my use cases are different as I specifically aim to integrate MPC wallet signature checks within Taproot scripts rather than standard multi-sig setups.

Can you provide guidance or examples on how to implement this in a P2TR script? Are there specific opcodes, unique features (such as Schnorr Signatures or Script Leaves), or are there any techniques to explore to achieve this custom spending term?

]]>
https://earlybirdsinvest.com/is-it-possible-to-create-a-multi-party-calculation-mpc-p2tr-custom-spending-script/feed/ 0 30058