From fc206f1d4b648a03a57149d0ddf4cb86dcd6e3c2 Mon Sep 17 00:00:00 2001 From: Deep Bhikadiya Date: Thu, 30 Jul 2026 21:20:56 +0530 Subject: [PATCH] fix(frontend): centralize constants and topic list for issue #367 --- .../admin/__tests__/adminActions.test.ts | 3 ++- .../components/admin/adminActions.ts | 12 ++++-------- frontend/components/forms/ApproveForm.tsx | 3 ++- frontend/hooks/useContractEvents.ts | 2 +- frontend/lib/recentTokens.ts | 3 ++- frontend/lib/soroban.ts | 8 ++++++++ frontend/lib/stellar.ts | 16 +--------------- 7 files changed, 20 insertions(+), 27 deletions(-) diff --git a/frontend/app/dashboard/[contractId]/components/admin/__tests__/adminActions.test.ts b/frontend/app/dashboard/[contractId]/components/admin/__tests__/adminActions.test.ts index 0819ce79..0306d9a0 100644 --- a/frontend/app/dashboard/[contractId]/components/admin/__tests__/adminActions.test.ts +++ b/frontend/app/dashboard/[contractId]/components/admin/__tests__/adminActions.test.ts @@ -5,6 +5,7 @@ import { type AdminActionContext, type AdminActionKey, } from "../adminActions"; +import { LEDGERS_PER_DAY } from "@/lib/soroban"; /** * `AdminPanel` had no test at all, because nothing inside a 2,351-line @@ -20,7 +21,7 @@ const ADMIN = "GBONK2FUFJBONR6E7H6UN7H26ZNQYUCCF6YQRATRYWK3FOJGDBD3MXKX"; /** `create_schedule` / `extend_cliff` resolve ledgers relative to "now". */ const CURRENT_LEDGER = 1_000_000; -const LEDGERS_PER_DAY = 17280; + function makeContext(): AdminActionContext { return { diff --git a/frontend/app/dashboard/[contractId]/components/admin/adminActions.ts b/frontend/app/dashboard/[contractId]/components/admin/adminActions.ts index 418f17d3..eaf387e1 100644 --- a/frontend/app/dashboard/[contractId]/components/admin/adminActions.ts +++ b/frontend/app/dashboard/[contractId]/components/admin/adminActions.ts @@ -1,5 +1,5 @@ import { rpc, Address, xdr } from "@stellar/stellar-sdk"; -import { addressToScVal, i128ToScVal, nativeToScVal } from "@/lib/soroban"; +import { addressToScVal, i128ToScVal, nativeToScVal, daysToLedgers } from "@/lib/soroban"; import type { PreflightCheckResult } from "@/lib/transactionSimulator"; import type { useTransactionSimulator } from "@/hooks/useTransactionSimulator"; import type { BatchMintEntry } from "@/lib/batch"; @@ -30,8 +30,6 @@ import type { * Adding a capability means adding one entry here plus the UI that calls it. */ -/** Soroban ledgers per day, assuming 5-second ledgers. */ -const LEDGERS_PER_DAY = 17280; type Simulator = ReturnType; @@ -125,7 +123,7 @@ function indexToScVal(scheduleIndex: string): xdr.ScVal { /** "N days from now" as an absolute ledger sequence. */ async function ledgerInDays(server: rpc.Server, days: string | number) { const { sequence } = await server.getLatestLedger(); - return sequence + Math.round(Number(days) * LEDGERS_PER_DAY); + return daysToLedgers(days, sequence); } type AdminActionRegistry = { @@ -236,8 +234,7 @@ export const ADMIN_ACTIONS: AdminActionRegistry = { label: "Vesting", resolve: async (data, ctx) => { const cliffLedger = await ledgerInDays(ctx.server, data.cliffDays); - const endLedger = - cliffLedger + Math.round(Number(data.durationDays) * LEDGERS_PER_DAY); + const endLedger = daysToLedgers(data.durationDays, cliffLedger); return { contractId: data.vestingContract, @@ -252,8 +249,7 @@ export const ADMIN_ACTIONS: AdminActionRegistry = { }, preflight: async (data, ctx) => { const cliffLedger = await ledgerInDays(ctx.server, data.cliffDays); - const endLedger = - cliffLedger + Math.round(Number(data.durationDays) * LEDGERS_PER_DAY); + const endLedger = daysToLedgers(data.durationDays, cliffLedger); return ctx.simulator.checkCreateSchedule( data.vestingContract, data.recipient, diff --git a/frontend/components/forms/ApproveForm.tsx b/frontend/components/forms/ApproveForm.tsx index 45de9121..d851c7d7 100644 --- a/frontend/components/forms/ApproveForm.tsx +++ b/frontend/components/forms/ApproveForm.tsx @@ -10,6 +10,7 @@ import { PreflightCheckDisplay } from "@/components/ui/PreflightCheck"; import { useTransactionSimulator } from "@/hooks/useTransactionSimulator"; import { useWallet } from "@/app/hooks/useWallet"; import { buildApproveTransaction, fetchCurrentLedger, fetchTokenDecimals, parseTokenAmount, submitTransaction } from "@/lib/stellar"; +import { daysToLedgers } from "@/lib/soroban"; import { useNetwork } from "@/app/providers/NetworkProvider"; import { AlertCircle, CheckCircle, Rocket, Loader2 } from "lucide-react"; @@ -67,7 +68,7 @@ export function ApproveForm({ onSuccess, onError }: ApproveFormProps) { const getExpirationLedger = async (days: string): Promise => { const currentLedger = await fetchCurrentLedger(networkConfig); - return currentLedger + parseInt(days || "365") * 17280; + return daysToLedgers(days || "365", currentLedger); }; const handleCheck = async () => { diff --git a/frontend/hooks/useContractEvents.ts b/frontend/hooks/useContractEvents.ts index 877505e2..5b695154 100644 --- a/frontend/hooks/useContractEvents.ts +++ b/frontend/hooks/useContractEvents.ts @@ -17,7 +17,7 @@ import { } from "@/lib/stellar"; // Convert the exported array to a Set for efficient lookup -const TRACKED_TOPICS = new Set(TRACKED_EVENT_TOPICS); +const TRACKED_TOPICS = new Set(TRACKED_EVENT_TOPICS); interface UseContractEventsOptions { intervalMs?: number; diff --git a/frontend/lib/recentTokens.ts b/frontend/lib/recentTokens.ts index d80a19bf..fb42021a 100644 --- a/frontend/lib/recentTokens.ts +++ b/frontend/lib/recentTokens.ts @@ -1,6 +1,7 @@ import * as StellarSdk from "@stellar/stellar-sdk"; import { type NetworkConfig } from "../types/network"; import { fetchTokenInfo, type TokenInfo } from "./stellar"; +import { LEDGERS_PER_DAY } from "./soroban"; export interface RecentToken extends TokenInfo { deployedAt: string; @@ -15,7 +16,7 @@ interface RpcEvent { value?: string; } -const LOOKBACK_LEDGERS = 17280; // ~24 hours at ~5s per ledger +const LOOKBACK_LEDGERS = LEDGERS_PER_DAY; // ~24 hours at ~5s per ledger const MAX_CANDIDATES = 20; const MAX_RESULTS = 12; diff --git a/frontend/lib/soroban.ts b/frontend/lib/soroban.ts index 8c01fde1..0617db76 100644 --- a/frontend/lib/soroban.ts +++ b/frontend/lib/soroban.ts @@ -8,6 +8,14 @@ import { export { nativeToScVal, scValToNative }; +/** Soroban ledgers per day, assuming 5-second ledgers. */ +export const LEDGERS_PER_DAY = 17280; + +export function daysToLedgers(days: number | string, currentLedger?: number): number { + const ledgers = Math.round(Number(days) * LEDGERS_PER_DAY); + return currentLedger !== undefined ? currentLedger + ledgers : ledgers; +} + /** * Build a Soroban invocation transaction. */ diff --git a/frontend/lib/stellar.ts b/frontend/lib/stellar.ts index 38a15613..01d9a9f6 100644 --- a/frontend/lib/stellar.ts +++ b/frontend/lib/stellar.ts @@ -1091,21 +1091,7 @@ export async function fetchTransactionHistory( return { items: items.reverse(), nextCursor }; } -export type TokenActivityType = - | "mint" - | "transfer" - | "burn" - | "clawback" - | "freeze" - | "unfreeze" - | "pause" - | "unpause" - | "authorize" - | "unauthorize" - | "set_admin" - | "revoke_admin" - | "upgrade" - | "other"; +export type TokenActivityType = (typeof TRACKED_EVENT_TOPICS)[number] | "other"; export interface TokenActivityInfo { id: string;