Skip to content

Commit cdb05b3

Browse files
vrtnd0xreflexivity
andauthored
fxrp (#431)
* add: fxrp fasset * fix: XRPL name and remove comments --------- Co-authored-by: amadiaflare <anthony.madia@flare.network>
1 parent 173f2bc commit cdb05b3

File tree

4 files changed

+175
-5
lines changed

4 files changed

+175
-5
lines changed

src/adapters/flare/fxrp/index.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { BridgeAdapter, PartialContractEventParams } from "../../../helpers/bridgeAdapter.type";
2+
import { getTxDataFromEVMEventLogs } from "../../../helpers/processTransactions";
3+
4+
const FXRP = "0xAd552A648C74D49E10027AB8a618A3ad4901c5bE";
5+
const ZERO = "0x0000000000000000000000000000000000000000";
6+
7+
const transferAbi = [
8+
"event Transfer(address indexed from, address indexed to, uint256 value)",
9+
];
10+
11+
const depositMintParams: PartialContractEventParams = {
12+
target: FXRP,
13+
topic: "Transfer(address,address,uint256)",
14+
abi: transferAbi,
15+
isDeposit: true,
16+
logKeys: {
17+
blockNumber: "blockNumber",
18+
txHash: "transactionHash",
19+
token: "address",
20+
},
21+
argKeys: {
22+
from: "from",
23+
to: "to",
24+
amount: "value",
25+
},
26+
filter: {
27+
includeFrom: [ZERO],
28+
},
29+
};
30+
31+
const withdrawBurnParams: PartialContractEventParams = {
32+
target: FXRP,
33+
topic: "Transfer(address,address,uint256)",
34+
abi: transferAbi,
35+
isDeposit: false,
36+
logKeys: {
37+
blockNumber: "blockNumber",
38+
txHash: "transactionHash",
39+
token: "address",
40+
},
41+
argKeys: {
42+
from: "from",
43+
to: "to",
44+
amount: "value",
45+
},
46+
filter: {
47+
includeTo: [ZERO],
48+
},
49+
};
50+
51+
const constructParams = () => {
52+
const eventParams = [depositMintParams, withdrawBurnParams];
53+
return async (fromBlock: number, toBlock: number) =>
54+
getTxDataFromEVMEventLogs("fxrp", "flare", fromBlock, toBlock, eventParams);
55+
};
56+
57+
const adapter: BridgeAdapter = {
58+
flare: constructParams(),
59+
};
60+
61+
export default adapter;

src/adapters/flare/fxrp/test.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { getLogs } from "@defillama/sdk/build/util";
2+
import { ethers } from "ethers";
3+
import BigNumber from "bignumber.js";
4+
import { getLlamaPrices } from "../../../utils/prices";
5+
6+
const FXRP = "0xAd552A648C74D49E10027AB8a618A3ad4901c5bE";
7+
const ZERO = "0x0000000000000000000000000000000000000000";
8+
const TRANSFER_TOPIC = ethers.utils.id("Transfer(address,address,uint256)");
9+
10+
async function main() {
11+
// pick a recent range; widen if needed
12+
const fromBlock = 48104361;
13+
const toBlock = 48185336;
14+
15+
const logs = (await getLogs({
16+
target: FXRP,
17+
topic: "Transfer(address,address,uint256)",
18+
keys: [],
19+
fromBlock,
20+
toBlock,
21+
topics: [TRANSFER_TOPIC],
22+
chain: "flare",
23+
})).output;
24+
25+
// Fetch price/decimals once for FXRP at a representative timestamp (end of window)
26+
const tokenKey = `flare:${FXRP.toLowerCase()}`;
27+
const approxTs = Math.floor(Date.now() / 1000); // Optionally replace with block->ts lookup for higher accuracy
28+
const prices = await getLlamaPrices([tokenKey], approxTs);
29+
const priceData = prices[tokenKey];
30+
if (!priceData) {
31+
console.warn(`No price data for ${tokenKey}. USD values will be omitted.`);
32+
}
33+
const tokenDecimals = priceData?.decimals ?? 18; // fallback to 18 if missing
34+
const tokenPrice = priceData?.price ?? 0;
35+
36+
const iface = new ethers.utils.Interface([
37+
"event Transfer(address indexed from, address indexed to, uint256 value)",
38+
]);
39+
40+
const specialHits: any[] = [];
41+
let mintCount = 0, burnCount = 0, xferCount = 0;
42+
let mintUsd = 0, burnUsd = 0, xferUsd = 0;
43+
for (const log of logs) {
44+
const parsed = iface.parseLog({ topics: [...log.topics], data: log.data });
45+
const from = parsed.args.from.toLowerCase();
46+
const to = parsed.args.to.toLowerCase();
47+
const rawAmount = new BigNumber(parsed.args.value.toString());
48+
const amount = rawAmount.dividedBy(new BigNumber(10).pow(tokenDecimals));
49+
const usd = amount.multipliedBy(tokenPrice).toNumber();
50+
if (from === ZERO || to === ZERO) {
51+
specialHits.push({
52+
blockNumber: log.blockNumber,
53+
txHash: log.transactionHash,
54+
from,
55+
to,
56+
amount: amount.toString(10),
57+
usd,
58+
});
59+
}
60+
61+
if (from === ZERO) {
62+
mintCount += 1;
63+
mintUsd += usd || 0;
64+
} else if (to === ZERO) {
65+
burnCount += 1;
66+
burnUsd += usd || 0;
67+
} else {
68+
xferCount += 1;
69+
xferUsd += usd || 0;
70+
}
71+
}
72+
73+
console.log("Special mint/burn-like hits:");
74+
console.table(specialHits);
75+
76+
// USD summary
77+
const fmt = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 2 });
78+
const netMinted = mintUsd - burnUsd;
79+
console.log(`[flare | FXRP] Summary for blocks ${fromBlock}-${toBlock}`);
80+
console.log(`Mints (from ZERO): ${mintCount}, USD: ${fmt.format(mintUsd)}`);
81+
console.log(`Burns (to ZERO): ${burnCount}, USD: ${fmt.format(burnUsd)}`);
82+
console.log(`Regular transfers: ${xferCount}, USD: ${fmt.format(xferUsd)}`);
83+
console.log(`Net minted USD (Mints - Burns): ${fmt.format(netMinted)}`);
84+
85+
// optional: surface any “suspicious” constant sink addresses you might treat as burns
86+
const counts: Record<string, number> = {};
87+
for (const l of logs) {
88+
const parsed = iface.parseLog({ topics: [...l.topics], data: l.data });
89+
const to = parsed.args.to.toLowerCase();
90+
counts[to] = (counts[to] || 0) + 1;
91+
}
92+
console.log("Top 'to' addresses:");
93+
console.log(Object.entries(counts).sort((a,b) => b[1]-a[1]).slice(0,20));
94+
}
95+
96+
main().catch(console.error);

src/adapters/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ import usdt0 from "./usdt0";
9595
import pheasantNetwork from "./pheasant-network";
9696
import teleswap from "./teleswap";
9797
import agglayer from "./agglayer";
98+
import fxrp from "./flare/fxrp";
9899

99100
export default {
100101
polygon,
@@ -193,6 +194,7 @@ export default {
193194
pheasantNetwork,
194195
teleswap,
195196
agglayer,
197+
fxrp,
196198
} as {
197199
[bridge: string]: BridgeAdapter | AsyncBridgeAdapter;
198200
};

src/data/bridgeNetworkData.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2525,25 +2525,25 @@ export default [
25252525
url: "https://app.cashmere.exchange/",
25262526
chains: [
25272527
"ethereum",
2528-
"avax", // Changed: match adapter export
2528+
"avax", // Changed: match adapter export
25292529
"optimism",
25302530
"arbitrum",
25312531
"base",
25322532
"polygon",
25332533
"unichain",
25342534
"linea",
25352535
"sonic",
2536-
"wc", // Changed: match adapter export
2536+
"wc", // Changed: match adapter export
25372537
"sei",
25382538
"hyperliquid",
25392539
"aptos",
25402540
"sui",
25412541
"solana",
25422542
],
25432543
chainMapping: {
2544-
"avax": "avax", // Identity mapping
2545-
"wc": "wc", // Identity mapping
2546-
"hyperliquid": "hyperliquid", // Identity mapping
2544+
avax: "avax", // Identity mapping
2545+
wc: "wc", // Identity mapping
2546+
hyperliquid: "hyperliquid", // Identity mapping
25472547
},
25482548
},
25492549
{
@@ -2569,4 +2569,15 @@ export default [
25692569
"Linea",
25702570
],
25712571
},
2572+
{
2573+
id: 100,
2574+
displayName: "FAssets",
2575+
bridgeDbName: "fxrp",
2576+
slug: "flare",
2577+
iconLink: "chain:flare",
2578+
largeTxThreshold: 10000,
2579+
url: "https://flare.network/products/fassets",
2580+
chains: ["Flare", "XRPL"],
2581+
destinationChain: "XRPL",
2582+
},
25722583
] as BridgeNetwork[];

0 commit comments

Comments
 (0)