diff --git a/app/features/idl/ui/IdlCard.tsx b/app/features/idl/ui/IdlCard.tsx index 765d508cf..9ea24003d 100644 --- a/app/features/idl/ui/IdlCard.tsx +++ b/app/features/idl/ui/IdlCard.tsx @@ -7,6 +7,8 @@ import { cn } from '@shared/utils'; import { useEffect, useMemo, useState } from 'react'; import { AlertTriangle, ExternalLink } from 'react-feather'; +import { clusterSlug } from '@/app/utils/cluster'; + import { BaseWarningCard } from '../interactive-idl/ui/BaseWarningCard'; import { IdlVariant, useIdlLastTransactionDate } from '../model/use-idl-last-transaction-date'; import { IdlInstructionSection } from './IdlInstructionSection'; @@ -21,6 +23,7 @@ type IdlTab = { export function IdlCard({ programId }: { programId: string }) { const { url, cluster } = useCluster(); + const network = clusterSlug(cluster); const { idl } = useAnchorProgram(programId, url, cluster); const { programMetadataIdl } = useProgramMetadataIdl(programId, url, cluster); const [activeTabIndex, setActiveTabIndex] = useState(); @@ -149,6 +152,8 @@ export function IdlCard({ programId }: { programId: string }) { } idl={activeTab.idl} + idlSource={activeTab.id} + network={network} programId={programId} searchStr={searchStr} onSearchChange={setSearchStr} diff --git a/app/features/idl/ui/IdlSection.tsx b/app/features/idl/ui/IdlSection.tsx index b7d5913cc..93db0b953 100644 --- a/app/features/idl/ui/IdlSection.tsx +++ b/app/features/idl/ui/IdlSection.tsx @@ -1,37 +1,89 @@ import type { SupportedIdl } from '@entities/idl'; import { Button } from '@shared/ui/button'; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@shared/ui/dialog'; import { Input } from '@shared/ui/input'; import { Label } from '@shared/ui/label'; import { Switch } from '@shared/ui/switch'; -import { useMemo, useState } from 'react'; -import { Code, Download, Search } from 'react-feather'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import { AlertCircle, Code, Download, ExternalLink, Search } from 'react-feather'; import { WalletProvider } from '@/app/providers/wallet-provider'; import { triggerDownload } from '@/app/shared/lib/triggerDownload'; +import { type IdlVariant } from '../model/use-idl-last-transaction-date'; import { IdlRenderer } from './IdlRenderer'; export function IdlSection({ idl, badge, programId, + idlSource, + network, searchStr, onSearchChange, }: { idl: SupportedIdl; badge: React.ReactNode; programId: string; + idlSource: IdlVariant; + network: string; searchStr: string; onSearchChange: (str: string) => void; }) { const [isExpanded, setIsExpanded] = useState(false); const [isRawIdlView, setIsRawIdlView] = useState(false); + const [isCastawayDialogOpen, setIsCastawayDialogOpen] = useState(false); + const downloadDropdownRef = useRef(null); const idlBase64 = useMemo(() => { return Buffer.from(JSON.stringify(idl, null, 2)).toString('base64'); }, [idl]); + const castawayUrl = useMemo(() => { + const params = new URLSearchParams({ idlSource, network, program: programId }); + return `https://www.castaway.lol/?${params.toString()}`; + }, [idlSource, network, programId]); + + useEffect(() => { + if (!downloadDropdownRef.current) { + return; + } + + let isMounted = true; + let dropdown: { dispose: () => void } | null = null; + + void import('bootstrap/js/dist/dropdown').then(module => { + if (!isMounted || !downloadDropdownRef.current) { + return; + } + + const BsDropdown = module.default; + dropdown = new BsDropdown(downloadDropdownRef.current, { + popperConfig() { + return { strategy: 'fixed' as const }; + }, + }); + }); + + return () => { + isMounted = false; + dropdown?.dispose(); + }; + }, []); const handleDownloadIdl = () => triggerDownload(idlBase64, `${programId}-idl.json`); + const handleOpenCastawayDialog = () => setIsCastawayDialogOpen(true); + const handleCastawayContinue = () => { + window.open(castawayUrl, '_blank', 'noopener,noreferrer'); + setIsCastawayDialogOpen(false); + }; return ( <> @@ -58,10 +110,55 @@ export function IdlSection({ )}
- +
+ +
+
+ + +
+
+
+ + + + + + + Leaving Solana Explorer + + +
+ + You are now leaving Explorer and going to Castaway. + + + {castawayUrl} + +
+ + + + + + +
+