@hyperlane-xyz/cli
Version:
A command-line utility for common Hyperlane operations
113 lines • 5.2 kB
JavaScript
import { stringify as yamlStringify } from 'yaml';
import { HyperlaneCore, HyperlaneRelayer, MultiProtocolProvider, ProviderType, TokenAmount, WarpCore, } from '@hyperlane-xyz/sdk';
import { parseWarpRouteMessage, timeout } from '@hyperlane-xyz/utils';
import { EXPLORER_URL, MINIMUM_TEST_SEND_GAS } from '../consts.js';
import { runPreflightChecksForChains } from '../deploy/utils.js';
import { log, logBlue, logGreen, logRed } from '../logger.js';
import { indentYamlOrJson } from '../utils/files.js';
import { stubMerkleTreeConfig } from '../utils/relay.js';
import { runTokenSelectionStep } from '../utils/tokens.js';
export const WarpSendLogs = {
SUCCESS: 'Transfer was self-relayed!',
};
export async function sendTestTransfer({ context, warpCoreConfig, chains, amount, recipient, timeoutSec, skipWaitForDelivery, selfRelay, }) {
await runPreflightChecksForChains({
context,
chains,
minGas: MINIMUM_TEST_SEND_GAS,
});
for (let i = 0; i < chains.length; i++) {
const origin = chains[i];
const destination = chains[i + 1];
if (destination) {
logBlue(`Sending a message from ${origin} to ${destination}`);
await timeout(executeDelivery({
context,
origin,
destination,
warpCoreConfig,
amount,
recipient,
skipWaitForDelivery,
selfRelay,
}), timeoutSec * 1000, 'Timed out waiting for messages to be delivered');
}
}
}
async function executeDelivery({ context, origin, destination, warpCoreConfig, amount, recipient, skipWaitForDelivery, selfRelay, }) {
const { multiProvider, registry } = context;
const signer = multiProvider.getSigner(origin);
const recipientSigner = multiProvider.getSigner(destination);
const recipientAddress = await recipientSigner.getAddress();
const signerAddress = await signer.getAddress();
recipient ||= recipientAddress;
const chainAddresses = await registry.getAddresses();
const core = HyperlaneCore.fromAddressesMap(chainAddresses, multiProvider);
const provider = multiProvider.getProvider(origin);
const connectedSigner = signer.connect(provider);
const warpCore = WarpCore.FromConfig(MultiProtocolProvider.fromMultiProvider(multiProvider), warpCoreConfig);
let token;
const tokensForRoute = warpCore.getTokensForRoute(origin, destination);
if (tokensForRoute.length === 0) {
logRed(`No Warp Routes found from ${origin} to ${destination}`);
throw new Error('Error finding warp route');
}
else if (tokensForRoute.length === 1) {
token = tokensForRoute[0];
}
else {
logBlue(`Please select a token from the Warp config`);
const routerAddress = await runTokenSelectionStep(tokensForRoute);
token = warpCore.findToken(origin, routerAddress);
}
const errors = await warpCore.validateTransfer({
originTokenAmount: token.amount(amount),
destination,
recipient,
sender: signerAddress,
});
if (errors) {
logRed('Error validating transfer', JSON.stringify(errors));
throw new Error('Error validating transfer');
}
// TODO: override hook address for self-relay
const transferTxs = await warpCore.getTransferRemoteTxs({
originTokenAmount: new TokenAmount(amount, token),
destination,
sender: signerAddress,
recipient,
});
const txReceipts = [];
for (const tx of transferTxs) {
if (tx.type === ProviderType.EthersV5) {
const txResponse = await connectedSigner.sendTransaction(tx.transaction);
const txReceipt = await multiProvider.handleTx(origin, txResponse);
txReceipts.push(txReceipt);
}
}
const transferTxReceipt = txReceipts[txReceipts.length - 1];
const messageIndex = 0;
const message = HyperlaneCore.getDispatchedMessages(transferTxReceipt)[messageIndex];
const parsed = parseWarpRouteMessage(message.parsed.body);
logBlue(`Sent transfer from sender (${signerAddress}) on ${origin} to recipient (${recipient}) on ${destination}.`);
logBlue(`Message ID: ${message.id}`);
logBlue(`Explorer Link: ${EXPLORER_URL}/message/${message.id}`);
log(`Message:\n${indentYamlOrJson(yamlStringify(message, null, 2), 4)}`);
log(`Body:\n${indentYamlOrJson(yamlStringify(parsed, null, 2), 4)}`);
if (selfRelay) {
const relayer = new HyperlaneRelayer({ core });
const hookAddress = await core.getSenderHookAddress(message);
const merkleAddress = chainAddresses[origin].merkleTreeHook;
stubMerkleTreeConfig(relayer, origin, hookAddress, merkleAddress);
log('Attempting self-relay of transfer...');
await relayer.relayMessage(transferTxReceipt, messageIndex, message);
logGreen(WarpSendLogs.SUCCESS);
return;
}
if (skipWaitForDelivery)
return;
// Max wait 10 minutes
await core.waitForMessageProcessed(transferTxReceipt, 10000, 60);
logGreen(`Transfer sent to ${destination} chain!`);
}
//# sourceMappingURL=transfer.js.map