UNPKG

@layerzerolabs/lz-sui-sdk-v2

Version:

1,258 lines (1,242 loc) 430 kB
import { bcs } from '@mysten/sui/bcs'; import { Transaction } from '@mysten/sui/transactions'; import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'; import { fromBase64 } from '@mysten/sui/utils'; import sha3 from 'js-sha3'; import { Stage, Chain } from '@layerzerolabs/lz-definitions'; import { createHash } from 'crypto'; var __typeError = (msg) => { throw TypeError(msg); }; var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method); var DvnDstConfigBcs = bcs.struct("DstConfig", { gas: bcs.U256, multiplier_bps: bcs.U16, floor_margin_usd: bcs.U128 }); var TimeoutBcs = bcs.struct("Timeout", { expiry: bcs.U64, fallback_lib: bcs.Address }); var Bytes32Bcs = bcs.struct("Bytes32", { bytes: bcs.vector(bcs.u8()) }); var ExecutorConfigBcs = bcs.struct("ExecutorConfig", { max_message_size: bcs.U64, executor: bcs.Address }); var DstConfigBcs = bcs.struct("DstConfig", { lz_receive_base_gas: bcs.U64, lz_compose_base_gas: bcs.U64, multiplier_bps: bcs.U16, floor_margin_usd: bcs.U128, native_cap: bcs.U128 }); var NativeDropParamsBcs = bcs.struct("NativeDropParams", { receiver: bcs.Address, amount: bcs.U64 }); var MessagingFeeBcs = bcs.struct("MessagingFee", { native_fee: bcs.U64, zro_fee: bcs.U64 }); var FunctionBCS = bcs.struct("Function", { package: bcs.Address, module_name: bcs.string(), name: bcs.string() }); var ArgumentBCS = bcs.enum("Argument", { ID: bcs.vector(bcs.u8()), Object: bcs.Address, Pure: bcs.vector(bcs.u8()), NestedResult: bcs.struct("NestedResult", { call_index: bcs.u16(), result_index: bcs.u16() }) }); var MoveCallBCS = bcs.struct("MoveCall", { function: FunctionBCS, arguments: bcs.vector(ArgumentBCS), type_arguments: bcs.vector(bcs.string()), // TypeName serialized as string is_builder_call: bcs.bool(), result_ids: bcs.vector(bcs.vector(bcs.u8())) }); var VectorMoveCallBCS = bcs.vector(MoveCallBCS); var OAppInfoV1Bcs = bcs.struct("OAppInfoV1", { // Object ID address of the OApp instance oapp_object: bcs.Address, // Used to populate the MoveCalls to fetch the next nonce that can be executed by an executor next_nonce_info: bcs.vector(bcs.u8()), // Used to populate the MoveCalls to execute lz_receive by executor lz_receive_info: bcs.vector(bcs.u8()), // Additional configuration data for custom OApp functionality extra_info: bcs.vector(bcs.u8()) }); var PriceBcs = bcs.struct("Price", { price_ratio: bcs.U128, gas_price_in_unit: bcs.U64, gas_per_byte: bcs.U32 }); var ArbitrumPriceExtBcs = bcs.struct("ArbitrumPriceExt", { gas_per_l2_tx: bcs.U64, gas_per_l1_call_data_byte: bcs.U32 }); var ModelTypeBcs = bcs.enum("ModelType", { DEFAULT: null, ARB_STACK: null, OP_STACK: null }); var UlnConfigBcs = bcs.struct("UlnConfig", { confirmations: bcs.U64, required_dvns: bcs.vector(bcs.Address), optional_dvns: bcs.vector(bcs.Address), optional_dvn_threshold: bcs.U8 }); var OAppUlnConfigBcs = bcs.struct("OAppUlnConfig", { use_default_confirmations: bcs.Bool, use_default_required_dvns: bcs.Bool, use_default_optional_dvns: bcs.Bool, uln_config: UlnConfigBcs }); // src/types/modules.ts var Modules = /* @__PURE__ */ ((Modules2) => { Modules2["Endpoint"] = "endpoint"; Modules2["SimpleMessageLib"] = "simpleMessageLib"; Modules2["BlockedMessageLib"] = "blockedMessageLib"; Modules2["Uln302"] = "uln302"; Modules2["Utils"] = "utils"; Modules2["Zro"] = "zro"; Modules2["Call"] = "call"; Modules2["Treasury"] = "treasury"; Modules2["LayerZeroViews"] = "layerZeroViews"; Modules2["PtbBuilder"] = "ptbBuilder"; Modules2["EndpointPtbBuilder"] = "endpointPtbBuilder"; Modules2["SimpleMessageLibPtbBuilder"] = "simpleMessageLibPtbBuilder"; Modules2["BlockedMessageLibPtbBuilder"] = "blockedMessageLibPtbBuilder"; Modules2["Uln302PtbBuilder"] = "uln302PtbBuilder"; Modules2["Oapp"] = "oapp"; Modules2["Dvn"] = "dvn"; Modules2["DvnFeeLib"] = "dvnFeeLib"; Modules2["DvnLayerZero"] = "dvnLayerZero"; Modules2["Executor"] = "executor"; Modules2["ExecutorFeeLib"] = "executorFeeLib"; Modules2["ExecutorLayerZero"] = "executorLayerZero"; Modules2["PackageWhitelistValidator"] = "packageWhitelistValidator"; Modules2["PriceFeed"] = "priceFeed"; Modules2["Counter"] = "counter"; Modules2["DvnPtbBuilder"] = "dvnPtbBuilder"; Modules2["ExecutorPtbBuilder"] = "executorPtbBuilder"; Modules2["WorkerRegistry"] = "workerRegistry"; return Modules2; })(Modules || {}); // src/types/errors.ts var MoveAbortError = class extends Error { constructor(abortCode, rawMsg) { super(`Move abort with code: ${abortCode}. Raw error message: ${rawMsg}`); this.abortCode = abortCode; } }; var UnclassifiedError = class extends Error { }; // src/types/executor.ts var ExecutorOptionType = { LZRECEIVE: 1, NATIVE_DROP: 2, LZCOMPOSE: 3, ORDERED_EXECUTION: 4 }; var ALL_EXECUTOR_OPTION_TYPES = Object.values(ExecutorOptionType); // src/types/ptb-builder.ts var MAX_BATCH_SIZE = 50; var DEFAULT_SIMULATION_TIMES = 5; // src/types/price-feed.ts var ModelType = /* @__PURE__ */ ((ModelType2) => { ModelType2[ModelType2["DEFAULT"] = 0] = "DEFAULT"; ModelType2[ModelType2["ARB_STACK"] = 1] = "ARB_STACK"; ModelType2[ModelType2["OP_STACK"] = 2] = "OP_STACK"; return ModelType2; })(ModelType || {}); // src/types/message-lib.ts var MessageLibType = /* @__PURE__ */ ((MessageLibType2) => { MessageLibType2[MessageLibType2["Send"] = 0] = "Send"; MessageLibType2[MessageLibType2["Receive"] = 1] = "Receive"; MessageLibType2[MessageLibType2["SendAndReceive"] = 2] = "SendAndReceive"; return MessageLibType2; })(MessageLibType || {}); var CONFIG_TYPE = { EXECUTOR: 1, SEND_ULN: 2, RECEIVE_ULN: 3 }; // src/types/move-types.ts var LzTypeName = /* @__PURE__ */ ((LzTypeName2) => { LzTypeName2["EndpointQuoteParam"] = "EndpointQuoteParam"; LzTypeName2["EndpointSendParam"] = "EndpointSendParam"; LzTypeName2["MessageLibQuoteParam"] = "MessageLibQuoteParam"; LzTypeName2["MessageLibSendParam"] = "MessageLibSendParam"; LzTypeName2["MessageLibSetConfigParam"] = "MessageLibSetConfigParam"; LzTypeName2["MessagingFee"] = "MessagingFee"; LzTypeName2["MessagingReceipt"] = "MessagingReceipt"; LzTypeName2["MoveCall"] = "MoveCall"; LzTypeName2["EndpointLzReceiveParam"] = "EndpointLzReceiveParam"; LzTypeName2["EndpointLzComposeParam"] = "EndpointLzComposeParam"; LzTypeName2["CallVoid"] = "CallVoid"; LzTypeName2["MessageLibSendResult"] = "MessageLibSendResult"; return LzTypeName2; })(LzTypeName || {}); var CallTypeName = /* @__PURE__ */ ((CallTypeName2) => { CallTypeName2["EndpointQuoteCall"] = "EndpointQuoteCall"; CallTypeName2["EndpointSendCall"] = "EndpointSendCall"; CallTypeName2["MessageLibSendCall"] = "MessageLibSendCall"; CallTypeName2["MessageLibQuoteCall"] = "MessageLibQuoteCall"; CallTypeName2["MessageLibSetConfigCall"] = "MessageLibSetConfigCall"; CallTypeName2["EndpointLzReceiveCall"] = "EndpointLzReceiveCall"; CallTypeName2["EndpointLzComposeCall"] = "EndpointLzComposeCall"; return CallTypeName2; })(CallTypeName || {}); // src/types/layerzero-views.ts var EndpointExecutionState = { STATE_NOT_EXECUTABLE: 0, STATE_VERIFIED_BUT_NOT_EXECUTABLE: 1, STATE_EXECUTABLE: 2, STATE_EXECUTED: 3 }; var UlnVerificationState = { STATE_VERIFYING: 0, STATE_VERIFIABLE: 1, STATE_VERIFIED: 2, STATE_NOT_INITIALIZABLE: 3 }; // src/types/endpoint.ts var OAppInfoVersion = { VERSION_1: 1, VERSION_2: 2 }; var LzReceiveVersion = { VERSION_1: 1 }; var LzComposeVersion = { VERSION_1: 1 }; function isTransactionArgument(value) { if (typeof value === "function") { return true; } if (value !== null && typeof value === "object" && "$kind" in value) { const obj = value; return obj.$kind === "GasCoin" || obj.$kind === "Input" || obj.$kind === "Result" || obj.$kind === "NestedResult"; } return false; } function asArg(value, converter) { if (isTransactionArgument(value)) { return value; } return converter(value); } function asArgWithTx(tx, value, converter) { if (isTransactionArgument(value)) { return value; } return converter(tx, value); } async function asArgWithTxAsync(tx, value, converter) { if (isTransactionArgument(value)) { return value; } return converter(tx, value); } function asObject(tx, value) { return asArg(value, (val) => tx.object(val)); } function asAddress(tx, value) { return asArg(value, (val) => tx.pure.address(val)); } function asU8(tx, value) { return asArg(value, (val) => tx.pure.u8(val)); } function asU16(tx, value) { return asArg(value, (val) => tx.pure.u16(val)); } function asU32(tx, value) { return asArg(value, (val) => tx.pure.u32(val)); } function asU64(tx, value) { return asArg(value, (val) => tx.pure.u64(val)); } function asU128(tx, value) { return asArg(value, (val) => tx.pure.u128(val)); } function asU256(tx, value) { return asArg(value, (val) => tx.pure.u256(val)); } function asBytes32(tx, value, utils) { return asArgWithTx(tx, value, (tx2, bytes) => utils.fromBytesMoveCall(tx2, bytes)); } function asBytes(tx, value) { return asArg(value, (val) => tx.pure(bcs.vector(bcs.u8()).serialize(val))); } function asBytesVector(tx, value) { return asArg(value, (val) => tx.pure(bcs.vector(bcs.vector(bcs.u8())).serialize(val))); } function asString(tx, value) { return asArg(value, (val) => tx.pure.string(val)); } function asAddressVector(tx, value) { return asArg(value, (val) => tx.pure(bcs.vector(bcs.Address).serialize(val))); } function asBool(tx, value) { return asArg(value, (val) => tx.pure.bool(val)); } async function simulateTransaction(suiClient, tx, sender) { const resolvedSender = determineSenderAddress(tx, sender); const { results, error } = await suiClient.devInspectTransactionBlock({ transactionBlock: tx, sender: resolvedSender }); if (error != void 0 && error != null) { throw handleError(error); } if (results === void 0 || results === null) { throw new Error("No results found"); } const lastCommandResults = results[results.length - 1]; if (lastCommandResults.returnValues === void 0) { throw new Error("No return values found"); } return lastCommandResults.returnValues.map((result) => { return { value: typeof result[0] === "string" ? fromBase64(result[0]) : new Uint8Array(result[0]), type: result[1] }; }); } async function simulateTransactionMultiResult(suiClient, tx, resultIndex, sender) { const resolvedSender = determineSenderAddress(tx, sender); const { results, error } = await suiClient.devInspectTransactionBlock({ transactionBlock: tx, sender: resolvedSender }); if (error != void 0 && error != null) { throw handleError(error); } if (results === void 0 || results === null) { throw new Error("No results found"); } const selectedResults = resultIndex.map((idx) => { return results[idx]; }); return selectedResults.map((result) => { if (result.returnValues === void 0) { throw new Error("No return values found"); } return result.returnValues.map((result2) => { return { value: typeof result2[0] === "string" ? fromBase64(result2[0]) : new Uint8Array(result2[0]), type: result2[1] }; }); }); } async function validateTransaction(client, signer, tx) { tx.setSenderIfNotSet(signer.getPublicKey().toSuiAddress()); const result = await client.signAndExecuteTransaction({ signer, transaction: tx, options: { showEffects: true, showObjectChanges: true, showEvents: true } }); if (result.effects?.status.status !== "success") { throw new Error(result.effects?.status.error); } await client.waitForTransaction({ digest: result.digest }); return result; } async function executeSimulate(client, moveCallFn, parser) { const tx = new Transaction(); await moveCallFn(tx); const result = await simulateTransaction(client, tx); return parser(result); } function determineSenderAddress(tx, preferredSender) { if (preferredSender) return preferredSender; const existingSender = tx.getData().sender; if (typeof existingSender === "string") return existingSender; return Ed25519Keypair.generate().toSuiAddress(); } function handleError(e) { if (e.includes("ExecutionError")) { const majorStatusMatch = e.match(/major_status:\s([A-Z_]+)/); if (majorStatusMatch !== null) { const major_status = majorStatusMatch[1]; if (major_status === "ABORTED") { const subStatusMatch = e.match(/sub_status:\sSome\((\d+)\)/); if (subStatusMatch === null) { return new MoveAbortError(Number.NEGATIVE_INFINITY, e); } else { return new MoveAbortError(Number(subStatusMatch[1]), e); } } } else { return new UnclassifiedError(e); } } return new Error(e); } // src/utils/package-allowlist-validator.ts var PackageAllowlistValidator = class { constructor(packageWhitelist = [], validator) { if (packageWhitelist.length == 0 && validator == null) { throw new Error("PackageAllowlistValidator requires either a packageWhitelist or a validator"); } this.packageWhitelist = new Set(packageWhitelist); this.validator = validator; } /** * Validates that all function calls and object arguments belong to whitelisted packages * @param moveCallsWithDetails - Array of move calls with object details * @throws Error if any function call or object belongs to a non-whitelisted package */ async validate(moveCallsWithDetails) { const allPackages = /* @__PURE__ */ new Set(); for (const { moveCall } of moveCallsWithDetails) { const packageId = moveCall.function.package; if (packageId === "") { throw new Error("Move call package is missing"); } allPackages.add(packageId); } for (const { objectDetails } of moveCallsWithDetails) { for (const [objectId, objectResponse] of objectDetails) { if (!objectResponse.data) { throw new Error(`Object ${objectId} not found`); } const packageId = this.extractPackageIdFromType(objectResponse.data.type); if (packageId == null) { throw new Error(`Could not extract package ID from object ${objectId}`); } allPackages.add(packageId); } } const isAllValid = await this.validatePackages(Array.from(allPackages)); if (!isAllValid) { throw new Error( `One or more packages are not allowlisted. Packages: [${Array.from(allPackages).join(", ")}]` ); } } /** * Validate multiple packages at once * @param packages - Array of package IDs to validate * @returns Object mapping package ID to validation result */ async validatePackages(packages) { if (packages.length === 0) { return true; } if (this.packageWhitelist.size > 0) { for (const packageId of packages) { if (!this.packageWhitelist.has(packageId)) { return false; } } return true; } else { try { return await this.validator.validate(packages); } catch (error) { console.warn(`Failed to check whitelist:`, error); return false; } } } /** * Extracts package ID from object type string * Object types are in format: "packageId::module::struct<generics>" * @param objectType - The object type string * @returns The package ID or null if extraction fails */ extractPackageIdFromType(objectType) { if (objectType == null) { return null; } const parts = objectType.split("::"); if (parts.length < 2) { return null; } const packageId = parts[0]; if (!packageId.startsWith("0x") || packageId.length < 3) { return null; } return packageId; } /** * Get available packages for error messages */ getAvailablePackagesList() { if (this.packageWhitelist.size > 0) { return Array.from(this.packageWhitelist).join(", "); } return "contract whitelist"; } }; // src/utils/non-sender-object-validator.ts var NonSenderObjectValidator = class { constructor(sender) { this.sender = sender; } /** * Validates that objects are not owned by the sender * @param moveCallsWithDetails - Array of move calls with object details * @throws Error if any object is owned by the sender */ validate(moveCallsWithDetails) { for (const { objectDetails } of moveCallsWithDetails) { for (const [objectId, objectResponse] of objectDetails) { const owner = objectResponse.data?.owner; if (owner == null) { throw new Error(`Object ${objectId} has no owner`); } if (!this.isValidOwnership(owner)) { const ownerType = this.getOwnershipType(owner); throw new Error( `Object ${objectId} is owned by the sender (${this.sender}). Only Shared, Immutable, or objects owned by other addresses are allowed. Current ownership: ${ownerType}` ); } } } } /** * Checks if the ownership is valid (not owned by sender) * @param owner - The object owner to check * @returns true if ownership is valid (Shared, Immutable, or owned by another address) */ isValidOwnership(owner) { if (typeof owner === "object" && "Shared" in owner) { return true; } if (owner === "Immutable") { return true; } if (typeof owner === "object" && "AddressOwner" in owner && owner.AddressOwner !== this.sender) { return true; } if (typeof owner === "object" && "ObjectOwner" in owner) { return true; } return false; } /** * Gets a human-readable description of the ownership type * @param owner - The object owner * @returns String description of ownership type */ getOwnershipType(owner) { if (typeof owner === "object" && "Shared" in owner) { return `Shared (initial_shared_version: ${owner.Shared.initial_shared_version})`; } if (owner === "Immutable") { return "Immutable"; } if (typeof owner === "object" && "AddressOwner" in owner) { return `AddressOwner: ${owner.AddressOwner}`; } if (typeof owner === "object" && "ObjectOwner" in owner) { return `ObjectOwner: ${owner.ObjectOwner}`; } return "Unknown ownership type"; } }; // src/utils/share-object-validator.ts var ShareObjectValidator = class { /** * Validates move calls with pre-fetched object details * @param moveCallsWithDetails - Array of move calls with object details * @throws Error if any object is not Shared/Immutable */ validate(moveCallsWithDetails) { for (const { objectDetails } of moveCallsWithDetails) { for (const [objectId, objectResponse] of objectDetails) { if (objectResponse.data?.owner == null) { throw new Error(`Object ${objectId} does not have owner`); } if (!this.isSharedOrImmutable(objectResponse.data.owner)) { throw new Error(`Object ${objectId} is not Shared/Immutable`); } } } } /** * Checks if an object owner is Shared or Immutable * @param owner - The object owner to check * @returns true if the owner is Shared or Immutable, false otherwise */ isSharedOrImmutable(owner) { return typeof owner === "object" && "Shared" in owner || owner === "Immutable"; } }; // src/utils/move-call-object-fetcher.ts var MoveCallObjectFetcher = class { constructor(client, batchSize = 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, options = {}) { const objectIdSet = /* @__PURE__ */ new Set(); 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) { return moveCalls.map((moveCall) => ({ moveCall, objectDetails: /* @__PURE__ */ new Map() })); } if (this.batchSize > MAX_BATCH_SIZE || this.batchSize < 1) { throw new Error(`batchSize must be between 1 and ${MAX_BATCH_SIZE}`); } const objectDetailsMap = /* @__PURE__ */ new Map(); 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 }); objects.forEach((object, index) => { const objectId = batch[index]; objectDetailsMap.set(objectId, object); }); } return moveCalls.map((moveCall) => { const moveCallObjectDetails = /* @__PURE__ */ new Map(); 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 }; }); } }; // src/utils/validate-with-details.ts async function validateWithDetails(client, moveCalls, validators, sender, userOptions = {}, batchSize = MAX_BATCH_SIZE) { if (validators.length === 0) { return; } const defaultOptions = { showOwner: true, showType: true, showContent: false, showBcs: false, showDisplay: false, showStorageRebate: false }; const finalOptions = { ...defaultOptions, ...userOptions }; const objectFetcher = new MoveCallObjectFetcher(client, batchSize); const moveCallsWithDetails = await objectFetcher.fetchObjectDetails(moveCalls, finalOptions); for (const validator of validators) { const result = validator.validate(moveCallsWithDetails, sender); if (result instanceof Promise) { await result; } } } var TYPE_CONFIG = { ["EndpointQuoteParam" /* EndpointQuoteParam */]: { pkg: "endpoint" /* Endpoint */, module: "endpoint_quote", type: "QuoteParam" }, ["EndpointSendParam" /* EndpointSendParam */]: { pkg: "endpoint" /* Endpoint */, module: "endpoint_send", type: "SendParam" }, ["MessageLibQuoteParam" /* MessageLibQuoteParam */]: { pkg: "endpoint" /* Endpoint */, module: "message_lib_quote", type: "QuoteParam" }, ["MessageLibSendParam" /* MessageLibSendParam */]: { pkg: "endpoint" /* Endpoint */, module: "message_lib_send", type: "SendParam" }, ["MessageLibSendResult" /* MessageLibSendResult */]: { pkg: "endpoint" /* Endpoint */, module: "message_lib_send", type: "SendResult" }, ["MessageLibSetConfigParam" /* MessageLibSetConfigParam */]: { pkg: "endpoint" /* Endpoint */, module: "message_lib_set_config", type: "SetConfigParam" }, ["MessagingFee" /* MessagingFee */]: { pkg: "endpoint" /* Endpoint */, module: "messaging_fee", type: "MessagingFee" }, ["MessagingReceipt" /* MessagingReceipt */]: { pkg: "endpoint" /* Endpoint */, module: "messaging_receipt", type: "MessagingReceipt" }, ["EndpointLzReceiveParam" /* EndpointLzReceiveParam */]: { pkg: "endpoint" /* Endpoint */, module: "lz_receive", type: "LzReceiveParam" }, ["EndpointLzComposeParam" /* EndpointLzComposeParam */]: { pkg: "endpoint" /* Endpoint */, module: "lz_compose", type: "LzComposeParam" }, ["MoveCall" /* MoveCall */]: { pkg: "call" /* Call */, module: "move_call", type: "MoveCall" }, ["CallVoid" /* CallVoid */]: { pkg: "call" /* Call */, module: "call", type: "Void" } }; var CALL_TYPE_CONFIG = { ["EndpointQuoteCall" /* EndpointQuoteCall */]: { param: "EndpointQuoteParam" /* EndpointQuoteParam */, result: "MessagingFee" /* MessagingFee */ }, ["EndpointSendCall" /* EndpointSendCall */]: { param: "EndpointSendParam" /* EndpointSendParam */, result: "MessagingReceipt" /* MessagingReceipt */ }, ["MessageLibQuoteCall" /* MessageLibQuoteCall */]: { param: "MessageLibQuoteParam" /* MessageLibQuoteParam */, result: "MessagingFee" /* MessagingFee */ }, ["MessageLibSendCall" /* MessageLibSendCall */]: { param: "MessageLibSendParam" /* MessageLibSendParam */, result: "MessageLibSendResult" /* MessageLibSendResult */ }, ["MessageLibSetConfigCall" /* MessageLibSetConfigCall */]: { param: "MessageLibSetConfigParam" /* MessageLibSetConfigParam */, result: "CallVoid" /* CallVoid */ }, ["EndpointLzReceiveCall" /* EndpointLzReceiveCall */]: { param: "EndpointLzReceiveParam" /* EndpointLzReceiveParam */, result: "CallVoid" /* CallVoid */ }, ["EndpointLzComposeCall" /* EndpointLzComposeCall */]: { param: "EndpointLzComposeParam" /* EndpointLzComposeParam */, result: "CallVoid" /* CallVoid */ } }; function getTypeName(moduleManager, type) { if (type in TYPE_CONFIG) { const config = TYPE_CONFIG[type]; const { packageId } = moduleManager.getModule(config.pkg); return buildTypeName(packageId, config.module, config.type); } if (type in CALL_TYPE_CONFIG) { const callConfig = CALL_TYPE_CONFIG[type]; const paramType = getTypeName(moduleManager, callConfig.param); const resultType = getTypeName(moduleManager, callConfig.result); return buildCallTypeName(moduleManager.getCall().packageId, paramType, resultType); } throw new Error(`Unknown type name: ${JSON.stringify(type)}`); } function normalizeSuiPackageId(packageId, includePrefix = false, trimLeadingZeros = false) { let normalized = packageId.startsWith("0x") ? packageId.slice(2) : packageId; if (trimLeadingZeros) { normalized = normalized.replace(/^0+/, "") || "0"; } return includePrefix ? `0x${normalized}` : normalized; } function callId(moduleManager, type) { return sha3.keccak_256(Buffer.from(getTypeName(moduleManager, type))); } function buildTypeName(packageId, module, type) { return `${normalizeSuiPackageId(packageId)}::${module}::${type}`; } function buildCallTypeName(packageId, paramType, resultType) { return `${normalizeSuiPackageId(packageId)}::call::Call<${paramType},${resultType}>`; } // src/modules/endpoint.ts var MODULE_NAME = "endpoint_v2"; var EndpointErrorCode = { // MessageLibManager related errors (with MessageLibManager_ prefix) MessageLibManager_EAlreadyRegistered: 1, MessageLibManager_EDefaultReceiveLibUnavailable: 2, MessageLibManager_EDefaultSendLibUnavailable: 3, MessageLibManager_EInvalidAddress: 4, MessageLibManager_EInvalidBounds: 5, MessageLibManager_EInvalidExpiry: 6, MessageLibManager_EInvalidReceiveLib: 7, MessageLibManager_EOnlyNonDefaultLib: 8, MessageLibManager_EOnlyReceiveLib: 9, MessageLibManager_EOnlyRegisteredLib: 10, MessageLibManager_EOnlySendLib: 11, MessageLibManager_ESameValue: 12, MessagingChannel_EAlreadyInitialized: 1, MessagingChannel_EInsufficientNativeFee: 2, MessagingChannel_EInsufficientZroFee: 3, MessagingChannel_EInvalidNonce: 4, MessagingChannel_EInvalidOApp: 5, MessagingChannel_EInvalidPayloadHash: 6, MessagingChannel_ENotSending: 7, MessagingChannel_EPathNotVerifiable: 8, MessagingChannel_EPayloadHashNotFound: 9, MessagingChannel_ESendReentrancy: 10, MessagingChannel_EUninitializedChannel: 11, // MessagingComposer related errors (with MessagingComposer_ prefix) MessagingComposer_EComposeExists: 1, MessagingComposer_EComposeMessageMismatch: 2, MessagingComposer_EComposeNotFound: 3, MessagingComposer_EComposerNotRegistered: 4, MessagingComposer_EComposerRegistered: 5, // OAppRegistry related errors (with OAppRegistry_ prefix) OAppRegistry_EOAppNotRegistered: 1, OAppRegistry_EOAppRegistered: 2, // Endpoint related errors (with Endpoint_ prefix) Endpoint_EAlreadyInitialized: 1, Endpoint_EInvalidEid: 2, Endpoint_ENotInitialized: 3, Endpoint_ERefundAddressNotFound: 4, Endpoint_EUnauthorizedOApp: 5, Endpoint_EUnauthorizedSendLibrary: 6 }; var _Endpoint_instances, addRequiredValidators_fn, target_fn; var Endpoint = class { constructor(packageId, client, objects, moduleManager) { this.moduleManager = moduleManager; __privateAdd(this, _Endpoint_instances); this.packageId = packageId; this.client = client; this.objects = objects; } // === Set Functions === /** * Initialize the endpoint with an Endpoint ID (EID) * @param tx - The transaction to add the move call to * @param eid - The endpoint ID to initialize or transaction argument */ initEidMoveCall(tx, eid) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "init_eid"), arguments: [tx.object(this.objects.endpointV2), tx.object(this.objects.endpointAdminCap), asU32(tx, eid)] }); } // ===== OApp Messaging Functions ===== /** * Register an OApp with the endpoint * @param tx - The transaction to add the move call to * @param oappCap - The OApp capability object ID or transaction argument * @param oappInfo - OApp information including lz_receive execution information * @returns Transaction result containing the messaging channel address */ registerOAppMoveCall(tx, oappCap, oappInfo) { return tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "register_oapp"), arguments: [tx.object(this.objects.endpointV2), asObject(tx, oappCap), asBytes(tx, oappInfo)] }); } /** * Set a delegate for an OApp * @param tx - The transaction to add the move call to * @param oappCap - The OApp capability object ID or transaction argument * @param newDelegate - The new delegate address or transaction argument */ setDelegateMoveCall(tx, oappCap, newDelegate) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "set_delegate"), arguments: [tx.object(this.objects.endpointV2), asObject(tx, oappCap), asAddress(tx, newDelegate)] }); } /** * Set OApp information for an OApp * @param tx - The transaction to add the move call to * @param callerCap - The caller capability object ID or transaction argument * @param oapp - The OApp address or transaction argument * @param oappInfo - The OApp information including lz_receive execution information as bytes or transaction argument */ setOappInfoMoveCall(tx, callerCap, oapp, oappInfo) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "set_oapp_info"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, callerCap), asAddress(tx, oapp), asBytes(tx, oappInfo) ] }); } /** * Initialize a messaging channel between local and remote OApps * @param tx - The transaction to add the move call to * @param callerCap - The caller capability object ID or transaction argument * @param messagingChannel - The messaging channel object ID or transaction argument * @param remoteEid - The remote endpoint ID or transaction argument * @param remoteOapp - The remote OApp address as bytes or transaction argument */ initChannelMoveCall(tx, callerCap, messagingChannel, remoteEid, remoteOapp) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "init_channel"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, callerCap), asObject(tx, messagingChannel), asU32(tx, remoteEid), asBytes32(tx, remoteOapp, this.moduleManager.getUtils()) ] }); } /** * Quote the messaging fee for sending a message * @param tx - The transaction to add the move call to * @param messagingChannel - The messaging channel object ID or transaction argument * @param call - The call transaction result * @returns Transaction result containing the quote */ quoteMoveCall(tx, messagingChannel, call) { return tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "quote"), arguments: [tx.object(this.objects.endpointV2), asObject(tx, messagingChannel), call] }); } /** * Confirm quote operation with message library * @param tx - The transaction to add the move call to * @param endpointCall - The endpoint call transaction result or transaction argument * @param messageLibCall - The message library call transaction result or transaction argument */ confirmQuoteMoveCall(tx, endpointCall, messageLibCall) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "confirm_quote"), arguments: [tx.object(this.objects.endpointV2), endpointCall, messageLibCall] }); } /** * Send a message through the messaging channel * @param tx - The transaction to add the move call to * @param messagingChannel - The messaging channel object ID or transaction argument * @param call - The call transaction result * @returns Transaction result containing the send operation */ sendMoveCall(tx, messagingChannel, call) { return tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "send"), arguments: [tx.object(this.objects.endpointV2), asObject(tx, messagingChannel), call] }); } /** * Confirm send operation with send library * @param tx - The transaction to add the move call to * @param sendLibrary - The send library object ID or transaction argument * @param messagingChannel - The messaging channel object ID or transaction argument * @param endpointCall - The endpoint call transaction result * @param sendLibraryCall - The send library call transaction result * @returns Transaction result containing the confirmed send operation */ confirmSendMoveCall(tx, sendLibrary, messagingChannel, endpointCall, sendLibraryCall) { return tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "confirm_send"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, sendLibrary), asObject(tx, messagingChannel), endpointCall, sendLibraryCall ] }); } /** * Refund fees from a send operation * @param tx - The transaction to add the move call to * @param sendCall - The send call transaction result or transaction argument * @returns Transaction result containing the refund operation */ refundMoveCall(tx, sendCall) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "refund"), arguments: [tx.object(this.objects.endpointV2), sendCall] }); } /** * Verify a message from another chain * @param tx - The transaction to add the move call to * @param receiveLibrary - The receive library object ID or transaction argument * @param messagingChannel - The messaging channel object ID or transaction argument * @param srcEid - The source endpoint ID or transaction argument * @param sender - The sender address as bytes or transaction argument * @param nonce - The message nonce or transaction argument * @param payloadHash - The payload hash as bytes or transaction argument */ verifyMoveCall(tx, receiveLibrary, messagingChannel, srcEid, sender, nonce, payloadHash) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "verify"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, receiveLibrary), asObject(tx, messagingChannel), asU32(tx, srcEid), asBytes32(tx, sender, this.moduleManager.getUtils()), asU64(tx, nonce), asBytes32(tx, payloadHash, this.moduleManager.getUtils()), tx.object.clock() ] }); } /** * Clear a verified message by executing it * @param tx - The transaction to add the move call to * @param caller - The caller object ID or transaction argument * @param messagingChannel - The messaging channel object ID or transaction argument * @param srcEid - Source endpoint ID or transaction argument * @param sender - Sender address as bytes or transaction argument * @param nonce - Message nonce or transaction argument * @param guid - Globally unique identifier as bytes or transaction argument * @param message - Message payload as bytes or transaction argument */ clearMoveCall(tx, caller, messagingChannel, srcEid, sender, nonce, guid, message) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "clear"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, caller), asObject(tx, messagingChannel), asU32(tx, srcEid), asBytes32(tx, sender, this.moduleManager.getUtils()), asU64(tx, nonce), asBytes32(tx, guid, this.moduleManager.getUtils()), asBytes(tx, message) ] }); } /** * Skip a message (mark as processed without execution) * @param tx - The transaction to add the move call to * @param caller - The caller object ID or transaction argument * @param messagingChannel - The messaging channel object ID or transaction argument * @param srcEid - Source endpoint ID or transaction argument * @param sender - Sender address as bytes or transaction argument * @param nonce - Message nonce or transaction argument */ skipMoveCall(tx, caller, messagingChannel, srcEid, sender, nonce) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "skip"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, caller), asObject(tx, messagingChannel), asU32(tx, srcEid), asBytes32(tx, sender, this.moduleManager.getUtils()), asU64(tx, nonce) ] }); } /** * Nilify a message (clear without execution) * @param tx - The transaction to add the move call to * @param caller - The caller object ID or transaction argument * @param messagingChannel - The messaging channel object ID or transaction argument * @param srcEid - Source endpoint ID or transaction argument * @param sender - Sender address as bytes or transaction argument * @param nonce - Message nonce or transaction argument * @param payloadHash - Message payload hash as bytes or transaction argument */ nilifyMoveCall(tx, caller, messagingChannel, srcEid, sender, nonce, payloadHash) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "nilify"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, caller), asObject(tx, messagingChannel), asU32(tx, srcEid), asBytes32(tx, sender, this.moduleManager.getUtils()), asU64(tx, nonce), asBytes32(tx, payloadHash, this.moduleManager.getUtils()) ] }); } /** * Burn a message (permanently remove) * @param tx - The transaction to add the move call to * @param caller - The caller object ID or transaction argument * @param messagingChannel - The messaging channel object ID or transaction argument * @param srcEid - Source endpoint ID or transaction argument * @param sender - Sender address as bytes or transaction argument * @param nonce - Message nonce or transaction argument * @param payloadHash - Message payload hash as bytes or transaction argument */ burnMoveCall(tx, caller, messagingChannel, srcEid, sender, nonce, payloadHash) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "burn"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, caller), asObject(tx, messagingChannel), asU32(tx, srcEid), asBytes32(tx, sender, this.moduleManager.getUtils()), asU64(tx, nonce), asBytes32(tx, payloadHash, this.moduleManager.getUtils()) ] }); } /** * Execute a LayerZero receive operation * @param tx - The transaction to add the move call to * @param executorCallCap - The executor call capability * @param messagingChannel - The messaging channel object ID or transaction argument * @param srcEid - The source endpoint ID or transaction argument * @param sender - The sender address as bytes or transaction argument * @param nonce - The message nonce or transaction argument * @param guid - The globally unique identifier as bytes or transaction argument * @param message - The message payload as bytes or transaction argument * @param extraData - Additional data as bytes or transaction argument (optional) * @param value - The native token value to transfer or transaction argument * @returns Transaction result containing the receive operation */ lzReceiveMoveCall(tx, executorCallCap, messagingChannel, srcEid, sender, nonce, guid, message, extraData = new Uint8Array(), value) { return tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "lz_receive"), arguments: [ tx.object(this.objects.endpointV2), executorCallCap, asObject(tx, messagingChannel), asU32(tx, srcEid), asBytes32(tx, sender, this.moduleManager.getUtils()), asU64(tx, nonce), asBytes32(tx, guid, this.moduleManager.getUtils()), asBytes(tx, message), asBytes(tx, extraData), asArgWithTx(tx, value, (tx2, val) => this.moduleManager.getUtils().createOptionSuiMoveCall(tx2, val)) ] }); } /** * Send alert for failed LayerZero receive operation * @param tx - The transaction to add the move call to * @param executor - The executor object ID or transaction argument * @param srcEid - Source endpoint ID or transaction argument * @param sender - Sender address as bytes or transaction argument * @param nonce - Message nonce or transaction argument * @param receiver - Receiver address or transaction argument * @param guid - Globally unique identifier as bytes or transaction argument * @param gas - Gas amount for execution or transaction argument * @param value - Native token value or transaction argument * @param message - Message payload as bytes or transaction argument * @param extraData - Additional execution data as bytes or transaction argument * @param reason - Failure reason or transaction argument */ lzReceiveAlertMoveCall(tx, executor, srcEid, sender, nonce, receiver, guid, gas, value, message, extraData, reason) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "lz_receive_alert"), arguments: [ asObject(tx, executor), asU32(tx, srcEid), asBytes32(tx, sender, this.moduleManager.getUtils()), asU64(tx, nonce), asAddress(tx, receiver), asBytes32(tx, guid, this.moduleManager.getUtils()), asU64(tx, gas), asU64(tx, value), asBytes(tx, message), asBytes(tx, extraData), asString(tx, reason) ] }); } /** * Register a composer with the endpoint * @param tx - The transaction to add the move call to * @param composerCap - The composer capability object ID or transaction argument * @param composerInfo - Composer information including lz_compose execution information as bytes * @returns Transaction result containing the compose queue address */ registerComposerMoveCall(tx, composerCap, composerInfo) { return tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "register_composer"), arguments: [tx.object(this.objects.endpointV2), asObject(tx, composerCap), asBytes(tx, composerInfo)] }); } /** * Set composer information for a composer * @param tx - The transaction to add the move call to * @param composerCap - The composer capability object ID or transaction argument * @param composerInfo - Composer information including lz_compose execution information as bytes or transaction argument */ setComposerInfoMoveCall(tx, composerCap, composerInfo) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "set_composer_info"), arguments: [tx.object(this.objects.endpointV2), asObject(tx, composerCap), asBytes(tx, composerInfo)] }); } /** * Send compose message to queue * @param tx - The transaction to add the move call to * @param from - The sender object ID or transaction argument * @param composeQueue - The compose queue object ID or transaction argument * @param guid - Globally unique identifier as bytes or transaction argument * @param index - Compose message index or transaction argument * @param message - Message payload as bytes or transaction argument */ sendComposeMoveCall(tx, from, composeQueue, guid, index, message) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "send_compose"), arguments: [ asObject(tx, from), asObject(tx, composeQueue), asBytes32(tx, guid, this.moduleManager.getUtils()), asU16(tx, index), asBytes(tx, message) ] }); } /** * Execute LayerZero compose operation * @param tx - The transaction to add the move call to * @param executorCallCap - The executor call capability * @param composeQueue - The compose queue object ID or transaction argument * @param from - Source address or transaction argument * @param guid - Globally unique identifier as bytes or transaction argument * @param index - Compose message index or transaction argument * @param message - Message payload as bytes or transaction argument * @param extraData - Additional execution data as bytes or transaction argument (optional) * @param value - Native token value to transfer or transaction argument * @returns Transaction result containing the compose operation */ lzComposeMoveCall(tx, executorCallCap, composeQueue, from, guid, index, message, extraData = new Uint8Array(), value) { return tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "lz_compose"), arguments: [ tx.object(this.objects.endpointV2), executorCallCap, asObject(tx, composeQueue), asAddress(tx, from), asBytes32(tx, guid, this.moduleManager.getUtils()), asU16(tx, index), asBytes(tx, message), asBytes(tx, extraData), asArgWithTx(tx, value, (tx2, val) => this.moduleManager.getUtils().createOptionSuiMoveCall(tx2, val)) ] }); } /** * Send alert for failed LayerZero compose operation * @param tx - The transaction to add the move call to * @param executor - The executor object ID or transaction argument * @param from - Source address or transaction argument * @param to - Destination address or transaction argument * @param guid - Globally unique identifier as bytes or transaction argument * @param index - Compose message index or transaction argument * @param gas - Gas amount for execution or transaction argument * @param value - Native token value or transaction argument * @param message - Message payload as bytes or transaction argument * @param extraData - Additional execution data as bytes or transaction argument * @param reason - Failure reason or transaction argument */ lzComposeAlertMoveCall(tx, executor, from, to, guid, index, gas, value, message, extraData, reason) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "lz_compose_alert"), arguments: [ asObject(tx, executor), asAddress(tx, from), asAddress(tx, to), asBytes32(tx, guid, this.moduleManager.getUtils()), asU16(tx, index), asU64(tx, gas), asU64(tx, value), asBytes(tx, message), asBytes(tx, extraData), asString(tx, reason) ] }); } // ===== OApp Library Configuration Functions ===== /** * Set the send library for an OApp to a specific destination * @param tx - The transaction to add the move call to * @param caller - The caller capability object ID or transaction argument * @param sender - The sender OApp address or transaction argument * @param dstEid - The destination endpoint ID or transaction argument * @param newLib - The new send library address or transaction argument */ setSendLibraryMoveCall(tx, caller, sender, dstEid, newLib) { tx.moveCall({ target: __privateMethod(this, _Endpoint_instances, target_fn).call(this, "set_send_library"), arguments: [ tx.object(this.objects.endpointV2), asObject(tx, caller), asAddress(tx, sender), asU32(tx, dstEid), asAddress(tx, newLib) ] }); } /** * Set the receive library for an OApp from a specific source * @param tx - The transaction to add the move call to * @param caller - The caller capability object ID or transaction argument * @param receiver - The receiver OApp address or transaction argument * @param srcEid - The source endpoint ID or transaction argument * @param newLib - The new receive library address or transaction argument * @param gracePeriod - The grace period in seconds or transaction argument */ setReceiveLi