@layerzerolabs/lz-sui-sdk-v2
Version:
1,258 lines (1,242 loc) • 430 kB
JavaScript
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