@hyperlane-xyz/cli
Version:
A command-line utility for common Hyperlane operations
886 lines (863 loc) • 8.8 MB
JavaScript
export const id = 79;
export const ids = [79];
export const modules = {
/***/ 13079:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
SealevelProtocolProvider: () => (/* reexport */ SvmProtocolProvider)
});
// UNUSED EXPORTS: DeployStageKind, HYPERLANE_SVM_PROGRAM_BYTES, SealevelHookArtifactManager, SealevelIgpHookReader, SealevelIgpHookWriter, SealevelIsmArtifactManager, SealevelMailboxArtifactManager, SealevelMailboxReader, SealevelMailboxWriter, SealevelMerkleTreeHookReader, SealevelMerkleTreeHookWriter, SealevelMessageIdMultisigIsmReader, SealevelMessageIdMultisigIsmWriter, SealevelProvider, SealevelSigner, SealevelTestIsmReader, SealevelTestIsmWriter, SealevelValidatorAnnounceArtifactManager, SealevelValidatorAnnounceReader, SealevelValidatorAnnounceWriter, SvmCrossCollateralTokenReader, SvmCrossCollateralTokenWriter, buildSetDefaultIsmInstruction, buildTransactionMessage, convertLegacySolanaTransaction, createDeployProgramPlan, createRpc, createUpgradeProgramPlan, decodeCrossCollateralStateAccount, decodeHyperlaneTokenAccount, decodeIgpAccount, decodeIgpProgramDataAccount, decodeMailboxInboxAccount, decodeMailboxOutboxAccount, decodeMultisigIsmAccessControlAccount, decodeMultisigIsmDomainDataAccount, decodeOverheadIgpAccount, decodeTestIsmStorageAccount, decodeValidatorAnnounceAccount, decodeValidatorStorageLocationsAccount, deriveAtaPayerPda, deriveCrossCollateralDispatchAuthorityPda, deriveCrossCollateralStatePda, deriveHyperlaneTokenPda, deriveIgpAccountPda, deriveIgpProgramDataPda, deriveMailboxInboxPda, deriveMailboxOutboxPda, deriveMultisigIsmAccessControlPda, deriveMultisigIsmDomainDataPda, deriveOverheadIgpAccountPda, deriveReplayProtectionPda, deriveTestIsmStoragePda, deriveValidatorAnnouncePda, deriveValidatorStorageLocationsPda, executeDeployPlan, fetchMailboxInboxAccount, fetchMultisigIsmAccessControl, getComputeBudgetInstructions, getMultisigIsmTransferOwnershipInstruction, getProgramUpgradeAuthority, getSetUpgradeAuthorityInstruction, isLegacySolanaTransaction, resolveProgram, serializeUnsignedTransaction
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+addresses@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/addresses/dist/index.node.mjs
var index_node = __webpack_require__(89735);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+instructions@6.1.0_typescript@6.0.2/node_modules/@solana/instructions/dist/index.node.mjs
var dist_index_node = __webpack_require__(49957);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+transaction-messages@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/transaction-messages/dist/index.node.mjs
var transaction_messages_dist_index_node = __webpack_require__(65175);
// EXTERNAL MODULE: ../utils/dist/validation.js
var validation = __webpack_require__(21387);
// EXTERNAL MODULE: ../utils/dist/logging.js
var logging = __webpack_require__(94523);
;// CONCATENATED MODULE: ../svm-sdk/dist/constants.js
const PROGRAM_INSTRUCTION_DISCRIMINATOR = new Uint8Array([
1, 1, 1, 1, 1, 1, 1, 1,
]);
const constants_SYSTEM_PROGRAM_ADDRESS = '11111111111111111111111111111111';
const RENT_SYSVAR_ADDRESS = 'SysvarRent111111111111111111111111111111111';
const CLOCK_SYSVAR_ADDRESS = 'SysvarC1ock11111111111111111111111111111111';
// Kept as literals to avoid adding a direct '@solana/sysvars' dependency here.
const SPL_NOOP_PROGRAM_ADDRESS = 'noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV';
const constants_LOADER_V3_PROGRAM_ADDRESS = 'BPFLoaderUpgradeab1e11111111111111111111111';
// Solana hard limit on account data size.
const MAX_ACCOUNT_DATA_SIZE = 10_485_760;
// Fixed base fee per signature on Solana.
// https://solana.com/docs/core/fees#base-fee
const LAMPORTS_PER_SIGNATURE = 5_000;
// https://spl.solana.com/token
const SPL_TOKEN_PROGRAM_ADDRESS = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
// https://spl.solana.com/token-2022
const TOKEN_2022_PROGRAM_ADDRESS = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb';
// https://github.com/metaplex-foundation/mpl-token-metadata/blob/c314930196b6b16e1ba8fefdf206e9af7b0e4c37/programs/token-metadata/program/src/lib.rs#L25
const METAPLEX_METADATA_PROGRAM_ADDRESS = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s';
// Hand-rolled to avoid adding @solana-program/compute-budget as a dependency.
const COMPUTE_BUDGET_PROGRAM_ID = (0,index_node/* address */.hl)('ComputeBudget111111111111111111111111111111');
// Default compute unit budget for SVM deployment transactions.
const constants_DEFAULT_COMPUTE_UNITS = 400_000;
//# sourceMappingURL=constants.js.map
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+rpc@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/rpc/dist/index.node.mjs + 7 modules
var rpc_dist_index_node = __webpack_require__(15328);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+accounts@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/accounts/dist/index.node.mjs
var accounts_dist_index_node = __webpack_require__(96659);
;// CONCATENATED MODULE: ../svm-sdk/dist/rpc.js
function createRpc(url) {
return (0,rpc_dist_index_node/* createSolanaRpc */.AP)(url);
}
// Returns MaybeEncodedAccount to preserve Kit's explicit existence-check shape.
// Callers should branch on .exists or use assertAccountExists().
async function fetchAccount(rpc, address) {
return fetchEncodedAccount(rpc, address);
}
/**
* Fetches raw account data bytes, returning null when the account does not exist.
*/
async function rpc_fetchAccountDataRaw(rpc, address) {
const maybeAccount = await (0,accounts_dist_index_node/* fetchEncodedAccount */.oG)(rpc, address, {
commitment: 'confirmed',
});
if (!maybeAccount.exists)
return null;
return maybeAccount.data;
}
//# sourceMappingURL=rpc.js.map
;// CONCATENATED MODULE: ../svm-sdk/dist/clients/provider.js
class SvmProvider {
rpc;
rpcUrls;
static async connect(rpcUrls, _chainId, _extraParams) {
(0,validation/* assert */.v)(rpcUrls.length > 0, 'At least one RPC URL is required');
const rpc = createRpc(rpcUrls[0]);
return new SvmProvider(rpc, rpcUrls);
}
constructor(rpc, rpcUrls) {
this.rpc = rpc;
this.rpcUrls = rpcUrls;
}
// ### QUERY BASE ###
async isHealthy() {
try {
await this.rpc.getSlot().send();
return true;
}
catch (error) {
logging/* rootLogger */.Jk.debug('SVM health check failed', { error });
return false;
}
}
getRpcUrls() {
return this.rpcUrls;
}
async getHeight() {
const slot = await this.rpc.getSlot().send();
return Number(slot);
}
async getBalance(req) {
const balance = await this.rpc.getBalance((0,index_node/* address */.hl)(req.address)).send();
return balance.value;
}
async getTotalSupply(_req) {
throw new Error('getTotalSupply not supported on Sealevel');
}
async estimateTransactionFee(req) {
const signerAddresses = new Set();
// Collect signers from instruction account metas
for (const ix of req.transaction.instructions) {
if (ix.accounts) {
for (const account of ix.accounts) {
if (account.role >= dist_index_node/* AccountRole */.Uv.READONLY_SIGNER) {
signerAddresses.add(account.address);
}
}
}
}
// Collect additional signers
for (const signer of req.transaction.additionalSigners ?? []) {
signerAddresses.add(signer.address);
}
// +1 for fee payer (may already be in the set, but overcount to be safe)
const numSigners = signerAddresses.size + 1;
const gasPrice = await this.queryBaseFeePerSignature();
const fee = BigInt(numSigners) * BigInt(gasPrice);
const gasUnits = BigInt(req.transaction.computeUnits ?? constants_DEFAULT_COMPUTE_UNITS);
return { gasUnits, gasPrice, fee };
}
/**
* Queries the RPC for the base fee per signature using a minimal
* unsigned message.
*/
async queryBaseFeePerSignature() {
try {
const { value: latestBlockhash } = await this.rpc
.getLatestBlockhash()
.send();
const baseMessage = (0,transaction_messages_dist_index_node/* createTransactionMessage */.mN)({ version: 0 });
const withFeePayer = (0,transaction_messages_dist_index_node/* setTransactionMessageFeePayer */.t_)(constants_SYSTEM_PROGRAM_ADDRESS, baseMessage);
const withLifetime = (0,transaction_messages_dist_index_node/* setTransactionMessageLifetimeUsingBlockhash */.S$)(latestBlockhash, withFeePayer);
const compiled = (0,transaction_messages_dist_index_node/* compileTransactionMessage */.rt)(withLifetime);
const messageBytes = (0,transaction_messages_dist_index_node/* getCompiledTransactionMessageEncoder */.dU)().encode(compiled);
const base64Message = Buffer.from(messageBytes).toString('base64');
const result = await this.rpc.getFeeForMessage(base64Message).send();
if (result.value != null) {
return Number(result.value);
}
}
catch (error) {
logging/* rootLogger */.Jk.debug('getFeeForMessage failed, using static fallback', {
error,
});
}
return LAMPORTS_PER_SIGNATURE;
}
async isMessageDelivered(_req) {
throw new Error('isMessageDelivered not supported on Sealevel, use the Artifact API instead');
}
// ### QUERY WARP ###
async getToken(_req) {
throw new Error('getToken not supported on Sealevel, use the Artifact API instead');
}
async getRemoteRouters(_req) {
throw new Error('getRemoteRouters not supported on Sealevel, use the Artifact API instead');
}
async getBridgedSupply(_req) {
throw new Error('getBridgedSupply not supported on Sealevel, use the Artifact API instead');
}
async quoteRemoteTransfer(_req) {
throw new Error('quoteRemoteTransfer not supported on Sealevel, use the Artifact API instead');
}
}
//# sourceMappingURL=provider.js.map
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+codecs-strings@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/codecs-strings/dist/index.node.mjs
var codecs_strings_dist_index_node = __webpack_require__(98915);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+signers@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/signers/dist/index.node.mjs
var signers_dist_index_node = __webpack_require__(26285);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+transactions@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/transactions/dist/index.node.mjs
var transactions_dist_index_node = __webpack_require__(89331);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+keys@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/keys/dist/index.node.mjs
var keys_dist_index_node = __webpack_require__(27303);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+errors@6.1.0_typescript@6.0.2/node_modules/@solana/errors/dist/index.node.mjs
var errors_dist_index_node = __webpack_require__(13197);
// EXTERNAL MODULE: ../utils/dist/addresses.js
var addresses = __webpack_require__(93142);
// EXTERNAL MODULE: ../utils/dist/async.js
var dist_async = __webpack_require__(14918);
;// CONCATENATED MODULE: ../svm-sdk/dist/legacy-compat.js
/**
* Converts legacy @solana/web3.js Transaction objects to @solana/kit SvmTransaction format.
* Used when SDK adapters return legacy Transactions but the SvmSigner expects kit-format instructions.
*/
const SET_COMPUTE_UNIT_LIMIT_DISCRIMINATOR = 2;
function convertAccountMeta(meta) {
const address = (0,index_node/* address */.hl)(meta.pubkey.toBase58());
const role = meta.isSigner
? meta.isWritable
? dist_index_node/* AccountRole */.Uv.WRITABLE_SIGNER
: dist_index_node/* AccountRole */.Uv.READONLY_SIGNER
: meta.isWritable
? dist_index_node/* AccountRole */.Uv.WRITABLE
: dist_index_node/* AccountRole */.Uv.READONLY;
return { address, role };
}
function convertInstruction(ix) {
return {
programAddress: (0,index_node/* address */.hl)(ix.programId.toBase58()),
accounts: ix.keys.map(convertAccountMeta),
data: new Uint8Array(ix.data),
};
}
/**
* Converts a legacy @solana/web3.js Transaction to the SvmTransaction format
* expected by SvmSigner. The SetComputeUnitLimit instruction is extracted into
* `computeUnits` (the signer recreates it). All other instructions — including
* SetComputeUnitPrice — are preserved as-is.
*
* @param legacyTx Legacy Transaction returned by SDK adapters.
* @param extraSigners Keypairs that partial-signed the legacy tx (e.g. random
* wallet for message storage PDAs). Converted to @solana/kit TransactionSigners.
*/
async function convertLegacySolanaTransaction(legacyTx, extraSigners) {
let computeUnits;
const instructions = [];
for (const ix of legacyTx.instructions) {
const isComputeBudget = ix.programId.toBase58() === COMPUTE_BUDGET_PROGRAM_ID;
if (isComputeBudget &&
ix.data[0] === SET_COMPUTE_UNIT_LIMIT_DISCRIMINATOR &&
ix.data.length >= 5) {
// Extract compute unit limit — SvmSigner recreates this instruction
// from the `computeUnits` field via buildTransactionMessage.
const dataArr = new Uint8Array(ix.data);
computeUnits = new DataView(dataArr.buffer, dataArr.byteOffset).getUint32(1, true);
continue;
}
// Preserve all other instructions including SetComputeUnitPrice.
instructions.push(convertInstruction(ix));
}
let additionalSigners;
if (extraSigners?.length) {
additionalSigners = await Promise.all(extraSigners.map((kp) => (0,signers_dist_index_node/* createKeyPairSignerFromBytes */.Lt)(kp.secretKey)));
}
return {
instructions,
computeUnits,
additionalSigners,
};
}
/**
* Detects whether an object is a legacy @solana/web3.js Transaction
* by checking for the `programId` property on its first instruction.
*/
function isLegacySolanaTransaction(tx) {
if (typeof tx !== 'object' || tx === null)
return false;
// CAST: tx is narrowed to non-null object above; Partial<LegacyTransaction> ensures
// property access stays in sync with the interface.
const maybeIx = tx.instructions;
if (!Array.isArray(maybeIx) || maybeIx.length === 0)
return false;
const first = maybeIx[0];
return (typeof first === 'object' &&
first !== null &&
'programId' in first &&
!('programAddress' in first));
}
//# sourceMappingURL=legacy-compat.js.map
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+codecs-numbers@6.1.0_typescript@6.0.2/node_modules/@solana/codecs-numbers/dist/index.node.mjs
var codecs_numbers_dist_index_node = __webpack_require__(17991);
// EXTERNAL MODULE: ../../node_modules/.pnpm/@solana+rpc-types@6.1.0_fastestsmallesttextencoderdecoder@1.0.22_typescript@6.0.2/node_modules/@solana/rpc-types/dist/index.node.mjs
var rpc_types_dist_index_node = __webpack_require__(81133);
;// CONCATENATED MODULE: ../svm-sdk/dist/tx.js
// Max data per BPFLoaderUpgradeable Write tx: 1232 packet limit minus tx
// overhead. With 2 signers (payer != authority) overhead is ~355 bytes,
// giving ~877 bytes max. Use 850 to leave margin for all signer configs.
const tx_DEFAULT_WRITE_CHUNK_SIZE = 850;
const DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS = 1;
function createSetComputeUnitLimitInstruction(units) {
const data = new Uint8Array(5);
data[0] = 2;
new DataView(data.buffer).setUint32(1, units, true);
return { programAddress: COMPUTE_BUDGET_PROGRAM_ID, accounts: [], data };
}
function createSetComputeUnitPriceInstruction(microLamports) {
const data = new Uint8Array(9);
data[0] = 3;
new DataView(data.buffer).setBigUint64(1, microLamports, true);
return { programAddress: COMPUTE_BUDGET_PROGRAM_ID, accounts: [], data };
}
function getComputeBudgetInstructions(units = constants_DEFAULT_COMPUTE_UNITS, microLamports) {
const instructions = [
createSetComputeUnitLimitInstruction(units),
];
if (microLamports !== undefined && microLamports > 0) {
instructions.push(createSetComputeUnitPriceInstruction(BigInt(microLamports)));
}
return instructions;
}
function buildTransactionMessage(params) {
const { instructions, feePayer, recentBlockhash, lastValidBlockHeight, computeUnits = constants_DEFAULT_COMPUTE_UNITS, priorityFeeMicroLamports, } = params;
const computeBudgetIxs = getComputeBudgetInstructions(computeUnits, priorityFeeMicroLamports);
const allInstructions = [...computeBudgetIxs, ...instructions];
const txMessage = (0,transaction_messages_dist_index_node/* createTransactionMessage */.mN)({ version: 0 });
const withFeePayer = (0,signers_dist_index_node/* setTransactionMessageFeePayerSigner */.pt)(feePayer, txMessage);
const withLifetime = (0,transaction_messages_dist_index_node/* setTransactionMessageLifetimeUsingBlockhash */.S$)({ blockhash: recentBlockhash, lastValidBlockHeight }, withFeePayer);
return (0,transaction_messages_dist_index_node/* appendTransactionMessageInstructions */.Fx)(allInstructions, withLifetime);
}
function transactionToInstructions(tx) {
const computeUnits = tx.computeUnits ?? DEFAULT_COMPUTE_UNITS;
const computeBudgetIxs = getComputeBudgetInstructions(computeUnits);
return [...computeBudgetIxs, ...tx.instructions];
}
// ---------------------------------------------------------------------------
// Unsigned transaction serialization (Squads-compatible v0 format)
// ---------------------------------------------------------------------------
const base58Decoder = (0,codecs_strings_dist_index_node/* getBase58Decoder */.BC)();
const messageEncoder = (0,transaction_messages_dist_index_node/* getCompiledTransactionMessageEncoder */.dU)();
const shortU16Encoder = (0,codecs_numbers_dist_index_node/* getShortU16Encoder */.tD)();
/** Default blockhash (32 zero bytes) that needs to be replaced at submission time */
const DEFAULT_BLOCKHASH = (0,rpc_types_dist_index_node/* blockhash */.Ae)('11111111111111111111111111111111');
/**
* Builds the wire bytes of an unsigned versioned (v0) transaction.
* Prepends compact-u16 signature count + N zero-filled 64-byte signature
* slots to the compiled message bytes.
*/
function buildUnsignedTransactionBytes(numSigners, messageBytes) {
const sigCountBytes = shortU16Encoder.encode(numSigners);
const sigsLen = numSigners * 64;
const result = new Uint8Array(sigCountBytes.length + sigsLen + messageBytes.length);
result.set(sigCountBytes, 0);
// signature slots are already zero-filled by Uint8Array constructor
result.set(messageBytes, sigCountBytes.length + sigsLen);
return result;
}
/**
* Serializes an SvmTransaction into base58-encoded formats compatible
* with the Squads multisig UI.
*
* Produces two representations:
* - `transaction_base58`: full unsigned v0 transaction (signatures + message)
* - `message_base58`: compiled message only (no signature wrapper)
*
* Both use a default (all-zeros) blockhash since these are unsigned
* transactions intended for offline / multisig signing workflows.
*/
function serializeUnsignedTransaction(instructions, feePayer) {
const txMessage = (0,transaction_messages_dist_index_node/* createTransactionMessage */.mN)({ version: 0 });
const withFeePayer = (0,transaction_messages_dist_index_node/* setTransactionMessageFeePayer */.t_)(feePayer, txMessage);
const withLifetime = (0,transaction_messages_dist_index_node/* setTransactionMessageLifetimeUsingBlockhash */.S$)({ blockhash: DEFAULT_BLOCKHASH, lastValidBlockHeight: 0n }, withFeePayer);
const withInstructions = (0,transaction_messages_dist_index_node/* appendTransactionMessageInstructions */.Fx)(instructions, withLifetime);
const compiled = (0,transaction_messages_dist_index_node/* compileTransactionMessage */.rt)(withInstructions);
const messageBytes = messageEncoder.encode(compiled);
const transactionBytes = buildUnsignedTransactionBytes(compiled.header.numSignerAccounts, messageBytes);
return {
transactionBase58: base58Decoder.decode(transactionBytes),
messageBase58: base58Decoder.decode(messageBytes),
};
}
//# sourceMappingURL=tx.js.map
;// CONCATENATED MODULE: ../svm-sdk/dist/clients/signer.js
class SvmTransactionError extends Error {
constructor(signature, cause) {
super(`Transaction failed: ${signature}, err: ${JSON.stringify(cause, (_k, v) => (typeof v === 'bigint' ? v.toString() : v))}`);
this.name = 'SvmTransactionError';
this.cause = cause;
}
}
const base58Encoder = (0,codecs_strings_dist_index_node/* getBase58Encoder */.nZ)();
function parseKeyBytes(privateKey) {
// Try hex (32 bytes = 64 hex chars, 64 bytes = 128 hex chars)
const stripped = (0,addresses/* strip0x */.LL)(privateKey);
if (/^[0-9a-fA-F]{64}$/.test(stripped)) {
return new Uint8Array(Buffer.from(stripped, 'hex'));
}
if (/^[0-9a-fA-F]{128}$/.test(stripped)) {
return new Uint8Array(Buffer.from(stripped, 'hex'));
}
// Try base58
let keyBytes;
try {
keyBytes = base58Encoder.encode(privateKey);
}
catch (err) {
throw new Error(`Failed to parse private key. Expected hex (64 or 128 chars) or base58. ` +
`Base58 error: ${err instanceof Error ? err.message : String(err)}`);
}
if (keyBytes.length !== 32 && keyBytes.length !== 64) {
throw new Error(`Base58-decoded key has invalid length: ${keyBytes.length}. Expected 32 (private key) or 64 (keypair).`);
}
return keyBytes;
}
const RPC_COMMITMENT_LEVEL = 'confirmed';
/**
* Detects blockhash-not-found errors from sendTransaction.
* The RPC wraps it as a preflight failure (-32002) with the
* BlockhashNotFound error as its cause.
*/
function isBlockhashNotFoundError(error) {
if ((0,errors_dist_index_node/* isSolanaError */.zbS)(error, errors_dist_index_node/* SOLANA_ERROR__TRANSACTION_ERROR__BLOCKHASH_NOT_FOUND */.fmt)) {
return true;
}
if ((0,errors_dist_index_node/* isSolanaError */.zbS)(error, errors_dist_index_node/* SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE */.d0u)) {
return (0,errors_dist_index_node/* isSolanaError */.zbS)(error.cause, errors_dist_index_node/* SOLANA_ERROR__TRANSACTION_ERROR__BLOCKHASH_NOT_FOUND */.fmt);
}
return false;
}
class SvmSigner extends SvmProvider {
signer;
logger = logging/* rootLogger */.Jk.child({ module: 'SvmSigner' });
constructor(rpc, rpcUrls, signer) {
super(rpc, rpcUrls);
this.signer = signer;
}
static async connectWithSigner(rpcUrls, privateKey, _extraParams) {
(0,validation/* assert */.v)(rpcUrls.length > 0, 'At least one RPC URL is required');
const rpc = createRpc(rpcUrls[0]);
const keyBytes = parseKeyBytes(privateKey);
let keypair;
if (keyBytes.length === 32) {
keypair = await (0,signers_dist_index_node/* createKeyPairSignerFromPrivateKeyBytes */.bY)(keyBytes);
}
else if (keyBytes.length === 64) {
keypair = await (0,signers_dist_index_node/* createKeyPairSignerFromBytes */.Lt)(keyBytes);
}
else {
throw new Error(`Invalid key length: ${keyBytes.length}. Expected 32 (private key) or 64 (keypair).`);
}
return new SvmSigner(rpc, rpcUrls, keypair);
}
getSignerAddress() {
return this.signer.address;
}
supportsTransactionBatching() {
return false;
}
async transactionToPrintableJson(transaction) {
const { transactionBase58, messageBase58 } = serializeUnsignedTransaction(transaction.instructions, transaction.feePayer ?? this.signer.address);
return {
annotation: transaction.annotation,
instructions: transaction.instructions.map((ix) => ({
programAddress: ix.programAddress,
accounts: ix.accounts,
data: ix.data ? Buffer.from(ix.data).toString('hex') : undefined,
})),
computeUnits: transaction.computeUnits,
transaction_base58: transactionBase58,
message_base58: messageBase58,
};
}
/**
* Builds, signs, and sends a transaction with a confirmed blockhash.
* Retries on blockhash-not-found errors with backoff to handle
* load-balanced RPC node desync.
*/
async signAndSend(tx, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const { value: latestBlockhash } = await this.rpc
.getLatestBlockhash({ commitment: RPC_COMMITMENT_LEVEL })
.send();
let txMessage = buildTransactionMessage({
instructions: tx.instructions,
feePayer: this.signer,
recentBlockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
computeUnits: tx.computeUnits ?? constants_DEFAULT_COMPUTE_UNITS,
});
if (tx.additionalSigners?.length) {
txMessage = (0,signers_dist_index_node/* addSignersToTransactionMessage */.pO)(tx.additionalSigners, txMessage);
}
const signedTx = await (0,signers_dist_index_node/* signTransactionMessageWithSigners */.Q4)(txMessage);
const signature = (0,transactions_dist_index_node/* getSignatureFromTransaction */.fz)(signedTx);
try {
const rawTx = (0,transactions_dist_index_node/* getBase64EncodedWireTransaction */.RO)(signedTx);
await this.rpc
.sendTransaction(rawTx, {
encoding: 'base64',
skipPreflight: tx.skipPreflight ?? false,
// Set to 0 to avoid conflicts between the rpc/provider
// retrying and the signer as it tracks and retries
// pending txs manually
maxRetries: 0n,
preflightCommitment: RPC_COMMITMENT_LEVEL,
})
.send();
return {
signature,
rawTx,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
};
}
catch (error) {
if (isBlockhashNotFoundError(error) && attempt < maxAttempts - 1) {
const delay = 500 * (attempt + 1);
this.logger.debug(`Blockhash not found on attempt ${attempt + 1}, retrying in ${delay}ms`);
await (0,dist_async/* sleep */.yy)(delay);
continue;
}
throw error;
}
}
// Unreachable: the loop always either returns or throws
throw new Error('signAndSend: unreachable');
}
/**
* Evaluates a signature status result. Throws on error, returns
* `{ confirmed: true, slot }` if confirmed/finalized, `{ confirmed: false }`
* if still progressing, or `null` if the signature was not found.
*/
checkSignatureResult(signature, result) {
if (!result)
return null;
if (result.err) {
throw new SvmTransactionError(signature, result.err);
}
if (result.confirmationStatus === RPC_COMMITMENT_LEVEL ||
result.confirmationStatus === 'finalized') {
return { confirmed: true, slot: result.slot };
}
return { confirmed: false };
}
/**
* Sends a transaction and polls for confirmation. On blockhash expiry,
* checks transaction history before resubmitting to prevent double-execution.
*/
async send(tx) {
const maxBlockhashAttempts = 3;
const pollIntervalMs = 2000;
let lastSignature;
for (let blockhashAttempt = 0; blockhashAttempt < maxBlockhashAttempts; blockhashAttempt++) {
const { signature, rawTx, lastValidBlockHeight } = await this.signAndSend(tx);
lastSignature = signature;
// Poll while blockhash is valid
const result = await this.pollForConfirmation(signature, rawTx, lastValidBlockHeight, pollIntervalMs);
if (result) {
return result;
}
// Blockhash expired — check history before resubmitting
let historyCheck = null;
try {
const historyStatus = await this.rpc
.getSignatureStatuses([signature], {
searchTransactionHistory: true,
})
.send();
historyCheck = this.checkSignatureResult(signature, historyStatus.value[0]);
}
catch (error) {
if (error instanceof SvmTransactionError)
throw error;
throw new Error(`Cannot safely resubmit: history lookup failed for ${signature}, aborting to prevent double-execution.`, { cause: error });
}
if (historyCheck?.confirmed) {
return { signature, slot: historyCheck.slot };
}
if (historyCheck) {
// Tx still progressing (e.g. 'processed') — keep polling same
// signature with a fresh block height ceiling
const { value: freshBlockhash } = await this.rpc
.getLatestBlockhash({ commitment: RPC_COMMITMENT_LEVEL })
.send();
const retry = await this.pollForConfirmation(signature, rawTx, freshBlockhash.lastValidBlockHeight, pollIntervalMs);
if (retry)
return retry;
throw new Error(`Transaction ${signature} was observed at 'processed' but never confirmed`);
}
if (blockhashAttempt < maxBlockhashAttempts - 1) {
this.logger.debug(`Blockhash expired and tx not found, resubmitting (attempt ${blockhashAttempt + 2}/${maxBlockhashAttempts})`);
}
}
throw new Error(`Transaction not confirmed after ${maxBlockhashAttempts} blockhash attempts (last signature: ${lastSignature})`);
}
/**
* Polls getSignatureStatuses while the blockhash is still valid.
* Rebroadcasts the same signed tx periodically (fire-and-forget).
* Returns the receipt if confirmed, or null if the blockhash expired.
*/
async pollForConfirmation(signature, rawTx, lastValidBlockHeight, pollIntervalMs) {
const maxBlockHeightFailures = 3;
const wallClockDeadline = Date.now() + 2 * 60 * 1000;
let blockHeightFailures = 0;
let delay = Math.max(Math.floor(pollIntervalMs / 4), 250);
while (Date.now() < wallClockDeadline) {
await (0,dist_async/* sleep */.yy)(delay);
delay = Math.min(Math.floor(delay * 1.5), pollIntervalMs);
// Check confirmation status
try {
const status = await this.rpc.getSignatureStatuses([signature]).send();
const check = this.checkSignatureResult(signature, status.value[0]);
if (check?.confirmed) {
return { signature, slot: check.slot };
}
// Transaction seen (e.g. 'processed') — keep polling, don't rebroadcast
if (check)
continue;
}
catch (error) {
if (error instanceof SvmTransactionError)
throw error;
this.logger.debug('Status poll failed', { error });
}
// Check if blockhash expired
try {
const currentBlockHeight = await this.rpc
.getBlockHeight({ commitment: RPC_COMMITMENT_LEVEL })
.send();
// Reset on successful fetch
blockHeightFailures = 0;
if (currentBlockHeight > lastValidBlockHeight) {
return null;
}
}
catch (error) {
blockHeightFailures++;
this.logger.debug('Block height check failed', { error });
if (blockHeightFailures >= maxBlockHeightFailures) {
this.logger.warn(`Block height check failed ${maxBlockHeightFailures} times, treating as expired`);
return null;
}
}
// Rebroadcast same signed tx (fire-and-forget, always skip preflight)
try {
await this.rpc
.sendTransaction(rawTx, {
encoding: 'base64',
skipPreflight: true,
maxRetries: 0n,
})
.send();
}
catch (error) {
this.logger.debug('Rebroadcast failed', { error, signature });
}
}
// Wall-clock timeout exceeded — tx fate unknown, unsafe to resubmit
throw new Error(`Poll timeout exceeded for ${signature}, aborting to prevent potential double-execution`);
}
async sendAndConfirmTransaction(transaction) {
const tx = isLegacySolanaTransaction(transaction)
? await convertLegacySolanaTransaction(transaction, transaction.extraSigners)
: transaction;
const receipt = await this.send(tx);
return this.fetchTransactionMeta(receipt);
}
/**
* Fetches full transaction to populate meta (including logs) on the receipt.
* Retries with backoff since RPC indexing can lag behind confirmation.
* // TODO: make meta-fetch opt-in once the legacy compat layer is removed
*/
async fetchTransactionMeta(receipt, maxRetries = 5) {
(0,keys_dist_index_node/* assertIsSignature */.P)(receipt.signature);
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const fullTx = await this.rpc
.getTransaction(receipt.signature, {
commitment: RPC_COMMITMENT_LEVEL,
maxSupportedTransactionVersion: 0,
encoding: 'jsonParsed',
})
.send();
if (fullTx?.meta?.logMessages) {
return {
...receipt,
meta: { logMessages: fullTx.meta.logMessages },
};
}
}
catch (error) {
this.logger.debug(`Attempt ${attempt + 1} failed to fetch tx meta`, {
error,
});
}
if (attempt < maxRetries - 1) {
await (0,dist_async/* sleep */.yy)(1000 * (attempt + 1));
}
}
this.logger.warn('Transaction meta unavailable after retries', {
signature: receipt.signature,
});
return receipt;
}
async sendAndConfirmBatchTransactions(_transactions) {
throw new Error('Sealevel does not support transaction batching');
}
}
//# sourceMappingURL=signer.js.map
;// CONCATENATED MODULE: ../svm-sdk/dist/hyperlane/program-bytes.js
/**
* Auto-generated program bytes from compiled .so binaries.
* DO NOT EDIT — regenerate with:
* pnpm -C typescript/svm-sdk program:build
* pnpm -C typescript/svm-sdk program:generate
*/
/** SHA-256 of Rust sealevel sources at generation time. Used for CI staleness detection. */
const SEALEVEL_SOURCE_HASH = '51857b8b96079e6a98161e7a4a9cb069edc25a18212983086a7da4e5235beb09';
const HYPERLANE_SVM_PROGRAM_BYTES = {
mailbox: new Uint8Array([
127, 69, 76, 70, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 7, 1, 1, 0, 0, 0,
240, 235, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 208, 167, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 64, 0, 56, 0, 4, 0, 64, 0, 9, 0, 8, 0, 1, 0, 0, 0, 5, 0,
0, 0, 32, 1, 0, 0, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0,
0, 0, 160, 72, 2, 0, 0, 0, 0, 0, 160, 72, 2, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 192, 73, 2, 0, 0, 0, 0, 0, 192, 73, 2, 0,
0, 0, 0, 0, 192, 73, 2, 0, 0, 0, 0, 0, 240, 50, 0, 0, 0, 0, 0, 0, 240, 50,
0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 96, 125,
2, 0, 0, 0, 0, 0, 96, 125, 2, 0, 0, 0, 0, 0, 96, 125, 2, 0, 0, 0, 0, 0, 40,
42, 0, 0, 0, 0, 0, 0, 40, 42, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 2,
0, 0, 0, 6, 0, 0, 0, 176, 124, 2, 0, 0, 0, 0, 0, 176, 124, 2, 0, 0, 0, 0, 0,
176, 124, 2, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0,
0, 8, 0, 0, 0, 0, 0, 0, 0, 191, 39, 0, 0, 0, 0, 0, 0, 123, 26, 232, 251, 0,
0, 0, 0, 122, 10, 232, 255, 0, 0, 0, 0, 122, 10, 224, 255, 0, 0, 0, 0, 122,
10, 216, 255, 0, 0, 0, 0, 122, 10, 208, 255, 0, 0, 0, 0, 191, 161, 0, 0, 0,
0, 0, 0, 7, 1, 0, 0, 240, 251, 255, 255, 183, 6, 0, 0, 0, 0, 0, 0, 183, 2,
0, 0, 0, 0, 0, 0, 183, 3, 0, 0, 224, 3, 0, 0, 133, 16, 0, 0, 90, 71, 0, 0,
121, 120, 0, 0, 0, 0, 0, 0, 123, 122, 224, 251, 0, 0, 0, 0, 121, 113, 8, 0,
0, 0, 0, 0, 191, 18, 0, 0, 0, 0, 0, 0, 191, 41, 0, 0, 0, 0, 0, 0, 191, 103,
0, 0, 0, 0, 0, 0, 165, 9, 28, 0, 32, 0, 0, 0, 191, 130, 0, 0, 0, 0, 0, 0,
15, 114, 0, 0, 0, 0, 0, 0, 121, 35, 6, 0, 0, 0, 0, 0, 113, 36, 14, 0, 0, 0,
0, 0, 115, 74, 248, 255, 0, 0, 0, 0, 123, 58, 240, 255, 0, 0, 0, 0, 191,
164, 0, 0, 0, 0, 0, 0, 7, 4, 0, 0, 240, 251, 255, 255, 15, 116, 0, 0, 0, 0,
0, 0, 121, 165, 241, 255, 0, 0, 0, 0, 97, 32, 0, 0, 0, 0, 0, 0, 99, 4, 0, 0,
0, 0, 0, 0, 105, 32, 4, 0, 0, 0, 0, 0, 107, 4, 4, 0, 0, 0, 0, 0, 123, 84, 7,
0, 0, 0, 0, 0, 115, 52, 6, 0, 0, 0, 0, 0, 121, 35, 15, 0, 0, 0, 0, 0, 123,
52, 15, 0, 0, 0, 0, 0, 121, 35, 23, 0, 0, 0, 0, 0, 123, 52, 23, 0, 0, 0, 0,
0, 113, 34, 31, 0, 0, 0, 0, 0, 115, 36, 31, 0, 0, 0, 0, 0, 191, 146, 0, 0,
0, 0, 0, 0, 7, 2, 0, 0, 224, 255, 255, 255, 191, 118, 0, 0, 0, 0, 0, 0, 7,
6, 0, 0, 32, 0, 0, 0, 85, 6, 226, 255, 0, 4, 0, 0, 53, 2, 12, 0, 8, 0, 0, 0,
24, 1, 0, 0, 88, 110, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 187, 55,
0, 0, 15, 120, 0, 0, 0, 0, 0, 0, 15, 152, 0, 0, 0, 0, 0, 0, 121, 161, 224,
251, 0, 0, 0, 0, 123, 129, 0, 0, 0, 0, 0, 0, 122, 1, 8, 0, 0, 0, 0, 0, 121,
161, 232, 251, 0, 0, 0, 0, 123, 1, 8, 0, 0, 0, 0, 0, 122, 1, 0, 0, 1, 0, 0,
0, 5, 0, 17, 0, 0, 0, 0, 0, 15, 104, 0, 0, 0, 0, 0, 0, 31, 97, 0, 0, 0, 0,
0, 0, 7, 1, 0, 0, 248, 255, 255, 255, 121, 134, 0, 0, 0, 0, 0, 0, 121, 162,
224, 251, 0, 0, 0, 0, 123, 18, 8, 0, 0, 0, 0, 0, 7, 8, 0, 0, 8, 0, 0, 0,
123, 130, 0, 0, 0, 0, 0, 0, 121, 167, 232, 251, 0, 0, 0, 0, 191, 113, 0, 0,
0, 0, 0, 0, 7, 1, 0, 0, 8, 0, 0, 0, 191, 162, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0,
240, 251, 255, 255, 183, 3, 0, 0, 0, 4, 0, 0, 133, 16, 0, 0, 24, 71, 0, 0,
123, 103, 8, 4, 0, 0, 0, 0, 122, 7, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0,
0, 191, 38, 0, 0, 0, 0, 0, 0, 113, 24, 100, 0, 0, 0, 0, 0, 121, 98, 0, 0, 0,
0, 0, 0, 121, 103, 16, 0, 0, 0, 0, 0, 29, 114, 80, 0, 0, 0, 0, 0, 121, 99,
8, 0, 0, 0, 0, 0, 191, 52, 0, 0, 0, 0, 0, 0, 15, 116, 0, 0, 0, 0, 0, 0, 115,
132, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 1, 0, 0, 0, 123, 118, 16, 0, 0, 0, 0, 0,
191, 36, 0, 0, 0, 0, 0, 0, 31, 116, 0, 0, 0, 0, 0, 0, 97, 24, 88, 0, 0, 0,
0, 0, 220, 8, 0, 0, 32, 0, 0, 0, 181, 4, 78, 0, 3, 0, 0, 0, 191, 52, 0, 0,
0, 0, 0, 0, 15, 116, 0, 0, 0, 0, 0, 0, 99, 132, 0, 0, 0, 0, 0, 0, 7, 7, 0,
0, 4, 0, 0, 0, 123, 118, 16, 0, 0, 0, 0, 0, 31, 114, 0, 0, 0, 0, 0, 0, 97,
24, 92, 0, 0, 0, 0, 0, 220, 8, 0, 0, 32, 0, 0, 0, 181, 2, 79, 0, 3, 0, 0, 0,
15, 115, 0, 0, 0, 0, 0, 0, 99, 131, 0, 0, 0, 0, 0, 0, 191, 24, 0, 0, 0, 0,
0, 0, 7, 8, 0, 0, 24, 0, 0, 0, 7, 7, 0, 0, 4, 0, 0, 0, 123, 118, 16, 0, 0,
0, 0, 0, 121, 99, 0, 0, 0, 0, 0, 0, 191, 50, 0, 0, 0, 0, 0, 0, 31, 114, 0,
0, 0, 0, 0, 0, 181, 2, 78, 0, 31, 0, 0, 0, 121, 98, 8, 0, 0, 0, 0, 0, 191,
36, 0, 0, 0, 0, 0, 0, 15, 116, 0, 0, 0, 0, 0, 0, 121, 133, 24, 0, 0, 0, 0,
0, 123, 84, 24, 0, 0, 0, 0, 0, 121, 133, 16, 0, 0, 0, 0, 0, 123, 84, 16, 0,
0, 0, 0, 0, 121, 133, 8, 0, 0, 0, 0, 0, 123, 84, 8, 0, 0, 0, 0, 0, 121, 133,
0, 0, 0, 0, 0, 0, 123, 84, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 32, 0, 0, 0, 123,
118, 16, 0, 0, 0, 0, 0, 191, 52, 0, 0, 0, 0, 0, 0, 31, 116, 0, 0, 0, 0, 0,
0, 97, 24, 96, 0, 0, 0, 0, 0, 220, 8, 0, 0, 32, 0, 0, 0, 181, 4, 69, 0, 3,
0, 0, 0, 191, 36, 0, 0, 0, 0, 0, 0, 15, 116, 0, 0, 0, 0, 0, 0, 99, 132, 0,
0, 0, 0, 0, 0, 7, 7, 0, 0, 4, 0, 0, 0, 123, 118, 16, 0, 0, 0, 0, 0, 191, 24,
0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 56, 0, 0, 0, 31, 115, 0, 0, 0, 0, 0, 0, 181,
3, 70, 0, 31, 0, 0, 0, 15, 114, 0, 0, 0, 0, 0, 0, 121, 131, 24, 0, 0, 0, 0,
0, 123, 50, 24, 0, 0, 0, 0, 0, 121, 131, 16, 0, 0, 0, 0, 0, 123, 50, 16, 0,
0, 0, 0, 0, 121, 131, 8, 0, 0, 0, 0, 0, 123, 50, 8, 0, 0, 0, 0, 0, 121, 131,
0, 0, 0, 0, 0, 0, 123, 50, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 32, 0, 0, 0, 123,
118, 16, 0, 0, 0, 0, 0, 121, 99, 0, 0, 0, 0, 0, 0, 31, 115, 0, 0, 0, 0, 0,
0, 121, 18, 8, 0, 0, 0, 0, 0, 121, 24, 16, 0, 0, 0, 0, 0, 173, 131, 63, 0,
0, 0, 0, 0, 121, 97, 8, 0, 0, 0, 0, 0, 15, 113, 0, 0, 0, 0, 0, 0, 191, 131,
0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 195, 70, 0, 0, 15, 135, 0, 0, 0, 0, 0, 0,
123, 118, 16, 0, 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 191, 25, 0, 0, 0, 0,
0, 0, 191, 97, 0, 0, 0, 0, 0, 0, 191, 114, 0, 0, 0, 0, 0, 0, 183, 3, 0, 0,
1, 0, 0, 0, 133, 16, 0, 0, 159, 7, 0, 0, 191, 145, 0, 0, 0, 0, 0, 0, 121,
98, 0, 0, 0, 0, 0, 0, 121, 103, 16, 0, 0, 0, 0, 0, 5, 0, 167, 255, 0, 0, 0,
0, 191, 25, 0, 0, 0, 0, 0, 0, 191, 97, 0, 0, 0, 0, 0, 0, 191, 114, 0, 0, 0,
0, 0, 0, 183, 3, 0, 0, 4, 0, 0, 0, 133, 16, 0, 0, 150, 7, 0, 0, 191, 145, 0,
0, 0, 0, 0, 0, 121, 98, 0, 0, 0, 0, 0, 0, 121, 99, 8, 0, 0, 0, 0, 0, 121,
103, 16, 0, 0, 0, 0, 0, 5, 0, 168, 255, 0, 0, 0, 0, 191, 25, 0, 0, 0, 0, 0,
0, 191, 97, 0, 0, 0, 0, 0, 0, 191, 114, 0, 0, 0, 0, 0, 0, 183, 3, 0, 0, 4,
0, 0, 0, 133, 16, 0, 0, 140, 7, 0, 0, 191, 145, 0, 0, 0, 0, 0, 0, 121, 99,
8, 0, 0, 0, 0, 0, 121, 103, 16, 0, 0, 0, 0, 0, 5, 0, 168, 255, 0, 0, 0, 0,
191, 25, 0, 0, 0, 0, 0, 0, 191, 97, 0, 0, 0, 0, 0, 0, 191, 114, 0, 0, 0, 0,
0, 0, 183, 3, 0, 0, 32, 0, 0, 0, 133, 16, 0, 0, 131, 7, 0, 0, 191, 145, 0,
0, 0, 0, 0, 0, 121, 99, 0, 0, 0, 0, 0, 0, 121, 103, 16, 0, 0, 0, 0, 0, 5, 0,
169, 255, 0, 0, 0, 0, 191, 25, 0, 0, 0, 0, 0, 0, 191, 97, 0, 0, 0, 0, 0, 0,
191, 114, 0, 0, 0, 0, 0, 0, 183, 3, 0, 0, 4, 0, 0, 0, 133, 16, 0, 0, 122, 7,
0, 0, 191, 145, 0, 0, 0, 0, 0, 0, 121, 99, 0, 0, 0, 0, 0, 0, 121, 98, 8, 0,
0, 0, 0, 0, 121, 103, 16, 0, 0, 0, 0, 0, 5, 0, 177, 255, 0, 0, 0, 0, 191,
25, 0, 0, 0, 0, 0, 0, 191, 97, 0, 0, 0, 0, 0, 0, 191, 114, 0, 0, 0, 0, 0, 0,
183, 3, 0, 0, 32, 0, 0, 0, 133, 16, 0, 0, 112, 7, 0, 0, 191, 145, 0, 0, 0,
0, 0, 0, 121, 98, 8, 0, 0, 0, 0, 0, 121, 103, 16, 0, 0, 0, 0, 0, 5, 0, 177,
255, 0, 0, 0, 0, 191, 97, 0, 0, 0, 0, 0, 0, 191, 41, 0, 0, 0, 0, 0, 0, 191,
114, 0, 0, 0, 0, 0, 0, 191, 131, 0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 103, 7, 0,
0, 191, 146, 0, 0, 0, 0, 0, 0, 121, 103, 16, 0, 0, 0, 0, 0, 5, 0, 185, 255,
0, 0, 0, 0, 191, 54, 0, 0, 0, 0, 0, 0, 191, 39, 0, 0, 0, 0, 0, 0, 123, 26,
232, 255, 0, 0, 0, 0, 183, 9, 0, 0, 1, 0, 0, 0, 85, 6, 1, 0, 0, 0, 0, 0,
183, 9, 0, 0, 0, 0, 0, 0, 114, 10, 243, 255, 1, 0, 0, 0, 191, 162, 0, 0, 0,
0, 0, 0, 7, 2, 0, 0, 243, 255, 255, 255, 191, 113, 0, 0, 0, 0, 0, 0, 191,
147, 0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 116, 70, 0, 0, 21, 6, 49, 0, 0, 0, 0,
0, 31, 150, 0, 0, 0, 0, 0, 0, 121, 161, 232, 255, 0, 0, 0, 0, 97, 17, 40, 0,
0, 0, 0, 0, 99, 26, 244, 255, 0, 0, 0, 0, 15, 151, 0, 0, 0, 0, 0, 0, 191,
105, 0, 0, 0, 0, 0, 0, 165, 6, 1, 0, 4, 0, 0, 0, 183, 9, 0, 0, 4, 0, 0, 0,
191, 162, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 244, 255, 255, 255, 191, 113, 0, 0,
0, 0, 0, 0, 191, 147, 0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 102, 70, 0, 0, 165,
6, 35, 0, 4, 0, 0, 0, 183, 8, 0, 0, 1, 0, 0, 0, 85, 6, 1, 0, 4, 0, 0, 0,
183, 8, 0, 0, 0, 0, 0, 0, 15, 151, 0, 0, 0, 0, 0, 0, 121, 162, 232, 255, 0,
0, 0, 0, 7, 2, 0, 0, 44, 0, 0, 0, 191, 113, 0, 0, 0, 0, 0, 0, 191, 131, 0,
0, 0, 0, 0, 0, 133, 16, 0, 0, 92, 70, 0, 0, 21, 6, 25, 0, 4, 0, 0, 0, 15,
135, 0, 0, 0, 0, 0, 0, 167, 9, 0, 0, 255, 255, 255, 255, 15, 150, 0, 0, 0,
0, 0, 0, 191, 104, 0, 0, 0, 0, 0, 0, 165, 6, 1, 0, 32, 0, 0, 0, 183, 8, 0,
0, 32, 0, 0, 0, 191, 113, 0, 0, 0, 0, 0, 0, 121, 162, 232, 255, 0, 0, 0, 0,
191, 131, 0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 81, 70, 0, 0, 165, 6, 14, 0, 32,
0, 0, 0, 121, 161, 232, 255, 0, 0, 0, 0, 121, 17, 32, 0, 0, 0, 0, 0, 123,
26, 248, 255, 0, 0, 0, 0, 15, 135, 0, 0, 0, 0, 0, 0, 31, 134, 0, 0, 0, 0, 0,
0, 191, 99, 0, 0, 0, 0, 0, 0, 165, 6, 1, 0, 8, 0, 0, 0, 183, 3, 0, 0, 8, 0,
0, 0, 191, 162, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 248, 255, 255, 255, 191, 113,
0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 68, 70, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 37,
6, 21, 0, 7, 0, 0, 0, 24, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 121,
17, 0, 0, 0, 0, 0, 0, 191, 19, 0, 0, 0, 0, 0, 0, 7, 3, 0, 0, 248, 255, 255,
255, 183, 2, 0, 0, 0, 0, 0, 0, 183, 4, 0, 0, 1, 0, 0, 0, 189, 19, 14, 0, 0,
0, 0, 0, 21, 4, 15, 0, 0, 0, 0, 0, 24, 0, 0, 0, 248, 127, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 85, 1, 16, 0, 0, 0, 0, 0, 24, 1, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 173, 16, 18, 0, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 123, 1, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 240, 109, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0, 123, 16, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 183, 4,
0, 0, 0, 0, 0, 0, 85, 4, 241, 255, 0, 0, 0, 0, 191, 50, 0, 0, 0, 0, 0, 0,
24, 0, 0, 0, 248, 127, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 21, 1, 240, 255, 0, 0,
0, 0, 87, 2, 0, 0, 248, 255, 255, 255, 191, 32, 0, 0, 0, 0, 0, 0, 24, 1, 0,
0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 61, 16, 238, 255, 0, 0, 0, 0, 183, 1,
0, 0, 8, 0, 0, 0, 183, 2, 0, 0, 8, 0, 0, 0, 133, 16, 0, 0, 182, 56, 0, 0,
191, 39, 0, 0, 0, 0, 0, 0, 191, 22, 0, 0, 0, 0, 0, 0, 121, 121, 0, 0, 0, 0,
0, 0, 121, 113, 8, 0, 0, 0, 0, 0, 53, 1, 2, 0, 4, 0, 0, 0, 15, 25, 0, 0, 0,
0, 0, 0, 5, 0, 2, 0, 0, 0, 0, 0, 85, 1, 21, 0, 4, 0, 0, 0, 7, 9, 0, 0, 4, 0,
0, 0, 24, 1, 0, 0, 88, 110, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 16, 0, 0,
157, 54, 0, 0, 123, 151, 0, 0, 0, 0, 0, 0, 122, 7, 8, 0, 0, 0, 0, 0, 191, 1,
0, 0, 0, 0, 0, 0, 87, 1, 0, 0, 3, 0, 0, 0, 191, 18, 0, 0, 0, 0, 0, 0, 7, 2,
0, 0, 254, 255, 255, 255, 165, 2, 6, 0, 2, 0, 0, 0, 21, 1, 5, 0, 0, 0, 0, 0,
121, 1, 7, 0, 0, 0, 0, 0, 121, 18, 0, 0, 0, 0, 0, 0, 21, 2, 2, 0, 0, 0, 0,
0, 121, 1, 255, 255, 0, 0, 0, 0, 141, 0, 0, 0, 2, 0, 0, 0, 98, 6, 4, 0, 14,
0, 0, 0, 183, 1, 0, 0, 1, 0, 0, 0, 99, 22, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0,
0, 0, 0, 0, 97, 148, 0, 0, 0, 0, 0, 0, 191, 18, 0, 0, 0, 0, 0, 0, 7, 2, 0,
0, 251, 255, 255, 255, 113, 149, 4, 0, 0, 0, 0, 0, 123, 39, 8, 0, 0, 0, 0,
0, 21, 2, 40, 0, 0, 0, 0, 0, 191, 19, 0, 0, 0, 0, 0, 0, 7, 3, 0, 0, 250,
255, 255, 255, 113, 152, 5, 0, 0, 0, 0, 0, 123, 55, 8, 0, 0, 0, 0, 0, 191,
147, 0, 0, 0, 0, 0, 0, 7, 3, 0, 0, 6, 0, 0, 0, 123, 55, 0, 0, 0, 0, 0, 0,
115, 138, 215, 255, 0, 0, 0, 0, 21, 8, 37, 0, 0, 0, 0, 0, 85, 8, 57, 0, 1,
0, 0, 0, 165, 2, 215, 255, 33, 0, 0, 0, 123, 90, 104, 247, 0, 0, 0, 0, 123,
74, 112, 247, 0, 0, 0, 0, 121, 146, 12, 0, 0, 0, 0, 0, 113, 148, 20, 0, 0,
0, 0, 0, 115, 74, 176, 247, 0, 0, 0, 0, 97, 52, 0, 0, 0, 0, 0, 0, 99, 74,
160, 247, 0, 0, 0, 0, 105, 51, 4, 0, 0, 0, 0, 0, 107, 58, 164, 247, 0, 0, 0,
0, 123, 42, 168, 247, 0, 0, 0, 0, 121, 165, 169, 247, 0, 0, 0, 0, 7, 1, 0,
0, 218, 255, 255, 255, 123, 23, 8, 0, 0, 0, 0, 0, 191, 145, 0, 0, 0, 0, 0,
0, 7, 1, 0, 0, 38, 0, 0, 0, 123, 23, 0, 0, 0, 0, 0, 0, 121, 145, 21, 0, 0,
0, 0, 0, 121, 147, 29, 0, 0, 0, 0, 0, 113, 148, 37, 0, 0, 0, 0, 0, 115, 42,
144, 247, 0, 0, 0, 0, 115, 74, 136, 247, 0, 0, 0, 0, 123, 58, 128, 247, 0,
0, 0, 0, 123, 26, 120, 247, 0, 0, 0, 0, 123, 90, 145, 247, 0, 0, 0, 0, 119,
5, 0, 0, 56, 0, 0, 0, 123, 90, 88, 247, 0, 0, 0, 0, 121, 161, 144, 247, 0,
0, 0, 0, 123, 26, 80, 247, 0, 0, 0, 0, 5, 0, 8, 0, 0, 0, 0, 0, 7, 9, 0, 0,
5, 0, 0, 0, 24, 1, 0, 0, 88, 110, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 16, 0,
0, 90, 54, 0, 0, 123, 151, 0, 0, 0, 0, 0, 0, 5, 0, 189, 255, 0, 0, 0, 0,
123, 90, 104, 247, 0, 0, 0, 0, 123, 74, 112, 247, 0, 0, 0, 0, 191, 161, 0,
0, 0, 0, 0, 0, 7, 1, 0, 0, 168, 247, 255, 255, 191, 114, 0, 0, 0, 0, 0