Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 11 additions & 16 deletions src/app/api/fee-compare/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ type GainsApiTrade = {
realizedTradingFeesCollateral?: number;
realizedFundingFeesCollateral?: number;
realizedNewBorrowingFeesCollateral?: number;
realizedOldBorrowingFeesCollateral?: number;
};
};
};
Expand Down Expand Up @@ -180,8 +181,7 @@ type HlWalletData = {

type GainsWalletData = {
events: number;
feesUsdc: number; // pure taker fee only (uiRealizedPnlData)
vaultFeesUsdc: number; // OI imbalance vault surcharge (tradeFeesData - uiRealizedPnlData)
feesUsdc: number;
fundingFeesUsdc: number;
fundingEstimated: boolean;
borrowingFeesUsdc: number;
Expand All @@ -193,8 +193,7 @@ type GainsWalletData = {
pair: string;
action: string;
notional: number;
tradingFee: number; // taker fee only
vaultFee: number; // OI vault surcharge
tradingFee: number;
fundingFee: number;
borrowingFee: number;
equivFee?: number; // equivalent fee on the other venue
Expand Down Expand Up @@ -1525,23 +1524,20 @@ export async function GET(req: Request) {
const otherSlug = slug === venueA ? venueB : venueA;
const otherRate = slug === venueA ? rateB : rateA;
let feesUsdc = 0;
let vaultFeesUsdc = 0;
let fundingFeesUsdc = 0;
let borrowingFeesUsdc = 0;
let notionalUsd = 0;
const recentTrades: GainsWalletData["recentTrades"] = [];

for (const t of usdcTrades) {
// uiRealizedPnlData = pure taker fee; tradeFeesData = taker + OI vault surcharge
// Gains settles carry (funding + borrowing) on every action, not just closes.
// uiRealizedPnlData breaks down taker, funding, and borrowing separately — use it for all.
const takerFee = t.meta?.uiRealizedPnlData?.realizedTradingFeesCollateral
?? t.meta?.tradeFeesData?.realizedTradingFeesCollateral ?? 0;
const totalTradingFee = t.meta?.tradeFeesData?.realizedTradingFeesCollateral ?? takerFee;
const vaultFee = Math.max(0, totalTradingFee - takerFee);
const isClose = CLOSE_ACTIONS.has(t.action);
const fundingFee = isClose ? (t.meta?.uiRealizedPnlData?.realizedFundingFeesCollateral ?? 0) : 0;
const borrowingFee = isClose ? (t.meta?.uiRealizedPnlData?.realizedNewBorrowingFeesCollateral ?? 0) : 0;
const fundingFee = t.meta?.uiRealizedPnlData?.realizedFundingFeesCollateral ?? 0;
const borrowingFee = (t.meta?.uiRealizedPnlData?.realizedNewBorrowingFeesCollateral ?? 0)
+ (t.meta?.uiRealizedPnlData?.realizedOldBorrowingFeesCollateral ?? 0);
feesUsdc += takerFee;
vaultFeesUsdc += vaultFee;
fundingFeesUsdc += fundingFee;
borrowingFeesUsdc += borrowingFee;
const tradeNotional = t.size * t.leverage;
Expand All @@ -1550,7 +1546,7 @@ export async function GET(req: Request) {
const equivFee = otherSlug === "hyperliquid"
? tradeNotional * (gainsData.perSide[t.pair.split("/")[0]] ?? otherRate)
: tradeNotional * otherRate;
recentTrades.push({ date: t.date, pair: t.pair, action: t.action, notional: tradeNotional, tradingFee: takerFee, vaultFee, fundingFee, borrowingFee, equivFee, pnl_net: t.pnl_net });
recentTrades.push({ date: t.date, pair: t.pair, action: t.action, notional: tradeNotional, tradingFee: takerFee, fundingFee, borrowingFee, equivFee, pnl_net: t.pnl_net });
}
}

Expand All @@ -1566,17 +1562,16 @@ export async function GET(req: Request) {
}
}

const netCostUsdc = feesUsdc + vaultFeesUsdc + fundingFeesUsdc + borrowingFeesUsdc;
const netCostUsdc = feesUsdc + fundingFeesUsdc + borrowingFeesUsdc;
walletData = {
events: usdcTrades.length,
feesUsdc,
vaultFeesUsdc,
fundingFeesUsdc,
fundingEstimated,
borrowingFeesUsdc,
netCostUsdc,
positionSizeUsdc: notionalUsd,
avgFeeRateBps: notionalUsd > 0 ? (feesUsdc / notionalUsd) * 10000 : 0,
avgFeeRateBps: notionalUsd > 0 ? (netCostUsdc / notionalUsd) * 10000 : 0,
recentTrades,
} satisfies GainsWalletData;
} else if (fetchEvmWallet && slug === "gmx-v2" && gmxWalletData) {
Expand Down
20 changes: 1 addition & 19 deletions src/components/fee-compare-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ type HlWalletData = {
type GainsWalletData = {
events: number;
feesUsdc: number;
vaultFeesUsdc: number;
fundingFeesUsdc: number;
fundingEstimated: boolean;
borrowingFeesUsdc: number;
Expand All @@ -88,7 +87,6 @@ type GainsWalletData = {
action: string;
notional: number;
tradingFee: number;
vaultFee: number;
fundingFee: number;
borrowingFee: number;
equivFee?: number;
Expand Down Expand Up @@ -735,7 +733,6 @@ function WalletSide({
})()}
{venue.slug === "gains" && (() => {
const gW = w as GainsWalletData;
const hasVault = (gW.vaultFeesUsdc ?? 0) > 0.5;
const hasFunding = Math.abs(gW.fundingFeesUsdc) > 0.5;
const hasBorrowing = gW.borrowingFeesUsdc > 0.5;
return (
Expand All @@ -752,19 +749,6 @@ function WalletSide({
<p className="text-[11px] text-ink-faint">Taker fees</p>
<p className="font-mono text-xs font-semibold text-ink">{fmtUsd(gW.feesUsdc)}</p>
</div>
{hasVault && (
<>
<div className="flex items-center justify-between">
<p className="text-[11px] text-ink-faint">Vault fee</p>
<p className="font-mono text-xs font-semibold text-amber-500">
+{fmtUsd(gW.vaultFeesUsdc)}
</p>
</div>
<p className="text-[10px] text-ink-faint/60 leading-snug">
Gains charges an extra fee to LPs when your trade increases the long/short imbalance. Hyperliquid does not have this — it uses funding rates instead.
</p>
</>
)}
{hasFunding && (
<div className="flex items-center justify-between">
<p className="text-[11px] text-ink-faint">
Expand Down Expand Up @@ -1202,8 +1186,7 @@ function GainsTradeTable({
</thead>
<tbody>
{rows.map((t, i) => {
const hasVault = (t.vaultFee ?? 0) > 0.001;
const netCost = t.tradingFee + (t.vaultFee ?? 0) + t.fundingFee + t.borrowingFee;
const netCost = t.tradingFee + t.fundingFee + t.borrowingFee;
const diff = hasEquiv && t.equivFee !== undefined ? t.equivFee - netCost : undefined;
return (
<tr key={i} className="border-b border-ink/5 last:border-0 hover:bg-ink/2 transition-colors">
Expand All @@ -1225,7 +1208,6 @@ function GainsTradeTable({
<p className="font-mono text-xs font-bold text-ink">{fmtUsd(netCost)}</p>
<p className="text-[10px] text-ink-faint/70 mt-0.5 whitespace-nowrap">
{fmtUsd(t.tradingFee)} taker
{hasVault ? ` +${fmtUsd(t.vaultFee)} vault LP` : ""}
{t.borrowingFee > 0.001 ? ` +${fmtUsd(t.borrowingFee)} borrow` : ""}
{Math.abs(t.fundingFee) > 0.001
? ` ${t.fundingFee > 0 ? "+" : "−"}${fmtUsd(Math.abs(t.fundingFee))} fund`
Expand Down
Loading