@routstr/sdk 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.mts +7 -2
- package/dist/client/index.d.ts +7 -2
- package/dist/client/index.js +204 -68
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +204 -68
- package/dist/client/index.mjs.map +1 -1
- package/dist/discovery/index.d.mts +7 -1
- package/dist/discovery/index.d.ts +7 -1
- package/dist/discovery/index.js +66 -0
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +66 -0
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +325 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +325 -72
- package/dist/index.mjs.map +1 -1
- package/dist/{interfaces-BOfiz3Tt.d.mts → interfaces-B85Wx7ni.d.mts} +15 -0
- package/dist/{interfaces-BbAtkq7z.d.ts → interfaces-BVNyAmKu.d.ts} +15 -0
- package/dist/{interfaces-CW773NQv.d.ts → interfaces-CC0LT9p9.d.ts} +20 -0
- package/dist/{interfaces-CEOwpdG0.d.mts → interfaces-DGdP8fQp.d.mts} +20 -0
- package/dist/storage/index.d.mts +23 -4
- package/dist/storage/index.d.ts +23 -4
- package/dist/storage/index.js +55 -4
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +55 -4
- package/dist/storage/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +15 -3
- package/dist/wallet/index.d.ts +15 -3
- package/dist/wallet/index.js +84 -17
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +84 -17
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/client/index.mjs
CHANGED
|
@@ -106,6 +106,26 @@ var CashuSpender = class {
|
|
|
106
106
|
this.balanceManager = balanceManager;
|
|
107
107
|
}
|
|
108
108
|
_isBusy = false;
|
|
109
|
+
debugLevel = "WARN";
|
|
110
|
+
async receiveToken(token) {
|
|
111
|
+
const result = await this.walletAdapter.receiveToken(token);
|
|
112
|
+
if (!result.success && result.message?.includes("Failed to fetch mint")) {
|
|
113
|
+
const cachedTokens = this.storageAdapter.getCachedReceiveTokens();
|
|
114
|
+
const existingIndex = cachedTokens.findIndex((t) => t.token === token);
|
|
115
|
+
if (existingIndex === -1) {
|
|
116
|
+
this.storageAdapter.setCachedReceiveTokens([
|
|
117
|
+
...cachedTokens,
|
|
118
|
+
{
|
|
119
|
+
token,
|
|
120
|
+
amount: result.amount,
|
|
121
|
+
unit: result.unit,
|
|
122
|
+
createdAt: Date.now()
|
|
123
|
+
}
|
|
124
|
+
]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
109
129
|
async _getBalanceState() {
|
|
110
130
|
const mintBalances = await this.walletAdapter.getBalances();
|
|
111
131
|
const units = this.walletAdapter.getMintUnits();
|
|
@@ -148,6 +168,32 @@ var CashuSpender = class {
|
|
|
148
168
|
get isBusy() {
|
|
149
169
|
return this._isBusy;
|
|
150
170
|
}
|
|
171
|
+
getDebugLevel() {
|
|
172
|
+
return this.debugLevel;
|
|
173
|
+
}
|
|
174
|
+
setDebugLevel(level) {
|
|
175
|
+
this.debugLevel = level;
|
|
176
|
+
}
|
|
177
|
+
_log(level, ...args) {
|
|
178
|
+
const levelPriority = {
|
|
179
|
+
DEBUG: 0,
|
|
180
|
+
WARN: 1,
|
|
181
|
+
ERROR: 2
|
|
182
|
+
};
|
|
183
|
+
if (levelPriority[level] >= levelPriority[this.debugLevel]) {
|
|
184
|
+
switch (level) {
|
|
185
|
+
case "DEBUG":
|
|
186
|
+
console.log(...args);
|
|
187
|
+
break;
|
|
188
|
+
case "WARN":
|
|
189
|
+
console.warn(...args);
|
|
190
|
+
break;
|
|
191
|
+
case "ERROR":
|
|
192
|
+
console.error(...args);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
151
197
|
/**
|
|
152
198
|
* Spend Cashu tokens with automatic mint selection and retry logic
|
|
153
199
|
* Throws errors on failure instead of returning failed SpendResult
|
|
@@ -214,12 +260,16 @@ var CashuSpender = class {
|
|
|
214
260
|
excludeMints,
|
|
215
261
|
retryCount
|
|
216
262
|
} = options;
|
|
217
|
-
|
|
263
|
+
this._log(
|
|
264
|
+
"DEBUG",
|
|
218
265
|
`[CashuSpender] _spendInternal: amount=${amount}, mintUrl=${mintUrl}, baseUrl=${baseUrl}, reuseToken=${reuseToken}`
|
|
219
266
|
);
|
|
220
267
|
let adjustedAmount = Math.ceil(amount);
|
|
221
268
|
if (!adjustedAmount || isNaN(adjustedAmount)) {
|
|
222
|
-
|
|
269
|
+
this._log(
|
|
270
|
+
"ERROR",
|
|
271
|
+
`[CashuSpender] _spendInternal: Invalid amount: ${amount}`
|
|
272
|
+
);
|
|
223
273
|
return {
|
|
224
274
|
token: null,
|
|
225
275
|
status: "failed",
|
|
@@ -228,7 +278,8 @@ var CashuSpender = class {
|
|
|
228
278
|
};
|
|
229
279
|
}
|
|
230
280
|
if (reuseToken && baseUrl) {
|
|
231
|
-
|
|
281
|
+
this._log(
|
|
282
|
+
"DEBUG",
|
|
232
283
|
`[CashuSpender] _spendInternal: Attempting to reuse token for ${baseUrl}`
|
|
233
284
|
);
|
|
234
285
|
const existingResult = await this._tryReuseToken(
|
|
@@ -237,12 +288,14 @@ var CashuSpender = class {
|
|
|
237
288
|
mintUrl
|
|
238
289
|
);
|
|
239
290
|
if (existingResult) {
|
|
240
|
-
|
|
291
|
+
this._log(
|
|
292
|
+
"DEBUG",
|
|
241
293
|
`[CashuSpender] _spendInternal: Successfully reused token, balance: ${existingResult.balance}`
|
|
242
294
|
);
|
|
243
295
|
return existingResult;
|
|
244
296
|
}
|
|
245
|
-
|
|
297
|
+
this._log(
|
|
298
|
+
"DEBUG",
|
|
246
299
|
`[CashuSpender] _spendInternal: Could not reuse token, will create new token`
|
|
247
300
|
);
|
|
248
301
|
}
|
|
@@ -260,12 +313,14 @@ var CashuSpender = class {
|
|
|
260
313
|
(sum, item) => sum + item.amount,
|
|
261
314
|
0
|
|
262
315
|
);
|
|
263
|
-
|
|
316
|
+
this._log(
|
|
317
|
+
"DEBUG",
|
|
264
318
|
`[CashuSpender] _spendInternal: totalBalance=${totalBalance}, totalPending=${totalPending}, adjustedAmount=${adjustedAmount}`
|
|
265
319
|
);
|
|
266
320
|
const totalAvailableBalance = totalBalance + totalPending;
|
|
267
321
|
if (totalAvailableBalance < adjustedAmount) {
|
|
268
|
-
|
|
322
|
+
this._log(
|
|
323
|
+
"ERROR",
|
|
269
324
|
`[CashuSpender] _spendInternal: Insufficient balance, have=${totalAvailableBalance}, need=${adjustedAmount}`
|
|
270
325
|
);
|
|
271
326
|
return this._createInsufficientBalanceError(
|
|
@@ -333,7 +388,8 @@ var CashuSpender = class {
|
|
|
333
388
|
baseUrl,
|
|
334
389
|
status: "success"
|
|
335
390
|
});
|
|
336
|
-
|
|
391
|
+
this._log(
|
|
392
|
+
"DEBUG",
|
|
337
393
|
`[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`
|
|
338
394
|
);
|
|
339
395
|
return {
|
|
@@ -351,7 +407,7 @@ var CashuSpender = class {
|
|
|
351
407
|
if (!storedToken) return null;
|
|
352
408
|
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
353
409
|
const balanceForBaseUrl = pendingDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
|
|
354
|
-
|
|
410
|
+
this._log("DEBUG", "RESUINGDSR GSODGNSD", balanceForBaseUrl, amount);
|
|
355
411
|
if (balanceForBaseUrl > amount) {
|
|
356
412
|
const units = this.walletAdapter.getMintUnits();
|
|
357
413
|
const unit = units[mintUrl] || "sat";
|
|
@@ -369,7 +425,7 @@ var CashuSpender = class {
|
|
|
369
425
|
baseUrl,
|
|
370
426
|
amount: topUpAmount
|
|
371
427
|
});
|
|
372
|
-
|
|
428
|
+
this._log("DEBUG", "TOPUP ", topUpResult);
|
|
373
429
|
if (topUpResult.success && topUpResult.toppedUpAmount) {
|
|
374
430
|
const newBalance = balanceForBaseUrl + topUpResult.toppedUpAmount;
|
|
375
431
|
const units = this.walletAdapter.getMintUnits();
|
|
@@ -391,7 +447,7 @@ var CashuSpender = class {
|
|
|
391
447
|
baseUrl,
|
|
392
448
|
storedToken
|
|
393
449
|
);
|
|
394
|
-
|
|
450
|
+
this._log("DEBUG", providerBalance);
|
|
395
451
|
if (providerBalance <= 0) {
|
|
396
452
|
this.storageAdapter.removeToken(baseUrl);
|
|
397
453
|
}
|
|
@@ -410,7 +466,7 @@ var CashuSpender = class {
|
|
|
410
466
|
const refundResults = await Promise.allSettled(
|
|
411
467
|
toRefund.map(async (pending) => {
|
|
412
468
|
const token = this.storageAdapter.getToken(pending.baseUrl);
|
|
413
|
-
|
|
469
|
+
this._log("DEBUG", token, this.balanceManager);
|
|
414
470
|
if (!token || !this.balanceManager) {
|
|
415
471
|
return { baseUrl: pending.baseUrl, success: false };
|
|
416
472
|
}
|
|
@@ -426,7 +482,7 @@ var CashuSpender = class {
|
|
|
426
482
|
baseUrl: pending.baseUrl,
|
|
427
483
|
token
|
|
428
484
|
});
|
|
429
|
-
|
|
485
|
+
this._log("DEBUG", result);
|
|
430
486
|
if (result.success) {
|
|
431
487
|
this.storageAdapter.removeToken(pending.baseUrl);
|
|
432
488
|
}
|
|
@@ -524,11 +580,22 @@ var CashuSpender = class {
|
|
|
524
580
|
|
|
525
581
|
// wallet/BalanceManager.ts
|
|
526
582
|
var BalanceManager = class {
|
|
527
|
-
constructor(walletAdapter, storageAdapter, providerRegistry) {
|
|
583
|
+
constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender) {
|
|
528
584
|
this.walletAdapter = walletAdapter;
|
|
529
585
|
this.storageAdapter = storageAdapter;
|
|
530
586
|
this.providerRegistry = providerRegistry;
|
|
587
|
+
if (cashuSpender) {
|
|
588
|
+
this.cashuSpender = cashuSpender;
|
|
589
|
+
} else {
|
|
590
|
+
this.cashuSpender = new CashuSpender(
|
|
591
|
+
walletAdapter,
|
|
592
|
+
storageAdapter,
|
|
593
|
+
providerRegistry,
|
|
594
|
+
this
|
|
595
|
+
);
|
|
596
|
+
}
|
|
531
597
|
}
|
|
598
|
+
cashuSpender;
|
|
532
599
|
/**
|
|
533
600
|
* Unified refund - handles both NIP-60 and legacy wallet refunds
|
|
534
601
|
*/
|
|
@@ -563,7 +630,7 @@ var BalanceManager = class {
|
|
|
563
630
|
this.storageAdapter.removeToken(baseUrl);
|
|
564
631
|
return { success: true, message: "No balance to refund" };
|
|
565
632
|
}
|
|
566
|
-
const receiveResult = await this.
|
|
633
|
+
const receiveResult = await this.cashuSpender.receiveToken(
|
|
567
634
|
fetchResult.token
|
|
568
635
|
);
|
|
569
636
|
const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
|
|
@@ -608,7 +675,7 @@ var BalanceManager = class {
|
|
|
608
675
|
if (fetchResult.error === "No balance to refund") {
|
|
609
676
|
return { success: false, message: "No balance to refund" };
|
|
610
677
|
}
|
|
611
|
-
const receiveResult = await this.
|
|
678
|
+
const receiveResult = await this.cashuSpender.receiveToken(
|
|
612
679
|
fetchResult.token
|
|
613
680
|
);
|
|
614
681
|
const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
|
|
@@ -1049,7 +1116,7 @@ var BalanceManager = class {
|
|
|
1049
1116
|
*/
|
|
1050
1117
|
async _recoverFailedTopUp(cashuToken) {
|
|
1051
1118
|
try {
|
|
1052
|
-
await this.
|
|
1119
|
+
await this.cashuSpender.receiveToken(cashuToken);
|
|
1053
1120
|
} catch (error) {
|
|
1054
1121
|
console.error(
|
|
1055
1122
|
"[BalanceManager._recoverFailedTopUp] Failed to recover token",
|
|
@@ -1720,12 +1787,39 @@ var RoutstrClient = class {
|
|
|
1720
1787
|
providerManager;
|
|
1721
1788
|
alertLevel;
|
|
1722
1789
|
mode;
|
|
1790
|
+
debugLevel = "WARN";
|
|
1723
1791
|
/**
|
|
1724
1792
|
* Get the current client mode
|
|
1725
1793
|
*/
|
|
1726
1794
|
getMode() {
|
|
1727
1795
|
return this.mode;
|
|
1728
1796
|
}
|
|
1797
|
+
getDebugLevel() {
|
|
1798
|
+
return this.debugLevel;
|
|
1799
|
+
}
|
|
1800
|
+
setDebugLevel(level) {
|
|
1801
|
+
this.debugLevel = level;
|
|
1802
|
+
}
|
|
1803
|
+
_log(level, ...args) {
|
|
1804
|
+
const levelPriority = {
|
|
1805
|
+
DEBUG: 0,
|
|
1806
|
+
WARN: 1,
|
|
1807
|
+
ERROR: 2
|
|
1808
|
+
};
|
|
1809
|
+
if (levelPriority[level] >= levelPriority[this.debugLevel]) {
|
|
1810
|
+
switch (level) {
|
|
1811
|
+
case "DEBUG":
|
|
1812
|
+
console.log(...args);
|
|
1813
|
+
break;
|
|
1814
|
+
case "WARN":
|
|
1815
|
+
console.warn(...args);
|
|
1816
|
+
break;
|
|
1817
|
+
case "ERROR":
|
|
1818
|
+
console.error(...args);
|
|
1819
|
+
break;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1729
1823
|
/**
|
|
1730
1824
|
* Get the CashuSpender instance
|
|
1731
1825
|
*/
|
|
@@ -1789,7 +1883,7 @@ var RoutstrClient = class {
|
|
|
1789
1883
|
amount: requiredSats,
|
|
1790
1884
|
baseUrl
|
|
1791
1885
|
});
|
|
1792
|
-
|
|
1886
|
+
this._log("DEBUG", token, baseUrl);
|
|
1793
1887
|
let requestBody = body;
|
|
1794
1888
|
if (body && typeof body === "object") {
|
|
1795
1889
|
const bodyObj = body;
|
|
@@ -1813,8 +1907,9 @@ var RoutstrClient = class {
|
|
|
1813
1907
|
});
|
|
1814
1908
|
const tokenBalanceInSats = tokenBalanceUnit === "msat" ? tokenBalance / 1e3 : tokenBalance;
|
|
1815
1909
|
const baseUrlUsed = response.baseUrl || baseUrl;
|
|
1910
|
+
const tokenUsed = response.token || token;
|
|
1816
1911
|
await this._handlePostResponseBalanceUpdate({
|
|
1817
|
-
token,
|
|
1912
|
+
token: tokenUsed,
|
|
1818
1913
|
baseUrl: baseUrlUsed,
|
|
1819
1914
|
initialTokenBalance: tokenBalanceInSats,
|
|
1820
1915
|
response
|
|
@@ -1950,22 +2045,30 @@ var RoutstrClient = class {
|
|
|
1950
2045
|
const { path, method, body, baseUrl, token, headers } = params;
|
|
1951
2046
|
try {
|
|
1952
2047
|
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
1953
|
-
if (this.mode === "xcashu")
|
|
2048
|
+
if (this.mode === "xcashu") this._log("DEBUG", "HEADERS,", headers);
|
|
1954
2049
|
const response = await fetch(url, {
|
|
1955
2050
|
method,
|
|
1956
2051
|
headers,
|
|
1957
2052
|
body: body === void 0 || method === "GET" ? void 0 : JSON.stringify(body)
|
|
1958
2053
|
});
|
|
1959
|
-
if (this.mode === "xcashu")
|
|
2054
|
+
if (this.mode === "xcashu") this._log("DEBUG", "response,", response);
|
|
1960
2055
|
response.baseUrl = baseUrl;
|
|
2056
|
+
response.token = token;
|
|
1961
2057
|
if (!response.ok) {
|
|
1962
2058
|
const requestId = response.headers.get("x-routstr-request-id") || void 0;
|
|
2059
|
+
let bodyText;
|
|
2060
|
+
try {
|
|
2061
|
+
bodyText = await response.text();
|
|
2062
|
+
} catch (e) {
|
|
2063
|
+
bodyText = void 0;
|
|
2064
|
+
}
|
|
1963
2065
|
return await this._handleErrorResponse(
|
|
1964
2066
|
params,
|
|
1965
2067
|
token,
|
|
1966
2068
|
response.status,
|
|
1967
2069
|
requestId,
|
|
1968
|
-
this.mode === "xcashu" ? response.headers.get("x-cashu") ?? void 0 : void 0
|
|
2070
|
+
this.mode === "xcashu" ? response.headers.get("x-cashu") ?? void 0 : void 0,
|
|
2071
|
+
bodyText
|
|
1969
2072
|
);
|
|
1970
2073
|
}
|
|
1971
2074
|
return response;
|
|
@@ -1984,41 +2087,47 @@ var RoutstrClient = class {
|
|
|
1984
2087
|
/**
|
|
1985
2088
|
* Handle error responses with failover
|
|
1986
2089
|
*/
|
|
1987
|
-
async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken) {
|
|
2090
|
+
async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken, responseBody) {
|
|
1988
2091
|
const { path, method, body, selectedModel, baseUrl, mintUrl } = params;
|
|
1989
2092
|
let tryNextProvider = false;
|
|
1990
|
-
|
|
2093
|
+
this._log(
|
|
2094
|
+
"DEBUG",
|
|
1991
2095
|
`[RoutstrClient] _handleErrorResponse: status=${status}, baseUrl=${baseUrl}, mode=${this.mode}, token preview=${token}, requestId=${requestId}`
|
|
1992
2096
|
);
|
|
1993
|
-
|
|
2097
|
+
this._log(
|
|
2098
|
+
"DEBUG",
|
|
1994
2099
|
`[RoutstrClient] _handleErrorResponse: Attempting to receive/restore token for ${baseUrl}`
|
|
1995
2100
|
);
|
|
1996
2101
|
if (params.token.startsWith("cashu")) {
|
|
1997
|
-
const tryReceiveTokenResult = await this.
|
|
2102
|
+
const tryReceiveTokenResult = await this.cashuSpender.receiveToken(
|
|
1998
2103
|
params.token
|
|
1999
2104
|
);
|
|
2000
2105
|
if (tryReceiveTokenResult.success) {
|
|
2001
|
-
|
|
2106
|
+
this._log(
|
|
2107
|
+
"DEBUG",
|
|
2002
2108
|
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${tryReceiveTokenResult.amount}`
|
|
2003
2109
|
);
|
|
2004
2110
|
tryNextProvider = true;
|
|
2005
2111
|
if (this.mode === "lazyrefund")
|
|
2006
2112
|
this.storageAdapter.removeToken(baseUrl);
|
|
2007
2113
|
} else {
|
|
2008
|
-
|
|
2009
|
-
|
|
2114
|
+
this._log(
|
|
2115
|
+
"DEBUG",
|
|
2116
|
+
`[RoutstrClient] _handleErrorResponse: Failed to receive token. `
|
|
2010
2117
|
);
|
|
2011
2118
|
}
|
|
2012
2119
|
}
|
|
2013
2120
|
if (this.mode === "xcashu") {
|
|
2014
2121
|
if (xCashuRefundToken) {
|
|
2015
|
-
|
|
2122
|
+
this._log(
|
|
2123
|
+
"DEBUG",
|
|
2016
2124
|
`[RoutstrClient] _handleErrorResponse: Attempting to receive xcashu refund token, preview=${xCashuRefundToken.substring(0, 20)}...`
|
|
2017
2125
|
);
|
|
2018
2126
|
try {
|
|
2019
|
-
const receiveResult = await this.
|
|
2127
|
+
const receiveResult = await this.cashuSpender.receiveToken(xCashuRefundToken);
|
|
2020
2128
|
if (receiveResult.success) {
|
|
2021
|
-
|
|
2129
|
+
this._log(
|
|
2130
|
+
"DEBUG",
|
|
2022
2131
|
`[RoutstrClient] _handleErrorResponse: xcashu refund received, amount=${receiveResult.amount}`
|
|
2023
2132
|
);
|
|
2024
2133
|
tryNextProvider = true;
|
|
@@ -2030,7 +2139,7 @@ var RoutstrClient = class {
|
|
|
2030
2139
|
requestId
|
|
2031
2140
|
);
|
|
2032
2141
|
} catch (error) {
|
|
2033
|
-
|
|
2142
|
+
this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
|
|
2034
2143
|
throw new ProviderError(
|
|
2035
2144
|
baseUrl,
|
|
2036
2145
|
status,
|
|
@@ -2048,14 +2157,15 @@ var RoutstrClient = class {
|
|
|
2048
2157
|
);
|
|
2049
2158
|
}
|
|
2050
2159
|
}
|
|
2051
|
-
if (status === 402 && !tryNextProvider && (this.mode === "apikeys" || this.mode === "lazyrefund")) {
|
|
2160
|
+
if ((status === 402 || status === 413 && responseBody?.includes("Insufficient balance")) && !tryNextProvider && (this.mode === "apikeys" || this.mode === "lazyrefund")) {
|
|
2052
2161
|
const topupResult = await this.balanceManager.topUp({
|
|
2053
2162
|
mintUrl,
|
|
2054
2163
|
baseUrl,
|
|
2055
2164
|
amount: params.requiredSats * TOPUP_MARGIN,
|
|
2056
2165
|
token: params.token
|
|
2057
2166
|
});
|
|
2058
|
-
|
|
2167
|
+
this._log(
|
|
2168
|
+
"DEBUG",
|
|
2059
2169
|
`[RoutstrClient] _handleErrorResponse: Topup result for ${baseUrl}: success=${topupResult.success}, message=${topupResult.message}`
|
|
2060
2170
|
);
|
|
2061
2171
|
if (!topupResult.success) {
|
|
@@ -2065,18 +2175,21 @@ var RoutstrClient = class {
|
|
|
2065
2175
|
const haveMatch = message.match(/have (\d+)/);
|
|
2066
2176
|
const required = needMatch ? parseInt(needMatch[1], 10) : params.requiredSats;
|
|
2067
2177
|
const available = haveMatch ? parseInt(haveMatch[1], 10) : 0;
|
|
2068
|
-
|
|
2178
|
+
this._log(
|
|
2179
|
+
"DEBUG",
|
|
2069
2180
|
`[RoutstrClient] _handleErrorResponse: Insufficient balance, need=${required}, have=${available}`
|
|
2070
2181
|
);
|
|
2071
2182
|
throw new InsufficientBalanceError(required, available);
|
|
2072
2183
|
} else {
|
|
2073
|
-
|
|
2184
|
+
this._log(
|
|
2185
|
+
"DEBUG",
|
|
2074
2186
|
`[RoutstrClient] _handleErrorResponse: Topup failed with non-insufficient-balance error, will try next provider`
|
|
2075
2187
|
);
|
|
2076
2188
|
tryNextProvider = true;
|
|
2077
2189
|
}
|
|
2078
2190
|
} else {
|
|
2079
|
-
|
|
2191
|
+
this._log(
|
|
2192
|
+
"DEBUG",
|
|
2080
2193
|
`[RoutstrClient] _handleErrorResponse: Topup successful, will retry with new token`
|
|
2081
2194
|
);
|
|
2082
2195
|
}
|
|
@@ -2087,8 +2200,9 @@ var RoutstrClient = class {
|
|
|
2087
2200
|
headers: this._withAuthHeader(params.baseHeaders, params.token)
|
|
2088
2201
|
});
|
|
2089
2202
|
}
|
|
2090
|
-
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 521) && !tryNextProvider) {
|
|
2091
|
-
|
|
2203
|
+
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
2204
|
+
this._log(
|
|
2205
|
+
"DEBUG",
|
|
2092
2206
|
`[RoutstrClient] _handleErrorResponse: Status ${status} (auth/server error), attempting refund for ${baseUrl}, mode=${this.mode}`
|
|
2093
2207
|
);
|
|
2094
2208
|
if (this.mode === "lazyrefund") {
|
|
@@ -2098,7 +2212,8 @@ var RoutstrClient = class {
|
|
|
2098
2212
|
baseUrl,
|
|
2099
2213
|
token: params.token
|
|
2100
2214
|
});
|
|
2101
|
-
|
|
2215
|
+
this._log(
|
|
2216
|
+
"DEBUG",
|
|
2102
2217
|
`[RoutstrClient] _handleErrorResponse: Lazyrefund result: success=${refundResult.success}`
|
|
2103
2218
|
);
|
|
2104
2219
|
if (refundResult.success) this.storageAdapter.removeToken(baseUrl);
|
|
@@ -2118,14 +2233,16 @@ var RoutstrClient = class {
|
|
|
2118
2233
|
);
|
|
2119
2234
|
}
|
|
2120
2235
|
} else if (this.mode === "apikeys") {
|
|
2121
|
-
|
|
2236
|
+
this._log(
|
|
2237
|
+
"DEBUG",
|
|
2122
2238
|
`[RoutstrClient] _handleErrorResponse: Attempting API key refund for ${baseUrl}, key preview=${token}`
|
|
2123
2239
|
);
|
|
2124
2240
|
const initialBalance = await this.balanceManager.getTokenBalance(
|
|
2125
2241
|
token,
|
|
2126
2242
|
baseUrl
|
|
2127
2243
|
);
|
|
2128
|
-
|
|
2244
|
+
this._log(
|
|
2245
|
+
"DEBUG",
|
|
2129
2246
|
`[RoutstrClient] _handleErrorResponse: Initial API key balance: ${initialBalance.amount}`
|
|
2130
2247
|
);
|
|
2131
2248
|
const refundResult = await this.balanceManager.refundApiKey({
|
|
@@ -2133,7 +2250,8 @@ var RoutstrClient = class {
|
|
|
2133
2250
|
baseUrl,
|
|
2134
2251
|
apiKey: token
|
|
2135
2252
|
});
|
|
2136
|
-
|
|
2253
|
+
this._log(
|
|
2254
|
+
"DEBUG",
|
|
2137
2255
|
`[RoutstrClient] _handleErrorResponse: API key refund result: success=${refundResult.success}, message=${refundResult.message}`
|
|
2138
2256
|
);
|
|
2139
2257
|
if (!refundResult.success && initialBalance.amount > 0) {
|
|
@@ -2148,7 +2266,8 @@ var RoutstrClient = class {
|
|
|
2148
2266
|
}
|
|
2149
2267
|
}
|
|
2150
2268
|
this.providerManager.markFailed(baseUrl);
|
|
2151
|
-
|
|
2269
|
+
this._log(
|
|
2270
|
+
"DEBUG",
|
|
2152
2271
|
`[RoutstrClient] _handleErrorResponse: Marked provider ${baseUrl} as failed`
|
|
2153
2272
|
);
|
|
2154
2273
|
if (!selectedModel) {
|
|
@@ -2163,7 +2282,8 @@ var RoutstrClient = class {
|
|
|
2163
2282
|
baseUrl
|
|
2164
2283
|
);
|
|
2165
2284
|
if (nextProvider) {
|
|
2166
|
-
|
|
2285
|
+
this._log(
|
|
2286
|
+
"DEBUG",
|
|
2167
2287
|
`[RoutstrClient] _handleErrorResponse: Failing over to next provider: ${nextProvider}, model: ${selectedModel.id}`
|
|
2168
2288
|
);
|
|
2169
2289
|
const newModel = await this.providerManager.getModelForProvider(
|
|
@@ -2178,7 +2298,8 @@ var RoutstrClient = class {
|
|
|
2178
2298
|
messagesForPricing,
|
|
2179
2299
|
params.maxTokens
|
|
2180
2300
|
);
|
|
2181
|
-
|
|
2301
|
+
this._log(
|
|
2302
|
+
"DEBUG",
|
|
2182
2303
|
`[RoutstrClient] _handleErrorResponse: Creating new token for failover provider ${nextProvider}, required sats: ${newRequiredSats}`
|
|
2183
2304
|
);
|
|
2184
2305
|
const spendResult = await this._spendToken({
|
|
@@ -2210,10 +2331,10 @@ var RoutstrClient = class {
|
|
|
2210
2331
|
const refundToken = response.headers.get("x-cashu") ?? void 0;
|
|
2211
2332
|
if (refundToken) {
|
|
2212
2333
|
try {
|
|
2213
|
-
const receiveResult = await this.
|
|
2334
|
+
const receiveResult = await this.cashuSpender.receiveToken(refundToken);
|
|
2214
2335
|
satsSpent = initialTokenBalance - receiveResult.amount * (receiveResult.unit == "sat" ? 1 : 1e3);
|
|
2215
2336
|
} catch (error) {
|
|
2216
|
-
|
|
2337
|
+
this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
|
|
2217
2338
|
}
|
|
2218
2339
|
}
|
|
2219
2340
|
} else if (this.mode === "lazyrefund") {
|
|
@@ -2230,7 +2351,8 @@ var RoutstrClient = class {
|
|
|
2230
2351
|
token,
|
|
2231
2352
|
baseUrl
|
|
2232
2353
|
);
|
|
2233
|
-
|
|
2354
|
+
this._log(
|
|
2355
|
+
"DEBUG",
|
|
2234
2356
|
"LATEST Balance",
|
|
2235
2357
|
latestBalanceInfo.amount,
|
|
2236
2358
|
latestBalanceInfo.reserved,
|
|
@@ -2242,7 +2364,7 @@ var RoutstrClient = class {
|
|
|
2242
2364
|
this.storageAdapter.updateApiKeyBalance(baseUrl, latestTokenBalance);
|
|
2243
2365
|
satsSpent = initialTokenBalance - latestTokenBalance;
|
|
2244
2366
|
} catch (e) {
|
|
2245
|
-
|
|
2367
|
+
this._log("WARN", "Could not get updated API key balance:", e);
|
|
2246
2368
|
satsSpent = fallbackSatsSpent ?? initialTokenBalance;
|
|
2247
2369
|
}
|
|
2248
2370
|
}
|
|
@@ -2353,11 +2475,12 @@ var RoutstrClient = class {
|
|
|
2353
2475
|
* Handle errors and notify callbacks
|
|
2354
2476
|
*/
|
|
2355
2477
|
_handleError(error, callbacks) {
|
|
2356
|
-
|
|
2478
|
+
this._log("ERROR", "[RoutstrClient] _handleError: Error occurred", error);
|
|
2357
2479
|
if (error instanceof Error) {
|
|
2358
2480
|
const isStreamError = error.message.includes("Error in input stream") || error.message.includes("Load failed");
|
|
2359
2481
|
const modifiedErrorMsg = isStreamError ? "AI stream was cut off, turn on Keep Active or please try again" : error.message;
|
|
2360
|
-
|
|
2482
|
+
this._log(
|
|
2483
|
+
"ERROR",
|
|
2361
2484
|
`[RoutstrClient] _handleError: Error type=${error.constructor.name}, message=${modifiedErrorMsg}, isStreamError=${isStreamError}`
|
|
2362
2485
|
);
|
|
2363
2486
|
callbacks.onMessageAppend({
|
|
@@ -2386,13 +2509,15 @@ var RoutstrClient = class {
|
|
|
2386
2509
|
*/
|
|
2387
2510
|
async _spendToken(params) {
|
|
2388
2511
|
const { mintUrl, amount, baseUrl } = params;
|
|
2389
|
-
|
|
2512
|
+
this._log(
|
|
2513
|
+
"DEBUG",
|
|
2390
2514
|
`[RoutstrClient] _spendToken: mode=${this.mode}, amount=${amount}, baseUrl=${baseUrl}, mintUrl=${mintUrl}`
|
|
2391
2515
|
);
|
|
2392
2516
|
if (this.mode === "apikeys") {
|
|
2393
2517
|
let parentApiKey = this.storageAdapter.getApiKey(baseUrl);
|
|
2394
2518
|
if (!parentApiKey) {
|
|
2395
|
-
|
|
2519
|
+
this._log(
|
|
2520
|
+
"DEBUG",
|
|
2396
2521
|
`[RoutstrClient] _spendToken: No existing API key for ${baseUrl}, creating new one via Cashu`
|
|
2397
2522
|
);
|
|
2398
2523
|
const spendResult2 = await this.cashuSpender.spend({
|
|
@@ -2402,7 +2527,8 @@ var RoutstrClient = class {
|
|
|
2402
2527
|
reuseToken: false
|
|
2403
2528
|
});
|
|
2404
2529
|
if (!spendResult2.token) {
|
|
2405
|
-
|
|
2530
|
+
this._log(
|
|
2531
|
+
"ERROR",
|
|
2406
2532
|
`[RoutstrClient] _spendToken: Failed to create Cashu token for API key creation, error:`,
|
|
2407
2533
|
spendResult2.error
|
|
2408
2534
|
);
|
|
@@ -2410,30 +2536,35 @@ var RoutstrClient = class {
|
|
|
2410
2536
|
`[RoutstrClient] _spendToken: Failed to create Cashu token for API key creation, error: ${spendResult2.error}`
|
|
2411
2537
|
);
|
|
2412
2538
|
} else {
|
|
2413
|
-
|
|
2539
|
+
this._log(
|
|
2540
|
+
"DEBUG",
|
|
2414
2541
|
`[RoutstrClient] _spendToken: Cashu token created, token preview: ${spendResult2.token}`
|
|
2415
2542
|
);
|
|
2416
2543
|
}
|
|
2417
|
-
|
|
2544
|
+
this._log(
|
|
2545
|
+
"DEBUG",
|
|
2418
2546
|
`[RoutstrClient] _spendToken: Created API key for ${baseUrl}, key preview: ${spendResult2.token}, balance: ${spendResult2.balance}`
|
|
2419
2547
|
);
|
|
2420
2548
|
try {
|
|
2421
2549
|
this.storageAdapter.setApiKey(baseUrl, spendResult2.token);
|
|
2422
2550
|
} catch (error) {
|
|
2423
2551
|
if (error instanceof Error && error.message.includes("ApiKey already exists")) {
|
|
2424
|
-
const tryReceiveTokenResult = await this.
|
|
2552
|
+
const tryReceiveTokenResult = await this.cashuSpender.receiveToken(
|
|
2425
2553
|
spendResult2.token
|
|
2426
2554
|
);
|
|
2427
2555
|
if (tryReceiveTokenResult.success) {
|
|
2428
|
-
|
|
2556
|
+
this._log(
|
|
2557
|
+
"DEBUG",
|
|
2429
2558
|
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${tryReceiveTokenResult.amount}`
|
|
2430
2559
|
);
|
|
2431
2560
|
} else {
|
|
2432
|
-
|
|
2561
|
+
this._log(
|
|
2562
|
+
"DEBUG",
|
|
2433
2563
|
`[RoutstrClient] _handleErrorResponse: Token restore failed or not needed`
|
|
2434
2564
|
);
|
|
2435
2565
|
}
|
|
2436
|
-
|
|
2566
|
+
this._log(
|
|
2567
|
+
"DEBUG",
|
|
2437
2568
|
`[RoutstrClient] _spendToken: API key already exists for ${baseUrl}, using existing key`
|
|
2438
2569
|
);
|
|
2439
2570
|
} else {
|
|
@@ -2442,7 +2573,8 @@ var RoutstrClient = class {
|
|
|
2442
2573
|
}
|
|
2443
2574
|
parentApiKey = this.storageAdapter.getApiKey(baseUrl);
|
|
2444
2575
|
} else {
|
|
2445
|
-
|
|
2576
|
+
this._log(
|
|
2577
|
+
"DEBUG",
|
|
2446
2578
|
`[RoutstrClient] _spendToken: Using existing API key for ${baseUrl}, key preview: ${parentApiKey.key}`
|
|
2447
2579
|
);
|
|
2448
2580
|
}
|
|
@@ -2464,10 +2596,11 @@ var RoutstrClient = class {
|
|
|
2464
2596
|
tokenBalance = balanceInfo.amount;
|
|
2465
2597
|
tokenBalanceUnit = balanceInfo.unit;
|
|
2466
2598
|
} catch (e) {
|
|
2467
|
-
|
|
2599
|
+
this._log("WARN", "Could not get initial API key balance:", e);
|
|
2468
2600
|
}
|
|
2469
2601
|
}
|
|
2470
|
-
|
|
2602
|
+
this._log(
|
|
2603
|
+
"DEBUG",
|
|
2471
2604
|
`[RoutstrClient] _spendToken: Returning token with balance=${tokenBalance} ${tokenBalanceUnit}`
|
|
2472
2605
|
);
|
|
2473
2606
|
return {
|
|
@@ -2476,7 +2609,8 @@ var RoutstrClient = class {
|
|
|
2476
2609
|
tokenBalanceUnit
|
|
2477
2610
|
};
|
|
2478
2611
|
}
|
|
2479
|
-
|
|
2612
|
+
this._log(
|
|
2613
|
+
"DEBUG",
|
|
2480
2614
|
`[RoutstrClient] _spendToken: Calling CashuSpender.spend for amount=${amount}, mintUrl=${mintUrl}, mode=${this.mode}`
|
|
2481
2615
|
);
|
|
2482
2616
|
const spendResult = await this.cashuSpender.spend({
|
|
@@ -2486,12 +2620,14 @@ var RoutstrClient = class {
|
|
|
2486
2620
|
reuseToken: this.mode === "lazyrefund"
|
|
2487
2621
|
});
|
|
2488
2622
|
if (!spendResult.token) {
|
|
2489
|
-
|
|
2623
|
+
this._log(
|
|
2624
|
+
"ERROR",
|
|
2490
2625
|
`[RoutstrClient] _spendToken: CashuSpender.spend failed, error:`,
|
|
2491
2626
|
spendResult.error
|
|
2492
2627
|
);
|
|
2493
2628
|
} else {
|
|
2494
|
-
|
|
2629
|
+
this._log(
|
|
2630
|
+
"DEBUG",
|
|
2495
2631
|
`[RoutstrClient] _spendToken: Cashu token created, token preview: ${spendResult.token}, balance: ${spendResult.balance} ${spendResult.unit ?? "sat"}`
|
|
2496
2632
|
);
|
|
2497
2633
|
}
|