@layerzerolabs/lz-sui-sdk-v2
Version:
106 lines (92 loc) • 3.54 kB
text/typescript
import { SuiClient, SuiObjectResponse } from '@mysten/sui/client'
import { MAX_BATCH_SIZE, MoveCall } from '../types'
/**
* Represents a move call with its associated object details
*/
export interface MoveCallWithObjectDetails {
moveCall: MoveCall
objectDetails: Map<string, SuiObjectResponse>
}
/**
* MoveCallObjectFetcher fetches object details for move calls once
* and provides them to validators to avoid multiple API calls
*/
export class MoveCallObjectFetcher {
private client: SuiClient
private batchSize: number
constructor(client: SuiClient, batchSize: number = MAX_BATCH_SIZE) {
this.client = client
this.batchSize = batchSize
}
/**
* Fetches object details for all objects referenced in move calls
* @param moveCalls - Array of move calls to fetch object details for
* @param options - Options for what object data to fetch
* @returns Array of move calls with their associated object details
*/
async fetchObjectDetails(
moveCalls: MoveCall[],
options: {
showOwner?: boolean
showType?: boolean
showContent?: boolean
showBcs?: boolean
showDisplay?: boolean
showStorageRebate?: boolean
} = {}
): Promise<MoveCallWithObjectDetails[]> {
// Extract all unique object IDs from move calls
const objectIdSet = new Set<string>()
for (const moveCall of moveCalls) {
for (const arg of moveCall.arguments) {
if ('Object' in arg) {
objectIdSet.add(arg.Object)
}
}
}
const objectIds = Array.from(objectIdSet)
if (objectIds.length === 0) {
// No objects to fetch, return move calls with empty object details
return moveCalls.map((moveCall) => ({
moveCall,
objectDetails: new Map<string, SuiObjectResponse>(),
}))
}
// Validate batch size
if (this.batchSize > MAX_BATCH_SIZE || this.batchSize < 1) {
throw new Error(`batchSize must be between 1 and ${MAX_BATCH_SIZE}`)
}
// Fetch all objects in batches
const objectDetailsMap = new Map<string, SuiObjectResponse>()
for (let i = 0; i < objectIds.length; i += this.batchSize) {
const batch = objectIds.slice(i, i + this.batchSize)
const objects = await this.client.multiGetObjects({
ids: batch,
options,
})
// Map object responses to their IDs
objects.forEach((object, index) => {
const objectId = batch[index]
objectDetailsMap.set(objectId, object)
})
}
// Create move calls with object details
return moveCalls.map((moveCall) => {
// Get object details for this specific move call
const moveCallObjectDetails = new Map<string, SuiObjectResponse>()
for (const arg of moveCall.arguments) {
if ('Object' in arg) {
const objectId = arg.Object
const objectDetail = objectDetailsMap.get(objectId)
if (objectDetail) {
moveCallObjectDetails.set(objectId, objectDetail)
}
}
}
return {
moveCall,
objectDetails: moveCallObjectDetails,
}
})
}
}