PHP WebShell

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

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

import {
  AccountAddress,
  AuthenticationKey,
  Deserializer,
  Ed25519PublicKey,
  EntryFunctionArgument,
  Hex,
  SignedTransaction,
  TransactionPayload,
  TransactionPayloadEntryFunction,
  U64,
} from '@aptos-labs/ts-sdk';
import {
  BaseUtils,
  InvalidTransactionError,
  isValidEd25519PublicKey,
  isValidEd25519SecretKey,
  TransactionRecipient,
  TransactionType,
} from '@bitgo/sdk-core';
import {
  APT_ADDRESS_LENGTH,
  APT_BLOCK_ID_LENGTH,
  APT_SIGNATURE_LENGTH,
  APT_TRANSACTION_ID_LENGTH,
  COIN_BATCH_TRANSFER_FUNCTION,
  COIN_TRANSFER_FUNCTION,
  DIGITAL_ASSET_TRANSFER_FUNCTION,
  FUNGIBLE_ASSET_TRANSFER_FUNCTION,
  SECONDS_PER_WEEK,
  ADDRESS_BYTES_LENGTH,
  AMOUNT_BYTES_LENGTH,
  FUNGIBLE_ASSET_BATCH_TRANSFER_FUNCTION,
} from './constants';
import BigNumber from 'bignumber.js';
import { RecipientsValidationResult } from './iface';

export class Utils implements BaseUtils {
  /** @inheritdoc */
  isValidAddress(address: string): boolean {
    return this.isValidHex(address, APT_ADDRESS_LENGTH);
  }

  /** @inheritdoc */
  isValidBlockId(hash: string): boolean {
    return this.isValidHex(hash, APT_BLOCK_ID_LENGTH);
  }

  /** @inheritdoc */
  isValidPrivateKey(key: string): boolean {
    return isValidEd25519SecretKey(key);
  }

  /** @inheritdoc */
  isValidPublicKey(key: string): boolean {
    return isValidEd25519PublicKey(key);
  }

  /** @inheritdoc */
  isValidSignature(signature: string): boolean {
    return this.isValidHex(signature, APT_SIGNATURE_LENGTH);
  }

  /** @inheritdoc */
  isValidTransactionId(txId: string): boolean {
    return this.isValidHex(txId, APT_TRANSACTION_ID_LENGTH);
  }

  isValidHex(value: string, length: number): boolean {
    const regex = new RegExp(`^(0x|0X)[a-fA-F0-9]{${length}}$`);
    return regex.test(value);
  }

  getAddressFromPublicKey(publicKey: string): string {
    const aptosPublicKey = new Ed25519PublicKey(Buffer.from(publicKey, 'hex'));
    const authKey = AuthenticationKey.fromPublicKey({ publicKey: aptosPublicKey });
    const accountAddress = authKey.derivedAddress();
    return accountAddress.toString();
  }

  getTransactionTypeFromTransactionPayload(payload: TransactionPayload): TransactionType {
    if (!(payload instanceof TransactionPayloadEntryFunction)) {
      throw new Error('Invalid Payload: Expected TransactionPayloadEntryFunction');
    }
    const entryFunction = payload.entryFunction;
    const moduleAddress = entryFunction.module_name.address.toString();
    const moduleIdentifier = entryFunction.module_name.name.identifier;
    const functionIdentifier = entryFunction.function_name.identifier;
    const uniqueIdentifier = `${moduleAddress}::${moduleIdentifier}::${functionIdentifier}`;
    switch (uniqueIdentifier) {
      case COIN_TRANSFER_FUNCTION:
      case COIN_BATCH_TRANSFER_FUNCTION:
        return TransactionType.Send;
      case FUNGIBLE_ASSET_TRANSFER_FUNCTION:
      case FUNGIBLE_ASSET_BATCH_TRANSFER_FUNCTION:
        return TransactionType.SendToken;
      case DIGITAL_ASSET_TRANSFER_FUNCTION:
        return TransactionType.SendNFT;
      default:
        throw new InvalidTransactionError(`Invalid transaction: unable to fetch transaction type ${moduleIdentifier}`);
    }
  }

  fetchAndValidateRecipients(
    addressArg: EntryFunctionArgument,
    amountArg: EntryFunctionArgument
  ): RecipientsValidationResult {
    const addressBytes = addressArg.bcsToBytes();
    const amountBytes = amountArg.bcsToBytes();
    let deserializedAddresses: string[];
    let deserializedAmounts: Uint8Array<ArrayBuffer>[];
    if (addressBytes.length > ADDRESS_BYTES_LENGTH || amountBytes.length > AMOUNT_BYTES_LENGTH) {
      deserializedAddresses = utils.deserializeAccountAddressVector(addressBytes);
      deserializedAmounts = utils.deserializeU64Vector(amountBytes);
      if (deserializedAddresses.length !== deserializedAmounts.length) {
        console.error('invalid payload entry function arguments : addresses and amounts length mismatch');
        return { recipients: { deserializedAddresses: [], deserializedAmounts: [] }, isValid: false };
      }
    } else {
      deserializedAddresses = [addressArg.toString()];
      deserializedAmounts = [amountBytes];
    }
    const allAddressesValid = deserializedAddresses.every((address) => utils.isValidAddress(address.toString()));
    const allAmountsValid = deserializedAmounts.every((amount) =>
      new BigNumber(utils.getAmountFromPayloadArgs(amount)).isGreaterThan(0)
    );
    return {
      recipients: { deserializedAddresses, deserializedAmounts },
      isValid: allAddressesValid && allAmountsValid,
    };
  }

  parseRecipients(addressArg: EntryFunctionArgument, amountArg: EntryFunctionArgument): TransactionRecipient[] {
    const { recipients, isValid } = utils.fetchAndValidateRecipients(addressArg, amountArg);
    if (!isValid) {
      throw new InvalidTransactionError('Invalid transaction recipients');
    }
    return recipients.deserializedAddresses.map((address, index) => ({
      address,
      amount: utils.getAmountFromPayloadArgs(recipients.deserializedAmounts[index]),
    })) as TransactionRecipient[];
  }

  deserializeSignedTransaction(rawTransaction: string): SignedTransaction {
    const txnBytes = Hex.fromHexString(rawTransaction).toUint8Array();
    const deserializer = new Deserializer(txnBytes);
    return deserializer.deserialize(SignedTransaction);
  }

  deserializeAccountAddressVector(serializedBytes: Uint8Array): string[] {
    const deserializer = new Deserializer(serializedBytes);
    const deserializedAddresses = deserializer.deserializeVector(AccountAddress);
    return deserializedAddresses.map((address) => address.toString());
  }

  deserializeU64Vector(serializedBytes: Uint8Array): Uint8Array[] {
    const deserializer = new Deserializer(serializedBytes);
    const deserializedAmounts = deserializer.deserializeVector(U64);
    return deserializedAmounts.map((amount) => amount.bcsToBytes());
  }

  getBufferFromHexString(hexString: string): Buffer {
    return Buffer.from(Hex.fromHexString(hexString).toUint8Array());
  }

  castToNumber(value: bigint): number {
    return new BigNumber(value.toString()).toNumber();
  }

  /**
   * Strip hex prefix
   * @param str
   * @returns hex string without 0x prefix
   */
  stripHexPrefix(str: string): string {
    return str.replace(/^0x/i, '');
  }

  getAmountFromPayloadArgs(amountArg: Uint8Array): string {
    const amountBuffer = Buffer.from(amountArg);
    const low = BigInt(amountBuffer.readUint32LE());
    const high = BigInt(amountBuffer.readUint32LE(4));
    const amount = (high << BigInt(32)) + low;
    return amount.toString();
  }

  /**
   * Returns the Aptos transaction expiration timestamp in seconds.
   * It is set to 1 week from now.
   */
  getTxnExpirationTimestamp(): number {
    return Math.floor(Date.now() / 1e3) + SECONDS_PER_WEEK;
  }
}

const utils = new Utils();

export default utils;

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


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