@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.js
CHANGED
|
@@ -108,6 +108,26 @@ var CashuSpender = class {
|
|
|
108
108
|
this.balanceManager = balanceManager;
|
|
109
109
|
}
|
|
110
110
|
_isBusy = false;
|
|
111
|
+
debugLevel = "WARN";
|
|
112
|
+
async receiveToken(token) {
|
|
113
|
+
const result = await this.walletAdapter.receiveToken(token);
|
|
114
|
+
if (!result.success && result.message?.includes("Failed to fetch mint")) {
|
|
115
|
+
const cachedTokens = this.storageAdapter.getCachedReceiveTokens();
|
|
116
|
+
const existingIndex = cachedTokens.findIndex((t) => t.token === token);
|
|
117
|
+
if (existingIndex === -1) {
|
|
118
|
+
this.storageAdapter.setCachedReceiveTokens([
|
|
119
|
+
...cachedTokens,
|
|
120
|
+
{
|
|
121
|
+
token,
|
|
122
|
+
amount: result.amount,
|
|
123
|
+
unit: result.unit,
|
|
124
|
+
createdAt: Date.now()
|
|
125
|
+
}
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
111
131
|
async _getBalanceState() {
|
|
112
132
|
const mintBalances = await this.walletAdapter.getBalances();
|
|
113
133
|
const units = this.walletAdapter.getMintUnits();
|
|
@@ -150,6 +170,32 @@ var CashuSpender = class {
|
|
|
150
170
|
get isBusy() {
|
|
151
171
|
return this._isBusy;
|
|
152
172
|
}
|
|
173
|
+
getDebugLevel() {
|
|
174
|
+
return this.debugLevel;
|
|
175
|
+
}
|
|
176
|
+
setDebugLevel(level) {
|
|
177
|
+
this.debugLevel = level;
|
|
178
|
+
}
|
|
179
|
+
_log(level, ...args) {
|
|
180
|
+
const levelPriority = {
|
|
181
|
+
DEBUG: 0,
|
|
182
|
+
WARN: 1,
|
|
183
|
+
ERROR: 2
|
|
184
|
+
};
|
|
185
|
+
if (levelPriority[level] >= levelPriority[this.debugLevel]) {
|
|
186
|
+
switch (level) {
|
|
187
|
+
case "DEBUG":
|
|
188
|
+
console.log(...args);
|
|
189
|
+
break;
|
|
190
|
+
case "WARN":
|
|
191
|
+
console.warn(...args);
|
|
192
|
+
break;
|
|
193
|
+
case "ERROR":
|
|
194
|
+
console.error(...args);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
153
199
|
/**
|
|
154
200
|
* Spend Cashu tokens with automatic mint selection and retry logic
|
|
155
201
|
* Throws errors on failure instead of returning failed SpendResult
|
|
@@ -216,12 +262,16 @@ var CashuSpender = class {
|
|
|
216
262
|
excludeMints,
|
|
217
263
|
retryCount
|
|
218
264
|
} = options;
|
|
219
|
-
|
|
265
|
+
this._log(
|
|
266
|
+
"DEBUG",
|
|
220
267
|
`[CashuSpender] _spendInternal: amount=${amount}, mintUrl=${mintUrl}, baseUrl=${baseUrl}, reuseToken=${reuseToken}`
|
|
221
268
|
);
|
|
222
269
|
let adjustedAmount = Math.ceil(amount);
|
|
223
270
|
if (!adjustedAmount || isNaN(adjustedAmount)) {
|
|
224
|
-
|
|
271
|
+
this._log(
|
|
272
|
+
"ERROR",
|
|
273
|
+
`[CashuSpender] _spendInternal: Invalid amount: ${amount}`
|
|
274
|
+
);
|
|
225
275
|
return {
|
|
226
276
|
token: null,
|
|
227
277
|
status: "failed",
|
|
@@ -230,7 +280,8 @@ var CashuSpender = class {
|
|
|
230
280
|
};
|
|
231
281
|
}
|
|
232
282
|
if (reuseToken && baseUrl) {
|
|
233
|
-
|
|
283
|
+
this._log(
|
|
284
|
+
"DEBUG",
|
|
234
285
|
`[CashuSpender] _spendInternal: Attempting to reuse token for ${baseUrl}`
|
|
235
286
|
);
|
|
236
287
|
const existingResult = await this._tryReuseToken(
|
|
@@ -239,12 +290,14 @@ var CashuSpender = class {
|
|
|
239
290
|
mintUrl
|
|
240
291
|
);
|
|
241
292
|
if (existingResult) {
|
|
242
|
-
|
|
293
|
+
this._log(
|
|
294
|
+
"DEBUG",
|
|
243
295
|
`[CashuSpender] _spendInternal: Successfully reused token, balance: ${existingResult.balance}`
|
|
244
296
|
);
|
|
245
297
|
return existingResult;
|
|
246
298
|
}
|
|
247
|
-
|
|
299
|
+
this._log(
|
|
300
|
+
"DEBUG",
|
|
248
301
|
`[CashuSpender] _spendInternal: Could not reuse token, will create new token`
|
|
249
302
|
);
|
|
250
303
|
}
|
|
@@ -262,12 +315,14 @@ var CashuSpender = class {
|
|
|
262
315
|
(sum, item) => sum + item.amount,
|
|
263
316
|
0
|
|
264
317
|
);
|
|
265
|
-
|
|
318
|
+
this._log(
|
|
319
|
+
"DEBUG",
|
|
266
320
|
`[CashuSpender] _spendInternal: totalBalance=${totalBalance}, totalPending=${totalPending}, adjustedAmount=${adjustedAmount}`
|
|
267
321
|
);
|
|
268
322
|
const totalAvailableBalance = totalBalance + totalPending;
|
|
269
323
|
if (totalAvailableBalance < adjustedAmount) {
|
|
270
|
-
|
|
324
|
+
this._log(
|
|
325
|
+
"ERROR",
|
|
271
326
|
`[CashuSpender] _spendInternal: Insufficient balance, have=${totalAvailableBalance}, need=${adjustedAmount}`
|
|
272
327
|
);
|
|
273
328
|
return this._createInsufficientBalanceError(
|
|
@@ -335,7 +390,8 @@ var CashuSpender = class {
|
|
|
335
390
|
baseUrl,
|
|
336
391
|
status: "success"
|
|
337
392
|
});
|
|
338
|
-
|
|
393
|
+
this._log(
|
|
394
|
+
"DEBUG",
|
|
339
395
|
`[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`
|
|
340
396
|
);
|
|
341
397
|
return {
|
|
@@ -353,7 +409,7 @@ var CashuSpender = class {
|
|
|
353
409
|
if (!storedToken) return null;
|
|
354
410
|
const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
|
|
355
411
|
const balanceForBaseUrl = pendingDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
|
|
356
|
-
|
|
412
|
+
this._log("DEBUG", "RESUINGDSR GSODGNSD", balanceForBaseUrl, amount);
|
|
357
413
|
if (balanceForBaseUrl > amount) {
|
|
358
414
|
const units = this.walletAdapter.getMintUnits();
|
|
359
415
|
const unit = units[mintUrl] || "sat";
|
|
@@ -371,7 +427,7 @@ var CashuSpender = class {
|
|
|
371
427
|
baseUrl,
|
|
372
428
|
amount: topUpAmount
|
|
373
429
|
});
|
|
374
|
-
|
|
430
|
+
this._log("DEBUG", "TOPUP ", topUpResult);
|
|
375
431
|
if (topUpResult.success && topUpResult.toppedUpAmount) {
|
|
376
432
|
const newBalance = balanceForBaseUrl + topUpResult.toppedUpAmount;
|
|
377
433
|
const units = this.walletAdapter.getMintUnits();
|
|
@@ -393,7 +449,7 @@ var CashuSpender = class {
|
|
|
393
449
|
baseUrl,
|
|
394
450
|
storedToken
|
|
395
451
|
);
|
|
396
|
-
|
|
452
|
+
this._log("DEBUG", providerBalance);
|
|
397
453
|
if (providerBalance <= 0) {
|
|
398
454
|
this.storageAdapter.removeToken(baseUrl);
|
|
399
455
|
}
|
|
@@ -412,7 +468,7 @@ var CashuSpender = class {
|
|
|
412
468
|
const refundResults = await Promise.allSettled(
|
|
413
469
|
toRefund.map(async (pending) => {
|
|
414
470
|
const token = this.storageAdapter.getToken(pending.baseUrl);
|
|
415
|
-
|
|
471
|
+
this._log("DEBUG", token, this.balanceManager);
|
|
416
472
|
if (!token || !this.balanceManager) {
|
|
417
473
|
return { baseUrl: pending.baseUrl, success: false };
|
|
418
474
|
}
|
|
@@ -428,7 +484,7 @@ var CashuSpender = class {
|
|
|
428
484
|
baseUrl: pending.baseUrl,
|
|
429
485
|
token
|
|
430
486
|
});
|
|
431
|
-
|
|
487
|
+
this._log("DEBUG", result);
|
|
432
488
|
if (result.success) {
|
|
433
489
|
this.storageAdapter.removeToken(pending.baseUrl);
|
|
434
490
|
}
|
|
@@ -526,11 +582,22 @@ var CashuSpender = class {
|
|
|
526
582
|
|
|
527
583
|
// wallet/BalanceManager.ts
|
|
528
584
|
var BalanceManager = class {
|
|
529
|
-
constructor(walletAdapter, storageAdapter, providerRegistry) {
|
|
585
|
+
constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender) {
|
|
530
586
|
this.walletAdapter = walletAdapter;
|
|
531
587
|
this.storageAdapter = storageAdapter;
|
|
532
588
|
this.providerRegistry = providerRegistry;
|
|
589
|
+
if (cashuSpender) {
|
|
590
|
+
this.cashuSpender = cashuSpender;
|
|
591
|
+
} else {
|
|
592
|
+
this.cashuSpender = new CashuSpender(
|
|
593
|
+
walletAdapter,
|
|
594
|
+
storageAdapter,
|
|
595
|
+
providerRegistry,
|
|
596
|
+
this
|
|
597
|
+
);
|
|
598
|
+
}
|
|
533
599
|
}
|
|
600
|
+
cashuSpender;
|
|
534
601
|
/**
|
|
535
602
|
* Unified refund - handles both NIP-60 and legacy wallet refunds
|
|
536
603
|
*/
|
|
@@ -565,7 +632,7 @@ var BalanceManager = class {
|
|
|
565
632
|
this.storageAdapter.removeToken(baseUrl);
|
|
566
633
|
return { success: true, message: "No balance to refund" };
|
|
567
634
|
}
|
|
568
|
-
const receiveResult = await this.
|
|
635
|
+
const receiveResult = await this.cashuSpender.receiveToken(
|
|
569
636
|
fetchResult.token
|
|
570
637
|
);
|
|
571
638
|
const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
|
|
@@ -610,7 +677,7 @@ var BalanceManager = class {
|
|
|
610
677
|
if (fetchResult.error === "No balance to refund") {
|
|
611
678
|
return { success: false, message: "No balance to refund" };
|
|
612
679
|
}
|
|
613
|
-
const receiveResult = await this.
|
|
680
|
+
const receiveResult = await this.cashuSpender.receiveToken(
|
|
614
681
|
fetchResult.token
|
|
615
682
|
);
|
|
616
683
|
const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
|
|
@@ -1051,7 +1118,7 @@ var BalanceManager = class {
|
|
|
1051
1118
|
*/
|
|
1052
1119
|
async _recoverFailedTopUp(cashuToken) {
|
|
1053
1120
|
try {
|
|
1054
|
-
await this.
|
|
1121
|
+
await this.cashuSpender.receiveToken(cashuToken);
|
|
1055
1122
|
} catch (error) {
|
|
1056
1123
|
console.error(
|
|
1057
1124
|
"[BalanceManager._recoverFailedTopUp] Failed to recover token",
|
|
@@ -1722,12 +1789,39 @@ var RoutstrClient = class {
|
|
|
1722
1789
|
providerManager;
|
|
1723
1790
|
alertLevel;
|
|
1724
1791
|
mode;
|
|
1792
|
+
debugLevel = "WARN";
|
|
1725
1793
|
/**
|
|
1726
1794
|
* Get the current client mode
|
|
1727
1795
|
*/
|
|
1728
1796
|
getMode() {
|
|
1729
1797
|
return this.mode;
|
|
1730
1798
|
}
|
|
1799
|
+
getDebugLevel() {
|
|
1800
|
+
return this.debugLevel;
|
|
1801
|
+
}
|
|
1802
|
+
setDebugLevel(level) {
|
|
1803
|
+
this.debugLevel = level;
|
|
1804
|
+
}
|
|
1805
|
+
_log(level, ...args) {
|
|
1806
|
+
const levelPriority = {
|
|
1807
|
+
DEBUG: 0,
|
|
1808
|
+
WARN: 1,
|
|
1809
|
+
ERROR: 2
|
|
1810
|
+
};
|
|
1811
|
+
if (levelPriority[level] >= levelPriority[this.debugLevel]) {
|
|
1812
|
+
switch (level) {
|
|
1813
|
+
case "DEBUG":
|
|
1814
|
+
console.log(...args);
|
|
1815
|
+
break;
|
|
1816
|
+
case "WARN":
|
|
1817
|
+
console.warn(...args);
|
|
1818
|
+
break;
|
|
1819
|
+
case "ERROR":
|
|
1820
|
+
console.error(...args);
|
|
1821
|
+
break;
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1731
1825
|
/**
|
|
1732
1826
|
* Get the CashuSpender instance
|
|
1733
1827
|
*/
|
|
@@ -1791,7 +1885,7 @@ var RoutstrClient = class {
|
|
|
1791
1885
|
amount: requiredSats,
|
|
1792
1886
|
baseUrl
|
|
1793
1887
|
});
|
|
1794
|
-
|
|
1888
|
+
this._log("DEBUG", token, baseUrl);
|
|
1795
1889
|
let requestBody = body;
|
|
1796
1890
|
if (body && typeof body === "object") {
|
|
1797
1891
|
const bodyObj = body;
|
|
@@ -1815,8 +1909,9 @@ var RoutstrClient = class {
|
|
|
1815
1909
|
});
|
|
1816
1910
|
const tokenBalanceInSats = tokenBalanceUnit === "msat" ? tokenBalance / 1e3 : tokenBalance;
|
|
1817
1911
|
const baseUrlUsed = response.baseUrl || baseUrl;
|
|
1912
|
+
const tokenUsed = response.token || token;
|
|
1818
1913
|
await this._handlePostResponseBalanceUpdate({
|
|
1819
|
-
token,
|
|
1914
|
+
token: tokenUsed,
|
|
1820
1915
|
baseUrl: baseUrlUsed,
|
|
1821
1916
|
initialTokenBalance: tokenBalanceInSats,
|
|
1822
1917
|
response
|
|
@@ -1952,22 +2047,30 @@ var RoutstrClient = class {
|
|
|
1952
2047
|
const { path, method, body, baseUrl, token, headers } = params;
|
|
1953
2048
|
try {
|
|
1954
2049
|
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
1955
|
-
if (this.mode === "xcashu")
|
|
2050
|
+
if (this.mode === "xcashu") this._log("DEBUG", "HEADERS,", headers);
|
|
1956
2051
|
const response = await fetch(url, {
|
|
1957
2052
|
method,
|
|
1958
2053
|
headers,
|
|
1959
2054
|
body: body === void 0 || method === "GET" ? void 0 : JSON.stringify(body)
|
|
1960
2055
|
});
|
|
1961
|
-
if (this.mode === "xcashu")
|
|
2056
|
+
if (this.mode === "xcashu") this._log("DEBUG", "response,", response);
|
|
1962
2057
|
response.baseUrl = baseUrl;
|
|
2058
|
+
response.token = token;
|
|
1963
2059
|
if (!response.ok) {
|
|
1964
2060
|
const requestId = response.headers.get("x-routstr-request-id") || void 0;
|
|
2061
|
+
let bodyText;
|
|
2062
|
+
try {
|
|
2063
|
+
bodyText = await response.text();
|
|
2064
|
+
} catch (e) {
|
|
2065
|
+
bodyText = void 0;
|
|
2066
|
+
}
|
|
1965
2067
|
return await this._handleErrorResponse(
|
|
1966
2068
|
params,
|
|
1967
2069
|
token,
|
|
1968
2070
|
response.status,
|
|
1969
2071
|
requestId,
|
|
1970
|
-
this.mode === "xcashu" ? response.headers.get("x-cashu") ?? void 0 : void 0
|
|
2072
|
+
this.mode === "xcashu" ? response.headers.get("x-cashu") ?? void 0 : void 0,
|
|
2073
|
+
bodyText
|
|
1971
2074
|
);
|
|
1972
2075
|
}
|
|
1973
2076
|
return response;
|
|
@@ -1986,41 +2089,47 @@ var RoutstrClient = class {
|
|
|
1986
2089
|
/**
|
|
1987
2090
|
* Handle error responses with failover
|
|
1988
2091
|
*/
|
|
1989
|
-
async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken) {
|
|
2092
|
+
async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken, responseBody) {
|
|
1990
2093
|
const { path, method, body, selectedModel, baseUrl, mintUrl } = params;
|
|
1991
2094
|
let tryNextProvider = false;
|
|
1992
|
-
|
|
2095
|
+
this._log(
|
|
2096
|
+
"DEBUG",
|
|
1993
2097
|
`[RoutstrClient] _handleErrorResponse: status=${status}, baseUrl=${baseUrl}, mode=${this.mode}, token preview=${token}, requestId=${requestId}`
|
|
1994
2098
|
);
|
|
1995
|
-
|
|
2099
|
+
this._log(
|
|
2100
|
+
"DEBUG",
|
|
1996
2101
|
`[RoutstrClient] _handleErrorResponse: Attempting to receive/restore token for ${baseUrl}`
|
|
1997
2102
|
);
|
|
1998
2103
|
if (params.token.startsWith("cashu")) {
|
|
1999
|
-
const tryReceiveTokenResult = await this.
|
|
2104
|
+
const tryReceiveTokenResult = await this.cashuSpender.receiveToken(
|
|
2000
2105
|
params.token
|
|
2001
2106
|
);
|
|
2002
2107
|
if (tryReceiveTokenResult.success) {
|
|
2003
|
-
|
|
2108
|
+
this._log(
|
|
2109
|
+
"DEBUG",
|
|
2004
2110
|
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${tryReceiveTokenResult.amount}`
|
|
2005
2111
|
);
|
|
2006
2112
|
tryNextProvider = true;
|
|
2007
2113
|
if (this.mode === "lazyrefund")
|
|
2008
2114
|
this.storageAdapter.removeToken(baseUrl);
|
|
2009
2115
|
} else {
|
|
2010
|
-
|
|
2011
|
-
|
|
2116
|
+
this._log(
|
|
2117
|
+
"DEBUG",
|
|
2118
|
+
`[RoutstrClient] _handleErrorResponse: Failed to receive token. `
|
|
2012
2119
|
);
|
|
2013
2120
|
}
|
|
2014
2121
|
}
|
|
2015
2122
|
if (this.mode === "xcashu") {
|
|
2016
2123
|
if (xCashuRefundToken) {
|
|
2017
|
-
|
|
2124
|
+
this._log(
|
|
2125
|
+
"DEBUG",
|
|
2018
2126
|
`[RoutstrClient] _handleErrorResponse: Attempting to receive xcashu refund token, preview=${xCashuRefundToken.substring(0, 20)}...`
|
|
2019
2127
|
);
|
|
2020
2128
|
try {
|
|
2021
|
-
const receiveResult = await this.
|
|
2129
|
+
const receiveResult = await this.cashuSpender.receiveToken(xCashuRefundToken);
|
|
2022
2130
|
if (receiveResult.success) {
|
|
2023
|
-
|
|
2131
|
+
this._log(
|
|
2132
|
+
"DEBUG",
|
|
2024
2133
|
`[RoutstrClient] _handleErrorResponse: xcashu refund received, amount=${receiveResult.amount}`
|
|
2025
2134
|
);
|
|
2026
2135
|
tryNextProvider = true;
|
|
@@ -2032,7 +2141,7 @@ var RoutstrClient = class {
|
|
|
2032
2141
|
requestId
|
|
2033
2142
|
);
|
|
2034
2143
|
} catch (error) {
|
|
2035
|
-
|
|
2144
|
+
this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
|
|
2036
2145
|
throw new ProviderError(
|
|
2037
2146
|
baseUrl,
|
|
2038
2147
|
status,
|
|
@@ -2050,14 +2159,15 @@ var RoutstrClient = class {
|
|
|
2050
2159
|
);
|
|
2051
2160
|
}
|
|
2052
2161
|
}
|
|
2053
|
-
if (status === 402 && !tryNextProvider && (this.mode === "apikeys" || this.mode === "lazyrefund")) {
|
|
2162
|
+
if ((status === 402 || status === 413 && responseBody?.includes("Insufficient balance")) && !tryNextProvider && (this.mode === "apikeys" || this.mode === "lazyrefund")) {
|
|
2054
2163
|
const topupResult = await this.balanceManager.topUp({
|
|
2055
2164
|
mintUrl,
|
|
2056
2165
|
baseUrl,
|
|
2057
2166
|
amount: params.requiredSats * TOPUP_MARGIN,
|
|
2058
2167
|
token: params.token
|
|
2059
2168
|
});
|
|
2060
|
-
|
|
2169
|
+
this._log(
|
|
2170
|
+
"DEBUG",
|
|
2061
2171
|
`[RoutstrClient] _handleErrorResponse: Topup result for ${baseUrl}: success=${topupResult.success}, message=${topupResult.message}`
|
|
2062
2172
|
);
|
|
2063
2173
|
if (!topupResult.success) {
|
|
@@ -2067,18 +2177,21 @@ var RoutstrClient = class {
|
|
|
2067
2177
|
const haveMatch = message.match(/have (\d+)/);
|
|
2068
2178
|
const required = needMatch ? parseInt(needMatch[1], 10) : params.requiredSats;
|
|
2069
2179
|
const available = haveMatch ? parseInt(haveMatch[1], 10) : 0;
|
|
2070
|
-
|
|
2180
|
+
this._log(
|
|
2181
|
+
"DEBUG",
|
|
2071
2182
|
`[RoutstrClient] _handleErrorResponse: Insufficient balance, need=${required}, have=${available}`
|
|
2072
2183
|
);
|
|
2073
2184
|
throw new InsufficientBalanceError(required, available);
|
|
2074
2185
|
} else {
|
|
2075
|
-
|
|
2186
|
+
this._log(
|
|
2187
|
+
"DEBUG",
|
|
2076
2188
|
`[RoutstrClient] _handleErrorResponse: Topup failed with non-insufficient-balance error, will try next provider`
|
|
2077
2189
|
);
|
|
2078
2190
|
tryNextProvider = true;
|
|
2079
2191
|
}
|
|
2080
2192
|
} else {
|
|
2081
|
-
|
|
2193
|
+
this._log(
|
|
2194
|
+
"DEBUG",
|
|
2082
2195
|
`[RoutstrClient] _handleErrorResponse: Topup successful, will retry with new token`
|
|
2083
2196
|
);
|
|
2084
2197
|
}
|
|
@@ -2089,8 +2202,9 @@ var RoutstrClient = class {
|
|
|
2089
2202
|
headers: this._withAuthHeader(params.baseHeaders, params.token)
|
|
2090
2203
|
});
|
|
2091
2204
|
}
|
|
2092
|
-
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 521) && !tryNextProvider) {
|
|
2093
|
-
|
|
2205
|
+
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
2206
|
+
this._log(
|
|
2207
|
+
"DEBUG",
|
|
2094
2208
|
`[RoutstrClient] _handleErrorResponse: Status ${status} (auth/server error), attempting refund for ${baseUrl}, mode=${this.mode}`
|
|
2095
2209
|
);
|
|
2096
2210
|
if (this.mode === "lazyrefund") {
|
|
@@ -2100,7 +2214,8 @@ var RoutstrClient = class {
|
|
|
2100
2214
|
baseUrl,
|
|
2101
2215
|
token: params.token
|
|
2102
2216
|
});
|
|
2103
|
-
|
|
2217
|
+
this._log(
|
|
2218
|
+
"DEBUG",
|
|
2104
2219
|
`[RoutstrClient] _handleErrorResponse: Lazyrefund result: success=${refundResult.success}`
|
|
2105
2220
|
);
|
|
2106
2221
|
if (refundResult.success) this.storageAdapter.removeToken(baseUrl);
|
|
@@ -2120,14 +2235,16 @@ var RoutstrClient = class {
|
|
|
2120
2235
|
);
|
|
2121
2236
|
}
|
|
2122
2237
|
} else if (this.mode === "apikeys") {
|
|
2123
|
-
|
|
2238
|
+
this._log(
|
|
2239
|
+
"DEBUG",
|
|
2124
2240
|
`[RoutstrClient] _handleErrorResponse: Attempting API key refund for ${baseUrl}, key preview=${token}`
|
|
2125
2241
|
);
|
|
2126
2242
|
const initialBalance = await this.balanceManager.getTokenBalance(
|
|
2127
2243
|
token,
|
|
2128
2244
|
baseUrl
|
|
2129
2245
|
);
|
|
2130
|
-
|
|
2246
|
+
this._log(
|
|
2247
|
+
"DEBUG",
|
|
2131
2248
|
`[RoutstrClient] _handleErrorResponse: Initial API key balance: ${initialBalance.amount}`
|
|
2132
2249
|
);
|
|
2133
2250
|
const refundResult = await this.balanceManager.refundApiKey({
|
|
@@ -2135,7 +2252,8 @@ var RoutstrClient = class {
|
|
|
2135
2252
|
baseUrl,
|
|
2136
2253
|
apiKey: token
|
|
2137
2254
|
});
|
|
2138
|
-
|
|
2255
|
+
this._log(
|
|
2256
|
+
"DEBUG",
|
|
2139
2257
|
`[RoutstrClient] _handleErrorResponse: API key refund result: success=${refundResult.success}, message=${refundResult.message}`
|
|
2140
2258
|
);
|
|
2141
2259
|
if (!refundResult.success && initialBalance.amount > 0) {
|
|
@@ -2150,7 +2268,8 @@ var RoutstrClient = class {
|
|
|
2150
2268
|
}
|
|
2151
2269
|
}
|
|
2152
2270
|
this.providerManager.markFailed(baseUrl);
|
|
2153
|
-
|
|
2271
|
+
this._log(
|
|
2272
|
+
"DEBUG",
|
|
2154
2273
|
`[RoutstrClient] _handleErrorResponse: Marked provider ${baseUrl} as failed`
|
|
2155
2274
|
);
|
|
2156
2275
|
if (!selectedModel) {
|
|
@@ -2165,7 +2284,8 @@ var RoutstrClient = class {
|
|
|
2165
2284
|
baseUrl
|
|
2166
2285
|
);
|
|
2167
2286
|
if (nextProvider) {
|
|
2168
|
-
|
|
2287
|
+
this._log(
|
|
2288
|
+
"DEBUG",
|
|
2169
2289
|
`[RoutstrClient] _handleErrorResponse: Failing over to next provider: ${nextProvider}, model: ${selectedModel.id}`
|
|
2170
2290
|
);
|
|
2171
2291
|
const newModel = await this.providerManager.getModelForProvider(
|
|
@@ -2180,7 +2300,8 @@ var RoutstrClient = class {
|
|
|
2180
2300
|
messagesForPricing,
|
|
2181
2301
|
params.maxTokens
|
|
2182
2302
|
);
|
|
2183
|
-
|
|
2303
|
+
this._log(
|
|
2304
|
+
"DEBUG",
|
|
2184
2305
|
`[RoutstrClient] _handleErrorResponse: Creating new token for failover provider ${nextProvider}, required sats: ${newRequiredSats}`
|
|
2185
2306
|
);
|
|
2186
2307
|
const spendResult = await this._spendToken({
|
|
@@ -2212,10 +2333,10 @@ var RoutstrClient = class {
|
|
|
2212
2333
|
const refundToken = response.headers.get("x-cashu") ?? void 0;
|
|
2213
2334
|
if (refundToken) {
|
|
2214
2335
|
try {
|
|
2215
|
-
const receiveResult = await this.
|
|
2336
|
+
const receiveResult = await this.cashuSpender.receiveToken(refundToken);
|
|
2216
2337
|
satsSpent = initialTokenBalance - receiveResult.amount * (receiveResult.unit == "sat" ? 1 : 1e3);
|
|
2217
2338
|
} catch (error) {
|
|
2218
|
-
|
|
2339
|
+
this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
|
|
2219
2340
|
}
|
|
2220
2341
|
}
|
|
2221
2342
|
} else if (this.mode === "lazyrefund") {
|
|
@@ -2232,7 +2353,8 @@ var RoutstrClient = class {
|
|
|
2232
2353
|
token,
|
|
2233
2354
|
baseUrl
|
|
2234
2355
|
);
|
|
2235
|
-
|
|
2356
|
+
this._log(
|
|
2357
|
+
"DEBUG",
|
|
2236
2358
|
"LATEST Balance",
|
|
2237
2359
|
latestBalanceInfo.amount,
|
|
2238
2360
|
latestBalanceInfo.reserved,
|
|
@@ -2244,7 +2366,7 @@ var RoutstrClient = class {
|
|
|
2244
2366
|
this.storageAdapter.updateApiKeyBalance(baseUrl, latestTokenBalance);
|
|
2245
2367
|
satsSpent = initialTokenBalance - latestTokenBalance;
|
|
2246
2368
|
} catch (e) {
|
|
2247
|
-
|
|
2369
|
+
this._log("WARN", "Could not get updated API key balance:", e);
|
|
2248
2370
|
satsSpent = fallbackSatsSpent ?? initialTokenBalance;
|
|
2249
2371
|
}
|
|
2250
2372
|
}
|
|
@@ -2355,11 +2477,12 @@ var RoutstrClient = class {
|
|
|
2355
2477
|
* Handle errors and notify callbacks
|
|
2356
2478
|
*/
|
|
2357
2479
|
_handleError(error, callbacks) {
|
|
2358
|
-
|
|
2480
|
+
this._log("ERROR", "[RoutstrClient] _handleError: Error occurred", error);
|
|
2359
2481
|
if (error instanceof Error) {
|
|
2360
2482
|
const isStreamError = error.message.includes("Error in input stream") || error.message.includes("Load failed");
|
|
2361
2483
|
const modifiedErrorMsg = isStreamError ? "AI stream was cut off, turn on Keep Active or please try again" : error.message;
|
|
2362
|
-
|
|
2484
|
+
this._log(
|
|
2485
|
+
"ERROR",
|
|
2363
2486
|
`[RoutstrClient] _handleError: Error type=${error.constructor.name}, message=${modifiedErrorMsg}, isStreamError=${isStreamError}`
|
|
2364
2487
|
);
|
|
2365
2488
|
callbacks.onMessageAppend({
|
|
@@ -2388,13 +2511,15 @@ var RoutstrClient = class {
|
|
|
2388
2511
|
*/
|
|
2389
2512
|
async _spendToken(params) {
|
|
2390
2513
|
const { mintUrl, amount, baseUrl } = params;
|
|
2391
|
-
|
|
2514
|
+
this._log(
|
|
2515
|
+
"DEBUG",
|
|
2392
2516
|
`[RoutstrClient] _spendToken: mode=${this.mode}, amount=${amount}, baseUrl=${baseUrl}, mintUrl=${mintUrl}`
|
|
2393
2517
|
);
|
|
2394
2518
|
if (this.mode === "apikeys") {
|
|
2395
2519
|
let parentApiKey = this.storageAdapter.getApiKey(baseUrl);
|
|
2396
2520
|
if (!parentApiKey) {
|
|
2397
|
-
|
|
2521
|
+
this._log(
|
|
2522
|
+
"DEBUG",
|
|
2398
2523
|
`[RoutstrClient] _spendToken: No existing API key for ${baseUrl}, creating new one via Cashu`
|
|
2399
2524
|
);
|
|
2400
2525
|
const spendResult2 = await this.cashuSpender.spend({
|
|
@@ -2404,7 +2529,8 @@ var RoutstrClient = class {
|
|
|
2404
2529
|
reuseToken: false
|
|
2405
2530
|
});
|
|
2406
2531
|
if (!spendResult2.token) {
|
|
2407
|
-
|
|
2532
|
+
this._log(
|
|
2533
|
+
"ERROR",
|
|
2408
2534
|
`[RoutstrClient] _spendToken: Failed to create Cashu token for API key creation, error:`,
|
|
2409
2535
|
spendResult2.error
|
|
2410
2536
|
);
|
|
@@ -2412,30 +2538,35 @@ var RoutstrClient = class {
|
|
|
2412
2538
|
`[RoutstrClient] _spendToken: Failed to create Cashu token for API key creation, error: ${spendResult2.error}`
|
|
2413
2539
|
);
|
|
2414
2540
|
} else {
|
|
2415
|
-
|
|
2541
|
+
this._log(
|
|
2542
|
+
"DEBUG",
|
|
2416
2543
|
`[RoutstrClient] _spendToken: Cashu token created, token preview: ${spendResult2.token}`
|
|
2417
2544
|
);
|
|
2418
2545
|
}
|
|
2419
|
-
|
|
2546
|
+
this._log(
|
|
2547
|
+
"DEBUG",
|
|
2420
2548
|
`[RoutstrClient] _spendToken: Created API key for ${baseUrl}, key preview: ${spendResult2.token}, balance: ${spendResult2.balance}`
|
|
2421
2549
|
);
|
|
2422
2550
|
try {
|
|
2423
2551
|
this.storageAdapter.setApiKey(baseUrl, spendResult2.token);
|
|
2424
2552
|
} catch (error) {
|
|
2425
2553
|
if (error instanceof Error && error.message.includes("ApiKey already exists")) {
|
|
2426
|
-
const tryReceiveTokenResult = await this.
|
|
2554
|
+
const tryReceiveTokenResult = await this.cashuSpender.receiveToken(
|
|
2427
2555
|
spendResult2.token
|
|
2428
2556
|
);
|
|
2429
2557
|
if (tryReceiveTokenResult.success) {
|
|
2430
|
-
|
|
2558
|
+
this._log(
|
|
2559
|
+
"DEBUG",
|
|
2431
2560
|
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${tryReceiveTokenResult.amount}`
|
|
2432
2561
|
);
|
|
2433
2562
|
} else {
|
|
2434
|
-
|
|
2563
|
+
this._log(
|
|
2564
|
+
"DEBUG",
|
|
2435
2565
|
`[RoutstrClient] _handleErrorResponse: Token restore failed or not needed`
|
|
2436
2566
|
);
|
|
2437
2567
|
}
|
|
2438
|
-
|
|
2568
|
+
this._log(
|
|
2569
|
+
"DEBUG",
|
|
2439
2570
|
`[RoutstrClient] _spendToken: API key already exists for ${baseUrl}, using existing key`
|
|
2440
2571
|
);
|
|
2441
2572
|
} else {
|
|
@@ -2444,7 +2575,8 @@ var RoutstrClient = class {
|
|
|
2444
2575
|
}
|
|
2445
2576
|
parentApiKey = this.storageAdapter.getApiKey(baseUrl);
|
|
2446
2577
|
} else {
|
|
2447
|
-
|
|
2578
|
+
this._log(
|
|
2579
|
+
"DEBUG",
|
|
2448
2580
|
`[RoutstrClient] _spendToken: Using existing API key for ${baseUrl}, key preview: ${parentApiKey.key}`
|
|
2449
2581
|
);
|
|
2450
2582
|
}
|
|
@@ -2466,10 +2598,11 @@ var RoutstrClient = class {
|
|
|
2466
2598
|
tokenBalance = balanceInfo.amount;
|
|
2467
2599
|
tokenBalanceUnit = balanceInfo.unit;
|
|
2468
2600
|
} catch (e) {
|
|
2469
|
-
|
|
2601
|
+
this._log("WARN", "Could not get initial API key balance:", e);
|
|
2470
2602
|
}
|
|
2471
2603
|
}
|
|
2472
|
-
|
|
2604
|
+
this._log(
|
|
2605
|
+
"DEBUG",
|
|
2473
2606
|
`[RoutstrClient] _spendToken: Returning token with balance=${tokenBalance} ${tokenBalanceUnit}`
|
|
2474
2607
|
);
|
|
2475
2608
|
return {
|
|
@@ -2478,7 +2611,8 @@ var RoutstrClient = class {
|
|
|
2478
2611
|
tokenBalanceUnit
|
|
2479
2612
|
};
|
|
2480
2613
|
}
|
|
2481
|
-
|
|
2614
|
+
this._log(
|
|
2615
|
+
"DEBUG",
|
|
2482
2616
|
`[RoutstrClient] _spendToken: Calling CashuSpender.spend for amount=${amount}, mintUrl=${mintUrl}, mode=${this.mode}`
|
|
2483
2617
|
);
|
|
2484
2618
|
const spendResult = await this.cashuSpender.spend({
|
|
@@ -2488,12 +2622,14 @@ var RoutstrClient = class {
|
|
|
2488
2622
|
reuseToken: this.mode === "lazyrefund"
|
|
2489
2623
|
});
|
|
2490
2624
|
if (!spendResult.token) {
|
|
2491
|
-
|
|
2625
|
+
this._log(
|
|
2626
|
+
"ERROR",
|
|
2492
2627
|
`[RoutstrClient] _spendToken: CashuSpender.spend failed, error:`,
|
|
2493
2628
|
spendResult.error
|
|
2494
2629
|
);
|
|
2495
2630
|
} else {
|
|
2496
|
-
|
|
2631
|
+
this._log(
|
|
2632
|
+
"DEBUG",
|
|
2497
2633
|
`[RoutstrClient] _spendToken: Cashu token created, token preview: ${spendResult.token}, balance: ${spendResult.balance} ${spendResult.unit ?? "sat"}`
|
|
2498
2634
|
);
|
|
2499
2635
|
}
|