PHP WebShell

Текущая директория: /opt/BitGoJS/modules/utxo-bin/src

Просмотр файла: fetch.ts

import * as fs from 'fs';
import * as process from 'process';
import { promisify } from 'util';

import * as utxolib from '@bitgo/utxo-lib';
import * as blockapis from '@bitgo/blockapis';
import { BaseHttpClient, CachingHttpClient, getTransactionIdsAtHeight, HttpClient } from '@bitgo/blockapis';
import { coins, UtxoCoin } from '@bitgo/statics';

import { ParserTx } from './ParserTx';

function getTxOutPoints(tx: ParserTx): utxolib.bitgo.TxOutPoint[] {
  if (tx instanceof utxolib.bitgo.UtxoTransaction) {
    return tx.ins.map((i) => utxolib.bitgo.getOutputIdForInput(i));
  } else {
    return tx.txInputs.map((i) => utxolib.bitgo.getOutputIdForInput(i));
  }
}

function getCoinName(network: utxolib.Network): string {
  const networkName = utxolib.getNetworkName(network);

  // the bitcoincash network actually has two coins: bch and bcha - hardcode bch by default here
  switch (networkName) {
    case 'bitcoincash':
      return 'bch';
    case 'bitcoincashTestnet':
      return 'tbch';
  }

  const matches = [...coins].flatMap(([, coin]) =>
    coin instanceof UtxoCoin && coin.network.utxolibName === networkName ? [coin.name] : []
  );
  switch (matches.length) {
    case 0:
      throw new Error(`no coin for network ${networkName}`);
    case 1:
      return matches[0];
    default:
      throw new Error(`more than one coin for ${networkName}: ${matches}`);
  }
}

function getApi(httpClient: HttpClient, network: utxolib.Network): blockapis.UtxoApi {
  const coinName = getCoinName(network);
  switch (coinName) {
    case 'btc':
    case 'tbtc':
      return blockapis.BlockstreamApi.forCoin(coinName, { httpClient });
    default:
      return blockapis.BlockchairApi.forCoin(coinName, { httpClient });
  }
}

export async function fetchTransactionHex(
  httpClient: HttpClient,
  location: {
    txid?: string;
    blockHeight?: number;
    txIndex?: number;
  },
  network: utxolib.Network
): Promise<string> {
  location = Object.fromEntries(Object.entries(location).filter(([k, v]) => v !== undefined));

  if (location.blockHeight !== undefined && location.txIndex !== undefined) {
    const api = getApi(httpClient, network);
    if (api instanceof blockapis.BlockstreamApi) {
      const txids = await getTransactionIdsAtHeight(api, location.blockHeight);
      const txid = txids[location.txIndex];
      if (!txid) {
        throw new Error(`no tx at height ${location.blockHeight} position ${location.txIndex}`);
      }
      return fetchTransactionHex(httpClient, { txid }, network);
    }
    throw new Error(`cannot use api ${api.constructor.name} to fetch tx by height`);
  }

  if (location.txid) {
    if (Object.keys(location).length > 1) {
      throw new Error(`cannot specify both txid and ${Object.keys(location)}`);
    }
    return await getApi(httpClient, network).getTransactionHex(location.txid);
  }

  throw new Error(`invalid location: ${JSON.stringify(location)}`);
}

export async function fetchTransactionStatus(
  httpClient: HttpClient,
  txid: string,
  network: utxolib.Network
): Promise<blockapis.TransactionStatus> {
  return await getApi(httpClient, network).getTransactionStatus(txid);
}

export async function fetchPrevOutputs(httpClient: HttpClient, tx: ParserTx): Promise<utxolib.TxOutput<bigint>[]> {
  return (await blockapis.fetchInputs(getTxOutPoints(tx), getApi(httpClient, tx.network), tx.network)).map((v) => ({
    ...v,
    value: BigInt(v.value),
  }));
}

export async function fetchPrevOutputSpends(
  httpClient: HttpClient,
  tx: utxolib.bitgo.UtxoTransaction<bigint> | utxolib.bitgo.UtxoPsbt
): Promise<blockapis.OutputSpend[]> {
  return await blockapis.fetchTransactionSpends(getTxOutPoints(tx), getApi(httpClient, tx.network));
}

export async function fetchOutputSpends(
  httpClient: HttpClient,
  tx: utxolib.bitgo.UtxoTransaction<bigint>
): Promise<blockapis.OutputSpend[]> {
  try {
    return await getApi(httpClient, tx.network).getTransactionSpends(tx.getId());
  } catch (e) {
    console.error(`error fetching spends for tx ${tx.getId()}: ${e}`);
    return [];
  }
}

export async function getClient({ cache }: { cache: boolean }): Promise<HttpClient> {
  if (cache) {
    const mkdir = promisify(fs.mkdir);
    const dir = `${process.env.HOME}/.cache/utxo-bin/`;
    await mkdir(dir, { recursive: true });
    return new CachingHttpClient(dir);
  }
  return new BaseHttpClient();
}

Выполнить команду


Для локальной разработки. Не используйте в интернете!