import { CoinStruct, SuiClient } from '@mysten/sui.js/client'; import { NotEnoughBalanceError } from '@/error/NotEnoughBalanceError'; import { SanityError } from '@/error/SanityError'; import { EntryIterator, getAllFromIterator } from '@/sui/iterator/iterator'; import { Requester, PagedData } from '@/sui/iterator/requester'; const DEF_REQ_PAGE_SIZE = 25; export async function getCoinsWithAmount( suiClient: SuiClient, owner: string, requestAmount: bigint, coinType: string = '0x2::sui::SUI', pageSize: number = DEF_REQ_PAGE_SIZE, ) { const it = new OwnedCoinIterator(suiClient, owner, coinType, pageSize); let totalAmount = BigInt(0); const res: CoinStruct[] = []; while ((await it.hasNext()) && totalAmount < requestAmount) { const val = await it.next(); if (!val) { continue; } res.push(val); totalAmount += BigInt(val.balance); } if (totalAmount < requestAmount) { throw new NotEnoughBalanceError(coinType, requestAmount, totalAmount); } return res; } export async function getAllOwnedCoins( suiClient: SuiClient, owner: string, coinType: string = '0x2::sui::SUI', pageSize: number = DEF_REQ_PAGE_SIZE, ) { const iter = new OwnedCoinIterator(suiClient, owner, coinType, pageSize); return (await getAllFromIterator(iter)) as CoinStruct[]; } export class OwnedCoinIterator extends EntryIterator { constructor( private readonly suiClient: SuiClient, private readonly owner: string, private readonly coinType: string, private readonly reqPageSize: number, ) { super(new OwnedCoinRequester(suiClient, owner, coinType, reqPageSize)); } } export class OwnedCoinRequester implements Requester { nextCursor: string | null | undefined; constructor( private readonly suiClient: SuiClient, private readonly owner: string, private readonly coinType: string, private readonly reqPageSize: number, ) { if (reqPageSize <= 0) { throw new SanityError('Invalid reqPageSize'); } } async doNextRequest(): Promise> { const res = await this.suiClient.getCoins({ owner: this.owner, coinType: this.coinType, cursor: this.nextCursor, limit: this.reqPageSize, }); this.nextCursor = res.nextCursor; return { data: res.data, hasNext: res.hasNextPage, }; } }