UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

515 lines 17.4 kB
import { PublicKey } from '@solana/web3.js'; import { assert } from '@hyperlane-xyz/utils'; import { SealevelInterchainGasPaymasterConfig, SealevelInterchainGasPaymasterConfigSchema, } from '../../gas/adapters/serialization.js'; import { SealevelAccountDataWrapper, SealevelInstructionWrapper, getSealevelAccountDataSchema, } from '../../utils/sealevelSerialization.js'; /** * Hyperlane Token Borsh Schema */ // Should match https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/libraries/hyperlane-sealevel-token/src/accounts.rs#L25C12-L25C26 export class SealevelHyperlaneTokenData { fields; /// The bump seed for this PDA. bump; /// The address of the mailbox contract. mailbox; mailbox_pubkey; /// The Mailbox process authority specific to this program as the recipient. mailbox_process_authority; mailbox_process_authority_pubkey; /// The dispatch authority PDA's bump seed. dispatch_authority_bump; /// The decimals of the local token. decimals; /// The decimals of the remote token. remote_decimals; /// Access control owner. owner; owner_pub_key; /// The interchain security module. interchain_security_module; interchain_security_module_pubkey; // The interchain gas paymaster interchain_gas_paymaster; interchain_gas_paymaster_pubkey; interchain_gas_paymaster_account_pubkey; // Gas amounts by destination destination_gas; /// Remote routers. remote_routers; remote_router_pubkeys; constructor(fields) { this.fields = fields; Object.assign(this, fields); this.mailbox_pubkey = new PublicKey(this.mailbox); this.mailbox_process_authority_pubkey = new PublicKey(this.mailbox_process_authority); this.owner_pub_key = this.owner ? new PublicKey(this.owner) : undefined; this.interchain_security_module_pubkey = this.interchain_security_module ? new PublicKey(this.interchain_security_module) : undefined; this.interchain_gas_paymaster_pubkey = this.interchain_gas_paymaster ?.program_id ? new PublicKey(this.interchain_gas_paymaster.program_id) : undefined; this.interchain_gas_paymaster_account_pubkey = this.interchain_gas_paymaster ?.igp_account ? new PublicKey(this.interchain_gas_paymaster.igp_account) : undefined; this.remote_router_pubkeys = new Map(); if (this.remote_routers) { for (const [k, v] of this.remote_routers.entries()) { this.remote_router_pubkeys.set(k, new PublicKey(v)); } } } } export const SealevelHyperlaneTokenDataSchema = new Map([ [ SealevelAccountDataWrapper, getSealevelAccountDataSchema(SealevelHyperlaneTokenData), ], [ SealevelHyperlaneTokenData, { kind: 'struct', fields: [ ['bump', 'u8'], ['mailbox', [32]], ['mailbox_process_authority', [32]], ['dispatch_authority_bump', 'u8'], ['decimals', 'u8'], ['remote_decimals', 'u8'], ['owner', { kind: 'option', type: [32] }], ['interchain_security_module', { kind: 'option', type: [32] }], [ 'interchain_gas_paymaster', { kind: 'option', type: SealevelInterchainGasPaymasterConfig, }, ], ['destination_gas', { kind: 'map', key: 'u32', value: 'u64' }], ['remote_routers', { kind: 'map', key: 'u32', value: [32] }], ], }, ], [ SealevelInterchainGasPaymasterConfig, SealevelInterchainGasPaymasterConfigSchema, ], ]); /** * Transfer Remote Borsh Schema */ // Should match Instruction in https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/libraries/hyperlane-sealevel-token/src/instruction.rs export var SealevelHypTokenInstruction; (function (SealevelHypTokenInstruction) { SealevelHypTokenInstruction[SealevelHypTokenInstruction["Init"] = 0] = "Init"; SealevelHypTokenInstruction[SealevelHypTokenInstruction["TransferRemote"] = 1] = "TransferRemote"; SealevelHypTokenInstruction[SealevelHypTokenInstruction["EnrollRemoteRouter"] = 2] = "EnrollRemoteRouter"; SealevelHypTokenInstruction[SealevelHypTokenInstruction["EnrollRemoteRouters"] = 3] = "EnrollRemoteRouters"; SealevelHypTokenInstruction[SealevelHypTokenInstruction["SetDestinationGasConfigs"] = 4] = "SetDestinationGasConfigs"; SealevelHypTokenInstruction[SealevelHypTokenInstruction["SetInterchainSecurityModule"] = 5] = "SetInterchainSecurityModule"; SealevelHypTokenInstruction[SealevelHypTokenInstruction["SetInterchainGasPaymaster"] = 6] = "SetInterchainGasPaymaster"; SealevelHypTokenInstruction[SealevelHypTokenInstruction["TransferOwnership"] = 7] = "TransferOwnership"; })(SealevelHypTokenInstruction || (SealevelHypTokenInstruction = {})); /** * Human-readable names for Hyperlane Token instructions */ export const SealevelHypTokenInstructionName = { [SealevelHypTokenInstruction.Init]: 'Init', [SealevelHypTokenInstruction.TransferRemote]: 'TransferRemote', [SealevelHypTokenInstruction.EnrollRemoteRouter]: 'EnrollRemoteRouter', [SealevelHypTokenInstruction.EnrollRemoteRouters]: 'EnrollRemoteRouters', [SealevelHypTokenInstruction.SetDestinationGasConfigs]: 'SetDestinationGasConfigs', [SealevelHypTokenInstruction.SetInterchainSecurityModule]: 'SetInterchainSecurityModule', [SealevelHypTokenInstruction.SetInterchainGasPaymaster]: 'SetInterchainGasPaymaster', [SealevelHypTokenInstruction.TransferOwnership]: 'TransferOwnership', }; export class SealevelTransferRemoteInstruction { fields; destination_domain; recipient; recipient_pubkey; amount_or_id; constructor(fields) { this.fields = fields; Object.assign(this, fields); this.recipient_pubkey = new PublicKey(this.recipient); } } export const SealevelTransferRemoteSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelTransferRemoteInstruction], ], }, ], [ SealevelTransferRemoteInstruction, { kind: 'struct', fields: [ ['destination_domain', 'u32'], ['recipient', [32]], ['amount_or_id', 'u256'], ], }, ], ]); // ============================================================================ // Cross-Collateral Instruction Schemas // ============================================================================ export var SealevelCCInstructionKind; (function (SealevelCCInstructionKind) { SealevelCCInstructionKind[SealevelCCInstructionKind["SetCrossCollateralRouters"] = 0] = "SetCrossCollateralRouters"; SealevelCCInstructionKind[SealevelCCInstructionKind["TransferRemoteTo"] = 1] = "TransferRemoteTo"; SealevelCCInstructionKind[SealevelCCInstructionKind["HandleLocal"] = 2] = "HandleLocal"; SealevelCCInstructionKind[SealevelCCInstructionKind["HandleLocalAccountMetas"] = 3] = "HandleLocalAccountMetas"; })(SealevelCCInstructionKind || (SealevelCCInstructionKind = {})); export class SealevelCCTransferRemoteToInstruction { fields; destination_domain; recipient; amount_or_id; target_router; constructor(fields) { this.fields = fields; Object.assign(this, fields); } } export const SealevelCCTransferRemoteToSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelCCTransferRemoteToInstruction], ], }, ], [ SealevelCCTransferRemoteToInstruction, { kind: 'struct', fields: [ ['destination_domain', 'u32'], ['recipient', [32]], ['amount_or_id', 'u256'], ['target_router', [32]], ], }, ], ]); export class SealevelCCHandleLocalInstruction { fields; sender_program_id; message; constructor(fields) { this.fields = fields; Object.assign(this, fields); } } export const SealevelCCHandleLocalSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelCCHandleLocalInstruction], ], }, ], [ SealevelCCHandleLocalInstruction, { kind: 'struct', fields: [ ['sender_program_id', [32]], ['message', ['u8']], ], }, ], ]); /** * Encodes a TokenMessage matching the Rust `hyperlane_warp_route::TokenMessage`. * Layout: recipient (32 bytes) + amount (32 bytes, big-endian U256) + metadata (variable). */ export function encodeTokenMessage(recipient, amount, metadata = new Uint8Array(0)) { assert(recipient.length === 32, 'TokenMessage recipient must be 32 bytes'); assert(amount >= 0n && amount < 2n ** 256n, 'TokenMessage amount out of U256 range'); const buf = Buffer.alloc(64 + metadata.length); buf.set(recipient, 0); const amountHex = amount.toString(16).padStart(64, '0'); buf.set(Buffer.from(amountHex, 'hex'), 32); if (metadata.length > 0) { buf.set(metadata, 64); } return buf; } // ============================================================================ // Governance Instruction Schemas // ============================================================================ /** * RemoteRouterConfig - Configuration for a remote router * Matches: rust/sealevel/libraries/hyperlane-sealevel-connection-client/src/router.rs */ export class SealevelRemoteRouterConfig { domain; router; // Option<H256> - 32-byte address get routerAddress() { return this.router ? `0x${Buffer.from(this.router).toString('hex')}` : null; } constructor(fields) { Object.assign(this, fields); } } export const SealevelRemoteRouterConfigSchema = { kind: 'struct', fields: [ ['domain', 'u32'], ['router', { kind: 'option', type: [32] }], ], }; /** * GasRouterConfig - Configuration for destination gas * Matches: rust/sealevel/libraries/hyperlane-sealevel-connection-client/src/gas_router.rs */ export class SealevelGasRouterConfig { domain; gas; // Option<u64> constructor(fields) { Object.assign(this, fields); } } export const SealevelGasRouterConfigSchema = { kind: 'struct', fields: [ ['domain', 'u32'], ['gas', { kind: 'option', type: 'u64' }], ], }; /** * EnrollRemoteRouter instruction data * Matches: EnrollRemoteRouter(RemoteRouterConfig) */ export class SealevelEnrollRemoteRouterInstruction { config; constructor(fields) { Object.assign(this, fields); } } export const SealevelEnrollRemoteRouterInstructionSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelEnrollRemoteRouterInstruction], ], }, ], [ SealevelEnrollRemoteRouterInstruction, { kind: 'struct', fields: [['config', SealevelRemoteRouterConfig]], }, ], [SealevelRemoteRouterConfig, SealevelRemoteRouterConfigSchema], ]); /** * EnrollRemoteRouters instruction data * Matches: EnrollRemoteRouters(Vec<RemoteRouterConfig>) */ export class SealevelEnrollRemoteRoutersInstruction { configs; constructor(fields) { Object.assign(this, fields); } } export const SealevelEnrollRemoteRoutersInstructionSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelEnrollRemoteRoutersInstruction], ], }, ], [ SealevelEnrollRemoteRoutersInstruction, { kind: 'struct', fields: [['configs', [SealevelRemoteRouterConfig]]], }, ], [SealevelRemoteRouterConfig, SealevelRemoteRouterConfigSchema], ]); /** * SetDestinationGasConfigs instruction data * Matches: SetDestinationGasConfigs(Vec<GasRouterConfig>) */ export class SealevelSetDestinationGasConfigsInstruction { configs; constructor(fields) { Object.assign(this, fields); } } export const SealevelSetDestinationGasConfigsInstructionSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelSetDestinationGasConfigsInstruction], ], }, ], [ SealevelSetDestinationGasConfigsInstruction, { kind: 'struct', fields: [['configs', [SealevelGasRouterConfig]]], }, ], [SealevelGasRouterConfig, SealevelGasRouterConfigSchema], ]); /** * SetInterchainSecurityModule instruction data * Matches: SetInterchainSecurityModule(Option<Pubkey>) */ export class SealevelSetInterchainSecurityModuleInstruction { ism; // Option<Pubkey> ismPubkey; constructor(fields) { Object.assign(this, fields); this.ismPubkey = this.ism ? new PublicKey(this.ism) : undefined; } } export const SealevelSetInterchainSecurityModuleInstructionSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelSetInterchainSecurityModuleInstruction], ], }, ], [ SealevelSetInterchainSecurityModuleInstruction, { kind: 'struct', fields: [['ism', { kind: 'option', type: [32] }]], }, ], ]); /** * InterchainGasPaymasterType with inner Pubkey for instruction serialization * This represents the tuple (Pubkey, InterchainGasPaymasterType) in Rust * Matches: rust/sealevel/programs/hyperlane-sealevel-igp/src/accounts.rs * * Note: The Rust enum InterchainGasPaymasterType has variants: * Igp(Pubkey) = 0 * OverheadIgp(Pubkey) = 1 * But in the warp route instruction, it's serialized as Option<(Pubkey, InterchainGasPaymasterType)> * where InterchainGasPaymasterType becomes (u8 discriminator, Pubkey) */ export class SealevelIgpConfig { programId; // Pubkey - the IGP program igpType; // 0 = Igp, 1 = OverheadIgp igpAccount; // Pubkey - the IGP account (inner data of the enum) programIdPubkey; igpAccountPubkey; get igpTypeName() { return this.igpType === 0 ? 'Igp' : 'OverheadIgp'; } constructor(fields) { Object.assign(this, fields); this.programIdPubkey = new PublicKey(this.programId); this.igpAccountPubkey = new PublicKey(this.igpAccount); } } export const SealevelIgpConfigSchema = { kind: 'struct', fields: [ ['programId', [32]], ['igpType', 'u8'], ['igpAccount', [32]], ], }; /** * SetInterchainGasPaymaster instruction data * Matches: SetInterchainGasPaymaster(Option<(Pubkey, InterchainGasPaymasterType)>) */ export class SealevelSetInterchainGasPaymasterInstruction { igpConfig; constructor(fields) { Object.assign(this, fields); } } export const SealevelSetInterchainGasPaymasterInstructionSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelSetInterchainGasPaymasterInstruction], ], }, ], [ SealevelSetInterchainGasPaymasterInstruction, { kind: 'struct', fields: [['igpConfig', { kind: 'option', type: SealevelIgpConfig }]], }, ], [SealevelIgpConfig, SealevelIgpConfigSchema], ]); /** * TransferOwnership instruction data for warp routes * Matches: TransferOwnership(Option<Pubkey>) */ export class SealevelHypTokenTransferOwnershipInstruction { newOwner; // Option<Pubkey> newOwnerPubkey; constructor(fields) { Object.assign(this, fields); this.newOwnerPubkey = this.newOwner ? new PublicKey(this.newOwner) : undefined; } } export const SealevelHypTokenTransferOwnershipInstructionSchema = new Map([ [ SealevelInstructionWrapper, { kind: 'struct', fields: [ ['instruction', 'u8'], ['data', SealevelHypTokenTransferOwnershipInstruction], ], }, ], [ SealevelHypTokenTransferOwnershipInstruction, { kind: 'struct', fields: [['newOwner', { kind: 'option', type: [32] }]], }, ], ]); //# sourceMappingURL=serialization.js.map