import { CoinMetadata, SuiClient, SuiObjectData } from '@mysten/sui.js/client'; import { normalizeStructTag } from '@mysten/sui.js/utils'; // CoinHelper is the coin helper to query for coin metadata. export class CoinHelper { private _client: SuiClient; private _queryCache: Map>; private _coinMetaReg: Map; constructor(client: SuiClient) { this._client = client; this._queryCache = new Map(); this._coinMetaReg = new Map(); } async getCoinMeta(coinType: string): Promise { const normalized = normalizeStructTag(coinType); if (this._coinMetaReg.has(normalized)) { return this._coinMetaReg.get(normalized); } if (!this._queryCache.has(normalized)) { this._queryCache.set( normalized, this.queryCoinMeta(normalized).then((meta) => { if (meta) { this._coinMetaReg.set(normalized, meta); } return meta; }), ); } return this._queryCache.get(normalized); } private async queryCoinMeta(coinType: string): Promise { const res = await this._client.getCoinMetadata({ coinType }); return res || undefined; } } // Copied from sui/sdk/typescript/src/framework/framework.ts export const COIN_TYPE_ARG_REGEX = /^0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<(.+)>$/; export class Coin { static isCoin(type: string | undefined | null): boolean { if (!type) { return false; } return normalizeStructTag(type).match(COIN_TYPE_ARG_REGEX) != null; } static getCoinType(type: string) { const [, res] = normalizeStructTag(type).match(COIN_TYPE_ARG_REGEX) ?? []; return res || null; } static getBalance(data: SuiObjectData): bigint | undefined { if (!Coin.isCoin(data.type)) { return undefined; } if (data.content?.dataType !== 'moveObject') { return undefined; } const { balance } = data.content?.fields as any; if (balance === undefined) { return undefined; } return BigInt(balance); } }