@layerzerolabs/lz-sui-sdk-v2
Version:
1,410 lines (1,316 loc) • 62.7 kB
text/typescript
import { bcs } from '@mysten/sui/bcs'
import { SuiClient } from '@mysten/sui/client'
import { Transaction, TransactionArgument, TransactionResult } from '@mysten/sui/transactions'
import { Bytes32Bcs, DvnDstConfigBcs } from '../../bcs'
import { ModuleManager } from '../../module-manager'
import { DvnDstConfig, ObjectOptions } from '../../types'
import {
asAddress,
asBool,
asBytes,
asBytes32,
asObject,
asU128,
asU16,
asU256,
asU32,
asU64,
executeSimulate,
} from '../../utils'
const MODULE_NAME = 'dvn'
export const DVNErrorCode = {
// DVN related errors (with DVN_ prefix)
DVN_EExpiredSignature: 1,
DVN_EEidNotSupported: 2,
DVN_EHashAlreadyUsed: 3,
DVN_EPtbBuilderAlreadyInitialized: 4,
// Multisig related errors (matching multisig.move)
Multisig_EDuplicatedSigner: 1,
Multisig_EInvalidSignatureLength: 2,
Multisig_EInvalidSignerLength: 3,
Multisig_EQuorumIsZero: 4,
Multisig_ESignaturesLessThanQuorum: 5,
Multisig_ESignerAlreadyExists: 6,
Multisig_ESignerNotFound: 7,
Multisig_ESignerNotInCommittee: 8,
Multisig_ESignersSizeIsLessThanQuorum: 9,
// DVNInfoV1 related errors (matching dvn_info_v1.move)
DVNInfoV1_EInvalidData: 1,
DVNInfoV1_EInvalidVersion: 2,
} as const
export class DVN {
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
}
// === Set Functions ===
/**
* Set admin role for an address (admin only)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param admin - The admin address or transaction argument
* @param active - Whether to activate or deactivate the admin role or transaction argument
*/
setAdminMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
admin: string | TransactionArgument,
active: boolean | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_admin'),
arguments: [tx.object(this.objects.dvn), asObject(tx, adminCap), asAddress(tx, admin), asBool(tx, active)],
})
}
/**
* Set default multiplier basis points for fee calculation (admin only)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param multiplierBps - The multiplier in basis points or transaction argument
*/
setDefaultMultiplierBpsMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
multiplierBps: number | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_default_multiplier_bps'),
arguments: [tx.object(this.objects.dvn), asObject(tx, adminCap), asU16(tx, multiplierBps)],
})
}
/**
* Set deposit address for DVN fees (admin only)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param depositAddress - The new deposit address or transaction argument
*/
setDepositAddressMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
depositAddress: string | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_deposit_address'),
arguments: [tx.object(this.objects.dvn), asObject(tx, adminCap), asAddress(tx, depositAddress)],
})
}
/**
* Set price feed for DVN (admin only)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param priceFeed - The price feed address or transaction argument
*/
setPriceFeedMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
priceFeed: string | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_price_feed'),
arguments: [tx.object(this.objects.dvn), asObject(tx, adminCap), asAddress(tx, priceFeed)],
})
}
/**
* Set supported option types for a destination EID (admin only)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param dstEid - Destination endpoint ID
* @param optionTypes - Array of supported option types
*/
setSupportedOptionTypesMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
dstEid: number | TransactionArgument,
optionTypes: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_supported_option_types'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asU32(tx, dstEid),
asBytes(tx, optionTypes),
],
})
}
/**
* Set worker fee library (admin only)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param workerFeeLib - The worker fee library address
*/
setWorkerFeeLibMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
workerFeeLib: string | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_worker_fee_lib'),
arguments: [tx.object(this.objects.dvn), asObject(tx, adminCap), asAddress(tx, workerFeeLib)],
})
}
/**
* Set destination configuration for DVN (admin only)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param dstEid - Destination endpoint ID
* @param gas - Gas amount for verification
* @param multiplierBps - Multiplier in basis points
* @param floorMarginUsd - Floor margin in USD
*/
setDstConfigMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
dstEid: number | TransactionArgument,
gas: bigint | number | string | TransactionArgument,
multiplierBps: number | TransactionArgument,
floorMarginUsd: bigint | number | string | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_dst_config'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asU32(tx, dstEid),
asU256(tx, gas),
asU16(tx, multiplierBps),
asU128(tx, floorMarginUsd),
],
})
}
/**
* Initialize PTB builder move calls for DVN worker operations (admin only) - can only be called once
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param targetPtbBuilder - Target PTB builder address
* @param getFeeMoveCalls - Get fee move calls transaction argument
* @param assignJobMoveCalls - Assign job move calls transaction argument
* @returns Transaction result containing the init PTB builder call
*/
initPtbBuilderMoveCallsMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
targetPtbBuilder: string | TransactionArgument,
getFeeMoveCalls: TransactionArgument,
assignJobMoveCalls: TransactionArgument
): TransactionResult {
return tx.moveCall({
target: this.#target('init_ptb_builder_move_calls'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asAddress(tx, targetPtbBuilder),
getFeeMoveCalls, // First element of DVN PTB result tuple
assignJobMoveCalls, // Second element of DVN PTB result tuple
],
})
}
/**
* Set PTB builder move calls for DVN worker operations (admin with signatures)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param targetPtbBuilder - Target PTB builder address
* @param getFeeMoveCalls - Get fee move calls transaction argument
* @param assignJobMoveCalls - Assign job move calls transaction argument
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
* @returns Transaction result containing the set PTB builder call
*/
setPtbBuilderMoveCallsMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
targetPtbBuilder: string | TransactionArgument,
getFeeMoveCalls: TransactionArgument,
assignJobMoveCalls: TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): TransactionResult {
return tx.moveCall({
target: this.#target('set_ptb_builder_move_calls'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asAddress(tx, targetPtbBuilder),
getFeeMoveCalls, // First element of DVN PTB result tuple
assignJobMoveCalls, // Second element of DVN PTB result tuple
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
// === Set Functions with Signatures ===
/**
* Set supported message library (admin with signatures)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param messageLib - The message library address
* @param supported - Whether to support or remove support for the message library
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
*/
setSupportedMessageLibMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
messageLib: string | TransactionArgument,
supported: boolean | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_supported_message_lib'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asAddress(tx, messageLib),
asBool(tx, supported),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
/**
* Set allowlist status for an OApp sender (admin with signatures)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param oapp - The OApp address to allowlist/remove
* @param allowed - Whether to allow or remove from allowlist
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
*/
setAllowlistMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
oapp: string | TransactionArgument,
allowed: boolean | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_allowlist'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asAddress(tx, oapp),
asBool(tx, allowed),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
/**
* Set denylist status for an OApp sender (admin with signatures)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param oapp - The OApp address to denylist/remove
* @param denied - Whether to deny or remove from denylist
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
*/
setDenylistMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
oapp: string | TransactionArgument,
denied: boolean | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_denylist'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asAddress(tx, oapp),
asBool(tx, denied),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
/**
* Set paused state with multisig signatures (admin with signatures)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param paused - Whether to pause or unpause the DVN
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
*/
setPausedMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
paused: boolean | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_paused'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asBool(tx, paused),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
/**
* Set quorum threshold with multisig signatures (admin with signatures)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param quorum - The new quorum threshold
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
*/
setQuorumMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
quorum: bigint | number | string | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_quorum'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asU64(tx, quorum),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
/**
* Set DVN signer with multisig signatures (admin with signatures)
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param signer - The signer public key as bytes
* @param active - Whether to activate or deactivate the signer
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
*/
setDvnSignerMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
signer: Uint8Array | TransactionArgument,
active: boolean | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('set_dvn_signer'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asBytes(tx, signer),
asBool(tx, active),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
/**
* Change admin status using quorum signatures
* @param tx - The transaction to add the move call to
* @param admin - The admin address to change
* @param active - Whether to activate or deactivate the admin
* @param expiration - Signature expiration timestamp
* @param signatures - Multisig signatures for authorization
*/
quorumChangeAdminMoveCall(
tx: Transaction,
admin: string | TransactionArgument,
active: boolean | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): void {
tx.moveCall({
target: this.#target('quorum_change_admin'),
arguments: [
tx.object(this.objects.dvn),
asAddress(tx, admin),
asBool(tx, active),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
// Verification Functions
/**
* Verify a packet with DVN signatures (admin with signatures) - returns Call object for ULN302
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID
* @param targetMessageLib - The target message library address (usually ULN302)
* @param packetHeader - The packet header as bytes
* @param payloadHash - The payload hash as bytes
* @param confirmations - Required confirmations count
* @param expiration - Signature expiration timestamp
* @param signatures - DVN multisig signatures
* @returns Transaction result containing the verification Call object
*/
verifyMoveCall(
tx: Transaction,
adminCap: string | TransactionArgument,
targetMessageLib: string | TransactionArgument,
packetHeader: Uint8Array | TransactionArgument,
payloadHash: Uint8Array | TransactionArgument,
confirmations: bigint | number | string | TransactionArgument,
expiration: bigint | number | string | TransactionArgument,
signatures: Uint8Array | TransactionArgument
): TransactionResult {
return tx.moveCall({
target: this.#target('verify'),
arguments: [
tx.object(this.objects.dvn),
asObject(tx, adminCap),
asAddress(tx, targetMessageLib),
asBytes(tx, packetHeader),
asBytes32(tx, payloadHash, this.moduleManager.getUtils()),
asU64(tx, confirmations),
asU64(tx, expiration),
asBytes(tx, signatures),
tx.object.clock(),
],
})
}
// Worker Functions
/**
* Assign verification job for DVN (called via PTB with MultiCall created by send function in ULN302)
* @param tx - The transaction to add the move call to
* @param dvnMultiCall - The DVN multi-call transaction result
* @returns Transaction result containing a Call for fee calculation
*/
assignJobMoveCall(tx: Transaction, dvnMultiCall: TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('assign_job'),
arguments: [tx.object(this.objects.dvn), dvnMultiCall],
})
}
/**
* Confirm assign job operation with fee calculation
* @param tx - The transaction to add the move call to
* @param dvnMultiCall - The DVN multi-call transaction result
* @param feelibCall - The fee library call transaction result
*/
confirmAssignJobMoveCall(
tx: Transaction,
dvnMultiCall: TransactionArgument,
feelibCall: TransactionArgument
): void {
tx.moveCall({
target: this.#target('confirm_assign_job'),
arguments: [tx.object(this.objects.dvn), dvnMultiCall, feelibCall],
})
}
/**
* Get fee for verification (using MultiCall created by quote function in ULN302)
* @param tx - The transaction to add the move call to
* @param dvnMultiCall - The DVN multi-call transaction result
* @returns Transaction result containing a Call for fee calculation
*/
getFeeMoveCall(tx: Transaction, dvnMultiCall: TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('get_fee'),
arguments: [tx.object(this.objects.dvn), dvnMultiCall],
})
}
/**
* Confirm get fee operation with fee calculation
* @param tx - The transaction to add the move call to
* @param dvnMultiCall - The DVN multi-call transaction result
* @param feelibCall - The fee library call transaction result
*/
confirmGetFeeMoveCall(tx: Transaction, dvnMultiCall: TransactionArgument, feelibCall: TransactionArgument): void {
tx.moveCall({
target: this.#target('confirm_get_fee'),
arguments: [tx.object(this.objects.dvn), dvnMultiCall, feelibCall],
})
}
// === View Functions ===
/**
* Get the size of the allowlist
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the allowlist size
*/
allowlistSizeMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('allowlist_size'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get the size of the allowlist
* @returns Promise<bigint> - The number of addresses in the allowlist
*/
async allowlistSize(): Promise<bigint> {
return executeSimulate(
this.client,
(tx) => {
this.allowlistSizeMoveCall(tx)
},
(result) => BigInt(bcs.U64.parse(result[0].value))
)
}
/**
* Get default multiplier basis points
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the default multiplier bps
*/
defaultMultiplierBpsMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('default_multiplier_bps'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get default multiplier basis points
* @returns Promise<number> - The default multiplier in basis points
*/
async defaultMultiplierBps(): Promise<number> {
return executeSimulate(
this.client,
(tx) => {
this.defaultMultiplierBpsMoveCall(tx)
},
(result) => bcs.U16.parse(result[0].value)
)
}
/**
* Get DVN deposit address for fee collection
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the deposit address
*/
depositAddressMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('deposit_address'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get DVN deposit address for fee collection
* @returns Promise<string> - The deposit address
*/
async depositAddress(): Promise<string> {
return executeSimulate(
this.client,
(tx) => {
this.depositAddressMoveCall(tx)
},
(result) => bcs.Address.parse(result[0].value)
)
}
/**
* Get destination configuration for DVN
* @param tx - The transaction to add the move call to
* @param dstEid - Destination endpoint ID
* @returns Transaction result containing the destination configuration
*/
dstConfigMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('dst_config'),
arguments: [tx.object(this.objects.dvn), asU32(tx, dstEid)],
})
}
/**
* Get destination configuration for DVN
* @param dstEid - Destination endpoint ID
* @returns Promise<DvnDstConfig> - The destination configuration
*/
async dstConfig(dstEid: number): Promise<DvnDstConfig> {
return executeSimulate(
this.client,
(tx) => {
this.dstConfigMoveCall(tx, dstEid)
},
(result) => {
const value = DvnDstConfigBcs.parse(result[0].value)
return {
gas: BigInt(value.gas),
multiplierBps: value.multiplier_bps,
floorMarginUsd: BigInt(value.floor_margin_usd),
}
}
)
}
/**
* Check if an address has ACL (Access Control List) permission
* @param tx - The transaction to add the move call to
* @param account - The account address to check
* @returns Transaction result containing the ACL permission status
*/
hasAclMoveCall(tx: Transaction, account: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('has_acl'),
arguments: [tx.object(this.objects.dvn), asAddress(tx, account)],
})
}
/**
* Check if an address has ACL (Access Control List) permission
* @param account - The account address to check
* @returns Promise<boolean> - True if the address has ACL permission
*/
async hasAcl(account: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.hasAclMoveCall(tx, account)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Get all registered DVN admins
* @param tx - The transaction to add the move call to
* @returns Transaction result containing array of admin addresses
*/
adminsMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('admins'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get all registered DVN admins
* @returns Promise<string[]> - Array of admin addresses
*/
async admins(): Promise<string[]> {
return executeSimulate(
this.client,
(tx) => {
this.adminsMoveCall(tx)
},
(result) => {
const parsed = bcs.vector(bcs.Address).parse(result[0].value)
return parsed
}
)
}
/**
* Check if an admin cap is valid
* @param tx - The transaction to add the move call to
* @param adminCap - The admin capability object ID to check
* @returns Transaction result containing the admin status
*/
isAdminMoveCall(tx: Transaction, adminCap: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_admin'),
arguments: [tx.object(this.objects.dvn), asObject(tx, adminCap)],
})
}
/**
* Check if an admin cap is valid
* @param adminCap - The admin capability object ID to check
* @returns Promise<boolean> - True if the admin cap is valid
*/
async isAdmin(adminCap: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isAdminMoveCall(tx, adminCap)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Check if an address is an admin
* @param tx - The transaction to add the move call to
* @param admin - The admin address to check
* @returns Transaction result containing the admin status
*/
isAdminAddressMoveCall(tx: Transaction, admin: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_admin_address'),
arguments: [tx.object(this.objects.dvn), asAddress(tx, admin)],
})
}
/**
* Check if an address is an admin
* @param admin - The admin address to check
* @returns Promise<boolean> - True if the address is an admin
*/
async isAdminAddress(admin: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isAdminAddressMoveCall(tx, admin)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Check if a message library is supported by this DVN
* @param tx - The transaction to add the move call to
* @param messageLib - The message library address to check
* @returns Transaction result containing the support status
*/
isSupportedMessageLibMoveCall(tx: Transaction, messageLib: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_supported_message_lib'),
arguments: [tx.object(this.objects.dvn), asAddress(tx, messageLib)],
})
}
/**
* Check if a message library is supported by this DVN
* @param messageLib - The message library address to check
* @returns Promise<boolean> - True if the message library is supported
*/
async isSupportedMessageLib(messageLib: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isSupportedMessageLibMoveCall(tx, messageLib)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Check if an address is allowlisted
* @param tx - The transaction to add the move call to
* @param account - The account address to check
* @returns Transaction result containing the allowlist status
*/
isAllowlistedMoveCall(tx: Transaction, account: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_allowlisted'),
arguments: [tx.object(this.objects.dvn), asAddress(tx, account)],
})
}
/**
* Check if an address is in the allowlist
* @param account - The account address to check
* @returns Promise<boolean> - True if the address is allowlisted
*/
async isAllowlisted(account: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isAllowlistedMoveCall(tx, account)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Check if an address is denylisted
* @param tx - The transaction to add the move call to
* @param account - The account address to check
* @returns Transaction result containing the denylist status
*/
isDenylistedMoveCall(tx: Transaction, account: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_denylisted'),
arguments: [tx.object(this.objects.dvn), asAddress(tx, account)],
})
}
/**
* Check if an address is in the denylist
* @param account - The account address to check
* @returns Promise<boolean> - True if the address is denylisted
*/
async isDenylisted(account: string): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isDenylistedMoveCall(tx, account)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Check if DVN is paused
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the paused status
*/
isPausedMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('is_paused'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Check if DVN worker is paused
* @returns Promise<boolean> - True if the worker is paused
*/
async isPaused(): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isPausedMoveCall(tx)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Check if an address is a registered DVN signer
* @param tx - The transaction to add the move call to
* @param signer - The signer public key as bytes
* @returns Transaction result containing the signer status
*/
isSignerMoveCall(tx: Transaction, signer: Uint8Array | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('is_signer'),
arguments: [tx.object(this.objects.dvn), asBytes(tx, signer)],
})
}
/**
* Check if an address is a registered DVN signer
* @param signer - The signer public key as bytes
* @returns Promise<boolean> - True if the address is a registered signer
*/
async isSigner(signer: Uint8Array): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isSignerMoveCall(tx, signer)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Get DVN price feed address
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the price feed address
*/
priceFeedMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('price_feed'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get DVN price feed address
* @returns Promise<string> - The price feed address
*/
async priceFeed(): Promise<string> {
return executeSimulate(
this.client,
(tx) => {
this.priceFeedMoveCall(tx)
},
(result) => bcs.Address.parse(result[0].value)
)
}
/**
* Get DVN quorum threshold
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the quorum threshold
*/
quorumMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('quorum'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get DVN quorum threshold
* @returns Promise<bigint> - The quorum threshold
*/
async quorum(): Promise<bigint> {
return executeSimulate(
this.client,
(tx) => {
this.quorumMoveCall(tx)
},
(result) => BigInt(bcs.U64.parse(result[0].value))
)
}
/**
* Get the total count of registered DVN signers
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the signer count
*/
signerCountMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('signer_count'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get the total count of registered DVN signers
* @returns Promise<bigint> - The number of registered signers
*/
async signerCount(): Promise<bigint> {
return executeSimulate(
this.client,
(tx) => {
this.signerCountMoveCall(tx)
},
(result) => BigInt(bcs.U64.parse(result[0].value))
)
}
/**
* Get all registered DVN signers
* @param tx - The transaction to add the move call to
* @returns Transaction result containing array of signer public keys
*/
signersMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('signers'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get all registered DVN signers
* @returns Promise<Uint8Array[]> - Array of signer public keys as byte arrays
*/
async signers(): Promise<Uint8Array[]> {
return executeSimulate(
this.client,
(tx) => {
this.signersMoveCall(tx)
},
(result) => {
const parsed = bcs.vector(bcs.vector(bcs.u8())).parse(result[0].value)
return parsed.map((signer) => Buffer.from(signer))
}
)
}
/**
* Get supported option types for a destination EID
* @param tx - The transaction to add the move call to
* @param dstEid - Destination endpoint ID
* @returns Transaction result containing supported option types
*/
supportedOptionTypesMoveCall(tx: Transaction, dstEid: number | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('supported_option_types'),
arguments: [tx.object(this.objects.dvn), asU32(tx, dstEid)],
})
}
/**
* Get supported option types for a destination EID
* @param dstEid - Destination endpoint ID
* @returns Promise<Uint8Array> - Array of supported option types as bytes
*/
async supportedOptionTypes(dstEid: number): Promise<Uint8Array> {
return executeSimulate(
this.client,
(tx) => {
this.supportedOptionTypesMoveCall(tx, dstEid)
},
(result) => {
const parsed = bcs.vector(bcs.u8()).parse(result[0].value)
return Buffer.from(parsed)
}
)
}
/**
* Get DVN Verifier ID (VID)
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the VID
*/
vidMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('vid'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get DVN VID (Verifier ID)
* @returns Promise<number> - The DVN verifier ID
*/
async vid(): Promise<number> {
return executeSimulate(
this.client,
(tx) => {
this.vidMoveCall(tx)
},
(result) => bcs.U32.parse(result[0].value)
)
}
/**
* Get DVN worker capability address
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the worker capability address
*/
workerCapAddressMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('worker_cap_address'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get DVN worker capability address
* @returns Promise<string> - The worker capability address
*/
async workerCapAddress(): Promise<string> {
return executeSimulate(
this.client,
(tx) => {
this.workerCapAddressMoveCall(tx)
},
(result) => bcs.Address.parse(result[0].value)
)
}
/**
* Get DVN worker fee library address
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the worker fee library address
*/
workerFeeLibMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('worker_fee_lib'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Get DVN worker fee library address
* @returns Promise<string> - The worker fee library address
*/
async workerFeeLib(): Promise<string> {
return executeSimulate(
this.client,
(tx) => {
this.workerFeeLibMoveCall(tx)
},
(result) => bcs.Address.parse(result[0].value)
)
}
/**
* Get admin capability ID from admin address
* @param tx - The transaction to add the move call to
* @param admin - The admin address
* @returns Transaction result containing the admin capability ID
*/
adminCapIdMoveCall(tx: Transaction, admin: string | TransactionArgument): TransactionResult {
return tx.moveCall({
target: this.#target('admin_cap_id'),
arguments: [tx.object(this.objects.dvn), asAddress(tx, admin)],
})
}
/**
* Get admin capability ID from admin address
* @param admin - The admin address
* @returns Promise<string> - The admin capability ID
*/
async adminCapId(admin: string): Promise<string> {
return executeSimulate(
this.client,
(tx) => {
this.adminCapIdMoveCall(tx, admin)
},
(result) => bcs.Address.parse(result[0].value)
)
}
/**
* Check if PTB builder has been initialized
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the PTB builder initialization status
*/
isPtbBuilderInitializedMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: this.#target('is_ptb_builder_initialized'),
arguments: [tx.object(this.objects.dvn)],
})
}
/**
* Check if PTB builder has been initialized
* @returns Promise<boolean> - True if the PTB builder has been initialized
*/
async isPtbBuilderInitialized(): Promise<boolean> {
return executeSimulate(
this.client,
(tx) => {
this.isPtbBuilderInitializedMoveCall(tx)
},
(result) => bcs.Bool.parse(result[0].value)
)
}
/**
* Get DVN object address from worker registry using this DVN's worker capability (as a move call)
* This function chains Move calls to decode worker info and extract the DVN object address
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the DVN object address
*/
getDvnObjectAddressMoveCall(tx: Transaction): TransactionResult {
// Step 1: Get this DVN's worker capability address
const workerCapAddress = this.workerCapAddressMoveCall(tx)
// Step 2: Get worker info bytes from registry
const workerInfoBytes = this.moduleManager
.getWorkerRegistry(this.client)
.getWorkerInfoMoveCall(tx, workerCapAddress)
// Step 3: Decode worker info using worker_common::worker_info_v1::decode
const workerInfo = tx.moveCall({
target: `${this.moduleManager.packages.workerCommon}::worker_info_v1::decode`,
arguments: [workerInfoBytes],
})
// Step 4: Extract worker_info field from decoded WorkerInfoV1
const dvnInfoBytes = tx.moveCall({
target: `${this.moduleManager.packages.workerCommon}::worker_info_v1::worker_info`,
arguments: [workerInfo],
})
// Step 5: Decode DVN info using dvn::dvn_info_v1::decode
const dvnInfo = tx.moveCall({
target: `${this.packageId}::dvn_info_v1::decode`,
arguments: [dvnInfoBytes],
})
// Step 6: Extract dvn_object address from decoded DVNInfoV1
return tx.moveCall({
target: `${this.packageId}::dvn_info_v1::dvn_object`,
arguments: [dvnInfo],
})
}
/**
* Get DVN object address from worker registry using this DVN's worker capability
* This function uses Move calls to decode worker info and extract the DVN object address
* @returns Promise<string> - The DVN object address
* @throws Will throw an error if worker info is not found or if decoding fails
*/
async getDvnObjectAddress(): Promise<string> {
return executeSimulate(
this.client,
(tx) => {
this.getDvnObjectAddressMoveCall(tx)
},
(result) => {
// The result is the DVN object address directly from the Move call chain
return bcs.Address.parse(result[0].value)
}
)
}
// === Witness Functions ===
/**
* Create a LayerZero witness for DVN package whitelist registration
* @param tx - The transaction to add the move call to
* @returns Transaction result containing the LayerZero witness
*/
createLayerZeroWitnessMoveCall(tx: Transaction): TransactionResult {
return tx.moveCall({
target: `${this.packageId}::dvn_witness::new`,
arguments: [],
})
}
// === Hash Functions ===
/**
* Create a verify hash for packet verification
* @param tx - The transaction to add the move call to
* @param packetHeader - The packet header as bytes
* @param payloadHash - The payload hash as bytes
* @param confirmations - Required confirmations count
* @param target - Target address for verification
* @param vid - Verifier ID
* @param expiration - Signature expiration timestamp
* @returns Transaction result containing the verify hash
*/
createVerifyHashMoveCall(
tx: Transaction,
packetHeader: Uint8Array | TransactionArgument,
payloadHash: Uint8Array | TransactionArgument,
confirmations: bigint | number | string | TransactionArgument,
target: string | TransactionArgument,
vid: number | TransactionArgument,
expiration: bigint | number | string | TransactionArgument
): TransactionResult {
return tx.moveCall({
target: this.#target('create_verify_hash', 'hashes'),
arguments: [
asBytes(tx, packetHeader),
asBytes(tx, payloadHash),
asU64(tx, confirmations),
asAddress(tx, target),
asU32(tx, vid),
asU64(tx, expiration),
],
})
}
/**
* Create a verify hash for packet verification
* @param packetHeader - The packet header as bytes
* @param payloadHash - The payload hash as bytes
* @param confirmations - Required confirmations count
* @param target - Target address for verification
* @param vid - Verifier ID
* @param expiration - Signature expiration timestamp
* @returns Promise<Uint8Array> - The verify hash as bytes
*/
async createVerifyHash(
packetHeader: Uint8Array,
payloadHash: Uint8Array,
confirmations: bigint,
target: string,
vid: number,
expiration: bigint
): Promise<Uint8Array> {
return executeSimulate(
this.client,
(tx) => {
this.createVerifyHashMoveCall(tx, packetHeader, payloadHash, confirmations, target, vid, expiration)
},
(result) => {
const bytes32Struct = Bytes32Bcs.parse(result[0].value)
return Buffer.from(bytes32Struct.bytes)
}
)
}
/**
* Create a set DVN signer hash for signature verification
* @param tx - The transaction to add the move call to
* @param signer - The signer public key as bytes
* @param active - Whether to activate or deactivate the signer
* @param vid - Verifier ID
* @param expiration - Signature expiration timestamp
* @returns Transaction result containing the set DVN signer hash
*/
createSetDvnSignerHashMoveCall(
tx: Transaction,
signer: Uint8Array | TransactionArgument,
active: boolean | TransactionArgument,
vid: number | TransactionArgument,
expiration: bigint | number | string | TransactionArgument
): TransactionResult {
return tx.moveCall({
target: this.#target('create_set_dvn_signer_hash', 'hashes'),
arguments: [asBytes(tx, signer), asBool(tx, active), asU32(tx, vid), asU64(tx, expiration)],
})
}
/**
* Create a set DVN signer hash for signature verification
* @param signer - The signer public key as bytes
* @param active - Whether to activate or deactivate the signer
* @param vid - Verifier ID
* @param expiration - Signature expiration timestamp
* @returns Promise<Uint8Array> - The set DVN signer hash as bytes
*/
async createSetDvnSignerHash(
signer: Uint8Array,
active: boolean,
vid: number,
expiration: bigint
): Promise<Uint8Array> {
return executeSimulate(
this.client,
(tx) => {
this.createSetDvnSignerHashMoveCall(tx, signer, active, vid, expiration)
},
(result) => {
const bytes32Struct = Bytes32Bcs.parse(result[0].value)
return Buffer.from(bytes32Struct.bytes)
}
)
}
/**
* Create a set quorum hash for signature verification
* @param tx - The transaction to add the move call to
* @param quorum - The new quorum threshold
* @param vid - Verifier ID
* @param expiration - Signature expiration timestamp
* @returns Transaction result containing the set quorum hash
*/
createSetQuorumHashMoveCall(
tx: Transaction,
quorum: bigint | number | string | TransactionArgument,
vid: nu