@@ -160,19 +160,27 @@ class AleoNetworkClient {
160
160
* @param url
161
161
*/
162
162
async fetchRaw ( url = "/" ) : Promise < string > {
163
- try {
164
- const response = await get ( this . host + url , {
165
- headers : this . headers ,
166
- } ) ;
167
- return await response . text ( ) ;
168
- } catch ( error ) {
169
- throw new Error ( `Error fetching data: ${ error } ` ) ;
170
- }
171
- }
163
+ try {
164
+ return await retryWithBackoff ( async ( ) => {
165
+ const response = await get ( this . host + url , {
166
+ headers : this . headers ,
167
+ } ) ;
168
+ return await response . text ( ) ;
169
+ } , {
170
+ retryOnStatus : [ 500 , 502 , 503 , 504 ] ,
171
+ shouldRetry : ( err ) => {
172
+ const msg = err ?. message ?. toLowerCase ?.( ) || "" ;
173
+ return msg . includes ( "network" ) || msg . includes ( "timeout" ) || msg . includes ( "503" ) ;
174
+ }
175
+ } ) ;
176
+ } catch ( error ) {
177
+ throw new Error ( `Error fetching data: ${ error } ` ) ;
178
+ }
179
+ }
172
180
173
181
174
182
/**
175
- * Wrapper around the POST helper to allow mocking in tests.
183
+ * Wrapper around the POST helper to allow mocking in tests. Not meant for use in production.
176
184
*
177
185
* @param url The URL to POST to.
178
186
* @param options The RequestInit options for the POST request.
@@ -383,25 +391,27 @@ class AleoNetworkClient {
383
391
}
384
392
385
393
if ( unspent ) {
386
- // Otherwise record the nonce that has been found
387
- const serialNumber =
388
- recordPlaintext . serialNumberString (
389
- resolvedPrivateKey ,
390
- "credits.aleo" ,
391
- "credits" ,
392
- ) ;
393
- // Attempt to see if the serial number is spent
394
- try {
395
- await this . getTransitionId (
396
- serialNumber ,
397
- ) ;
398
- continue ;
399
- } catch ( error ) {
400
- console . log (
401
- "Found unspent record!" ,
402
- ) ;
403
- }
404
- }
394
+ // Otherwise record the nonce that has been found
395
+ const serialNumber = recordPlaintext . serialNumberString (
396
+ resolvedPrivateKey ,
397
+ "credits.aleo" ,
398
+ "credits" ,
399
+ ) ;
400
+ // Attempt to see if the serial number is spent
401
+ try {
402
+ await retryWithBackoff ( ( ) => this . getTransitionId ( serialNumber ) , {
403
+ retryOnStatus : [ 500 , 502 , 503 ] ,
404
+ shouldRetry : ( err ) => {
405
+ const msg = err ?. message ?. toLowerCase ?.( ) || "" ;
406
+ return msg . includes ( "timeout" ) || msg . includes ( "503" ) || msg . includes ( "network" ) ;
407
+ }
408
+ } ) ;
409
+ // If it succeeds, it means the record was spent → skip it
410
+ continue ;
411
+ } catch ( error ) {
412
+ console . log ( "Found unspent record!" ) ;
413
+ }
414
+ }
405
415
406
416
// Add the record to the list of records if the user did not specify amounts.
407
417
if ( ! amounts ) {
@@ -1433,29 +1443,38 @@ class AleoNetworkClient {
1433
1443
* @returns {Promise<string> } The solution id of the submitted solution or the resulting error.
1434
1444
*/
1435
1445
async submitSolution ( solution : string ) : Promise < string > {
1436
- try {
1437
- const response = await post ( this . host + "/solution/broadcast" , {
1438
- body : solution ,
1439
- headers : Object . assign ( { } , this . headers , {
1440
- "Content-Type" : "application/json" ,
1441
- } ) ,
1442
- } ) ;
1443
-
1444
- try {
1445
- const text = await response . text ( ) ;
1446
- return parseJSON ( text ) ;
1447
- } catch ( error : any ) {
1448
- throw new Error (
1449
- `Error posting transaction. Aleo network response: ${ error . message } ` ,
1450
- ) ;
1451
- }
1452
- } catch ( error : any ) {
1453
- throw new Error (
1454
- `Error posting transaction: No response received: ${ error . message } ` ,
1455
- ) ;
1456
- }
1457
- }
1458
-
1446
+ try {
1447
+ const response = await retryWithBackoff ( ( ) =>
1448
+ post ( this . host + "/solution/broadcast" , {
1449
+ body : solution ,
1450
+ headers : Object . assign ( { } , this . headers , {
1451
+ "Content-Type" : "application/json" ,
1452
+ } ) ,
1453
+ } ) ,
1454
+ {
1455
+ // Only retry on network-level / transient errors to avoid duplicate submission
1456
+ retryOnStatus : [ 500 , 502 , 503 , 504 ] ,
1457
+ shouldRetry : ( err ) => {
1458
+ const msg = err ?. message ?. toLowerCase ?.( ) || "" ;
1459
+ return msg . includes ( "timeout" ) || msg . includes ( "network" ) || msg . includes ( "503" ) ;
1460
+ } ,
1461
+ }
1462
+ ) ;
1463
+
1464
+ try {
1465
+ const text = await response . text ( ) ;
1466
+ return parseJSON ( text ) ;
1467
+ } catch ( error : any ) {
1468
+ throw new Error (
1469
+ `Error posting solution. Aleo network response: ${ error . message } ` ,
1470
+ ) ;
1471
+ }
1472
+ } catch ( error : any ) {
1473
+ throw new Error (
1474
+ `Error posting solution: No response received: ${ error . message } ` ,
1475
+ ) ;
1476
+ }
1477
+ }
1459
1478
/**
1460
1479
* Await a submitted transaction to be confirmed or rejected on the Aleo network.
1461
1480
*
0 commit comments