Skip to content

Commit 115ca33

Browse files
Feat(moon enable cronos chain) (#4203)
* feat: enable cronos chain * feat: enable cronos chain on chains config * feat: adding open interest * feat: adding fees daily api and data fetching * refactor * version 2 * Fees adapter * chore: refactor with multi chain config adapter * feat: adding fetching volume with exclude feature --------- Co-authored-by: treeoflife2 <[email protected]>
1 parent 2fb6e64 commit 115ca33

File tree

2 files changed

+133
-23
lines changed

2 files changed

+133
-23
lines changed

dexs/moonlander/index.ts

Lines changed: 131 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,153 @@
1-
import { httpGet, } from "../../utils/fetchURL";
2-
import { FetchOptions } from "../../adapters/types";
1+
import { httpGet, httpPost } from "../../utils/fetchURL";
2+
import { FetchOptions, SimpleAdapter } from "../../adapters/types";
33
import { CHAIN } from "../../helpers/chains";
44

5-
const dailyEndpoint = "https://api.moonlander.trade/v1/trading-volumes/sum-by-date";
5+
const CONFIG = {
6+
[CHAIN.CRONOS]: {
7+
chainName: "CRONOS",
8+
start: "2025-04-29",
9+
address: "0xE6F6351fb66f3a35313fEEFF9116698665FBEeC9",
10+
excludeFilters: [
11+
{
12+
pairBase: "0xbad4ccc91ef0dfffbcab1402c519601fbaf244ef", // 500BTC pair address
13+
excludeStartTime: "2025-07-08T09:00:00.000Z", // Jul 8 5:00pm HKT
14+
excludeEndTime: "2025-07-29T09:00:00.000Z", // Jul 29 5:00pm HKT
15+
},
16+
],
17+
},
18+
[CHAIN.CRONOS_ZKEVM]: {
19+
chainName: "CRONOS_ZKEVM",
20+
start: "2024-12-17",
21+
address: "0x02ae2e56bfDF1ee4667405eE7e959CD3fE717A05",
22+
excludeFilters: [], // No need to remove zkEVM's
23+
},
24+
};
25+
26+
const pairsAbi =
27+
"function pairsV4() view returns ((string name, address base, uint16 basePosition, uint8 pairType, uint8 status, uint256 maxLongOiUsd, uint256 maxShortOiUsd, uint256 fundingFeePerSecondP, uint256 minFundingFeeR, uint256 maxFundingFeeR, (uint256 notionalUsd, uint16 tier, uint16 maxLeverage, uint16 initialLostP, uint16 liqLostP)[] leverageMargins, uint16 slippageConfigIndex, uint16 slippagePosition, (string name, uint256 onePercentDepthAboveUsd, uint256 onePercentDepthBelowUsd, uint16 slippageLongP, uint16 slippageShortP, uint16 index, uint8 slippageType, bool enable, uint256 longThresholdUsd, uint256 shortThresholdUsd) slippageConfig, uint16 feeConfigIndex, uint16 feePosition, (string name, uint16 index, uint16 openFeeP, uint16 closeFeeP, bool enable, uint24 shareP, uint24 minCloseFeeP) feeConfig, uint40 longHoldingFeeRate, uint40 shortHoldingFeeRate)[])";
28+
const marketInfoAbi =
29+
"function getMarketInfos(address[] pairBases) view returns ((address pairBase, uint256 longQty, uint256 shortQty, uint128 lpLongAvgPrice, uint128 lpShortAvgPrice, int256 fundingFeeRate)[])";
30+
const priceAbi = "function getPrice(address token) view returns (uint256)";
631

7-
const chains: { [key: string]: string } = {
8-
// [CHAIN.CRONOS]: "CRONOS",
9-
[CHAIN.CRONOS_ZKEVM]: "CRONOS_ZKEVM",
32+
const BASE_API_URL = "https://api.moonlander.trade/v1/defillama";
33+
const VOLUME_ENDPOINT = `${BASE_API_URL}/volume`;
34+
const FEES_ENDPOINT = `${BASE_API_URL}/fee`;
35+
36+
const getDailyVolumeData = async ({ chain, startTime, endTime }: any) => {
37+
const requestBody = {
38+
chains: [CONFIG[chain].chainName],
39+
startTime: startTime.toISOString(),
40+
endTime: endTime.toISOString(),
41+
exclusionFilters: CONFIG[chain].excludeFilters,
42+
};
43+
44+
return await httpPost(VOLUME_ENDPOINT, requestBody);
1045
};
1146

12-
const getDailyUri = ({ chain, startTime, endTime, }: any) => {
13-
return `${dailyEndpoint}?chains=${chains[chain]}&startTime=${startTime.toISOString()}&endTime=${endTime.toISOString()}`;
47+
const getFeesUri = ({ chain, startTime, endTime }: any) => {
48+
return `${FEES_ENDPOINT}?block_chain=${
49+
CONFIG[chain].chainName
50+
}&startDate=${startTime.toISOString()}&endDate=${endTime.toISOString()}`;
1451
};
1552

16-
interface APIResponse {
53+
const getOpenInterest = async ({
54+
chain,
55+
api,
56+
}: Pick<FetchOptions, "chain" | "api">) => {
57+
const pairs = await api.call({
58+
target: CONFIG[chain].address,
59+
abi: pairsAbi,
60+
});
61+
const pairBases = pairs.map((pair: any) => pair.base);
62+
63+
const pairsMarketInfo = await api.call({
64+
target: CONFIG[chain].address,
65+
abi: marketInfoAbi,
66+
params: [pairBases],
67+
});
68+
69+
const pairPrices = await api.multiCall({
70+
abi: priceAbi,
71+
calls: pairs.map((pair: any) => ({
72+
target: CONFIG[chain].address,
73+
params: pair.base,
74+
})),
75+
permitFailure: true,
76+
});
77+
78+
let totalLongOIUsd = 0,
79+
totalShortOIUsd = 0;
80+
81+
pairPrices.forEach((pairPrice, index) => {
82+
const longOI = pairsMarketInfo[index].longQty / 1e10; // qty is 10 decimals
83+
const shortOI = pairsMarketInfo[index].shortQty / 1e10; // qty is 10 decimals
84+
85+
const longOIUsd = longOI * (pairPrice / 1e18); // convert to USD, price is 18 decimals
86+
const shortOIUsd = shortOI * (pairPrice / 1e18); // convert to USD, price is 18 decimals
87+
88+
totalLongOIUsd += longOIUsd;
89+
totalShortOIUsd += shortOIUsd;
90+
});
91+
92+
return {
93+
longOpenInterestAtEnd: totalLongOIUsd,
94+
shortOpenInterestAtEnd: totalShortOIUsd,
95+
openInterestAtEnd: totalLongOIUsd + totalShortOIUsd,
96+
};
97+
};
98+
99+
interface DailyDateAPIResponse {
17100
vol: string;
18101
usdVol: string;
19102
}
20103

21-
async function fetch({ startTimestamp, endTimestamp, chain }: FetchOptions) {
22-
const dailyData: APIResponse = await httpGet(getDailyUri({
104+
interface FeesAPIResponse {
105+
dailyFeeAmountUsd: number;
106+
}
107+
108+
async function fetch({
109+
startTimestamp,
110+
endTimestamp,
111+
chain,
112+
api,
113+
}: FetchOptions) {
114+
const dailyData: DailyDateAPIResponse = await getDailyVolumeData({
23115
chain,
24116
startTime: new Date(startTimestamp * 1000),
25117
endTime: new Date(endTimestamp * 1000),
26-
}));
118+
});
119+
120+
const dailyFeesData: FeesAPIResponse = await httpGet(
121+
getFeesUri({
122+
chain,
123+
startTime: new Date(startTimestamp * 1000),
124+
endTime: new Date(endTimestamp * 1000),
125+
})
126+
);
127+
128+
const { shortOpenInterestAtEnd, longOpenInterestAtEnd, openInterestAtEnd } =
129+
await getOpenInterest({ chain, api });
27130

28131
return {
29132
dailyVolume: dailyData.usdVol,
133+
shortOpenInterestAtEnd,
134+
longOpenInterestAtEnd,
135+
openInterestAtEnd,
136+
dailyFees: dailyFeesData.dailyFeeAmountUsd,
30137
};
31138
}
32139

33-
const startTimestamps: { [chain: string]: string } = {
34-
// [CHAIN.CRONOS]: '2025-04-29',
35-
[CHAIN.CRONOS_ZKEVM]: '2024-12-17',
36-
};
37-
const adapter: any = {}
38-
39-
Object.keys(chains).forEach((chain) => adapter[chain] = { fetch, start: startTimestamps[chain], })
40-
41-
export default {
42-
adapter,
140+
const adapter: SimpleAdapter = {
43141
version: 2,
44-
}
142+
adapter: Object.fromEntries(
143+
Object.entries(CONFIG).map(([chain, config]) => [
144+
chain,
145+
{
146+
fetch: (options: FetchOptions) => fetch({ ...options, chain }),
147+
start: config.start,
148+
},
149+
])
150+
),
151+
};
45152

153+
export default adapter;

fees/moonlander/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import adapter from "../../dexs/moonlander";
2+
export default adapter;

0 commit comments

Comments
 (0)