From a08754f705e2ccc9eff6ccfa9380331e18eb7af2 Mon Sep 17 00:00:00 2001 From: SatoshiQaziMuhammed Date: Sat, 17 Oct 2026 20:46:08 +0400 Subject: [PATCH] fix(deposits): stop sending an empty TronGrid key and log TronGrid failures (#32) Both TRC20 deposit functions sent `TRON-PRO-API-KEY: ''` when the key was unset, and check-deposits returned silently on any non-2xx TronGrid response, so a 401 or 429 skipped a user's deposits with nothing in the logs. - send the key header only when TRONGRID_API_KEY is set; warn once if not - check-deposits logs the status and deposit index on a failed call - process-deposits records the TronGrid status in results.trc20.errors - type the batch item in check-deposits (deno check TS7006, pre-existing) --- supabase/functions/check-deposits/index.ts | 23 +++++++++++++++++--- supabase/functions/process-deposits/index.ts | 18 ++++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/supabase/functions/check-deposits/index.ts b/supabase/functions/check-deposits/index.ts index 214edef..184199f 100644 --- a/supabase/functions/check-deposits/index.ts +++ b/supabase/functions/check-deposits/index.ts @@ -24,6 +24,20 @@ const TRC20_FEE = 3; // $3 fee for TRC20 // API endpoints const TON_API = 'https://tonapi.io/v2'; const TRON_API = 'https://api.trongrid.io'; + +// Keyless TronGrid calls share a low public rate limit, so a missing key must +// show up in the logs rather than go out as an empty header. +let warnedNoTronKey = false; +function tronHeaders(): Record { + const key = Deno.env.get('TRONGRID_API_KEY'); + if (key) return { 'TRON-PRO-API-KEY': key }; + if (!warnedNoTronKey) { + console.warn('TRONGRID_API_KEY is not set; TronGrid calls are unauthenticated'); + warnedNoTronKey = true; + } + return {}; +} + const SUBSCAN_API = 'https://assethub-polkadot.api.subscan.io'; // Contract addresses - raw format from TonAPI @@ -274,7 +288,7 @@ async function checkTrc20Deposits( for (let i = 0; i < users.length; i += CONCURRENCY) { const batch = users.slice(i, i + CONCURRENCY); await Promise.all( - batch.map(async (user) => { + batch.map(async (user: { id: string; deposit_index: number }) => { try { const address = deriveTronAddress(hdMnemonic, user.deposit_index); @@ -282,11 +296,14 @@ async function checkTrc20Deposits( const response = await fetch( `${TRON_API}/v1/accounts/${address}/transactions/trc20?limit=20&contract_address=${TRON_USDT_CONTRACT}`, { - headers: { 'TRON-PRO-API-KEY': Deno.env.get('TRONGRID_API_KEY') || '' }, + headers: tronHeaders(), } ); - if (!response.ok) return; + if (!response.ok) { + console.error(`TronGrid ${response.status} for deposit index ${user.deposit_index}`); + return; + } const data = await response.json(); const transfers = data.data || []; diff --git a/supabase/functions/process-deposits/index.ts b/supabase/functions/process-deposits/index.ts index ef2db25..a4a449d 100644 --- a/supabase/functions/process-deposits/index.ts +++ b/supabase/functions/process-deposits/index.ts @@ -8,6 +8,20 @@ import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'; import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; const TRON_API = 'https://api.trongrid.io'; + +// Keyless TronGrid calls share a low public rate limit, so a missing key must +// show up in the logs rather than go out as an empty header. +let warnedNoTronKey = false; +function tronHeaders(): Record { + const key = Deno.env.get('TRONGRID_API_KEY'); + if (key) return { 'TRON-PRO-API-KEY': key }; + if (!warnedNoTronKey) { + console.warn('TRONGRID_API_KEY is not set; TronGrid calls are unauthenticated'); + warnedNoTronKey = true; + } + return {}; +} + const USDT_TRC20_CONTRACT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'; // USDT TRC20 contract interface TRC20Transfer { @@ -78,7 +92,7 @@ serve(async (req) => { const response = await fetch( `${TRON_API}/v1/accounts/${tronAddress}/transactions/trc20?limit=50&contract_address=${USDT_TRC20_CONTRACT}`, { - headers: { 'TRON-PRO-API-KEY': Deno.env.get('TRONGRID_API_KEY') || '' }, + headers: tronHeaders(), } ); @@ -125,6 +139,8 @@ serve(async (req) => { results.trc20.processed++; } } + } else { + results.trc20.errors.push(`TronGrid HTTP ${response.status}`); } } catch (err) { results.trc20.errors.push(`TRC20 error: ${err}`);