@layerzerolabs/lz-sui-sdk-v2
Version:
246 lines (223 loc) • 8.39 kB
text/typescript
import { bcs } from '@mysten/sui/bcs'
import { SuiClient } from '@mysten/sui/client'
import { Transaction, TransactionArgument, TransactionResult } from '@mysten/sui/transactions'
import { asObject, executeSimulate } from '../utils'
const DEFAULT_MODULE_NAME = 'call'
export const CallErrorCode = {
// Call related errors (matching call.move)
Call_ECallNotActive: 1,
Call_ECallNotCompleted: 2,
Call_ECallNotCreating: 3,
Call_ECallNotRoot: 4,
Call_ECallNotWaiting: 5,
Call_EInvalidChild: 6,
Call_EInvalidNonce: 7,
Call_EInvalidParent: 8,
Call_EParameterNotMutable: 9,
Call_EUnauthorized: 10,
// CallCap related errors (matching call_cap.move)
CallCap_EBadWitness: 1,
// MultiCall related errors (matching dynamic-call/multi-call/multi_call.move)
MultiCall_ENoMoreCalls: 1,
MultiCall_EUnauthorized: 2,
} as const
export class Call {
public packageId: string
public readonly client: SuiClient
constructor(packageId: string, client: SuiClient) {
this.packageId = packageId
this.client = client
}
// === Set function ===
/**
* Create a new CallCap for a user (direct interaction)
* Creates a user-based CallCap that uses its own UID as the identifier
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the new individual CallCap
*/
newIndividualCapMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('new_individual_cap', 'call_cap'),
arguments: [],
})
}
/**
* Create a void result for calls with no meaningful return value
* @param tx - The transaction to add the move call to
* @returns Transaction result containing a void result
*/
voidMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('void'),
arguments: [],
})
}
// === View function ===
/**
* Get the result from a call
* @param tx - The transaction to add the move call to
* @param paramType - The parameter type for the call
* @param resultType - The result type for the call
* @param call - The call transaction result or transaction argument
* @returns Transaction result containing the call result
*/
resultMoveCall(
tx: Transaction,
paramType: string,
resultType: string,
call: TransactionArgument
): TransactionResult {
return tx.moveCall({
target: this.#target('result'),
typeArguments: [paramType, resultType],
arguments: [call],
})
}
/**
* Get the recipient from a call
* @param tx - The transaction to add the move call to
* @param paramType - The parameter type for the call
* @param resultType - The result type for the call
* @param call - The call transaction result or transaction argument
* @returns Transaction result containing the call recipient
*/
recipientMoveCall(
tx: Transaction,
paramType: string,
resultType: string,
call: TransactionArgument
): TransactionResult {
return tx.moveCall({
target: this.#target('recipient'),
typeArguments: [paramType, resultType],
arguments: [call],
})
}
/**
* Get the unique identifier for a CallCap
* Returns the appropriate identifier based on the source type
* @param tx - The transaction to add the move call to
* @param callCap - The CallCap object ID or transaction argument
* @returns Transaction result containing the CallCap identifier
*/
callCapIdMoveCall(tx: Transaction, callCap: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('id', 'call_cap'),
arguments: [asObject(tx, callCap)],
})
}
/**
* Get the unique identifier for a CallCap
* Returns the appropriate identifier based on the source type
* @param callCap - The CallCap object ID
* @returns Promise resolving to the CallCap identifier as a string
*/
async getCallCapId(callCap: string): Promise<string> {
return executeSimulate(
this.client,
(tx) => {
this.callCapIdMoveCall(tx, callCap)
},
(result) => bcs.Address.parse(result[0].value)
)
}
/**
* Check if this is an Individual CallCap
* @param tx - The transaction to add the move call to
* @param callCap - The CallCap object ID or transaction argument
* @returns Transaction result containing a boolean indicating if it's an Individual CallCap
*/
isIndividualCapMoveCall(tx: Transaction, callCap: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_individual', 'call_cap'),
arguments: [asObject(tx, callCap)],
})
}
/**
* Check if this is an Individual CallCap
* @param callCap - The CallCap object ID
* @returns Promise resolving to true if it's an Individual CallCap
*/
async isIndividualCap(callCap: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isIndividualCapMoveCall(tx, callCap)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Check if this is a Package CallCap
* @param tx - The transaction to add the move call to
* @param callCap - The CallCap object ID or transaction argument
* @returns Transaction result containing a boolean indicating if it's a Package CallCap
*/
isPackageCapMoveCall(tx: Transaction, callCap: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_package', 'call_cap'),
arguments: [asObject(tx, callCap)],
})
}
/**
* Check if this is a Package CallCap
* @param callCap - The CallCap object ID
* @returns Promise resolving to true if it's a Package CallCap
*/
async isPackageCap(callCap: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isPackageCapMoveCall(tx, callCap)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Get the package address for a Package CallCap
* Returns None if this is a User CallCap
* @param tx - The transaction to add the move call to
* @param callCap - The CallCap object ID or transaction argument
* @returns Transaction result containing the package address option
*/
packageAddressMoveCall(tx: Transaction, callCap: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('package_address', 'call_cap'),
arguments: [asObject(tx, callCap)],
})
}
/**
* Get the package address for a Package CallCap
* Returns null if this is an Individual CallCap
* @param callCap - The CallCap object ID
* @returns Promise resolving to the package address or null if Individual CallCap
*/
async getPackageAddress(callCap: string): Promise<string | null> {
return executeSimulate(
this.client,
(tx) => {
this.packageAddressMoveCall(tx, callCap)
},
(result) => {
try {
// Try to parse as Option<address>
const option = bcs.option(bcs.Address).parse(result[0].value)
return option ?? null
} catch {
// If parsing fails, it might be None
return null
}
}
)
}
/**
* Generate the full target path for move calls
* @param name - The function name to call
* @param module_name - The module name (defaults to DEFAULT_MODULE_NAME)
* @returns The full module path for the move call
* @private
*/
#target(name: string, module_name = DEFAULT_MODULE_NAME): string {
return `${this.packageId}::${module_name}::${name}`
}
}