Skip to content

Commit 3bc7fe0

Browse files
authored
Add Mayan Finance volume to bridges (#415)
* set up mayan adapter * Add Mayan adapter and integrate event fetching and volume calculation * Refactor Mayan event fetching to use API key and improve error handling; streamline volume calculation logic * deleted pnpm lock yaml * removed old comment * Refactor Mayan event fetching to use secure API endpoint and improve error handling; update handler export for scheduled execution
1 parent 1b714b1 commit 3bc7fe0

File tree

6 files changed

+384
-17
lines changed

6 files changed

+384
-17
lines changed

src/adapters/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ import retrobridge from "./retrobridge";
7676
import layerswap from "./layerswap";
7777
import hyperlane from "./hyperlane";
7878
import wormhole from "./wormhole";
79+
import mayan from "./mayan";
7980
import thresholdnetwork from "./threshold-network";
8081
import zircuit from "./zircuit";
8182
import hyperliquid from "./hyperliquid";
@@ -172,6 +173,7 @@ export default {
172173
layerswap,
173174
hyperlane,
174175
wormhole,
176+
mayan,
175177
thresholdnetwork,
176178
zircuit,
177179
hyperliquid,

src/adapters/mayan/index.ts

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import dayjs from "dayjs";
2+
type WormholeBridgeEvent = {
3+
block_timestamp: string;
4+
transaction_hash: string;
5+
token_transfer_from_address: string;
6+
token_transfer_to_address: string;
7+
token_address: string;
8+
token_usd_amount: string;
9+
token_amount: string;
10+
source_chain: string;
11+
destination_chain: string;
12+
is_deposit?: boolean;
13+
};
14+
15+
const chains = [
16+
"ethereum",
17+
"avalanche",
18+
"avax",
19+
"bsc",
20+
"polygon",
21+
"arbitrum",
22+
"optimism",
23+
"base",
24+
"zksync",
25+
"scroll",
26+
"aptos",
27+
"sui",
28+
"solana",
29+
"sei",
30+
"mantle",
31+
"fantom",
32+
"injective",
33+
"moonbeam",
34+
"oasis",
35+
"celo",
36+
"kaia",
37+
"near",
38+
"algorand",
39+
"terra",
40+
"terra classic",
41+
"karura",
42+
"acala",
43+
"wormchain",
44+
];
45+
46+
export const chainNameMapping: { [key: string]: string } = {
47+
ethereum: "Ethereum",
48+
avalanche: "Avalanche",
49+
avax: "Avalanche",
50+
polygon: "Polygon",
51+
arbitrum: "Arbitrum",
52+
optimism: "Optimism",
53+
fantom: "Fantom",
54+
base: "Base",
55+
solana: "Solana",
56+
sui: "Sui",
57+
aptos: "Aptos",
58+
celo: "Celo",
59+
mantle: "Mantle",
60+
scroll: "Scroll",
61+
algorand: "Algorand",
62+
sei: "Sei",
63+
moonbeam: "Moonbeam",
64+
injective: "Injective",
65+
kaia: "Kaia",
66+
oasis: "Oasis",
67+
BNB_Smart_Chain: "BSC",
68+
bnb_smart_chain: "BSC",
69+
terra: "Terra Classic",
70+
terra2: "Terra",
71+
"terra classic": "Terra Classic",
72+
near: "Near",
73+
karura: "Karura",
74+
acala: "Acala",
75+
wormchain: "Wormchain",
76+
xlayer: "xLayer",
77+
blast: "Blast",
78+
xpla: "XPLA",
79+
};
80+
81+
export function normalizeChainName(chainName: string): string {
82+
const lowercaseChain = chainName.toLowerCase();
83+
84+
const mapping = chainNameMapping[lowercaseChain] || chainNameMapping[chainName];
85+
86+
if (mapping) {
87+
return mapping?.toLowerCase();
88+
}
89+
90+
return chainName?.toLowerCase();
91+
}
92+
93+
// Map wormhole chain IDs to chain names
94+
const wormholeChainMap: { [key: string]: string } = {
95+
"1": "solana",
96+
"2": "ethereum",
97+
"30": "base",
98+
"23": "arbitrum",
99+
"24": "optimism",
100+
"5": "polygon",
101+
"6": "avalanche",
102+
"4": "bsc",
103+
"21": "sui",
104+
"44": "unichain",
105+
"22": "aptos",
106+
"38": "linea",
107+
};
108+
109+
export const fetchMayanEvents = async (fromTimestamp: number, toTimestamp: number): Promise<WormholeBridgeEvent[]> => {
110+
let allResults: WormholeBridgeEvent[] = [];
111+
let offset = 0;
112+
const BATCH_SIZE = 10000;
113+
const API_KEY = process.env.MAYAN_API_KEY || "";
114+
115+
// Convert timestamps to milliseconds for API
116+
const startMs = fromTimestamp * 1000;
117+
const endMs = toTimestamp * 1000;
118+
119+
while (true) {
120+
try {
121+
const url = `https://dlapi.wormhole.com/swaps?startTs=${startMs}&endTs=${endMs}&offset=${offset}&limit=${BATCH_SIZE}`;
122+
123+
const response = await fetch(url, {
124+
headers: {
125+
"API-KEY": API_KEY,
126+
"Content-Type": "application/json",
127+
},
128+
});
129+
130+
if (!response.ok) {
131+
throw new Error(`API request failed with status: ${response.status}`);
132+
}
133+
134+
const result = await response.json();
135+
136+
if (result.length === 0) {
137+
break;
138+
}
139+
140+
const normalizedBatch = result.map((row: any) => {
141+
// Parse timestamp - handle both ISO string and unix formats
142+
const timestamp = row.ts ? dayjs(row.ts).unix() : dayjs().unix();
143+
144+
// Map chain IDs to chain names
145+
const sourceChain = wormholeChainMap[row.originChain] || row.originChain || "unknown";
146+
const destChain = wormholeChainMap[row.chain] || row.chain || "unknown";
147+
148+
// For deposits, swap source/dest (deposit means going FROM origin TO current chain)
149+
const [source, dest] = row.isDeposit ? [sourceChain, destChain] : [destChain, sourceChain];
150+
151+
// Parse USD amount
152+
const usdAmount = parseFloat(row.amountUsd || "0") || 0;
153+
154+
return {
155+
block_timestamp: timestamp,
156+
transaction_hash: row.txHash || row.orderId || "",
157+
token_transfer_from_address: row.txFrom || "",
158+
token_transfer_to_address: row.txTo || "",
159+
token_address: row.token || "",
160+
token_usd_amount: String(usdAmount),
161+
token_amount: row.amount || "0",
162+
source_chain: source,
163+
destination_chain: dest,
164+
is_deposit: row.isDeposit, // Include deposit flag for filtering in handler
165+
};
166+
});
167+
168+
allResults = [...allResults, ...normalizedBatch];
169+
170+
offset += BATCH_SIZE;
171+
172+
if (result.length < BATCH_SIZE) {
173+
break;
174+
}
175+
} catch (error) {
176+
throw error;
177+
}
178+
}
179+
180+
return allResults;
181+
};
182+
183+
const adapter = chains.reduce((acc: any, chain: string) => {
184+
acc[chain] = true;
185+
return acc;
186+
}, {});
187+
188+
export default adapter;

src/data/bridgeNetworkData.ts

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,14 +1235,27 @@ export default [
12351235
iconLink: "icons:butter-network",
12361236
largeTxThreshold: 10000,
12371237
url: "",
1238-
chains: ["Ethereum", "Polygon", "BSC", "Arbitrum", "Base", "Optimism", "Tron",
1239-
"X Layer", "MAP Relay Chain", "Kaia", "Linea",
1240-
"Scroll", "Mantle", "Merlin", "Blast"],
1238+
chains: [
1239+
"Ethereum",
1240+
"Polygon",
1241+
"BSC",
1242+
"Arbitrum",
1243+
"Base",
1244+
"Optimism",
1245+
"Tron",
1246+
"X Layer",
1247+
"MAP Relay Chain",
1248+
"Kaia",
1249+
"Linea",
1250+
"Scroll",
1251+
"Mantle",
1252+
"Merlin",
1253+
"Blast",
1254+
],
12411255
chainMapping: {
12421256
"map relay chain": "map",
12431257
"x layer": "xlayer",
12441258
kaia: "klaytn",
1245-
12461259
},
12471260
destinationChain: "MAP Relay Chain",
12481261
},
@@ -2455,13 +2468,7 @@ export default [
24552468
iconLink: "icons:agglayer",
24562469
largeTxThreshold: 10000,
24572470
url: "https://agglayer.dev/",
2458-
chains: [
2459-
"Ethereum",
2460-
"Katana",
2461-
"Polygon Zkevm",
2462-
"Ternoa",
2463-
"X Layer"
2464-
],
2471+
chains: ["Ethereum", "Katana", "Polygon Zkevm", "Ternoa", "X Layer"],
24652472
chainMapping: {
24662473
"polygon zkevm": "polygon_zkevm",
24672474
"x layer": "xlayer",
@@ -2493,9 +2500,32 @@ export default [
24932500
"solana",
24942501
],
24952502
chainMapping: {
2496-
"avalanche": "avax",
2503+
avalanche: "avax",
24972504
"world chain": "wc",
2498-
"hyperliquid": "hyperliquid",
2505+
hyperliquid: "hyperliquid",
24992506
},
25002507
},
2508+
{
2509+
id: 99,
2510+
displayName: "Mayan",
2511+
bridgeDbName: "mayan",
2512+
slug: "mayan",
2513+
iconLink: "icons:mayana",
2514+
largeTxThreshold: 10000,
2515+
url: "https://swap.mayan.finance/",
2516+
chains: [
2517+
"Solana",
2518+
"Ethereum",
2519+
"Base",
2520+
"Arbitrum",
2521+
"Optimism",
2522+
"Polygon",
2523+
"Avalanche",
2524+
"BSC",
2525+
"Sui",
2526+
"Unichain",
2527+
"Aptos",
2528+
"Linea",
2529+
],
2530+
},
25012531
] as BridgeNetwork[];

0 commit comments

Comments
 (0)