@routstr/sdk 0.3.3 → 0.3.5
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/dist/client/index.d.mts +9 -5
- package/dist/client/index.d.ts +9 -5
- package/dist/client/index.js +107 -136
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +107 -136
- package/dist/client/index.mjs.map +1 -1
- package/dist/discovery/index.d.mts +8 -2
- package/dist/discovery/index.d.ts +8 -2
- package/dist/discovery/index.js +27 -16
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +27 -16
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/index.d.mts +10 -8
- package/dist/index.d.ts +10 -8
- package/dist/index.js +179 -193
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +178 -194
- package/dist/index.mjs.map +1 -1
- package/dist/{interfaces-C5fLD3jB.d.mts → interfaces-Bp0Ngmqv.d.mts} +1 -1
- package/dist/{interfaces-BxDEka72.d.ts → interfaces-CIfd_phZ.d.ts} +1 -1
- package/dist/{interfaces-BWJJTCXO.d.mts → interfaces-Cxi8R4TT.d.mts} +1 -1
- package/dist/{interfaces-B62Rw-dd.d.ts → interfaces-D2FDCLyP.d.ts} +1 -1
- package/dist/storage/index.d.mts +9 -7
- package/dist/storage/index.d.ts +9 -7
- package/dist/storage/index.js +52 -37
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +52 -37
- package/dist/storage/index.mjs.map +1 -1
- package/dist/{store-h7m23ffq.d.ts → store-BD5zF9Hp.d.ts} +4 -4
- package/dist/{store-DGeLPv9E.d.mts → store-CBSyK2qg.d.mts} +4 -4
- package/dist/{types-BYj_8c5c.d.mts → types-DPQM6tIG.d.mts} +10 -1
- package/dist/{types-BYj_8c5c.d.ts → types-DPQM6tIG.d.ts} +10 -1
- package/dist/wallet/index.d.mts +8 -6
- package/dist/wallet/index.d.ts +8 -6
- package/dist/wallet/index.js +80 -57
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +80 -57
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/client/index.mjs
CHANGED
|
@@ -3,6 +3,19 @@ import { createStore } from 'zustand/vanilla';
|
|
|
3
3
|
import { Transform } from 'stream';
|
|
4
4
|
import { StringDecoder } from 'string_decoder';
|
|
5
5
|
|
|
6
|
+
// core/types.ts
|
|
7
|
+
function makeConsoleLogger(prefix) {
|
|
8
|
+
const fmt = (args) => prefix ? [prefix, ...args] : args;
|
|
9
|
+
return {
|
|
10
|
+
log: (...args) => console.log(...fmt(args)),
|
|
11
|
+
warn: (...args) => console.warn(...fmt(args)),
|
|
12
|
+
error: (...args) => console.error(...fmt(args)),
|
|
13
|
+
debug: (...args) => console.log(...fmt(args)),
|
|
14
|
+
child: (p) => makeConsoleLogger(prefix ? `${prefix}:${p}` : p)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
var consoleLogger = makeConsoleLogger();
|
|
18
|
+
|
|
6
19
|
// core/errors.ts
|
|
7
20
|
var InsufficientBalanceError = class extends Error {
|
|
8
21
|
constructor(required, available, maxMintBalance = 0, maxMintUrl = "", customMessage) {
|
|
@@ -102,14 +115,16 @@ function selectMintWithBalance(balances, units, amount, excludeMints = []) {
|
|
|
102
115
|
return { selectedMintUrl: null, selectedMintBalance: 0 };
|
|
103
116
|
}
|
|
104
117
|
var CashuSpender = class {
|
|
105
|
-
constructor(walletAdapter, storageAdapter, _providerRegistry, balanceManager) {
|
|
118
|
+
constructor(walletAdapter, storageAdapter, _providerRegistry, balanceManager, logger) {
|
|
106
119
|
this.walletAdapter = walletAdapter;
|
|
107
120
|
this.storageAdapter = storageAdapter;
|
|
108
121
|
this._providerRegistry = _providerRegistry;
|
|
109
122
|
this.balanceManager = balanceManager;
|
|
123
|
+
this.logger = (logger ?? consoleLogger).child("CashuSpender");
|
|
110
124
|
}
|
|
111
125
|
_isBusy = false;
|
|
112
126
|
debugLevel = "WARN";
|
|
127
|
+
logger;
|
|
113
128
|
async receiveToken(token) {
|
|
114
129
|
try {
|
|
115
130
|
const result = await this.walletAdapter.receiveToken(token);
|
|
@@ -205,13 +220,13 @@ var CashuSpender = class {
|
|
|
205
220
|
if (levelPriority[level] >= levelPriority[this.debugLevel]) {
|
|
206
221
|
switch (level) {
|
|
207
222
|
case "DEBUG":
|
|
208
|
-
|
|
223
|
+
this.logger.log(...args);
|
|
209
224
|
break;
|
|
210
225
|
case "WARN":
|
|
211
|
-
|
|
226
|
+
this.logger.warn(...args);
|
|
212
227
|
break;
|
|
213
228
|
case "ERROR":
|
|
214
|
-
|
|
229
|
+
this.logger.error(...args);
|
|
215
230
|
break;
|
|
216
231
|
}
|
|
217
232
|
}
|
|
@@ -559,19 +574,50 @@ var CashuSpender = class {
|
|
|
559
574
|
apiKeyEntry.baseUrl
|
|
560
575
|
);
|
|
561
576
|
if (apiKeyEntryFull && this.balanceManager) {
|
|
577
|
+
try {
|
|
578
|
+
const balanceResult = await this.balanceManager.getTokenBalance(
|
|
579
|
+
apiKeyEntryFull.key,
|
|
580
|
+
apiKeyEntry.baseUrl
|
|
581
|
+
);
|
|
582
|
+
if (balanceResult.isInvalidApiKey) {
|
|
583
|
+
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
584
|
+
results.push({
|
|
585
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
586
|
+
success: true
|
|
587
|
+
});
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
if (balanceResult.amount >= 0) {
|
|
591
|
+
const balanceSat = balanceResult.unit === "msat" ? Math.floor(balanceResult.amount / 1e3) : balanceResult.amount;
|
|
592
|
+
this.storageAdapter.updateApiKeyBalance(
|
|
593
|
+
apiKeyEntry.baseUrl,
|
|
594
|
+
balanceSat
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
} catch {
|
|
598
|
+
}
|
|
599
|
+
const refreshedEntry = this.storageAdapter.getApiKey(
|
|
600
|
+
apiKeyEntry.baseUrl
|
|
601
|
+
);
|
|
602
|
+
if (!refreshedEntry) continue;
|
|
562
603
|
const refundResult = await this.balanceManager.refundApiKey({
|
|
563
604
|
mintUrl,
|
|
564
605
|
baseUrl: apiKeyEntry.baseUrl,
|
|
565
|
-
apiKey:
|
|
606
|
+
apiKey: refreshedEntry.key,
|
|
566
607
|
forceRefund
|
|
567
608
|
});
|
|
568
609
|
if (refundResult.success) {
|
|
569
610
|
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
570
611
|
} else {
|
|
571
|
-
this.storageAdapter.
|
|
572
|
-
apiKeyEntry.baseUrl
|
|
573
|
-
apiKeyEntry.amount
|
|
612
|
+
const currentEntry = this.storageAdapter.getApiKey(
|
|
613
|
+
apiKeyEntry.baseUrl
|
|
574
614
|
);
|
|
615
|
+
if (currentEntry) {
|
|
616
|
+
this.storageAdapter.updateApiKeyBalance(
|
|
617
|
+
apiKeyEntry.baseUrl,
|
|
618
|
+
currentEntry.balance
|
|
619
|
+
);
|
|
620
|
+
}
|
|
575
621
|
}
|
|
576
622
|
results.push({
|
|
577
623
|
baseUrl: apiKeyEntry.baseUrl,
|
|
@@ -638,10 +684,11 @@ var CashuSpender = class {
|
|
|
638
684
|
|
|
639
685
|
// wallet/BalanceManager.ts
|
|
640
686
|
var BalanceManager = class _BalanceManager {
|
|
641
|
-
constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender) {
|
|
687
|
+
constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender, logger) {
|
|
642
688
|
this.walletAdapter = walletAdapter;
|
|
643
689
|
this.storageAdapter = storageAdapter;
|
|
644
690
|
this.providerRegistry = providerRegistry;
|
|
691
|
+
this.logger = (logger ?? consoleLogger).child("BalanceManager");
|
|
645
692
|
if (cashuSpender) {
|
|
646
693
|
this.cashuSpender = cashuSpender;
|
|
647
694
|
} else {
|
|
@@ -658,6 +705,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
658
705
|
providerWalletOps = /* @__PURE__ */ new Map();
|
|
659
706
|
/** Cooldown (ms) between opposite operations on the same provider */
|
|
660
707
|
static PROVIDER_WALLET_COOLDOWN_MS = 1e4;
|
|
708
|
+
logger;
|
|
661
709
|
/**
|
|
662
710
|
* Check whether a wallet operation (topup/refund) may run for a provider.
|
|
663
711
|
* Returns the reason when blocked.
|
|
@@ -732,7 +780,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
732
780
|
const { mintUrl, baseUrl, apiKey, forceRefund } = options;
|
|
733
781
|
const guard = this._canRunProviderWalletOperation(baseUrl, "refund");
|
|
734
782
|
if (!guard.allowed) {
|
|
735
|
-
|
|
783
|
+
this.logger.log(`Skipping refund for ${baseUrl} - ${guard.reason}`);
|
|
736
784
|
return { success: false, message: guard.reason };
|
|
737
785
|
}
|
|
738
786
|
this._beginProviderWalletOperation(baseUrl, "refund");
|
|
@@ -752,9 +800,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
752
800
|
if (apiKeyEntry?.lastUsed) {
|
|
753
801
|
const fiveMinutesAgo = Date.now() - 5 * 60 * 1e3;
|
|
754
802
|
if (apiKeyEntry.lastUsed > fiveMinutesAgo) {
|
|
755
|
-
|
|
756
|
-
`[BalanceManager] Skipping refund for ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1e3)}s ago`
|
|
757
|
-
);
|
|
803
|
+
this.logger.log(`Skipping refund for ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1e3)}s ago`);
|
|
758
804
|
return {
|
|
759
805
|
success: false,
|
|
760
806
|
message: "API key was used recently, skipping refund"
|
|
@@ -780,7 +826,8 @@ var BalanceManager = class _BalanceManager {
|
|
|
780
826
|
};
|
|
781
827
|
}
|
|
782
828
|
if (fetchResult.error === "No balance to refund") {
|
|
783
|
-
|
|
829
|
+
this.storageAdapter.removeApiKey(baseUrl);
|
|
830
|
+
return { success: true, message: "No balance to refund, key cleaned up" };
|
|
784
831
|
}
|
|
785
832
|
const receiveResult = await this.cashuSpender.receiveToken(
|
|
786
833
|
fetchResult.token
|
|
@@ -796,7 +843,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
796
843
|
requestId: fetchResult.requestId
|
|
797
844
|
};
|
|
798
845
|
} catch (error) {
|
|
799
|
-
|
|
846
|
+
this.logger.error("API key refund error", error);
|
|
800
847
|
return this._handleRefundError(error, mintUrl, fetchResult?.requestId);
|
|
801
848
|
}
|
|
802
849
|
}
|
|
@@ -848,7 +895,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
848
895
|
};
|
|
849
896
|
} catch (error) {
|
|
850
897
|
clearTimeout(timeoutId);
|
|
851
|
-
|
|
898
|
+
this.logger.error("fetchRefundToken fetch error", error);
|
|
852
899
|
if (error instanceof Error) {
|
|
853
900
|
if (error.name === "AbortError") {
|
|
854
901
|
return {
|
|
@@ -874,7 +921,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
874
921
|
const { mintUrl, baseUrl, amount, token: providedToken } = options;
|
|
875
922
|
const guard = this._canRunProviderWalletOperation(baseUrl, "topup");
|
|
876
923
|
if (!guard.allowed) {
|
|
877
|
-
|
|
924
|
+
this.logger.log(`Skipping topup for ${baseUrl} - ${guard.reason}`);
|
|
878
925
|
return { success: false, message: guard.reason };
|
|
879
926
|
}
|
|
880
927
|
this._beginProviderWalletOperation(baseUrl, "topup");
|
|
@@ -911,7 +958,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
911
958
|
cashuToken = tokenResult.token;
|
|
912
959
|
const topUpResult = await this._postTopUp(baseUrl, apiKey, cashuToken);
|
|
913
960
|
requestId = topUpResult.requestId;
|
|
914
|
-
|
|
961
|
+
this.logger.log("topUpResult:", topUpResult);
|
|
915
962
|
if (!topUpResult.success) {
|
|
916
963
|
await this._recoverFailedTopUp(cashuToken);
|
|
917
964
|
return {
|
|
@@ -927,10 +974,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
927
974
|
requestId
|
|
928
975
|
};
|
|
929
976
|
} catch (error) {
|
|
930
|
-
|
|
931
|
-
"DEBUG",
|
|
932
|
-
`[TopuPU] topup: Topup result for ${baseUrl}: error=${error}`
|
|
933
|
-
);
|
|
977
|
+
this.logger.log(`topup error for ${baseUrl}: ${error}`);
|
|
934
978
|
if (cashuToken) {
|
|
935
979
|
await this._recoverFailedTopUp(cashuToken);
|
|
936
980
|
}
|
|
@@ -947,13 +991,9 @@ var BalanceManager = class _BalanceManager {
|
|
|
947
991
|
p2pkPubkey
|
|
948
992
|
} = options;
|
|
949
993
|
const adjustedAmount = Math.ceil(amount);
|
|
950
|
-
|
|
951
|
-
`[BalanceManager.createProviderToken] Starting: baseUrl=${baseUrl}, mintUrl=${mintUrl}, amount=${amount}, adjustedAmount=${adjustedAmount}, retryCount=${retryCount}`
|
|
952
|
-
);
|
|
994
|
+
this.logger.log(`createProviderToken: baseUrl=${baseUrl} mintUrl=${mintUrl} amount=${amount} adjustedAmount=${adjustedAmount} retryCount=${retryCount}`);
|
|
953
995
|
if (!adjustedAmount || isNaN(adjustedAmount)) {
|
|
954
|
-
|
|
955
|
-
`[BalanceManager.createProviderToken] FAILURE: Invalid amount - amount=${amount}, adjustedAmount=${adjustedAmount}`
|
|
956
|
-
);
|
|
996
|
+
this.logger.error(`createProviderToken: invalid amount=${amount}`);
|
|
957
997
|
return { success: false, error: "Invalid top up amount" };
|
|
958
998
|
}
|
|
959
999
|
const balanceState = await this.getBalanceState();
|
|
@@ -984,9 +1024,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
984
1024
|
{ url: "", balance: 0 }
|
|
985
1025
|
).url
|
|
986
1026
|
);
|
|
987
|
-
|
|
988
|
-
`[BalanceManager.createProviderToken] FAILURE: Insufficient balance - required=${adjustedAmount}, available=${totalMintBalance + targetProviderBalance}, totalMintBalance=${totalMintBalance}, targetProviderBalance=${targetProviderBalance}, refundableProviderBalance=${refundableProviderBalance}`
|
|
989
|
-
);
|
|
1027
|
+
this.logger.error(`createProviderToken: insufficient balance required=${adjustedAmount} available=${totalMintBalance + targetProviderBalance} totalMint=${totalMintBalance} targetProvider=${targetProviderBalance}`);
|
|
990
1028
|
return { success: false, error: error.message };
|
|
991
1029
|
}
|
|
992
1030
|
const providerMints = baseUrl && this.providerRegistry ? this.providerRegistry.getProviderMints(baseUrl) : [];
|
|
@@ -1022,9 +1060,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1022
1060
|
maxMintUrl = mintUrl2;
|
|
1023
1061
|
}
|
|
1024
1062
|
}
|
|
1025
|
-
|
|
1026
|
-
`[BalanceManager.createProviderToken] FAILURE: No candidate mints found - requiredAmount=${requiredAmount}, totalMintBalance=${totalMintBalance}, maxBalance=${maxBalance}, maxMintUrl=${maxMintUrl}, providerMints=${JSON.stringify(providerMints)}`
|
|
1027
|
-
);
|
|
1063
|
+
this.logger.error(`createProviderToken: no candidate mints required=${requiredAmount} totalMint=${totalMintBalance} maxBalance=${maxBalance} maxMint=${maxMintUrl}`);
|
|
1028
1064
|
const error = new InsufficientBalanceError(
|
|
1029
1065
|
adjustedAmount,
|
|
1030
1066
|
totalMintBalance,
|
|
@@ -1036,17 +1072,13 @@ var BalanceManager = class _BalanceManager {
|
|
|
1036
1072
|
let lastError;
|
|
1037
1073
|
for (const candidateMint of candidates) {
|
|
1038
1074
|
try {
|
|
1039
|
-
|
|
1040
|
-
`[BalanceManager.createProviderToken] Attempting mint: ${candidateMint}, amount: ${requiredAmount}`
|
|
1041
|
-
);
|
|
1075
|
+
this.logger.log(`createProviderToken: attempting mint=${candidateMint} amount=${requiredAmount}`);
|
|
1042
1076
|
const token = await this.walletAdapter.sendToken(
|
|
1043
1077
|
candidateMint,
|
|
1044
1078
|
requiredAmount,
|
|
1045
1079
|
p2pkPubkey
|
|
1046
1080
|
);
|
|
1047
|
-
|
|
1048
|
-
`[BalanceManager.createProviderToken] SUCCESS: Token created from mint ${candidateMint}, all mint balances: ${JSON.stringify(Object.fromEntries(Object.entries(balances).map(([mint, balance]) => [mint, getBalanceInSats(balance, units[mint])])))}`
|
|
1049
|
-
);
|
|
1081
|
+
this.logger.log(`createProviderToken: success from mint=${candidateMint}`);
|
|
1050
1082
|
return {
|
|
1051
1083
|
success: true,
|
|
1052
1084
|
token,
|
|
@@ -1055,15 +1087,11 @@ var BalanceManager = class _BalanceManager {
|
|
|
1055
1087
|
};
|
|
1056
1088
|
} catch (error) {
|
|
1057
1089
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1058
|
-
|
|
1059
|
-
`[BalanceManager.createProviderToken] FAILURE: Mint ${candidateMint} failed with error: ${errorMsg}`
|
|
1060
|
-
);
|
|
1090
|
+
this.logger.error(`createProviderToken: mint=${candidateMint} failed: ${errorMsg}`);
|
|
1061
1091
|
if (error instanceof Error) {
|
|
1062
1092
|
lastError = errorMsg;
|
|
1063
1093
|
if (isNetworkErrorMessage(error.message)) {
|
|
1064
|
-
|
|
1065
|
-
`[BalanceManager.createProviderToken] Network error from ${candidateMint}, trying next mint...`
|
|
1066
|
-
);
|
|
1094
|
+
this.logger.warn(`createProviderToken: network error from ${candidateMint}, trying next mint...`);
|
|
1067
1095
|
continue;
|
|
1068
1096
|
}
|
|
1069
1097
|
}
|
|
@@ -1073,9 +1101,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1073
1101
|
};
|
|
1074
1102
|
}
|
|
1075
1103
|
}
|
|
1076
|
-
|
|
1077
|
-
`[BalanceManager.createProviderToken] FAILURE: All candidate mints exhausted - lastError=${lastError}, candidates=${JSON.stringify(candidates)}`
|
|
1078
|
-
);
|
|
1104
|
+
this.logger.error(`createProviderToken: all candidate mints exhausted lastError=${lastError}`);
|
|
1079
1105
|
return {
|
|
1080
1106
|
success: false,
|
|
1081
1107
|
error: lastError || "All candidate mints failed while creating top up token"
|
|
@@ -1190,7 +1216,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1190
1216
|
return { success: true, requestId };
|
|
1191
1217
|
} catch (error) {
|
|
1192
1218
|
clearTimeout(timeoutId);
|
|
1193
|
-
|
|
1219
|
+
this.logger.error("_postTopUp fetch error", error);
|
|
1194
1220
|
if (error instanceof Error) {
|
|
1195
1221
|
if (error.name === "AbortError") {
|
|
1196
1222
|
return {
|
|
@@ -1216,10 +1242,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1216
1242
|
try {
|
|
1217
1243
|
await this.cashuSpender.receiveToken(cashuToken);
|
|
1218
1244
|
} catch (error) {
|
|
1219
|
-
|
|
1220
|
-
"[BalanceManager._recoverFailedTopUp] Failed to recover token",
|
|
1221
|
-
error
|
|
1222
|
-
);
|
|
1245
|
+
this.logger.error("_recoverFailedTopUp: failed to recover token", error);
|
|
1223
1246
|
}
|
|
1224
1247
|
}
|
|
1225
1248
|
/**
|
|
@@ -1272,9 +1295,9 @@ var BalanceManager = class _BalanceManager {
|
|
|
1272
1295
|
apiKey: data.api_key
|
|
1273
1296
|
};
|
|
1274
1297
|
} else {
|
|
1275
|
-
|
|
1298
|
+
this.logger.warn(`getTokenBalance: status=${response.status}`);
|
|
1276
1299
|
const data = await response.json();
|
|
1277
|
-
|
|
1300
|
+
this.logger.warn("getTokenBalance: FAILED", data);
|
|
1278
1301
|
const isInvalidApiKey = response.status === 401 && data?.detail?.error?.code === "invalid_api_key" && data?.detail?.error?.message?.includes("proofs already spent");
|
|
1279
1302
|
return {
|
|
1280
1303
|
amount: -1,
|
|
@@ -1285,7 +1308,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1285
1308
|
};
|
|
1286
1309
|
}
|
|
1287
1310
|
} catch (error) {
|
|
1288
|
-
|
|
1311
|
+
this.logger.error("getTokenBalance error", error);
|
|
1289
1312
|
}
|
|
1290
1313
|
return { amount: -1, reserved: 0, unit: "sat", apiKey: "" };
|
|
1291
1314
|
}
|
|
@@ -1751,9 +1774,10 @@ function isInsecureHttpUrl(url) {
|
|
|
1751
1774
|
return url.startsWith("http://");
|
|
1752
1775
|
}
|
|
1753
1776
|
var ProviderManager = class _ProviderManager {
|
|
1754
|
-
constructor(providerRegistry, store) {
|
|
1777
|
+
constructor(providerRegistry, store, logger) {
|
|
1755
1778
|
this.providerRegistry = providerRegistry;
|
|
1756
1779
|
this.instanceId = `pm_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1780
|
+
this.logger = (logger ?? consoleLogger).child(`ProviderManager:${this.instanceId}`);
|
|
1757
1781
|
if (store) {
|
|
1758
1782
|
this.store = store;
|
|
1759
1783
|
this.hydrateFromStore();
|
|
@@ -1770,6 +1794,7 @@ var ProviderManager = class _ProviderManager {
|
|
|
1770
1794
|
store = null;
|
|
1771
1795
|
/** Instance ID for debugging */
|
|
1772
1796
|
instanceId;
|
|
1797
|
+
logger;
|
|
1773
1798
|
/**
|
|
1774
1799
|
* Hydrate in-memory state from persistent store
|
|
1775
1800
|
*/
|
|
@@ -1782,10 +1807,7 @@ var ProviderManager = class _ProviderManager {
|
|
|
1782
1807
|
this.providersOnCoolDown = state.providersOnCooldown.filter(
|
|
1783
1808
|
(entry) => now - entry.timestamp < _ProviderManager.COOLDOWN_DURATION_MS
|
|
1784
1809
|
).map((entry) => [entry.baseUrl, entry.timestamp]);
|
|
1785
|
-
|
|
1786
|
-
console.log(` failedProviders: ${this.failedProviders.size}`);
|
|
1787
|
-
console.log(` lastFailed: ${this.lastFailed.size}`);
|
|
1788
|
-
console.log(` providersOnCooldown: ${this.providersOnCoolDown.length}`);
|
|
1810
|
+
this.logger.log(`Hydrated from store: failedProviders=${this.failedProviders.size} lastFailed=${this.lastFailed.size} providersOnCooldown=${this.providersOnCoolDown.length}`);
|
|
1789
1811
|
}
|
|
1790
1812
|
/**
|
|
1791
1813
|
* Get instance ID for debugging
|
|
@@ -1805,9 +1827,7 @@ var ProviderManager = class _ProviderManager {
|
|
|
1805
1827
|
const age = now - timestamp;
|
|
1806
1828
|
const isExpired = age >= _ProviderManager.COOLDOWN_DURATION_MS;
|
|
1807
1829
|
if (isExpired) {
|
|
1808
|
-
|
|
1809
|
-
`[cleanupExpiredCooldowns:${this.instanceId}] Removing expired cooldown for ${url} (age: ${age}ms, cooldown: ${_ProviderManager.COOLDOWN_DURATION_MS}ms)`
|
|
1810
|
-
);
|
|
1830
|
+
this.logger.log(`Removing expired cooldown for ${url} (age: ${age}ms)`);
|
|
1811
1831
|
this.failedProviders.delete(url);
|
|
1812
1832
|
if (this.store) {
|
|
1813
1833
|
this.store.getState().removeFailedProvider(url);
|
|
@@ -1818,9 +1838,7 @@ var ProviderManager = class _ProviderManager {
|
|
|
1818
1838
|
);
|
|
1819
1839
|
const after = this.providersOnCoolDown.length;
|
|
1820
1840
|
if (before !== after) {
|
|
1821
|
-
|
|
1822
|
-
`[cleanupExpiredCooldowns:${this.instanceId}] Cleaned up ${before - after} expired cooldown(s), ${after} remaining`
|
|
1823
|
-
);
|
|
1841
|
+
this.logger.log(`Cleaned up ${before - after} expired cooldown(s), ${after} remaining`);
|
|
1824
1842
|
}
|
|
1825
1843
|
}
|
|
1826
1844
|
/**
|
|
@@ -1872,24 +1890,10 @@ var ProviderManager = class _ProviderManager {
|
|
|
1872
1890
|
markFailed(baseUrl) {
|
|
1873
1891
|
const now = Date.now();
|
|
1874
1892
|
const lastFailure = this.lastFailed.get(baseUrl);
|
|
1875
|
-
|
|
1876
|
-
console.log(
|
|
1877
|
-
`[markFailed:${this.instanceId}] lastFailure from map: ${lastFailure}`
|
|
1878
|
-
);
|
|
1879
|
-
console.log(
|
|
1880
|
-
`[markFailed:${this.instanceId}] current timestamp (now): ${now}`
|
|
1881
|
-
);
|
|
1882
|
-
console.log(
|
|
1883
|
-
`[markFailed:${this.instanceId}] COOLDOWN_DURATION_MS: ${_ProviderManager.COOLDOWN_DURATION_MS}`
|
|
1884
|
-
);
|
|
1893
|
+
this.logger.log(`markFailed: ${baseUrl} lastFailure=${lastFailure} now=${now}`);
|
|
1885
1894
|
if (lastFailure !== void 0) {
|
|
1886
1895
|
const timeSinceLastFailure = now - lastFailure;
|
|
1887
|
-
|
|
1888
|
-
`[markFailed:${this.instanceId}] timeSinceLastFailure: ${timeSinceLastFailure}ms`
|
|
1889
|
-
);
|
|
1890
|
-
console.log(
|
|
1891
|
-
`[markFailed:${this.instanceId}] isWithinCooldownWindow: ${timeSinceLastFailure < _ProviderManager.COOLDOWN_DURATION_MS}`
|
|
1892
|
-
);
|
|
1896
|
+
this.logger.log(`markFailed: timeSinceLastFailure=${timeSinceLastFailure}ms withinCooldown=${timeSinceLastFailure < _ProviderManager.COOLDOWN_DURATION_MS}`);
|
|
1893
1897
|
}
|
|
1894
1898
|
this.lastFailed.set(baseUrl, now);
|
|
1895
1899
|
this.failedProviders.add(baseUrl);
|
|
@@ -1897,38 +1901,23 @@ var ProviderManager = class _ProviderManager {
|
|
|
1897
1901
|
this.store.getState().setLastFailedTimestamp(baseUrl, now);
|
|
1898
1902
|
this.store.getState().addFailedProvider(baseUrl);
|
|
1899
1903
|
}
|
|
1900
|
-
|
|
1901
|
-
`[markFailed:${this.instanceId}] Updated lastFailed map for ${baseUrl} to ${now}`
|
|
1902
|
-
);
|
|
1903
|
-
console.log(
|
|
1904
|
-
`[markFailed:${this.instanceId}] failedProviders set size: ${this.failedProviders.size}`
|
|
1905
|
-
);
|
|
1904
|
+
this.logger.log(`markFailed: updated ${baseUrl} to ${now}, failedProviders=${this.failedProviders.size}`);
|
|
1906
1905
|
if (lastFailure !== void 0 && now - lastFailure < _ProviderManager.COOLDOWN_DURATION_MS) {
|
|
1907
|
-
|
|
1908
|
-
`[markFailed:${this.instanceId}] Second failure detected within cooldown window for ${baseUrl}`
|
|
1909
|
-
);
|
|
1906
|
+
this.logger.log(`markFailed: second failure within cooldown window for ${baseUrl}`);
|
|
1910
1907
|
if (!this.isOnCooldown(baseUrl)) {
|
|
1911
1908
|
this.providersOnCoolDown.push([baseUrl, now]);
|
|
1912
1909
|
if (this.store) {
|
|
1913
1910
|
this.store.getState().addProviderOnCooldown(baseUrl, now);
|
|
1914
1911
|
}
|
|
1915
|
-
|
|
1916
|
-
`[markFailed:${this.instanceId}] Provider ${baseUrl} added to cooldown after second failure within 5 minutes`
|
|
1917
|
-
);
|
|
1912
|
+
this.logger.log(`markFailed: ${baseUrl} added to cooldown`);
|
|
1918
1913
|
} else {
|
|
1919
|
-
|
|
1920
|
-
`[markFailed:${this.instanceId}] Provider ${baseUrl} is already on cooldown`
|
|
1921
|
-
);
|
|
1914
|
+
this.logger.log(`markFailed: ${baseUrl} already on cooldown`);
|
|
1922
1915
|
}
|
|
1923
1916
|
} else {
|
|
1924
1917
|
if (lastFailure === void 0) {
|
|
1925
|
-
|
|
1926
|
-
`[markFailed:${this.instanceId}] First failure for ${baseUrl} - not adding to cooldown yet`
|
|
1927
|
-
);
|
|
1918
|
+
this.logger.log(`markFailed: first failure for ${baseUrl}`);
|
|
1928
1919
|
} else {
|
|
1929
|
-
|
|
1930
|
-
`[markFailed:${this.instanceId}] Failure outside cooldown window for ${baseUrl} (timeSinceLastFailure: ${now - lastFailure}ms)`
|
|
1931
|
-
);
|
|
1920
|
+
this.logger.log(`markFailed: failure outside cooldown window for ${baseUrl} (${now - lastFailure}ms ago)`);
|
|
1932
1921
|
}
|
|
1933
1922
|
}
|
|
1934
1923
|
}
|
|
@@ -1985,25 +1974,12 @@ var ProviderManager = class _ProviderManager {
|
|
|
1985
1974
|
const disabledProviders = new Set(
|
|
1986
1975
|
this.providerRegistry.getDisabledProviders()
|
|
1987
1976
|
);
|
|
1988
|
-
|
|
1989
|
-
`[findNextBestProvider:${this.instanceId}] Starting search for model: ${modelId}`
|
|
1990
|
-
);
|
|
1991
|
-
console.log(
|
|
1992
|
-
`[findNextBestProvider:${this.instanceId}] disabledProviders: ${[...disabledProviders]}`
|
|
1993
|
-
);
|
|
1994
|
-
console.log(
|
|
1995
|
-
`[findNextBestProvider:${this.instanceId}] providersOnCooldown: ${this.providersOnCoolDown.map(([url]) => url)}`
|
|
1996
|
-
);
|
|
1977
|
+
this.logger.log(`findNextBestProvider: model=${modelId} disabled=${[...disabledProviders].length} onCooldown=${this.providersOnCoolDown.length}`);
|
|
1997
1978
|
const allProviders = this.providerRegistry.getAllProvidersModels();
|
|
1998
|
-
|
|
1999
|
-
`[findNextBestProvider:${this.instanceId}] Total providers in registry: ${Object.keys(allProviders).length}`
|
|
2000
|
-
);
|
|
1979
|
+
this.logger.log(`findNextBestProvider: total providers=${Object.keys(allProviders).length}`);
|
|
2001
1980
|
const candidates = [];
|
|
2002
1981
|
for (const [baseUrl, models] of Object.entries(allProviders)) {
|
|
2003
1982
|
if (baseUrl === currentBaseUrl) {
|
|
2004
|
-
console.log(
|
|
2005
|
-
`[findNextBestProvider:${this.instanceId}] SKIP (current): ${baseUrl}`
|
|
2006
|
-
);
|
|
2007
1983
|
continue;
|
|
2008
1984
|
}
|
|
2009
1985
|
if (disabledProviders.has(baseUrl)) {
|
|
@@ -2029,7 +2005,7 @@ var ProviderManager = class _ProviderManager {
|
|
|
2029
2005
|
return null;
|
|
2030
2006
|
}
|
|
2031
2007
|
} catch (error) {
|
|
2032
|
-
|
|
2008
|
+
this.logger.error("findNextBestProvider error:", error);
|
|
2033
2009
|
return null;
|
|
2034
2010
|
}
|
|
2035
2011
|
}
|
|
@@ -2156,16 +2132,9 @@ var ProviderManager = class _ProviderManager {
|
|
|
2156
2132
|
res.height
|
|
2157
2133
|
);
|
|
2158
2134
|
imageTokens += tokensFromImage;
|
|
2159
|
-
|
|
2160
|
-
width: res.width,
|
|
2161
|
-
height: res.height,
|
|
2162
|
-
tokensFromImage
|
|
2163
|
-
});
|
|
2135
|
+
this.logger.log(`IMAGE INPUT RESOLUTION width=${res.width} height=${res.height} tokens=${tokensFromImage}`);
|
|
2164
2136
|
} else {
|
|
2165
|
-
|
|
2166
|
-
"IMAGE INPUT RESOLUTION",
|
|
2167
|
-
"unknown (unsupported format or parse failure)"
|
|
2168
|
-
);
|
|
2137
|
+
this.logger.log("IMAGE INPUT RESOLUTION: unknown format");
|
|
2169
2138
|
}
|
|
2170
2139
|
}
|
|
2171
2140
|
}
|
|
@@ -2198,7 +2167,7 @@ var ProviderManager = class _ProviderManager {
|
|
|
2198
2167
|
const totalEstimatedCosts = (promptCosts + completionCost) * 1.05;
|
|
2199
2168
|
return totalEstimatedCosts;
|
|
2200
2169
|
} catch (e) {
|
|
2201
|
-
|
|
2170
|
+
this.logger.error("getRequiredSatsForModel error:", e);
|
|
2202
2171
|
return 0;
|
|
2203
2172
|
}
|
|
2204
2173
|
}
|
|
@@ -3695,6 +3664,7 @@ var RoutstrClient = class {
|
|
|
3695
3664
|
this.walletAdapter = walletAdapter;
|
|
3696
3665
|
this.storageAdapter = storageAdapter;
|
|
3697
3666
|
this.providerRegistry = providerRegistry;
|
|
3667
|
+
this.logger = (options.logger ?? consoleLogger).child("RoutstrClient");
|
|
3698
3668
|
this.balanceManager = new BalanceManager(
|
|
3699
3669
|
walletAdapter,
|
|
3700
3670
|
storageAdapter,
|
|
@@ -3711,7 +3681,7 @@ var RoutstrClient = class {
|
|
|
3711
3681
|
this.mode = mode;
|
|
3712
3682
|
this.usageTrackingDriver = options.usageTrackingDriver;
|
|
3713
3683
|
this.sdkStore = options.sdkStore;
|
|
3714
|
-
this.providerManager = options.providerManager ?? new ProviderManager(providerRegistry, this.sdkStore);
|
|
3684
|
+
this.providerManager = options.providerManager ?? new ProviderManager(providerRegistry, this.sdkStore, this.logger);
|
|
3715
3685
|
}
|
|
3716
3686
|
cashuSpender;
|
|
3717
3687
|
balanceManager;
|
|
@@ -3722,6 +3692,7 @@ var RoutstrClient = class {
|
|
|
3722
3692
|
debugLevel = "WARN";
|
|
3723
3693
|
usageTrackingDriver;
|
|
3724
3694
|
sdkStore;
|
|
3695
|
+
logger;
|
|
3725
3696
|
/**
|
|
3726
3697
|
* Get the current client mode
|
|
3727
3698
|
*/
|
|
@@ -3743,13 +3714,13 @@ var RoutstrClient = class {
|
|
|
3743
3714
|
if (levelPriority[level] >= levelPriority[this.debugLevel]) {
|
|
3744
3715
|
switch (level) {
|
|
3745
3716
|
case "DEBUG":
|
|
3746
|
-
|
|
3717
|
+
this.logger.log(...args);
|
|
3747
3718
|
break;
|
|
3748
3719
|
case "WARN":
|
|
3749
|
-
|
|
3720
|
+
this.logger.warn(...args);
|
|
3750
3721
|
break;
|
|
3751
3722
|
case "ERROR":
|
|
3752
|
-
|
|
3723
|
+
this.logger.error(...args);
|
|
3753
3724
|
break;
|
|
3754
3725
|
}
|
|
3755
3726
|
}
|
|
@@ -4353,7 +4324,7 @@ var RoutstrClient = class {
|
|
|
4353
4324
|
tryNextProvider = true;
|
|
4354
4325
|
}
|
|
4355
4326
|
}
|
|
4356
|
-
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 429 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
4327
|
+
if ((status === 401 || status === 403 || status === 404 || status === 413 || status === 400 || status === 429 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
4357
4328
|
this._log(
|
|
4358
4329
|
"DEBUG",
|
|
4359
4330
|
`[RoutstrClient] _handleErrorResponse: Status ${status} (${status === 429 ? "rate limited" : "auth/server error"}), attempting refund for ${baseUrl}, mode=${this.mode}`
|