@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.
- package/README.md +10 -2
- package/dist/client/index.d.mts +38 -11
- package/dist/client/index.d.ts +38 -11
- package/dist/client/index.js +1771 -391
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +1771 -392
- package/dist/client/index.mjs.map +1 -1
- package/dist/discovery/index.d.mts +2 -2
- package/dist/discovery/index.d.ts +2 -2
- package/dist/discovery/index.js +1 -4
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +1 -4
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/index.d.mts +26 -22
- package/dist/index.d.ts +26 -22
- package/dist/index.js +3005 -2107
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2997 -2108
- package/dist/index.mjs.map +1 -1
- package/dist/{interfaces-B85Wx7ni.d.mts → interfaces-B62Rw-dd.d.ts} +20 -15
- package/dist/{interfaces-DGdP8fQp.d.mts → interfaces-BWJJTCXO.d.mts} +1 -1
- package/dist/{interfaces-CC0LT9p9.d.ts → interfaces-BxDEka72.d.ts} +1 -1
- package/dist/{interfaces-BVNyAmKu.d.ts → interfaces-C5fLD3jB.d.mts} +20 -15
- package/dist/storage/index.d.mts +38 -142
- package/dist/storage/index.d.ts +38 -142
- package/dist/storage/index.js +852 -158
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +846 -159
- package/dist/storage/index.mjs.map +1 -1
- package/dist/store-BJlwiDX5.d.ts +151 -0
- package/dist/store-C5lnyX8k.d.mts +151 -0
- package/dist/{types-BlHjmWRK.d.mts → types-BYj_8c5c.d.mts} +3 -0
- package/dist/{types-BlHjmWRK.d.ts → types-BYj_8c5c.d.ts} +3 -0
- package/dist/wallet/index.d.mts +24 -26
- package/dist/wallet/index.d.ts +24 -26
- package/dist/wallet/index.js +130 -259
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +130 -259
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/wallet/index.mjs
CHANGED
|
@@ -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
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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
|
|
370
|
+
* Try to reuse an existing API key
|
|
392
371
|
*/
|
|
393
372
|
async _tryReuseToken(baseUrl, amount, mintUrl) {
|
|
394
|
-
const
|
|
395
|
-
if (!
|
|
396
|
-
const
|
|
397
|
-
const balanceForBaseUrl =
|
|
398
|
-
this._log("DEBUG", "
|
|
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:
|
|
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:
|
|
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
|
-
|
|
416
|
+
apiKeyEntry.key
|
|
437
417
|
);
|
|
438
418
|
this._log("DEBUG", providerBalance);
|
|
439
419
|
if (providerBalance <= 0) {
|
|
440
|
-
this.storageAdapter.
|
|
420
|
+
this.storageAdapter.removeApiKey(baseUrl);
|
|
441
421
|
}
|
|
442
422
|
}
|
|
443
423
|
return null;
|
|
444
424
|
}
|
|
445
425
|
/**
|
|
446
|
-
* Refund
|
|
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
|
|
432
|
+
async refundXcashuTokens(mintUrl, excludeBaseUrls) {
|
|
449
433
|
const results = [];
|
|
450
|
-
const
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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
|
|
505
|
-
|
|
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
|
-
|
|
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
|
|
788
|
-
|
|
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
|
-
|
|
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 <
|
|
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
|
|
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
|
*/
|