@routstr/sdk 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/client/index.d.mts +19 -5
- package/dist/client/index.d.ts +19 -5
- package/dist/client/index.js +506 -451
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +506 -451
- package/dist/client/index.mjs.map +1 -1
- package/dist/index.d.mts +16 -8
- package/dist/index.d.ts +16 -8
- package/dist/index.js +627 -528
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +625 -529
- 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 +36 -162
- package/dist/storage/index.d.ts +36 -162
- package/dist/storage/index.js +434 -189
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +432 -190
- package/dist/storage/index.mjs.map +1 -1
- package/dist/store-BJlwiDX5.d.ts +151 -0
- package/dist/store-C5lnyX8k.d.mts +151 -0
- package/dist/wallet/index.d.mts +18 -24
- package/dist/wallet/index.d.ts +18 -24
- package/dist/wallet/index.js +106 -255
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +106 -255
- 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) {
|
|
@@ -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,108 @@ 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 and increment tryCounts on failure.
|
|
1085
|
+
* Reuses receiveToken from BalanceManager/CashuSpender for receiving refunds.
|
|
1086
|
+
* @param mintUrl - The mint URL for receiving tokens
|
|
1087
|
+
* @param excludeBaseUrls - Base URLs to exclude from refund (optional)
|
|
1088
|
+
* @returns Results for each xcashu token refund attempt
|
|
1113
1089
|
*/
|
|
1114
|
-
async
|
|
1090
|
+
async refundXcashuTokens(mintUrl, excludeBaseUrls) {
|
|
1115
1091
|
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
|
-
(r) => r.status === "fulfilled" ? r.value : { baseUrl: "", success: false }
|
|
1149
|
-
)
|
|
1150
|
-
);
|
|
1151
|
-
if (refundApiKeys) {
|
|
1152
|
-
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
1153
|
-
const apiKeysToRefund = apiKeyDistribution.filter(
|
|
1154
|
-
(p) => baseUrls.includes(p.baseUrl)
|
|
1155
|
-
);
|
|
1156
|
-
for (const apiKeyEntry of apiKeysToRefund) {
|
|
1157
|
-
const apiKeyEntryFull = this.storageAdapter.getApiKey(
|
|
1158
|
-
apiKeyEntry.baseUrl
|
|
1159
|
-
);
|
|
1160
|
-
if (apiKeyEntryFull && this.balanceManager) {
|
|
1161
|
-
const refundResult = await this.balanceManager.refundApiKey({
|
|
1162
|
-
mintUrl,
|
|
1163
|
-
baseUrl: apiKeyEntry.baseUrl,
|
|
1164
|
-
apiKey: apiKeyEntryFull.key,
|
|
1165
|
-
forceRefund
|
|
1166
|
-
});
|
|
1167
|
-
if (refundResult.success) {
|
|
1168
|
-
this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, 0);
|
|
1092
|
+
const xcashuTokens = this.storageAdapter.getXcashuTokens();
|
|
1093
|
+
const excludedUrls = new Set(excludeBaseUrls || []);
|
|
1094
|
+
for (const [baseUrl, tokens] of Object.entries(xcashuTokens)) {
|
|
1095
|
+
if (excludedUrls.has(baseUrl)) continue;
|
|
1096
|
+
for (const xcashuToken of tokens) {
|
|
1097
|
+
try {
|
|
1098
|
+
const receiveResult = await this.receiveToken(xcashuToken.token);
|
|
1099
|
+
if (receiveResult.success) {
|
|
1100
|
+
this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
|
|
1101
|
+
results.push({
|
|
1102
|
+
baseUrl,
|
|
1103
|
+
token: xcashuToken.token,
|
|
1104
|
+
success: true
|
|
1105
|
+
});
|
|
1106
|
+
this._log(
|
|
1107
|
+
"DEBUG",
|
|
1108
|
+
`[CashuSpender] refundXcashuTokens: Successfully refunded xcashu token for ${baseUrl}, amount=${receiveResult.amount}`
|
|
1109
|
+
);
|
|
1110
|
+
} else {
|
|
1111
|
+
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
1112
|
+
const newTryCount = currentTryCount + 1;
|
|
1113
|
+
this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
|
|
1114
|
+
results.push({
|
|
1115
|
+
baseUrl,
|
|
1116
|
+
token: xcashuToken.token,
|
|
1117
|
+
success: false,
|
|
1118
|
+
error: receiveResult.message ?? "Refund failed"
|
|
1119
|
+
});
|
|
1120
|
+
this._log(
|
|
1121
|
+
"DEBUG",
|
|
1122
|
+
`[CashuSpender] refundXcashuTokens: Failed to refund xcashu token for ${baseUrl}, incremented tryCount to ${newTryCount}`
|
|
1123
|
+
);
|
|
1169
1124
|
}
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
1127
|
+
const newTryCount = currentTryCount + 1;
|
|
1128
|
+
this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
|
|
1129
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1170
1130
|
results.push({
|
|
1171
|
-
baseUrl
|
|
1172
|
-
|
|
1131
|
+
baseUrl,
|
|
1132
|
+
token: xcashuToken.token,
|
|
1133
|
+
success: false,
|
|
1134
|
+
error: errorMessage
|
|
1173
1135
|
});
|
|
1136
|
+
this._log(
|
|
1137
|
+
"ERROR",
|
|
1138
|
+
`[CashuSpender] refundXcashuTokens: Exception during refund for ${baseUrl}: ${errorMessage}, incremented tryCount to ${newTryCount}`
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
return results;
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Refund specific providers without retrying spend
|
|
1147
|
+
*/
|
|
1148
|
+
async refundProviders(mintUrl, forceRefund) {
|
|
1149
|
+
const results = [];
|
|
1150
|
+
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
1151
|
+
for (const apiKeyEntry of apiKeyDistribution) {
|
|
1152
|
+
const apiKeyEntryFull = this.storageAdapter.getApiKey(
|
|
1153
|
+
apiKeyEntry.baseUrl
|
|
1154
|
+
);
|
|
1155
|
+
if (apiKeyEntryFull && this.balanceManager) {
|
|
1156
|
+
const refundResult = await this.balanceManager.refundApiKey({
|
|
1157
|
+
mintUrl,
|
|
1158
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
1159
|
+
apiKey: apiKeyEntryFull.key,
|
|
1160
|
+
forceRefund
|
|
1161
|
+
});
|
|
1162
|
+
if (refundResult.success) {
|
|
1163
|
+
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
1174
1164
|
} else {
|
|
1175
|
-
|
|
1176
|
-
baseUrl: apiKeyEntry.baseUrl,
|
|
1177
|
-
success: false
|
|
1178
|
-
});
|
|
1165
|
+
this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, apiKeyEntry.amount);
|
|
1179
1166
|
}
|
|
1167
|
+
results.push({
|
|
1168
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
1169
|
+
success: refundResult.success
|
|
1170
|
+
});
|
|
1171
|
+
} else {
|
|
1172
|
+
results.push({
|
|
1173
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
1174
|
+
success: false
|
|
1175
|
+
});
|
|
1180
1176
|
}
|
|
1181
1177
|
}
|
|
1182
1178
|
return results;
|
|
@@ -1261,13 +1257,8 @@ var BalanceManager = class {
|
|
|
1261
1257
|
normalizedMintBalances[url] = balanceInSats;
|
|
1262
1258
|
totalMintBalance += balanceInSats;
|
|
1263
1259
|
}
|
|
1264
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
1265
1260
|
const providerBalances = {};
|
|
1266
1261
|
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
1262
|
const apiKeys = this.storageAdapter.getAllApiKeys();
|
|
1272
1263
|
for (const apiKey of apiKeys) {
|
|
1273
1264
|
if (!providerBalances[apiKey.baseUrl]) {
|
|
@@ -1282,57 +1273,6 @@ var BalanceManager = class {
|
|
|
1282
1273
|
mintBalances: normalizedMintBalances
|
|
1283
1274
|
};
|
|
1284
1275
|
}
|
|
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
1276
|
/**
|
|
1337
1277
|
* Refund API key balance - convert remaining API key balance to cashu token
|
|
1338
1278
|
* @param options - Refund options including forceRefund flag
|
|
@@ -1468,8 +1408,9 @@ var BalanceManager = class {
|
|
|
1468
1408
|
if (!amount || amount <= 0) {
|
|
1469
1409
|
return { success: false, message: "Invalid top up amount" };
|
|
1470
1410
|
}
|
|
1471
|
-
const
|
|
1472
|
-
|
|
1411
|
+
const apiKeyEntry = providedToken ? null : this.storageAdapter.getApiKey(baseUrl);
|
|
1412
|
+
const apiKey = providedToken || apiKeyEntry?.key;
|
|
1413
|
+
if (!apiKey) {
|
|
1473
1414
|
return { success: false, message: "No API key available for top up" };
|
|
1474
1415
|
}
|
|
1475
1416
|
let cashuToken = null;
|
|
@@ -1489,7 +1430,7 @@ var BalanceManager = class {
|
|
|
1489
1430
|
cashuToken = tokenResult.token;
|
|
1490
1431
|
const topUpResult = await this._postTopUp(
|
|
1491
1432
|
baseUrl,
|
|
1492
|
-
|
|
1433
|
+
apiKey,
|
|
1493
1434
|
cashuToken
|
|
1494
1435
|
);
|
|
1495
1436
|
requestId = topUpResult.requestId;
|
|
@@ -1704,38 +1645,11 @@ var BalanceManager = class {
|
|
|
1704
1645
|
return candidates;
|
|
1705
1646
|
}
|
|
1706
1647
|
async _refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount) {
|
|
1707
|
-
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
1708
1648
|
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
1709
1649
|
const forceRefund = retryCount >= 2;
|
|
1710
|
-
const toRefund = pendingDistribution.filter(
|
|
1711
|
-
(pending) => pending.baseUrl !== baseUrl
|
|
1712
|
-
);
|
|
1713
1650
|
const apiKeysToRefund = apiKeyDistribution.filter(
|
|
1714
1651
|
(apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0
|
|
1715
1652
|
);
|
|
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
1653
|
const apiKeyRefundResults = await Promise.allSettled(
|
|
1740
1654
|
apiKeysToRefund.map(async (apiKeyEntry) => {
|
|
1741
1655
|
const fullApiKeyEntry = this.storageAdapter.getApiKey(
|
|
@@ -1759,77 +1673,6 @@ var BalanceManager = class {
|
|
|
1759
1673
|
}
|
|
1760
1674
|
}
|
|
1761
1675
|
}
|
|
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
1676
|
/**
|
|
1834
1677
|
* Post topup request to provider API
|
|
1835
1678
|
*/
|
|
@@ -2874,38 +2717,54 @@ var createMemoryDriver = (seed) => {
|
|
|
2874
2717
|
var isBun = () => {
|
|
2875
2718
|
return typeof process.versions.bun !== "undefined";
|
|
2876
2719
|
};
|
|
2877
|
-
var
|
|
2720
|
+
var cachedDbModule = null;
|
|
2721
|
+
var loadDatabase = async (dbPath) => {
|
|
2878
2722
|
if (isBun()) {
|
|
2879
2723
|
throw new Error(
|
|
2880
|
-
"SQLite driver not supported in Bun. Use
|
|
2724
|
+
"SQLite driver not supported in Bun. Use createBunSqliteDriver() instead."
|
|
2881
2725
|
);
|
|
2882
2726
|
}
|
|
2883
|
-
let Database = null;
|
|
2884
2727
|
try {
|
|
2885
|
-
|
|
2728
|
+
if (!cachedDbModule) {
|
|
2729
|
+
cachedDbModule = (await import('better-sqlite3')).default;
|
|
2730
|
+
}
|
|
2731
|
+
return new cachedDbModule(dbPath);
|
|
2886
2732
|
} catch (error) {
|
|
2887
2733
|
throw new Error(
|
|
2888
2734
|
`better-sqlite3 is required for sqlite storage. Install it to use sqlite storage. (${error})`
|
|
2889
2735
|
);
|
|
2890
2736
|
}
|
|
2891
|
-
return new Database(dbPath);
|
|
2892
2737
|
};
|
|
2893
2738
|
var createSqliteDriver = (options = {}) => {
|
|
2894
2739
|
const dbPath = options.dbPath || "routstr.sqlite";
|
|
2895
2740
|
const tableName = options.tableName || "sdk_storage";
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
const
|
|
2901
|
-
|
|
2902
|
-
|
|
2741
|
+
let db;
|
|
2742
|
+
let selectStmt;
|
|
2743
|
+
let upsertStmt;
|
|
2744
|
+
let deleteStmt;
|
|
2745
|
+
const initDb = async () => {
|
|
2746
|
+
if (!db) {
|
|
2747
|
+
db = await loadDatabase(dbPath);
|
|
2748
|
+
db.exec(
|
|
2749
|
+
`CREATE TABLE IF NOT EXISTS ${tableName} (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
|
|
2750
|
+
);
|
|
2751
|
+
selectStmt = db.prepare(`SELECT value FROM ${tableName} WHERE key = ?`);
|
|
2752
|
+
upsertStmt = db.prepare(
|
|
2753
|
+
`INSERT INTO ${tableName} (key, value) VALUES (?, ?)
|
|
2903
2754
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
2904
|
-
|
|
2905
|
-
|
|
2755
|
+
);
|
|
2756
|
+
deleteStmt = db.prepare(`DELETE FROM ${tableName} WHERE key = ?`);
|
|
2757
|
+
}
|
|
2758
|
+
};
|
|
2759
|
+
const ensureInit = async () => {
|
|
2760
|
+
if (!db) {
|
|
2761
|
+
await initDb();
|
|
2762
|
+
}
|
|
2763
|
+
};
|
|
2906
2764
|
return {
|
|
2907
2765
|
async getItem(key, defaultValue) {
|
|
2908
2766
|
try {
|
|
2767
|
+
await ensureInit();
|
|
2909
2768
|
const row = selectStmt.get(key);
|
|
2910
2769
|
if (!row || typeof row.value !== "string") return defaultValue;
|
|
2911
2770
|
try {
|
|
@@ -2923,6 +2782,7 @@ var createSqliteDriver = (options = {}) => {
|
|
|
2923
2782
|
},
|
|
2924
2783
|
async setItem(key, value) {
|
|
2925
2784
|
try {
|
|
2785
|
+
await ensureInit();
|
|
2926
2786
|
upsertStmt.run(key, JSON.stringify(value));
|
|
2927
2787
|
} catch (error) {
|
|
2928
2788
|
console.error(`SQLite setItem failed for key "${key}":`, error);
|
|
@@ -2930,6 +2790,7 @@ var createSqliteDriver = (options = {}) => {
|
|
|
2930
2790
|
},
|
|
2931
2791
|
async removeItem(key) {
|
|
2932
2792
|
try {
|
|
2793
|
+
await ensureInit();
|
|
2933
2794
|
deleteStmt.run(key);
|
|
2934
2795
|
} catch (error) {
|
|
2935
2796
|
console.error(`SQLite removeItem failed for key "${key}":`, error);
|
|
@@ -2937,6 +2798,54 @@ var createSqliteDriver = (options = {}) => {
|
|
|
2937
2798
|
}
|
|
2938
2799
|
};
|
|
2939
2800
|
};
|
|
2801
|
+
async function createBunSqliteDriver(dbPath) {
|
|
2802
|
+
const SQLite = (await import(
|
|
2803
|
+
/* webpackIgnore: true */
|
|
2804
|
+
'bun:sqlite'
|
|
2805
|
+
)).default;
|
|
2806
|
+
const db = new SQLite(dbPath);
|
|
2807
|
+
db.run(`
|
|
2808
|
+
CREATE TABLE IF NOT EXISTS sdk_storage (
|
|
2809
|
+
key TEXT PRIMARY KEY,
|
|
2810
|
+
value TEXT NOT NULL
|
|
2811
|
+
)
|
|
2812
|
+
`);
|
|
2813
|
+
return {
|
|
2814
|
+
async getItem(key, defaultValue) {
|
|
2815
|
+
try {
|
|
2816
|
+
const row = db.query("SELECT value FROM sdk_storage WHERE key = ?").get(key);
|
|
2817
|
+
if (!row || typeof row.value !== "string") return defaultValue;
|
|
2818
|
+
try {
|
|
2819
|
+
return JSON.parse(row.value);
|
|
2820
|
+
} catch (parseError) {
|
|
2821
|
+
if (typeof defaultValue === "string") {
|
|
2822
|
+
return row.value;
|
|
2823
|
+
}
|
|
2824
|
+
throw parseError;
|
|
2825
|
+
}
|
|
2826
|
+
} catch (error) {
|
|
2827
|
+
console.error(`SQLite getItem failed for key "${key}":`, error);
|
|
2828
|
+
return defaultValue;
|
|
2829
|
+
}
|
|
2830
|
+
},
|
|
2831
|
+
async setItem(key, value) {
|
|
2832
|
+
try {
|
|
2833
|
+
db.query(
|
|
2834
|
+
"INSERT INTO sdk_storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
2835
|
+
).run(key, JSON.stringify(value));
|
|
2836
|
+
} catch (error) {
|
|
2837
|
+
console.error(`SQLite setItem failed for key "${key}":`, error);
|
|
2838
|
+
}
|
|
2839
|
+
},
|
|
2840
|
+
async removeItem(key) {
|
|
2841
|
+
try {
|
|
2842
|
+
db.query("DELETE FROM sdk_storage WHERE key = ?").run(key);
|
|
2843
|
+
} catch (error) {
|
|
2844
|
+
console.error(`SQLite removeItem failed for key "${key}":`, error);
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
};
|
|
2848
|
+
}
|
|
2940
2849
|
|
|
2941
2850
|
// storage/drivers/indexedDB.ts
|
|
2942
2851
|
var isBrowser = typeof indexedDB !== "undefined";
|
|
@@ -3042,9 +2951,9 @@ var SDK_STORAGE_KEYS = {
|
|
|
3042
2951
|
INFO_FROM_ALL_PROVIDERS: "info_from_all_providers",
|
|
3043
2952
|
LAST_MODELS_UPDATE: "lastModelsUpdate",
|
|
3044
2953
|
LAST_BASE_URLS_UPDATE: "lastBaseUrlsUpdate",
|
|
3045
|
-
LOCAL_CASHU_TOKENS: "local_cashu_tokens",
|
|
3046
2954
|
API_KEYS: "api_keys",
|
|
3047
2955
|
CHILD_KEYS: "child_keys",
|
|
2956
|
+
XCASHU_TOKENS: "xcashu_tokens",
|
|
3048
2957
|
ROUTSTR21_MODELS: "routstr21Models",
|
|
3049
2958
|
LAST_ROUTSTR21_MODELS_UPDATE: "lastRoutstr21ModelsUpdate",
|
|
3050
2959
|
CACHED_RECEIVE_TOKENS: "cached_receive_tokens",
|
|
@@ -3235,21 +3144,23 @@ var normalizeBaseUrl2 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUr
|
|
|
3235
3144
|
var isBun2 = () => {
|
|
3236
3145
|
return typeof process.versions.bun !== "undefined";
|
|
3237
3146
|
};
|
|
3238
|
-
var
|
|
3147
|
+
var cachedDbModule2 = null;
|
|
3148
|
+
var loadDatabase2 = async (dbPath) => {
|
|
3239
3149
|
if (isBun2()) {
|
|
3240
3150
|
throw new Error(
|
|
3241
3151
|
"SQLite driver not supported in Bun. Use createMemoryDriver() instead."
|
|
3242
3152
|
);
|
|
3243
3153
|
}
|
|
3244
|
-
let Database = null;
|
|
3245
3154
|
try {
|
|
3246
|
-
|
|
3155
|
+
if (!cachedDbModule2) {
|
|
3156
|
+
cachedDbModule2 = (await import('better-sqlite3')).default;
|
|
3157
|
+
}
|
|
3158
|
+
return new cachedDbModule2(dbPath);
|
|
3247
3159
|
} catch (error) {
|
|
3248
3160
|
throw new Error(
|
|
3249
3161
|
`better-sqlite3 is required for sqlite usage tracking. Install it to use sqlite storage. (${error})`
|
|
3250
3162
|
);
|
|
3251
3163
|
}
|
|
3252
|
-
return new Database(dbPath);
|
|
3253
3164
|
};
|
|
3254
3165
|
var buildWhereClause = (options = {}) => {
|
|
3255
3166
|
const clauses = [];
|
|
@@ -3286,38 +3197,49 @@ var buildWhereClause = (options = {}) => {
|
|
|
3286
3197
|
var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
3287
3198
|
const dbPath = options.dbPath || "routstr.sqlite";
|
|
3288
3199
|
const tableName = options.tableName || "usage_tracking";
|
|
3289
|
-
const db = createDatabase2(dbPath);
|
|
3290
3200
|
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
|
-
`);
|
|
3201
|
+
let db;
|
|
3202
|
+
let insertStmt;
|
|
3320
3203
|
let migrationComplete = false;
|
|
3204
|
+
const initDb = async () => {
|
|
3205
|
+
if (!db) {
|
|
3206
|
+
db = await loadDatabase2(dbPath);
|
|
3207
|
+
db.exec(`
|
|
3208
|
+
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
3209
|
+
id TEXT PRIMARY KEY,
|
|
3210
|
+
timestamp INTEGER NOT NULL,
|
|
3211
|
+
model_id TEXT NOT NULL,
|
|
3212
|
+
base_url TEXT NOT NULL,
|
|
3213
|
+
request_id TEXT NOT NULL,
|
|
3214
|
+
cost REAL NOT NULL,
|
|
3215
|
+
sats_cost REAL NOT NULL,
|
|
3216
|
+
prompt_tokens INTEGER NOT NULL,
|
|
3217
|
+
completion_tokens INTEGER NOT NULL,
|
|
3218
|
+
total_tokens INTEGER NOT NULL,
|
|
3219
|
+
client TEXT,
|
|
3220
|
+
session_id TEXT,
|
|
3221
|
+
tags TEXT
|
|
3222
|
+
);
|
|
3223
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
|
|
3224
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
|
|
3225
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
|
|
3226
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
|
|
3227
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
|
|
3228
|
+
`);
|
|
3229
|
+
insertStmt = db.prepare(`
|
|
3230
|
+
INSERT OR REPLACE INTO ${tableName} (
|
|
3231
|
+
id, timestamp, model_id, base_url, request_id,
|
|
3232
|
+
cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
|
|
3233
|
+
client, session_id, tags
|
|
3234
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3235
|
+
`);
|
|
3236
|
+
}
|
|
3237
|
+
};
|
|
3238
|
+
const ensureInit = async () => {
|
|
3239
|
+
if (!db) {
|
|
3240
|
+
await initDb();
|
|
3241
|
+
}
|
|
3242
|
+
};
|
|
3321
3243
|
const appendOne = (entry) => {
|
|
3322
3244
|
insertStmt.run(
|
|
3323
3245
|
entry.id,
|
|
@@ -3375,19 +3297,23 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
|
3375
3297
|
});
|
|
3376
3298
|
return {
|
|
3377
3299
|
async migrate() {
|
|
3300
|
+
await ensureInit();
|
|
3378
3301
|
await ensureMigrated();
|
|
3379
3302
|
},
|
|
3380
3303
|
async append(entry) {
|
|
3304
|
+
await ensureInit();
|
|
3381
3305
|
await ensureMigrated();
|
|
3382
3306
|
appendOne(entry);
|
|
3383
3307
|
},
|
|
3384
3308
|
async appendMany(entries) {
|
|
3309
|
+
await ensureInit();
|
|
3385
3310
|
await ensureMigrated();
|
|
3386
3311
|
for (const entry of entries) {
|
|
3387
3312
|
appendOne(entry);
|
|
3388
3313
|
}
|
|
3389
3314
|
},
|
|
3390
3315
|
async list(options2 = {}) {
|
|
3316
|
+
await ensureInit();
|
|
3391
3317
|
await ensureMigrated();
|
|
3392
3318
|
const { sql, params } = buildWhereClause(options2);
|
|
3393
3319
|
const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
|
|
@@ -3400,6 +3326,7 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
|
3400
3326
|
return rows.map(mapRow);
|
|
3401
3327
|
},
|
|
3402
3328
|
async count(options2 = {}) {
|
|
3329
|
+
await ensureInit();
|
|
3403
3330
|
await ensureMigrated();
|
|
3404
3331
|
const { sql, params } = buildWhereClause(options2);
|
|
3405
3332
|
const stmt = db.prepare(`SELECT COUNT(*) as count FROM ${tableName} ${sql}`);
|
|
@@ -3407,20 +3334,197 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
|
3407
3334
|
return Number(row?.count ?? 0);
|
|
3408
3335
|
},
|
|
3409
3336
|
async deleteOlderThan(timestamp) {
|
|
3337
|
+
await ensureInit();
|
|
3410
3338
|
await ensureMigrated();
|
|
3411
3339
|
const stmt = db.prepare(`DELETE FROM ${tableName} WHERE timestamp < ?`);
|
|
3412
3340
|
const result = stmt.run(timestamp);
|
|
3413
3341
|
return result.changes;
|
|
3414
3342
|
},
|
|
3415
3343
|
async clear() {
|
|
3344
|
+
await ensureInit();
|
|
3416
3345
|
await ensureMigrated();
|
|
3417
3346
|
db.prepare(`DELETE FROM ${tableName}`).run();
|
|
3418
3347
|
}
|
|
3419
3348
|
};
|
|
3420
3349
|
};
|
|
3421
3350
|
|
|
3422
|
-
// storage/usageTracking/
|
|
3351
|
+
// storage/usageTracking/bunSqlite.ts
|
|
3352
|
+
var MIGRATION_MARKER_KEY3 = "usage_tracking_migration_v1";
|
|
3423
3353
|
var normalizeBaseUrl3 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
3354
|
+
var buildWhereClause2 = (options = {}) => {
|
|
3355
|
+
const clauses = [];
|
|
3356
|
+
const params = [];
|
|
3357
|
+
if (typeof options.before === "number") {
|
|
3358
|
+
clauses.push("timestamp < ?");
|
|
3359
|
+
params.push(options.before);
|
|
3360
|
+
}
|
|
3361
|
+
if (typeof options.after === "number") {
|
|
3362
|
+
clauses.push("timestamp > ?");
|
|
3363
|
+
params.push(options.after);
|
|
3364
|
+
}
|
|
3365
|
+
if (options.modelId) {
|
|
3366
|
+
clauses.push("model_id = ?");
|
|
3367
|
+
params.push(options.modelId);
|
|
3368
|
+
}
|
|
3369
|
+
if (options.baseUrl) {
|
|
3370
|
+
clauses.push("base_url = ?");
|
|
3371
|
+
params.push(normalizeBaseUrl3(options.baseUrl));
|
|
3372
|
+
}
|
|
3373
|
+
if (options.sessionId) {
|
|
3374
|
+
clauses.push("session_id = ?");
|
|
3375
|
+
params.push(options.sessionId);
|
|
3376
|
+
}
|
|
3377
|
+
if (options.client) {
|
|
3378
|
+
clauses.push("client = ?");
|
|
3379
|
+
params.push(options.client);
|
|
3380
|
+
}
|
|
3381
|
+
return {
|
|
3382
|
+
sql: clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "",
|
|
3383
|
+
params
|
|
3384
|
+
};
|
|
3385
|
+
};
|
|
3386
|
+
var createBunSqliteUsageTrackingDriver = (options = {}) => {
|
|
3387
|
+
const dbPath = options.dbPath || "routstr.sqlite";
|
|
3388
|
+
const tableName = options.tableName || "usage_tracking";
|
|
3389
|
+
const legacyStorageDriver = options.legacyStorageDriver;
|
|
3390
|
+
const SQLiteDatabase = options.sqlite?.Database;
|
|
3391
|
+
let migrationPromise = null;
|
|
3392
|
+
if (!SQLiteDatabase) {
|
|
3393
|
+
throw new Error(
|
|
3394
|
+
"Bun SQLite Database constructor is required. Pass { sqlite: { Database } } when creating the driver."
|
|
3395
|
+
);
|
|
3396
|
+
}
|
|
3397
|
+
const db = new SQLiteDatabase(dbPath);
|
|
3398
|
+
db.run(`
|
|
3399
|
+
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
3400
|
+
id TEXT PRIMARY KEY,
|
|
3401
|
+
timestamp INTEGER NOT NULL,
|
|
3402
|
+
model_id TEXT NOT NULL,
|
|
3403
|
+
base_url TEXT NOT NULL,
|
|
3404
|
+
request_id TEXT NOT NULL,
|
|
3405
|
+
cost REAL NOT NULL,
|
|
3406
|
+
sats_cost REAL NOT NULL,
|
|
3407
|
+
prompt_tokens INTEGER NOT NULL,
|
|
3408
|
+
completion_tokens INTEGER NOT NULL,
|
|
3409
|
+
total_tokens INTEGER NOT NULL,
|
|
3410
|
+
client TEXT,
|
|
3411
|
+
session_id TEXT,
|
|
3412
|
+
tags TEXT
|
|
3413
|
+
)
|
|
3414
|
+
`);
|
|
3415
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp)`);
|
|
3416
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id)`);
|
|
3417
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url)`);
|
|
3418
|
+
const appendOne = (entry) => {
|
|
3419
|
+
db.query(`
|
|
3420
|
+
INSERT OR REPLACE INTO ${tableName} (
|
|
3421
|
+
id, timestamp, model_id, base_url, request_id,
|
|
3422
|
+
cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
|
|
3423
|
+
client, session_id, tags
|
|
3424
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3425
|
+
`).run(
|
|
3426
|
+
entry.id,
|
|
3427
|
+
entry.timestamp,
|
|
3428
|
+
entry.modelId,
|
|
3429
|
+
normalizeBaseUrl3(entry.baseUrl),
|
|
3430
|
+
entry.requestId,
|
|
3431
|
+
entry.cost,
|
|
3432
|
+
entry.satsCost,
|
|
3433
|
+
entry.promptTokens,
|
|
3434
|
+
entry.completionTokens,
|
|
3435
|
+
entry.totalTokens,
|
|
3436
|
+
entry.client ?? null,
|
|
3437
|
+
entry.sessionId ?? null,
|
|
3438
|
+
JSON.stringify(entry.tags ?? [])
|
|
3439
|
+
);
|
|
3440
|
+
};
|
|
3441
|
+
const mapRow = (row) => ({
|
|
3442
|
+
id: row.id,
|
|
3443
|
+
timestamp: row.timestamp,
|
|
3444
|
+
modelId: row.model_id,
|
|
3445
|
+
baseUrl: row.base_url,
|
|
3446
|
+
requestId: row.request_id,
|
|
3447
|
+
cost: row.cost,
|
|
3448
|
+
satsCost: row.sats_cost,
|
|
3449
|
+
promptTokens: row.prompt_tokens,
|
|
3450
|
+
completionTokens: row.completion_tokens,
|
|
3451
|
+
totalTokens: row.total_tokens,
|
|
3452
|
+
client: row.client ?? void 0,
|
|
3453
|
+
sessionId: row.session_id ?? void 0,
|
|
3454
|
+
tags: typeof row.tags === "string" ? JSON.parse(row.tags) : void 0
|
|
3455
|
+
});
|
|
3456
|
+
const ensureMigrated = async () => {
|
|
3457
|
+
if (!legacyStorageDriver) return;
|
|
3458
|
+
if (!migrationPromise) {
|
|
3459
|
+
migrationPromise = (async () => {
|
|
3460
|
+
const migrated = await legacyStorageDriver.getItem(
|
|
3461
|
+
MIGRATION_MARKER_KEY3,
|
|
3462
|
+
false
|
|
3463
|
+
);
|
|
3464
|
+
if (migrated) return;
|
|
3465
|
+
const legacyEntries = await legacyStorageDriver.getItem(
|
|
3466
|
+
SDK_STORAGE_KEYS.USAGE_TRACKING,
|
|
3467
|
+
[]
|
|
3468
|
+
);
|
|
3469
|
+
if (legacyEntries.length > 0) {
|
|
3470
|
+
for (const entry of legacyEntries) {
|
|
3471
|
+
appendOne(entry);
|
|
3472
|
+
}
|
|
3473
|
+
await legacyStorageDriver.removeItem(SDK_STORAGE_KEYS.USAGE_TRACKING);
|
|
3474
|
+
}
|
|
3475
|
+
await legacyStorageDriver.setItem(MIGRATION_MARKER_KEY3, true);
|
|
3476
|
+
})();
|
|
3477
|
+
}
|
|
3478
|
+
await migrationPromise;
|
|
3479
|
+
};
|
|
3480
|
+
return {
|
|
3481
|
+
async migrate() {
|
|
3482
|
+
await ensureMigrated();
|
|
3483
|
+
},
|
|
3484
|
+
async append(entry) {
|
|
3485
|
+
await ensureMigrated();
|
|
3486
|
+
appendOne(entry);
|
|
3487
|
+
},
|
|
3488
|
+
async appendMany(entries) {
|
|
3489
|
+
await ensureMigrated();
|
|
3490
|
+
for (const entry of entries) {
|
|
3491
|
+
appendOne(entry);
|
|
3492
|
+
}
|
|
3493
|
+
},
|
|
3494
|
+
async list(options2 = {}) {
|
|
3495
|
+
await ensureMigrated();
|
|
3496
|
+
const { sql, params } = buildWhereClause2(options2);
|
|
3497
|
+
const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
|
|
3498
|
+
const query = `SELECT * FROM ${tableName} ${sql} ORDER BY timestamp DESC${limitSql}`;
|
|
3499
|
+
let rows;
|
|
3500
|
+
if (typeof options2.limit === "number") {
|
|
3501
|
+
rows = db.query(query).all(...params, options2.limit);
|
|
3502
|
+
} else {
|
|
3503
|
+
rows = db.query(query).all(...params);
|
|
3504
|
+
}
|
|
3505
|
+
return rows.map(mapRow);
|
|
3506
|
+
},
|
|
3507
|
+
async count(options2 = {}) {
|
|
3508
|
+
const { sql, params } = buildWhereClause2(options2);
|
|
3509
|
+
const query = `SELECT COUNT(*) as count FROM ${tableName} ${sql}`;
|
|
3510
|
+
const row = db.query(query).get(...params);
|
|
3511
|
+
return Number(row?.count ?? 0);
|
|
3512
|
+
},
|
|
3513
|
+
async deleteOlderThan(timestamp) {
|
|
3514
|
+
await ensureMigrated();
|
|
3515
|
+
const before = timestamp;
|
|
3516
|
+
const result = db.query(`DELETE FROM ${tableName} WHERE timestamp < ?`).run(before);
|
|
3517
|
+
return result.changes ?? 0;
|
|
3518
|
+
},
|
|
3519
|
+
async clear() {
|
|
3520
|
+
await ensureMigrated();
|
|
3521
|
+
db.query(`DELETE FROM ${tableName}`).run();
|
|
3522
|
+
}
|
|
3523
|
+
};
|
|
3524
|
+
};
|
|
3525
|
+
|
|
3526
|
+
// storage/usageTracking/memory.ts
|
|
3527
|
+
var normalizeBaseUrl4 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
3424
3528
|
var matchesFilters2 = (entry, options = {}) => {
|
|
3425
3529
|
if (typeof options.before === "number" && entry.timestamp >= options.before) {
|
|
3426
3530
|
return false;
|
|
@@ -3431,7 +3535,7 @@ var matchesFilters2 = (entry, options = {}) => {
|
|
|
3431
3535
|
if (options.modelId && entry.modelId !== options.modelId) {
|
|
3432
3536
|
return false;
|
|
3433
3537
|
}
|
|
3434
|
-
if (options.baseUrl &&
|
|
3538
|
+
if (options.baseUrl && normalizeBaseUrl4(entry.baseUrl) !== normalizeBaseUrl4(options.baseUrl)) {
|
|
3435
3539
|
return false;
|
|
3436
3540
|
}
|
|
3437
3541
|
if (options.sessionId && entry.sessionId !== options.sessionId) {
|
|
@@ -3445,18 +3549,18 @@ var matchesFilters2 = (entry, options = {}) => {
|
|
|
3445
3549
|
var createMemoryUsageTrackingDriver = (seed = []) => {
|
|
3446
3550
|
const store = /* @__PURE__ */ new Map();
|
|
3447
3551
|
for (const entry of seed) {
|
|
3448
|
-
store.set(entry.id, { ...entry, baseUrl:
|
|
3552
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
|
|
3449
3553
|
}
|
|
3450
3554
|
return {
|
|
3451
3555
|
async migrate() {
|
|
3452
3556
|
return;
|
|
3453
3557
|
},
|
|
3454
3558
|
async append(entry) {
|
|
3455
|
-
store.set(entry.id, { ...entry, baseUrl:
|
|
3559
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
|
|
3456
3560
|
},
|
|
3457
3561
|
async appendMany(entries) {
|
|
3458
3562
|
for (const entry of entries) {
|
|
3459
|
-
store.set(entry.id, { ...entry, baseUrl:
|
|
3563
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
|
|
3460
3564
|
}
|
|
3461
3565
|
},
|
|
3462
3566
|
async list(options = {}) {
|
|
@@ -3484,20 +3588,7 @@ var createMemoryUsageTrackingDriver = (seed = []) => {
|
|
|
3484
3588
|
}
|
|
3485
3589
|
};
|
|
3486
3590
|
};
|
|
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
|
-
};
|
|
3591
|
+
var normalizeBaseUrl5 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
3501
3592
|
var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
3502
3593
|
modelsFromAllProviders: {},
|
|
3503
3594
|
lastUsedModel: null,
|
|
@@ -3507,9 +3598,9 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3507
3598
|
mintsFromAllProviders: {},
|
|
3508
3599
|
infoFromAllProviders: {},
|
|
3509
3600
|
lastModelsUpdate: {},
|
|
3510
|
-
cachedTokens: [],
|
|
3511
3601
|
apiKeys: [],
|
|
3512
3602
|
childKeys: [],
|
|
3603
|
+
xcashuTokens: {},
|
|
3513
3604
|
routstr21Models: [],
|
|
3514
3605
|
lastRoutstr21ModelsUpdate: null,
|
|
3515
3606
|
cachedReceiveTokens: [],
|
|
@@ -3517,7 +3608,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3517
3608
|
setModelsFromAllProviders: (value) => {
|
|
3518
3609
|
const normalized = {};
|
|
3519
3610
|
for (const [baseUrl, models] of Object.entries(value)) {
|
|
3520
|
-
normalized[
|
|
3611
|
+
normalized[normalizeBaseUrl5(baseUrl)] = models;
|
|
3521
3612
|
}
|
|
3522
3613
|
void driver.setItem(
|
|
3523
3614
|
SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
|
|
@@ -3530,7 +3621,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3530
3621
|
set({ lastUsedModel: value });
|
|
3531
3622
|
},
|
|
3532
3623
|
setBaseUrlsList: (value) => {
|
|
3533
|
-
const normalized = value.map((url) =>
|
|
3624
|
+
const normalized = value.map((url) => normalizeBaseUrl5(url));
|
|
3534
3625
|
void driver.setItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, normalized);
|
|
3535
3626
|
set({ baseUrlsList: normalized });
|
|
3536
3627
|
},
|
|
@@ -3539,14 +3630,14 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3539
3630
|
set({ lastBaseUrlsUpdate: value });
|
|
3540
3631
|
},
|
|
3541
3632
|
setDisabledProviders: (value) => {
|
|
3542
|
-
const normalized = value.map((url) =>
|
|
3633
|
+
const normalized = value.map((url) => normalizeBaseUrl5(url));
|
|
3543
3634
|
void driver.setItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, normalized);
|
|
3544
3635
|
set({ disabledProviders: normalized });
|
|
3545
3636
|
},
|
|
3546
3637
|
setMintsFromAllProviders: (value) => {
|
|
3547
3638
|
const normalized = {};
|
|
3548
3639
|
for (const [baseUrl, mints] of Object.entries(value)) {
|
|
3549
|
-
normalized[
|
|
3640
|
+
normalized[normalizeBaseUrl5(baseUrl)] = mints.map(
|
|
3550
3641
|
(mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint
|
|
3551
3642
|
);
|
|
3552
3643
|
}
|
|
@@ -3559,7 +3650,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3559
3650
|
setInfoFromAllProviders: (value) => {
|
|
3560
3651
|
const normalized = {};
|
|
3561
3652
|
for (const [baseUrl, info] of Object.entries(value)) {
|
|
3562
|
-
normalized[
|
|
3653
|
+
normalized[normalizeBaseUrl5(baseUrl)] = info;
|
|
3563
3654
|
}
|
|
3564
3655
|
void driver.setItem(SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS, normalized);
|
|
3565
3656
|
set({ infoFromAllProviders: normalized });
|
|
@@ -3567,30 +3658,17 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3567
3658
|
setLastModelsUpdate: (value) => {
|
|
3568
3659
|
const normalized = {};
|
|
3569
3660
|
for (const [baseUrl, timestamp] of Object.entries(value)) {
|
|
3570
|
-
normalized[
|
|
3661
|
+
normalized[normalizeBaseUrl5(baseUrl)] = timestamp;
|
|
3571
3662
|
}
|
|
3572
3663
|
void driver.setItem(SDK_STORAGE_KEYS.LAST_MODELS_UPDATE, normalized);
|
|
3573
3664
|
set({ lastModelsUpdate: normalized });
|
|
3574
3665
|
},
|
|
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
3666
|
setApiKeys: (value) => {
|
|
3589
3667
|
set((state) => {
|
|
3590
3668
|
const updates = typeof value === "function" ? value(state.apiKeys) : value;
|
|
3591
3669
|
const normalized = updates.map((entry) => ({
|
|
3592
3670
|
...entry,
|
|
3593
|
-
baseUrl:
|
|
3671
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3594
3672
|
balance: entry.balance ?? 0,
|
|
3595
3673
|
lastUsed: entry.lastUsed ?? null
|
|
3596
3674
|
}));
|
|
@@ -3602,7 +3680,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3602
3680
|
set((state) => {
|
|
3603
3681
|
const updates = typeof value === "function" ? value(state.childKeys) : value;
|
|
3604
3682
|
const normalized = updates.map((entry) => ({
|
|
3605
|
-
parentBaseUrl:
|
|
3683
|
+
parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
|
|
3606
3684
|
childKey: entry.childKey,
|
|
3607
3685
|
balance: entry.balance ?? 0,
|
|
3608
3686
|
balanceLimit: entry.balanceLimit,
|
|
@@ -3613,6 +3691,30 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
|
3613
3691
|
return { childKeys: normalized };
|
|
3614
3692
|
});
|
|
3615
3693
|
},
|
|
3694
|
+
setXcashuTokens: (value) => {
|
|
3695
|
+
const normalized = {};
|
|
3696
|
+
for (const [baseUrl, tokens] of Object.entries(value)) {
|
|
3697
|
+
normalized[normalizeBaseUrl5(baseUrl)] = tokens.map((entry) => ({
|
|
3698
|
+
...entry,
|
|
3699
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3700
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
3701
|
+
tryCount: entry.tryCount ?? 0
|
|
3702
|
+
}));
|
|
3703
|
+
}
|
|
3704
|
+
void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, normalized);
|
|
3705
|
+
set({ xcashuTokens: normalized });
|
|
3706
|
+
},
|
|
3707
|
+
updateXcashuTokenTryCount: (token, tryCount) => {
|
|
3708
|
+
const currentTokens = get().xcashuTokens;
|
|
3709
|
+
const updatedTokens = {};
|
|
3710
|
+
for (const [baseUrl, tokens] of Object.entries(currentTokens)) {
|
|
3711
|
+
updatedTokens[baseUrl] = tokens.map(
|
|
3712
|
+
(entry) => entry.token === token ? { ...entry, tryCount } : entry
|
|
3713
|
+
);
|
|
3714
|
+
}
|
|
3715
|
+
void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, updatedTokens);
|
|
3716
|
+
set({ xcashuTokens: updatedTokens });
|
|
3717
|
+
},
|
|
3616
3718
|
setRoutstr21Models: (value) => {
|
|
3617
3719
|
void driver.setItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, value);
|
|
3618
3720
|
set({ routstr21Models: value });
|
|
@@ -3654,9 +3756,9 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3654
3756
|
rawMints,
|
|
3655
3757
|
rawInfo,
|
|
3656
3758
|
rawLastModelsUpdate,
|
|
3657
|
-
rawCachedTokens,
|
|
3658
3759
|
rawApiKeys,
|
|
3659
3760
|
rawChildKeys,
|
|
3761
|
+
rawXcashuTokens,
|
|
3660
3762
|
rawRoutstr21Models,
|
|
3661
3763
|
rawLastRoutstr21ModelsUpdate,
|
|
3662
3764
|
rawCachedReceiveTokens,
|
|
@@ -3682,9 +3784,9 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3682
3784
|
SDK_STORAGE_KEYS.LAST_MODELS_UPDATE,
|
|
3683
3785
|
{}
|
|
3684
3786
|
),
|
|
3685
|
-
driver.getItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, []),
|
|
3686
3787
|
driver.getItem(SDK_STORAGE_KEYS.API_KEYS, []),
|
|
3687
3788
|
driver.getItem(SDK_STORAGE_KEYS.CHILD_KEYS, []),
|
|
3789
|
+
driver.getItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, {}),
|
|
3688
3790
|
driver.getItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, []),
|
|
3689
3791
|
driver.getItem(
|
|
3690
3792
|
SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
|
|
@@ -3695,52 +3797,57 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3695
3797
|
]);
|
|
3696
3798
|
const modelsFromAllProviders = Object.fromEntries(
|
|
3697
3799
|
Object.entries(rawModels).map(([baseUrl, models]) => [
|
|
3698
|
-
|
|
3800
|
+
normalizeBaseUrl5(baseUrl),
|
|
3699
3801
|
models
|
|
3700
3802
|
])
|
|
3701
3803
|
);
|
|
3702
|
-
const baseUrlsList = rawBaseUrls.map((url) =>
|
|
3804
|
+
const baseUrlsList = rawBaseUrls.map((url) => normalizeBaseUrl5(url));
|
|
3703
3805
|
const disabledProviders = rawDisabledProviders.map(
|
|
3704
|
-
(url) =>
|
|
3806
|
+
(url) => normalizeBaseUrl5(url)
|
|
3705
3807
|
);
|
|
3706
3808
|
const mintsFromAllProviders = Object.fromEntries(
|
|
3707
3809
|
Object.entries(rawMints).map(([baseUrl, mints]) => [
|
|
3708
|
-
|
|
3810
|
+
normalizeBaseUrl5(baseUrl),
|
|
3709
3811
|
mints.map((mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint)
|
|
3710
3812
|
])
|
|
3711
3813
|
);
|
|
3712
3814
|
const infoFromAllProviders = Object.fromEntries(
|
|
3713
3815
|
Object.entries(rawInfo).map(([baseUrl, info]) => [
|
|
3714
|
-
|
|
3816
|
+
normalizeBaseUrl5(baseUrl),
|
|
3715
3817
|
info
|
|
3716
3818
|
])
|
|
3717
3819
|
);
|
|
3718
3820
|
const lastModelsUpdate = Object.fromEntries(
|
|
3719
3821
|
Object.entries(rawLastModelsUpdate).map(([baseUrl, timestamp]) => [
|
|
3720
|
-
|
|
3822
|
+
normalizeBaseUrl5(baseUrl),
|
|
3721
3823
|
timestamp
|
|
3722
3824
|
])
|
|
3723
3825
|
);
|
|
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
3826
|
const apiKeys = rawApiKeys.map((entry) => ({
|
|
3731
3827
|
...entry,
|
|
3732
|
-
baseUrl:
|
|
3828
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3733
3829
|
balance: entry.balance ?? 0,
|
|
3734
3830
|
lastUsed: entry.lastUsed ?? null
|
|
3735
3831
|
}));
|
|
3736
3832
|
const childKeys = rawChildKeys.map((entry) => ({
|
|
3737
|
-
parentBaseUrl:
|
|
3833
|
+
parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
|
|
3738
3834
|
childKey: entry.childKey,
|
|
3739
3835
|
balance: entry.balance ?? 0,
|
|
3740
3836
|
balanceLimit: entry.balanceLimit,
|
|
3741
3837
|
validityDate: entry.validityDate,
|
|
3742
3838
|
createdAt: entry.createdAt ?? Date.now()
|
|
3743
3839
|
}));
|
|
3840
|
+
const xcashuTokens = Object.fromEntries(
|
|
3841
|
+
Object.entries(rawXcashuTokens).map(([baseUrl, tokens]) => [
|
|
3842
|
+
normalizeBaseUrl5(baseUrl),
|
|
3843
|
+
tokens.map((entry) => ({
|
|
3844
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3845
|
+
token: entry.token,
|
|
3846
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
3847
|
+
tryCount: entry.tryCount ?? 0
|
|
3848
|
+
}))
|
|
3849
|
+
])
|
|
3850
|
+
);
|
|
3744
3851
|
const routstr21Models = rawRoutstr21Models;
|
|
3745
3852
|
const lastRoutstr21ModelsUpdate = rawLastRoutstr21ModelsUpdate;
|
|
3746
3853
|
const cachedReceiveTokens = rawCachedReceiveTokens?.map((entry) => ({
|
|
@@ -3763,9 +3870,9 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3763
3870
|
mintsFromAllProviders,
|
|
3764
3871
|
infoFromAllProviders,
|
|
3765
3872
|
lastModelsUpdate,
|
|
3766
|
-
cachedTokens,
|
|
3767
3873
|
apiKeys,
|
|
3768
3874
|
childKeys,
|
|
3875
|
+
xcashuTokens,
|
|
3769
3876
|
routstr21Models,
|
|
3770
3877
|
lastRoutstr21ModelsUpdate,
|
|
3771
3878
|
cachedReceiveTokens,
|
|
@@ -3789,12 +3896,12 @@ var createDiscoveryAdapterFromStore = (store) => ({
|
|
|
3789
3896
|
getCachedProviderInfo: () => store.getState().infoFromAllProviders,
|
|
3790
3897
|
setCachedProviderInfo: (info) => store.getState().setInfoFromAllProviders(info),
|
|
3791
3898
|
getProviderLastUpdate: (baseUrl) => {
|
|
3792
|
-
const normalized =
|
|
3899
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3793
3900
|
const timestamps = store.getState().lastModelsUpdate;
|
|
3794
3901
|
return timestamps[normalized] || null;
|
|
3795
3902
|
},
|
|
3796
3903
|
setProviderLastUpdate: (baseUrl, timestamp) => {
|
|
3797
|
-
const normalized =
|
|
3904
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3798
3905
|
const timestamps = { ...store.getState().lastModelsUpdate };
|
|
3799
3906
|
timestamps[normalized] = timestamp;
|
|
3800
3907
|
store.getState().setLastModelsUpdate(timestamps);
|
|
@@ -3812,59 +3919,6 @@ var createDiscoveryAdapterFromStore = (store) => ({
|
|
|
3812
3919
|
setRoutstr21ModelsLastUpdate: (timestamp) => store.getState().setRoutstr21ModelsLastUpdate(timestamp)
|
|
3813
3920
|
});
|
|
3814
3921
|
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
3922
|
getApiKeyDistribution: () => {
|
|
3869
3923
|
const apiKeys = store.getState().apiKeys;
|
|
3870
3924
|
const distributionMap = {};
|
|
@@ -3877,28 +3931,24 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3877
3931
|
return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
|
|
3878
3932
|
},
|
|
3879
3933
|
saveProviderInfo: (baseUrl, info) => {
|
|
3880
|
-
const normalized =
|
|
3934
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3881
3935
|
const next = { ...store.getState().infoFromAllProviders };
|
|
3882
3936
|
next[normalized] = info;
|
|
3883
3937
|
store.getState().setInfoFromAllProviders(next);
|
|
3884
3938
|
},
|
|
3885
3939
|
getProviderInfo: (baseUrl) => {
|
|
3886
|
-
const normalized =
|
|
3940
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3887
3941
|
return store.getState().infoFromAllProviders[normalized] || null;
|
|
3888
3942
|
},
|
|
3889
3943
|
// ========== API Keys (for apikeys mode) ==========
|
|
3890
3944
|
getApiKey: (baseUrl) => {
|
|
3891
|
-
const normalized =
|
|
3945
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3892
3946
|
const entry = store.getState().apiKeys.find((key) => key.baseUrl === normalized);
|
|
3893
3947
|
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
3948
|
return entry;
|
|
3899
3949
|
},
|
|
3900
3950
|
setApiKey: (baseUrl, key) => {
|
|
3901
|
-
const normalized =
|
|
3951
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3902
3952
|
const keys = store.getState().apiKeys;
|
|
3903
3953
|
const existingIndex = keys.findIndex(
|
|
3904
3954
|
(entry) => entry.baseUrl === normalized
|
|
@@ -3916,15 +3966,15 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3916
3966
|
store.getState().setApiKeys(next);
|
|
3917
3967
|
},
|
|
3918
3968
|
updateApiKeyBalance: (baseUrl, balance) => {
|
|
3919
|
-
const normalized =
|
|
3969
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3920
3970
|
const keys = store.getState().apiKeys;
|
|
3921
3971
|
const next = keys.map(
|
|
3922
|
-
(entry) => entry.baseUrl === normalized ? { ...entry, balance } : entry
|
|
3972
|
+
(entry) => entry.baseUrl === normalized ? { ...entry, balance, lastUsed: Date.now() } : entry
|
|
3923
3973
|
);
|
|
3924
3974
|
store.getState().setApiKeys(next);
|
|
3925
3975
|
},
|
|
3926
3976
|
removeApiKey: (baseUrl) => {
|
|
3927
|
-
const normalized =
|
|
3977
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3928
3978
|
const next = store.getState().apiKeys.filter((entry) => entry.baseUrl !== normalized);
|
|
3929
3979
|
store.getState().setApiKeys(next);
|
|
3930
3980
|
},
|
|
@@ -3938,7 +3988,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3938
3988
|
},
|
|
3939
3989
|
// ========== Child Keys ==========
|
|
3940
3990
|
getChildKey: (parentBaseUrl) => {
|
|
3941
|
-
const normalized =
|
|
3991
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3942
3992
|
const entry = store.getState().childKeys.find((key) => key.parentBaseUrl === normalized);
|
|
3943
3993
|
if (!entry) return null;
|
|
3944
3994
|
return {
|
|
@@ -3951,7 +4001,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3951
4001
|
};
|
|
3952
4002
|
},
|
|
3953
4003
|
setChildKey: (parentBaseUrl, childKey, balance, validityDate, balanceLimit) => {
|
|
3954
|
-
const normalized =
|
|
4004
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3955
4005
|
const keys = store.getState().childKeys;
|
|
3956
4006
|
const existingIndex = keys.findIndex(
|
|
3957
4007
|
(entry) => entry.parentBaseUrl === normalized
|
|
@@ -3982,7 +4032,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3982
4032
|
}
|
|
3983
4033
|
},
|
|
3984
4034
|
updateChildKeyBalance: (parentBaseUrl, balance) => {
|
|
3985
|
-
const normalized =
|
|
4035
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3986
4036
|
const keys = store.getState().childKeys;
|
|
3987
4037
|
const next = keys.map(
|
|
3988
4038
|
(entry) => entry.parentBaseUrl === normalized ? { ...entry, balance } : entry
|
|
@@ -3990,7 +4040,7 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
3990
4040
|
store.getState().setChildKeys(next);
|
|
3991
4041
|
},
|
|
3992
4042
|
removeChildKey: (parentBaseUrl) => {
|
|
3993
|
-
const normalized =
|
|
4043
|
+
const normalized = normalizeBaseUrl5(parentBaseUrl);
|
|
3994
4044
|
const next = store.getState().childKeys.filter((entry) => entry.parentBaseUrl !== normalized);
|
|
3995
4045
|
store.getState().setChildKeys(next);
|
|
3996
4046
|
},
|
|
@@ -4009,20 +4059,60 @@ var createStorageAdapterFromStore = (store) => ({
|
|
|
4009
4059
|
},
|
|
4010
4060
|
setCachedReceiveTokens: (tokens) => {
|
|
4011
4061
|
store.getState().setCachedReceiveTokens(tokens);
|
|
4062
|
+
},
|
|
4063
|
+
// ========== XCashu Tokens (multiple tokens per baseUrl) ==========
|
|
4064
|
+
getXcashuTokens: () => {
|
|
4065
|
+
return store.getState().xcashuTokens;
|
|
4066
|
+
},
|
|
4067
|
+
getXcashuTokensForBaseUrl: (baseUrl) => {
|
|
4068
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4069
|
+
return store.getState().xcashuTokens[normalized] || [];
|
|
4070
|
+
},
|
|
4071
|
+
addXcashuToken: (baseUrl, token) => {
|
|
4072
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4073
|
+
const tokens = store.getState().xcashuTokens;
|
|
4074
|
+
const existing = tokens[normalized] || [];
|
|
4075
|
+
const next = { ...tokens };
|
|
4076
|
+
next[normalized] = [
|
|
4077
|
+
...existing,
|
|
4078
|
+
{ baseUrl: normalized, token, createdAt: Date.now(), tryCount: 0 }
|
|
4079
|
+
];
|
|
4080
|
+
store.getState().setXcashuTokens(next);
|
|
4081
|
+
},
|
|
4082
|
+
removeXcashuToken: (baseUrl, token) => {
|
|
4083
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4084
|
+
const tokens = store.getState().xcashuTokens;
|
|
4085
|
+
const existing = tokens[normalized] || [];
|
|
4086
|
+
const next = { ...tokens };
|
|
4087
|
+
next[normalized] = existing.filter((entry) => entry.token !== token);
|
|
4088
|
+
if (next[normalized].length === 0) {
|
|
4089
|
+
delete next[normalized];
|
|
4090
|
+
}
|
|
4091
|
+
store.getState().setXcashuTokens(next);
|
|
4092
|
+
},
|
|
4093
|
+
clearXcashuTokensForBaseUrl: (baseUrl) => {
|
|
4094
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4095
|
+
const tokens = store.getState().xcashuTokens;
|
|
4096
|
+
const next = { ...tokens };
|
|
4097
|
+
delete next[normalized];
|
|
4098
|
+
store.getState().setXcashuTokens(next);
|
|
4099
|
+
},
|
|
4100
|
+
updateXcashuTokenTryCount: (token, tryCount) => {
|
|
4101
|
+
store.getState().updateXcashuTokenTryCount(token, tryCount);
|
|
4012
4102
|
}
|
|
4013
4103
|
});
|
|
4014
4104
|
var createProviderRegistryFromStore = (store) => ({
|
|
4015
4105
|
getModelsForProvider: (baseUrl) => {
|
|
4016
|
-
const normalized =
|
|
4106
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4017
4107
|
return store.getState().modelsFromAllProviders[normalized] || [];
|
|
4018
4108
|
},
|
|
4019
4109
|
getDisabledProviders: () => store.getState().disabledProviders,
|
|
4020
4110
|
getProviderMints: (baseUrl) => {
|
|
4021
|
-
const normalized =
|
|
4111
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4022
4112
|
return store.getState().mintsFromAllProviders[normalized] || [];
|
|
4023
4113
|
},
|
|
4024
4114
|
getProviderInfo: async (baseUrl) => {
|
|
4025
|
-
const normalized =
|
|
4115
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
4026
4116
|
const cached = store.getState().infoFromAllProviders[normalized];
|
|
4027
4117
|
if (cached) return cached;
|
|
4028
4118
|
try {
|
|
@@ -4097,7 +4187,7 @@ var getDefaultUsageTrackingDriver = () => {
|
|
|
4097
4187
|
return defaultUsageTrackingDriver;
|
|
4098
4188
|
}
|
|
4099
4189
|
if (isBun3()) {
|
|
4100
|
-
defaultUsageTrackingDriver =
|
|
4190
|
+
defaultUsageTrackingDriver = createBunSqliteUsageTrackingDriver();
|
|
4101
4191
|
return defaultUsageTrackingDriver;
|
|
4102
4192
|
}
|
|
4103
4193
|
if (isNode()) {
|
|
@@ -4109,21 +4199,28 @@ var getDefaultUsageTrackingDriver = () => {
|
|
|
4109
4199
|
defaultUsageTrackingDriver = createMemoryUsageTrackingDriver();
|
|
4110
4200
|
return defaultUsageTrackingDriver;
|
|
4111
4201
|
};
|
|
4202
|
+
var setDefaultUsageTrackingDriver = (driver) => {
|
|
4203
|
+
defaultUsageTrackingDriver = driver;
|
|
4204
|
+
};
|
|
4112
4205
|
var getDefaultDiscoveryAdapter = async () => createDiscoveryAdapterFromStore(await getDefaultSdkStore());
|
|
4113
4206
|
var getDefaultStorageAdapter = async () => createStorageAdapterFromStore(await getDefaultSdkStore());
|
|
4114
4207
|
var getDefaultProviderRegistry = async () => createProviderRegistryFromStore(await getDefaultSdkStore());
|
|
4115
4208
|
function createSSEParserTransform(onUsage, onResponseId) {
|
|
4116
4209
|
let buffer = "";
|
|
4210
|
+
let usageCaptured = false;
|
|
4211
|
+
let responseIdCaptured = false;
|
|
4117
4212
|
const maybeCaptureUsageFromJson = (jsonText) => {
|
|
4118
4213
|
try {
|
|
4119
4214
|
const data = JSON.parse(jsonText);
|
|
4120
4215
|
const responseId = data.id;
|
|
4121
4216
|
if (typeof responseId === "string" && responseId.trim().length > 0) {
|
|
4122
4217
|
onResponseId?.(responseId.trim());
|
|
4218
|
+
responseIdCaptured = true;
|
|
4123
4219
|
}
|
|
4124
4220
|
const usage = extractUsageFromSSEJson(data);
|
|
4125
4221
|
if (usage) {
|
|
4126
4222
|
onUsage(usage);
|
|
4223
|
+
usageCaptured = true;
|
|
4127
4224
|
}
|
|
4128
4225
|
} catch {
|
|
4129
4226
|
}
|
|
@@ -4179,7 +4276,7 @@ function createSSEParserTransform(onUsage, onResponseId) {
|
|
|
4179
4276
|
}
|
|
4180
4277
|
var TOPUP_MARGIN = 1.2;
|
|
4181
4278
|
var RoutstrClient = class {
|
|
4182
|
-
constructor(walletAdapter, storageAdapter, providerRegistry, alertLevel, mode = "xcashu") {
|
|
4279
|
+
constructor(walletAdapter, storageAdapter, providerRegistry, alertLevel, mode = "xcashu", options = {}) {
|
|
4183
4280
|
this.walletAdapter = walletAdapter;
|
|
4184
4281
|
this.storageAdapter = storageAdapter;
|
|
4185
4282
|
this.providerRegistry = providerRegistry;
|
|
@@ -4197,13 +4294,9 @@ var RoutstrClient = class {
|
|
|
4197
4294
|
this.streamProcessor = new StreamProcessor();
|
|
4198
4295
|
this.providerManager = new ProviderManager(providerRegistry);
|
|
4199
4296
|
this.alertLevel = alertLevel;
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
this.mode = "lazyrefund";
|
|
4204
|
-
} else {
|
|
4205
|
-
this.mode = mode;
|
|
4206
|
-
}
|
|
4297
|
+
this.mode = mode;
|
|
4298
|
+
this.usageTrackingDriver = options.usageTrackingDriver;
|
|
4299
|
+
this.sdkStore = options.sdkStore;
|
|
4207
4300
|
}
|
|
4208
4301
|
cashuSpender;
|
|
4209
4302
|
balanceManager;
|
|
@@ -4212,6 +4305,8 @@ var RoutstrClient = class {
|
|
|
4212
4305
|
alertLevel;
|
|
4213
4306
|
mode;
|
|
4214
4307
|
debugLevel = "WARN";
|
|
4308
|
+
usageTrackingDriver;
|
|
4309
|
+
sdkStore;
|
|
4215
4310
|
/**
|
|
4216
4311
|
* Get the current client mode
|
|
4217
4312
|
*/
|
|
@@ -4281,11 +4376,13 @@ var RoutstrClient = class {
|
|
|
4281
4376
|
const satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4282
4377
|
token: prepared.tokenUsed,
|
|
4283
4378
|
baseUrl: prepared.baseUrlUsed,
|
|
4379
|
+
mintUrl: params.mintUrl,
|
|
4284
4380
|
initialTokenBalance: prepared.tokenBalanceInSats,
|
|
4285
4381
|
response: prepared.response,
|
|
4286
4382
|
modelId: prepared.modelId,
|
|
4287
4383
|
usage: prepared.capturedUsage,
|
|
4288
|
-
requestId: prepared.capturedResponseId
|
|
4384
|
+
requestId: prepared.capturedResponseId,
|
|
4385
|
+
clientApiKey: prepared.clientApiKey
|
|
4289
4386
|
});
|
|
4290
4387
|
prepared.response.satsSpent = satsSpent;
|
|
4291
4388
|
prepared.response.usage = prepared.capturedUsage;
|
|
@@ -4304,11 +4401,13 @@ var RoutstrClient = class {
|
|
|
4304
4401
|
const satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4305
4402
|
token: prepared.tokenUsed,
|
|
4306
4403
|
baseUrl: prepared.baseUrlUsed,
|
|
4404
|
+
mintUrl: params.mintUrl,
|
|
4307
4405
|
initialTokenBalance: prepared.tokenBalanceInSats,
|
|
4308
4406
|
response: prepared.response,
|
|
4309
4407
|
modelId: prepared.modelId,
|
|
4310
4408
|
usage: prepared.capturedUsage,
|
|
4311
|
-
requestId: prepared.capturedResponseId
|
|
4409
|
+
requestId: prepared.capturedResponseId,
|
|
4410
|
+
clientApiKey: prepared.clientApiKey
|
|
4312
4411
|
});
|
|
4313
4412
|
prepared.response.satsSpent = satsSpent;
|
|
4314
4413
|
res.end();
|
|
@@ -4324,11 +4423,13 @@ var RoutstrClient = class {
|
|
|
4324
4423
|
const satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4325
4424
|
token: prepared.tokenUsed,
|
|
4326
4425
|
baseUrl: prepared.baseUrlUsed,
|
|
4426
|
+
mintUrl: params.mintUrl,
|
|
4327
4427
|
initialTokenBalance: prepared.tokenBalanceInSats,
|
|
4328
4428
|
response: prepared.response,
|
|
4329
4429
|
modelId: prepared.modelId,
|
|
4330
4430
|
usage: prepared.capturedUsage,
|
|
4331
|
-
requestId: prepared.capturedResponseId
|
|
4431
|
+
requestId: prepared.capturedResponseId,
|
|
4432
|
+
clientApiKey: prepared.clientApiKey
|
|
4332
4433
|
});
|
|
4333
4434
|
prepared.response.satsSpent = satsSpent;
|
|
4334
4435
|
prepared.response.usage = prepared.capturedUsage;
|
|
@@ -4358,8 +4459,10 @@ var RoutstrClient = class {
|
|
|
4358
4459
|
headers = {},
|
|
4359
4460
|
baseUrl,
|
|
4360
4461
|
mintUrl,
|
|
4361
|
-
modelId
|
|
4462
|
+
modelId,
|
|
4463
|
+
clientApiKey: providedClientApiKey
|
|
4362
4464
|
} = params;
|
|
4465
|
+
const clientApiKey = providedClientApiKey ?? this._extractClientApiKey(headers);
|
|
4363
4466
|
await this._checkBalance();
|
|
4364
4467
|
let requiredSats = 1;
|
|
4365
4468
|
let selectedModel;
|
|
@@ -4381,7 +4484,6 @@ var RoutstrClient = class {
|
|
|
4381
4484
|
amount: requiredSats,
|
|
4382
4485
|
baseUrl
|
|
4383
4486
|
});
|
|
4384
|
-
this._log("DEBUG", token, baseUrl);
|
|
4385
4487
|
let requestBody = body;
|
|
4386
4488
|
if (body && typeof body === "object") {
|
|
4387
4489
|
const bodyObj = body;
|
|
@@ -4389,7 +4491,7 @@ var RoutstrClient = class {
|
|
|
4389
4491
|
requestBody = { ...bodyObj, stream: false };
|
|
4390
4492
|
}
|
|
4391
4493
|
}
|
|
4392
|
-
const baseHeaders = this._buildBaseHeaders(
|
|
4494
|
+
const baseHeaders = this._buildBaseHeaders();
|
|
4393
4495
|
const requestHeaders = this._withAuthHeader(baseHeaders, token);
|
|
4394
4496
|
const response = await this._makeRequest({
|
|
4395
4497
|
path,
|
|
@@ -4441,9 +4543,21 @@ var RoutstrClient = class {
|
|
|
4441
4543
|
tokenBalanceInSats,
|
|
4442
4544
|
modelId,
|
|
4443
4545
|
capturedUsage,
|
|
4444
|
-
capturedResponseId
|
|
4546
|
+
capturedResponseId,
|
|
4547
|
+
clientApiKey
|
|
4445
4548
|
};
|
|
4446
4549
|
}
|
|
4550
|
+
/**
|
|
4551
|
+
* Extract clientApiKey from Authorization Bearer token if present
|
|
4552
|
+
*/
|
|
4553
|
+
_extractClientApiKey(headers) {
|
|
4554
|
+
const authHeader = headers["Authorization"] || headers["authorization"];
|
|
4555
|
+
if (authHeader?.startsWith("Bearer ")) {
|
|
4556
|
+
const extractedKey = authHeader.slice(7);
|
|
4557
|
+
return extractedKey;
|
|
4558
|
+
}
|
|
4559
|
+
return void 0;
|
|
4560
|
+
}
|
|
4447
4561
|
/**
|
|
4448
4562
|
* Fetch AI response with streaming
|
|
4449
4563
|
*/
|
|
@@ -4547,6 +4661,7 @@ var RoutstrClient = class {
|
|
|
4547
4661
|
let satsSpent = await this._handlePostResponseBalanceUpdate({
|
|
4548
4662
|
token,
|
|
4549
4663
|
baseUrl: baseUrlUsed,
|
|
4664
|
+
mintUrl,
|
|
4550
4665
|
initialTokenBalance: tokenBalanceInSats,
|
|
4551
4666
|
fallbackSatsSpent: isApikeysEstimate ? this._getEstimatedCosts(selectedModel, streamingResult) : void 0,
|
|
4552
4667
|
response,
|
|
@@ -4585,7 +4700,6 @@ var RoutstrClient = class {
|
|
|
4585
4700
|
try {
|
|
4586
4701
|
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
4587
4702
|
if (this.mode === "xcashu") this._log("DEBUG", "HEADERS,", headers);
|
|
4588
|
-
this._log("DEBUG", "HEADERS,", headers);
|
|
4589
4703
|
const response = await fetch(url, {
|
|
4590
4704
|
method,
|
|
4591
4705
|
headers,
|
|
@@ -4654,8 +4768,6 @@ var RoutstrClient = class {
|
|
|
4654
4768
|
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${tryReceiveTokenResult.amount}`
|
|
4655
4769
|
);
|
|
4656
4770
|
tryNextProvider = true;
|
|
4657
|
-
if (this.mode === "lazyrefund")
|
|
4658
|
-
this.storageAdapter.removeToken(baseUrl);
|
|
4659
4771
|
} else {
|
|
4660
4772
|
this._log(
|
|
4661
4773
|
"DEBUG",
|
|
@@ -4703,22 +4815,15 @@ var RoutstrClient = class {
|
|
|
4703
4815
|
);
|
|
4704
4816
|
}
|
|
4705
4817
|
}
|
|
4706
|
-
if (status === 402 && !tryNextProvider &&
|
|
4818
|
+
if (status === 402 && !tryNextProvider && this.mode === "apikeys") {
|
|
4707
4819
|
this.storageAdapter.getApiKey(baseUrl);
|
|
4708
4820
|
let topupAmount = params.requiredSats;
|
|
4709
4821
|
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
|
-
}
|
|
4822
|
+
const currentBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
4823
|
+
params.token,
|
|
4824
|
+
baseUrl
|
|
4825
|
+
);
|
|
4826
|
+
const currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1e3 : currentBalanceInfo.amount;
|
|
4722
4827
|
const shortfall = Math.max(0, params.requiredSats - currentBalance);
|
|
4723
4828
|
topupAmount = shortfall > 0 ? shortfall : params.requiredSats;
|
|
4724
4829
|
} catch (e) {
|
|
@@ -4855,34 +4960,7 @@ var RoutstrClient = class {
|
|
|
4855
4960
|
"DEBUG",
|
|
4856
4961
|
`[RoutstrClient] _handleErrorResponse: Status ${status} (auth/server error), attempting refund for ${baseUrl}, mode=${this.mode}`
|
|
4857
4962
|
);
|
|
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") {
|
|
4963
|
+
if (this.mode === "apikeys") {
|
|
4886
4964
|
this._log(
|
|
4887
4965
|
"DEBUG",
|
|
4888
4966
|
`[RoutstrClient] _handleErrorResponse: Attempting API key refund for ${baseUrl}, key preview=${token}`
|
|
@@ -4898,7 +4976,8 @@ var RoutstrClient = class {
|
|
|
4898
4976
|
const refundResult = await this.balanceManager.refundApiKey({
|
|
4899
4977
|
mintUrl,
|
|
4900
4978
|
baseUrl,
|
|
4901
|
-
apiKey: token
|
|
4979
|
+
apiKey: token,
|
|
4980
|
+
forceRefund: true
|
|
4902
4981
|
});
|
|
4903
4982
|
this._log(
|
|
4904
4983
|
"DEBUG",
|
|
@@ -4980,12 +5059,14 @@ var RoutstrClient = class {
|
|
|
4980
5059
|
const {
|
|
4981
5060
|
token,
|
|
4982
5061
|
baseUrl,
|
|
5062
|
+
mintUrl,
|
|
4983
5063
|
initialTokenBalance,
|
|
4984
5064
|
fallbackSatsSpent,
|
|
4985
5065
|
response,
|
|
4986
5066
|
modelId,
|
|
4987
5067
|
usage,
|
|
4988
|
-
requestId
|
|
5068
|
+
requestId,
|
|
5069
|
+
clientApiKey
|
|
4989
5070
|
} = params;
|
|
4990
5071
|
let satsSpent = initialTokenBalance;
|
|
4991
5072
|
if (this.mode === "xcashu" && response) {
|
|
@@ -4993,19 +5074,14 @@ var RoutstrClient = class {
|
|
|
4993
5074
|
if (refundToken) {
|
|
4994
5075
|
try {
|
|
4995
5076
|
const receiveResult = await this.cashuSpender.receiveToken(refundToken);
|
|
4996
|
-
|
|
5077
|
+
if (receiveResult.success) {
|
|
5078
|
+
this.storageAdapter.removeXcashuToken(baseUrl, token);
|
|
5079
|
+
satsSpent = initialTokenBalance - receiveResult.amount * (receiveResult.unit == "sat" ? 1 : 1e3);
|
|
5080
|
+
}
|
|
4997
5081
|
} catch (error) {
|
|
4998
5082
|
this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
|
|
4999
5083
|
}
|
|
5000
5084
|
}
|
|
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
5085
|
} else if (this.mode === "apikeys") {
|
|
5010
5086
|
try {
|
|
5011
5087
|
const latestBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
@@ -5040,8 +5116,18 @@ var RoutstrClient = class {
|
|
|
5040
5116
|
modelId,
|
|
5041
5117
|
satsSpent,
|
|
5042
5118
|
usage,
|
|
5043
|
-
requestId
|
|
5119
|
+
requestId,
|
|
5120
|
+
clientApiKey
|
|
5044
5121
|
});
|
|
5122
|
+
(async () => {
|
|
5123
|
+
try {
|
|
5124
|
+
const xcashuResults = await this.cashuSpender.refundXcashuTokens(mintUrl);
|
|
5125
|
+
this._log("DEBUG", "Refund xcashu tokens results:", xcashuResults);
|
|
5126
|
+
const results = await this.cashuSpender.refundProviders(mintUrl);
|
|
5127
|
+
} catch (error) {
|
|
5128
|
+
this._log("ERROR", "Failed to refund providers:", error);
|
|
5129
|
+
}
|
|
5130
|
+
})();
|
|
5045
5131
|
return satsSpent;
|
|
5046
5132
|
}
|
|
5047
5133
|
async _trackResponseUsage(params) {
|
|
@@ -5052,7 +5138,8 @@ var RoutstrClient = class {
|
|
|
5052
5138
|
modelId,
|
|
5053
5139
|
satsSpent,
|
|
5054
5140
|
usage: providedUsage,
|
|
5055
|
-
requestId: providedRequestId
|
|
5141
|
+
requestId: providedRequestId,
|
|
5142
|
+
clientApiKey
|
|
5056
5143
|
} = params;
|
|
5057
5144
|
if (!response || !modelId) {
|
|
5058
5145
|
return;
|
|
@@ -5079,13 +5166,14 @@ var RoutstrClient = class {
|
|
|
5079
5166
|
return;
|
|
5080
5167
|
}
|
|
5081
5168
|
const finalRequestId = requestId || "unknown";
|
|
5082
|
-
const store = await getDefaultSdkStore();
|
|
5169
|
+
const store = this.sdkStore ?? await getDefaultSdkStore();
|
|
5083
5170
|
const state = store.getState();
|
|
5171
|
+
const matchKey = clientApiKey ?? token;
|
|
5084
5172
|
const matchingClient = state.clientIds.find(
|
|
5085
|
-
(client) => client.apiKey ===
|
|
5173
|
+
(client) => client.apiKey === matchKey
|
|
5086
5174
|
);
|
|
5087
5175
|
const entryId = finalRequestId === "unknown" ? `req-${Date.now()}-${modelId}` : finalRequestId;
|
|
5088
|
-
const usageTracking = getDefaultUsageTrackingDriver();
|
|
5176
|
+
const usageTracking = this.usageTrackingDriver ?? getDefaultUsageTrackingDriver();
|
|
5089
5177
|
const entry = {
|
|
5090
5178
|
id: entryId,
|
|
5091
5179
|
timestamp: Date.now(),
|
|
@@ -5160,11 +5248,11 @@ var RoutstrClient = class {
|
|
|
5160
5248
|
return estimatedCosts;
|
|
5161
5249
|
}
|
|
5162
5250
|
/**
|
|
5163
|
-
* Get pending
|
|
5251
|
+
* Get pending API key amount
|
|
5164
5252
|
*/
|
|
5165
5253
|
_getPendingCashuTokenAmount() {
|
|
5166
|
-
const
|
|
5167
|
-
return
|
|
5254
|
+
const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
|
|
5255
|
+
return apiKeyDistribution.reduce((total, item) => total + item.amount, 0);
|
|
5168
5256
|
}
|
|
5169
5257
|
/**
|
|
5170
5258
|
* Handle errors and notify callbacks
|
|
@@ -5311,8 +5399,8 @@ var RoutstrClient = class {
|
|
|
5311
5399
|
const spendResult = await this.cashuSpender.spend({
|
|
5312
5400
|
mintUrl,
|
|
5313
5401
|
amount,
|
|
5314
|
-
baseUrl:
|
|
5315
|
-
reuseToken:
|
|
5402
|
+
baseUrl: "",
|
|
5403
|
+
reuseToken: false
|
|
5316
5404
|
});
|
|
5317
5405
|
if (!spendResult.token) {
|
|
5318
5406
|
this._log(
|
|
@@ -5325,6 +5413,7 @@ var RoutstrClient = class {
|
|
|
5325
5413
|
"DEBUG",
|
|
5326
5414
|
`[RoutstrClient] _spendToken: Cashu token created, token preview: ${spendResult.token}, balance: ${spendResult.balance} ${spendResult.unit ?? "sat"}`
|
|
5327
5415
|
);
|
|
5416
|
+
this.storageAdapter.addXcashuToken(baseUrl, spendResult.token);
|
|
5328
5417
|
}
|
|
5329
5418
|
return {
|
|
5330
5419
|
token: spendResult.token,
|
|
@@ -5362,6 +5451,7 @@ async function resolveRouteRequestContext(options) {
|
|
|
5362
5451
|
modelId,
|
|
5363
5452
|
requestBody,
|
|
5364
5453
|
path = "/v1/chat/completions",
|
|
5454
|
+
headers = {},
|
|
5365
5455
|
forcedProvider,
|
|
5366
5456
|
walletAdapter,
|
|
5367
5457
|
storageAdapter,
|
|
@@ -5372,7 +5462,9 @@ async function resolveRouteRequestContext(options) {
|
|
|
5372
5462
|
forceRefresh = false,
|
|
5373
5463
|
modelManager: providedModelManager,
|
|
5374
5464
|
debugLevel,
|
|
5375
|
-
mode = "apikeys"
|
|
5465
|
+
mode = "apikeys",
|
|
5466
|
+
usageTrackingDriver,
|
|
5467
|
+
sdkStore
|
|
5376
5468
|
} = options;
|
|
5377
5469
|
let modelManager;
|
|
5378
5470
|
let providers;
|
|
@@ -5436,7 +5528,8 @@ async function resolveRouteRequestContext(options) {
|
|
|
5436
5528
|
storageAdapter,
|
|
5437
5529
|
providerRegistry,
|
|
5438
5530
|
"min",
|
|
5439
|
-
mode
|
|
5531
|
+
mode,
|
|
5532
|
+
{ usageTrackingDriver, sdkStore }
|
|
5440
5533
|
);
|
|
5441
5534
|
if (debugLevel) {
|
|
5442
5535
|
client.setDebugLevel(debugLevel);
|
|
@@ -5456,17 +5549,19 @@ async function resolveRouteRequestContext(options) {
|
|
|
5456
5549
|
baseUrl,
|
|
5457
5550
|
mintUrl,
|
|
5458
5551
|
path,
|
|
5552
|
+
headers,
|
|
5459
5553
|
modelId,
|
|
5460
5554
|
proxiedBody
|
|
5461
5555
|
};
|
|
5462
5556
|
}
|
|
5463
5557
|
async function routeRequests(options) {
|
|
5464
|
-
const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5558
|
+
const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5465
5559
|
try {
|
|
5466
5560
|
const response = await client.routeRequest({
|
|
5467
5561
|
path,
|
|
5468
5562
|
method: "POST",
|
|
5469
5563
|
body: proxiedBody,
|
|
5564
|
+
headers,
|
|
5470
5565
|
baseUrl,
|
|
5471
5566
|
mintUrl,
|
|
5472
5567
|
modelId
|
|
@@ -5484,12 +5579,13 @@ async function routeRequests(options) {
|
|
|
5484
5579
|
}
|
|
5485
5580
|
async function routeRequestsToNodeResponse(options) {
|
|
5486
5581
|
const { res } = options;
|
|
5487
|
-
const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5582
|
+
const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
|
|
5488
5583
|
try {
|
|
5489
5584
|
await client.routeRequestToNodeResponse({
|
|
5490
5585
|
path,
|
|
5491
5586
|
method: "POST",
|
|
5492
5587
|
body: proxiedBody,
|
|
5588
|
+
headers,
|
|
5493
5589
|
baseUrl,
|
|
5494
5590
|
mintUrl,
|
|
5495
5591
|
modelId,
|
|
@@ -5519,6 +5615,6 @@ function extractStream(requestBody) {
|
|
|
5519
5615
|
return typeof stream === "boolean" ? stream : void 0;
|
|
5520
5616
|
}
|
|
5521
5617
|
|
|
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 };
|
|
5618
|
+
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
5619
|
//# sourceMappingURL=index.mjs.map
|
|
5524
5620
|
//# sourceMappingURL=index.mjs.map
|