diff --git a/.env.example b/.env.example index 6d9331a..5218f16 100644 --- a/.env.example +++ b/.env.example @@ -23,10 +23,10 @@ NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/graphql NEXT_PUBLIC_ALNT_COST_LRN=lrn://laconic/pricing/alnt NEXT_PUBLIC_DEPLOYMENT_COST_LRN=lrn://laconic/pricing/webapp-deployment REGISTRY_GAS_PRICE=0.001 -REGISTRY_BOND_ID=5d82586d156fb6671a9170d92f930a72a49a29afb45e30e16fff2100e30776e2 REGISTRY_AUTHORITY=laconic-deploy +REGISTRY_BOND_ID=5d82586d156fb6671a9170d92f930a72a49a29afb45e30e16fff2100e30776e2 REGISTRY_USER_KEY= # Application Configuration -DEPLOYER_LRN= -NEXT_PUBLIC_DOMAIN_SUFFIX= +DEPLOYER_LRN=lrn://vaasl-provider/deployers/webapp-deployer-api.apps.vaasl.io +NEXT_PUBLIC_DOMAIN_SUFFIX=apps.vaasl.io diff --git a/src/app/page.tsx b/src/app/page.tsx index bd80876..046f55b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useCallback, useEffect, useState, useRef } from 'react'; +import { useCallback, useEffect, useState, useRef, useMemo } from 'react'; import dynamic from 'next/dynamic'; import { WalletMultiButton } from '@solana/wallet-adapter-react-ui'; @@ -27,6 +27,14 @@ const PaymentModal = dynamic(() => import('@/components/PaymentModal'), { ssr: f // RPC endpoint reference: https://docs.gorbagana.wtf/testnet-v2-devnet.html const GORBAGANA_GENESIS_HASH = '533uBE9RRquhTBqEX58oV52FdTTsReMdAvaUvP6hNjsn'; +// Use following curl request to get Solana chain genesis hash: +// curl https://api.mainnet-beta.solana.com \ +// -X POST \ +// -H "Content-Type: application/json" \ +// --data '{"jsonrpc":"2.0","id":1,"method":"getGenesisHash"}' +// RPC endpoint reference: https://solana.com/docs/references/clusters#on-a-high-level +const SOLANA_GENESIS_HASH = '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d'; + export default function Home() { const { wallet, connected, publicKey, disconnect } = useWallet(); @@ -42,7 +50,8 @@ export default function Home() { const [appName, setAppName] = useState(null); const [repoUrl, setRepoUrl] = useState(null); const [error, setError] = useState(null); - const [incorrectChainWarining, setIncorrectChainWarining] = useState(null); + const [incorrectChainWarning, setIncorrectChainWarning] = useState(null); + const [isFetchingChainGenesisHash, setIsFetchingChainGenesisHash] = useState(false); useEffect(() => { if (!IS_NAT_GOR_TRANSFER_ENABLED) { @@ -51,20 +60,38 @@ export default function Home() { }, [setSelectedPaymentMethod]); useEffect(() => { - if (!wallet || wallet.adapter.name !== BackpackWalletName || selectedPaymentMethod !== PaymentMethod.NAT_GOR) { + setIncorrectChainWarning(null); + if (!wallet || wallet.adapter.name !== BackpackWalletName || !connected || !selectedPaymentMethod) { return; } const warnOnIncorrectChain = async () => { - // @ts-expect-error: backpack exists on window object - const genesisHash = await window.backpack.solana.connection.getGenesisHash(); - if (genesisHash !== GORBAGANA_GENESIS_HASH) { - setIncorrectChainWarining("WARNING: Unsupported chain selected in wallet. Please switch to Gorbagana chain") + setIsFetchingChainGenesisHash(true); + + try { + // @ts-expect-error: backpack exists on window object + const genesisHash = await window.backpack.solana.connection.getGenesisHash(); + + const expectedGenesisHash = selectedPaymentMethod === PaymentMethod.NAT_GOR + ? GORBAGANA_GENESIS_HASH + : SOLANA_GENESIS_HASH; + + const expectedChainName = selectedPaymentMethod === PaymentMethod.NAT_GOR + ? "Gorbagana" + : "Solana"; + + if (genesisHash !== expectedGenesisHash) { + setIncorrectChainWarning( + `Unsupported network selected in wallet. Please switch to network for ${expectedChainName} chain and reconnect the wallet.` + ); + } + } finally { + setIsFetchingChainGenesisHash(false); } } warnOnIncorrectChain(); - }, [wallet, selectedPaymentMethod]); + }, [wallet, selectedPaymentMethod, connected]); // Track previous payment method to detect switches const previousPaymentMethodRef = useRef(null); @@ -90,7 +117,7 @@ export default function Home() { }; // Helper function to check if current wallet is compatible with selected payment method - const isWalletCompatible = () => { + const isWalletCompatible = useMemo(() => { if (!selectedPaymentMethod || !wallet) return false; const walletName = wallet.adapter.name.toLowerCase(); @@ -99,9 +126,9 @@ export default function Home() { if (selectedPaymentMethod === PaymentMethod.NAT_GOR) { return isBackpack; // Only Backpack for native GOR } else { - return !isBackpack; // Only non-Backpack wallets for SPL tokens + return true; // Only non-Backpack wallets for SPL tokens } - }; + }, [selectedPaymentMethod, wallet]); const handlePaymentComplete = useCallback(async (hash: string, paymentMethod: PaymentMethod) => { if (!publicKey || !url) { @@ -193,7 +220,7 @@ export default function Home() {

{process.env.NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL} Token

- Compatible with: Phantom, Solflare + Compatible with: All Solana compatible wallets

@@ -225,23 +252,28 @@ export default function Home() {

- {isWalletCompatible() ? 'Compatible' : 'Incompatible'} Wallet ({wallet?.adapter.name}) + {isWalletCompatible ? 'Compatible' : 'Incompatible'} Wallet ({wallet?.adapter.name})

- {!isWalletCompatible() && ( + {!isWalletCompatible && (

This wallet is not compatible with {PAYMENT_METHOD_LABELS[selectedPaymentMethod]} payments. Please select a different wallet or payment method.

)} - {incorrectChainWarining && ( + { isFetchingChainGenesisHash && ( +

+ Checking wallet network compatibility... +

+ )} + {incorrectChainWarning && (

- {incorrectChainWarining} + {incorrectChainWarning}

)}
@@ -276,18 +308,19 @@ export default function Home() {
)}
+ {/* Step 3: URL Input */}

Enter URL to Deploy

diff --git a/src/components/URLForm.tsx b/src/components/URLForm.tsx index 3ab5aaa..fe88542 100644 --- a/src/components/URLForm.tsx +++ b/src/components/URLForm.tsx @@ -103,7 +103,7 @@ export default function URLForm({ onSubmit, disabled }: URLFormProps) { opacity: (disabled || !url) ? '0.7' : '1', }} > - {disabled ? 'Connect Wallet First' : 'Deploy URL'} + Deploy URL );