PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-coin-avaxp/src/lib

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

import {
  Address,
  utils as AvaxUtils,
  Credential,
  pvmSerial,
  TransferOutput,
  UnsignedTx,
} from '@bitgo-forks/avalanchejs';
import { BaseTransactionBuilderFactory, NotSupported } from '@bitgo/sdk-core';
import { AvalancheNetwork, BaseCoin as CoinConfig } from '@bitgo/statics';
import { Buffer as BufferAvax } from 'avalanche';
import { Tx as EVMTx } from 'avalanche/dist/apis/evm';
import { Tx as PVMTx } from 'avalanche/dist/apis/platformvm';
import { DeprecatedTransactionBuilder } from './deprecatedTransactionBuilder';
import { ExportInCTxBuilder } from './exportInCTxBuilder';
import { ExportTxBuilder } from './exportTxBuilder';
import { ImportInCTxBuilder } from './importInCTxBuilder';
import { ImportTxBuilder } from './importTxBuilder';
import { PermissionlessValidatorTxBuilder } from './permissionlessValidatorTxBuilder';
import { TransactionBuilder } from './transactionBuilder';
import utils from './utils';
import { ValidatorTxBuilder } from './validatorTxBuilder';

export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
  protected recoverSigner = false;
  constructor(_coinConfig: Readonly<CoinConfig>) {
    super(_coinConfig);
  }

  /** @inheritdoc */
  from(raw: string): TransactionBuilder | DeprecatedTransactionBuilder {
    utils.validateRawTransaction(raw);
    let txSource: 'EVM' | 'PVM' = 'PVM';
    let transactionBuilder: TransactionBuilder | DeprecatedTransactionBuilder | undefined = undefined;
    let tx: PVMTx | EVMTx | UnsignedTx;
    const rawNoHex = utils.removeHexPrefix(raw);
    try {
      tx = new PVMTx();
      // could throw an error if a txType doesn't match.
      tx.fromBuffer(BufferAvax.from(rawNoHex, 'hex'));

      if (!utils.isTransactionOf(tx, (this._coinConfig.network as AvalancheNetwork).blockchainID)) {
        throw new Error('It is not a transaction of this platformvm old flow');
      }
    } catch (e) {
      try {
        txSource = 'EVM';
        tx = new EVMTx();
        tx.fromBuffer(BufferAvax.from(rawNoHex, 'hex'));

        if (!utils.isTransactionOf(tx, (this._coinConfig.network as AvalancheNetwork).cChainBlockchainID)) {
          throw new Error('It is not a transaction of this network or C chain EVM');
        }
      } catch (e) {
        try {
          txSource = 'PVM';
          // this should be the last because other PVM functions are still being detected in the new SDK
          const manager = AvaxUtils.getManagerForVM('PVM');
          const [codec, txBytes] = manager.getCodecFromBuffer(AvaxUtils.hexToBuffer(raw));
          const unpackedTx = codec.UnpackPrefix<pvmSerial.AddPermissionlessValidatorTx>(txBytes);
          // A signed transaction includes 4 bytes for the number of credentials as an Int type that is not known by the codec
          // We'll skip those 4 bytes, instead we'll loop until we've parsed all credentials
          // @see https://docs.avax.network/reference/avalanchego/p-chain/txn-format#signed-transaction-example
          const credentials: Credential[] = [];
          let credentialBytes = unpackedTx[1].slice(4);
          let moreCredentials = true;
          do {
            try {
              const [credential, rest] = codec.UnpackPrefix<Credential>(credentialBytes);
              credentials.push(credential);
              credentialBytes = rest;
            } catch (e) {
              moreCredentials = false;
            }
          } while (credentialBytes.length > 0 && moreCredentials);

          const unpacked = codec.UnpackPrefix<pvmSerial.AddPermissionlessValidatorTx>(txBytes);
          const permissionlessValidatorTx = unpacked[0] as pvmSerial.AddPermissionlessValidatorTx;
          const outputs = permissionlessValidatorTx.baseTx.outputs;
          const output = outputs[0].output as TransferOutput;
          if (outputs[0].getAssetId() !== (this._coinConfig.network as AvalancheNetwork).avaxAssetID) {
            throw new Error('The Asset ID of the output does not match the transaction');
          }
          const fromAddresses = output.outputOwners.addrs.map((a) => AvaxUtils.hexToBuffer(a.toHex()));
          const addressMaps = fromAddresses.map((a) => new AvaxUtils.AddressMap([[new Address(a), 0]]));
          tx = new UnsignedTx(unpacked[0], [], new AvaxUtils.AddressMaps(addressMaps), credentials);
        } catch (e) {
          throw new Error(
            `The transaction type is not recognized as an old PVM or old EVM transaction. Additionally, parsing of the new PVM AddPermissionlessValidatorTx type failed: ${e.message}`
          );
        }
      }
    }

    if (txSource === 'PVM') {
      if ((tx as UnsignedTx)?.tx?._type && PermissionlessValidatorTxBuilder.verifyTxType((tx as UnsignedTx).tx._type)) {
        transactionBuilder = this.getPermissionlessValidatorTxBuilder();
        transactionBuilder.initBuilder(tx);
      } else if (ValidatorTxBuilder.verifyTxType((tx as PVMTx).getUnsignedTx().getTransaction())) {
        transactionBuilder = this.getValidatorBuilder();
        transactionBuilder.initBuilder(tx as PVMTx);
      } else if (ExportTxBuilder.verifyTxType((tx as PVMTx).getUnsignedTx().getTransaction())) {
        transactionBuilder = this.getExportBuilder();
        transactionBuilder.initBuilder(tx as PVMTx);
      } else if (ImportTxBuilder.verifyTxType((tx as PVMTx).getUnsignedTx().getTransaction())) {
        transactionBuilder = this.getImportBuilder();
        transactionBuilder.initBuilder(tx as PVMTx);
      }
    } else if (txSource === 'EVM') {
      if (ImportInCTxBuilder.verifyTxType((tx as EVMTx).getUnsignedTx().getTransaction())) {
        transactionBuilder = this.getImportInCBuilder();
        transactionBuilder.initBuilder(tx as EVMTx);
      } else if (ExportInCTxBuilder.verifyTxType((tx as EVMTx).getUnsignedTx().getTransaction())) {
        transactionBuilder = this.getExportInCBuilder();
        transactionBuilder.initBuilder(tx as EVMTx);
      }
    }
    if (transactionBuilder === undefined) {
      throw new NotSupported('Transaction cannot be parsed or has an unsupported transaction type');
    }
    return transactionBuilder;
  }

  /** @inheritdoc */
  getTransferBuilder(): DeprecatedTransactionBuilder {
    throw new NotSupported('Transfer is not supported in P Chain');
  }

  /**
   * Initialize Validator builder
   *
   * @returns {ValidatorTxBuilder} the builder initialized
   */
  getValidatorBuilder(): ValidatorTxBuilder {
    return new ValidatorTxBuilder(this._coinConfig);
  }

  /**
   * Initialize Permissionless Validator builder
   *
   * @returns {PermissionlessValidatorTxBuilder} the builder initialized
   */
  getPermissionlessValidatorTxBuilder(): PermissionlessValidatorTxBuilder {
    return new PermissionlessValidatorTxBuilder(this._coinConfig);
  }

  /**
   * Export Cross chain transfer
   *
   * @returns {ExportTxBuilder} the builder initialized
   */
  getExportBuilder(): ExportTxBuilder {
    return new ExportTxBuilder(this._coinConfig);
  }

  /**
   * Import Cross chain transfer
   *
   * @returns {ImportTxBuilder} the builder initialized
   */
  getImportBuilder(): ImportTxBuilder {
    return new ImportTxBuilder(this._coinConfig);
  }

  /**
   * Import in C chain Cross chain transfer
   *
   * @returns {ImportInCTxBuilder} the builder initialized
   */
  getImportInCBuilder(): ImportInCTxBuilder {
    return new ImportInCTxBuilder(this._coinConfig);
  }

  /**
   * Export in C chain Cross chain transfer
   *
   * @returns {ExportInCTxBuilder} the builder initialized
   */
  getExportInCBuilder(): ExportInCTxBuilder {
    return new ExportInCTxBuilder(this._coinConfig);
  }

  /** @inheritdoc */
  getWalletInitializationBuilder(): DeprecatedTransactionBuilder {
    throw new NotSupported('Wallet initialization is not needed');
  }
}

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


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