@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/index.js
CHANGED
|
@@ -4,16 +4,8 @@ var applesauceRelay = require('applesauce-relay');
|
|
|
4
4
|
var applesauceCore = require('applesauce-core');
|
|
5
5
|
var rxjs = require('rxjs');
|
|
6
6
|
var vanilla = require('zustand/vanilla');
|
|
7
|
-
var cashuTs = require('@cashu/cashu-ts');
|
|
8
7
|
var stream = require('stream');
|
|
9
8
|
|
|
10
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
11
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
12
|
-
}) : x)(function(x) {
|
|
13
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
14
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
15
|
-
});
|
|
16
|
-
|
|
17
9
|
// core/errors.ts
|
|
18
10
|
var InsufficientBalanceError = class extends Error {
|
|
19
11
|
constructor(required, available, maxMintBalance = 0, maxMintUrl = "", customMessage) {
|
|
@@ -476,7 +468,7 @@ var ModelManager = class _ModelManager {
|
|
|
476
468
|
}
|
|
477
469
|
}
|
|
478
470
|
const DEFAULT_RELAYS = [
|
|
479
|
-
"wss://relay.
|
|
471
|
+
"wss://relay.damus.io",
|
|
480
472
|
"wss://nos.lol",
|
|
481
473
|
"wss://relay.routstr.com"
|
|
482
474
|
];
|
|
@@ -788,13 +780,8 @@ var CashuSpender = class {
|
|
|
788
780
|
normalizedMintBalances[url] = balanceInSats;
|
|
789
781
|
totalMintBalance += balanceInSats;
|
|
790
782
|
}
|
|
791
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
792
783
|
const providerBalances = {};
|
|
793
784
|
let totalProviderBalance = 0;
|
|
794
|
-
for (const pending of pendingDistribution) {
|
|
795
|
-
providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
|
|
796
|
-
totalProviderBalance += pending.amount;
|
|
797
|
-
}
|
|
798
785
|
const apiKeys = this.storageAdapter.getAllApiKeys();
|
|
799
786
|
for (const apiKey of apiKeys) {
|
|
800
787
|
if (!providerBalances[apiKey.baseUrl]) {
|
|
@@ -1015,27 +1002,11 @@ var CashuSpender = class {
|
|
|
1015
1002
|
};
|
|
1016
1003
|
}
|
|
1017
1004
|
}
|
|
1018
|
-
if (token
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
this._log(
|
|
1024
|
-
"DEBUG",
|
|
1025
|
-
`[CashuSpender] _spendInternal: Token already exists for ${baseUrl}, receiving newly created token and using existing`
|
|
1026
|
-
);
|
|
1027
|
-
const receiveResult = await this.receiveToken(token);
|
|
1028
|
-
if (receiveResult.success) {
|
|
1029
|
-
this._log(
|
|
1030
|
-
"DEBUG",
|
|
1031
|
-
`[CashuSpender] _spendInternal: Token restored successfully, amount=${receiveResult.amount}`
|
|
1032
|
-
);
|
|
1033
|
-
}
|
|
1034
|
-
token = this.storageAdapter.getToken(baseUrl);
|
|
1035
|
-
} else {
|
|
1036
|
-
throw error;
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1005
|
+
if (token) {
|
|
1006
|
+
this._log(
|
|
1007
|
+
"DEBUG",
|
|
1008
|
+
`[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`
|
|
1009
|
+
);
|
|
1039
1010
|
}
|
|
1040
1011
|
this._logTransaction("spend", {
|
|
1041
1012
|
amount: spentAmount,
|
|
@@ -1056,19 +1027,19 @@ var CashuSpender = class {
|
|
|
1056
1027
|
};
|
|
1057
1028
|
}
|
|
1058
1029
|
/**
|
|
1059
|
-
* Try to reuse an existing
|
|
1030
|
+
* Try to reuse an existing API key
|
|
1060
1031
|
*/
|
|
1061
1032
|
async _tryReuseToken(baseUrl, amount, mintUrl) {
|
|
1062
|
-
const
|
|
1063
|
-
if (!
|
|
1064
|
-
const
|
|
1065
|
-
const balanceForBaseUrl =
|
|
1066
|
-
this._log("DEBUG", "
|
|
1033
|
+
const apiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
|
|
1034
|
+
if (!apiKeyEntry) return null;
|
|
1035
|
+
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
1036
|
+
const balanceForBaseUrl = apiKeyDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
|
|
1037
|
+
this._log("DEBUG", "Reusing API key", balanceForBaseUrl, amount);
|
|
1067
1038
|
if (balanceForBaseUrl > amount) {
|
|
1068
1039
|
const units = this.walletAdapter.getMintUnits();
|
|
1069
1040
|
const unit = units[mintUrl] || "sat";
|
|
1070
1041
|
return {
|
|
1071
|
-
token:
|
|
1042
|
+
token: apiKeyEntry.key,
|
|
1072
1043
|
status: "success",
|
|
1073
1044
|
balance: balanceForBaseUrl,
|
|
1074
1045
|
unit
|
|
@@ -1079,7 +1050,8 @@ var CashuSpender = class {
|
|
|
1079
1050
|
const topUpResult = await this.balanceManager.topUp({
|
|
1080
1051
|
mintUrl,
|
|
1081
1052
|
baseUrl,
|
|
1082
|
-
amount: topUpAmount
|
|
1053
|
+
amount: topUpAmount,
|
|
1054
|
+
token: apiKeyEntry.key
|
|
1083
1055
|
});
|
|
1084
1056
|
this._log("DEBUG", "TOPUP ", topUpResult);
|
|
1085
1057
|
if (topUpResult.success && topUpResult.toppedUpAmount) {
|
|
@@ -1093,7 +1065,7 @@ var CashuSpender = class {
|
|
|
1093
1065
|
status: "success"
|
|
1094
1066
|
});
|
|
1095
1067
|
return {
|
|
1096
|
-
token:
|
|
1068
|
+
token: apiKeyEntry.key,
|
|
1097
1069
|
status: "success",
|
|
1098
1070
|
balance: newBalance,
|
|
1099
1071
|
unit
|
|
@@ -1101,84 +1073,131 @@ var CashuSpender = class {
|
|
|
1101
1073
|
}
|
|
1102
1074
|
const providerBalance = await this._getProviderTokenBalance(
|
|
1103
1075
|
baseUrl,
|
|
1104
|
-
|
|
1076
|
+
apiKeyEntry.key
|
|
1105
1077
|
);
|
|
1106
1078
|
this._log("DEBUG", providerBalance);
|
|
1107
1079
|
if (providerBalance <= 0) {
|
|
1108
|
-
this.storageAdapter.
|
|
1080
|
+
this.storageAdapter.removeApiKey(baseUrl);
|
|
1109
1081
|
}
|
|
1110
1082
|
}
|
|
1111
1083
|
return null;
|
|
1112
1084
|
}
|
|
1113
1085
|
/**
|
|
1114
|
-
* Refund
|
|
1086
|
+
* Refund all xcashu tokens from storage by calling the provider's refund endpoint.
|
|
1087
|
+
* The xcashu token acts as an API key to claim the refund, and the response contains
|
|
1088
|
+
* the actual refunded Cashu token which is then received into the wallet.
|
|
1089
|
+
* @param mintUrl - The mint URL for receiving tokens
|
|
1090
|
+
* @param excludeBaseUrls - Base URLs to exclude from refund (optional)
|
|
1091
|
+
* @returns Results for each xcashu token refund attempt
|
|
1115
1092
|
*/
|
|
1116
|
-
async
|
|
1093
|
+
async refundXcashuTokens(mintUrl, excludeBaseUrls) {
|
|
1117
1094
|
const results = [];
|
|
1118
|
-
const
|
|
1119
|
-
const
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
apiKey: apiKeyEntryFull.key,
|
|
1167
|
-
forceRefund
|
|
1168
|
-
});
|
|
1169
|
-
if (refundResult.success) {
|
|
1170
|
-
this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, 0);
|
|
1095
|
+
const xcashuTokens = this.storageAdapter.getXcashuTokens();
|
|
1096
|
+
const excludedUrls = new Set(excludeBaseUrls || []);
|
|
1097
|
+
for (const [baseUrl, tokens] of Object.entries(xcashuTokens)) {
|
|
1098
|
+
if (excludedUrls.has(baseUrl)) continue;
|
|
1099
|
+
for (const xcashuToken of tokens) {
|
|
1100
|
+
try {
|
|
1101
|
+
if (!this.balanceManager) {
|
|
1102
|
+
throw new Error("BalanceManager not available for xcashu refund");
|
|
1103
|
+
}
|
|
1104
|
+
const fetchResult = await this.balanceManager.fetchRefundToken(
|
|
1105
|
+
baseUrl,
|
|
1106
|
+
xcashuToken.token,
|
|
1107
|
+
true
|
|
1108
|
+
);
|
|
1109
|
+
if (!fetchResult.success || !fetchResult.token) {
|
|
1110
|
+
throw new Error(
|
|
1111
|
+
fetchResult.error || "Failed to fetch refund token from provider"
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
const receiveResult = await this.receiveToken(fetchResult.token);
|
|
1115
|
+
if (receiveResult.success) {
|
|
1116
|
+
this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
|
|
1117
|
+
results.push({
|
|
1118
|
+
baseUrl,
|
|
1119
|
+
token: xcashuToken.token,
|
|
1120
|
+
success: true
|
|
1121
|
+
});
|
|
1122
|
+
this._log(
|
|
1123
|
+
"DEBUG",
|
|
1124
|
+
`[CashuSpender] refundXcashuTokens: Successfully refunded xcashu token for ${baseUrl}, amount=${receiveResult.amount}`
|
|
1125
|
+
);
|
|
1126
|
+
} else {
|
|
1127
|
+
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
1128
|
+
const newTryCount = currentTryCount + 1;
|
|
1129
|
+
this.storageAdapter.updateXcashuTokenTryCount(
|
|
1130
|
+
xcashuToken.token,
|
|
1131
|
+
newTryCount
|
|
1132
|
+
);
|
|
1133
|
+
results.push({
|
|
1134
|
+
baseUrl,
|
|
1135
|
+
token: xcashuToken.token,
|
|
1136
|
+
success: false,
|
|
1137
|
+
error: receiveResult.message ?? "Refund failed"
|
|
1138
|
+
});
|
|
1139
|
+
this._log(
|
|
1140
|
+
"DEBUG",
|
|
1141
|
+
`[CashuSpender] refundXcashuTokens: Failed to receive refund token for ${baseUrl}, incremented tryCount to ${newTryCount}`
|
|
1142
|
+
);
|
|
1171
1143
|
}
|
|
1144
|
+
} catch (error) {
|
|
1145
|
+
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
1146
|
+
const newTryCount = currentTryCount + 1;
|
|
1147
|
+
this.storageAdapter.updateXcashuTokenTryCount(
|
|
1148
|
+
xcashuToken.token,
|
|
1149
|
+
newTryCount
|
|
1150
|
+
);
|
|
1151
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1172
1152
|
results.push({
|
|
1173
|
-
baseUrl
|
|
1174
|
-
|
|
1153
|
+
baseUrl,
|
|
1154
|
+
token: xcashuToken.token,
|
|
1155
|
+
success: false,
|
|
1156
|
+
error: errorMessage
|
|
1175
1157
|
});
|
|
1158
|
+
this._log(
|
|
1159
|
+
"ERROR",
|
|
1160
|
+
`[CashuSpender] refundXcashuTokens: Exception during refund for ${baseUrl}: ${errorMessage}, incremented tryCount to ${newTryCount}`
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return results;
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Refund specific providers without retrying spend
|
|
1169
|
+
*/
|
|
1170
|
+
async refundProviders(mintUrl, forceRefund) {
|
|
1171
|
+
const results = [];
|
|
1172
|
+
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
1173
|
+
for (const apiKeyEntry of apiKeyDistribution) {
|
|
1174
|
+
const apiKeyEntryFull = this.storageAdapter.getApiKey(
|
|
1175
|
+
apiKeyEntry.baseUrl
|
|
1176
|
+
);
|
|
1177
|
+
if (apiKeyEntryFull && this.balanceManager) {
|
|
1178
|
+
const refundResult = await this.balanceManager.refundApiKey({
|
|
1179
|
+
mintUrl,
|
|
1180
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
1181
|
+
apiKey: apiKeyEntryFull.key,
|
|
1182
|
+
forceRefund
|
|
1183
|
+
});
|
|
1184
|
+
if (refundResult.success) {
|
|
1185
|
+
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
1176
1186
|
} else {
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1187
|
+
this.storageAdapter.updateApiKeyBalance(
|
|
1188
|
+
apiKeyEntry.baseUrl,
|
|
1189
|
+
apiKeyEntry.amount
|
|
1190
|
+
);
|
|
1181
1191
|
}
|
|
1192
|
+
results.push({
|
|
1193
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
1194
|
+
success: refundResult.success
|
|
1195
|
+
});
|
|
1196
|
+
} else {
|
|
1197
|
+
results.push({
|
|
1198
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
1199
|
+
success: false
|
|
1200
|
+
});
|
|
1182
1201
|
}
|
|
1183
1202
|
}
|
|
1184
1203
|
return results;
|
|
@@ -1263,13 +1282,8 @@ var BalanceManager = class {
|
|
|
1263
1282
|
normalizedMintBalances[url] = balanceInSats;
|
|
1264
1283
|
totalMintBalance += balanceInSats;
|
|
1265
1284
|
}
|
|
1266
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
1267
1285
|
const providerBalances = {};
|
|
1268
1286
|
let totalProviderBalance = 0;
|
|
1269
|
-
for (const pending of pendingDistribution) {
|
|
1270
|
-
providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
|
|
1271
|
-
totalProviderBalance += pending.amount;
|
|
1272
|
-
}
|
|
1273
1287
|
const apiKeys = this.storageAdapter.getAllApiKeys();
|
|
1274
1288
|
for (const apiKey of apiKeys) {
|
|
1275
1289
|
if (!providerBalances[apiKey.baseUrl]) {
|
|
@@ -1284,57 +1298,6 @@ var BalanceManager = class {
|
|
|
1284
1298
|
mintBalances: normalizedMintBalances
|
|
1285
1299
|
};
|
|
1286
1300
|
}
|
|
1287
|
-
/**
|
|
1288
|
-
* Unified refund - handles both NIP-60 and legacy wallet refunds
|
|
1289
|
-
*/
|
|
1290
|
-
async refund(options) {
|
|
1291
|
-
const { mintUrl, baseUrl, token: providedToken } = options;
|
|
1292
|
-
const storedToken = providedToken || this.storageAdapter.getToken(baseUrl);
|
|
1293
|
-
if (!storedToken) {
|
|
1294
|
-
console.log("[BalanceManager] No token to refund, returning early");
|
|
1295
|
-
return { success: true, message: "No API key to refund" };
|
|
1296
|
-
}
|
|
1297
|
-
let fetchResult;
|
|
1298
|
-
try {
|
|
1299
|
-
fetchResult = await this._fetchRefundToken(baseUrl, storedToken);
|
|
1300
|
-
if (!fetchResult.success) {
|
|
1301
|
-
return {
|
|
1302
|
-
success: false,
|
|
1303
|
-
message: fetchResult.error || "Refund failed",
|
|
1304
|
-
requestId: fetchResult.requestId
|
|
1305
|
-
};
|
|
1306
|
-
}
|
|
1307
|
-
if (!fetchResult.token) {
|
|
1308
|
-
return {
|
|
1309
|
-
success: false,
|
|
1310
|
-
message: "No token received from refund",
|
|
1311
|
-
requestId: fetchResult.requestId
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
if (fetchResult.error === "No balance to refund") {
|
|
1315
|
-
console.log(
|
|
1316
|
-
"[BalanceManager] No balance to refund, removing stored token"
|
|
1317
|
-
);
|
|
1318
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
1319
|
-
return { success: true, message: "No balance to refund" };
|
|
1320
|
-
}
|
|
1321
|
-
const receiveResult = await this.cashuSpender.receiveToken(
|
|
1322
|
-
fetchResult.token
|
|
1323
|
-
);
|
|
1324
|
-
const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
|
|
1325
|
-
if (!providedToken) {
|
|
1326
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
1327
|
-
}
|
|
1328
|
-
return {
|
|
1329
|
-
success: receiveResult.success,
|
|
1330
|
-
refundedAmount: totalAmountMsat,
|
|
1331
|
-
requestId: fetchResult.requestId
|
|
1332
|
-
};
|
|
1333
|
-
} catch (error) {
|
|
1334
|
-
console.error("[BalanceManager] Refund error", error);
|
|
1335
|
-
return this._handleRefundError(error, mintUrl, fetchResult?.requestId);
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
1301
|
/**
|
|
1339
1302
|
* Refund API key balance - convert remaining API key balance to cashu token
|
|
1340
1303
|
* @param options - Refund options including forceRefund flag
|
|
@@ -1362,7 +1325,7 @@ var BalanceManager = class {
|
|
|
1362
1325
|
}
|
|
1363
1326
|
let fetchResult;
|
|
1364
1327
|
try {
|
|
1365
|
-
fetchResult = await this.
|
|
1328
|
+
fetchResult = await this.fetchRefundToken(baseUrl, apiKey);
|
|
1366
1329
|
if (!fetchResult.success) {
|
|
1367
1330
|
return {
|
|
1368
1331
|
success: false,
|
|
@@ -1398,9 +1361,9 @@ var BalanceManager = class {
|
|
|
1398
1361
|
}
|
|
1399
1362
|
}
|
|
1400
1363
|
/**
|
|
1401
|
-
* Fetch refund token from provider API using API key authentication
|
|
1364
|
+
* Fetch refund token from provider API using API key (or xcashu token) authentication
|
|
1402
1365
|
*/
|
|
1403
|
-
async
|
|
1366
|
+
async fetchRefundToken(baseUrl, apiKeyOrToken, xCashu = false) {
|
|
1404
1367
|
if (!baseUrl) {
|
|
1405
1368
|
return {
|
|
1406
1369
|
success: false,
|
|
@@ -1414,12 +1377,17 @@ var BalanceManager = class {
|
|
|
1414
1377
|
controller.abort();
|
|
1415
1378
|
}, 6e4);
|
|
1416
1379
|
try {
|
|
1380
|
+
const headers = {
|
|
1381
|
+
"Content-Type": "application/json"
|
|
1382
|
+
};
|
|
1383
|
+
if (xCashu) {
|
|
1384
|
+
headers["X-Cashu"] = apiKeyOrToken;
|
|
1385
|
+
} else {
|
|
1386
|
+
headers["Authorization"] = `Bearer ${apiKeyOrToken}`;
|
|
1387
|
+
}
|
|
1417
1388
|
const response = await fetch(url, {
|
|
1418
1389
|
method: "POST",
|
|
1419
|
-
headers
|
|
1420
|
-
Authorization: `Bearer ${apiKey}`,
|
|
1421
|
-
"Content-Type": "application/json"
|
|
1422
|
-
},
|
|
1390
|
+
headers,
|
|
1423
1391
|
signal: controller.signal
|
|
1424
1392
|
});
|
|
1425
1393
|
clearTimeout(timeoutId);
|
|
@@ -1440,10 +1408,7 @@ var BalanceManager = class {
|
|
|
1440
1408
|
};
|
|
1441
1409
|
} catch (error) {
|
|
1442
1410
|
clearTimeout(timeoutId);
|
|
1443
|
-
console.error(
|
|
1444
|
-
"[BalanceManager._fetchRefundTokenWithApiKey] Fetch error",
|
|
1445
|
-
error
|
|
1446
|
-
);
|
|
1411
|
+
console.error("[BalanceManager.fetchRefundToken] Fetch error", error);
|
|
1447
1412
|
if (error instanceof Error) {
|
|
1448
1413
|
if (error.name === "AbortError") {
|
|
1449
1414
|
return {
|
|
@@ -1470,8 +1435,9 @@ var BalanceManager = class {
|
|
|
1470
1435
|
if (!amount || amount <= 0) {
|
|
1471
1436
|
return { success: false, message: "Invalid top up amount" };
|
|
1472
1437
|
}
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1438
|
+
const apiKeyEntry = providedToken ? null : this.storageAdapter.getApiKey(baseUrl);
|
|
1439
|
+
const apiKey = providedToken || apiKeyEntry?.key;
|
|
1440
|
+
if (!apiKey) {
|
|
1475
1441
|
return { success: false, message: "No API key available for top up" };
|
|
1476
1442
|
}
|
|
1477
1443
|
let cashuToken = null;
|
|
@@ -1489,11 +1455,7 @@ var BalanceManager = class {
|
|
|
1489
1455
|
};
|
|
1490
1456
|
}
|
|
1491
1457
|
cashuToken = tokenResult.token;
|
|
1492
|
-
const topUpResult = await this._postTopUp(
|
|
1493
|
-
baseUrl,
|
|
1494
|
-
storedToken,
|
|
1495
|
-
cashuToken
|
|
1496
|
-
);
|
|
1458
|
+
const topUpResult = await this._postTopUp(baseUrl, apiKey, cashuToken);
|
|
1497
1459
|
requestId = topUpResult.requestId;
|
|
1498
1460
|
console.log(topUpResult);
|
|
1499
1461
|
if (!topUpResult.success) {
|
|
@@ -1706,38 +1668,11 @@ var BalanceManager = class {
|
|
|
1706
1668
|
return candidates;
|
|
1707
1669
|
}
|
|
1708
1670
|
async _refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount) {
|
|
1709
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
1710
1671
|
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
1711
1672
|
const forceRefund = retryCount >= 2;
|
|
1712
|
-
const toRefund = pendingDistribution.filter(
|
|
1713
|
-
(pending) => pending.baseUrl !== baseUrl
|
|
1714
|
-
);
|
|
1715
1673
|
const apiKeysToRefund = apiKeyDistribution.filter(
|
|
1716
1674
|
(apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0
|
|
1717
1675
|
);
|
|
1718
|
-
const tokenRefundResults = await Promise.allSettled(
|
|
1719
|
-
toRefund.map(async (pending) => {
|
|
1720
|
-
const token = this.storageAdapter.getToken(pending.baseUrl);
|
|
1721
|
-
if (!token) {
|
|
1722
|
-
return { baseUrl: pending.baseUrl, success: false };
|
|
1723
|
-
}
|
|
1724
|
-
const tokenBalance = await this.getTokenBalance(token, pending.baseUrl);
|
|
1725
|
-
if (tokenBalance.reserved > 0) {
|
|
1726
|
-
return { baseUrl: pending.baseUrl, success: false };
|
|
1727
|
-
}
|
|
1728
|
-
const result = await this.refund({
|
|
1729
|
-
mintUrl,
|
|
1730
|
-
baseUrl: pending.baseUrl,
|
|
1731
|
-
token
|
|
1732
|
-
});
|
|
1733
|
-
return { baseUrl: pending.baseUrl, success: result.success };
|
|
1734
|
-
})
|
|
1735
|
-
);
|
|
1736
|
-
for (const result of tokenRefundResults) {
|
|
1737
|
-
if (result.status === "fulfilled" && result.value.success) {
|
|
1738
|
-
this.storageAdapter.removeToken(result.value.baseUrl);
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
1676
|
const apiKeyRefundResults = await Promise.allSettled(
|
|
1742
1677
|
apiKeysToRefund.map(async (apiKeyEntry) => {
|
|
1743
1678
|
const fullApiKeyEntry = this.storageAdapter.getApiKey(
|
|
@@ -1761,77 +1696,6 @@ var BalanceManager = class {
|
|
|
1761
1696
|
}
|
|
1762
1697
|
}
|
|
1763
1698
|
}
|
|
1764
|
-
/**
|
|
1765
|
-
* Fetch refund token from provider API
|
|
1766
|
-
*/
|
|
1767
|
-
async _fetchRefundToken(baseUrl, storedToken) {
|
|
1768
|
-
if (!baseUrl) {
|
|
1769
|
-
return {
|
|
1770
|
-
success: false,
|
|
1771
|
-
error: "No base URL configured"
|
|
1772
|
-
};
|
|
1773
|
-
}
|
|
1774
|
-
const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
1775
|
-
const url = `${normalizedBaseUrl}v1/wallet/refund`;
|
|
1776
|
-
const controller = new AbortController();
|
|
1777
|
-
const timeoutId = setTimeout(() => {
|
|
1778
|
-
controller.abort();
|
|
1779
|
-
}, 6e4);
|
|
1780
|
-
try {
|
|
1781
|
-
const response = await fetch(url, {
|
|
1782
|
-
method: "POST",
|
|
1783
|
-
headers: {
|
|
1784
|
-
Authorization: `Bearer ${storedToken}`,
|
|
1785
|
-
"Content-Type": "application/json"
|
|
1786
|
-
},
|
|
1787
|
-
signal: controller.signal
|
|
1788
|
-
});
|
|
1789
|
-
clearTimeout(timeoutId);
|
|
1790
|
-
const requestId = response.headers.get("x-routstr-request-id") || void 0;
|
|
1791
|
-
if (!response.ok) {
|
|
1792
|
-
const errorData = await response.json().catch(() => ({}));
|
|
1793
|
-
if (response.status === 400 && errorData?.detail === "No balance to refund") {
|
|
1794
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
1795
|
-
return {
|
|
1796
|
-
success: false,
|
|
1797
|
-
requestId,
|
|
1798
|
-
error: "No balance to refund"
|
|
1799
|
-
};
|
|
1800
|
-
}
|
|
1801
|
-
return {
|
|
1802
|
-
success: false,
|
|
1803
|
-
requestId,
|
|
1804
|
-
error: `Refund request failed with status ${response.status}: ${errorData?.detail || response.statusText}`
|
|
1805
|
-
};
|
|
1806
|
-
}
|
|
1807
|
-
const data = await response.json();
|
|
1808
|
-
console.log("refund rsule", data);
|
|
1809
|
-
return {
|
|
1810
|
-
success: true,
|
|
1811
|
-
token: data.token,
|
|
1812
|
-
requestId
|
|
1813
|
-
};
|
|
1814
|
-
} catch (error) {
|
|
1815
|
-
clearTimeout(timeoutId);
|
|
1816
|
-
console.error("[BalanceManager._fetchRefundToken] Fetch error", error);
|
|
1817
|
-
if (error instanceof Error) {
|
|
1818
|
-
if (error.name === "AbortError") {
|
|
1819
|
-
return {
|
|
1820
|
-
success: false,
|
|
1821
|
-
error: "Request timed out after 1 minute"
|
|
1822
|
-
};
|
|
1823
|
-
}
|
|
1824
|
-
return {
|
|
1825
|
-
success: false,
|
|
1826
|
-
error: error.message
|
|
1827
|
-
};
|
|
1828
|
-
}
|
|
1829
|
-
return {
|
|
1830
|
-
success: false,
|
|
1831
|
-
error: "Unknown error occurred during refund request"
|
|
1832
|
-
};
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
1699
|
/**
|
|
1836
1700
|
* Post topup request to provider API
|
|
1837
1701
|
*/
|
|
@@ -1957,7 +1821,7 @@ var BalanceManager = class {
|
|
|
1957
1821
|
console.log(response.status);
|
|
1958
1822
|
const data = await response.json();
|
|
1959
1823
|
console.log("FAILED ", data);
|
|
1960
|
-
const isInvalidApiKey = response.status === 401 && data?.code === "invalid_api_key" && data?.message?.includes("proofs already spent");
|
|
1824
|
+
const isInvalidApiKey = response.status === 401 && data?.detail?.error?.code === "invalid_api_key" && data?.detail?.error?.message?.includes("proofs already spent");
|
|
1961
1825
|
return {
|
|
1962
1826
|
amount: -1,
|
|
1963
1827
|
reserved: data.reserved ?? 0,
|
|
@@ -2455,8 +2319,13 @@ function isInsecureHttpUrl(url) {
|
|
|
2455
2319
|
return url.startsWith("http://");
|
|
2456
2320
|
}
|
|
2457
2321
|
var ProviderManager = class _ProviderManager {
|
|
2458
|
-
constructor(providerRegistry) {
|
|
2322
|
+
constructor(providerRegistry, store) {
|
|
2459
2323
|
this.providerRegistry = providerRegistry;
|
|
2324
|
+
this.instanceId = `pm_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2325
|
+
if (store) {
|
|
2326
|
+
this.store = store;
|
|
2327
|
+
this.hydrateFromStore();
|
|
2328
|
+
}
|
|
2460
2329
|
}
|
|
2461
2330
|
failedProviders = /* @__PURE__ */ new Set();
|
|
2462
2331
|
/** Track when each provider last failed (provider URL -> timestamp) */
|
|
@@ -2465,14 +2334,57 @@ var ProviderManager = class _ProviderManager {
|
|
|
2465
2334
|
providersOnCoolDown = [];
|
|
2466
2335
|
/** Cooldown duration in milliseconds (5 minutes) */
|
|
2467
2336
|
static COOLDOWN_DURATION_MS = 5 * 60 * 1e3;
|
|
2337
|
+
/** Optional persistent store for failure tracking */
|
|
2338
|
+
store = null;
|
|
2339
|
+
/** Instance ID for debugging */
|
|
2340
|
+
instanceId;
|
|
2341
|
+
/**
|
|
2342
|
+
* Hydrate in-memory state from persistent store
|
|
2343
|
+
*/
|
|
2344
|
+
hydrateFromStore() {
|
|
2345
|
+
if (!this.store) return;
|
|
2346
|
+
const state = this.store.getState();
|
|
2347
|
+
this.failedProviders = new Set(state.failedProviders);
|
|
2348
|
+
this.lastFailed = new Map(Object.entries(state.lastFailed));
|
|
2349
|
+
const now = Date.now();
|
|
2350
|
+
this.providersOnCoolDown = state.providersOnCooldown.filter(
|
|
2351
|
+
(entry) => now - entry.timestamp < _ProviderManager.COOLDOWN_DURATION_MS
|
|
2352
|
+
).map((entry) => [entry.baseUrl, entry.timestamp]);
|
|
2353
|
+
console.log(`[ProviderManager:${this.instanceId}] Hydrated from store:`);
|
|
2354
|
+
console.log(` failedProviders: ${this.failedProviders.size}`);
|
|
2355
|
+
console.log(` lastFailed: ${this.lastFailed.size}`);
|
|
2356
|
+
console.log(` providersOnCooldown: ${this.providersOnCoolDown.length}`);
|
|
2357
|
+
}
|
|
2358
|
+
/**
|
|
2359
|
+
* Get instance ID for debugging
|
|
2360
|
+
*/
|
|
2361
|
+
getInstanceId() {
|
|
2362
|
+
return this.instanceId;
|
|
2363
|
+
}
|
|
2468
2364
|
/**
|
|
2469
2365
|
* Clean up expired cooldown entries
|
|
2470
2366
|
*/
|
|
2471
2367
|
cleanupExpiredCooldowns() {
|
|
2472
2368
|
const now = Date.now();
|
|
2369
|
+
const before = this.providersOnCoolDown.length;
|
|
2473
2370
|
this.providersOnCoolDown = this.providersOnCoolDown.filter(
|
|
2474
|
-
([, timestamp]) =>
|
|
2371
|
+
([url, timestamp]) => {
|
|
2372
|
+
const age = now - timestamp;
|
|
2373
|
+
const isExpired = age >= _ProviderManager.COOLDOWN_DURATION_MS;
|
|
2374
|
+
if (isExpired) {
|
|
2375
|
+
console.log(
|
|
2376
|
+
`[cleanupExpiredCooldowns:${this.instanceId}] Removing expired cooldown for ${url} (age: ${age}ms, cooldown: ${_ProviderManager.COOLDOWN_DURATION_MS}ms)`
|
|
2377
|
+
);
|
|
2378
|
+
}
|
|
2379
|
+
return !isExpired;
|
|
2380
|
+
}
|
|
2475
2381
|
);
|
|
2382
|
+
const after = this.providersOnCoolDown.length;
|
|
2383
|
+
if (before !== after) {
|
|
2384
|
+
console.log(
|
|
2385
|
+
`[cleanupExpiredCooldowns:${this.instanceId}] Cleaned up ${before - after} expired cooldown(s), ${after} remaining`
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2476
2388
|
}
|
|
2477
2389
|
/**
|
|
2478
2390
|
* Get the cooldown duration in milliseconds
|
|
@@ -2485,7 +2397,8 @@ var ProviderManager = class _ProviderManager {
|
|
|
2485
2397
|
*/
|
|
2486
2398
|
isOnCooldown(baseUrl) {
|
|
2487
2399
|
this.cleanupExpiredCooldowns();
|
|
2488
|
-
|
|
2400
|
+
const result = this.providersOnCoolDown.some(([url]) => url === baseUrl);
|
|
2401
|
+
return result;
|
|
2489
2402
|
}
|
|
2490
2403
|
/**
|
|
2491
2404
|
* Get all providers currently on cooldown
|
|
@@ -2499,6 +2412,9 @@ var ProviderManager = class _ProviderManager {
|
|
|
2499
2412
|
*/
|
|
2500
2413
|
resetFailedProviders() {
|
|
2501
2414
|
this.failedProviders.clear();
|
|
2415
|
+
if (this.store) {
|
|
2416
|
+
this.store.getState().setFailedProviders([]);
|
|
2417
|
+
}
|
|
2502
2418
|
}
|
|
2503
2419
|
/**
|
|
2504
2420
|
* Get the last failed timestamp for a provider
|
|
@@ -2519,13 +2435,62 @@ var ProviderManager = class _ProviderManager {
|
|
|
2519
2435
|
markFailed(baseUrl) {
|
|
2520
2436
|
const now = Date.now();
|
|
2521
2437
|
const lastFailure = this.lastFailed.get(baseUrl);
|
|
2438
|
+
console.log(`[markFailed:${this.instanceId}] baseUrl: ${baseUrl}`);
|
|
2439
|
+
console.log(
|
|
2440
|
+
`[markFailed:${this.instanceId}] lastFailure from map: ${lastFailure}`
|
|
2441
|
+
);
|
|
2442
|
+
console.log(
|
|
2443
|
+
`[markFailed:${this.instanceId}] current timestamp (now): ${now}`
|
|
2444
|
+
);
|
|
2445
|
+
console.log(
|
|
2446
|
+
`[markFailed:${this.instanceId}] COOLDOWN_DURATION_MS: ${_ProviderManager.COOLDOWN_DURATION_MS}`
|
|
2447
|
+
);
|
|
2448
|
+
if (lastFailure !== void 0) {
|
|
2449
|
+
const timeSinceLastFailure = now - lastFailure;
|
|
2450
|
+
console.log(
|
|
2451
|
+
`[markFailed:${this.instanceId}] timeSinceLastFailure: ${timeSinceLastFailure}ms`
|
|
2452
|
+
);
|
|
2453
|
+
console.log(
|
|
2454
|
+
`[markFailed:${this.instanceId}] isWithinCooldownWindow: ${timeSinceLastFailure < _ProviderManager.COOLDOWN_DURATION_MS}`
|
|
2455
|
+
);
|
|
2456
|
+
}
|
|
2522
2457
|
this.lastFailed.set(baseUrl, now);
|
|
2523
2458
|
this.failedProviders.add(baseUrl);
|
|
2459
|
+
if (this.store) {
|
|
2460
|
+
this.store.getState().setLastFailedTimestamp(baseUrl, now);
|
|
2461
|
+
this.store.getState().addFailedProvider(baseUrl);
|
|
2462
|
+
}
|
|
2463
|
+
console.log(
|
|
2464
|
+
`[markFailed:${this.instanceId}] Updated lastFailed map for ${baseUrl} to ${now}`
|
|
2465
|
+
);
|
|
2466
|
+
console.log(
|
|
2467
|
+
`[markFailed:${this.instanceId}] failedProviders set size: ${this.failedProviders.size}`
|
|
2468
|
+
);
|
|
2524
2469
|
if (lastFailure !== void 0 && now - lastFailure < _ProviderManager.COOLDOWN_DURATION_MS) {
|
|
2470
|
+
console.log(
|
|
2471
|
+
`[markFailed:${this.instanceId}] Second failure detected within cooldown window for ${baseUrl}`
|
|
2472
|
+
);
|
|
2525
2473
|
if (!this.isOnCooldown(baseUrl)) {
|
|
2526
2474
|
this.providersOnCoolDown.push([baseUrl, now]);
|
|
2475
|
+
if (this.store) {
|
|
2476
|
+
this.store.getState().addProviderOnCooldown(baseUrl, now);
|
|
2477
|
+
}
|
|
2478
|
+
console.log(
|
|
2479
|
+
`[markFailed:${this.instanceId}] Provider ${baseUrl} added to cooldown after second failure within 5 minutes`
|
|
2480
|
+
);
|
|
2481
|
+
} else {
|
|
2482
|
+
console.log(
|
|
2483
|
+
`[markFailed:${this.instanceId}] Provider ${baseUrl} is already on cooldown`
|
|
2484
|
+
);
|
|
2485
|
+
}
|
|
2486
|
+
} else {
|
|
2487
|
+
if (lastFailure === void 0) {
|
|
2488
|
+
console.log(
|
|
2489
|
+
`[markFailed:${this.instanceId}] First failure for ${baseUrl} - not adding to cooldown yet`
|
|
2490
|
+
);
|
|
2491
|
+
} else {
|
|
2527
2492
|
console.log(
|
|
2528
|
-
`
|
|
2493
|
+
`[markFailed:${this.instanceId}] Failure outside cooldown window for ${baseUrl} (timeSinceLastFailure: ${now - lastFailure}ms)`
|
|
2529
2494
|
);
|
|
2530
2495
|
}
|
|
2531
2496
|
}
|
|
@@ -2537,18 +2502,27 @@ var ProviderManager = class _ProviderManager {
|
|
|
2537
2502
|
this.providersOnCoolDown = this.providersOnCoolDown.filter(
|
|
2538
2503
|
([url]) => url !== baseUrl
|
|
2539
2504
|
);
|
|
2505
|
+
if (this.store) {
|
|
2506
|
+
this.store.getState().removeProviderFromCooldown(baseUrl);
|
|
2507
|
+
}
|
|
2540
2508
|
}
|
|
2541
2509
|
/**
|
|
2542
2510
|
* Clear all cooldown tracking
|
|
2543
2511
|
*/
|
|
2544
2512
|
clearCooldowns() {
|
|
2545
2513
|
this.providersOnCoolDown = [];
|
|
2514
|
+
if (this.store) {
|
|
2515
|
+
this.store.getState().clearProvidersOnCooldown();
|
|
2516
|
+
}
|
|
2546
2517
|
}
|
|
2547
2518
|
/**
|
|
2548
2519
|
* Clear all failure tracking (lastFailed timestamps)
|
|
2549
2520
|
*/
|
|
2550
2521
|
clearFailureHistory() {
|
|
2551
2522
|
this.lastFailed.clear();
|
|
2523
|
+
if (this.store) {
|
|
2524
|
+
this.store.getState().setLastFailed({});
|
|
2525
|
+
}
|
|
2552
2526
|
}
|
|
2553
2527
|
/**
|
|
2554
2528
|
* Check if a provider has failed
|
|
@@ -2876,38 +2850,54 @@ var createMemoryDriver = (seed) => {
|
|
|
2876
2850
|
var isBun = () => {
|
|
2877
2851
|
return typeof process.versions.bun !== "undefined";
|
|
2878
2852
|
};
|
|
2879
|
-
var
|
|
2853
|
+
var cachedDbModule = null;
|
|
2854
|
+
var loadDatabase = async (dbPath) => {
|
|
2880
2855
|
if (isBun()) {
|
|
2881
2856
|
throw new Error(
|
|
2882
|
-
"SQLite driver not supported in Bun. Use
|
|
2857
|
+
"SQLite driver not supported in Bun. Use createBunSqliteDriver() instead."
|
|
2883
2858
|
);
|
|
2884
2859
|
}
|
|
2885
|
-
let Database = null;
|
|
2886
2860
|
try {
|
|
2887
|
-
|
|
2861
|
+
if (!cachedDbModule) {
|
|
2862
|
+
cachedDbModule = (await import('better-sqlite3')).default;
|
|
2863
|
+
}
|
|
2864
|
+
return new cachedDbModule(dbPath);
|
|
2888
2865
|
} catch (error) {
|
|
2889
2866
|
throw new Error(
|
|
2890
2867
|
`better-sqlite3 is required for sqlite storage. Install it to use sqlite storage. (${error})`
|
|
2891
2868
|
);
|
|
2892
2869
|
}
|
|
2893
|
-
return new Database(dbPath);
|
|
2894
2870
|
};
|
|
2895
2871
|
var createSqliteDriver = (options = {}) => {
|
|
2896
2872
|
const dbPath = options.dbPath || "routstr.sqlite";
|
|
2897
2873
|
const tableName = options.tableName || "sdk_storage";
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
const
|
|
2903
|
-
|
|
2904
|
-
|
|
2874
|
+
let db;
|
|
2875
|
+
let selectStmt;
|
|
2876
|
+
let upsertStmt;
|
|
2877
|
+
let deleteStmt;
|
|
2878
|
+
const initDb = async () => {
|
|
2879
|
+
if (!db) {
|
|
2880
|
+
db = await loadDatabase(dbPath);
|
|
2881
|
+
db.exec(
|
|
2882
|
+
`CREATE TABLE IF NOT EXISTS ${tableName} (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
|
|
2883
|
+
);
|
|
2884
|
+
selectStmt = db.prepare(`SELECT value FROM ${tableName} WHERE key = ?`);
|
|
2885
|
+
upsertStmt = db.prepare(
|
|
2886
|
+
`INSERT INTO ${tableName} (key, value) VALUES (?, ?)
|
|
2905
2887
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
2906
|
-
|
|
2907
|
-
|
|
2888
|
+
);
|
|
2889
|
+
deleteStmt = db.prepare(`DELETE FROM ${tableName} WHERE key = ?`);
|
|
2890
|
+
}
|
|
2891
|
+
};
|
|
2892
|
+
const ensureInit = async () => {
|
|
2893
|
+
if (!db) {
|
|
2894
|
+
await initDb();
|
|
2895
|
+
}
|
|
2896
|
+
};
|
|
2908
2897
|
return {
|
|
2909
2898
|
async getItem(key, defaultValue) {
|
|
2910
2899
|
try {
|
|
2900
|
+
await ensureInit();
|
|
2911
2901
|
const row = selectStmt.get(key);
|
|
2912
2902
|
if (!row || typeof row.value !== "string") return defaultValue;
|
|
2913
2903
|
try {
|
|
@@ -2925,6 +2915,7 @@ var createSqliteDriver = (options = {}) => {
|
|
|
2925
2915
|
},
|
|
2926
2916
|
async setItem(key, value) {
|
|
2927
2917
|
try {
|
|
2918
|
+
await ensureInit();
|
|
2928
2919
|
upsertStmt.run(key, JSON.stringify(value));
|
|
2929
2920
|
} catch (error) {
|
|
2930
2921
|
console.error(`SQLite setItem failed for key "${key}":`, error);
|
|
@@ -2932,6 +2923,7 @@ var createSqliteDriver = (options = {}) => {
|
|
|
2932
2923
|
},
|
|
2933
2924
|
async removeItem(key) {
|
|
2934
2925
|
try {
|
|
2926
|
+
await ensureInit();
|
|
2935
2927
|
deleteStmt.run(key);
|
|
2936
2928
|
} catch (error) {
|
|
2937
2929
|
console.error(`SQLite removeItem failed for key "${key}":`, error);
|
|
@@ -2939,6 +2931,54 @@ var createSqliteDriver = (options = {}) => {
|
|
|
2939
2931
|
}
|
|
2940
2932
|
};
|
|
2941
2933
|
};
|
|
2934
|
+
async function createBunSqliteDriver(dbPath) {
|
|
2935
|
+
const SQLite = (await import(
|
|
2936
|
+
/* webpackIgnore: true */
|
|
2937
|
+
'bun:sqlite'
|
|
2938
|
+
)).default;
|
|
2939
|
+
const db = new SQLite(dbPath);
|
|
2940
|
+
db.run(`
|
|
2941
|
+
CREATE TABLE IF NOT EXISTS sdk_storage (
|
|
2942
|
+
key TEXT PRIMARY KEY,
|
|
2943
|
+
value TEXT NOT NULL
|
|
2944
|
+
)
|
|
2945
|
+
`);
|
|
2946
|
+
return {
|
|
2947
|
+
async getItem(key, defaultValue) {
|
|
2948
|
+
try {
|
|
2949
|
+
const row = db.query("SELECT value FROM sdk_storage WHERE key = ?").get(key);
|
|
2950
|
+
if (!row || typeof row.value !== "string") return defaultValue;
|
|
2951
|
+
try {
|
|
2952
|
+
return JSON.parse(row.value);
|
|
2953
|
+
} catch (parseError) {
|
|
2954
|
+
if (typeof defaultValue === "string") {
|
|
2955
|
+
return row.value;
|
|
2956
|
+
}
|
|
2957
|
+
throw parseError;
|
|
2958
|
+
}
|
|
2959
|
+
} catch (error) {
|
|
2960
|
+
console.error(`SQLite getItem failed for key "${key}":`, error);
|
|
2961
|
+
return defaultValue;
|
|
2962
|
+
}
|
|
2963
|
+
},
|
|
2964
|
+
async setItem(key, value) {
|
|
2965
|
+
try {
|
|
2966
|
+
db.query(
|
|
2967
|
+
"INSERT INTO sdk_storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
2968
|
+
).run(key, JSON.stringify(value));
|
|
2969
|
+
} catch (error) {
|
|
2970
|
+
console.error(`SQLite setItem failed for key "${key}":`, error);
|
|
2971
|
+
}
|
|
2972
|
+
},
|
|
2973
|
+
async removeItem(key) {
|
|
2974
|
+
try {
|
|
2975
|
+
db.query("DELETE FROM sdk_storage WHERE key = ?").run(key);
|
|
2976
|
+
} catch (error) {
|
|
2977
|
+
console.error(`SQLite removeItem failed for key "${key}":`, error);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
};
|
|
2981
|
+
}
|
|
2942
2982
|
|
|
2943
2983
|
// storage/drivers/indexedDB.ts
|
|
2944
2984
|
var isBrowser = typeof indexedDB !== "undefined";
|
|
@@ -3044,14 +3084,17 @@ var SDK_STORAGE_KEYS = {
|
|
|
3044
3084
|
INFO_FROM_ALL_PROVIDERS: "info_from_all_providers",
|
|
3045
3085
|
LAST_MODELS_UPDATE: "lastModelsUpdate",
|
|
3046
3086
|
LAST_BASE_URLS_UPDATE: "lastBaseUrlsUpdate",
|
|
3047
|
-
LOCAL_CASHU_TOKENS: "local_cashu_tokens",
|
|
3048
3087
|
API_KEYS: "api_keys",
|
|
3049
3088
|
CHILD_KEYS: "child_keys",
|
|
3089
|
+
XCASHU_TOKENS: "xcashu_tokens",
|
|
3050
3090
|
ROUTSTR21_MODELS: "routstr21Models",
|
|
3051
3091
|
LAST_ROUTSTR21_MODELS_UPDATE: "lastRoutstr21ModelsUpdate",
|
|
3052
3092
|
CACHED_RECEIVE_TOKENS: "cached_receive_tokens",
|
|
3053
3093
|
USAGE_TRACKING: "usage_tracking",
|
|
3054
|
-
CLIENT_IDS: "client_ids"
|
|
3094
|
+
CLIENT_IDS: "client_ids",
|
|
3095
|
+
FAILED_PROVIDERS: "failed_providers",
|
|
3096
|
+
LAST_FAILED: "last_failed",
|
|
3097
|
+
PROVIDERS_ON_COOLDOWN: "providers_on_cooldown"
|
|
3055
3098
|
};
|
|
3056
3099
|
|
|
3057
3100
|
// storage/usageTracking/indexedDB.ts
|
|
@@ -3237,21 +3280,23 @@ var normalizeBaseUrl2 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUr
|
|
|
3237
3280
|
var isBun2 = () => {
|
|
3238
3281
|
return typeof process.versions.bun !== "undefined";
|
|
3239
3282
|
};
|
|
3240
|
-
var
|
|
3283
|
+
var cachedDbModule2 = null;
|
|
3284
|
+
var loadDatabase2 = async (dbPath) => {
|
|
3241
3285
|
if (isBun2()) {
|
|
3242
3286
|
throw new Error(
|
|
3243
3287
|
"SQLite driver not supported in Bun. Use createMemoryDriver() instead."
|
|
3244
3288
|
);
|
|
3245
3289
|
}
|
|
3246
|
-
let Database = null;
|
|
3247
3290
|
try {
|
|
3248
|
-
|
|
3291
|
+
if (!cachedDbModule2) {
|
|
3292
|
+
cachedDbModule2 = (await import('better-sqlite3')).default;
|
|
3293
|
+
}
|
|
3294
|
+
return new cachedDbModule2(dbPath);
|
|
3249
3295
|
} catch (error) {
|
|
3250
3296
|
throw new Error(
|
|
3251
3297
|
`better-sqlite3 is required for sqlite usage tracking. Install it to use sqlite storage. (${error})`
|
|
3252
3298
|
);
|
|
3253
3299
|
}
|
|
3254
|
-
return new Database(dbPath);
|
|
3255
3300
|
};
|
|
3256
3301
|
var buildWhereClause = (options = {}) => {
|
|
3257
3302
|
const clauses = [];
|
|
@@ -3288,38 +3333,49 @@ var buildWhereClause = (options = {}) => {
|
|
|
3288
3333
|
var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
3289
3334
|
const dbPath = options.dbPath || "routstr.sqlite";
|
|
3290
3335
|
const tableName = options.tableName || "usage_tracking";
|
|
3291
|
-
const db = createDatabase2(dbPath);
|
|
3292
3336
|
const legacyStorageDriver = options.legacyStorageDriver;
|
|
3293
|
-
db
|
|
3294
|
-
|
|
3295
|
-
id TEXT PRIMARY KEY,
|
|
3296
|
-
timestamp INTEGER NOT NULL,
|
|
3297
|
-
model_id TEXT NOT NULL,
|
|
3298
|
-
base_url TEXT NOT NULL,
|
|
3299
|
-
request_id TEXT NOT NULL,
|
|
3300
|
-
cost REAL NOT NULL,
|
|
3301
|
-
sats_cost REAL NOT NULL,
|
|
3302
|
-
prompt_tokens INTEGER NOT NULL,
|
|
3303
|
-
completion_tokens INTEGER NOT NULL,
|
|
3304
|
-
total_tokens INTEGER NOT NULL,
|
|
3305
|
-
client TEXT,
|
|
3306
|
-
session_id TEXT,
|
|
3307
|
-
tags TEXT
|
|
3308
|
-
);
|
|
3309
|
-
CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
|
|
3310
|
-
CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
|
|
3311
|
-
CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
|
|
3312
|
-
CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
|
|
3313
|
-
CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
|
|
3314
|
-
`);
|
|
3315
|
-
const insertStmt = db.prepare(`
|
|
3316
|
-
INSERT OR REPLACE INTO ${tableName} (
|
|
3317
|
-
id, timestamp, model_id, base_url, request_id,
|
|
3318
|
-
cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
|
|
3319
|
-
client, session_id, tags
|
|
3320
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3321
|
-
`);
|
|
3337
|
+
let db;
|
|
3338
|
+
let insertStmt;
|
|
3322
3339
|
let migrationComplete = false;
|
|
3340
|
+
const initDb = async () => {
|
|
3341
|
+
if (!db) {
|
|
3342
|
+
db = await loadDatabase2(dbPath);
|
|
3343
|
+
db.exec(`
|
|
3344
|
+
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
3345
|
+
id TEXT PRIMARY KEY,
|
|
3346
|
+
timestamp INTEGER NOT NULL,
|
|
3347
|
+
model_id TEXT NOT NULL,
|
|
3348
|
+
base_url TEXT NOT NULL,
|
|
3349
|
+
request_id TEXT NOT NULL,
|
|
3350
|
+
cost REAL NOT NULL,
|
|
3351
|
+
sats_cost REAL NOT NULL,
|
|
3352
|
+
prompt_tokens INTEGER NOT NULL,
|
|
3353
|
+
completion_tokens INTEGER NOT NULL,
|
|
3354
|
+
total_tokens INTEGER NOT NULL,
|
|
3355
|
+
client TEXT,
|
|
3356
|
+
session_id TEXT,
|
|
3357
|
+
tags TEXT
|
|
3358
|
+
);
|
|
3359
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
|
|
3360
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
|
|
3361
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
|
|
3362
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
|
|
3363
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
|
|
3364
|
+
`);
|
|
3365
|
+
insertStmt = db.prepare(`
|
|
3366
|
+
INSERT OR REPLACE INTO ${tableName} (
|
|
3367
|
+
id, timestamp, model_id, base_url, request_id,
|
|
3368
|
+
cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
|
|
3369
|
+
client, session_id, tags
|
|
3370
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3371
|
+
`);
|
|
3372
|
+
}
|
|
3373
|
+
};
|
|
3374
|
+
const ensureInit = async () => {
|
|
3375
|
+
if (!db) {
|
|
3376
|
+
await initDb();
|
|
3377
|
+
}
|
|
3378
|
+
};
|
|
3323
3379
|
const appendOne = (entry) => {
|
|
3324
3380
|
insertStmt.run(
|
|
3325
3381
|
entry.id,
|
|
@@ -3377,19 +3433,23 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
|
3377
3433
|
});
|
|
3378
3434
|
return {
|
|
3379
3435
|
async migrate() {
|
|
3436
|
+
await ensureInit();
|
|
3380
3437
|
await ensureMigrated();
|
|
3381
3438
|
},
|
|
3382
3439
|
async append(entry) {
|
|
3440
|
+
await ensureInit();
|
|
3383
3441
|
await ensureMigrated();
|
|
3384
3442
|
appendOne(entry);
|
|
3385
3443
|
},
|
|
3386
3444
|
async appendMany(entries) {
|
|
3445
|
+
await ensureInit();
|
|
3387
3446
|
await ensureMigrated();
|
|
3388
3447
|
for (const entry of entries) {
|
|
3389
3448
|
appendOne(entry);
|
|
3390
3449
|
}
|
|
3391
3450
|
},
|
|
3392
3451
|
async list(options2 = {}) {
|
|
3452
|
+
await ensureInit();
|
|
3393
3453
|
await ensureMigrated();
|
|
3394
3454
|
const { sql, params } = buildWhereClause(options2);
|
|
3395
3455
|
const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
|
|
@@ -3402,6 +3462,7 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
|
3402
3462
|
return rows.map(mapRow);
|
|
3403
3463
|
},
|
|
3404
3464
|
async count(options2 = {}) {
|
|
3465
|
+
await ensureInit();
|
|
3405
3466
|
await ensureMigrated();
|
|
3406
3467
|
const { sql, params } = buildWhereClause(options2);
|
|
3407
3468
|
const stmt = db.prepare(`SELECT COUNT(*) as count FROM ${tableName} ${sql}`);
|
|
@@ -3409,20 +3470,197 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
|
3409
3470
|
return Number(row?.count ?? 0);
|
|
3410
3471
|
},
|
|
3411
3472
|
async deleteOlderThan(timestamp) {
|
|
3473
|
+
await ensureInit();
|
|
3412
3474
|
await ensureMigrated();
|
|
3413
3475
|
const stmt = db.prepare(`DELETE FROM ${tableName} WHERE timestamp < ?`);
|
|
3414
3476
|
const result = stmt.run(timestamp);
|
|
3415
3477
|
return result.changes;
|
|
3416
3478
|
},
|
|
3417
3479
|
async clear() {
|
|
3480
|
+
await ensureInit();
|
|
3418
3481
|
await ensureMigrated();
|
|
3419
3482
|
db.prepare(`DELETE FROM ${tableName}`).run();
|
|
3420
3483
|
}
|
|
3421
3484
|
};
|
|
3422
3485
|
};
|
|
3423
3486
|
|
|
3424
|
-
// storage/usageTracking/
|
|
3487
|
+
// storage/usageTracking/bunSqlite.ts
|
|
3488
|
+
var MIGRATION_MARKER_KEY3 = "usage_tracking_migration_v1";
|
|
3425
3489
|
var normalizeBaseUrl3 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
3490
|
+
var buildWhereClause2 = (options = {}) => {
|
|
3491
|
+
const clauses = [];
|
|
3492
|
+
const params = [];
|
|
3493
|
+
if (typeof options.before === "number") {
|
|
3494
|
+
clauses.push("timestamp < ?");
|
|
3495
|
+
params.push(options.before);
|
|
3496
|
+
}
|
|
3497
|
+
if (typeof options.after === "number") {
|
|
3498
|
+
clauses.push("timestamp > ?");
|
|
3499
|
+
params.push(options.after);
|
|
3500
|
+
}
|
|
3501
|
+
if (options.modelId) {
|
|
3502
|
+
clauses.push("model_id = ?");
|
|
3503
|
+
params.push(options.modelId);
|
|
3504
|
+
}
|
|
3505
|
+
if (options.baseUrl) {
|
|
3506
|
+
clauses.push("base_url = ?");
|
|
3507
|
+
params.push(normalizeBaseUrl3(options.baseUrl));
|
|
3508
|
+
}
|
|
3509
|
+
if (options.sessionId) {
|
|
3510
|
+
clauses.push("session_id = ?");
|
|
3511
|
+
params.push(options.sessionId);
|
|
3512
|
+
}
|
|
3513
|
+
if (options.client) {
|
|
3514
|
+
clauses.push("client = ?");
|
|
3515
|
+
params.push(options.client);
|
|
3516
|
+
}
|
|
3517
|
+
return {
|
|
3518
|
+
sql: clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "",
|
|
3519
|
+
params
|
|
3520
|
+
};
|
|
3521
|
+
};
|
|
3522
|
+
var createBunSqliteUsageTrackingDriver = (options = {}) => {
|
|
3523
|
+
const dbPath = options.dbPath || "routstr.sqlite";
|
|
3524
|
+
const tableName = options.tableName || "usage_tracking";
|
|
3525
|
+
const legacyStorageDriver = options.legacyStorageDriver;
|
|
3526
|
+
const SQLiteDatabase = options.sqlite?.Database;
|
|
3527
|
+
let migrationPromise = null;
|
|
3528
|
+
if (!SQLiteDatabase) {
|
|
3529
|
+
throw new Error(
|
|
3530
|
+
"Bun SQLite Database constructor is required. Pass { sqlite: { Database } } when creating the driver."
|
|
3531
|
+
);
|
|
3532
|
+
}
|
|
3533
|
+
const db = new SQLiteDatabase(dbPath);
|
|
3534
|
+
db.run(`
|
|
3535
|
+
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
3536
|
+
id TEXT PRIMARY KEY,
|
|
3537
|
+
timestamp INTEGER NOT NULL,
|
|
3538
|
+
model_id TEXT NOT NULL,
|
|
3539
|
+
base_url TEXT NOT NULL,
|
|
3540
|
+
request_id TEXT NOT NULL,
|
|
3541
|
+
cost REAL NOT NULL,
|
|
3542
|
+
sats_cost REAL NOT NULL,
|
|
3543
|
+
prompt_tokens INTEGER NOT NULL,
|
|
3544
|
+
completion_tokens INTEGER NOT NULL,
|
|
3545
|
+
total_tokens INTEGER NOT NULL,
|
|
3546
|
+
client TEXT,
|
|
3547
|
+
session_id TEXT,
|
|
3548
|
+
tags TEXT
|
|
3549
|
+
)
|
|
3550
|
+
`);
|
|
3551
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp)`);
|
|
3552
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id)`);
|
|
3553
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url)`);
|
|
3554
|
+
const appendOne = (entry) => {
|
|
3555
|
+
db.query(`
|
|
3556
|
+
INSERT OR REPLACE INTO ${tableName} (
|
|
3557
|
+
id, timestamp, model_id, base_url, request_id,
|
|
3558
|
+
cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
|
|
3559
|
+
client, session_id, tags
|
|
3560
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3561
|
+
`).run(
|
|
3562
|
+
entry.id,
|
|
3563
|
+
entry.timestamp,
|
|
3564
|
+
entry.modelId,
|
|
3565
|
+
normalizeBaseUrl3(entry.baseUrl),
|
|
3566
|
+
entry.requestId,
|
|
3567
|
+
entry.cost,
|
|
3568
|
+
entry.satsCost,
|
|
3569
|
+
entry.promptTokens,
|
|
3570
|
+
entry.completionTokens,
|
|
3571
|
+
entry.totalTokens,
|
|
3572
|
+
entry.client ?? null,
|
|
3573
|
+
entry.sessionId ?? null,
|
|
3574
|
+
JSON.stringify(entry.tags ?? [])
|
|
3575
|
+
);
|
|
3576
|
+
};
|
|
3577
|
+
const mapRow = (row) => ({
|
|
3578
|
+
id: row.id,
|
|
3579
|
+
timestamp: row.timestamp,
|
|
3580
|
+
modelId: row.model_id,
|
|
3581
|
+
baseUrl: row.base_url,
|
|
3582
|
+
requestId: row.request_id,
|
|
3583
|
+
cost: row.cost,
|
|
3584
|
+
satsCost: row.sats_cost,
|
|
3585
|
+
promptTokens: row.prompt_tokens,
|
|
3586
|
+
completionTokens: row.completion_tokens,
|
|
3587
|
+
totalTokens: row.total_tokens,
|
|
3588
|
+
client: row.client ?? void 0,
|
|
3589
|
+
sessionId: row.session_id ?? void 0,
|
|
3590
|
+
tags: typeof row.tags === "string" ? JSON.parse(row.tags) : void 0
|
|
3591
|
+
});
|
|
3592
|
+
const ensureMigrated = async () => {
|
|
3593
|
+
if (!legacyStorageDriver) return;
|
|
3594
|
+
if (!migrationPromise) {
|
|
3595
|
+
migrationPromise = (async () => {
|
|
3596
|
+
const migrated = await legacyStorageDriver.getItem(
|
|
3597
|
+
MIGRATION_MARKER_KEY3,
|
|
3598
|
+
false
|
|
3599
|
+
);
|
|
3600
|
+
if (migrated) return;
|
|
3601
|
+
const legacyEntries = await legacyStorageDriver.getItem(
|
|
3602
|
+
SDK_STORAGE_KEYS.USAGE_TRACKING,
|
|
3603
|
+
[]
|
|
3604
|
+
);
|
|
3605
|
+
if (legacyEntries.length > 0) {
|
|
3606
|
+
for (const entry of legacyEntries) {
|
|
3607
|
+
appendOne(entry);
|
|
3608
|
+
}
|
|
3609
|
+
await legacyStorageDriver.removeItem(SDK_STORAGE_KEYS.USAGE_TRACKING);
|
|
3610
|
+
}
|
|
3611
|
+
await legacyStorageDriver.setItem(MIGRATION_MARKER_KEY3, true);
|
|
3612
|
+
})();
|
|
3613
|
+
}
|
|
3614
|
+
await migrationPromise;
|
|
3615
|
+
};
|
|
3616
|
+
return {
|
|
3617
|
+
async migrate() {
|
|
3618
|
+
await ensureMigrated();
|
|
3619
|
+
},
|
|
3620
|
+
async append(entry) {
|
|
3621
|
+
await ensureMigrated();
|
|
3622
|
+
appendOne(entry);
|
|
3623
|
+
},
|
|
3624
|
+
async appendMany(entries) {
|
|
3625
|
+
await ensureMigrated();
|
|
3626
|
+
for (const entry of entries) {
|
|
3627
|
+
appendOne(entry);
|
|
3628
|
+
}
|
|
3629
|
+
},
|
|
3630
|
+
async list(options2 = {}) {
|
|
3631
|
+
await ensureMigrated();
|
|
3632
|
+
const { sql, params } = buildWhereClause2(options2);
|
|
3633
|
+
const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
|
|
3634
|
+
const query = `SELECT * FROM ${tableName} ${sql} ORDER BY timestamp DESC${limitSql}`;
|
|
3635
|
+
let rows;
|
|
3636
|
+
if (typeof options2.limit === "number") {
|
|
3637
|
+
rows = db.query(query).all(...params, options2.limit);
|
|
3638
|
+
} else {
|
|
3639
|
+
rows = db.query(query).all(...params);
|
|
3640
|
+
}
|
|
3641
|
+
return rows.map(mapRow);
|
|
3642
|
+
},
|
|
3643
|
+
async count(options2 = {}) {
|
|
3644
|
+
const { sql, params } = buildWhereClause2(options2);
|
|
3645
|
+
const query = `SELECT COUNT(*) as count FROM ${tableName} ${sql}`;
|
|
3646
|
+
const row = db.query(query).get(...params);
|
|
3647
|
+
return Number(row?.count ?? 0);
|
|
3648
|
+
},
|
|
3649
|
+
async deleteOlderThan(timestamp) {
|
|
3650
|
+
await ensureMigrated();
|
|
3651
|
+
const before = timestamp;
|
|
3652
|
+
const result = db.query(`DELETE FROM ${tableName} WHERE timestamp < ?`).run(before);
|
|
3653
|
+
return result.changes ?? 0;
|
|
3654
|
+
},
|
|
3655
|
+
async clear() {
|
|
3656
|
+
await ensureMigrated();
|
|
3657
|
+
db.query(`DELETE FROM ${tableName}`).run();
|
|
3658
|
+
}
|
|
3659
|
+
};
|
|
3660
|
+
};
|
|
3661
|
+
|
|
3662
|
+
// storage/usageTracking/memory.ts
|
|
3663
|
+
var normalizeBaseUrl4 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
3426
3664
|
var matchesFilters2 = (entry, options = {}) => {
|
|
3427
3665
|
if (typeof options.before === "number" && entry.timestamp >= options.before) {
|
|
3428
3666
|
return false;
|
|
@@ -3433,7 +3671,7 @@ var matchesFilters2 = (entry, options = {}) => {
|
|
|
3433
3671
|
if (options.modelId && entry.modelId !== options.modelId) {
|
|
3434
3672
|
return false;
|
|
3435
3673
|
}
|
|
3436
|
-
if (options.baseUrl &&
|
|
3674
|
+
if (options.baseUrl && normalizeBaseUrl4(entry.baseUrl) !== normalizeBaseUrl4(options.baseUrl)) {
|
|
3437
3675
|
return false;
|
|
3438
3676
|
}
|
|
3439
3677
|
if (options.sessionId && entry.sessionId !== options.sessionId) {
|
|
@@ -3447,18 +3685,18 @@ var matchesFilters2 = (entry, options = {}) => {
|
|
|
3447
3685
|
var createMemoryUsageTrackingDriver = (seed = []) => {
|
|
3448
3686
|
const store = /* @__PURE__ */ new Map();
|
|
3449
3687
|
for (const entry of seed) {
|
|
3450
|
-
store.set(entry.id, { ...entry, baseUrl:
|
|
3688
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
|
|
3451
3689
|
}
|
|
3452
3690
|
return {
|
|
3453
3691
|
async migrate() {
|
|
3454
3692
|
return;
|
|
3455
3693
|
},
|
|
3456
3694
|
async append(entry) {
|
|
3457
|
-
store.set(entry.id, { ...entry, baseUrl:
|
|
3695
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
|
|
3458
3696
|
},
|
|
3459
3697
|
async appendMany(entries) {
|
|
3460
3698
|
for (const entry of entries) {
|
|
3461
|
-
store.set(entry.id, { ...entry, baseUrl:
|
|
3699
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
|
|
3462
3700
|
}
|
|
3463
3701
|
},
|
|
3464
3702
|
async list(options = {}) {
|
|
@@ -3486,20 +3724,7 @@ var createMemoryUsageTrackingDriver = (seed = []) => {
|
|
|
3486
3724
|
}
|
|
3487
3725
|
};
|
|
3488
3726
|
};
|
|
3489
|
-
var
|
|
3490
|
-
var getCashuTokenBalance = (token) => {
|
|
3491
|
-
try {
|
|
3492
|
-
const decoded = cashuTs.getDecodedToken(token);
|
|
3493
|
-
const unitDivisor = decoded.unit === "msat" ? 1e3 : 1;
|
|
3494
|
-
let sum = 0;
|
|
3495
|
-
for (const proof of decoded.proofs) {
|
|
3496
|
-
sum += proof.amount / unitDivisor;
|
|
3497
|
-
}
|
|
3498
|
-
return sum;
|
|
3499
|
-
} catch {
|
|
3500
|
-
return 0;
|
|
3501
|
-
}
|
|
3502
|
-
};
|
|
3727
|
+
var normalizeBaseUrl5 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
3503
3728
|
var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
3504
3729
|
modelsFromAllProviders: {},
|
|
3505
3730
|
lastUsedModel: null,
|
|
@@ -3509,17 +3734,20 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3509
3734
|
mintsFromAllProviders: {},
|
|
3510
3735
|
infoFromAllProviders: {},
|
|
3511
3736
|
lastModelsUpdate: {},
|
|
3512
|
-
cachedTokens: [],
|
|
3513
3737
|
apiKeys: [],
|
|
3514
3738
|
childKeys: [],
|
|
3739
|
+
xcashuTokens: {},
|
|
3515
3740
|
routstr21Models: [],
|
|
3516
3741
|
lastRoutstr21ModelsUpdate: null,
|
|
3517
3742
|
cachedReceiveTokens: [],
|
|
3518
3743
|
clientIds: [],
|
|
3744
|
+
failedProviders: [],
|
|
3745
|
+
lastFailed: {},
|
|
3746
|
+
providersOnCooldown: [],
|
|
3519
3747
|
setModelsFromAllProviders: (value) => {
|
|
3520
3748
|
const normalized = {};
|
|
3521
3749
|
for (const [baseUrl, models] of Object.entries(value)) {
|
|
3522
|
-
normalized[
|
|
3750
|
+
normalized[normalizeBaseUrl5(baseUrl)] = models;
|
|
3523
3751
|
}
|
|
3524
3752
|
void driver.setItem(
|
|
3525
3753
|
SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
|
|
@@ -3532,7 +3760,7 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3532
3760
|
set({ lastUsedModel: value });
|
|
3533
3761
|
},
|
|
3534
3762
|
setBaseUrlsList: (value) => {
|
|
3535
|
-
const normalized = value.map((url) =>
|
|
3763
|
+
const normalized = value.map((url) => normalizeBaseUrl5(url));
|
|
3536
3764
|
void driver.setItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, normalized);
|
|
3537
3765
|
set({ baseUrlsList: normalized });
|
|
3538
3766
|
},
|
|
@@ -3541,14 +3769,14 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3541
3769
|
set({ lastBaseUrlsUpdate: value });
|
|
3542
3770
|
},
|
|
3543
3771
|
setDisabledProviders: (value) => {
|
|
3544
|
-
const normalized = value.map((url) =>
|
|
3772
|
+
const normalized = value.map((url) => normalizeBaseUrl5(url));
|
|
3545
3773
|
void driver.setItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, normalized);
|
|
3546
3774
|
set({ disabledProviders: normalized });
|
|
3547
3775
|
},
|
|
3548
3776
|
setMintsFromAllProviders: (value) => {
|
|
3549
3777
|
const normalized = {};
|
|
3550
3778
|
for (const [baseUrl, mints] of Object.entries(value)) {
|
|
3551
|
-
normalized[
|
|
3779
|
+
normalized[normalizeBaseUrl5(baseUrl)] = mints.map(
|
|
3552
3780
|
(mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint
|
|
3553
3781
|
);
|
|
3554
3782
|
}
|
|
@@ -3561,7 +3789,7 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3561
3789
|
setInfoFromAllProviders: (value) => {
|
|
3562
3790
|
const normalized = {};
|
|
3563
3791
|
for (const [baseUrl, info] of Object.entries(value)) {
|
|
3564
|
-
normalized[
|
|
3792
|
+
normalized[normalizeBaseUrl5(baseUrl)] = info;
|
|
3565
3793
|
}
|
|
3566
3794
|
void driver.setItem(SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS, normalized);
|
|
3567
3795
|
set({ infoFromAllProviders: normalized });
|
|
@@ -3569,30 +3797,17 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3569
3797
|
setLastModelsUpdate: (value) => {
|
|
3570
3798
|
const normalized = {};
|
|
3571
3799
|
for (const [baseUrl, timestamp] of Object.entries(value)) {
|
|
3572
|
-
normalized[
|
|
3800
|
+
normalized[normalizeBaseUrl5(baseUrl)] = timestamp;
|
|
3573
3801
|
}
|
|
3574
3802
|
void driver.setItem(SDK_STORAGE_KEYS.LAST_MODELS_UPDATE, normalized);
|
|
3575
3803
|
set({ lastModelsUpdate: normalized });
|
|
3576
3804
|
},
|
|
3577
|
-
setCachedTokens: (value) => {
|
|
3578
|
-
set((state) => {
|
|
3579
|
-
const updates = typeof value === "function" ? value(state.cachedTokens) : value;
|
|
3580
|
-
const normalized = updates.map((entry) => ({
|
|
3581
|
-
...entry,
|
|
3582
|
-
baseUrl: normalizeBaseUrl4(entry.baseUrl),
|
|
3583
|
-
balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
|
|
3584
|
-
lastUsed: entry.lastUsed ?? null
|
|
3585
|
-
}));
|
|
3586
|
-
void driver.setItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, normalized);
|
|
3587
|
-
return { cachedTokens: normalized };
|
|
3588
|
-
});
|
|
3589
|
-
},
|
|
3590
3805
|
setApiKeys: (value) => {
|
|
3591
3806
|
set((state) => {
|
|
3592
3807
|
const updates = typeof value === "function" ? value(state.apiKeys) : value;
|
|
3593
3808
|
const normalized = updates.map((entry) => ({
|
|
3594
3809
|
...entry,
|
|
3595
|
-
baseUrl:
|
|
3810
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3596
3811
|
balance: entry.balance ?? 0,
|
|
3597
3812
|
lastUsed: entry.lastUsed ?? null
|
|
3598
3813
|
}));
|
|
@@ -3604,7 +3819,7 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3604
3819
|
set((state) => {
|
|
3605
3820
|
const updates = typeof value === "function" ? value(state.childKeys) : value;
|
|
3606
3821
|
const normalized = updates.map((entry) => ({
|
|
3607
|
-
parentBaseUrl:
|
|
3822
|
+
parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
|
|
3608
3823
|
childKey: entry.childKey,
|
|
3609
3824
|
balance: entry.balance ?? 0,
|
|
3610
3825
|
balanceLimit: entry.balanceLimit,
|
|
@@ -3615,6 +3830,30 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3615
3830
|
return { childKeys: normalized };
|
|
3616
3831
|
});
|
|
3617
3832
|
},
|
|
3833
|
+
setXcashuTokens: (value) => {
|
|
3834
|
+
const normalized = {};
|
|
3835
|
+
for (const [baseUrl, tokens] of Object.entries(value)) {
|
|
3836
|
+
normalized[normalizeBaseUrl5(baseUrl)] = tokens.map((entry) => ({
|
|
3837
|
+
...entry,
|
|
3838
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3839
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
3840
|
+
tryCount: entry.tryCount ?? 0
|
|
3841
|
+
}));
|
|
3842
|
+
}
|
|
3843
|
+
void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, normalized);
|
|
3844
|
+
set({ xcashuTokens: normalized });
|
|
3845
|
+
},
|
|
3846
|
+
updateXcashuTokenTryCount: (token, tryCount) => {
|
|
3847
|
+
const currentTokens = get().xcashuTokens;
|
|
3848
|
+
const updatedTokens = {};
|
|
3849
|
+
for (const [baseUrl, tokens] of Object.entries(currentTokens)) {
|
|
3850
|
+
updatedTokens[baseUrl] = tokens.map(
|
|
3851
|
+
(entry) => entry.token === token ? { ...entry, tryCount } : entry
|
|
3852
|
+
);
|
|
3853
|
+
}
|
|
3854
|
+
void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, updatedTokens);
|
|
3855
|
+
set({ xcashuTokens: updatedTokens });
|
|
3856
|
+
},
|
|
3618
3857
|
setRoutstr21Models: (value) => {
|
|
3619
3858
|
void driver.setItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, value);
|
|
3620
3859
|
set({ routstr21Models: value });
|
|
@@ -3644,6 +3883,71 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3644
3883
|
void driver.setItem(SDK_STORAGE_KEYS.CLIENT_IDS, normalized);
|
|
3645
3884
|
return { clientIds: normalized };
|
|
3646
3885
|
});
|
|
3886
|
+
},
|
|
3887
|
+
// ========== Failure Tracking ==========
|
|
3888
|
+
setFailedProviders: (value) => {
|
|
3889
|
+
const normalized = value.map((url) => normalizeBaseUrl5(url));
|
|
3890
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, normalized);
|
|
3891
|
+
set({ failedProviders: normalized });
|
|
3892
|
+
},
|
|
3893
|
+
addFailedProvider: (baseUrl) => {
|
|
3894
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3895
|
+
const current = get().failedProviders;
|
|
3896
|
+
if (!current.includes(normalized)) {
|
|
3897
|
+
const updated = [...current, normalized];
|
|
3898
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
|
|
3899
|
+
set({ failedProviders: updated });
|
|
3900
|
+
}
|
|
3901
|
+
},
|
|
3902
|
+
removeFailedProvider: (baseUrl) => {
|
|
3903
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3904
|
+
const current = get().failedProviders;
|
|
3905
|
+
const updated = current.filter((url) => url !== normalized);
|
|
3906
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
|
|
3907
|
+
set({ failedProviders: updated });
|
|
3908
|
+
},
|
|
3909
|
+
setLastFailed: (value) => {
|
|
3910
|
+
const normalized = {};
|
|
3911
|
+
for (const [baseUrl, timestamp] of Object.entries(value)) {
|
|
3912
|
+
normalized[normalizeBaseUrl5(baseUrl)] = timestamp;
|
|
3913
|
+
}
|
|
3914
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, normalized);
|
|
3915
|
+
set({ lastFailed: normalized });
|
|
3916
|
+
},
|
|
3917
|
+
setLastFailedTimestamp: (baseUrl, timestamp) => {
|
|
3918
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3919
|
+
const current = get().lastFailed;
|
|
3920
|
+
const updated = { ...current, [normalized]: timestamp };
|
|
3921
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, updated);
|
|
3922
|
+
set({ lastFailed: updated });
|
|
3923
|
+
},
|
|
3924
|
+
setProvidersOnCooldown: (value) => {
|
|
3925
|
+
const normalized = value.map((entry) => ({
|
|
3926
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3927
|
+
timestamp: entry.timestamp
|
|
3928
|
+
}));
|
|
3929
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, normalized);
|
|
3930
|
+
set({ providersOnCooldown: normalized });
|
|
3931
|
+
},
|
|
3932
|
+
addProviderOnCooldown: (baseUrl, timestamp) => {
|
|
3933
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3934
|
+
const current = get().providersOnCooldown;
|
|
3935
|
+
if (!current.some((entry) => entry.baseUrl === normalized)) {
|
|
3936
|
+
const updated = [...current, { baseUrl: normalized, timestamp }];
|
|
3937
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
|
|
3938
|
+
set({ providersOnCooldown: updated });
|
|
3939
|
+
}
|
|
3940
|
+
},
|
|
3941
|
+
removeProviderFromCooldown: (baseUrl) => {
|
|
3942
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3943
|
+
const current = get().providersOnCooldown;
|
|
3944
|
+
const updated = current.filter((entry) => entry.baseUrl !== normalized);
|
|
3945
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
|
|
3946
|
+
set({ providersOnCooldown: updated });
|
|
3947
|
+
},
|
|
3948
|
+
clearProvidersOnCooldown: () => {
|
|
3949
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, []);
|
|
3950
|
+
set({ providersOnCooldown: [] });
|
|
3647
3951
|
}
|
|
3648
3952
|
}));
|
|
3649
3953
|
var hydrateStoreFromDriver = async (store, driver) => {
|
|
@@ -3656,13 +3960,16 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3656
3960
|
rawMints,
|
|
3657
3961
|
rawInfo,
|
|
3658
3962
|
rawLastModelsUpdate,
|
|
3659
|
-
rawCachedTokens,
|
|
3660
3963
|
rawApiKeys,
|
|
3661
3964
|
rawChildKeys,
|
|
3965
|
+
rawXcashuTokens,
|
|
3662
3966
|
rawRoutstr21Models,
|
|
3663
3967
|
rawLastRoutstr21ModelsUpdate,
|
|
3664
3968
|
rawCachedReceiveTokens,
|
|
3665
|
-
rawClientIds
|
|
3969
|
+
rawClientIds,
|
|
3970
|
+
rawFailedProviders,
|
|
3971
|
+
rawLastFailed,
|
|
3972
|
+
rawProvidersOnCooldown
|
|
3666
3973
|
] = await Promise.all([
|
|
3667
3974
|
driver.getItem(
|
|
3668
3975
|
SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
|
|
@@ -3684,65 +3991,73 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3684
3991
|
SDK_STORAGE_KEYS.LAST_MODELS_UPDATE,
|
|
3685
3992
|
{}
|
|
3686
3993
|
),
|
|
3687
|
-
driver.getItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, []),
|
|
3688
3994
|
driver.getItem(SDK_STORAGE_KEYS.API_KEYS, []),
|
|
3689
3995
|
driver.getItem(SDK_STORAGE_KEYS.CHILD_KEYS, []),
|
|
3996
|
+
driver.getItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, {}),
|
|
3690
3997
|
driver.getItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, []),
|
|
3691
3998
|
driver.getItem(
|
|
3692
3999
|
SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
|
|
3693
4000
|
null
|
|
3694
4001
|
),
|
|
3695
4002
|
driver.getItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, []),
|
|
3696
|
-
driver.getItem(SDK_STORAGE_KEYS.CLIENT_IDS, [])
|
|
4003
|
+
driver.getItem(SDK_STORAGE_KEYS.CLIENT_IDS, []),
|
|
4004
|
+
driver.getItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, []),
|
|
4005
|
+
driver.getItem(SDK_STORAGE_KEYS.LAST_FAILED, {}),
|
|
4006
|
+
driver.getItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, [])
|
|
3697
4007
|
]);
|
|
3698
4008
|
const modelsFromAllProviders = Object.fromEntries(
|
|
3699
4009
|
Object.entries(rawModels).map(([baseUrl, models]) => [
|
|
3700
|
-
|
|
4010
|
+
normalizeBaseUrl5(baseUrl),
|
|
3701
4011
|
models
|
|
3702
4012
|
])
|
|
3703
4013
|
);
|
|
3704
|
-
const baseUrlsList = rawBaseUrls.map((url) =>
|
|
4014
|
+
const baseUrlsList = rawBaseUrls.map((url) => normalizeBaseUrl5(url));
|
|
3705
4015
|
const disabledProviders = rawDisabledProviders.map(
|
|
3706
|
-
(url) =>
|
|
4016
|
+
(url) => normalizeBaseUrl5(url)
|
|
3707
4017
|
);
|
|
3708
4018
|
const mintsFromAllProviders = Object.fromEntries(
|
|
3709
4019
|
Object.entries(rawMints).map(([baseUrl, mints]) => [
|
|
3710
|
-
|
|
4020
|
+
normalizeBaseUrl5(baseUrl),
|
|
3711
4021
|
mints.map((mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint)
|
|
3712
4022
|
])
|
|
3713
4023
|
);
|
|
3714
4024
|
const infoFromAllProviders = Object.fromEntries(
|
|
3715
4025
|
Object.entries(rawInfo).map(([baseUrl, info]) => [
|
|
3716
|
-
|
|
4026
|
+
normalizeBaseUrl5(baseUrl),
|
|
3717
4027
|
info
|
|
3718
4028
|
])
|
|
3719
4029
|
);
|
|
3720
4030
|
const lastModelsUpdate = Object.fromEntries(
|
|
3721
4031
|
Object.entries(rawLastModelsUpdate).map(([baseUrl, timestamp]) => [
|
|
3722
|
-
|
|
4032
|
+
normalizeBaseUrl5(baseUrl),
|
|
3723
4033
|
timestamp
|
|
3724
4034
|
])
|
|
3725
4035
|
);
|
|
3726
|
-
const cachedTokens = rawCachedTokens.map((entry) => ({
|
|
3727
|
-
...entry,
|
|
3728
|
-
baseUrl: normalizeBaseUrl4(entry.baseUrl),
|
|
3729
|
-
balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
|
|
3730
|
-
lastUsed: entry.lastUsed ?? null
|
|
3731
|
-
}));
|
|
3732
4036
|
const apiKeys = rawApiKeys.map((entry) => ({
|
|
3733
4037
|
...entry,
|
|
3734
|
-
baseUrl:
|
|
4038
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3735
4039
|
balance: entry.balance ?? 0,
|
|
3736
4040
|
lastUsed: entry.lastUsed ?? null
|
|
3737
4041
|
}));
|
|
3738
4042
|
const childKeys = rawChildKeys.map((entry) => ({
|
|
3739
|
-
parentBaseUrl:
|
|
4043
|
+
parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
|
|
3740
4044
|
childKey: entry.childKey,
|
|
3741
4045
|
balance: entry.balance ?? 0,
|
|
3742
4046
|
balanceLimit: entry.balanceLimit,
|
|
3743
4047
|
validityDate: entry.validityDate,
|
|
3744
4048
|
createdAt: entry.createdAt ?? Date.now()
|
|
3745
4049
|
}));
|
|
4050
|
+
const xcashuTokens = Object.fromEntries(
|
|
4051
|
+
Object.entries(rawXcashuTokens).map(([baseUrl, tokens]) => [
|
|
4052
|
+
normalizeBaseUrl5(baseUrl),
|
|
4053
|
+
tokens.map((entry) => ({
|
|
4054
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
4055
|
+
token: entry.token,
|
|
4056
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
4057
|
+
tryCount: entry.tryCount ?? 0
|
|
4058
|
+
}))
|
|
4059
|
+
])
|
|
4060
|
+
);
|
|
3746
4061
|
const routstr21Models = rawRoutstr21Models;
|
|
3747
4062
|
const lastRoutstr21ModelsUpdate = rawLastRoutstr21ModelsUpdate;
|
|
3748
4063
|
const cachedReceiveTokens = rawCachedReceiveTokens?.map((entry) => ({
|
|
@@ -3756,6 +4071,17 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3756
4071
|
createdAt: entry.createdAt ?? Date.now(),
|
|
3757
4072
|
lastUsed: entry.lastUsed ?? null
|
|
3758
4073
|
}));
|
|
4074
|
+
const failedProviders = rawFailedProviders.map((url) => normalizeBaseUrl5(url));
|
|
4075
|
+
const lastFailed = Object.fromEntries(
|
|
4076
|
+
Object.entries(rawLastFailed).map(([baseUrl, timestamp]) => [
|
|
4077
|
+
normalizeBaseUrl5(baseUrl),
|
|
4078
|
+
timestamp
|
|
4079
|
+
])
|
|
4080
|
+
);
|
|
4081
|
+
const providersOnCooldown = rawProvidersOnCooldown.map((entry) => ({
|
|
4082
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
4083
|
+
timestamp: entry.timestamp
|
|
4084
|
+
}));
|
|
3759
4085
|
store.setState({
|
|
3760
4086
|
modelsFromAllProviders,
|
|
3761
4087
|
lastUsedModel,
|
|
@@ -3765,13 +4091,16 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3765
4091
|
mintsFromAllProviders,
|
|
3766
4092
|
infoFromAllProviders,
|
|
3767
4093
|
lastModelsUpdate,
|
|
3768
|
-
cachedTokens,
|
|
3769
4094
|
apiKeys,
|
|
3770
4095
|
childKeys,
|
|
4096
|
+
xcashuTokens,
|
|
3771
4097
|
routstr21Models,
|
|
3772
4098
|
lastRoutstr21ModelsUpdate,
|
|
3773
4099
|
cachedReceiveTokens,
|
|
3774
|
-
clientIds
|
|
4100
|
+
clientIds,
|
|
4101
|
+
failedProviders,
|
|
4102
|
+
lastFailed,
|
|
4103
|
+
providersOnCooldown
|
|
3775
4104
|
});
|
|
3776
4105
|
};
|
|
3777
4106
|
var createSdkStore = ({
|
|
@@ -3791,12 +4120,12 @@ var createDiscoveryAdapterFromStore = (store) => ({
|
|
|
3791
4120
|
getCachedProviderInfo: () => store.getState().infoFromAllProviders,
|
|
3792
4121
|
setCachedProviderInfo: (info) => store.getState().setInfoFromAllProviders(info),
|
|
3793
4122
|
getProviderLastUpdate: (baseUrl) => {
|
|
3794
|
-
const normalized =
|
|
4123
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3795
4124
|
const timestamps = store.getState().lastModelsUpdate;
|
|
3796
4125
|
return timestamps[normalized] || null;
|
|
3797
4126
|
},
|
|
3798
4127
|
setProviderLastUpdate: (baseUrl, timestamp) => {
|
|
3799
|
-
const normalized =
|
|
4128
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3800
4129
|
const timestamps = { ...store.getState().lastModelsUpdate };
|
|
3801
4130
|
timestamps[normalized] = timestamp;
|
|
3802
4131
|
store.getState().setLastModelsUpdate(timestamps);
|
|
@@ -3814,59 +4143,6 @@ var createDiscoveryAdapterFromStore = (store) => ({
|
|
|
3814
4143
|
setRoutstr21ModelsLastUpdate: (timestamp) => store.getState().setRoutstr21ModelsLastUpdate(timestamp)
|
|
3815
4144
|
});
|
|
3816
4145
|
var createStorageAdapterFromStore = (store) => ({
|
|
3817
|
-
getToken: (baseUrl) => {
|
|
3818
|
-
const normalized = normalizeBaseUrl4(baseUrl);
|
|
3819
|
-
const entry = store.getState().cachedTokens.find((token) => token.baseUrl === normalized);
|
|
3820
|
-
if (!entry) return null;
|
|
3821
|
-
const next = store.getState().cachedTokens.map(
|
|
3822
|
-
(token) => token.baseUrl === normalized ? { ...token, lastUsed: Date.now() } : token
|
|
3823
|
-
);
|
|
3824
|
-
store.getState().setCachedTokens(next);
|
|
3825
|
-
return entry.token;
|
|
3826
|
-
},
|
|
3827
|
-
setToken: (baseUrl, token) => {
|
|
3828
|
-
const normalized = normalizeBaseUrl4(baseUrl);
|
|
3829
|
-
const tokens = store.getState().cachedTokens;
|
|
3830
|
-
const balance = getCashuTokenBalance(token);
|
|
3831
|
-
const existingIndex = tokens.findIndex(
|
|
3832
|
-
(entry) => entry.baseUrl === normalized
|
|
3833
|
-
);
|
|
3834
|
-
if (existingIndex !== -1) {
|
|
3835
|
-
throw new Error(`Token already exists for baseUrl: ${normalized}`);
|
|
3836
|
-
}
|
|
3837
|
-
const next = [...tokens];
|
|
3838
|
-
next.push({
|
|
3839
|
-
baseUrl: normalized,
|
|
3840
|
-
token,
|
|
3841
|
-
balance,
|
|
3842
|
-
lastUsed: Date.now()
|
|
3843
|
-
});
|
|
3844
|
-
store.getState().setCachedTokens(next);
|
|
3845
|
-
},
|
|
3846
|
-
removeToken: (baseUrl) => {
|
|
3847
|
-
const normalized = normalizeBaseUrl4(baseUrl);
|
|
3848
|
-
const next = store.getState().cachedTokens.filter((entry) => entry.baseUrl !== normalized);
|
|
3849
|
-
store.getState().setCachedTokens(next);
|
|
3850
|
-
},
|
|
3851
|
-
updateTokenBalance: (baseUrl, balance) => {
|
|
3852
|
-
const normalized = normalizeBaseUrl4(baseUrl);
|
|
3853
|
-
const tokens = store.getState().cachedTokens;
|
|
3854
|
-
const next = tokens.map(
|
|
3855
|
-
(entry) => entry.baseUrl === normalized ? { ...entry, balance } : entry
|
|
3856
|
-
);
|
|
3857
|
-
store.getState().setCachedTokens(next);
|
|
3858
|
-
},
|
|
3859
|
-
getCachedTokenDistribution: () => {
|
|
3860
|
-
const cachedTokens = store.getState().cachedTokens;
|
|
3861
|
-
const distributionMap = {};
|
|
3862
|
-
for (const entry of cachedTokens) {
|
|
3863
|
-
const sum = entry.balance || 0;
|
|
3864
|
-
if (sum > 0) {
|
|
3865
|
-
distributionMap[entry.baseUrl] = (distributionMap[entry.baseUrl] || 0) + sum;
|
|
3866
|
-
}
|
|
3867
|
-
}
|
|
3868
|
-
return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
|
|
3869
|
-
},
|
|
3870
4146
|
getApiKeyDistribution: () => {
|
|
3871
4147
|
const apiKeys = store.getState().apiKeys;
|
|
3872
4148
|
const distributionMap = {};
|
|
@@ -3879,28 +4155,24 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3879
4155
|
return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
|
|
3880
4156
|
},
|
|
3881
4157
|
saveProviderInfo: (baseUrl, info) => {
|
|
3882
|
-
const normalized =
|
|
4158
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3883
4159
|
const next = { ...store.getState().infoFromAllProviders };
|
|
3884
4160
|
next[normalized] = info;
|
|
3885
4161
|
store.getState().setInfoFromAllProviders(next);
|
|
3886
4162
|
},
|
|
3887
4163
|
getProviderInfo: (baseUrl) => {
|
|
3888
|
-
const normalized =
|
|
4164
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3889
4165
|
return store.getState().infoFromAllProviders[normalized] || null;
|
|
3890
4166
|
},
|
|
3891
4167
|
// ========== API Keys (for apikeys mode) ==========
|
|
3892
4168
|
getApiKey: (baseUrl) => {
|
|
3893
|
-
const normalized =
|
|
4169
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3894
4170
|
const entry = store.getState().apiKeys.find((key) => key.baseUrl === normalized);
|
|
3895
4171
|
if (!entry) return null;
|
|
3896
|
-
const next = store.getState().apiKeys.map(
|
|
3897
|
-
(key) => key.baseUrl === normalized ? { ...key, lastUsed: Date.now() } : key
|
|
3898
|
-
);
|
|
3899
|
-
store.getState().setApiKeys(next);
|
|
3900
4172
|
return entry;
|
|
3901
4173
|
},
|
|
3902
4174
|
setApiKey: (baseUrl, key) => {
|
|
3903
|
-
const normalized =
|
|
4175
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3904
4176
|
const keys = store.getState().apiKeys;
|
|
3905
4177
|
const existingIndex = keys.findIndex(
|
|
3906
4178
|
(entry) => entry.baseUrl === normalized
|
|
@@ -3918,15 +4190,15 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3918
4190
|
store.getState().setApiKeys(next);
|
|
3919
4191
|
},
|
|
3920
4192
|
updateApiKeyBalance: (baseUrl, balance) => {
|
|
3921
|
-
const normalized =
|
|
4193
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3922
4194
|
const keys = store.getState().apiKeys;
|
|
3923
4195
|
const next = keys.map(
|
|
3924
|
-
(entry) => entry.baseUrl === normalized ? { ...entry, balance } : entry
|
|
4196
|
+
(entry) => entry.baseUrl === normalized ? { ...entry, balance, lastUsed: Date.now() } : entry
|
|
3925
4197
|
);
|
|
3926
4198
|
store.getState().setApiKeys(next);
|
|
3927
4199
|
},
|
|
3928
4200
|
removeApiKey: (baseUrl) => {
|
|
3929
|
-
const normalized =
|
|
4201
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3930
4202
|
const next = store.getState().apiKeys.filter((entry) => entry.baseUrl !== normalized);
|
|
3931
4203
|
store.getState().setApiKeys(next);
|
|
3932
4204
|
},
|
|
@@ -3940,7 +4212,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3940
4212
|
},
|
|
3941
4213
|
// ========== Child Keys ==========
|
|
3942
4214
|
getChildKey: (parentBaseUrl) => {
|
|
3943
|
-
const normalized =
|
|
4215
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3944
4216
|
const entry = store.getState().childKeys.find((key) => key.parentBaseUrl === normalized);
|
|
3945
4217
|
if (!entry) return null;
|
|
3946
4218
|
return {
|
|
@@ -3953,7 +4225,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3953
4225
|
};
|
|
3954
4226
|
},
|
|
3955
4227
|
setChildKey: (parentBaseUrl, childKey, balance, validityDate, balanceLimit) => {
|
|
3956
|
-
const normalized =
|
|
4228
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3957
4229
|
const keys = store.getState().childKeys;
|
|
3958
4230
|
const existingIndex = keys.findIndex(
|
|
3959
4231
|
(entry) => entry.parentBaseUrl === normalized
|
|
@@ -3984,7 +4256,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3984
4256
|
}
|
|
3985
4257
|
},
|
|
3986
4258
|
updateChildKeyBalance: (parentBaseUrl, balance) => {
|
|
3987
|
-
const normalized =
|
|
4259
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3988
4260
|
const keys = store.getState().childKeys;
|
|
3989
4261
|
const next = keys.map(
|
|
3990
4262
|
(entry) => entry.parentBaseUrl === normalized ? { ...entry, balance } : entry
|
|
@@ -3992,7 +4264,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3992
4264
|
store.getState().setChildKeys(next);
|
|
3993
4265
|
},
|
|
3994
4266
|
removeChildKey: (parentBaseUrl) => {
|
|
3995
|
-
const normalized =
|
|
4267
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3996
4268
|
const next = store.getState().childKeys.filter((entry) => entry.parentBaseUrl !== normalized);
|
|
3997
4269
|
store.getState().setChildKeys(next);
|
|
3998
4270
|
},
|
|
@@ -4011,20 +4283,60 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
4011
4283
|
},
|
|
4012
4284
|
setCachedReceiveTokens: (tokens) => {
|
|
4013
4285
|
store.getState().setCachedReceiveTokens(tokens);
|
|
4286
|
+
},
|
|
4287
|
+
// ========== XCashu Tokens (multiple tokens per baseUrl) ==========
|
|
4288
|
+
getXcashuTokens: () => {
|
|
4289
|
+
return store.getState().xcashuTokens;
|
|
4290
|
+
},
|
|
4291
|
+
getXcashuTokensForBaseUrl: (baseUrl) => {
|
|
4292
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4293
|
+
return store.getState().xcashuTokens[normalized] || [];
|
|
4294
|
+
},
|
|
4295
|
+
addXcashuToken: (baseUrl, token) => {
|
|
4296
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4297
|
+
const tokens = store.getState().xcashuTokens;
|
|
4298
|
+
const existing = tokens[normalized] || [];
|
|
4299
|
+
const next = { ...tokens };
|
|
4300
|
+
next[normalized] = [
|
|
4301
|
+
...existing,
|
|
4302
|
+
{ baseUrl: normalized, token, createdAt: Date.now(), tryCount: 0 }
|
|
4303
|
+
];
|
|
4304
|
+
store.getState().setXcashuTokens(next);
|
|
4305
|
+
},
|
|
4306
|
+
removeXcashuToken: (baseUrl, token) => {
|
|
4307
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4308
|
+
const tokens = store.getState().xcashuTokens;
|
|
4309
|
+
const existing = tokens[normalized] || [];
|
|
4310
|
+
const next = { ...tokens };
|
|
4311
|
+
next[normalized] = existing.filter((entry) => entry.token !== token);
|
|
4312
|
+
if (next[normalized].length === 0) {
|
|
4313
|
+
delete next[normalized];
|
|
4314
|
+
}
|
|
4315
|
+
store.getState().setXcashuTokens(next);
|
|
4316
|
+
},
|
|
4317
|
+
clearXcashuTokensForBaseUrl: (baseUrl) => {
|
|
4318
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4319
|
+
const tokens = store.getState().xcashuTokens;
|
|
4320
|
+
const next = { ...tokens };
|
|
4321
|
+
delete next[normalized];
|
|
4322
|
+
store.getState().setXcashuTokens(next);
|
|
4323
|
+
},
|
|
4324
|
+
updateXcashuTokenTryCount: (token, tryCount) => {
|
|
4325
|
+
store.getState().updateXcashuTokenTryCount(token, tryCount);
|
|
4014
4326
|
}
|
|
4015
4327
|
});
|
|
4016
4328
|
var createProviderRegistryFromStore = (store) => ({
|
|
4017
4329
|
getModelsForProvider: (baseUrl) => {
|
|
4018
|
-
const normalized =
|
|
4330
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4019
4331
|
return store.getState().modelsFromAllProviders[normalized] || [];
|
|
4020
4332
|
},
|
|
4021
4333
|
getDisabledProviders: () => store.getState().disabledProviders,
|
|
4022
4334
|
getProviderMints: (baseUrl) => {
|
|
4023
|
-
const normalized =
|
|
4335
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4024
4336
|
return store.getState().mintsFromAllProviders[normalized] || [];
|
|
4025
4337
|
},
|
|
4026
4338
|
getProviderInfo: async (baseUrl) => {
|
|
4027
|
-
const normalized =
|
|
4339
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4028
4340
|
const cached = store.getState().infoFromAllProviders[normalized];
|
|
4029
4341
|
if (cached) return cached;
|
|
4030
4342
|
try {
|
|
@@ -4099,7 +4411,7 @@ var getDefaultUsageTrackingDriver = () => {
|
|
|
4099
4411
|
return defaultUsageTrackingDriver;
|
|
4100
4412
|
}
|
|
4101
4413
|
if (isBun3()) {
|
|
4102
|
-
defaultUsageTrackingDriver =
|
|
4414
|
+
defaultUsageTrackingDriver = createBunSqliteUsageTrackingDriver();
|
|
4103
4415
|
return defaultUsageTrackingDriver;
|
|
4104
4416
|
}
|
|
4105
4417
|
if (isNode()) {
|
|
@@ -4111,21 +4423,28 @@ var getDefaultUsageTrackingDriver = () => {
|
|
|
4111
4423
|
defaultUsageTrackingDriver = createMemoryUsageTrackingDriver();
|
|
4112
4424
|
return defaultUsageTrackingDriver;
|
|
4113
4425
|
};
|
|
4426
|
+
var setDefaultUsageTrackingDriver = (driver) => {
|
|
4427
|
+
defaultUsageTrackingDriver = driver;
|
|
4428
|
+
};
|
|
4114
4429
|
var getDefaultDiscoveryAdapter = async () => createDiscoveryAdapterFromStore(await getDefaultSdkStore());
|
|
4115
4430
|
var getDefaultStorageAdapter = async () => createStorageAdapterFromStore(await getDefaultSdkStore());
|
|
4116
4431
|
var getDefaultProviderRegistry = async () => createProviderRegistryFromStore(await getDefaultSdkStore());
|
|
4117
4432
|
function createSSEParserTransform(onUsage, onResponseId) {
|
|
4118
4433
|
let buffer = "";
|
|
4434
|
+
let usageCaptured = false;
|
|
4435
|
+
let responseIdCaptured = false;
|
|
4119
4436
|
const maybeCaptureUsageFromJson = (jsonText) => {
|
|
4120
4437
|
try {
|
|
4121
4438
|
const data = JSON.parse(jsonText);
|
|
4122
4439
|
const responseId = data.id;
|
|
4123
4440
|
if (typeof responseId === "string" && responseId.trim().length > 0) {
|
|
4124
4441
|
onResponseId?.(responseId.trim());
|
|
4442
|
+
responseIdCaptured = true;
|
|
4125
4443
|
}
|
|
4126
4444
|
const usage = extractUsageFromSSEJson(data);
|
|
4127
4445
|
if (usage) {
|
|
4128
4446
|
onUsage(usage);
|
|
4447
|
+
usageCaptured = true;
|
|
4129
4448
|
}
|
|
4130
4449
|
} catch {
|
|
4131
4450
|
}
|
|
@@ -4181,7 +4500,7 @@ function createSSEParserTransform(onUsage, onResponseId) {
|
|
|
4181
4500
|
}
|
|
4182
4501
|
var TOPUP_MARGIN = 1.2;
|
|
4183
4502
|
var RoutstrClient = class {
|
|
4184
|
-
constructor(walletAdapter, storageAdapter, providerRegistry, alertLevel, mode = "xcashu") {
|
|
4503
|
+
constructor(walletAdapter, storageAdapter, providerRegistry, alertLevel, mode = "xcashu", options = {}) {
|
|
4185
4504
|
this.walletAdapter = walletAdapter;
|
|
4186
4505
|
this.storageAdapter = storageAdapter;
|
|
4187
4506
|
this.providerRegistry = providerRegistry;
|
|
@@ -4197,15 +4516,11 @@ var RoutstrClient = class {
|
|
|
4197
4516
|
this.balanceManager
|
|
4198
4517
|
);
|
|
4199
4518
|
this.streamProcessor = new StreamProcessor();
|
|
4200
|
-
this.providerManager = new ProviderManager(providerRegistry);
|
|
4201
4519
|
this.alertLevel = alertLevel;
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
} else {
|
|
4207
|
-
this.mode = mode;
|
|
4208
|
-
}
|
|
4520
|
+
this.mode = mode;
|
|
4521
|
+
this.usageTrackingDriver = options.usageTrackingDriver;
|
|
4522
|
+
this.sdkStore = options.sdkStore;
|
|
4523
|
+
this.providerManager = options.providerManager ?? new ProviderManager(providerRegistry, this.sdkStore);
|
|
4209
4524
|
}
|
|
4210
4525
|
cashuSpender;
|
|
4211
4526
|
balanceManager;
|
|
@@ -4214,6 +4529,8 @@ var RoutstrClient = class {
|
|
|
4214
4529
|
alertLevel;
|
|
4215
4530
|
mode;
|
|
4216
4531
|
debugLevel = "WARN";
|
|
4532
|
+
usageTrackingDriver;
|
|
4533
|
+
sdkStore;
|
|
4217
4534
|
/**
|
|
4218
4535
|
* Get the current client mode
|
|
4219
4536
|
*/
|
|
@@ -4283,11 +4600,13 @@ var RoutstrClient = class {
|
|
|
4283
4600
|
const satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4284
4601
|
token: prepared.tokenUsed,
|
|
4285
4602
|
baseUrl: prepared.baseUrlUsed,
|
|
4603
|
+
mintUrl: params.mintUrl,
|
|
4286
4604
|
initialTokenBalance: prepared.tokenBalanceInSats,
|
|
4287
4605
|
response: prepared.response,
|
|
4288
4606
|
modelId: prepared.modelId,
|
|
4289
4607
|
usage: prepared.capturedUsage,
|
|
4290
|
-
requestId: prepared.capturedResponseId
|
|
4608
|
+
requestId: prepared.capturedResponseId,
|
|
4609
|
+
clientApiKey: prepared.clientApiKey
|
|
4291
4610
|
});
|
|
4292
4611
|
prepared.response.satsSpent = satsSpent;
|
|
4293
4612
|
prepared.response.usage = prepared.capturedUsage;
|
|
@@ -4306,11 +4625,13 @@ var RoutstrClient = class {
|
|
|
4306
4625
|
const satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4307
4626
|
token: prepared.tokenUsed,
|
|
4308
4627
|
baseUrl: prepared.baseUrlUsed,
|
|
4628
|
+
mintUrl: params.mintUrl,
|
|
4309
4629
|
initialTokenBalance: prepared.tokenBalanceInSats,
|
|
4310
4630
|
response: prepared.response,
|
|
4311
4631
|
modelId: prepared.modelId,
|
|
4312
4632
|
usage: prepared.capturedUsage,
|
|
4313
|
-
requestId: prepared.capturedResponseId
|
|
4633
|
+
requestId: prepared.capturedResponseId,
|
|
4634
|
+
clientApiKey: prepared.clientApiKey
|
|
4314
4635
|
});
|
|
4315
4636
|
prepared.response.satsSpent = satsSpent;
|
|
4316
4637
|
res.end();
|
|
@@ -4326,11 +4647,13 @@ var RoutstrClient = class {
|
|
|
4326
4647
|
const satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4327
4648
|
token: prepared.tokenUsed,
|
|
4328
4649
|
baseUrl: prepared.baseUrlUsed,
|
|
4650
|
+
mintUrl: params.mintUrl,
|
|
4329
4651
|
initialTokenBalance: prepared.tokenBalanceInSats,
|
|
4330
4652
|
response: prepared.response,
|
|
4331
4653
|
modelId: prepared.modelId,
|
|
4332
4654
|
usage: prepared.capturedUsage,
|
|
4333
|
-
requestId: prepared.capturedResponseId
|
|
4655
|
+
requestId: prepared.capturedResponseId,
|
|
4656
|
+
clientApiKey: prepared.clientApiKey
|
|
4334
4657
|
});
|
|
4335
4658
|
prepared.response.satsSpent = satsSpent;
|
|
4336
4659
|
prepared.response.usage = prepared.capturedUsage;
|
|
@@ -4360,8 +4683,10 @@ var RoutstrClient = class {
|
|
|
4360
4683
|
headers = {},
|
|
4361
4684
|
baseUrl,
|
|
4362
4685
|
mintUrl,
|
|
4363
|
-
modelId
|
|
4686
|
+
modelId,
|
|
4687
|
+
clientApiKey: providedClientApiKey
|
|
4364
4688
|
} = params;
|
|
4689
|
+
const clientApiKey = providedClientApiKey ?? this._extractClientApiKey(headers);
|
|
4365
4690
|
await this._checkBalance();
|
|
4366
4691
|
let requiredSats = 1;
|
|
4367
4692
|
let selectedModel;
|
|
@@ -4383,7 +4708,6 @@ var RoutstrClient = class {
|
|
|
4383
4708
|
amount: requiredSats,
|
|
4384
4709
|
baseUrl
|
|
4385
4710
|
});
|
|
4386
|
-
this._log("DEBUG", token, baseUrl);
|
|
4387
4711
|
let requestBody = body;
|
|
4388
4712
|
if (body && typeof body === "object") {
|
|
4389
4713
|
const bodyObj = body;
|
|
@@ -4391,7 +4715,7 @@ var RoutstrClient = class {
|
|
|
4391
4715
|
requestBody = { ...bodyObj, stream: false };
|
|
4392
4716
|
}
|
|
4393
4717
|
}
|
|
4394
|
-
const baseHeaders = this._buildBaseHeaders(
|
|
4718
|
+
const baseHeaders = this._buildBaseHeaders();
|
|
4395
4719
|
const requestHeaders = this._withAuthHeader(baseHeaders, token);
|
|
4396
4720
|
const response = await this._makeRequest({
|
|
4397
4721
|
path,
|
|
@@ -4443,9 +4767,21 @@ var RoutstrClient = class {
|
|
|
4443
4767
|
tokenBalanceInSats,
|
|
4444
4768
|
modelId,
|
|
4445
4769
|
capturedUsage,
|
|
4446
|
-
capturedResponseId
|
|
4770
|
+
capturedResponseId,
|
|
4771
|
+
clientApiKey
|
|
4447
4772
|
};
|
|
4448
4773
|
}
|
|
4774
|
+
/**
|
|
4775
|
+
* Extract clientApiKey from Authorization Bearer token if present
|
|
4776
|
+
*/
|
|
4777
|
+
_extractClientApiKey(headers) {
|
|
4778
|
+
const authHeader = headers["Authorization"] || headers["authorization"];
|
|
4779
|
+
if (authHeader?.startsWith("Bearer ")) {
|
|
4780
|
+
const extractedKey = authHeader.slice(7);
|
|
4781
|
+
return extractedKey;
|
|
4782
|
+
}
|
|
4783
|
+
return void 0;
|
|
4784
|
+
}
|
|
4449
4785
|
/**
|
|
4450
4786
|
* Fetch AI response with streaming
|
|
4451
4787
|
*/
|
|
@@ -4549,6 +4885,7 @@ var RoutstrClient = class {
|
|
|
4549
4885
|
let satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4550
4886
|
token,
|
|
4551
4887
|
baseUrl: baseUrlUsed,
|
|
4888
|
+
mintUrl,
|
|
4552
4889
|
initialTokenBalance: tokenBalanceInSats,
|
|
4553
4890
|
fallbackSatsSpent: isApikeysEstimate ? this._getEstimatedCosts(selectedModel, streamingResult) : void 0,
|
|
4554
4891
|
response,
|
|
@@ -4587,7 +4924,6 @@ var RoutstrClient = class {
|
|
|
4587
4924
|
try {
|
|
4588
4925
|
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
4589
4926
|
if (this.mode === "xcashu") this._log("DEBUG", "HEADERS,", headers);
|
|
4590
|
-
this._log("DEBUG", "HEADERS,", headers);
|
|
4591
4927
|
const response = await fetch(url, {
|
|
4592
4928
|
method,
|
|
4593
4929
|
headers,
|
|
@@ -4656,8 +4992,6 @@ var RoutstrClient = class {
|
|
|
4656
4992
|
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${tryReceiveTokenResult.amount}`
|
|
4657
4993
|
);
|
|
4658
4994
|
tryNextProvider = true;
|
|
4659
|
-
if (this.mode === "lazyrefund")
|
|
4660
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
4661
4995
|
} else {
|
|
4662
4996
|
this._log(
|
|
4663
4997
|
"DEBUG",
|
|
@@ -4705,24 +5039,21 @@ var RoutstrClient = class {
|
|
|
4705
5039
|
);
|
|
4706
5040
|
}
|
|
4707
5041
|
}
|
|
4708
|
-
if (status === 402 && !tryNextProvider &&
|
|
5042
|
+
if (status === 402 && !tryNextProvider && this.mode === "apikeys") {
|
|
4709
5043
|
this.storageAdapter.getApiKey(baseUrl);
|
|
4710
5044
|
let topupAmount = params.requiredSats;
|
|
4711
5045
|
try {
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
);
|
|
4718
|
-
currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1e3 : currentBalanceInfo.amount;
|
|
4719
|
-
} else if (this.mode === "lazyrefund") {
|
|
4720
|
-
const distribution = this.storageAdapter.getCachedTokenDistribution();
|
|
4721
|
-
const tokenEntry = distribution.find((t) => t.baseUrl === baseUrl);
|
|
4722
|
-
currentBalance = tokenEntry?.amount ?? 0;
|
|
4723
|
-
}
|
|
5046
|
+
const currentBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
5047
|
+
params.token,
|
|
5048
|
+
baseUrl
|
|
5049
|
+
);
|
|
5050
|
+
const currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1e3 : currentBalanceInfo.amount;
|
|
4724
5051
|
const shortfall = Math.max(0, params.requiredSats - currentBalance);
|
|
4725
5052
|
topupAmount = shortfall > 0 ? shortfall : params.requiredSats;
|
|
5053
|
+
this._log(
|
|
5054
|
+
"DEBUG",
|
|
5055
|
+
`The shortfall is: ${shortfall}. requiredSats: ${params.requiredSats}. Current Balance: ${currentBalance} `
|
|
5056
|
+
);
|
|
4726
5057
|
} catch (e) {
|
|
4727
5058
|
this._log(
|
|
4728
5059
|
"WARN",
|
|
@@ -4852,61 +5183,49 @@ var RoutstrClient = class {
|
|
|
4852
5183
|
tryNextProvider = true;
|
|
4853
5184
|
}
|
|
4854
5185
|
}
|
|
5186
|
+
if (status === 401 && this.mode === "apikeys") {
|
|
5187
|
+
this._log(
|
|
5188
|
+
"DEBUG",
|
|
5189
|
+
`[RoutstrClient] _handleErrorResponse: Checking balance for ${baseUrl}, key preview=${token}`
|
|
5190
|
+
);
|
|
5191
|
+
const latestBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
5192
|
+
token,
|
|
5193
|
+
baseUrl
|
|
5194
|
+
);
|
|
5195
|
+
if (latestBalanceInfo.isInvalidApiKey) {
|
|
5196
|
+
this.storageAdapter.removeApiKey(baseUrl);
|
|
5197
|
+
tryNextProvider = true;
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
4855
5200
|
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
4856
5201
|
this._log(
|
|
4857
5202
|
"DEBUG",
|
|
4858
5203
|
`[RoutstrClient] _handleErrorResponse: Status ${status} (auth/server error), attempting refund for ${baseUrl}, mode=${this.mode}`
|
|
4859
5204
|
);
|
|
4860
|
-
if (this.mode === "
|
|
4861
|
-
try {
|
|
4862
|
-
const refundResult = await this.balanceManager.refund({
|
|
4863
|
-
mintUrl,
|
|
4864
|
-
baseUrl,
|
|
4865
|
-
token: params.token
|
|
4866
|
-
});
|
|
4867
|
-
this._log(
|
|
4868
|
-
"DEBUG",
|
|
4869
|
-
`[RoutstrClient] _handleErrorResponse: Lazyrefund result: success=${refundResult.success}`
|
|
4870
|
-
);
|
|
4871
|
-
if (refundResult.success) this.storageAdapter.removeToken(baseUrl);
|
|
4872
|
-
else
|
|
4873
|
-
throw new ProviderError(
|
|
4874
|
-
baseUrl,
|
|
4875
|
-
status,
|
|
4876
|
-
"refund failed",
|
|
4877
|
-
requestId
|
|
4878
|
-
);
|
|
4879
|
-
} catch (error) {
|
|
4880
|
-
throw new ProviderError(
|
|
4881
|
-
baseUrl,
|
|
4882
|
-
status,
|
|
4883
|
-
"Failed to refund token",
|
|
4884
|
-
requestId
|
|
4885
|
-
);
|
|
4886
|
-
}
|
|
4887
|
-
} else if (this.mode === "apikeys") {
|
|
5205
|
+
if (this.mode === "apikeys") {
|
|
4888
5206
|
this._log(
|
|
4889
5207
|
"DEBUG",
|
|
4890
5208
|
`[RoutstrClient] _handleErrorResponse: Attempting API key refund for ${baseUrl}, key preview=${token}`
|
|
4891
5209
|
);
|
|
4892
|
-
const
|
|
5210
|
+
const latestBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
4893
5211
|
token,
|
|
4894
5212
|
baseUrl
|
|
4895
5213
|
);
|
|
4896
5214
|
this._log(
|
|
4897
5215
|
"DEBUG",
|
|
4898
|
-
`[RoutstrClient] _handleErrorResponse: Initial API key balance: ${
|
|
5216
|
+
`[RoutstrClient] _handleErrorResponse: Initial API key balance: ${latestBalanceInfo.amount}`
|
|
4899
5217
|
);
|
|
4900
5218
|
const refundResult = await this.balanceManager.refundApiKey({
|
|
4901
5219
|
mintUrl,
|
|
4902
5220
|
baseUrl,
|
|
4903
|
-
apiKey: token
|
|
5221
|
+
apiKey: token,
|
|
5222
|
+
forceRefund: true
|
|
4904
5223
|
});
|
|
4905
5224
|
this._log(
|
|
4906
5225
|
"DEBUG",
|
|
4907
5226
|
`[RoutstrClient] _handleErrorResponse: API key refund result: success=${refundResult.success}, message=${refundResult.message}`
|
|
4908
5227
|
);
|
|
4909
|
-
if (!refundResult.success &&
|
|
5228
|
+
if (!refundResult.success && latestBalanceInfo.amount > 0) {
|
|
4910
5229
|
throw new ProviderError(
|
|
4911
5230
|
baseUrl,
|
|
4912
5231
|
status,
|
|
@@ -4982,12 +5301,14 @@ var RoutstrClient = class {
|
|
|
4982
5301
|
const {
|
|
4983
5302
|
token,
|
|
4984
5303
|
baseUrl,
|
|
5304
|
+
mintUrl,
|
|
4985
5305
|
initialTokenBalance,
|
|
4986
5306
|
fallbackSatsSpent,
|
|
4987
5307
|
response,
|
|
4988
5308
|
modelId,
|
|
4989
5309
|
usage,
|
|
4990
|
-
requestId
|
|
5310
|
+
requestId,
|
|
5311
|
+
clientApiKey
|
|
4991
5312
|
} = params;
|
|
4992
5313
|
let satsSpent = initialTokenBalance;
|
|
4993
5314
|
if (this.mode === "xcashu" && response) {
|
|
@@ -4995,19 +5316,14 @@ var RoutstrClient = class {
|
|
|
4995
5316
|
if (refundToken) {
|
|
4996
5317
|
try {
|
|
4997
5318
|
const receiveResult = await this.cashuSpender.receiveToken(refundToken);
|
|
4998
|
-
|
|
5319
|
+
if (receiveResult.success) {
|
|
5320
|
+
this.storageAdapter.removeXcashuToken(baseUrl, token);
|
|
5321
|
+
satsSpent = initialTokenBalance - receiveResult.amount * (receiveResult.unit == "sat" ? 1 : 1e3);
|
|
5322
|
+
}
|
|
4999
5323
|
} catch (error) {
|
|
5000
5324
|
this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
|
|
5001
5325
|
}
|
|
5002
5326
|
}
|
|
5003
|
-
} else if (this.mode === "lazyrefund") {
|
|
5004
|
-
const latestBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
5005
|
-
token,
|
|
5006
|
-
baseUrl
|
|
5007
|
-
);
|
|
5008
|
-
const latestTokenBalance = latestBalanceInfo.unit === "msat" ? latestBalanceInfo.amount / 1e3 : latestBalanceInfo.amount;
|
|
5009
|
-
this.storageAdapter.updateTokenBalance(baseUrl, latestTokenBalance);
|
|
5010
|
-
satsSpent = initialTokenBalance - latestTokenBalance;
|
|
5011
5327
|
} else if (this.mode === "apikeys") {
|
|
5012
5328
|
try {
|
|
5013
5329
|
const latestBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
@@ -5042,8 +5358,17 @@ var RoutstrClient = class {
|
|
|
5042
5358
|
modelId,
|
|
5043
5359
|
satsSpent,
|
|
5044
5360
|
usage,
|
|
5045
|
-
requestId
|
|
5361
|
+
requestId,
|
|
5362
|
+
clientApiKey
|
|
5046
5363
|
});
|
|
5364
|
+
(async () => {
|
|
5365
|
+
try {
|
|
5366
|
+
const xcashuResults = await this.cashuSpender.refundXcashuTokens(mintUrl);
|
|
5367
|
+
this._log("DEBUG", "Refund xcashu tokens results:", xcashuResults);
|
|
5368
|
+
} catch (error) {
|
|
5369
|
+
this._log("ERROR", "Failed to refund providers:", error);
|
|
5370
|
+
}
|
|
5371
|
+
})();
|
|
5047
5372
|
return satsSpent;
|
|
5048
5373
|
}
|
|
5049
5374
|
async _trackResponseUsage(params) {
|
|
@@ -5054,7 +5379,8 @@ var RoutstrClient = class {
|
|
|
5054
5379
|
modelId,
|
|
5055
5380
|
satsSpent,
|
|
5056
5381
|
usage: providedUsage,
|
|
5057
|
-
requestId: providedRequestId
|
|
5382
|
+
requestId: providedRequestId,
|
|
5383
|
+
clientApiKey
|
|
5058
5384
|
} = params;
|
|
5059
5385
|
if (!response || !modelId) {
|
|
5060
5386
|
return;
|
|
@@ -5081,13 +5407,14 @@ var RoutstrClient = class {
|
|
|
5081
5407
|
return;
|
|
5082
5408
|
}
|
|
5083
5409
|
const finalRequestId = requestId || "unknown";
|
|
5084
|
-
const store = await getDefaultSdkStore();
|
|
5410
|
+
const store = this.sdkStore ?? await getDefaultSdkStore();
|
|
5085
5411
|
const state = store.getState();
|
|
5412
|
+
const matchKey = clientApiKey ?? token;
|
|
5086
5413
|
const matchingClient = state.clientIds.find(
|
|
5087
|
-
(client) => client.apiKey ===
|
|
5414
|
+
(client) => client.apiKey === matchKey
|
|
5088
5415
|
);
|
|
5089
5416
|
const entryId = finalRequestId === "unknown" ? `req-${Date.now()}-${modelId}` : finalRequestId;
|
|
5090
|
-
const usageTracking = getDefaultUsageTrackingDriver();
|
|
5417
|
+
const usageTracking = this.usageTrackingDriver ?? getDefaultUsageTrackingDriver();
|
|
5091
5418
|
const entry = {
|
|
5092
5419
|
id: entryId,
|
|
5093
5420
|
timestamp: Date.now(),
|
|
@@ -5162,11 +5489,11 @@ var RoutstrClient = class {
|
|
|
5162
5489
|
return estimatedCosts;
|
|
5163
5490
|
}
|
|
5164
5491
|
/**
|
|
5165
|
-
* Get pending
|
|
5492
|
+
* Get pending API key amount
|
|
5166
5493
|
*/
|
|
5167
5494
|
_getPendingCashuTokenAmount() {
|
|
5168
|
-
const
|
|
5169
|
-
return
|
|
5495
|
+
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
5496
|
+
return apiKeyDistribution.reduce((total, item) => total + item.amount, 0);
|
|
5170
5497
|
}
|
|
5171
5498
|
/**
|
|
5172
5499
|
* Handle errors and notify callbacks
|
|
@@ -5313,8 +5640,8 @@ var RoutstrClient = class {
|
|
|
5313
5640
|
const spendResult = await this.cashuSpender.spend({
|
|
5314
5641
|
mintUrl,
|
|
5315
5642
|
amount,
|
|
5316
|
-
baseUrl:
|
|
5317
|
-
reuseToken:
|
|
5643
|
+
baseUrl: "",
|
|
5644
|
+
reuseToken: false
|
|
5318
5645
|
});
|
|
5319
5646
|
if (!spendResult.token) {
|
|
5320
5647
|
this._log(
|
|
@@ -5327,6 +5654,7 @@ var RoutstrClient = class {
|
|
|
5327
5654
|
"DEBUG",
|
|
5328
5655
|
`[RoutstrClient] _spendToken: Cashu token created, token preview: ${spendResult.token}, balance: ${spendResult.balance} ${spendResult.unit ?? "sat"}`
|
|
5329
5656
|
);
|
|
5657
|
+
this.storageAdapter.addXcashuToken(baseUrl, spendResult.token);
|
|
5330
5658
|
}
|
|
5331
5659
|
return {
|
|
5332
5660
|
token: spendResult.token,
|
|
@@ -5364,6 +5692,7 @@ async function resolveRouteRequestContext(options) {
|
|
|
5364
5692
|
modelId,
|
|
5365
5693
|
requestBody,
|
|
5366
5694
|
path = "/v1/chat/completions",
|
|
5695
|
+
headers = {},
|
|
5367
5696
|
forcedProvider,
|
|
5368
5697
|
walletAdapter,
|
|
5369
5698
|
storageAdapter,
|
|
@@ -5374,7 +5703,10 @@ async function resolveRouteRequestContext(options) {
|
|
|
5374
5703
|
forceRefresh = false,
|
|
5375
5704
|
modelManager: providedModelManager,
|
|
5376
5705
|
debugLevel,
|
|
5377
|
-
mode = "apikeys"
|
|
5706
|
+
mode = "apikeys",
|
|
5707
|
+
usageTrackingDriver,
|
|
5708
|
+
sdkStore,
|
|
5709
|
+
providerManager: providedProviderManager
|
|
5378
5710
|
} = options;
|
|
5379
5711
|
let modelManager;
|
|
5380
5712
|
let providers;
|
|
@@ -5394,7 +5726,7 @@ async function resolveRouteRequestContext(options) {
|
|
|
5394
5726
|
}
|
|
5395
5727
|
await modelManager.fetchModels(providers, forceRefresh);
|
|
5396
5728
|
}
|
|
5397
|
-
const providerManager = new ProviderManager(providerRegistry);
|
|
5729
|
+
const providerManager = providedProviderManager ?? new ProviderManager(providerRegistry, sdkStore);
|
|
5398
5730
|
let baseUrl;
|
|
5399
5731
|
let selectedModel;
|
|
5400
5732
|
if (forcedProvider) {
|
|
@@ -5438,7 +5770,8 @@ async function resolveRouteRequestContext(options) {
|
|
|
5438
5770
|
storageAdapter,
|
|
5439
5771
|
providerRegistry,
|
|
5440
5772
|
"min",
|
|
5441
|
-
mode
|
|
5773
|
+
mode,
|
|
5774
|
+
{ usageTrackingDriver, sdkStore, providerManager }
|
|
5442
5775
|
);
|
|
5443
5776
|
if (debugLevel) {
|
|
5444
5777
|
client.setDebugLevel(debugLevel);
|
|
@@ -5458,17 +5791,19 @@ async function resolveRouteRequestContext(options) {
|
|
|
5458
5791
|
baseUrl,
|
|
5459
5792
|
mintUrl,
|
|
5460
5793
|
path,
|
|
5794
|
+
headers,
|
|
5461
5795
|
modelId,
|
|
5462
5796
|
proxiedBody
|
|
5463
5797
|
};
|
|
5464
5798
|
}
|
|
5465
5799
|
async function routeRequests(options) {
|
|
5466
|
-
const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5800
|
+
const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5467
5801
|
try {
|
|
5468
5802
|
const response = await client.routeRequest({
|
|
5469
5803
|
path,
|
|
5470
5804
|
method: "POST",
|
|
5471
5805
|
body: proxiedBody,
|
|
5806
|
+
headers,
|
|
5472
5807
|
baseUrl,
|
|
5473
5808
|
mintUrl,
|
|
5474
5809
|
modelId
|
|
@@ -5486,12 +5821,13 @@ async function routeRequests(options) {
|
|
|
5486
5821
|
}
|
|
5487
5822
|
async function routeRequestsToNodeResponse(options) {
|
|
5488
5823
|
const { res } = options;
|
|
5489
|
-
const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5824
|
+
const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5490
5825
|
try {
|
|
5491
5826
|
await client.routeRequestToNodeResponse({
|
|
5492
5827
|
path,
|
|
5493
5828
|
method: "POST",
|
|
5494
5829
|
body: proxiedBody,
|
|
5830
|
+
headers,
|
|
5495
5831
|
baseUrl,
|
|
5496
5832
|
mintUrl,
|
|
5497
5833
|
modelId,
|
|
@@ -5539,6 +5875,8 @@ exports.SDK_STORAGE_KEYS = SDK_STORAGE_KEYS;
|
|
|
5539
5875
|
exports.StreamProcessor = StreamProcessor;
|
|
5540
5876
|
exports.StreamingError = StreamingError;
|
|
5541
5877
|
exports.TokenOperationError = TokenOperationError;
|
|
5878
|
+
exports.createBunSqliteDriver = createBunSqliteDriver;
|
|
5879
|
+
exports.createBunSqliteUsageTrackingDriver = createBunSqliteUsageTrackingDriver;
|
|
5542
5880
|
exports.createDiscoveryAdapterFromStore = createDiscoveryAdapterFromStore;
|
|
5543
5881
|
exports.createIndexedDBDriver = createIndexedDBDriver;
|
|
5544
5882
|
exports.createIndexedDBUsageTrackingDriver = createIndexedDBUsageTrackingDriver;
|
|
@@ -5564,5 +5902,6 @@ exports.localStorageDriver = localStorageDriver;
|
|
|
5564
5902
|
exports.normalizeProviderUrl = normalizeProviderUrl;
|
|
5565
5903
|
exports.routeRequests = routeRequests;
|
|
5566
5904
|
exports.routeRequestsToNodeResponse = routeRequestsToNodeResponse;
|
|
5905
|
+
exports.setDefaultUsageTrackingDriver = setDefaultUsageTrackingDriver;
|
|
5567
5906
|
//# sourceMappingURL=index.js.map
|
|
5568
5907
|
//# sourceMappingURL=index.js.map
|