@routstr/sdk 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +10 -2
  2. package/dist/client/index.d.mts +38 -11
  3. package/dist/client/index.d.ts +38 -11
  4. package/dist/client/index.js +1771 -391
  5. package/dist/client/index.js.map +1 -1
  6. package/dist/client/index.mjs +1771 -392
  7. package/dist/client/index.mjs.map +1 -1
  8. package/dist/discovery/index.d.mts +2 -2
  9. package/dist/discovery/index.d.ts +2 -2
  10. package/dist/discovery/index.js +1 -4
  11. package/dist/discovery/index.js.map +1 -1
  12. package/dist/discovery/index.mjs +1 -4
  13. package/dist/discovery/index.mjs.map +1 -1
  14. package/dist/index.d.mts +26 -22
  15. package/dist/index.d.ts +26 -22
  16. package/dist/index.js +3005 -2107
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +2997 -2108
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/{interfaces-B85Wx7ni.d.mts → interfaces-B62Rw-dd.d.ts} +20 -15
  21. package/dist/{interfaces-DGdP8fQp.d.mts → interfaces-BWJJTCXO.d.mts} +1 -1
  22. package/dist/{interfaces-CC0LT9p9.d.ts → interfaces-BxDEka72.d.ts} +1 -1
  23. package/dist/{interfaces-BVNyAmKu.d.ts → interfaces-C5fLD3jB.d.mts} +20 -15
  24. package/dist/storage/index.d.mts +38 -142
  25. package/dist/storage/index.d.ts +38 -142
  26. package/dist/storage/index.js +852 -158
  27. package/dist/storage/index.js.map +1 -1
  28. package/dist/storage/index.mjs +846 -159
  29. package/dist/storage/index.mjs.map +1 -1
  30. package/dist/store-BJlwiDX5.d.ts +151 -0
  31. package/dist/store-C5lnyX8k.d.mts +151 -0
  32. package/dist/{types-BlHjmWRK.d.mts → types-BYj_8c5c.d.mts} +3 -0
  33. package/dist/{types-BlHjmWRK.d.ts → types-BYj_8c5c.d.ts} +3 -0
  34. package/dist/wallet/index.d.mts +24 -26
  35. package/dist/wallet/index.d.ts +24 -26
  36. package/dist/wallet/index.js +130 -259
  37. package/dist/wallet/index.js.map +1 -1
  38. package/dist/wallet/index.mjs +130 -259
  39. package/dist/wallet/index.mjs.map +1 -1
  40. package/package.json +1 -1
@@ -120,13 +120,8 @@ var CashuSpender = class {
120
120
  normalizedMintBalances[url] = balanceInSats;
121
121
  totalMintBalance += balanceInSats;
122
122
  }
123
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
124
123
  const providerBalances = {};
125
124
  let totalProviderBalance = 0;
126
- for (const pending of pendingDistribution) {
127
- providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
128
- totalProviderBalance += pending.amount;
129
- }
130
125
  const apiKeys = this.storageAdapter.getAllApiKeys();
131
126
  for (const apiKey of apiKeys) {
132
127
  if (!providerBalances[apiKey.baseUrl]) {
@@ -347,27 +342,11 @@ var CashuSpender = class {
347
342
  };
348
343
  }
349
344
  }
350
- if (token && baseUrl) {
351
- try {
352
- this.storageAdapter.setToken(baseUrl, token);
353
- } catch (error) {
354
- if (error instanceof Error && error.message.includes("Token already exists")) {
355
- this._log(
356
- "DEBUG",
357
- `[CashuSpender] _spendInternal: Token already exists for ${baseUrl}, receiving newly created token and using existing`
358
- );
359
- const receiveResult = await this.receiveToken(token);
360
- if (receiveResult.success) {
361
- this._log(
362
- "DEBUG",
363
- `[CashuSpender] _spendInternal: Token restored successfully, amount=${receiveResult.amount}`
364
- );
365
- }
366
- token = this.storageAdapter.getToken(baseUrl);
367
- } else {
368
- throw error;
369
- }
370
- }
345
+ if (token) {
346
+ this._log(
347
+ "DEBUG",
348
+ `[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`
349
+ );
371
350
  }
372
351
  this._logTransaction("spend", {
373
352
  amount: spentAmount,
@@ -388,19 +367,19 @@ var CashuSpender = class {
388
367
  };
389
368
  }
390
369
  /**
391
- * Try to reuse an existing token
370
+ * Try to reuse an existing API key
392
371
  */
393
372
  async _tryReuseToken(baseUrl, amount, mintUrl) {
394
- const storedToken = this.storageAdapter.getToken(baseUrl);
395
- if (!storedToken) return null;
396
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
397
- const balanceForBaseUrl = pendingDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
398
- this._log("DEBUG", "RESUINGDSR GSODGNSD", balanceForBaseUrl, amount);
373
+ const apiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
374
+ if (!apiKeyEntry) return null;
375
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
376
+ const balanceForBaseUrl = apiKeyDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
377
+ this._log("DEBUG", "Reusing API key", balanceForBaseUrl, amount);
399
378
  if (balanceForBaseUrl > amount) {
400
379
  const units = this.walletAdapter.getMintUnits();
401
380
  const unit = units[mintUrl] || "sat";
402
381
  return {
403
- token: storedToken,
382
+ token: apiKeyEntry.key,
404
383
  status: "success",
405
384
  balance: balanceForBaseUrl,
406
385
  unit
@@ -411,7 +390,8 @@ var CashuSpender = class {
411
390
  const topUpResult = await this.balanceManager.topUp({
412
391
  mintUrl,
413
392
  baseUrl,
414
- amount: topUpAmount
393
+ amount: topUpAmount,
394
+ token: apiKeyEntry.key
415
395
  });
416
396
  this._log("DEBUG", "TOPUP ", topUpResult);
417
397
  if (topUpResult.success && topUpResult.toppedUpAmount) {
@@ -425,7 +405,7 @@ var CashuSpender = class {
425
405
  status: "success"
426
406
  });
427
407
  return {
428
- token: storedToken,
408
+ token: apiKeyEntry.key,
429
409
  status: "success",
430
410
  balance: newBalance,
431
411
  unit
@@ -433,83 +413,108 @@ var CashuSpender = class {
433
413
  }
434
414
  const providerBalance = await this._getProviderTokenBalance(
435
415
  baseUrl,
436
- storedToken
416
+ apiKeyEntry.key
437
417
  );
438
418
  this._log("DEBUG", providerBalance);
439
419
  if (providerBalance <= 0) {
440
- this.storageAdapter.removeToken(baseUrl);
420
+ this.storageAdapter.removeApiKey(baseUrl);
441
421
  }
442
422
  }
443
423
  return null;
444
424
  }
445
425
  /**
446
- * Refund specific providers without retrying spend
426
+ * Refund all xcashu tokens from storage and increment tryCounts on failure.
427
+ * Reuses receiveToken from BalanceManager/CashuSpender for receiving refunds.
428
+ * @param mintUrl - The mint URL for receiving tokens
429
+ * @param excludeBaseUrls - Base URLs to exclude from refund (optional)
430
+ * @returns Results for each xcashu token refund attempt
447
431
  */
448
- async refundProviders(baseUrls, mintUrl, refundApiKeys = false) {
432
+ async refundXcashuTokens(mintUrl, excludeBaseUrls) {
449
433
  const results = [];
450
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
451
- const toRefund = pendingDistribution.filter(
452
- (p) => baseUrls.includes(p.baseUrl)
453
- );
454
- const refundResults = await Promise.allSettled(
455
- toRefund.map(async (pending) => {
456
- const token = this.storageAdapter.getToken(pending.baseUrl);
457
- this._log("DEBUG", token, this.balanceManager);
458
- if (!token || !this.balanceManager) {
459
- return { baseUrl: pending.baseUrl, success: false };
460
- }
461
- const tokenBalance = await this.balanceManager.getTokenBalance(
462
- token,
463
- pending.baseUrl
464
- );
465
- if (tokenBalance.reserved > 0) {
466
- return { baseUrl: pending.baseUrl, success: false };
467
- }
468
- const result = await this.balanceManager.refund({
469
- mintUrl,
470
- baseUrl: pending.baseUrl,
471
- token
472
- });
473
- this._log("DEBUG", result);
474
- if (result.success) {
475
- this.storageAdapter.removeToken(pending.baseUrl);
476
- }
477
- return { baseUrl: pending.baseUrl, success: result.success };
478
- })
479
- );
480
- results.push(
481
- ...refundResults.map(
482
- (r) => r.status === "fulfilled" ? r.value : { baseUrl: "", success: false }
483
- )
484
- );
485
- if (refundApiKeys) {
486
- const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
487
- const apiKeysToRefund = apiKeyDistribution.filter(
488
- (p) => baseUrls.includes(p.baseUrl)
489
- );
490
- for (const apiKeyEntry of apiKeysToRefund) {
491
- const apiKeyEntryFull = this.storageAdapter.getApiKey(
492
- apiKeyEntry.baseUrl
493
- );
494
- if (apiKeyEntryFull && this.balanceManager) {
495
- const refundResult = await this.balanceManager.refundApiKey({
496
- mintUrl,
497
- baseUrl: apiKeyEntry.baseUrl,
498
- apiKey: apiKeyEntryFull.key
499
- });
500
- if (refundResult.success) {
501
- this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, 0);
434
+ const xcashuTokens = this.storageAdapter.getXcashuTokens();
435
+ const excludedUrls = new Set(excludeBaseUrls || []);
436
+ for (const [baseUrl, tokens] of Object.entries(xcashuTokens)) {
437
+ if (excludedUrls.has(baseUrl)) continue;
438
+ for (const xcashuToken of tokens) {
439
+ try {
440
+ const receiveResult = await this.receiveToken(xcashuToken.token);
441
+ if (receiveResult.success) {
442
+ this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
443
+ results.push({
444
+ baseUrl,
445
+ token: xcashuToken.token,
446
+ success: true
447
+ });
448
+ this._log(
449
+ "DEBUG",
450
+ `[CashuSpender] refundXcashuTokens: Successfully refunded xcashu token for ${baseUrl}, amount=${receiveResult.amount}`
451
+ );
452
+ } else {
453
+ const currentTryCount = xcashuToken.tryCount ?? 0;
454
+ const newTryCount = currentTryCount + 1;
455
+ this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
456
+ results.push({
457
+ baseUrl,
458
+ token: xcashuToken.token,
459
+ success: false,
460
+ error: receiveResult.message ?? "Refund failed"
461
+ });
462
+ this._log(
463
+ "DEBUG",
464
+ `[CashuSpender] refundXcashuTokens: Failed to refund xcashu token for ${baseUrl}, incremented tryCount to ${newTryCount}`
465
+ );
502
466
  }
467
+ } catch (error) {
468
+ const currentTryCount = xcashuToken.tryCount ?? 0;
469
+ const newTryCount = currentTryCount + 1;
470
+ this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
471
+ const errorMessage = error instanceof Error ? error.message : String(error);
503
472
  results.push({
504
- baseUrl: apiKeyEntry.baseUrl,
505
- success: refundResult.success
473
+ baseUrl,
474
+ token: xcashuToken.token,
475
+ success: false,
476
+ error: errorMessage
506
477
  });
478
+ this._log(
479
+ "ERROR",
480
+ `[CashuSpender] refundXcashuTokens: Exception during refund for ${baseUrl}: ${errorMessage}, incremented tryCount to ${newTryCount}`
481
+ );
482
+ }
483
+ }
484
+ }
485
+ return results;
486
+ }
487
+ /**
488
+ * Refund specific providers without retrying spend
489
+ */
490
+ async refundProviders(mintUrl, forceRefund) {
491
+ const results = [];
492
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
493
+ for (const apiKeyEntry of apiKeyDistribution) {
494
+ const apiKeyEntryFull = this.storageAdapter.getApiKey(
495
+ apiKeyEntry.baseUrl
496
+ );
497
+ if (apiKeyEntryFull && this.balanceManager) {
498
+ const refundResult = await this.balanceManager.refundApiKey({
499
+ mintUrl,
500
+ baseUrl: apiKeyEntry.baseUrl,
501
+ apiKey: apiKeyEntryFull.key,
502
+ forceRefund
503
+ });
504
+ if (refundResult.success) {
505
+ this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
507
506
  } else {
508
- results.push({
509
- baseUrl: apiKeyEntry.baseUrl,
510
- success: false
511
- });
507
+ this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, apiKeyEntry.amount);
512
508
  }
509
+ results.push({
510
+ baseUrl: apiKeyEntry.baseUrl,
511
+ success: refundResult.success
512
+ });
513
+ } else {
514
+ results.push({
515
+ baseUrl: apiKeyEntry.baseUrl,
516
+ success: false
517
+ });
513
518
  }
514
519
  }
515
520
  return results;
@@ -594,13 +599,8 @@ var BalanceManager = class {
594
599
  normalizedMintBalances[url] = balanceInSats;
595
600
  totalMintBalance += balanceInSats;
596
601
  }
597
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
598
602
  const providerBalances = {};
599
603
  let totalProviderBalance = 0;
600
- for (const pending of pendingDistribution) {
601
- providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
602
- totalProviderBalance += pending.amount;
603
- }
604
604
  const apiKeys = this.storageAdapter.getAllApiKeys();
605
605
  for (const apiKey of apiKeys) {
606
606
  if (!providerBalances[apiKey.baseUrl]) {
@@ -615,65 +615,31 @@ var BalanceManager = class {
615
615
  mintBalances: normalizedMintBalances
616
616
  };
617
617
  }
618
- /**
619
- * Unified refund - handles both NIP-60 and legacy wallet refunds
620
- */
621
- async refund(options) {
622
- const { mintUrl, baseUrl, token: providedToken } = options;
623
- const storedToken = providedToken || this.storageAdapter.getToken(baseUrl);
624
- if (!storedToken) {
625
- console.log("[BalanceManager] No token to refund, returning early");
626
- return { success: true, message: "No API key to refund" };
627
- }
628
- let fetchResult;
629
- try {
630
- fetchResult = await this._fetchRefundToken(baseUrl, storedToken);
631
- if (!fetchResult.success) {
632
- return {
633
- success: false,
634
- message: fetchResult.error || "Refund failed",
635
- requestId: fetchResult.requestId
636
- };
637
- }
638
- if (!fetchResult.token) {
639
- return {
640
- success: false,
641
- message: "No token received from refund",
642
- requestId: fetchResult.requestId
643
- };
644
- }
645
- if (fetchResult.error === "No balance to refund") {
646
- console.log(
647
- "[BalanceManager] No balance to refund, removing stored token"
648
- );
649
- this.storageAdapter.removeToken(baseUrl);
650
- return { success: true, message: "No balance to refund" };
651
- }
652
- const receiveResult = await this.cashuSpender.receiveToken(
653
- fetchResult.token
654
- );
655
- const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
656
- if (!providedToken) {
657
- this.storageAdapter.removeToken(baseUrl);
658
- }
659
- return {
660
- success: receiveResult.success,
661
- refundedAmount: totalAmountMsat,
662
- requestId: fetchResult.requestId
663
- };
664
- } catch (error) {
665
- console.error("[BalanceManager] Refund error", error);
666
- return this._handleRefundError(error, mintUrl, fetchResult?.requestId);
667
- }
668
- }
669
618
  /**
670
619
  * Refund API key balance - convert remaining API key balance to cashu token
620
+ * @param options - Refund options including forceRefund flag
621
+ * @returns Refund result
671
622
  */
672
623
  async refundApiKey(options) {
673
- const { mintUrl, baseUrl, apiKey } = options;
624
+ const { mintUrl, baseUrl, apiKey, forceRefund } = options;
674
625
  if (!apiKey) {
675
626
  return { success: false, message: "No API key to refund" };
676
627
  }
628
+ if (!forceRefund) {
629
+ const apiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
630
+ if (apiKeyEntry?.lastUsed) {
631
+ const fiveMinutesAgo = Date.now() - 5 * 60 * 1e3;
632
+ if (apiKeyEntry.lastUsed > fiveMinutesAgo) {
633
+ console.log(
634
+ `[BalanceManager] Skipping refund for ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1e3)}s ago`
635
+ );
636
+ return {
637
+ success: false,
638
+ message: "API key was used recently, skipping refund"
639
+ };
640
+ }
641
+ }
642
+ }
677
643
  let fetchResult;
678
644
  try {
679
645
  fetchResult = await this._fetchRefundTokenWithApiKey(baseUrl, apiKey);
@@ -784,8 +750,9 @@ var BalanceManager = class {
784
750
  if (!amount || amount <= 0) {
785
751
  return { success: false, message: "Invalid top up amount" };
786
752
  }
787
- const storedToken = providedToken || this.storageAdapter.getToken(baseUrl);
788
- if (!storedToken) {
753
+ const apiKeyEntry = providedToken ? null : this.storageAdapter.getApiKey(baseUrl);
754
+ const apiKey = providedToken || apiKeyEntry?.key;
755
+ if (!apiKey) {
789
756
  return { success: false, message: "No API key available for top up" };
790
757
  }
791
758
  let cashuToken = null;
@@ -805,7 +772,7 @@ var BalanceManager = class {
805
772
  cashuToken = tokenResult.token;
806
773
  const topUpResult = await this._postTopUp(
807
774
  baseUrl,
808
- storedToken,
775
+ apiKey,
809
776
  cashuToken
810
777
  );
811
778
  requestId = topUpResult.requestId;
@@ -865,8 +832,8 @@ var BalanceManager = class {
865
832
  const refundableProviderBalance = Object.entries(
866
833
  balanceState.providerBalances
867
834
  ).filter(([providerBaseUrl]) => providerBaseUrl !== baseUrl).reduce((sum, [, value]) => sum + value, 0);
868
- if (totalMintBalance + targetProviderBalance < adjustedAmount && totalMintBalance + targetProviderBalance + refundableProviderBalance >= adjustedAmount && retryCount < 1) {
869
- await this._refundOtherProvidersForTopUp(baseUrl, mintUrl);
835
+ if (totalMintBalance + targetProviderBalance < adjustedAmount && totalMintBalance + targetProviderBalance + refundableProviderBalance >= adjustedAmount && retryCount < 2) {
836
+ await this._refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount);
870
837
  return this.createProviderToken({
871
838
  ...options,
872
839
  retryCount: retryCount + 1
@@ -1019,38 +986,12 @@ var BalanceManager = class {
1019
986
  }
1020
987
  return candidates;
1021
988
  }
1022
- async _refundOtherProvidersForTopUp(baseUrl, mintUrl) {
1023
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
989
+ async _refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount) {
1024
990
  const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
1025
- const toRefund = pendingDistribution.filter(
1026
- (pending) => pending.baseUrl !== baseUrl
1027
- );
991
+ const forceRefund = retryCount >= 2;
1028
992
  const apiKeysToRefund = apiKeyDistribution.filter(
1029
993
  (apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0
1030
994
  );
1031
- const tokenRefundResults = await Promise.allSettled(
1032
- toRefund.map(async (pending) => {
1033
- const token = this.storageAdapter.getToken(pending.baseUrl);
1034
- if (!token) {
1035
- return { baseUrl: pending.baseUrl, success: false };
1036
- }
1037
- const tokenBalance = await this.getTokenBalance(token, pending.baseUrl);
1038
- if (tokenBalance.reserved > 0) {
1039
- return { baseUrl: pending.baseUrl, success: false };
1040
- }
1041
- const result = await this.refund({
1042
- mintUrl,
1043
- baseUrl: pending.baseUrl,
1044
- token
1045
- });
1046
- return { baseUrl: pending.baseUrl, success: result.success };
1047
- })
1048
- );
1049
- for (const result of tokenRefundResults) {
1050
- if (result.status === "fulfilled" && result.value.success) {
1051
- this.storageAdapter.removeToken(result.value.baseUrl);
1052
- }
1053
- }
1054
995
  const apiKeyRefundResults = await Promise.allSettled(
1055
996
  apiKeysToRefund.map(async (apiKeyEntry) => {
1056
997
  const fullApiKeyEntry = this.storageAdapter.getApiKey(
@@ -1062,7 +1003,8 @@ var BalanceManager = class {
1062
1003
  const result = await this.refundApiKey({
1063
1004
  mintUrl,
1064
1005
  baseUrl: apiKeyEntry.baseUrl,
1065
- apiKey: fullApiKeyEntry.key
1006
+ apiKey: fullApiKeyEntry.key,
1007
+ forceRefund
1066
1008
  });
1067
1009
  return { baseUrl: apiKeyEntry.baseUrl, success: result.success };
1068
1010
  })
@@ -1073,77 +1015,6 @@ var BalanceManager = class {
1073
1015
  }
1074
1016
  }
1075
1017
  }
1076
- /**
1077
- * Fetch refund token from provider API
1078
- */
1079
- async _fetchRefundToken(baseUrl, storedToken) {
1080
- if (!baseUrl) {
1081
- return {
1082
- success: false,
1083
- error: "No base URL configured"
1084
- };
1085
- }
1086
- const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
1087
- const url = `${normalizedBaseUrl}v1/wallet/refund`;
1088
- const controller = new AbortController();
1089
- const timeoutId = setTimeout(() => {
1090
- controller.abort();
1091
- }, 6e4);
1092
- try {
1093
- const response = await fetch(url, {
1094
- method: "POST",
1095
- headers: {
1096
- Authorization: `Bearer ${storedToken}`,
1097
- "Content-Type": "application/json"
1098
- },
1099
- signal: controller.signal
1100
- });
1101
- clearTimeout(timeoutId);
1102
- const requestId = response.headers.get("x-routstr-request-id") || void 0;
1103
- if (!response.ok) {
1104
- const errorData = await response.json().catch(() => ({}));
1105
- if (response.status === 400 && errorData?.detail === "No balance to refund") {
1106
- this.storageAdapter.removeToken(baseUrl);
1107
- return {
1108
- success: false,
1109
- requestId,
1110
- error: "No balance to refund"
1111
- };
1112
- }
1113
- return {
1114
- success: false,
1115
- requestId,
1116
- error: `Refund request failed with status ${response.status}: ${errorData?.detail || response.statusText}`
1117
- };
1118
- }
1119
- const data = await response.json();
1120
- console.log("refund rsule", data);
1121
- return {
1122
- success: true,
1123
- token: data.token,
1124
- requestId
1125
- };
1126
- } catch (error) {
1127
- clearTimeout(timeoutId);
1128
- console.error("[BalanceManager._fetchRefundToken] Fetch error", error);
1129
- if (error instanceof Error) {
1130
- if (error.name === "AbortError") {
1131
- return {
1132
- success: false,
1133
- error: "Request timed out after 1 minute"
1134
- };
1135
- }
1136
- return {
1137
- success: false,
1138
- error: error.message
1139
- };
1140
- }
1141
- return {
1142
- success: false,
1143
- error: "Unknown error occurred during refund request"
1144
- };
1145
- }
1146
- }
1147
1018
  /**
1148
1019
  * Post topup request to provider API
1149
1020
  */