Skip to content

Commit 5ea3aa6

Browse files
authored
docs(feat): fassets minting guide (#696)
1 parent 815b399 commit 5ea3aa6

File tree

7 files changed

+477
-4
lines changed

7 files changed

+477
-4
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
title: Mint FAssets
3+
tags: [intermediate, fassets]
4+
slug: fassets-mint
5+
description: Learn how to mint FAssets
6+
keywords: [fassets, flare-network]
7+
sidebar_position: 3
8+
---
9+
10+
import CodeBlock from "@theme/CodeBlock";
11+
import Remix from "@site/src/components/remix";
12+
import FAssetsReserveCollateral from "!!raw-loader!/examples/developer-hub-javascript/fassetsReserveCollateral.ts";
13+
import FAssetsCreateXrpPayment from "!!raw-loader!/examples/developer-hub-javascript/fassetsCreateXrpPayment.ts";
14+
import FAssetsExecuteMinting from "!!raw-loader!/examples/developer-hub-javascript/fassetsExecuteMinting.ts";
15+
16+
## Overview
17+
18+
This guide walks you through the complete process of minting FAssets (e.g., FXRP) on the Flare network.
19+
20+
Minting FAssets is the process of wrapping, for instance, XRP from the XRP Ledger into an FAsset, enabling it to be used within the Flare blockchain ecosystem.
21+
22+
See the [Minting](/fassets/minting) overview for more details.
23+
24+
## Prerequisites
25+
26+
- [Flare Hardhat Starter Kit](/network/guides/hardhat-foundry-starter-kit)
27+
- [Flare Network Periphery Contracts](https://www.npmjs.com/package/@flarenetwork/flare-periphery-contracts)
28+
29+
## Minting Process Steps
30+
31+
The minting process is a multi-step process that involves the following steps:
32+
33+
1. Reserve collateral from a suitable agent.
34+
2. Send the underlying asset (e.g., XRP) to the agent.
35+
3. Use [Flare Data Connector (FDC)](/fdc/overview) to generate proof of payment.
36+
4. Execute minting with the proof to receive FAssets.
37+
38+
## Reserve Collateral
39+
40+
The following code demonstrates how to reserve collateral by calling the [`reserveCollateral()`](/fassets/reference/IAssetManager#reservecollateral) function on the AssetManager contract.
41+
42+
<CodeBlock language="typescript" title="scripts/fassets/reserveCollateral.ts">
43+
{FAssetsReserveCollateral}
44+
</CodeBlock>
45+
46+
### Collateral Reservation Script Breakdown
47+
48+
1. Define constants
49+
50+
- `ASSET_MANAGER_ADDRESS`: FXRP AssetManager address on Songbird Testnet (Coston).
51+
- `LOTS_TO_MINT`: Number of FAsset lots to reserve.
52+
- `UNDERLYING_ADDRESS`: Target XRP Ledger address for the minted asset.
53+
- `ZERO_ADDRESS`: Placeholder for `executor` (not used in this script).
54+
55+
2. Retrieve and filter agents with enough free collateral and select the agent with the lowest fee and normal status.
56+
3. Parse [`CollateralReserved`](/fassets/reference/IAssetManagerEvents#collateralreserved) event.
57+
4. Start the minting reservation process at the script's entry point.
58+
5. Call `findBestAgent()` with the required number of lots.
59+
6. Fetch agent metadata from [`getAgentInfo()`](/fassets/reference/IAssetManager#getagentinfo) to get the agent's `feeBIPS`, which is used to calculate the collateral reservation fee.
60+
7. Calculate the collateral reservation fee by calling [`collateralReservationFee()`](/fassets/reference/IAssetManager#collateralreservationfee).
61+
8. Reserve collateral from agent by calling [`reserveCollateral()`](/fassets/reference/IAssetManager#reservecollateral)
62+
9. Call `assetMintingDecimals()` to determine the XRP token's decimal precision.
63+
10. Parse the [`CollateralReserved`](/fassets/reference/IAssetManagerEvents#collateralreserved) event.
64+
11. Calculate the total XRP value required for payment.
65+
66+
## Send Payment on XRP Ledger
67+
68+
The next step is to send the XRP Ledger payment to the agent, and you can use this script to do that.
69+
70+
<CodeBlock language="typescript" title="scripts/fassets/xrpPayment.ts">
71+
{FAssetsCreateXrpPayment}
72+
</CodeBlock>
73+
74+
### XRP Payment Script Breakdown
75+
76+
1. Install the `xrpl` package — it's not included in the Flare Hardhat Starter Kit by default.
77+
2. Define the needed constants.
78+
3. Create a client to connect to the XRP Ledger Testnet.
79+
4. Load the sender wallet.
80+
5. Construct the payment transaction.
81+
6. Sign and submit the transaction.
82+
83+
## Generate Proof with Flare Data Connector
84+
85+
Use the [FDC Payment](/fdc/guides/hardhat/payment) script to validate the XRP payment and generate a Merkle proof.
86+
87+
## Execute Minting
88+
89+
Once the XRP payment is validated, you can retrieve the FDC proof from the [Data Availability Layer](/fdc/overview#data-availability-layer) and call the [`executeMinting()`](/fassets/reference/IAssetManager#executeminting) function on the AssetManager contract.
90+
91+
This script demonstrates how to retrieve the FDC proof and execute minting.
92+
93+
<CodeBlock language="typescript" title="scripts/fassets/executeMinting.ts">
94+
{FAssetsExecuteMinting}
95+
</CodeBlock>
96+
97+
### Execute Minting Script Breakdown
98+
99+
1. Get environment variables.
100+
2. Declare the constant `ASSET_MANAGER_ADDRESS` pointing to the FXRP AssetManager on the Songbird Testnet (Coston network).
101+
102+
3. Set the collateral reservation ID to the previously reserved minting request.
103+
4. Set the Flare Data Connector (FDC) round ID to retrieve the proof.
104+
5. Prepare the FDC request payload data.
105+
6. Create a function to get the proof from the FDC.
106+
It sends a POST request to the [Flare Data Availability Layer](/fdc/overview#data-availability-layer) and returns a Merkle proof and attestation response from FDC.
107+
7. Retrieve the FDC proof from the Data Availability Layer.
108+
8. Call the [`executeMinting()`](/fassets/reference/IAssetManager#executeminting) function on the AssetManager contract and send a transaction to the Flare network to convert the attested XRP payment into FXRP (minting).
109+
9. On a successful transaction call `parseExecutemintingEvents()` to extract and log events [`RedemptionTicketCreated`](/fassets/reference/IAssetManagerEvents#redemptionticketcreated) and [`MintingExecuted`](/fassets/reference/IAssetManagerEvents#mintingexecuted).
110+
111+
## Next Steps
112+
113+
Now that you have successfully minted FAssets, you can use them in Flare dApps or transfer them to other users or smart contracts within the Flare ecosystem.
114+
115+
:::tip Redeem
116+
To convert your FAssets (e.g., FXRP) back into the original asset (e.g., XRP), follow the steps in the [FAssets Redemption Guide](/fassets/developer-guides/fassets-redeem).
117+
:::

docs/fassets/developer-guides/3-fassets-redeem.mdx renamed to docs/fassets/developer-guides/4-fassets-redeem.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ tags: [intermediate, fassets]
44
slug: fassets-redeem
55
description: Learn how to redeem FAssets
66
keywords: [fassets, flare-network]
7-
sidebar_position: 3
7+
sidebar_position: 4
88
---
99

1010
import CodeBlock from "@theme/CodeBlock";

docs/fassets/developer-guides/4-fassets-swap-redeem.mdx renamed to docs/fassets/developer-guides/5-fassets-swap-redeem.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ tags: [intermediate, fassets]
44
slug: fassets-swap-redeem
55
description: Learn how to swap and redeem FAssets
66
keywords: [fassets, flare-network]
7-
sidebar_position: 4
7+
sidebar_position: 5
88
---
99

1010
import CodeBlock from "@theme/CodeBlock";

docs/fassets/reference/IAssetManagerEvents.mdx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ sidebar_position: 2
99

1010
Sourced from `IAssetManagerEvents.sol` on [GitHub](https://github.com/flare-foundation/fassets/blob/main/contracts/userInterfaces/IAssetManagerEvents.sol).
1111

12-
// ... existing code ...
13-
1412
## Events
1513

1614
### `CollateralReserved`
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// 1. install xrpl package
2+
// https://www.npmjs.com/package/xrpl
3+
import { Client, Wallet, xrpToDrops, Payment, TxResponse } from "xrpl";
4+
5+
// 2. Define the constants
6+
const AGENT_ADDRESS = "r4KgCNzn9ZuNjpf17DEHZnyyiqpuj599Wm"; // Agent underlying chain address
7+
const AMOUNT_XRP = "20.05"; // XRP amount to send
8+
const PAYMENT_REFERENCE =
9+
"4642505266410001000000000000000000000000000000000000000000f655fb"; // Reference
10+
11+
async function send20XrpWithReference() {
12+
// 3. Create a client to connect to the XRP Ledger Testnet
13+
const client = new Client("wss://s.altnet.rippletest.net:51233"); // Testnet
14+
await client.connect();
15+
16+
// 4. XRP Ledger Testnet seed
17+
const wallet: Wallet = Wallet.fromSeed("s000000000000000000000000000000"); // Sender wallet seed
18+
19+
// 5. Create a payment transaction
20+
const paymentTx: Payment = {
21+
TransactionType: "Payment",
22+
Account: wallet.classicAddress,
23+
// Agent underlying chain address
24+
Destination: AGENT_ADDRESS,
25+
// XRP amount to send
26+
Amount: xrpToDrops(AMOUNT_XRP),
27+
// Payment reference
28+
InvoiceID: PAYMENT_REFERENCE, // Reference
29+
};
30+
31+
console.log(paymentTx);
32+
33+
// 6. Execute the transaction
34+
const prepared = await client.autofill(paymentTx);
35+
const signed = wallet.sign(prepared);
36+
const result: TxResponse = await client.submitAndWait(signed.tx_blob);
37+
38+
console.log("Transaction hash:", signed.hash);
39+
console.log("Explorer: https://testnet.xrpl.org/transactions/" + signed.hash);
40+
console.log("Result:", result);
41+
42+
await client.disconnect();
43+
}
44+
45+
send20XrpWithReference().catch(console.error);
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { artifacts, ethers } from "hardhat";
2+
3+
import { prepareAttestationRequestBase } from "../fdcExample/Base";
4+
import {
5+
IAssetManagerInstance,
6+
IAssetManagerContract,
7+
} from "../../typechain-types";
8+
9+
// 1. Environment variables
10+
const { COSTON2_DA_LAYER_URL, VERIFIER_URL_TESTNET, VERIFIER_API_KEY_TESTNET } =
11+
process.env;
12+
13+
// 2. AssetManager address on Flare Testnet Coston2 network
14+
const ASSET_MANAGER_ADDRESS = "0xDeD50DA9C3492Bee44560a4B35cFe0e778F41eC5";
15+
16+
// 3. Collateral reservation ID
17+
const COLLATERAL_RESERVATION_ID = 18615047;
18+
19+
// 4. Data to get the proof for
20+
const TARGET_ROUND_ID = 987510;
21+
22+
const attestationTypeBase = "Payment";
23+
const sourceIdBase = "testXRP";
24+
const verifierUrlBase = VERIFIER_URL_TESTNET;
25+
const urlTypeBase = "xrp";
26+
27+
// XRP transaction
28+
const transactionId =
29+
"65520665BB83D582E01D6813DA8B5ECB041F613F9891F9BE90EE2668AAC30543";
30+
const inUtxo = "0";
31+
const utxo = "0";
32+
33+
// 5. Prepare FDC request
34+
async function prepareFdcRequest(
35+
transactionId: string,
36+
inUtxo: string,
37+
utxo: string,
38+
) {
39+
const requestBody = {
40+
transactionId: transactionId,
41+
inUtxo: inUtxo,
42+
utxo: utxo,
43+
};
44+
45+
const url = `${verifierUrlBase}verifier/${urlTypeBase}/Payment/prepareRequest`;
46+
47+
return await prepareAttestationRequestBase(
48+
url,
49+
VERIFIER_API_KEY_TESTNET,
50+
attestationTypeBase,
51+
sourceIdBase,
52+
requestBody,
53+
);
54+
}
55+
56+
// 6. Get proof from FDC
57+
async function getProof(roundId: number) {
58+
const request = await prepareFdcRequest(transactionId, inUtxo, utxo);
59+
const proofAndData = await fetch(
60+
`${COSTON2_DA_LAYER_URL}api/v0/fdc/get-proof-round-id-bytes`,
61+
{
62+
method: "POST",
63+
headers: {
64+
"Content-Type": "application/json",
65+
"X-API-KEY": VERIFIER_API_KEY_TESTNET,
66+
},
67+
body: JSON.stringify({
68+
votingRoundId: roundId,
69+
requestBytes: request.abiEncodedRequest,
70+
}),
71+
},
72+
);
73+
74+
return await proofAndData.json();
75+
}
76+
77+
async function parseEvents(receipt) {
78+
console.log("\nParsing events...", receipt.rawLogs);
79+
80+
const assetManager = (await ethers.getContractAt(
81+
"IAssetManager",
82+
ASSET_MANAGER_ADDRESS,
83+
)) as IAssetManagerContract;
84+
85+
for (const log of receipt.rawLogs) {
86+
try {
87+
const parsedLog = assetManager.interface.parseLog({
88+
topics: log.topics,
89+
data: log.data,
90+
});
91+
92+
if (!parsedLog) continue;
93+
94+
const collateralReservedEvents = [
95+
"RedemptionTicketCreated",
96+
"MintingExecuted",
97+
];
98+
if (!collateralReservedEvents.includes(parsedLog.name)) continue;
99+
100+
console.log(`\nEvent: ${parsedLog.name}`);
101+
console.log("Arguments:", parsedLog.args);
102+
} catch (e) {
103+
console.log("Error parsing event:", e);
104+
}
105+
}
106+
}
107+
108+
async function main() {
109+
// 7. Get proof from FDC
110+
const proof = await getProof(TARGET_ROUND_ID);
111+
112+
// FAssets FXRP asset manager on Songbird Testnet Coston2 network
113+
const AssetManager = artifacts.require("IAssetManager");
114+
const assetManager: IAssetManagerInstance = await AssetManager.at(
115+
ASSET_MANAGER_ADDRESS,
116+
);
117+
118+
// 8. Execute minting with the proof
119+
const tx = await assetManager.executeMinting(
120+
{
121+
merkleProof: proof.proof,
122+
data: proof.response,
123+
},
124+
COLLATERAL_RESERVATION_ID,
125+
);
126+
console.log("Transaction successful:", tx);
127+
128+
// 9. Parse execute minting log events
129+
await parseEvents(tx.receipt);
130+
}
131+
132+
main().catch((error) => {
133+
console.error(error);
134+
process.exitCode = 1;
135+
});

0 commit comments

Comments
 (0)