Dapp: exact-position deep link route and single-position view; consume localStorage deeplink with ARB alias
This commit is contained in:
@@ -49,6 +49,7 @@ export default function DappPage() {
|
|||||||
const [presetKey, setPresetKey] = useState<string>('cbBTC-USDC');
|
const [presetKey, setPresetKey] = useState<string>('cbBTC-USDC');
|
||||||
const [manualWallet, setManualWallet] = useState<string>('');
|
const [manualWallet, setManualWallet] = useState<string>('');
|
||||||
const [manualTokenId, setManualTokenId] = useState('');
|
const [manualTokenId, setManualTokenId] = useState('');
|
||||||
|
const [deeplinkTokenId, setDeeplinkTokenId] = useState('');
|
||||||
const [detectedTokenIds, setDetectedTokenIds] = useState<bigint[]>([]);
|
const [detectedTokenIds, setDetectedTokenIds] = useState<bigint[]>([]);
|
||||||
const [scanBusy, setScanBusy] = useState(false);
|
const [scanBusy, setScanBusy] = useState(false);
|
||||||
const [scanComplete, setScanComplete] = useState(false);
|
const [scanComplete, setScanComplete] = useState(false);
|
||||||
@@ -271,6 +272,32 @@ export default function DappPage() {
|
|||||||
loadChainDefaults(selectedChainId);
|
loadChainDefaults(selectedChainId);
|
||||||
}, [selectedChainId]);
|
}, [selectedChainId]);
|
||||||
|
|
||||||
|
// Consume deep-link payload from /dapp/position/[network]/[preset]/[tokenId]
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
if (typeof window === 'undefined') return;
|
||||||
|
const raw = localStorage.getItem('dapp:deeplink:v1');
|
||||||
|
if (!raw) return;
|
||||||
|
localStorage.removeItem('dapp:deeplink:v1');
|
||||||
|
const parsed = JSON.parse(raw || '{}') as { network?: string; preset?: number; tokenId?: string; ts?: number };
|
||||||
|
const age = Math.floor(Date.now() / 1000) - (parsed.ts || 0);
|
||||||
|
if (age > 600) return; // ignore stale links >10min
|
||||||
|
const net = String(parsed.network || '').toUpperCase();
|
||||||
|
const presetIdx = Math.max(1, Number(parsed.preset || 1));
|
||||||
|
const nextChainId = net === 'BASE' ? base.id : ((net === 'ARBITRUM' || net === 'ARB') ? arbitrum.id : selectedChainId);
|
||||||
|
if (nextChainId !== selectedChainId) {
|
||||||
|
setSelectedChainId(nextChainId);
|
||||||
|
loadChainDefaults(nextChainId);
|
||||||
|
}
|
||||||
|
const list = PRESETS[nextChainId] || [];
|
||||||
|
const item = list[presetIdx - 1];
|
||||||
|
if (item?.key) setPresetKey(item.key);
|
||||||
|
// Force single-position view for deep link
|
||||||
|
if (parsed.tokenId) setDeeplinkTokenId(String(parsed.tokenId));
|
||||||
|
} catch {}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Detect ERC721Enumerable support: interfaceId 0x780e9d63
|
// Detect ERC721Enumerable support: interfaceId 0x780e9d63
|
||||||
const { data: supportsEnumerable } = useReadContract({
|
const { data: supportsEnumerable } = useReadContract({
|
||||||
abi: erc721Abi,
|
abi: erc721Abi,
|
||||||
@@ -320,9 +347,12 @@ export default function DappPage() {
|
|||||||
|
|
||||||
// Resolve tokenIds: either detected or manual entry
|
// Resolve tokenIds: either detected or manual entry
|
||||||
const tokenIds = useMemo(() => {
|
const tokenIds = useMemo(() => {
|
||||||
|
if (deeplinkTokenId.trim()) {
|
||||||
|
try { return [BigInt(deeplinkTokenId.trim())]; } catch { return []; }
|
||||||
|
}
|
||||||
const manual = manualTokenId.trim() ? [BigInt(manualTokenId.trim())] : [];
|
const manual = manualTokenId.trim() ? [BigInt(manualTokenId.trim())] : [];
|
||||||
return [...detectedTokenIds, ...manual];
|
return [...detectedTokenIds, ...manual];
|
||||||
}, [detectedTokenIds, manualTokenId]);
|
}, [detectedTokenIds, manualTokenId, deeplinkTokenId]);
|
||||||
|
|
||||||
// Build reads for debt contract
|
// Build reads for debt contract
|
||||||
const debtReads = useMemo(() => {
|
const debtReads = useMemo(() => {
|
||||||
|
|||||||
26
app/dapp/position/[network]/[preset]/[tokenId]/page.tsx
Normal file
26
app/dapp/position/[network]/[preset]/[tokenId]/page.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import DappPage from "../../../../page";
|
||||||
|
|
||||||
|
export default function PositionDeepLinkPage() {
|
||||||
|
const params = useParams<{ network: string; preset: string; tokenId: string }>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
const network = String(params?.network || '').toUpperCase();
|
||||||
|
const preset = Number(params?.preset || '1');
|
||||||
|
const tokenId = String(params?.tokenId || '');
|
||||||
|
if (!network || !preset || !tokenId) return;
|
||||||
|
// Persist for Dapp page to consume on mount; keep URL unchanged
|
||||||
|
const payload = { network, preset, tokenId, ts: Math.floor(Date.now() / 1000) };
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
localStorage.setItem('dapp:deeplink:v1', JSON.stringify(payload));
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}, [params]);
|
||||||
|
|
||||||
|
// Render the main Dapp UI without redirect; it will consume the deep-link
|
||||||
|
return <DappPage />;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user