diff --git a/apps/web/app/(basenames)/api/proxy/route.ts b/apps/web/app/(basenames)/api/proxy/route.ts index 06fa330b174..5fc535d40f6 100644 --- a/apps/web/app/(basenames)/api/proxy/route.ts +++ b/apps/web/app/(basenames)/api/proxy/route.ts @@ -2,7 +2,6 @@ import { NextRequest, NextResponse } from 'next/server'; import { isAddress } from 'viem'; const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY; -const BASESCAN_API_KEY = process.env.BASESCAN_API_KEY; const TALENT_PROTOCOL_API_KEY = process.env.TALENT_PROTOCOL_API_KEY; export async function GET(req: NextRequest) { @@ -19,16 +18,16 @@ export async function GET(req: NextRequest) { try { switch (apiType) { case 'etherscan': - apiUrl = `https://api.etherscan.io/api?address=${address}&apikey=${ETHERSCAN_API_KEY}&module=account&action=txlist`; + apiUrl = `https://api.etherscan.io/v2/api?module=account&action=txlist&address=${address}&chainid=1&apikey=${ETHERSCAN_API_KEY}`; break; case 'base-sepolia': - apiUrl = `https://api-sepolia.basescan.org/api?address=${address}&apikey=${BASESCAN_API_KEY}&module=account&action=txlistinternal`; + apiUrl = `https://api.etherscan.io/v2/api?module=account&action=txlistinternal&address=${address}&chainid=84532&apikey=${ETHERSCAN_API_KEY}`; break; case 'basescan': - apiUrl = `https://api.basescan.org/api?address=${address}&apikey=${BASESCAN_API_KEY}&module=account&action=txlist`; + apiUrl = `https://api.etherscan.io/v2/api?module=account&action=txlist&address=${address}&chainid=8453&apikey=${ETHERSCAN_API_KEY}`; break; case 'basescan-internal': - apiUrl = `https://api.basescan.org/api?address=${address}&apikey=${BASESCAN_API_KEY}&module=account&action=txlistinternal`; + apiUrl = `https://api.etherscan.io/v2/api?module=account&action=txlistinternal&address=${address}&chainid=8453&apikey=${ETHERSCAN_API_KEY}`; break; default: return NextResponse.json({ error: 'Invalid apiType parameter' }, { status: 400 }); @@ -49,7 +48,6 @@ export async function GET(req: NextRequest) { } else { responseData = await externalResponse.text(); } - if (externalResponse.ok) { return NextResponse.json({ data: responseData }); } else { diff --git a/apps/web/src/components/Basenames/UsernameProfileSectionHeatmap/index.tsx b/apps/web/src/components/Basenames/UsernameProfileSectionHeatmap/index.tsx index f296b90e67b..769d6dd3c32 100644 --- a/apps/web/src/components/Basenames/UsernameProfileSectionHeatmap/index.tsx +++ b/apps/web/src/components/Basenames/UsernameProfileSectionHeatmap/index.tsx @@ -162,25 +162,32 @@ export default function UsernameProfileSectionHeatmap() { }; }; + type EtherscanApiResponse = { + status: '1' | '0'; + message: string; + result: unknown; + }; + const fetchTransactions = useCallback( async (apiUrl: string, retryCount = 3): Promise => { try { const response = await fetch(apiUrl); - const json = (await response.json()) as { - data: { result: Transaction[]; status: '1' | '0'; message: string }; - }; + const json = (await response.json()) as { data: EtherscanApiResponse }; + const data = json.data; + + if (data.status === '1' && Array.isArray(data.result)) { + return data.result as Transaction[]; + } - if (json.data?.status === '1' && Array.isArray(json.data.result)) { - return json.data.result; - } else if (json.data?.status === '0' && json.data.message === 'No transactions found') { + if (data.status === '0' && data.message === 'No transactions found') { return []; // Return an empty array for no transactions - } else if (json.data?.status === '0' && json.data.message === 'Exception') { + } else if (data.status === '0' && data.message === 'Exception') { if (retryCount > 0) { console.log(`API returned an exception. Retrying... (${retryCount} attempts left)`); await new Promise((resolve) => setTimeout(resolve, 2000)); return await fetchTransactions(apiUrl, retryCount - 1); } else { - throw new Error(`API Error: ${json.data.message}`); + throw new Error(`API Error: ${data.message}`); } } else { console.error('Unexpected API response structure:', json); @@ -444,6 +451,7 @@ export default function UsernameProfileSectionHeatmap() { style={{ direction: 'rtl' }} className="w-full max-w-full overflow-x-auto overflow-y-hidden whitespace-nowrap" > + {/* @ts-expect-error react-calendar-heatmap has incompatible JSX types in our setup; runtime is fine */}