UNPKG

@layerzerolabs/lz-sui-sdk-v2

Version:

143 lines (126 loc) 5.01 kB
import { bcs } from '@mysten/sui/bcs' import { SuiClient } from '@mysten/sui/client' import { Transaction, TransactionArgument, TransactionResult } from '@mysten/sui/transactions' import { ModuleManager } from '../../module-manager' import { ObjectOptions } from '../../types' import { asAddress, executeSimulate } from '../../utils' const MODULE_NAME = 'package_whitelist_validator' export const ValidatorErrorCode = { // PTB Whitelist related errors EInvalidWitness: 1, } as const export class PackageWhitelistValidator { public packageId: string public readonly client: SuiClient private readonly objects: ObjectOptions constructor( packageId: string, client: SuiClient, objects: ObjectOptions, private readonly moduleManager: ModuleManager ) { this.packageId = packageId this.client = client this.objects = objects } // === Whitelist Management Functions === /** * Add a package to the whitelist using a LayerZero witness * This function is permissionless and allows packages to self-register * by providing a valid LayerZeroWitness type * @param tx - The transaction to add the move call to * @param witness - The LayerZero witness from the package * @template T - The witness type that must be named "_witness::LayerZeroWitness" */ addWhitelistMoveCall(tx: Transaction, witness: TransactionArgument, witnessType: string): void { tx.moveCall({ target: this.#target('add_whitelist'), typeArguments: [witnessType], arguments: [tx.object(this.objects.packageWhitelistValidator), witness], }) } // === View Functions === /** * Check if a package is whitelisted * @param tx - The transaction to add the move call to * @param packageAddress - The package address to check * @returns Transaction result containing the whitelist status */ isWhitelistedMoveCall(tx: Transaction, packageAddress: string | TransactionArgument): TransactionResult { return tx.moveCall({ target: this.#target('is_whitelisted'), arguments: [tx.object(this.objects.packageWhitelistValidator), asAddress(tx, packageAddress)], }) } /** * Validate multiple packages at once * @param tx - The transaction to add the move call to * @param packageAddresses - Array of package addresses to validate * @returns Transaction result containing the validation status */ validateMoveCall(tx: Transaction, packageAddresses: string[]): TransactionResult { return tx.moveCall({ target: this.#target('validate'), arguments: [ tx.object(this.objects.packageWhitelistValidator), tx.pure(bcs.vector(bcs.Address).serialize(packageAddresses)), ], }) } /** * Check if a package is whitelisted * @param packageAddress - The package address to check * @returns Promise<boolean> - True if the package is whitelisted */ async isWhitelisted(packageAddress: string): Promise<boolean> { return executeSimulate( this.client, (tx) => { this.isWhitelistedMoveCall(tx, packageAddress) }, (result) => bcs.Bool.parse(result[0].value) ) } // === Utility Functions === /** * Extract package ID from a witness type name * @param witnessTypeName - The full type name of the witness * @returns string | null - The package ID if extraction is successful */ extractPackageFromWitness(witnessTypeName: string): string | null { // Pattern: "0x123abc::my_package_witness::LayerZeroWitness" const parts = witnessTypeName.split('::') if (parts.length >= 3) { const packageId = parts[0] if (packageId.startsWith('0x') && packageId.length > 2) { return packageId } } return null } // === Batch Operations === /** * Validate multiple packages at once using the contract's validate function * @param packageAddresses - Array of package addresses to validate * @returns Promise<boolean> - True if all packages are whitelisted */ async validate(packageAddresses: string[]): Promise<boolean> { return executeSimulate( this.client, (tx) => { this.validateMoveCall(tx, packageAddresses) }, (result) => bcs.Bool.parse(result[0].value) ) } /** * Generate the full target path for move calls * @param name - The function name to call * @param module_name - The module name (defaults to MODULE_NAME) * @returns The full module path for the move call * @private */ #target(name: string, module_name = MODULE_NAME): string { return `${this.packageId}::${module_name}::${name}` } }