fix: seed campaign data when no live vault is reachable
All checks were successful
deploy / deploy (push) Successful in 54s
All checks were successful
deploy / deploy (push) Successful in 54s
The public build sets ACTIVE_CHAIN_ID to Arbitrum Sepolia (421614), which has no deployment and isn't in the prod wagmi config, so useReadContracts never resolved -> Campaigns/Markets/Positions hung on skeletons forever. Add CAMPAIGN_SEED (mirrors script/Deploy.s.sol's launch set) and HAS_LIVE_VAULT. When no vault is reachable, useCampaigns returns the seeded launch set instead of reading on-chain, and the position/balance reads are disabled so they can't hang against an unreachable chain. Live anvil/dev path is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
24fb890971
commit
68baf5704b
3 changed files with 77 additions and 5 deletions
|
|
@ -2,6 +2,8 @@ import { useAccount, useReadContracts } from "wagmi";
|
|||
import { hoodquidityVaultsAbi } from "@/lib/abi/HoodquidityVaults";
|
||||
import {
|
||||
ACTIVE_CHAIN_ID,
|
||||
CAMPAIGN_SEED,
|
||||
HAS_LIVE_VAULT,
|
||||
getActiveDeployment,
|
||||
USD_DECIMALS,
|
||||
type MarketMeta,
|
||||
|
|
@ -30,6 +32,35 @@ export function rewardsRemainingUsd(c: CampaignState, nowSec: number): number {
|
|||
|
||||
const scale = 10 ** USD_DECIMALS;
|
||||
|
||||
/** How far into the launch schedule the seeded campaigns sit: 2d 4h, so a
|
||||
* 14-day campaign reads ~11d 20h remaining, past the 1-day boost window. */
|
||||
const SEED_ELAPSED_SEC = 187_200;
|
||||
|
||||
/** Build a campaign row from the static seed, for the no-live-vault build. */
|
||||
function seedCampaign(meta: MarketMeta, now: number): CampaignState {
|
||||
const s = CAMPAIGN_SEED[meta.campaignId];
|
||||
const start = now - SEED_ELAPSED_SEC;
|
||||
const end = start + s.durationDays * 86_400;
|
||||
const boostWindow = s.boostWindowDays * 86_400;
|
||||
let status: CampaignState["status"] = "active";
|
||||
if (now < start) status = "upcoming";
|
||||
else if (now < start + boostWindow) status = "boost";
|
||||
else if (now >= end) status = "ended";
|
||||
return {
|
||||
meta,
|
||||
tvlUsd: s.tvlUsd,
|
||||
targetDepthUsd: s.targetDepthUsd,
|
||||
rewardBudgetUsd: s.rewardBudgetUsd,
|
||||
start,
|
||||
end,
|
||||
boostWindow,
|
||||
boostBps: s.boostBps,
|
||||
durationDays: s.durationDays,
|
||||
activeLPs: s.activeLPs,
|
||||
status,
|
||||
};
|
||||
}
|
||||
|
||||
export function useCampaigns() {
|
||||
const deployment = getActiveDeployment();
|
||||
|
||||
|
|
@ -41,10 +72,21 @@ export function useCampaigns() {
|
|||
args: [BigInt(m.campaignId)],
|
||||
chainId: ACTIVE_CHAIN_ID,
|
||||
})),
|
||||
query: { refetchInterval: 15_000 },
|
||||
query: { enabled: HAS_LIVE_VAULT, refetchInterval: 15_000 },
|
||||
});
|
||||
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
||||
// Showcase build with no reachable vault: render the seeded launch set.
|
||||
if (!HAS_LIVE_VAULT) {
|
||||
return {
|
||||
campaigns: deployment.markets.map((m) => seedCampaign(m, now)),
|
||||
isLoading: false,
|
||||
error: null,
|
||||
deployment,
|
||||
};
|
||||
}
|
||||
|
||||
const campaigns: CampaignState[] | undefined = data?.map((res, i) => {
|
||||
const meta = deployment.markets[i];
|
||||
const c = res.result as
|
||||
|
|
@ -122,7 +164,7 @@ export function usePositions() {
|
|||
chainId: ACTIVE_CHAIN_ID,
|
||||
} as const,
|
||||
]),
|
||||
query: { enabled: !!address, refetchInterval: 15_000 },
|
||||
query: { enabled: HAS_LIVE_VAULT && !!address, refetchInterval: 15_000 },
|
||||
});
|
||||
|
||||
const positions = deployment.markets.map((meta, i) => {
|
||||
|
|
@ -174,7 +216,7 @@ export function usePosition(campaignId: number) {
|
|||
chainId: ACTIVE_CHAIN_ID,
|
||||
},
|
||||
],
|
||||
query: { enabled: !!address, refetchInterval: 15_000 },
|
||||
query: { enabled: HAS_LIVE_VAULT && !!address, refetchInterval: 15_000 },
|
||||
});
|
||||
|
||||
const raw = data?.[0]?.result as
|
||||
|
|
|
|||
|
|
@ -98,6 +98,36 @@ const DEPLOYMENTS: Record<number, Deployment | null> = {
|
|||
*/
|
||||
export const ACTIVE_CHAIN_ID = import.meta.env.DEV ? 31337 : 421614;
|
||||
|
||||
/**
|
||||
* True only when a real vault contract is reachable on the active chain
|
||||
* (anvil in dev). The public showcase build has no live vault yet, so the
|
||||
* campaign hooks fall back to the seed below instead of hanging on reads.
|
||||
*/
|
||||
export const HAS_LIVE_VAULT = DEPLOYMENTS[ACTIVE_CHAIN_ID] != null;
|
||||
|
||||
export interface CampaignSeed {
|
||||
targetDepthUsd: number;
|
||||
rewardBudgetUsd: number;
|
||||
durationDays: number;
|
||||
boostWindowDays: number;
|
||||
boostBps: number;
|
||||
tvlUsd: number;
|
||||
activeLPs: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed campaign parameters mirroring script/Deploy.s.sol's launch set. Used
|
||||
* when HAS_LIVE_VAULT is false so the showcase renders realistic campaigns
|
||||
* without an on-chain vault. Keyed by campaignId.
|
||||
*/
|
||||
export const CAMPAIGN_SEED: Record<number, CampaignSeed> = {
|
||||
0: { targetDepthUsd: 1_000_000, rewardBudgetUsd: 50_000, durationDays: 14, boostWindowDays: 1, boostBps: 15_000, tvlUsd: 5_000, activeLPs: 1 },
|
||||
1: { targetDepthUsd: 750_000, rewardBudgetUsd: 40_000, durationDays: 14, boostWindowDays: 1, boostBps: 15_000, tvlUsd: 0, activeLPs: 0 },
|
||||
2: { targetDepthUsd: 500_000, rewardBudgetUsd: 25_000, durationDays: 21, boostWindowDays: 1, boostBps: 15_000, tvlUsd: 0, activeLPs: 0 },
|
||||
3: { targetDepthUsd: 2_000_000, rewardBudgetUsd: 60_000, durationDays: 30, boostWindowDays: 1, boostBps: 15_000, tvlUsd: 0, activeLPs: 0 },
|
||||
4: { targetDepthUsd: 400_000, rewardBudgetUsd: 35_000, durationDays: 14, boostWindowDays: 1, boostBps: 15_000, tvlUsd: 0, activeLPs: 0 },
|
||||
};
|
||||
|
||||
export function getActiveDeployment(): Deployment {
|
||||
return DEPLOYMENTS[ACTIVE_CHAIN_ID] ?? local;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
import { useAppKit } from "@reown/appkit/react";
|
||||
import { hoodquidityVaultsAbi } from "@/lib/abi/HoodquidityVaults";
|
||||
import { mockERC20Abi } from "@/lib/abi/MockERC20";
|
||||
import { ACTIVE_CHAIN_ID, getActiveDeployment, USD_DECIMALS } from "@/lib/contracts";
|
||||
import { ACTIVE_CHAIN_ID, HAS_LIVE_VAULT, getActiveDeployment, USD_DECIMALS } from "@/lib/contracts";
|
||||
import { useCampaigns, usePositions, type CampaignState } from "@/hooks/useCampaigns";
|
||||
import { useAllMarketData } from "@/hooks/useMarketData";
|
||||
import { feeApr, rewardApr } from "@/lib/math";
|
||||
|
|
@ -91,7 +91,7 @@ export default function AppBoard() {
|
|||
chainId: ACTIVE_CHAIN_ID,
|
||||
},
|
||||
],
|
||||
query: { enabled: !!address },
|
||||
query: { enabled: HAS_LIVE_VAULT && !!address },
|
||||
});
|
||||
const balance = (walletData?.[0]?.result as bigint | undefined) ?? 0n;
|
||||
const allowance = (walletData?.[1]?.result as bigint | undefined) ?? 0n;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue