diff --git a/web/src/components/NetworkStats.tsx b/web/src/components/NetworkStats.tsx index c74b4f07..d13987ce 100644 --- a/web/src/components/NetworkStats.tsx +++ b/web/src/components/NetworkStats.tsx @@ -5,7 +5,7 @@ import { Badge } from '@/components/ui/badge'; import { Activity, Wifi, WifiOff, Users, Box, TrendingUp } from 'lucide-react'; export const NetworkStats: React.FC = () => { - const { api, isApiReady, error } = usePezkuwi(); + const { api, assetHubApi, peopleApi, isApiReady, isAssetHubReady, isPeopleReady, error } = usePezkuwi(); const [blockNumber, setBlockNumber] = useState(0); const [blockHash, setBlockHash] = useState(''); const [finalizedBlock, setFinalizedBlock] = useState(0); @@ -52,17 +52,31 @@ export const NetworkStats: React.FC = () => { if (import.meta.env.DEV) console.warn('Failed to fetch validators', err); } - // 2. Fetch Collators (Invulnerables) + // 2. Fetch Collators from Parachains (Asset Hub + People Chain) let cCount = 0; + + // Fetch from Asset Hub try { - if (api.query.collatorSelection?.invulnerables) { - const invulnerables = await api.query.collatorSelection.invulnerables(); - if (invulnerables) { - cCount = invulnerables.length; + if (isAssetHubReady && assetHubApi?.query.collatorSelection?.invulnerables) { + const assetHubCollators = await assetHubApi.query.collatorSelection.invulnerables(); + if (assetHubCollators) { + cCount += assetHubCollators.length; } } } catch (err) { - if (import.meta.env.DEV) console.warn('Failed to fetch collators', err); + if (import.meta.env.DEV) console.warn('Failed to fetch Asset Hub collators', err); + } + + // Fetch from People Chain + try { + if (isPeopleReady && peopleApi?.query.collatorSelection?.invulnerables) { + const peopleCollators = await peopleApi.query.collatorSelection.invulnerables(); + if (peopleCollators) { + cCount += peopleCollators.length; + } + } + } catch (err) { + if (import.meta.env.DEV) console.warn('Failed to fetch People Chain collators', err); } // 3. Count Nominators @@ -103,7 +117,7 @@ export const NetworkStats: React.FC = () => { if (unsubscribeFinalizedHeads) unsubscribeFinalizedHeads(); if (intervalId) clearInterval(intervalId); }; - }, [api, isApiReady]); + }, [api, assetHubApi, peopleApi, isApiReady, isAssetHubReady, isPeopleReady]); if (error) { return ( diff --git a/web/supabase/functions/process-withdraw/index.ts b/web/supabase/functions/process-withdraw/index.ts index 996e9f3b..467f31e3 100644 --- a/web/supabase/functions/process-withdraw/index.ts +++ b/web/supabase/functions/process-withdraw/index.ts @@ -7,9 +7,20 @@ import { createClient } from 'npm:@supabase/supabase-js@2' import { ApiPromise, WsProvider, Keyring } from 'npm:@pezkuwi/api@16.5.11' import { cryptoWaitReady } from 'npm:@pezkuwi/util-crypto@14.0.11' -const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', +// Allowed origins for CORS +const ALLOWED_ORIGINS = [ + 'https://app.pezkuwichain.io', + 'https://www.pezkuwichain.io', + 'https://pezkuwichain.io', +] + +function getCorsHeaders(origin: string | null) { + const allowedOrigin = origin && ALLOWED_ORIGINS.includes(origin) ? origin : ALLOWED_ORIGINS[0] + return { + 'Access-Control-Allow-Origin': allowedOrigin, + 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', + 'Access-Control-Allow-Credentials': 'true', + } } // Platform hot wallet address @@ -167,6 +178,8 @@ async function sendTokens( } serve(async (req) => { + const corsHeaders = getCorsHeaders(req.headers.get('Origin')) + // Handle CORS preflight if (req.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }) diff --git a/web/supabase/functions/process-withdrawal/index.ts b/web/supabase/functions/process-withdrawal/index.ts index e14f2d66..c8598db5 100644 --- a/web/supabase/functions/process-withdrawal/index.ts +++ b/web/supabase/functions/process-withdrawal/index.ts @@ -177,10 +177,20 @@ async function processWithdrawal( * Main handler */ serve(async (req: Request) => { - // CORS headers + // Allowed origins for CORS + const ALLOWED_ORIGINS = [ + 'https://app.pezkuwichain.io', + 'https://www.pezkuwichain.io', + 'https://pezkuwichain.io', + ] + + const requestOrigin = req.headers.get('Origin') + const allowedOrigin = requestOrigin && ALLOWED_ORIGINS.includes(requestOrigin) ? requestOrigin : ALLOWED_ORIGINS[0] + const headers = { - "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Origin": allowedOrigin, "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", + "Access-Control-Allow-Credentials": "true", "Content-Type": "application/json", }; diff --git a/web/supabase/functions/verify-deposit/index.ts b/web/supabase/functions/verify-deposit/index.ts index 0902be01..ff6390a6 100644 --- a/web/supabase/functions/verify-deposit/index.ts +++ b/web/supabase/functions/verify-deposit/index.ts @@ -6,9 +6,20 @@ import { serve } from 'https://deno.land/std@0.168.0/http/server.ts' import { createClient } from 'npm:@supabase/supabase-js@2' import { ApiPromise, WsProvider } from 'npm:@pezkuwi/api@16.5.11' -const corsHeaders = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', +// Allowed origins for CORS +const ALLOWED_ORIGINS = [ + 'https://app.pezkuwichain.io', + 'https://www.pezkuwichain.io', + 'https://pezkuwichain.io', +] + +function getCorsHeaders(origin: string | null) { + const allowedOrigin = origin && ALLOWED_ORIGINS.includes(origin) ? origin : ALLOWED_ORIGINS[0] + return { + 'Access-Control-Allow-Origin': allowedOrigin, + 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', + 'Access-Control-Allow-Credentials': 'true', + } } // Platform hot wallet address (PRODUCTION) - Treasury_3 @@ -213,6 +224,8 @@ async function verifyTransactionOnChain( } serve(async (req) => { + const corsHeaders = getCorsHeaders(req.headers.get('Origin')) + // Handle CORS preflight if (req.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders })