@hyperlane-xyz/sdk
Version:
The official SDK for the Hyperlane Network
515 lines • 17.4 kB
JavaScript
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