PHP WebShell

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

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

import * as utxolib from '@bitgo/utxo-lib';
import { Dimensions } from '@bitgo/unspents';
import * as bitcoinjslib from 'bitcoinjs-lib';

bitcoinjslib.initEccLib(utxolib.ecc);

/**
 * Build a staking transaction for a wallet that assumes 2-of-3 multisig for the inputs
 *
 * Given the inputs and the staking outputs, we will create the PSBT with the desired fee rate.
 * We always add the change address as the last output.
 *
 * @param rootWalletKeys
 * @param unspents
 * @param createStakingOutputs
 * @param changeAddressInfo
 * @param feeRateSatKB
 * @param network
 */
export function buildFixedWalletStakingPsbt({
  rootWalletKeys,
  unspents,
  outputs,
  changeAddressInfo,
  feeRateSatKB,
  network,
  skipNonWitnessUtxo,
  dustAmount = BigInt(0),
}: {
  rootWalletKeys: utxolib.bitgo.RootWalletKeys;
  unspents: utxolib.bitgo.WalletUnspent<bigint>[];
  outputs: {
    script: Buffer;
    value: bigint;
  }[];
  changeAddressInfo: {
    chain: utxolib.bitgo.ChainCode;
    index: number;
    address: string;
  };
  feeRateSatKB: number;
  network: utxolib.Network;
  skipNonWitnessUtxo?: boolean;
  dustAmount?: bigint;
}): utxolib.bitgo.UtxoPsbt {
  if (feeRateSatKB < 1000) {
    throw new Error('Fee rate must be at least 1 sat/vbyte');
  }
  if (unspents.length === 0 || outputs.length === 0) {
    throw new Error('Must have at least one input and one output');
  }

  // Check the change address info
  const changeScript = utxolib.bitgo.outputScripts.createOutputScript2of3(
    rootWalletKeys.deriveForChainAndIndex(changeAddressInfo.chain, changeAddressInfo.index).publicKeys,
    utxolib.bitgo.scriptTypeForChain(changeAddressInfo.chain),
    network
  ).scriptPubKey;
  if (!changeScript.equals(utxolib.addressFormat.toOutputScriptTryFormats(changeAddressInfo.address, network))) {
    throw new Error('Change address info does not match the derived change script');
  }

  const psbt = utxolib.bitgo.createPsbtForNetwork({ network });
  utxolib.bitgo.addXpubsToPsbt(psbt, rootWalletKeys);

  const inputAmount = unspents.reduce((sum, unspent) => sum + unspent.value, BigInt(0));
  const outputAmount = outputs.reduce((sum, output) => sum + output.value, BigInt(0));

  unspents.forEach((unspent) =>
    utxolib.bitgo.addWalletUnspentToPsbt(psbt, unspent, rootWalletKeys, 'user', 'bitgo', {
      isReplaceableByFee: true,
      skipNonWitnessUtxo,
    })
  );
  outputs.forEach((output) => psbt.addOutput(output));

  const fee = Math.ceil(
    (Dimensions.fromPsbt(psbt)
      .plus(Dimensions.fromOutput({ script: changeScript }))
      .getVSize() *
      feeRateSatKB) /
      1000
  );

  const changeAmount = inputAmount - (outputAmount + BigInt(fee));
  if (changeAmount < BigInt(0)) {
    throw new Error(
      `Input amount ${inputAmount.toString()} cannot cover the staking amount ${outputAmount} and  the fee: ${fee}`
    );
  }

  if (changeAmount > dustAmount) {
    utxolib.bitgo.addWalletOutputToPsbt(
      psbt,
      rootWalletKeys,
      changeAddressInfo.chain,
      changeAddressInfo.index,
      changeAmount
    );
  }

  return psbt;
}

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


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