# Cross-Chain Mint

> Mint FXRP from XRP and bridge it to Sepolia in a single XRPL payment using Viem, LayerZero, and the Custom Instruction (0xFE).

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

Source: https://dev.flare.network/smart-accounts/guides/typescript-viem/cross-chain-mint-ts

In this guide, you will learn how to mint FXRP from native XRP on the XRPL and bridge it to Sepolia in a single end-to-end flow, using the [Custom Instruction](/smart-accounts/custom-instruction) (`0xFE`). The script combines two operations into one user journey, driven by a single XRPL payment:

-   mint FXRP on Flare from a payment made on the XRPL by the user's personal account.
-   bridge the minted FXRP to Sepolia using a LayerZero OFT, by calling the OFT Adapter directly from the personal account.
-   wait for the `OFTReceived` event on Sepolia to confirm that the FXRP has arrived.

Why 0xFE

The `0xFE` memo commits only a `keccak256` hash of the call batch and needs an off-chain executor to deliver the batch bytes and finalize the mint - see [Custom Instruction](/smart-accounts/custom-instruction) for the full protocol. Because the memo is a fixed 42 bytes regardless of batch size, the approve and bridge calls fit in a single XRPL payment, with no shim contract needed to keep calldata small. The alternative - the [Memo Field Custom Instruction](/smart-accounts/memo-field-custom-instruction) (`0xFF`) - ships the whole call batch inline in the memo instead, trading the off-chain executor for a lower XRPL memo-size ceiling; see the [Custom Instruction Comparison](/smart-accounts/custom-instruction-comparison) for when to pick which.

A prerequisite for the script to work is a funded personal account on Flare (the C2FLR is used to pay the LayerZero native fee) and a funded XRPL testnet wallet that will originate the XRPL payment. The [State Lookup guide](/smart-accounts/guides/typescript-viem/state-lookup-ts#personal-account-of-an-xrpl-address) explains how to obtain the personal account address from the XRPL address. Once known, the personal account can be funded using the [Flare faucet](https://faucet.flare.network/coston2).

The full code showcased in this guide, `cross-chain-mint.ts`, is available in the [`flare-viem-starter`](https://github.com/flare-foundation/flare-viem-starter/blob/main/src/layer-zero/cross-chain-mint.ts) repository under `src/layer-zero/cross-chain-mint.ts`.

info

The code in this guide is set up for the Coston2 testnet and the Sepolia testnet. Despite that, we will refer to the Flare-side network as Flare and its currency as FLR instead of Coston2 and C2FLR. Likewise, we will refer to the Sepolia testnet's currency as ETH instead of SETH.

## Setup[​](#setup "Direct link to Setup")

The script uses three clients: a Flare public client, a Sepolia public client, and an XRPL client. The Flare client is the same one introduced in the [State Lookup guide](/smart-accounts/guides/typescript-viem/state-lookup-ts); a second Viem public client is added for Sepolia, plus a wallet client and a signing account for write operations.

src/utils/client.ts

```
import { createPublicClient, createWalletClient, http } from "viem";import { privateKeyToAccount } from "viem/accounts";import { flareTestnet, sepolia } from "viem/chains";export const publicClient = createPublicClient({  chain: flareTestnet,  transport: http(),});export const account = privateKeyToAccount(  process.env.PRIVATE_KEY as `0x${string}`,);export const sepoliaPublicClient = createPublicClient({  chain: sepolia,  transport: http(process.env.SEPOLIA_RPC_URL),});
```

The XRPL `Client` and `Wallet` are imported from the [`xrpl`](https://js.xrpl.org) library and initialised from environment variables. The recipient of the bridged FXRP on Sepolia is the main externally owned account (EOA) loaded from the wallet client, not the personal account on Flare - the personal account is only the intermediary that performs the mint and the bridge call.

src/layer-zero/cross-chain-mint.ts

```
const xrplClient = new Client(process.env.XRPL_TESTNET_RPC_URL!);const xrplWallet = Wallet.fromSeed(process.env.XRPL_SEED!);const recipient = account.address;
```

## Reading state and fees[​](#reading-state-and-fees "Direct link to Reading state and fees")

Before sending anything, the script reads the personal account address, the FXRP token address and decimals, and the gross XRP payment amount (net mint plus [fees](/fassets/minting#fees)) in parallel:

src/layer-zero/cross-chain-mint.ts

```
const [personalAccount, fxrpAddress, fxrpDecimals, paymentAmountXrp] =  await Promise.all([    getPersonalAccountAddress(xrplWallet.address),    getFxrpAddress(),    getFxrpDecimals(),    computeDirectMintingPaymentAmountXrp({      netMintAmountXrp: fxrpMintAmountXrp,    }),  ]);
```

The `getPersonalAccountAddress` function is covered in the [State Lookup guide](/smart-accounts/guides/typescript-viem/state-lookup-ts).

The script bridges through the FXRP OFT Adapter directly rather than a shim contract, since the `0xFE` memo has no calldata-size pressure to work around. It builds the LayerZero `SendParam` and quotes the native fee before encoding the call batch:

src/layer-zero/cross-chain-mint.ts

```
const amountToBridge = BigInt(xrpToDrops(fxrpMintAmountXrp));const extraOptions = Options.newOptions()  .addExecutorLzReceiveOption(CONFIG.EXECUTOR_GAS, 0)  .toHex() as `0x${string}`;const sendParam: SendParam = {  dstEid: CONFIG.SEPOLIA_EID,  to: pad(recipient, { size: 32 }),  amountLD: amountToBridge,  minAmountLD: amountToBridge,  extraOptions,  composeMsg: "0x",  oftCmd: "0x",};const messagingFee = await publicClient.readContract({  address: CONFIG.COSTON2_OFT_ADAPTER,  abi: fxrpOftAbi,  functionName: "quoteSend",  args: [sendParam, false],});const nativeFee = messagingFee.nativeFee;
```

## Encoding the approve and bridge calls[​](#encoding-the-approve-and-bridge-calls "Direct link to Encoding the approve and bridge calls")

The personal account will receive the freshly minted FXRP, so the batch approves the OFT Adapter for that amount and then calls `send` directly:

src/layer-zero/cross-chain-mint.ts

```
const customInstruction: Call[] = [  {    target: fxrpAddress,    value: 0n,    data: encodeFunctionData({      abi: erc20Abi,      functionName: "approve",      args: [CONFIG.COSTON2_OFT_ADAPTER, amountToBridge],    }),  },  {    target: CONFIG.COSTON2_OFT_ADAPTER,    value: nativeFee,    data: encodeFunctionData({      abi: fxrpOftAbi,      functionName: "send",      args: [sendParam, { nativeFee, lzTokenFee: 0n }, personalAccount],    }),  },];
```

The `sendParam.to` value is the EOA recipient on Sepolia; the third argument to `send` is the **refund address** for any unused native fee. That is set to `personalAccount`, not `recipient` - the caller of `send` (via `executeUserOp`) is the personal account, so a leftover refund lands back where it came from. Because the `0xFE` memo is a fixed 42 bytes regardless of batch size, both calls fit in a single XRPL payment - see [Memo Layout](/smart-accounts/custom-instruction#memo-layout).

## Sending the XRPL payment[​](#sending-the-xrpl-payment "Direct link to Sending the XRPL payment")

The rest of the flow is the `0xFE` three-step protocol described in full in the [Custom Instruction guide](/smart-accounts/guides/typescript-viem/custom-instruction-ts):

1.  `sendHashInstruction` (user side) commits the batch's hash to a 42-byte memo and sends the XRPL payment that doubles as the direct-minting payment.
2.  `executeDirectMintingWithData` (executor side) fetches the FDC proof and finalizes the mint and the batch atomically.
3.  `findUserOperationExecuted` (confirmation) reads the result straight off the executor's transaction receipt.

src/layer-zero/cross-chain-mint.ts

```
// Sample the Sepolia block height before the bridge runs so we don't miss// the OFTReceived event if the LayerZero delivery is unusually fast.const startSepoliaBlock = await sepoliaPublicClient.getBlockNumber();// --- 1. USER SIDE ---------------------------------------------------------const userSide = await sendHashInstruction({  label: "mint-approve-and-bridge",  customInstruction,  amountXrp: paymentAmountXrp,  personalAccount,  xrplClient,  xrplWallet,});// --- 2. EXECUTOR SIDE ------------------------------------------------------const { hash: executorTxHash, receipt } = await executeDirectMintingWithData({  xrplTransactionHash: userSide.xrplTransactionHash,  data: userSide.data,  value: userSide.totalCallValue,  xrplClient,  label: "mint-approve-and-bridge",});// --- 3. CONFIRMATION --------------------------------------------------------const event = findUserOperationExecuted(  receipt,  personalAccount,  userSide.nonce,);
```

The `value` parameter on `executeDirectMintingWithData` is the sum of `call.value` across the batch (here, just the LayerZero native fee) - it is forwarded `AssetManagerFXRP -> MasterAccountController -> PersonalAccount.executeUserOp`, so the inner `send` call can attach it. The LayerZero [`send`](https://docs.layerzero.network/v2/developers/evm/oft/quickstart) call runs inside that same Flare transaction, so `executorTxHash` doubles as the LayerZero scan link.

## Waiting for arrival on Sepolia[​](#waiting-for-arrival-on-sepolia "Direct link to Waiting for arrival on Sepolia")

Once the executor's transaction confirms and LayerZero has accepted the message, the script tracks the LayerZero scanner link and then polls Sepolia for the `OFTReceived` event on the [FXRP OFT](/fxrp/oft) contract.

src/layer-zero/cross-chain-mint.ts

```
console.log(`https://testnet.layerzeroscan.com/tx/${executorTxHash}`);const arrivalEvent = await waitForOftReceivedOnSepolia({  oftAddress: sepoliaOft,  toAddress: recipient,  fromBlock: startSepoliaBlock,});
```

The `waitForOftReceivedOnSepolia` helper is defined in the same file as the main flow; it queries `sepoliaPublicClient.getContractEvents` every 10 seconds for up to 10 minutes, filtering on the recipient address.

## Full Script[​](#full-script "Direct link to Full Script")

The repository with the above example is available on [GitHub](https://github.com/flare-foundation/flare-viem-starter). In the example repository, certain helpers are isolated into separate files in the `src/utils` directory.

```
pnpm run script src/layer-zero/cross-chain-mint.ts
```

src/layer-zero/cross-chain-mint.ts

```
import {  encodeFunctionData,  erc20Abi,  formatUnits,  pad,  type Address,} from "viem";import { EndpointId } from "@layerzerolabs/lz-definitions";import { Client, Wallet, xrpToDrops } from "xrpl";import { Options } from "@layerzerolabs/lz-v2-utilities";import { account, publicClient, sepoliaPublicClient } from "./utils/client";import {  executeDirectMintingWithData,  findUserOperationExecuted,  getPersonalAccountAddress,  sendHashInstruction,  type Call,} from "./utils/smart-accounts";import {  computeDirectMintingPaymentAmountXrp,  getFxrpDecimals,} from "./utils/fassets";import { getFxrpAddress } from "./utils/flare-contract-registry";import { abi as fxrpOftAbi } from "./abis/FXRPOFT";import type { SendParam } from "./types";const CONFIG = {  COSTON2_OFT_ADAPTER: "0xCd3d2127935Ae82Af54Fc31cCD9D3440dbF46639" as Address,  SEPOLIA_FXRP_OFT: process.env.SEPOLIA_FXRP_OFT as Address | undefined,  SEPOLIA_EID: EndpointId.SEPOLIA_V2_TESTNET,  EXECUTOR_GAS: 200_000,} as const;const SEPOLIA_ARRIVAL_TIMEOUT_MS = 10 * 60 * 1000;const SEPOLIA_ARRIVAL_POLL_INTERVAL_MS = 10_000;async function waitForOftReceivedOnSepolia({  oftAddress,  toAddress,  fromBlock,}: {  oftAddress: Address;  toAddress: Address;  fromBlock: bigint;}) {  const deadline = Date.now() + SEPOLIA_ARRIVAL_TIMEOUT_MS;  while (Date.now() < deadline) {    const logs = await sepoliaPublicClient.getContractEvents({      address: oftAddress,      abi: fxrpOftAbi,      eventName: "OFTReceived",      args: { toAddress },      fromBlock,      strict: true,    });    if (logs.length > 0) {      return logs[0]!;    }    await new Promise((resolve) =>      setTimeout(resolve, SEPOLIA_ARRIVAL_POLL_INTERVAL_MS),    );  }  throw new Error(    `OFTReceived event not observed on Sepolia within ${SEPOLIA_ARRIVAL_TIMEOUT_MS}ms`,  );}// NOTE: For this example to work, you first need to faucet C2FLR to your// personal account address.// 0xFE is a three-step protocol; this script runs all three steps inline.//// The personal account drives the OFT Adapter directly - 0xFE's 42-byte memo// removes the calldata-size constraint that the memo-field flow needs a shim// to satisfy.//// The total call.value (the LayerZero nativeFee) is forwarded as msg.value in// step 2, so it flows AssetManager -> MasterAccountController -> PersonalAccount// -> OFT Adapter. Unused native fee is refunded by the adapter to the personal// account (the refund address we pass to `send`).async function main() {  const fxrpMintAmountXrp = 10;  if (!CONFIG.SEPOLIA_FXRP_OFT) {    throw new Error(      "SEPOLIA_FXRP_OFT env var is required (address of the FXRP OFT on Sepolia)",    );  }  const sepoliaOft = CONFIG.SEPOLIA_FXRP_OFT;  const xrplClient = new Client(process.env.XRPL_TESTNET_RPC_URL!);  const xrplWallet = Wallet.fromSeed(process.env.XRPL_SEED!);  const recipient = account.address;  const [personalAccount, fxrpAddress, fxrpDecimals, paymentAmountXrp] =    await Promise.all([      getPersonalAccountAddress(xrplWallet.address),      getFxrpAddress(),      getFxrpDecimals(),      computeDirectMintingPaymentAmountXrp({        netMintAmountXrp: fxrpMintAmountXrp,      }),    ]);  const amountToBridge = BigInt(xrpToDrops(fxrpMintAmountXrp));  const extraOptions = Options.newOptions()    .addExecutorLzReceiveOption(CONFIG.EXECUTOR_GAS, 0)    .toHex() as `0x${string}`;  const sendParam: SendParam = {    dstEid: CONFIG.SEPOLIA_EID,    to: pad(recipient, { size: 32 }),    amountLD: amountToBridge,    minAmountLD: amountToBridge,    extraOptions,    composeMsg: "0x",    oftCmd: "0x",  };  const messagingFee = await publicClient.readContract({    address: CONFIG.COSTON2_OFT_ADAPTER,    abi: fxrpOftAbi,    functionName: "quoteSend",    args: [sendParam, false],  });  const nativeFee = messagingFee.nativeFee;  console.log("Personal account:", personalAccount);  console.log("FXRP token:", fxrpAddress);  console.log("OFT Adapter (Coston2):", CONFIG.COSTON2_OFT_ADAPTER);  console.log("\nCross-chain mint details:");  console.log("From (XRPL):", xrplWallet.address);  console.log("Via (Coston2 personal account):", personalAccount);  console.log("To (Sepolia):", recipient);  console.log(    "Net FXRP to mint & bridge:",    formatUnits(amountToBridge, fxrpDecimals),    "FXRP",  );  console.log("XRPL payment amount (mint + fees):", paymentAmountXrp, "XRP");  console.log("LayerZero native fee:", formatUnits(nativeFee, 18), "C2FLR");  const customInstruction: Call[] = [    {      target: fxrpAddress,      value: 0n,      data: encodeFunctionData({        abi: erc20Abi,        functionName: "approve",        args: [CONFIG.COSTON2_OFT_ADAPTER, amountToBridge],      }),    },    {      target: CONFIG.COSTON2_OFT_ADAPTER,      value: nativeFee,      data: encodeFunctionData({        abi: fxrpOftAbi,        functionName: "send",        args: [sendParam, { nativeFee, lzTokenFee: 0n }, personalAccount],      }),    },  ];  // Sample the Sepolia block height before the bridge runs so we don't miss  // the OFTReceived event if the LayerZero delivery is unusually fast.  const startSepoliaBlock = await sepoliaPublicClient.getBlockNumber();  // --- 1. USER SIDE ---------------------------------------------------------  const userSide = await sendHashInstruction({    label: "mint-approve-and-bridge",    customInstruction,    amountXrp: paymentAmountXrp,    personalAccount,    xrplClient,    xrplWallet,  });  // --- 2. EXECUTOR SIDE ------------------------------------------------------  const { hash: executorTxHash, receipt } = await executeDirectMintingWithData({    xrplTransactionHash: userSide.xrplTransactionHash,    data: userSide.data,    value: userSide.totalCallValue,    xrplClient,    label: "mint-approve-and-bridge",  });  // --- 3. CONFIRMATION --------------------------------------------------------  const event = findUserOperationExecuted(    receipt,    personalAccount,    userSide.nonce,  );  console.log("UserOperationExecuted:", event, "\n");  console.log("\nTrack your cross-chain transaction:");  console.log(`https://testnet.layerzeroscan.com/tx/${executorTxHash}`);  console.log(    "\nWaiting for FXRP to arrive on Sepolia (this can take a few minutes)...",  );  const arrivalEvent = await waitForOftReceivedOnSepolia({    oftAddress: sepoliaOft,    toAddress: recipient,    fromBlock: startSepoliaBlock,  });  console.log("\nFXRP arrived on Sepolia:");  console.log("  Tx hash:", arrivalEvent.transactionHash);  console.log(    "  Amount received:",    formatUnits(arrivalEvent.args.amountReceivedLD, fxrpDecimals),    "FXRP",  );  console.log("  Recipient:", arrivalEvent.args.toAddress);}void main()  .then(() => process.exit(0))  .catch((error) => {    console.error(error);    process.exit(1);  });
```

## Expected output[​](#expected-output "Direct link to Expected output")

```
Personal account: 0xFd2f0eb6b9fA4FE5bb1F7B26fEE3c647ed103d9FFXRP token: 0x0b6A3645c240605887a5532109323A3E12273dc7OFT Adapter (Coston2): 0xCd3d2127935Ae82Af54Fc31cCD9D3440dbF46639Cross-chain mint details:From (XRPL): rPdLcCkSJzLvURM2vV3bCWwXBgT7FyJojUVia (Coston2 personal account): 0xFd2f0eb6b9fA4FE5bb1F7B26fEE3c647ed103d9FTo (Sepolia): 0xF5488132432118596fa13800B68df4C0fF25131dNet FXRP to mint & bridge: 10 FXRPXRPL payment amount (mint + fees): 10.2 XRPLayerZero native fee: 22.950824887834713257 C2FLR[mint-approve-and-bridge] customInstruction: [  {    target: '0x0b6A3645c240605887a5532109323A3E12273dc7',    value: 0n,    data: '0x095ea7b3000000000000000000000000cd3d2127935ae82af54fc31ccd9d3440dbf466390000000000000000000000000000000000000000000000000000000000989680'  },  {    target: '0xCd3d2127935Ae82Af54Fc31cCD9D3440dbF46639',    value: 22950824887834713257n,    data: '0xc7c7f5b300000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000013e81b5a305951ca90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd2f0eb6b9fa4fe5bb1f7b26fee3c647ed103d9f0000000000000000000000000000000000000000000000000000000000009ce1000000000000000000000000F5488132432118596fa13800B68df4C0fF25131d0000000000000000000000000000000000000000000000000000000000989680000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000001600030100110100000000000000000000000000030d400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'  }][mint-approve-and-bridge] current nonce: 194n[mint-approve-and-bridge] userOpHash: 0xd5e696a799759b79bca768fa41a6e568424766fde45f2de62b72fecdd5b80a07[mint-approve-and-bridge] _data (1472 bytes): 0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000fd2f0eb6b9fa4fe5bb1f7b26fee3c647ed103d9f00000000000000000000000000000000000000000000000000000000000000c20000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e42b2ee78300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000b6a3645c240605887a5532109323a3e12273dc7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000cd3d2127935ae82af54fc31ccd9d3440dbf46639000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000000000000000000000000000000000cd3d2127935ae82af54fc31ccd9d3440dbf466390000000000000000000000000000000000000000000000013e81b5a305951ca9000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e4c7c7f5b300000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000013e81b5a305951ca90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd2f0eb6b9fa4fe5bb1f7b26fee3c647ed103d9f0000000000000000000000000000000000000000000000000000000000009ce1000000000000000000000000F5488132432118596fa13800B68df4C0fF25131d0000000000000000000000000000000000000000000000000000000000989680000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000001600030100110100000000000000000000000000030d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000[mint-approve-and-bridge] total call.value (native value to attach on executor tx): 22950824887834713257n[mint-approve-and-bridge] XRPL transaction hash: 5EF35694B74846271B21BF697BAF658F3FBC1FB6E9401CBAE4650B1C8D134C3E[mint-approve-and-bridge] Waiting for XRPL transaction to reach 3 confirmations[mint-approve-and-bridge] XRPL finality reached: 3 confirmations (txLedger=20096460, validated=20096462)[mint-approve-and-bridge] Preparing FDC XRPPayment attestation for txid 0x5ef35694b74846271b21bf697baf658f3fbc1fb6e9401cbae4650b1c8d134c3e (proofOwner=0xF5488132432118596fa13800B68df4C0fF25131d)Url: https://fdc-verifiers-testnet.flare.network/verifier/xrp/XRPPayment/prepareRequestPrepared request: {  attestationType: '0x5852505061796d656e7400000000000000000000000000000000000000000000',  sourceId: '0x7465737458525000000000000000000000000000000000000000000000000000',  requestBody: {    transactionId: '0x5ef35694b74846271b21bf697baf658f3fbc1fb6e9401cbae4650b1c8d134c3e',    proofOwner: '0xF5488132432118596fa13800B68df4C0fF25131d'  }}Response status is OKFDC attestation submitted. Round id: 1432039View round progress in explorer: https://coston2-systems-explorer.flare.network/voting-round/1432039?tab=fdcWaiting for FDC round to finalize...Round finalized.[mint-approve-and-bridge] FDC proof obtained (votingRound=1432039)[mint-approve-and-bridge] Calling executeDirectMintingWithData on 0xc1Ca88b937d0b528842F95d5731ffB586f4fbDFA (value=22950824887834713257)[mint-approve-and-bridge] executeDirectMintingWithData tx: 0x660816d1387a716824c9ba0ffeaf98d2f55ac43028754bff80e9c71f9e4cabbeUserOperationExecuted: {  eventName: 'UserOperationExecuted',  args: {    personalAccount: '0xFd2f0eb6b9fA4FE5bb1F7B26fEE3c647ed103d9F',    nonce: 194n  },  address: '0x434936d47503353f06750db1a444dbdc5f0ad37c',  topics: [    '0xf1fb8f9b365735a54cdafe3a27ffbad0a0cf1f35454f0c4c0c4dc68591d484fe',    '0x000000000000000000000000fd2f0eb6b9fa4fe5bb1f7b26fee3c647ed103d9f'  ],  data: '0x00000000000000000000000000000000000000000000000000000000000000c2',  blockNumber: 34318342n,  transactionHash: '0x660816d1387a716824c9ba0ffeaf98d2f55ac43028754bff80e9c71f9e4cabbe',  transactionIndex: 1,  blockHash: '0x808445358b047d509c1986b1a5a254d184d46bafedc754cb0eded38ca87df464',  logIndex: 19,  removed: false,  blockTimestamp: undefined}Track your cross-chain transaction:https://testnet.layerzeroscan.com/tx/0x660816d1387a716824c9ba0ffeaf98d2f55ac43028754bff80e9c71f9e4cabbeWaiting for FXRP to arrive on Sepolia (this can take a few minutes)...FXRP arrived on Sepolia:  Tx hash: 0xe5a614e4518ede743b1db69f10f618a4d593edc140a90fa687de724fbdf3f705  Amount received: 10 FXRP  Recipient: 0xF5488132432118596fa13800B68df4C0fF25131d
```

## What's next[​](#whats-next "Direct link to What's next")

-   [Auto Minting and Bridging FXRP](/fxrp/oft/fxrp-automint) - the FXRP-focused overview of this same flow.
-   [Cross-Chain Redeem guide](/smart-accounts/guides/typescript-viem/cross-chain-redeem-ts)
-   [Cross-Chain Redeem to Tag guide](/smart-accounts/guides/typescript-viem/cross-chain-redeem-to-tag-ts)
-   [Minting overview](/fassets/minting)
