Execute Intent
This guide demonstrates how to execute a cross-chain intent using the SDK. The process is broken down into clear steps, each with a brief explanation.
1. Setup: Import Dependencies and Configure Environment
First, import the required libraries and set up your environment variables, such as your private key and a generic RPC URL.
import {
createCrossChainProvider,
createProviderExecutor,
InteropAddressParamsParser,
} from "@wonderland/interop";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
// Private key for the account to send the transactions
const PRIVATE_KEY = "";
// Configure your preferred RPC URL for Sepolia (or any supported chain)
const RPC_URL = process.env.RPC_URL || ""; // e.g., "https://sepolia.infura.io/v3/<API_KEY>"
const privateAccount = privateKeyToAccount(PRIVATE_KEY);
2. Initialize Blockchain Clients
Create public and wallet clients for interacting with the blockchain, using the generic RPC URL.
const publicClient = createPublicClient({
chain: sepolia,
transport: http(RPC_URL),
});
const walletClient = createWalletClient({
chain: sepolia,
transport: http(RPC_URL),
});
3. Set Up Cross-Chain Provider and Executor
Initialize the cross-chain provider and executor, which will handle quoting and executing cross-chain transfers.
const acrossProvider = createCrossChainProvider("across");
const executor = createProviderExecutor([acrossProvider], {
paramParser: new InteropAddressParamsParser(),
});
4. Retrieve a Cross-Chain Quote
Request a quote for a cross-chain transfer by specifying sender, recipient, amount, and token addresses.
const params = await executor.getQuotes("crossChainTransfer", {
sender: "0xeca5cca87fDF2Cb3f3a5d795699cEAA561c4B19d@eip155:11155111#2597C7E5",
recipient: "0x8043951e77347c5282d6bcD2294e134B4072fE3b@eip155:84532#D9F7BE3F",
amount: "0.100",
inputTokenAddress: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
outputTokenAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
});
if (!params[0] || (params[0] && "error" in params[0])) {
console.error(params[0]?.error || "No quote found");
return;
}
5. Execute the Cross-Chain Transaction
For each transaction in the quote, estimate gas, prepare, sign, and send the transaction, then wait for confirmation.
const txs = await executor.execute(params[0]);
console.log("Sending transactions...");
for (const tx of txs) {
console.log("Original transaction request:", tx);
try {
// Step 1: Get the current nonce for the account
const nonce = await publicClient.getTransactionCount({
address: privateAccount.address,
});
// Step 2: Estimate gas and prepare the transaction with all necessary fields
const gasEstimate = await publicClient.estimateGas({
...tx,
account: privateAccount.address,
});
console.log("Gas estimate:", gasEstimate);
// Step 3: Prepare a complete transaction request with all fields
const preparedTx = await publicClient.prepareTransactionRequest({
...tx,
nonce,
gas: gasEstimate,
account: privateAccount,
});
console.log("Prepared transaction:", preparedTx);
// Step 4: Sign the transaction locally
const signedTx = await walletClient.signTransaction(preparedTx);
console.log("Transaction signed successfully");
// Step 5: Send the raw signed transaction via the public client
const txHash = await publicClient.sendRawTransaction({
serializedTransaction: signedTx,
});
console.log("Transaction hash:", txHash);
// Step 6: Wait for the transaction to be mined
const receipt = await publicClient.waitForTransactionReceipt({
hash: txHash,
});
console.log("Transaction confirmed:", receipt.status === "success" ? "Success" : "Failed");
} catch (error) {
console.error("Transaction failed:", error);
// Log detailed error information
if (error.cause) {
console.error("Error details:", error.cause.details || error.cause.message);
}
break;
}
}
6. Run the Main Function
Finally, call the main function to execute the workflow.
const main = async (): Promise<void> => {
// ...all the above steps go here...
};
main().catch(console.error);