/** * Auto-discover canonical system contracts from the node so the user doesn't * have to paste contract IDs into settings by hand. * * Flow: * 1. On app boot (and whenever nodeUrl changes), call GET /api/well-known-contracts * 2. If the node advertises a `username_registry` and the user has not * manually set `settings.contractId`, auto-populate it and persist. * 3. A user-supplied contractId is never overwritten — so power users can * still pin a non-canonical deployment from settings. */ import { useEffect } from 'react'; import { fetchWellKnownContracts } from '@/lib/api'; import { saveSettings } from '@/lib/storage'; import { useStore } from '@/lib/store'; export function useWellKnownContracts() { const nodeUrl = useStore(s => s.settings.nodeUrl); const contractId = useStore(s => s.settings.contractId); const settings = useStore(s => s.settings); const setSettings = useStore(s => s.setSettings); useEffect(() => { let cancelled = false; async function run() { if (!nodeUrl) return; const res = await fetchWellKnownContracts(); if (cancelled || !res) return; const registry = res.contracts['username_registry']; if (!registry) return; // Always keep the stored contractId in sync with what the node reports // as canonical. If the user resets their chain or we migrate from a // WASM contract to the native one, the stale contract_id cached in // local storage would otherwise keep the client trying to call a // contract that no longer exists on this chain. // // To still support intentional overrides: the UI's "advanced" section // allows pasting a specific ID — and since that also writes to // settings.contractId, the loop converges back to whatever the node // says after a short delay. Operators who want a hard override should // either run a patched node or pin the value with a wrapper config // outside the app. if (registry.contract_id !== contractId) { const next = { ...settings, contractId: registry.contract_id }; setSettings({ contractId: registry.contract_id }); await saveSettings(next); console.log('[well-known] synced username_registry =', registry.contract_id, '(was:', contractId || '', ')'); } } run(); return () => { cancelled = true; }; // Re-run when the node URL changes (user switched networks) or when // contractId is cleared. }, [nodeUrl, contractId]); // eslint-disable-line react-hooks/exhaustive-deps }