Viewing File: /home/ubuntu/efiexchange-node-base/src/controllers/bitcoin/bitcoin.node.controller.ts

import * as bitcoin from "bitcoinjs-lib";
import fetch from "node-fetch";
import { nodeRpcCall } from "./rpc.connector";
import { result } from "lodash";

const getNetwork = (networkType: "mainnet" | "testnet") => {
  return networkType === "mainnet"
    ? bitcoin.networks.bitcoin
    : bitcoin.networks.testnet;
};

export const callBitcoinRPC = async (
    method: string,
    params: any[] = [],
  ): Promise<any> => {

    const rpcUser = 'admin';
    const rpcPassword = 'zzwQciHp6i+7Sq';
    const rpcPort = 18332; // Change to 18332 for testnet
    const rpcHost = '158.69.48.203';
  
    const response = await fetch(`http://${rpcHost}:${rpcPort}/wallet/testwallet`, {
      method: 'POST',
      headers: {
        'Content-Type': 'text/plain',
        Authorization:
          'Basic ' + Buffer.from(`${rpcUser}:${rpcPassword}`).toString('base64'),
      },
      body: JSON.stringify({
        jsonrpc: '1.0',
        id: 'gettx',
        method,
        params,
      }),
    });
  
    const data = await response.json();
  
    if (!response.ok || data.error) {
      throw new Error(data.error?.message || 'RPC Error');
    }
  
    return data.result;
  };
  

export const getNodeTransactions = async (req: any, res: any) => {
  try {
    let inputs = req.body;

    if (!inputs.transaction_hash) {
      return res.sendError("User Id is required");
    }

    let { transaction_hash } = inputs;  
    const result = await callBitcoinRPC('gettransaction', [transaction_hash]);

    return res.sendResponse(result, "Bitcoin Address generated successfully.");

  } catch (error: any) {
    if (error?.message) {
      return res.sendError(error.message);
    }
  }
};


export const importWatchWallet = async (req: any, res: any) => {
  try {
    let inputs = req.body;

    if (!inputs.address) {
      return res.sendError("Address is required");
    }

    if (!inputs.wallet_name) {
      return res.sendError("Wallet Name is required");
    }

    const data = await nodeRpcCall("importaddress", [inputs.address, inputs.wallet_name, false])
    return res.sendResponse(data, "Import Wallet Successfully.");

  } catch (error: any) {
    if (error?.message) {
      return res.sendError(error.message);
    }
  }
};

export const startWatchWallet = async (req: any, res: any) => {
  try {
    let inputs = req.body;

    if (!inputs.address) {
      return res.sendError("Address is required");
    }

    if (!inputs.wallet_name) {
      return res.sendError("Wallet Name is required");
    }

    const data = await nodeRpcCall("listtransactions", [inputs.wallet_name, 10, 0, true])
    return res.sendResponse({
      ...data,
      result: data?.result ? data.result.reverse() : [],
    }, "Wallet Details fetched successfully.");

  } catch (error: any) {
    if (error?.message) {
      return res.sendError(error.message);
    }
  }
};

export const fetchTransactionDetails = async (req: any, res: any) => {
  try {
    const { transaction_hash, block_hash, wallet_address } = req.body;

    if (!transaction_hash) return res.sendError("Transaction Hash is required");
    if (!block_hash) return res.sendError("Block Hash is required");
    if (!wallet_address) return res.sendError("Wallet Address is required");

    const txResponse = await nodeRpcCall("getrawtransaction", [transaction_hash, true, block_hash]);
    const tx = txResponse.result;

    if (!tx) return res.sendError("Transaction not found");

    // Get receiver address and value
    const output = tx.vout.find((v:any) => (v.scriptPubKey?.address && (v.scriptPubKey?.address === wallet_address)));
    const receiver_wallet_address = output?.scriptPubKey?.address || output?.scriptPubKey?.addresses?.[0] || null;
    const value = output?.value || 0;

    // Extract sender from first vin (if not coinbase)
    let from_wallet_address = null;
    let transactionFee = 0;

    if (tx.vin[0]?.txid) {
      const inputTxid = tx.vin[0].txid;
      const voutIndex = tx.vin[0].vout;
      const inputTxResponse = await nodeRpcCall("getrawtransaction", [inputTxid, true]);
      const inputTx = inputTxResponse.result;
      const inputOutput = inputTx?.vout?.[voutIndex];

      from_wallet_address = inputOutput?.scriptPubKey?.address || inputOutput?.scriptPubKey?.addresses?.[0] || null;

      const inputValue = inputOutput?.value || 0;
      const outputSum = tx.vout.reduce((sum:any, v:any) => sum + (v.value || 0), 0);
      transactionFee = inputValue - outputSum;
    }

    const status = tx.confirmations > 0 ? "confirmed" : "pending";
    const explorer_url = `https://mempool.space/tx/${tx.txid}`;

    const responseData = {
      transactionReponse: tx,
      transReceipt: tx.blockhash || null,
      value,
      transaction_fee: transactionFee,
      explorer_url,
      token_value: value,
      from_wallet_address,
      receiver_wallet_address,
      status,
    };

    return res.sendResponse(responseData, "Transaction Details fetched successfully.");
  } catch (error: any) {
    return res.sendError(error?.message || "Failed to fetch transaction details");
  }
};






Back to Directory File Manager