Redeem FXRP with Tag
Overview
This guide walks you through redeeming FXRP using redeemWithTag on the AssetManagerFXRP contract.
Compared to redeemAmount, redeemWithTag adds a required XRPL destination tag that the agent must include in the redemption payment — useful when redeeming directly to an exchange address that requires a tag.
The complete runnable example is available in the flare-viem-starter repository.
Prerequisites
- An EVM wallet with.
- Native tokens on the same wallet to cover the gas fees.
- An XRPL destination address and the destination tag the recipient requires.
Redeem with Tag Script
src/fassets/redeem-with-tag.ts
import { coston2 } from "@flarenetwork/flare-wagmi-periphery-package";
import { parseEventLogs, type Address } from "viem";
import { account, publicClient, walletClient } from "./utils/client";
import { getContractAddressByName } from "./utils/flare-contract-registry";
// 1. Amount to redeem in UBA (underlying base units; 1 XRP = 1_000_000 UBA).
const REDEEM_AMOUNT_UBA = 5000000n;
// 2. Redeemer underlying (XRPL) address that will receive the redeemed XRP.
const REDEEMER_UNDERLYING_ADDRESS_STRING = "rSHYuiEvsYsKR8uUHhBTuGP5zjRcGt4nm";
// 3. Executor (not used here, so the zero address).
const EXECUTOR_ZERO_ADDRESS: Address =
"0x0000000000000000000000000000000000000000";
// 4. XRPL destination tag the agent must include in the redemption payment
// (must fit in 32 bits; e.g. an exchange deposit tag).
const REDEMPTION_DESTINATION_TAG = 72n;
async function main() {
// 5. Resolve the AssetManagerFXRP address from the Flare Contract Registry.
const assetManagerAddress =
await getContractAddressByName("AssetManagerFXRP");
console.log("AssetManagerFXRP address:", assetManagerAddress, "\n");
// 6. Read the protocol-wide minimum redemption amount and assert that the
// requested amount is above it. Smaller redemptions are rejected on-chain.
const minimumRedeemAmountUBA = await publicClient.readContract({
address: assetManagerAddress,
abi: coston2.iAssetManagerAbi,
functionName: "minimumRedeemAmountUBA",
});
console.log(
"minimumRedeemAmountUBA:",
minimumRedeemAmountUBA.toString(),
"\n",
);
console.log(
"Requested redeem amount UBA:",
REDEEM_AMOUNT_UBA.toString(),
"\n",
);
console.log(
"Redemption destination tag:",
REDEMPTION_DESTINATION_TAG.toString(),
"\n",
);
if (REDEEM_AMOUNT_UBA < minimumRedeemAmountUBA) {
throw new Error(
`Redeem amount (${REDEEM_AMOUNT_UBA.toString()}) must be greater than minimumRedeemAmountUBA (${minimumRedeemAmountUBA.toString()}).`,
);
}
// 7. Simulate the redeemWithTag call to validate args and produce a request
// that walletClient can submit.
const { request } = await publicClient.simulateContract({
account,
address: assetManagerAddress,
abi: coston2.iAssetManagerAbi,
functionName: "redeemWithTag",
args: [
REDEEM_AMOUNT_UBA,
REDEEMER_UNDERLYING_ADDRESS_STRING,
EXECUTOR_ZERO_ADDRESS,
REDEMPTION_DESTINATION_TAG,
],
});
// 8. Submit the redemption request transaction on Flare.
const txHash = await walletClient.writeContract(request);
console.log("redeemWithTag tx hash:", txHash, "\n");
// 9. Wait for the transaction receipt.
const receipt = await publicClient.waitForTransactionReceipt({
hash: txHash,
});
console.log("redeemWithTag status:", receipt.status, "\n");
// 10. Decode RedemptionWithTagRequested events from the receipt logs and
// pick the one that belongs to this redeemer.
const redemptionLogs = parseEventLogs({
abi: coston2.iAssetManagerAbi,
eventName: "RedemptionWithTagRequested",
logs: receipt.logs,
});
const redemptionEvent = redemptionLogs.find(
(log) => log.args.redeemer.toLowerCase() === account.address.toLowerCase(),
);
if (!redemptionEvent) {
throw new Error(
"RedemptionWithTagRequested event not found for this transaction and redeemer",
);
}
console.log("RedemptionWithTagRequested event:", redemptionEvent, "\n");
}
void main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Code Breakdown
- Set
REDEEM_AMOUNT_UBAto the amount of FXRP to redeem in UBA (underlying base unit). - Set
REDEEMER_UNDERLYING_ADDRESS_STRINGto the XRPL address that will receive the redeemed XRP from the agent. EXECUTOR_ZERO_ADDRESSis used because no executor is appointed in this example. Pass a real address to delegate default-handling to an executor.- Set
REDEMPTION_DESTINATION_TAGto the XRPL destination tag the agent must include on the redemption payment. It must fit in a 32-bit integer. See minting with tag for more details or check out the minting with tag example on how to reserve a tag. - Resolve the
AssetManagerFXRPaddress through the Flare Contract Registry usinggetContractAddressByName. - Read
minimumRedeemAmountUBAand check that the requested amount is at least the protocol minimum. - Simulate the
redeemWithTagcall to validate the arguments and produce a signed request payload. - Submit the redemption request transaction.
- Wait for the transaction receipt.
- Decode
RedemptionWithTagRequestedevents from the receipt logs with theparseEventLogsfunction and select the one whoseredeemermatches the caller. A single call may emit multipleRedemptionWithTagRequestedevents when multiple agents fulfill the request.
Important Notes
- XRP-only feature.
redeemWithTagis an XRP-only feature and is only available for FXRP. minimumRedeemAmountUBAis enforced on-chain. Requests below the threshold revert.- The redemption may be partial. If the request requires too many redemption tickets, only part is filled and the leftover is returned via
RedemptionAmountIncomplete. CallredeemWithTagagain for the remainder. - Multiple agents may pay. A single
redeemWithTagcall can produce severalRedemptionWithTagRequestedevents — one per agent serving the request. Track eachrequestIdfor the agent's underlying-chain payment. - Default uses a dedicated proof type. Confirming a tagged redemption uses
confirmXRPRedemptionPayment, and if the agent fails to pay callxrpRedemptionPaymentDefaultto start the default process.
What's next
To continue your FAssets development journey, you can:
- Redeem any amount without a tag with
redeemAmount. - Handle non-paying agents in Monitor Redemptions & Execute Defaults.
- Mint without a tag using memo-based direct minting or direct minting with tag.