PHP WebShell

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

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

import {
  getObjectFields,
  SuiObjectResponse,
  SuiMoveObject,
  SuiObjectInfo,
  SuiObjectData,
  getObjectId,
  getObjectType,
} from '../types/objects';
import { normalizeSuiObjectId, ObjectId, SuiAddress } from '../types/common';

import { getOption, Option } from '../types/option';
import { CoinStruct } from '../types/coin';
import { StructTag } from '../types/sui-bcs';
import { Infer, literal, number, object, string, union } from 'superstruct';

export const SUI_SYSTEM_ADDRESS = '0x3';
export const SUI_FRAMEWORK_ADDRESS = '0x2';
export const MOVE_STDLIB_ADDRESS = '0x1';
export const OBJECT_MODULE_NAME = 'object';
export const UID_STRUCT_NAME = 'UID';
export const ID_STRUCT_NAME = 'ID';
export const SUI_TYPE_ARG = `${SUI_FRAMEWORK_ADDRESS}::sui::SUI`;
export const VALIDATORS_EVENTS_QUERY = '0x3::validator_set::ValidatorEpochInfoEvent';

export const SUI_CLOCK_OBJECT_ID = normalizeSuiObjectId('0x6');

// `sui::pay` module is used for Coin management (split, join, join_and_transfer etc);
export const PAY_MODULE_NAME = 'pay';
export const PAY_SPLIT_COIN_VEC_FUNC_NAME = 'split_vec';
export const PAY_JOIN_COIN_FUNC_NAME = 'join';
export const COIN_TYPE_ARG_REGEX = /^0x2::coin::Coin<(.+)>$/;

type ObjectData = ObjectDataFull | SuiObjectInfo;
type ObjectDataFull = SuiObjectResponse | SuiMoveObject;

export function isObjectDataFull(resp: ObjectData | ObjectDataFull): resp is SuiObjectResponse {
  return !!(resp as SuiObjectResponse).data || !!(resp as SuiMoveObject).type;
}

export const CoinMetadataStruct = object({
  decimals: number(),
  name: string(),
  symbol: string(),
  description: string(),
  iconUrl: union([string(), literal(null)]),
  id: union([ObjectId, literal(null)]),
});

export type CoinMetadata = Infer<typeof CoinMetadataStruct>;

/**
 * Utility class for 0x2::coin
 * as defined in https://github.com/MystenLabs/sui/blob/ca9046fd8b1a9e8634a4b74b0e7dabdc7ea54475/sui_programmability/framework/sources/Coin.move#L4
 */
export class Coin {
  static isCoin(data: ObjectData): boolean {
    return Coin.getType(data)?.match(COIN_TYPE_ARG_REGEX) != null;
  }

  static getCoinType(type: string) {
    const [, res] = type.match(COIN_TYPE_ARG_REGEX) ?? [];
    return res || null;
  }

  static getCoinTypeArg(obj: ObjectData) {
    const type = Coin.getType(obj);
    return type ? Coin.getCoinType(type) : null;
  }

  static isSUI(obj: ObjectData) {
    const arg = Coin.getCoinTypeArg(obj);
    return arg ? Coin.getCoinSymbol(arg) === 'SUI' : false;
  }

  static getCoinSymbol(coinTypeArg: string) {
    return coinTypeArg.substring(coinTypeArg.lastIndexOf(':') + 1);
  }

  static getCoinStructTag(coinTypeArg: string): StructTag {
    return {
      address: normalizeSuiObjectId(coinTypeArg.split('::')[0]),
      module: coinTypeArg.split('::')[1],
      name: coinTypeArg.split('::')[2],
      typeParams: [],
    };
  }

  public static getID(obj: ObjectData): ObjectId {
    if ('fields' in obj) {
      return obj.fields.id.id;
    }
    return getObjectId(obj);
  }

  static totalBalance(coins: CoinStruct[]): bigint {
    return coins.reduce((partialSum, c) => partialSum + Coin.getBalanceFromCoinStruct(c), BigInt(0));
  }

  /**
   * Sort coin by balance in an ascending order
   */
  static sortByBalance(coins: CoinStruct[]): CoinStruct[] {
    return [...coins].sort((a, b) =>
      Coin.getBalanceFromCoinStruct(a) < Coin.getBalanceFromCoinStruct(b)
        ? -1
        : Coin.getBalanceFromCoinStruct(a) > Coin.getBalanceFromCoinStruct(b)
        ? 1
        : 0
    );
  }

  static getBalanceFromCoinStruct(coin: CoinStruct): bigint {
    return BigInt(coin.balance);
  }

  static getBalance(data: ObjectDataFull): bigint | undefined {
    if (!Coin.isCoin(data)) {
      return undefined;
    }
    const balance = getObjectFields(data)?.balance;
    return BigInt(balance);
  }

  private static getType(data: ObjectData): string | undefined {
    if (isObjectDataFull(data)) {
      return getObjectType(data);
    }
    return data.type;
  }
}

export type DelegationData = SuiMoveObject & {
  dataType: 'moveObject';
  type: '0x2::delegation::Delegation';
  fields: {
    active_delegation: Option<number>;
    delegate_amount: number;
    next_reward_unclaimed_epoch: number;
    validator_address: SuiAddress;
    info: {
      id: string;
      version: number;
    };
    coin_locked_until_epoch: Option<SuiMoveObject>;
    ending_epoch: Option<number>;
  };
};

export type DelegationSuiObject = Omit<SuiObjectData, 'data'> & {
  data: DelegationData;
};

// Class for delegation.move
// see https://github.com/MystenLabs/fastnft/blob/161aa27fe7eb8ecf2866ec9eb192e768f25da768/crates/sui-framework/sources/governance/delegation.move
export class Delegation {
  public static readonly SUI_OBJECT_TYPE = '0x2::delegation::Delegation';
  private suiObject: DelegationSuiObject;

  public static isDelegationSuiObject(obj: SuiObjectData): obj is DelegationSuiObject {
    return 'type' in obj && obj.type === Delegation.SUI_OBJECT_TYPE;
  }

  constructor(obj: DelegationSuiObject) {
    this.suiObject = obj;
  }

  public nextRewardUnclaimedEpoch() {
    return this.suiObject.data.fields.next_reward_unclaimed_epoch;
  }

  public activeDelegation() {
    return BigInt(getOption(this.suiObject.data.fields.active_delegation) || 0);
  }

  public delegateAmount() {
    return this.suiObject.data.fields.delegate_amount;
  }

  public endingEpoch() {
    return getOption(this.suiObject.data.fields.ending_epoch);
  }

  public validatorAddress() {
    return this.suiObject.data.fields.validator_address;
  }

  public isActive() {
    return this.activeDelegation() > 0 && !this.endingEpoch();
  }

  public hasUnclaimedRewards(epoch: number) {
    return this.nextRewardUnclaimedEpoch() <= epoch && (this.isActive() || (this.endingEpoch() || 0) > epoch);
  }
}

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


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