bitcoinjs / bitcoinjs-lib

A javascript Bitcoin library for node.js and browsers.
MIT License
5.72k stars 2.11k forks source link

Getting error: No inputs were signed, while transferring BTC from my wallet to any other wallet #2146

Closed arunMtDev closed 3 months ago

arunMtDev commented 3 months ago
import * as bitcoin from "bitcoinjs-lib";
import * as ecc from "tiny-secp256k1";
import { ECPairFactory, ECPairInterface } from "ecpair";
import mempoolJS from "@mempool/mempool.js";

const ECPair = ECPairFactory(ecc);

const network = bitcoin.networks.testnet;

const estimateTransactionSize = (
  numInputs: number,
  numOutputs: number
): number => {
  return numInputs * 148 + numOutputs * 34 + 10;
};

const calculateFee = (
  feeRate: number,
  numInputs: number,
  numOutputs: number
): number => {
  const txSize = estimateTransactionSize(numInputs, numOutputs);
  return feeRate * txSize;
};

export const sendBTC = async (
  privateKey: string,     // my private keys
  toAddress: string,
  amount: number      // amount in BTC
): Promise<{ success: boolean; txHash: string }> => {
  try {
    const {
      bitcoin: { addresses, transactions, fees },
    } = mempoolJS({
      hostname: "mempool.space",
      network: "testnet",
    });

    const keyPair: ECPairInterface = ECPair.fromPrivateKey(
      Buffer.from(privateKey, "hex")
    );

    const p2wpkh = bitcoin.payments.p2wpkh({
      pubkey: keyPair.publicKey,
      network,
    });

    const address: string | undefined = p2wpkh?.address;

    if (!address) {
      return {
        success: false,
        txHash: "",
      };
    }

    const utxos = await addresses.getAddressTxsUtxo({
      address,
    });

    const feesRecommended = await fees.getFeesRecommended();

    let totalSatoshisAvailable = 0;

    utxos.forEach((utxo) => {
      totalSatoshisAvailable += utxo.value;
    });

    const numInputs = utxos.length;
    const numOutputs = 2; // One for the destination, one for change
    const fee = calculateFee(feesRecommended.minimumFee, numInputs, numOutputs);

    const change = totalSatoshisAvailable - amount * 100000000 - fee;

    const psbt = new bitcoin.Psbt({ network: network });

    for (const utxo of utxos) {
      const txHex = await transactions.getTxHex({ txid: utxo.txid });

      psbt.addInput({
        hash: utxo.txid,
        index: utxo.vout,
        nonWitnessUtxo: Buffer.from(txHex, "hex"),
      });
    }

    // Add outputs
    psbt.addOutput({
      address: toAddress,
      value: amount * 100000000,
    });

    if (change > 0) {
      psbt.addOutput({
        address: address!,
        value: change,
      });
    }

    // // Sign inputs
    // utxos.forEach((utxo, index) => {
    //   psbt.signInput(index, keyPair);
    // });

    psbt.signAllInputs(keyPair);

    // Finalize inputs
    psbt.finalizeAllInputs();

    const rawTransaction = psbt.extractTransaction().toHex();
    console.log("Raw transaction:", rawTransaction);

    const txId = await transactions.postTx({ txhex: rawTransaction });
    console.log(txId);

    if (!txId) {
      return {
        success: false,
        txHash: "",
      };
    }

    return {
      success: true,
      txHash: txId.toString(),
    };
  } catch (error) {
    console.log("error while transferring bitcoin", error);
    return {
      success: false,
      txHash: "",
    };
  }
};
jasonandjay commented 3 months ago

the same with @2147