@@ -12,14 +12,12 @@ export type WalletPortfolioData = {
1212 tokens : WalletPortfolioToken [ ] ;
1313} ;
1414
15- // Retry helper with exponential backoff
15+ // Retry helper with exponential backoff - returns null on failure instead of throwing
1616async function fetchWithRetry (
1717 url : string ,
1818 options : RequestInit ,
1919 maxRetries = 3 ,
20- ) : Promise < Response > {
21- let lastError : Error | null = null ;
22-
20+ ) : Promise < Response | null > {
2321 for ( let attempt = 0 ; attempt < maxRetries ; attempt ++ ) {
2422 try {
2523 const response = await fetch ( url , options ) ;
@@ -32,15 +30,15 @@ async function fetchWithRetry(
3230 }
3331
3432 return response ;
35- } catch ( e ) {
36- lastError = e instanceof Error ? e : new Error ( String ( e ) ) ;
33+ } catch ( _e ) {
3734 // Network error - retry with backoff
3835 const delay = Math . min ( 1000 * 2 ** attempt , 10000 ) ;
3936 await new Promise ( ( resolve ) => setTimeout ( resolve , delay ) ) ;
4037 }
4138 }
4239
43- throw lastError || new Error ( "Max retries exceeded" ) ;
40+ // All retries failed - return null instead of throwing
41+ return null ;
4442}
4543
4644// Fetch tokens for a single address on a single chain
@@ -74,7 +72,8 @@ async function fetchTokensForChain(
7472 } ,
7573 } ) ;
7674
77- if ( ! response . ok ) {
75+ // If all retries failed or response not ok, return empty (balance = 0)
76+ if ( ! response || ! response . ok ) {
7877 return [ ] ;
7978 }
8079
@@ -158,15 +157,18 @@ async function fetchAllPortfolios(
158157 onProgress ?: ( completed : number , total : number ) => void ,
159158) : Promise < Map < string , WalletPortfolioData > > {
160159 const results = new Map < string , WalletPortfolioData > ( ) ;
161- const batchSize = 10 ; // Process 10 addresses at a time for better throughput
160+ const concurrency = 50 ; // Process up to 50 addresses concurrently
162161 let completed = 0 ;
162+ let index = 0 ;
163163
164- for ( let i = 0 ; i < addresses . length ; i += batchSize ) {
165- const batch = addresses . slice ( i , i + batchSize ) ;
164+ // Worker function that processes one address at a time
165+ async function worker ( ) {
166+ while ( index < addresses . length ) {
167+ const currentIndex = index ++ ;
168+ const address = addresses [ currentIndex ] ;
169+ if ( ! address ) continue ;
166170
167- // Process batch concurrently with individual error handling
168- const batchResults = await Promise . allSettled (
169- batch . map ( async ( address ) => {
171+ try {
170172 const data = await fetchWalletPortfolio (
171173 address ,
172174 chainIds ,
@@ -175,26 +177,24 @@ async function fetchAllPortfolios(
175177 clientId ,
176178 ecosystemSlug ,
177179 ) ;
178- return { address, data } ;
179- } ) ,
180- ) ;
181-
182- // Only add successful results
183- for ( const result of batchResults ) {
184- if ( result . status === "fulfilled" ) {
185- results . set ( result . value . address , result . value . data ) ;
180+ results . set ( address , data ) ;
181+ } catch ( e ) {
182+ // Silent fail - continue with others
183+ console . warn ( `Failed to fetch portfolio for ${ address } :` , e ) ;
186184 }
187- }
188-
189- completed = Math . min ( i + batchSize , addresses . length ) ;
190- onProgress ?.( completed , addresses . length ) ;
191185
192- // Small delay between batches to avoid overwhelming the API
193- if ( i + batchSize < addresses . length ) {
194- await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
186+ completed ++ ;
187+ onProgress ?.( completed , addresses . length ) ;
195188 }
196189 }
197190
191+ // Start concurrent workers
192+ const workers = Array . from (
193+ { length : Math . min ( concurrency , addresses . length ) } ,
194+ ( ) => worker ( ) ,
195+ ) ;
196+ await Promise . all ( workers ) ;
197+
198198 return results ;
199199}
200200
0 commit comments