Skip to content

Commit 4bd8b95

Browse files
committed
set up logic for NERI calc
1 parent 70b189b commit 4bd8b95

3 files changed

Lines changed: 82 additions & 3 deletions

File tree

frontend/app/src/contracts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ export const CONTRACT_ADDRESSES = {
163163
WETH: CONTRACT_WETH,
164164
YUSND: CONTRACT_YUSND,
165165
ShellToken: CONTRACT_SHELL_TOKEN,
166+
NeriToken: "0x0000000000000000000000000000000000000000", // TODO: Replace with actual NERI token address
166167
GoSlowNft: "0x6da3c02293c96dfa5747b1739ebb492619222a8a",
167168

168169
strategies: {

frontend/app/src/screens/ClaimScreen/ClaimScreen.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { a, useSpring, useTrail } from "@react-spring/web";
88
import { Button, VFlex, ShellpointIcon, TokenIcon } from "@liquity2/uikit";
99
import { useState, useMemo, useEffect } from "react";
1010
import { useBalance } from "@/src/wagmi-utils";
11-
import { useShellActivitiesOfHolders, useWeightedActivitySnapshots, usePrivacyPoolSnapshots } from "@/src/shell-hooks";
11+
import { useShellActivitiesOfHolders, useWeightedActivitySnapshots, usePrivacyPoolSnapshots, useTotalShells, useNeriTotalSupply, calculateNeriAllocation } from "@/src/shell-hooks";
1212
import { CONTRACT_ADDRESSES } from "@/src/contracts";
1313
import { getAddress, isAddress, isAddressEqual } from "viem";
1414
import { getEnsAddress, normalize } from "viem/ens";
@@ -149,6 +149,19 @@ export function ClaimScreen() {
149149
// Fetch privacy pool snapshots (GoSlow NFT)
150150
const { data: privacyPoolSnapshots } = usePrivacyPoolSnapshots(lookupAddress);
151151

152+
// Fetch total shells for NERI calculation
153+
const { data: totalShells } = useTotalShells();
154+
155+
// Fetch NERI total supply from contract
156+
const { data: neriTotalSupply } = useNeriTotalSupply();
157+
158+
// Calculate NERI allocation based on user's shell balance, total shells, and NERI supply
159+
const neriAllocation = useMemo(() => {
160+
if (!shellBalance || !totalShells || totalShells === 0n || !neriTotalSupply) return 0n;
161+
const userShells = shellBalance[0];
162+
return calculateNeriAllocation(userShells, totalShells, neriTotalSupply);
163+
}, [shellBalance, totalShells, neriTotalSupply]);
164+
152165
// Get aggregated stats from weighted snapshots
153166
const activityStats = useMemo(() => {
154167
if (!weightedSnapshots || weightedSnapshots.length === 0) return null;
@@ -241,10 +254,10 @@ export function ClaimScreen() {
241254
config: { mass: 1, tension: 80, friction: 30 },
242255
});
243256

244-
// NERI amount animation (proportional to shells - placeholder conversion)
257+
// NERI amount animation
245258
const neriAmountSpring = useSpring({
246259
from: { number: 0 },
247-
to: { number: revealed && shellBalance ? Number(format(shellBalance, 0).replace(/,/g, '')) * 0.1 : 0 },
260+
to: { number: revealed && neriAllocation ? Number(neriAllocation / 10n ** 18n) : 0 },
248261
delay: revealed ? 400 : 0,
249262
config: { mass: 1, tension: 80, friction: 30 },
250263
});

frontend/app/src/shell-hooks.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ import { UniswapV4PositionManager } from "./abi/UniswapV4PositionManager";
1717
import { Abi } from "abitype";
1818
import { isAddressEqual, zeroAddress } from "viem";
1919

20+
21+
// NERI Airdrop Configuration
22+
export const NERI_CONFIG = {
23+
SHELL_ALLOCATION_PERCENT: 10,
24+
};
25+
2026
type Options = {
2127
refetchInterval?: number;
2228
};
@@ -196,4 +202,63 @@ export function usePrivacyPoolSnapshots(
196202
enabled: Boolean(user),
197203
...prepareOptions(options),
198204
});
205+
}
206+
207+
// Get total shells across all holders
208+
export function useTotalShells(options?: Options) {
209+
const { data: allBalances, ...rest } = useShellBalances(options);
210+
211+
const totalShells = allBalances?.reduce((sum, balance) => {
212+
return sum + BigInt(balance.balance);
213+
}, 0n) ?? 0n;
214+
215+
return {
216+
data: totalShells,
217+
...rest,
218+
};
219+
}
220+
221+
// Hook to get NERI total supply from contract
222+
export function useNeriTotalSupply(options?: Options) {
223+
const config = useWagmiConfig();
224+
225+
return useQuery({
226+
queryKey: ["NeriTotalSupply"],
227+
queryFn: async () => {
228+
const result = await readContracts(config, {
229+
allowFailure: false,
230+
contracts: [{
231+
address: CONTRACT_ADDRESSES.NeriToken as `0x${string}`,
232+
abi: [{
233+
name: "totalSupply",
234+
type: "function",
235+
stateMutability: "view",
236+
inputs: [],
237+
outputs: [{ type: "uint256" }],
238+
}] as const,
239+
functionName: "totalSupply",
240+
args: [],
241+
}],
242+
});
243+
return result[0] as bigint;
244+
},
245+
// Don't fetch if NERI token address is not set (zero address)
246+
enabled: CONTRACT_ADDRESSES.NeriToken !== "0x0000000000000000000000000000000000000000",
247+
...prepareOptions(options),
248+
});
249+
}
250+
251+
// Calculate NERI amount for a given shell balance
252+
export function calculateNeriAllocation(
253+
userShells: bigint,
254+
totalShells: bigint,
255+
neriTotalSupply: bigint
256+
): bigint {
257+
if (totalShells === 0n || neriTotalSupply === 0n) return 0n;
258+
259+
// NERI allocated to shell holders = neriTotalSupply * SHELL_ALLOCATION_PERCENT / 100
260+
const neriForShells = neriTotalSupply * BigInt(NERI_CONFIG.SHELL_ALLOCATION_PERCENT) / 100n;
261+
262+
// User's NERI = (userShells / totalShells) * neriForShells
263+
return (userShells * neriForShells) / totalShells;
199264
}

0 commit comments

Comments
 (0)