@routstr/sdk 0.2.5 → 0.2.7
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 +1 -2
- package/dist/client/index.d.mts +34 -6
- package/dist/client/index.d.ts +34 -6
- package/dist/client/index.js +773 -479
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +773 -479
- package/dist/client/index.mjs.map +1 -1
- package/dist/discovery/index.js +1 -1
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +1 -1
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/index.d.mts +21 -9
- package/dist/index.d.ts +21 -9
- package/dist/index.js +897 -558
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +895 -559
- package/dist/index.mjs.map +1 -1
- package/dist/{interfaces-CluftN4z.d.ts → interfaces-B62Rw-dd.d.ts} +19 -14
- package/dist/{interfaces-C6Dr6hKy.d.mts → interfaces-C5fLD3jB.d.mts} +19 -14
- package/dist/storage/index.d.mts +39 -162
- package/dist/storage/index.d.ts +39 -162
- package/dist/storage/index.js +529 -193
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +527 -194
- package/dist/storage/index.mjs.map +1 -1
- package/dist/store-DGeLPv9E.d.mts +172 -0
- package/dist/store-h7m23ffq.d.ts +172 -0
- package/dist/wallet/index.d.mts +26 -26
- package/dist/wallet/index.d.ts +26 -26
- package/dist/wallet/index.js +143 -271
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +143 -271
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/wallet/index.js
CHANGED
|
@@ -122,13 +122,8 @@ var CashuSpender = class {
|
|
|
122
122
|
normalizedMintBalances[url] = balanceInSats;
|
|
123
123
|
totalMintBalance += balanceInSats;
|
|
124
124
|
}
|
|
125
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
126
125
|
const providerBalances = {};
|
|
127
126
|
let totalProviderBalance = 0;
|
|
128
|
-
for (const pending of pendingDistribution) {
|
|
129
|
-
providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
|
|
130
|
-
totalProviderBalance += pending.amount;
|
|
131
|
-
}
|
|
132
127
|
const apiKeys = this.storageAdapter.getAllApiKeys();
|
|
133
128
|
for (const apiKey of apiKeys) {
|
|
134
129
|
if (!providerBalances[apiKey.baseUrl]) {
|
|
@@ -349,27 +344,11 @@ var CashuSpender = class {
|
|
|
349
344
|
};
|
|
350
345
|
}
|
|
351
346
|
}
|
|
352
|
-
if (token
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
this._log(
|
|
358
|
-
"DEBUG",
|
|
359
|
-
`[CashuSpender] _spendInternal: Token already exists for ${baseUrl}, receiving newly created token and using existing`
|
|
360
|
-
);
|
|
361
|
-
const receiveResult = await this.receiveToken(token);
|
|
362
|
-
if (receiveResult.success) {
|
|
363
|
-
this._log(
|
|
364
|
-
"DEBUG",
|
|
365
|
-
`[CashuSpender] _spendInternal: Token restored successfully, amount=${receiveResult.amount}`
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
token = this.storageAdapter.getToken(baseUrl);
|
|
369
|
-
} else {
|
|
370
|
-
throw error;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
347
|
+
if (token) {
|
|
348
|
+
this._log(
|
|
349
|
+
"DEBUG",
|
|
350
|
+
`[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`
|
|
351
|
+
);
|
|
373
352
|
}
|
|
374
353
|
this._logTransaction("spend", {
|
|
375
354
|
amount: spentAmount,
|
|
@@ -390,19 +369,19 @@ var CashuSpender = class {
|
|
|
390
369
|
};
|
|
391
370
|
}
|
|
392
371
|
/**
|
|
393
|
-
* Try to reuse an existing
|
|
372
|
+
* Try to reuse an existing API key
|
|
394
373
|
*/
|
|
395
374
|
async _tryReuseToken(baseUrl, amount, mintUrl) {
|
|
396
|
-
const
|
|
397
|
-
if (!
|
|
398
|
-
const
|
|
399
|
-
const balanceForBaseUrl =
|
|
400
|
-
this._log("DEBUG", "
|
|
375
|
+
const apiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
|
|
376
|
+
if (!apiKeyEntry) return null;
|
|
377
|
+
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
378
|
+
const balanceForBaseUrl = apiKeyDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
|
|
379
|
+
this._log("DEBUG", "Reusing API key", balanceForBaseUrl, amount);
|
|
401
380
|
if (balanceForBaseUrl > amount) {
|
|
402
381
|
const units = this.walletAdapter.getMintUnits();
|
|
403
382
|
const unit = units[mintUrl] || "sat";
|
|
404
383
|
return {
|
|
405
|
-
token:
|
|
384
|
+
token: apiKeyEntry.key,
|
|
406
385
|
status: "success",
|
|
407
386
|
balance: balanceForBaseUrl,
|
|
408
387
|
unit
|
|
@@ -413,7 +392,8 @@ var CashuSpender = class {
|
|
|
413
392
|
const topUpResult = await this.balanceManager.topUp({
|
|
414
393
|
mintUrl,
|
|
415
394
|
baseUrl,
|
|
416
|
-
amount: topUpAmount
|
|
395
|
+
amount: topUpAmount,
|
|
396
|
+
token: apiKeyEntry.key
|
|
417
397
|
});
|
|
418
398
|
this._log("DEBUG", "TOPUP ", topUpResult);
|
|
419
399
|
if (topUpResult.success && topUpResult.toppedUpAmount) {
|
|
@@ -427,7 +407,7 @@ var CashuSpender = class {
|
|
|
427
407
|
status: "success"
|
|
428
408
|
});
|
|
429
409
|
return {
|
|
430
|
-
token:
|
|
410
|
+
token: apiKeyEntry.key,
|
|
431
411
|
status: "success",
|
|
432
412
|
balance: newBalance,
|
|
433
413
|
unit
|
|
@@ -435,84 +415,131 @@ var CashuSpender = class {
|
|
|
435
415
|
}
|
|
436
416
|
const providerBalance = await this._getProviderTokenBalance(
|
|
437
417
|
baseUrl,
|
|
438
|
-
|
|
418
|
+
apiKeyEntry.key
|
|
439
419
|
);
|
|
440
420
|
this._log("DEBUG", providerBalance);
|
|
441
421
|
if (providerBalance <= 0) {
|
|
442
|
-
this.storageAdapter.
|
|
422
|
+
this.storageAdapter.removeApiKey(baseUrl);
|
|
443
423
|
}
|
|
444
424
|
}
|
|
445
425
|
return null;
|
|
446
426
|
}
|
|
447
427
|
/**
|
|
448
|
-
* Refund
|
|
428
|
+
* Refund all xcashu tokens from storage by calling the provider's refund endpoint.
|
|
429
|
+
* The xcashu token acts as an API key to claim the refund, and the response contains
|
|
430
|
+
* the actual refunded Cashu token which is then received into the wallet.
|
|
431
|
+
* @param mintUrl - The mint URL for receiving tokens
|
|
432
|
+
* @param excludeBaseUrls - Base URLs to exclude from refund (optional)
|
|
433
|
+
* @returns Results for each xcashu token refund attempt
|
|
449
434
|
*/
|
|
450
|
-
async
|
|
435
|
+
async refundXcashuTokens(mintUrl, excludeBaseUrls) {
|
|
451
436
|
const results = [];
|
|
452
|
-
const
|
|
453
|
-
const
|
|
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
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
apiKey: apiKeyEntryFull.key,
|
|
501
|
-
forceRefund
|
|
502
|
-
});
|
|
503
|
-
if (refundResult.success) {
|
|
504
|
-
this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, 0);
|
|
437
|
+
const xcashuTokens = this.storageAdapter.getXcashuTokens();
|
|
438
|
+
const excludedUrls = new Set(excludeBaseUrls || []);
|
|
439
|
+
for (const [baseUrl, tokens] of Object.entries(xcashuTokens)) {
|
|
440
|
+
if (excludedUrls.has(baseUrl)) continue;
|
|
441
|
+
for (const xcashuToken of tokens) {
|
|
442
|
+
try {
|
|
443
|
+
if (!this.balanceManager) {
|
|
444
|
+
throw new Error("BalanceManager not available for xcashu refund");
|
|
445
|
+
}
|
|
446
|
+
const fetchResult = await this.balanceManager.fetchRefundToken(
|
|
447
|
+
baseUrl,
|
|
448
|
+
xcashuToken.token,
|
|
449
|
+
true
|
|
450
|
+
);
|
|
451
|
+
if (!fetchResult.success || !fetchResult.token) {
|
|
452
|
+
throw new Error(
|
|
453
|
+
fetchResult.error || "Failed to fetch refund token from provider"
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
const receiveResult = await this.receiveToken(fetchResult.token);
|
|
457
|
+
if (receiveResult.success) {
|
|
458
|
+
this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
|
|
459
|
+
results.push({
|
|
460
|
+
baseUrl,
|
|
461
|
+
token: xcashuToken.token,
|
|
462
|
+
success: true
|
|
463
|
+
});
|
|
464
|
+
this._log(
|
|
465
|
+
"DEBUG",
|
|
466
|
+
`[CashuSpender] refundXcashuTokens: Successfully refunded xcashu token for ${baseUrl}, amount=${receiveResult.amount}`
|
|
467
|
+
);
|
|
468
|
+
} else {
|
|
469
|
+
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
470
|
+
const newTryCount = currentTryCount + 1;
|
|
471
|
+
this.storageAdapter.updateXcashuTokenTryCount(
|
|
472
|
+
xcashuToken.token,
|
|
473
|
+
newTryCount
|
|
474
|
+
);
|
|
475
|
+
results.push({
|
|
476
|
+
baseUrl,
|
|
477
|
+
token: xcashuToken.token,
|
|
478
|
+
success: false,
|
|
479
|
+
error: receiveResult.message ?? "Refund failed"
|
|
480
|
+
});
|
|
481
|
+
this._log(
|
|
482
|
+
"DEBUG",
|
|
483
|
+
`[CashuSpender] refundXcashuTokens: Failed to receive refund token for ${baseUrl}, incremented tryCount to ${newTryCount}`
|
|
484
|
+
);
|
|
505
485
|
}
|
|
486
|
+
} catch (error) {
|
|
487
|
+
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
488
|
+
const newTryCount = currentTryCount + 1;
|
|
489
|
+
this.storageAdapter.updateXcashuTokenTryCount(
|
|
490
|
+
xcashuToken.token,
|
|
491
|
+
newTryCount
|
|
492
|
+
);
|
|
493
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
506
494
|
results.push({
|
|
507
|
-
baseUrl
|
|
508
|
-
|
|
495
|
+
baseUrl,
|
|
496
|
+
token: xcashuToken.token,
|
|
497
|
+
success: false,
|
|
498
|
+
error: errorMessage
|
|
509
499
|
});
|
|
500
|
+
this._log(
|
|
501
|
+
"ERROR",
|
|
502
|
+
`[CashuSpender] refundXcashuTokens: Exception during refund for ${baseUrl}: ${errorMessage}, incremented tryCount to ${newTryCount}`
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return results;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Refund specific providers without retrying spend
|
|
511
|
+
*/
|
|
512
|
+
async refundProviders(mintUrl, forceRefund) {
|
|
513
|
+
const results = [];
|
|
514
|
+
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
515
|
+
for (const apiKeyEntry of apiKeyDistribution) {
|
|
516
|
+
const apiKeyEntryFull = this.storageAdapter.getApiKey(
|
|
517
|
+
apiKeyEntry.baseUrl
|
|
518
|
+
);
|
|
519
|
+
if (apiKeyEntryFull && this.balanceManager) {
|
|
520
|
+
const refundResult = await this.balanceManager.refundApiKey({
|
|
521
|
+
mintUrl,
|
|
522
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
523
|
+
apiKey: apiKeyEntryFull.key,
|
|
524
|
+
forceRefund
|
|
525
|
+
});
|
|
526
|
+
if (refundResult.success) {
|
|
527
|
+
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
510
528
|
} else {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
529
|
+
this.storageAdapter.updateApiKeyBalance(
|
|
530
|
+
apiKeyEntry.baseUrl,
|
|
531
|
+
apiKeyEntry.amount
|
|
532
|
+
);
|
|
515
533
|
}
|
|
534
|
+
results.push({
|
|
535
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
536
|
+
success: refundResult.success
|
|
537
|
+
});
|
|
538
|
+
} else {
|
|
539
|
+
results.push({
|
|
540
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
541
|
+
success: false
|
|
542
|
+
});
|
|
516
543
|
}
|
|
517
544
|
}
|
|
518
545
|
return results;
|
|
@@ -597,13 +624,8 @@ var BalanceManager = class {
|
|
|
597
624
|
normalizedMintBalances[url] = balanceInSats;
|
|
598
625
|
totalMintBalance += balanceInSats;
|
|
599
626
|
}
|
|
600
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
601
627
|
const providerBalances = {};
|
|
602
628
|
let totalProviderBalance = 0;
|
|
603
|
-
for (const pending of pendingDistribution) {
|
|
604
|
-
providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
|
|
605
|
-
totalProviderBalance += pending.amount;
|
|
606
|
-
}
|
|
607
629
|
const apiKeys = this.storageAdapter.getAllApiKeys();
|
|
608
630
|
for (const apiKey of apiKeys) {
|
|
609
631
|
if (!providerBalances[apiKey.baseUrl]) {
|
|
@@ -618,57 +640,6 @@ var BalanceManager = class {
|
|
|
618
640
|
mintBalances: normalizedMintBalances
|
|
619
641
|
};
|
|
620
642
|
}
|
|
621
|
-
/**
|
|
622
|
-
* Unified refund - handles both NIP-60 and legacy wallet refunds
|
|
623
|
-
*/
|
|
624
|
-
async refund(options) {
|
|
625
|
-
const { mintUrl, baseUrl, token: providedToken } = options;
|
|
626
|
-
const storedToken = providedToken || this.storageAdapter.getToken(baseUrl);
|
|
627
|
-
if (!storedToken) {
|
|
628
|
-
console.log("[BalanceManager] No token to refund, returning early");
|
|
629
|
-
return { success: true, message: "No API key to refund" };
|
|
630
|
-
}
|
|
631
|
-
let fetchResult;
|
|
632
|
-
try {
|
|
633
|
-
fetchResult = await this._fetchRefundToken(baseUrl, storedToken);
|
|
634
|
-
if (!fetchResult.success) {
|
|
635
|
-
return {
|
|
636
|
-
success: false,
|
|
637
|
-
message: fetchResult.error || "Refund failed",
|
|
638
|
-
requestId: fetchResult.requestId
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
if (!fetchResult.token) {
|
|
642
|
-
return {
|
|
643
|
-
success: false,
|
|
644
|
-
message: "No token received from refund",
|
|
645
|
-
requestId: fetchResult.requestId
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
if (fetchResult.error === "No balance to refund") {
|
|
649
|
-
console.log(
|
|
650
|
-
"[BalanceManager] No balance to refund, removing stored token"
|
|
651
|
-
);
|
|
652
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
653
|
-
return { success: true, message: "No balance to refund" };
|
|
654
|
-
}
|
|
655
|
-
const receiveResult = await this.cashuSpender.receiveToken(
|
|
656
|
-
fetchResult.token
|
|
657
|
-
);
|
|
658
|
-
const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
|
|
659
|
-
if (!providedToken) {
|
|
660
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
661
|
-
}
|
|
662
|
-
return {
|
|
663
|
-
success: receiveResult.success,
|
|
664
|
-
refundedAmount: totalAmountMsat,
|
|
665
|
-
requestId: fetchResult.requestId
|
|
666
|
-
};
|
|
667
|
-
} catch (error) {
|
|
668
|
-
console.error("[BalanceManager] Refund error", error);
|
|
669
|
-
return this._handleRefundError(error, mintUrl, fetchResult?.requestId);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
643
|
/**
|
|
673
644
|
* Refund API key balance - convert remaining API key balance to cashu token
|
|
674
645
|
* @param options - Refund options including forceRefund flag
|
|
@@ -696,7 +667,7 @@ var BalanceManager = class {
|
|
|
696
667
|
}
|
|
697
668
|
let fetchResult;
|
|
698
669
|
try {
|
|
699
|
-
fetchResult = await this.
|
|
670
|
+
fetchResult = await this.fetchRefundToken(baseUrl, apiKey);
|
|
700
671
|
if (!fetchResult.success) {
|
|
701
672
|
return {
|
|
702
673
|
success: false,
|
|
@@ -732,9 +703,9 @@ var BalanceManager = class {
|
|
|
732
703
|
}
|
|
733
704
|
}
|
|
734
705
|
/**
|
|
735
|
-
* Fetch refund token from provider API using API key authentication
|
|
706
|
+
* Fetch refund token from provider API using API key (or xcashu token) authentication
|
|
736
707
|
*/
|
|
737
|
-
async
|
|
708
|
+
async fetchRefundToken(baseUrl, apiKeyOrToken, xCashu = false) {
|
|
738
709
|
if (!baseUrl) {
|
|
739
710
|
return {
|
|
740
711
|
success: false,
|
|
@@ -748,12 +719,17 @@ var BalanceManager = class {
|
|
|
748
719
|
controller.abort();
|
|
749
720
|
}, 6e4);
|
|
750
721
|
try {
|
|
722
|
+
const headers = {
|
|
723
|
+
"Content-Type": "application/json"
|
|
724
|
+
};
|
|
725
|
+
if (xCashu) {
|
|
726
|
+
headers["X-Cashu"] = apiKeyOrToken;
|
|
727
|
+
} else {
|
|
728
|
+
headers["Authorization"] = `Bearer ${apiKeyOrToken}`;
|
|
729
|
+
}
|
|
751
730
|
const response = await fetch(url, {
|
|
752
731
|
method: "POST",
|
|
753
|
-
headers
|
|
754
|
-
Authorization: `Bearer ${apiKey}`,
|
|
755
|
-
"Content-Type": "application/json"
|
|
756
|
-
},
|
|
732
|
+
headers,
|
|
757
733
|
signal: controller.signal
|
|
758
734
|
});
|
|
759
735
|
clearTimeout(timeoutId);
|
|
@@ -774,10 +750,7 @@ var BalanceManager = class {
|
|
|
774
750
|
};
|
|
775
751
|
} catch (error) {
|
|
776
752
|
clearTimeout(timeoutId);
|
|
777
|
-
console.error(
|
|
778
|
-
"[BalanceManager._fetchRefundTokenWithApiKey] Fetch error",
|
|
779
|
-
error
|
|
780
|
-
);
|
|
753
|
+
console.error("[BalanceManager.fetchRefundToken] Fetch error", error);
|
|
781
754
|
if (error instanceof Error) {
|
|
782
755
|
if (error.name === "AbortError") {
|
|
783
756
|
return {
|
|
@@ -804,8 +777,9 @@ var BalanceManager = class {
|
|
|
804
777
|
if (!amount || amount <= 0) {
|
|
805
778
|
return { success: false, message: "Invalid top up amount" };
|
|
806
779
|
}
|
|
807
|
-
const
|
|
808
|
-
|
|
780
|
+
const apiKeyEntry = providedToken ? null : this.storageAdapter.getApiKey(baseUrl);
|
|
781
|
+
const apiKey = providedToken || apiKeyEntry?.key;
|
|
782
|
+
if (!apiKey) {
|
|
809
783
|
return { success: false, message: "No API key available for top up" };
|
|
810
784
|
}
|
|
811
785
|
let cashuToken = null;
|
|
@@ -823,11 +797,7 @@ var BalanceManager = class {
|
|
|
823
797
|
};
|
|
824
798
|
}
|
|
825
799
|
cashuToken = tokenResult.token;
|
|
826
|
-
const topUpResult = await this._postTopUp(
|
|
827
|
-
baseUrl,
|
|
828
|
-
storedToken,
|
|
829
|
-
cashuToken
|
|
830
|
-
);
|
|
800
|
+
const topUpResult = await this._postTopUp(baseUrl, apiKey, cashuToken);
|
|
831
801
|
requestId = topUpResult.requestId;
|
|
832
802
|
console.log(topUpResult);
|
|
833
803
|
if (!topUpResult.success) {
|
|
@@ -1040,38 +1010,11 @@ var BalanceManager = class {
|
|
|
1040
1010
|
return candidates;
|
|
1041
1011
|
}
|
|
1042
1012
|
async _refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount) {
|
|
1043
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
1044
1013
|
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
1045
1014
|
const forceRefund = retryCount >= 2;
|
|
1046
|
-
const toRefund = pendingDistribution.filter(
|
|
1047
|
-
(pending) => pending.baseUrl !== baseUrl
|
|
1048
|
-
);
|
|
1049
1015
|
const apiKeysToRefund = apiKeyDistribution.filter(
|
|
1050
1016
|
(apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0
|
|
1051
1017
|
);
|
|
1052
|
-
const tokenRefundResults = await Promise.allSettled(
|
|
1053
|
-
toRefund.map(async (pending) => {
|
|
1054
|
-
const token = this.storageAdapter.getToken(pending.baseUrl);
|
|
1055
|
-
if (!token) {
|
|
1056
|
-
return { baseUrl: pending.baseUrl, success: false };
|
|
1057
|
-
}
|
|
1058
|
-
const tokenBalance = await this.getTokenBalance(token, pending.baseUrl);
|
|
1059
|
-
if (tokenBalance.reserved > 0) {
|
|
1060
|
-
return { baseUrl: pending.baseUrl, success: false };
|
|
1061
|
-
}
|
|
1062
|
-
const result = await this.refund({
|
|
1063
|
-
mintUrl,
|
|
1064
|
-
baseUrl: pending.baseUrl,
|
|
1065
|
-
token
|
|
1066
|
-
});
|
|
1067
|
-
return { baseUrl: pending.baseUrl, success: result.success };
|
|
1068
|
-
})
|
|
1069
|
-
);
|
|
1070
|
-
for (const result of tokenRefundResults) {
|
|
1071
|
-
if (result.status === "fulfilled" && result.value.success) {
|
|
1072
|
-
this.storageAdapter.removeToken(result.value.baseUrl);
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
1018
|
const apiKeyRefundResults = await Promise.allSettled(
|
|
1076
1019
|
apiKeysToRefund.map(async (apiKeyEntry) => {
|
|
1077
1020
|
const fullApiKeyEntry = this.storageAdapter.getApiKey(
|
|
@@ -1095,77 +1038,6 @@ var BalanceManager = class {
|
|
|
1095
1038
|
}
|
|
1096
1039
|
}
|
|
1097
1040
|
}
|
|
1098
|
-
/**
|
|
1099
|
-
* Fetch refund token from provider API
|
|
1100
|
-
*/
|
|
1101
|
-
async _fetchRefundToken(baseUrl, storedToken) {
|
|
1102
|
-
if (!baseUrl) {
|
|
1103
|
-
return {
|
|
1104
|
-
success: false,
|
|
1105
|
-
error: "No base URL configured"
|
|
1106
|
-
};
|
|
1107
|
-
}
|
|
1108
|
-
const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
1109
|
-
const url = `${normalizedBaseUrl}v1/wallet/refund`;
|
|
1110
|
-
const controller = new AbortController();
|
|
1111
|
-
const timeoutId = setTimeout(() => {
|
|
1112
|
-
controller.abort();
|
|
1113
|
-
}, 6e4);
|
|
1114
|
-
try {
|
|
1115
|
-
const response = await fetch(url, {
|
|
1116
|
-
method: "POST",
|
|
1117
|
-
headers: {
|
|
1118
|
-
Authorization: `Bearer ${storedToken}`,
|
|
1119
|
-
"Content-Type": "application/json"
|
|
1120
|
-
},
|
|
1121
|
-
signal: controller.signal
|
|
1122
|
-
});
|
|
1123
|
-
clearTimeout(timeoutId);
|
|
1124
|
-
const requestId = response.headers.get("x-routstr-request-id") || void 0;
|
|
1125
|
-
if (!response.ok) {
|
|
1126
|
-
const errorData = await response.json().catch(() => ({}));
|
|
1127
|
-
if (response.status === 400 && errorData?.detail === "No balance to refund") {
|
|
1128
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
1129
|
-
return {
|
|
1130
|
-
success: false,
|
|
1131
|
-
requestId,
|
|
1132
|
-
error: "No balance to refund"
|
|
1133
|
-
};
|
|
1134
|
-
}
|
|
1135
|
-
return {
|
|
1136
|
-
success: false,
|
|
1137
|
-
requestId,
|
|
1138
|
-
error: `Refund request failed with status ${response.status}: ${errorData?.detail || response.statusText}`
|
|
1139
|
-
};
|
|
1140
|
-
}
|
|
1141
|
-
const data = await response.json();
|
|
1142
|
-
console.log("refund rsule", data);
|
|
1143
|
-
return {
|
|
1144
|
-
success: true,
|
|
1145
|
-
token: data.token,
|
|
1146
|
-
requestId
|
|
1147
|
-
};
|
|
1148
|
-
} catch (error) {
|
|
1149
|
-
clearTimeout(timeoutId);
|
|
1150
|
-
console.error("[BalanceManager._fetchRefundToken] Fetch error", error);
|
|
1151
|
-
if (error instanceof Error) {
|
|
1152
|
-
if (error.name === "AbortError") {
|
|
1153
|
-
return {
|
|
1154
|
-
success: false,
|
|
1155
|
-
error: "Request timed out after 1 minute"
|
|
1156
|
-
};
|
|
1157
|
-
}
|
|
1158
|
-
return {
|
|
1159
|
-
success: false,
|
|
1160
|
-
error: error.message
|
|
1161
|
-
};
|
|
1162
|
-
}
|
|
1163
|
-
return {
|
|
1164
|
-
success: false,
|
|
1165
|
-
error: "Unknown error occurred during refund request"
|
|
1166
|
-
};
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
1041
|
/**
|
|
1170
1042
|
* Post topup request to provider API
|
|
1171
1043
|
*/
|
|
@@ -1291,7 +1163,7 @@ var BalanceManager = class {
|
|
|
1291
1163
|
console.log(response.status);
|
|
1292
1164
|
const data = await response.json();
|
|
1293
1165
|
console.log("FAILED ", data);
|
|
1294
|
-
const isInvalidApiKey = response.status === 401 && data?.code === "invalid_api_key" && data?.message?.includes("proofs already spent");
|
|
1166
|
+
const isInvalidApiKey = response.status === 401 && data?.detail?.error?.code === "invalid_api_key" && data?.detail?.error?.message?.includes("proofs already spent");
|
|
1295
1167
|
return {
|
|
1296
1168
|
amount: -1,
|
|
1297
1169
|
reserved: data.reserved ?? 0,
|