Skip to content

Commit 9ac434b

Browse files
Merge pull request #15 from StabilityNexus/Frontend
Added proper balance and weight token address.
2 parents 04f1f73 + 3784c43 commit 9ac434b

1 file changed

Lines changed: 122 additions & 35 deletions

File tree

app/[oracleId]/InteractionClient.tsx

Lines changed: 122 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
CheckCircle,
2929
} from "lucide-react"
3030
import { useAccount, useWriteContract, useReadContract, useWaitForTransactionReceipt } from "wagmi"
31-
import { parseEther, formatEther, formatUnits, erc20Abi } from "viem"
31+
import { parseUnits, formatUnits, erc20Abi } from "viem"
3232

3333
function isHexAddress(value: string | null): value is `0x${string}` {
3434
return !!value && /^0x[a-fA-F0-9]{40}$/.test(value)
@@ -152,6 +152,20 @@ export default function OracleInteractionPage() {
152152
query: { enabled: !!oracleAddress }
153153
})
154154

155+
const { data: weightTokenSymbolData } = useReadContract({
156+
address: (weightTokenAddress as `0x${string}`) || undefined,
157+
abi: erc20Abi,
158+
functionName: 'symbol',
159+
query: { enabled: !!weightTokenAddress }
160+
})
161+
162+
const { data: weightTokenDecimalsData } = useReadContract({
163+
address: (weightTokenAddress as `0x${string}`) || undefined,
164+
abi: erc20Abi,
165+
functionName: 'decimals',
166+
query: { enabled: !!weightTokenAddress }
167+
})
168+
155169
// Read user's locked tokens (for governance operations)
156170
const { data: lockedTokensData } = useReadContract({
157171
address: oracleAddress || undefined,
@@ -305,20 +319,56 @@ export default function OracleInteractionPage() {
305319
query: { enabled: !!weightTokenAddress && !!userAddress && !!oracleAddress }
306320
})
307321

322+
const weightTokenSymbol = useMemo(() => (weightTokenSymbolData ? String(weightTokenSymbolData) : "WEIGHT"), [weightTokenSymbolData])
323+
const weightTokenDecimals = useMemo(() => {
324+
if (weightTokenDecimalsData === undefined || weightTokenDecimalsData === null) {
325+
return 18
326+
}
327+
const value = Number(weightTokenDecimalsData)
328+
return Number.isFinite(value) ? value : 18
329+
}, [weightTokenDecimalsData])
330+
const weightTokenAddressString = useMemo(() => (weightTokenAddress ? String(weightTokenAddress) : "—"), [weightTokenAddress])
331+
const canCopyWeightTokenAddress = useMemo(
332+
() => weightTokenAddressString.startsWith("0x") && weightTokenAddressString.length === 42,
333+
[weightTokenAddressString]
334+
)
335+
const formatTokenAmount = useCallback(
336+
(value?: bigint | null, fractionDigits = 2) => {
337+
try {
338+
const normalized = formatUnits(value ?? BigInt(0), weightTokenDecimals)
339+
const numeric = Number.parseFloat(normalized)
340+
if (!Number.isFinite(numeric)) {
341+
return "0.00"
342+
}
343+
return numeric.toFixed(fractionDigits)
344+
} catch {
345+
return "0.00"
346+
}
347+
},
348+
[weightTokenDecimals]
349+
)
350+
const walletTokenBalanceDisplay = useMemo(
351+
() => {
352+
const numeric = Number.parseFloat(userTokenBalance || "0")
353+
return Number.isFinite(numeric) ? numeric.toFixed(2) : "0.00"
354+
},
355+
[userTokenBalance]
356+
)
357+
308358
// Update real-time data when contract data changes
309359
useEffect(() => {
310360
// Calculate total deposited tokens (sum of locked and unlocked tokens)
311361
if (lockedTokensData !== undefined || unlockedTokensData !== undefined) {
312362
const locked = lockedTokensData ? BigInt(lockedTokensData as bigint) : BigInt(0)
313363
const unlocked = unlockedTokensData ? BigInt(unlockedTokensData as bigint) : BigInt(0)
314364
const total = locked + unlocked
315-
setUserDepositedTokens(formatEther(total))
365+
setUserDepositedTokens(formatTokenAmount(total, 4))
316366
}
317-
if (userTokenBalanceData) {
318-
setUserTokenBalance(formatEther(userTokenBalanceData as bigint))
367+
if (userTokenBalanceData !== undefined) {
368+
setUserTokenBalance(formatTokenAmount(userTokenBalanceData as bigint, 4))
319369
}
320-
if (tokenAllowanceData) {
321-
setTokenAllowance(formatEther(tokenAllowanceData as bigint))
370+
if (tokenAllowanceData !== undefined) {
371+
setTokenAllowance(formatTokenAmount(tokenAllowanceData as bigint, 4))
322372
}
323373
if (lastSubmissionTimeData) {
324374
const timestamp = Number(lastSubmissionTimeData as bigint)
@@ -379,7 +429,7 @@ export default function OracleInteractionPage() {
379429
}
380430
}
381431

382-
}, [lockedTokensData, unlockedTokensData, userTokenBalanceData, tokenAllowanceData, lastSubmissionTimeData, rewardData, halfLifeSecondsData, quorumData, operationLockingPeriodData, withdrawalLockingPeriodData, alphaData, depositTimestampData, lastOperationTimestampData])
432+
}, [lockedTokensData, unlockedTokensData, userTokenBalanceData, tokenAllowanceData, formatTokenAmount, weightTokenDecimals, lastSubmissionTimeData, rewardData, halfLifeSecondsData, quorumData, operationLockingPeriodData, withdrawalLockingPeriodData, alphaData, depositTimestampData, lastOperationTimestampData])
383433

384434
// Early validation before calling the hook
385435
if (!oracleAddress || !chainIdValid) {
@@ -568,7 +618,7 @@ export default function OracleInteractionPage() {
568618

569619
try {
570620
setIsApproving(true)
571-
const amount = parseEther(depositAmount)
621+
const amount = parseUnits(depositAmount, weightTokenDecimals)
572622

573623
writeContract({
574624
address: weightTokenAddress as `0x${string}`,
@@ -611,8 +661,8 @@ export default function OracleInteractionPage() {
611661
return
612662
}
613663

614-
const amount = parseEther(depositAmount)
615-
const allowance = parseEther(tokenAllowance)
664+
const amount = parseUnits(depositAmount, weightTokenDecimals)
665+
const allowance = tokenAllowanceData ? BigInt(tokenAllowanceData as bigint) : BigInt(0)
616666

617667
if (allowance < amount) {
618668
toast({
@@ -669,7 +719,7 @@ export default function OracleInteractionPage() {
669719

670720
try {
671721
setIsWithdrawing(true)
672-
const amount = parseEther(withdrawAmount)
722+
const amount = parseUnits(withdrawAmount, weightTokenDecimals)
673723

674724
console.log('Withdrawing tokens:', {
675725
amount: amount.toString(),
@@ -984,18 +1034,45 @@ export default function OracleInteractionPage() {
9841034
<p className="text-lg text-muted-foreground mb-6 max-w-3xl mx-auto font-light">{oracle.description}</p>
9851035
)}
9861036

987-
{/* Oracle Address */}
988-
<div className="flex items-center gap-2 justify-center mb-8">
989-
<code className="text-sm bg-card/50 border border-primary/30 px-4 py-2 rounded-xl text-primary font-mono">
990-
{oracle.address}
991-
</code>
992-
<button
993-
onClick={() => navigator.clipboard.writeText(oracle.address)}
994-
className="text-muted-foreground hover:text-primary transition-colors p-2 hover:bg-card/50 rounded-lg border border-transparent hover:border-primary/30"
995-
title="Copy address"
996-
>
997-
<Copy className="h-4 w-4" />
998-
</button>
1037+
{/* Addresses */}
1038+
<div className="grid gap-4 md:grid-cols-2 mb-8">
1039+
<div className="bg-card/40 border border-primary/25 rounded-xl p-4 text-left">
1040+
<div className="text-xs uppercase tracking-wide text-muted-foreground/70 mb-2">Oracle Address</div>
1041+
<div className="flex items-center justify-between gap-3">
1042+
<code className="flex-1 text-xs sm:text-sm bg-card/60 border border-primary/30 px-3 py-2 rounded-lg text-primary font-mono break-all">
1043+
{oracle.address}
1044+
</code>
1045+
<button
1046+
onClick={() => navigator.clipboard.writeText(oracle.address)}
1047+
className="text-muted-foreground hover:text-primary transition-colors p-2 hover:bg-card/50 rounded-lg border border-transparent hover:border-primary/30"
1048+
title="Copy oracle address"
1049+
>
1050+
<Copy className="h-4 w-4" />
1051+
</button>
1052+
</div>
1053+
</div>
1054+
1055+
<div className="bg-card/40 border border-primary/25 rounded-xl p-4 text-left">
1056+
<div className="flex items-center justify-between mb-2">
1057+
<div className="text-xs uppercase tracking-wide text-muted-foreground/70">Weight Token</div>
1058+
<span className="text-xs font-medium text-primary/80">{weightTokenSymbol}</span>
1059+
</div>
1060+
<div className="flex items-center justify-between gap-3">
1061+
<code className="flex-1 text-xs sm:text-sm bg-card/60 border border-primary/30 px-3 py-2 rounded-lg text-primary font-mono break-all">
1062+
{weightTokenAddressString}
1063+
</code>
1064+
<button
1065+
onClick={() =>
1066+
canCopyWeightTokenAddress && navigator.clipboard.writeText(weightTokenAddressString)
1067+
}
1068+
disabled={!canCopyWeightTokenAddress}
1069+
className="text-muted-foreground hover:text-primary transition-colors p-2 hover:bg-card/50 rounded-lg border border-transparent hover:border-primary/30 disabled:opacity-40 disabled:cursor-not-allowed"
1070+
title="Copy weight token address"
1071+
>
1072+
<Copy className="h-4 w-4" />
1073+
</button>
1074+
</div>
1075+
</div>
9991076
</div>
10001077
</div>
10011078

@@ -1124,17 +1201,25 @@ export default function OracleInteractionPage() {
11241201
<div className="space-y-3 mb-4">
11251202

11261203
{/* Detailed Token State Breakdown */}
1127-
<div className="grid grid-cols-2 gap-2 p-2 bg-card/30 border border-primary/20 rounded-lg text-xs">
1128-
<div className="text-center">
1129-
<div className="text-muted-foreground/80 mb-0.5">🔒 Locked</div>
1130-
<div className="text-foreground/90 font-light">{lockedTokensData ? parseFloat(formatEther(lockedTokensData as bigint)).toFixed(2) : '0.00'}</div>
1131-
</div>
1132-
<div className="text-center">
1133-
<div className="text-muted-foreground/80 mb-0.5">📅 Deposit Time</div>
1134-
<div className="text-foreground/90 font-light text-xs">{depositTimestamp}</div>
1135-
</div>
1204+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2 p-2 bg-card/30 border border-primary/20 rounded-lg text-xs">
1205+
<div className="text-center">
1206+
<div className="text-muted-foreground/80 mb-0.5">🔒 Locked</div>
1207+
<div className="text-foreground/90 font-light">
1208+
{formatTokenAmount(lockedTokensData ? (lockedTokensData as bigint) : undefined)} {weightTokenSymbol}
11361209
</div>
11371210
</div>
1211+
<div className="text-center">
1212+
<div className="text-muted-foreground/80 mb-0.5">📅 Deposit Time</div>
1213+
<div className="text-foreground/90 font-light text-xs">{depositTimestamp}</div>
1214+
</div>
1215+
<div className="text-center">
1216+
<div className="text-muted-foreground/80 mb-0.5">💼 Wallet Balance</div>
1217+
<div className="text-foreground/90 font-light">
1218+
{walletTokenBalanceDisplay} {weightTokenSymbol}
1219+
</div>
1220+
</div>
1221+
</div>
1222+
</div>
11381223
)}
11391224

11401225
<div className="space-y-2">
@@ -1151,8 +1236,8 @@ export default function OracleInteractionPage() {
11511236

11521237
{/* Conditional Buttons based on allowance */}
11531238
{(() => {
1154-
const amount = depositAmount ? parseEther(depositAmount) : BigInt(0)
1155-
const allowance = tokenAllowance ? parseEther(tokenAllowance) : BigInt(0)
1239+
const amount = depositAmount ? parseUnits(depositAmount, weightTokenDecimals) : BigInt(0)
1240+
const allowance = tokenAllowanceData ? BigInt(tokenAllowanceData as bigint) : BigInt(0)
11561241
const needsApproval = amount > allowance
11571242

11581243
if (needsApproval) {
@@ -1203,7 +1288,9 @@ export default function OracleInteractionPage() {
12031288
</div>
12041289
<div className="text-center">
12051290
<div className="text-muted-foreground/80 mb-0.5">✓ Unlocked</div>
1206-
<div className="text-foreground/90 font-light">{unlockedTokensData ? parseFloat(formatEther(unlockedTokensData as bigint)).toFixed(2) : '0.00'}</div>
1291+
<div className="text-foreground/90 font-light">
1292+
{formatTokenAmount(unlockedTokensData ? (unlockedTokensData as bigint) : undefined)} {weightTokenSymbol}
1293+
</div>
12071294
</div>
12081295
</div>
12091296
)}

0 commit comments

Comments
 (0)