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