@routstr/sdk 0.3.3 → 0.3.5
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 +9 -5
- package/dist/client/index.d.ts +9 -5
- package/dist/client/index.js +107 -136
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +107 -136
- package/dist/client/index.mjs.map +1 -1
- package/dist/discovery/index.d.mts +8 -2
- package/dist/discovery/index.d.ts +8 -2
- package/dist/discovery/index.js +27 -16
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +27 -16
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/index.d.mts +10 -8
- package/dist/index.d.ts +10 -8
- package/dist/index.js +179 -193
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +178 -194
- package/dist/index.mjs.map +1 -1
- package/dist/{interfaces-C5fLD3jB.d.mts → interfaces-Bp0Ngmqv.d.mts} +1 -1
- package/dist/{interfaces-BxDEka72.d.ts → interfaces-CIfd_phZ.d.ts} +1 -1
- package/dist/{interfaces-BWJJTCXO.d.mts → interfaces-Cxi8R4TT.d.mts} +1 -1
- package/dist/{interfaces-B62Rw-dd.d.ts → interfaces-D2FDCLyP.d.ts} +1 -1
- package/dist/storage/index.d.mts +9 -7
- package/dist/storage/index.d.ts +9 -7
- package/dist/storage/index.js +52 -37
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +52 -37
- package/dist/storage/index.mjs.map +1 -1
- package/dist/{store-h7m23ffq.d.ts → store-BD5zF9Hp.d.ts} +4 -4
- package/dist/{store-DGeLPv9E.d.mts → store-CBSyK2qg.d.mts} +4 -4
- package/dist/{types-BYj_8c5c.d.mts → types-DPQM6tIG.d.mts} +10 -1
- package/dist/{types-BYj_8c5c.d.ts → types-DPQM6tIG.d.ts} +10 -1
- package/dist/wallet/index.d.mts +8 -6
- package/dist/wallet/index.d.ts +8 -6
- package/dist/wallet/index.js +80 -57
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +80 -57
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/wallet/index.mjs
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { getDecodedToken } from '@cashu/cashu-ts';
|
|
2
2
|
|
|
3
|
+
// core/types.ts
|
|
4
|
+
function makeConsoleLogger(prefix) {
|
|
5
|
+
const fmt = (args) => prefix ? [prefix, ...args] : args;
|
|
6
|
+
return {
|
|
7
|
+
log: (...args) => console.log(...fmt(args)),
|
|
8
|
+
warn: (...args) => console.warn(...fmt(args)),
|
|
9
|
+
error: (...args) => console.error(...fmt(args)),
|
|
10
|
+
debug: (...args) => console.log(...fmt(args)),
|
|
11
|
+
child: (p) => makeConsoleLogger(prefix ? `${prefix}:${p}` : p)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
var consoleLogger = makeConsoleLogger();
|
|
15
|
+
|
|
3
16
|
// core/errors.ts
|
|
4
17
|
var InsufficientBalanceError = class extends Error {
|
|
5
18
|
constructor(required, available, maxMintBalance = 0, maxMintUrl = "", customMessage) {
|
|
@@ -78,14 +91,16 @@ function selectMintWithBalance(balances, units, amount, excludeMints = []) {
|
|
|
78
91
|
return { selectedMintUrl: null, selectedMintBalance: 0 };
|
|
79
92
|
}
|
|
80
93
|
var CashuSpender = class {
|
|
81
|
-
constructor(walletAdapter, storageAdapter, _providerRegistry, balanceManager) {
|
|
94
|
+
constructor(walletAdapter, storageAdapter, _providerRegistry, balanceManager, logger) {
|
|
82
95
|
this.walletAdapter = walletAdapter;
|
|
83
96
|
this.storageAdapter = storageAdapter;
|
|
84
97
|
this._providerRegistry = _providerRegistry;
|
|
85
98
|
this.balanceManager = balanceManager;
|
|
99
|
+
this.logger = (logger ?? consoleLogger).child("CashuSpender");
|
|
86
100
|
}
|
|
87
101
|
_isBusy = false;
|
|
88
102
|
debugLevel = "WARN";
|
|
103
|
+
logger;
|
|
89
104
|
async receiveToken(token) {
|
|
90
105
|
try {
|
|
91
106
|
const result = await this.walletAdapter.receiveToken(token);
|
|
@@ -181,13 +196,13 @@ var CashuSpender = class {
|
|
|
181
196
|
if (levelPriority[level] >= levelPriority[this.debugLevel]) {
|
|
182
197
|
switch (level) {
|
|
183
198
|
case "DEBUG":
|
|
184
|
-
|
|
199
|
+
this.logger.log(...args);
|
|
185
200
|
break;
|
|
186
201
|
case "WARN":
|
|
187
|
-
|
|
202
|
+
this.logger.warn(...args);
|
|
188
203
|
break;
|
|
189
204
|
case "ERROR":
|
|
190
|
-
|
|
205
|
+
this.logger.error(...args);
|
|
191
206
|
break;
|
|
192
207
|
}
|
|
193
208
|
}
|
|
@@ -535,19 +550,50 @@ var CashuSpender = class {
|
|
|
535
550
|
apiKeyEntry.baseUrl
|
|
536
551
|
);
|
|
537
552
|
if (apiKeyEntryFull && this.balanceManager) {
|
|
553
|
+
try {
|
|
554
|
+
const balanceResult = await this.balanceManager.getTokenBalance(
|
|
555
|
+
apiKeyEntryFull.key,
|
|
556
|
+
apiKeyEntry.baseUrl
|
|
557
|
+
);
|
|
558
|
+
if (balanceResult.isInvalidApiKey) {
|
|
559
|
+
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
560
|
+
results.push({
|
|
561
|
+
baseUrl: apiKeyEntry.baseUrl,
|
|
562
|
+
success: true
|
|
563
|
+
});
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
if (balanceResult.amount >= 0) {
|
|
567
|
+
const balanceSat = balanceResult.unit === "msat" ? Math.floor(balanceResult.amount / 1e3) : balanceResult.amount;
|
|
568
|
+
this.storageAdapter.updateApiKeyBalance(
|
|
569
|
+
apiKeyEntry.baseUrl,
|
|
570
|
+
balanceSat
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
} catch {
|
|
574
|
+
}
|
|
575
|
+
const refreshedEntry = this.storageAdapter.getApiKey(
|
|
576
|
+
apiKeyEntry.baseUrl
|
|
577
|
+
);
|
|
578
|
+
if (!refreshedEntry) continue;
|
|
538
579
|
const refundResult = await this.balanceManager.refundApiKey({
|
|
539
580
|
mintUrl,
|
|
540
581
|
baseUrl: apiKeyEntry.baseUrl,
|
|
541
|
-
apiKey:
|
|
582
|
+
apiKey: refreshedEntry.key,
|
|
542
583
|
forceRefund
|
|
543
584
|
});
|
|
544
585
|
if (refundResult.success) {
|
|
545
586
|
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
546
587
|
} else {
|
|
547
|
-
this.storageAdapter.
|
|
548
|
-
apiKeyEntry.baseUrl
|
|
549
|
-
apiKeyEntry.amount
|
|
588
|
+
const currentEntry = this.storageAdapter.getApiKey(
|
|
589
|
+
apiKeyEntry.baseUrl
|
|
550
590
|
);
|
|
591
|
+
if (currentEntry) {
|
|
592
|
+
this.storageAdapter.updateApiKeyBalance(
|
|
593
|
+
apiKeyEntry.baseUrl,
|
|
594
|
+
currentEntry.balance
|
|
595
|
+
);
|
|
596
|
+
}
|
|
551
597
|
}
|
|
552
598
|
results.push({
|
|
553
599
|
baseUrl: apiKeyEntry.baseUrl,
|
|
@@ -614,10 +660,11 @@ var CashuSpender = class {
|
|
|
614
660
|
|
|
615
661
|
// wallet/BalanceManager.ts
|
|
616
662
|
var BalanceManager = class _BalanceManager {
|
|
617
|
-
constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender) {
|
|
663
|
+
constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender, logger) {
|
|
618
664
|
this.walletAdapter = walletAdapter;
|
|
619
665
|
this.storageAdapter = storageAdapter;
|
|
620
666
|
this.providerRegistry = providerRegistry;
|
|
667
|
+
this.logger = (logger ?? consoleLogger).child("BalanceManager");
|
|
621
668
|
if (cashuSpender) {
|
|
622
669
|
this.cashuSpender = cashuSpender;
|
|
623
670
|
} else {
|
|
@@ -634,6 +681,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
634
681
|
providerWalletOps = /* @__PURE__ */ new Map();
|
|
635
682
|
/** Cooldown (ms) between opposite operations on the same provider */
|
|
636
683
|
static PROVIDER_WALLET_COOLDOWN_MS = 1e4;
|
|
684
|
+
logger;
|
|
637
685
|
/**
|
|
638
686
|
* Check whether a wallet operation (topup/refund) may run for a provider.
|
|
639
687
|
* Returns the reason when blocked.
|
|
@@ -708,7 +756,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
708
756
|
const { mintUrl, baseUrl, apiKey, forceRefund } = options;
|
|
709
757
|
const guard = this._canRunProviderWalletOperation(baseUrl, "refund");
|
|
710
758
|
if (!guard.allowed) {
|
|
711
|
-
|
|
759
|
+
this.logger.log(`Skipping refund for ${baseUrl} - ${guard.reason}`);
|
|
712
760
|
return { success: false, message: guard.reason };
|
|
713
761
|
}
|
|
714
762
|
this._beginProviderWalletOperation(baseUrl, "refund");
|
|
@@ -728,9 +776,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
728
776
|
if (apiKeyEntry?.lastUsed) {
|
|
729
777
|
const fiveMinutesAgo = Date.now() - 5 * 60 * 1e3;
|
|
730
778
|
if (apiKeyEntry.lastUsed > fiveMinutesAgo) {
|
|
731
|
-
|
|
732
|
-
`[BalanceManager] Skipping refund for ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1e3)}s ago`
|
|
733
|
-
);
|
|
779
|
+
this.logger.log(`Skipping refund for ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1e3)}s ago`);
|
|
734
780
|
return {
|
|
735
781
|
success: false,
|
|
736
782
|
message: "API key was used recently, skipping refund"
|
|
@@ -756,7 +802,8 @@ var BalanceManager = class _BalanceManager {
|
|
|
756
802
|
};
|
|
757
803
|
}
|
|
758
804
|
if (fetchResult.error === "No balance to refund") {
|
|
759
|
-
|
|
805
|
+
this.storageAdapter.removeApiKey(baseUrl);
|
|
806
|
+
return { success: true, message: "No balance to refund, key cleaned up" };
|
|
760
807
|
}
|
|
761
808
|
const receiveResult = await this.cashuSpender.receiveToken(
|
|
762
809
|
fetchResult.token
|
|
@@ -772,7 +819,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
772
819
|
requestId: fetchResult.requestId
|
|
773
820
|
};
|
|
774
821
|
} catch (error) {
|
|
775
|
-
|
|
822
|
+
this.logger.error("API key refund error", error);
|
|
776
823
|
return this._handleRefundError(error, mintUrl, fetchResult?.requestId);
|
|
777
824
|
}
|
|
778
825
|
}
|
|
@@ -824,7 +871,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
824
871
|
};
|
|
825
872
|
} catch (error) {
|
|
826
873
|
clearTimeout(timeoutId);
|
|
827
|
-
|
|
874
|
+
this.logger.error("fetchRefundToken fetch error", error);
|
|
828
875
|
if (error instanceof Error) {
|
|
829
876
|
if (error.name === "AbortError") {
|
|
830
877
|
return {
|
|
@@ -850,7 +897,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
850
897
|
const { mintUrl, baseUrl, amount, token: providedToken } = options;
|
|
851
898
|
const guard = this._canRunProviderWalletOperation(baseUrl, "topup");
|
|
852
899
|
if (!guard.allowed) {
|
|
853
|
-
|
|
900
|
+
this.logger.log(`Skipping topup for ${baseUrl} - ${guard.reason}`);
|
|
854
901
|
return { success: false, message: guard.reason };
|
|
855
902
|
}
|
|
856
903
|
this._beginProviderWalletOperation(baseUrl, "topup");
|
|
@@ -887,7 +934,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
887
934
|
cashuToken = tokenResult.token;
|
|
888
935
|
const topUpResult = await this._postTopUp(baseUrl, apiKey, cashuToken);
|
|
889
936
|
requestId = topUpResult.requestId;
|
|
890
|
-
|
|
937
|
+
this.logger.log("topUpResult:", topUpResult);
|
|
891
938
|
if (!topUpResult.success) {
|
|
892
939
|
await this._recoverFailedTopUp(cashuToken);
|
|
893
940
|
return {
|
|
@@ -903,10 +950,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
903
950
|
requestId
|
|
904
951
|
};
|
|
905
952
|
} catch (error) {
|
|
906
|
-
|
|
907
|
-
"DEBUG",
|
|
908
|
-
`[TopuPU] topup: Topup result for ${baseUrl}: error=${error}`
|
|
909
|
-
);
|
|
953
|
+
this.logger.log(`topup error for ${baseUrl}: ${error}`);
|
|
910
954
|
if (cashuToken) {
|
|
911
955
|
await this._recoverFailedTopUp(cashuToken);
|
|
912
956
|
}
|
|
@@ -923,13 +967,9 @@ var BalanceManager = class _BalanceManager {
|
|
|
923
967
|
p2pkPubkey
|
|
924
968
|
} = options;
|
|
925
969
|
const adjustedAmount = Math.ceil(amount);
|
|
926
|
-
|
|
927
|
-
`[BalanceManager.createProviderToken] Starting: baseUrl=${baseUrl}, mintUrl=${mintUrl}, amount=${amount}, adjustedAmount=${adjustedAmount}, retryCount=${retryCount}`
|
|
928
|
-
);
|
|
970
|
+
this.logger.log(`createProviderToken: baseUrl=${baseUrl} mintUrl=${mintUrl} amount=${amount} adjustedAmount=${adjustedAmount} retryCount=${retryCount}`);
|
|
929
971
|
if (!adjustedAmount || isNaN(adjustedAmount)) {
|
|
930
|
-
|
|
931
|
-
`[BalanceManager.createProviderToken] FAILURE: Invalid amount - amount=${amount}, adjustedAmount=${adjustedAmount}`
|
|
932
|
-
);
|
|
972
|
+
this.logger.error(`createProviderToken: invalid amount=${amount}`);
|
|
933
973
|
return { success: false, error: "Invalid top up amount" };
|
|
934
974
|
}
|
|
935
975
|
const balanceState = await this.getBalanceState();
|
|
@@ -960,9 +1000,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
960
1000
|
{ url: "", balance: 0 }
|
|
961
1001
|
).url
|
|
962
1002
|
);
|
|
963
|
-
|
|
964
|
-
`[BalanceManager.createProviderToken] FAILURE: Insufficient balance - required=${adjustedAmount}, available=${totalMintBalance + targetProviderBalance}, totalMintBalance=${totalMintBalance}, targetProviderBalance=${targetProviderBalance}, refundableProviderBalance=${refundableProviderBalance}`
|
|
965
|
-
);
|
|
1003
|
+
this.logger.error(`createProviderToken: insufficient balance required=${adjustedAmount} available=${totalMintBalance + targetProviderBalance} totalMint=${totalMintBalance} targetProvider=${targetProviderBalance}`);
|
|
966
1004
|
return { success: false, error: error.message };
|
|
967
1005
|
}
|
|
968
1006
|
const providerMints = baseUrl && this.providerRegistry ? this.providerRegistry.getProviderMints(baseUrl) : [];
|
|
@@ -998,9 +1036,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
998
1036
|
maxMintUrl = mintUrl2;
|
|
999
1037
|
}
|
|
1000
1038
|
}
|
|
1001
|
-
|
|
1002
|
-
`[BalanceManager.createProviderToken] FAILURE: No candidate mints found - requiredAmount=${requiredAmount}, totalMintBalance=${totalMintBalance}, maxBalance=${maxBalance}, maxMintUrl=${maxMintUrl}, providerMints=${JSON.stringify(providerMints)}`
|
|
1003
|
-
);
|
|
1039
|
+
this.logger.error(`createProviderToken: no candidate mints required=${requiredAmount} totalMint=${totalMintBalance} maxBalance=${maxBalance} maxMint=${maxMintUrl}`);
|
|
1004
1040
|
const error = new InsufficientBalanceError(
|
|
1005
1041
|
adjustedAmount,
|
|
1006
1042
|
totalMintBalance,
|
|
@@ -1012,17 +1048,13 @@ var BalanceManager = class _BalanceManager {
|
|
|
1012
1048
|
let lastError;
|
|
1013
1049
|
for (const candidateMint of candidates) {
|
|
1014
1050
|
try {
|
|
1015
|
-
|
|
1016
|
-
`[BalanceManager.createProviderToken] Attempting mint: ${candidateMint}, amount: ${requiredAmount}`
|
|
1017
|
-
);
|
|
1051
|
+
this.logger.log(`createProviderToken: attempting mint=${candidateMint} amount=${requiredAmount}`);
|
|
1018
1052
|
const token = await this.walletAdapter.sendToken(
|
|
1019
1053
|
candidateMint,
|
|
1020
1054
|
requiredAmount,
|
|
1021
1055
|
p2pkPubkey
|
|
1022
1056
|
);
|
|
1023
|
-
|
|
1024
|
-
`[BalanceManager.createProviderToken] SUCCESS: Token created from mint ${candidateMint}, all mint balances: ${JSON.stringify(Object.fromEntries(Object.entries(balances).map(([mint, balance]) => [mint, getBalanceInSats(balance, units[mint])])))}`
|
|
1025
|
-
);
|
|
1057
|
+
this.logger.log(`createProviderToken: success from mint=${candidateMint}`);
|
|
1026
1058
|
return {
|
|
1027
1059
|
success: true,
|
|
1028
1060
|
token,
|
|
@@ -1031,15 +1063,11 @@ var BalanceManager = class _BalanceManager {
|
|
|
1031
1063
|
};
|
|
1032
1064
|
} catch (error) {
|
|
1033
1065
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1034
|
-
|
|
1035
|
-
`[BalanceManager.createProviderToken] FAILURE: Mint ${candidateMint} failed with error: ${errorMsg}`
|
|
1036
|
-
);
|
|
1066
|
+
this.logger.error(`createProviderToken: mint=${candidateMint} failed: ${errorMsg}`);
|
|
1037
1067
|
if (error instanceof Error) {
|
|
1038
1068
|
lastError = errorMsg;
|
|
1039
1069
|
if (isNetworkErrorMessage(error.message)) {
|
|
1040
|
-
|
|
1041
|
-
`[BalanceManager.createProviderToken] Network error from ${candidateMint}, trying next mint...`
|
|
1042
|
-
);
|
|
1070
|
+
this.logger.warn(`createProviderToken: network error from ${candidateMint}, trying next mint...`);
|
|
1043
1071
|
continue;
|
|
1044
1072
|
}
|
|
1045
1073
|
}
|
|
@@ -1049,9 +1077,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1049
1077
|
};
|
|
1050
1078
|
}
|
|
1051
1079
|
}
|
|
1052
|
-
|
|
1053
|
-
`[BalanceManager.createProviderToken] FAILURE: All candidate mints exhausted - lastError=${lastError}, candidates=${JSON.stringify(candidates)}`
|
|
1054
|
-
);
|
|
1080
|
+
this.logger.error(`createProviderToken: all candidate mints exhausted lastError=${lastError}`);
|
|
1055
1081
|
return {
|
|
1056
1082
|
success: false,
|
|
1057
1083
|
error: lastError || "All candidate mints failed while creating top up token"
|
|
@@ -1166,7 +1192,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1166
1192
|
return { success: true, requestId };
|
|
1167
1193
|
} catch (error) {
|
|
1168
1194
|
clearTimeout(timeoutId);
|
|
1169
|
-
|
|
1195
|
+
this.logger.error("_postTopUp fetch error", error);
|
|
1170
1196
|
if (error instanceof Error) {
|
|
1171
1197
|
if (error.name === "AbortError") {
|
|
1172
1198
|
return {
|
|
@@ -1192,10 +1218,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1192
1218
|
try {
|
|
1193
1219
|
await this.cashuSpender.receiveToken(cashuToken);
|
|
1194
1220
|
} catch (error) {
|
|
1195
|
-
|
|
1196
|
-
"[BalanceManager._recoverFailedTopUp] Failed to recover token",
|
|
1197
|
-
error
|
|
1198
|
-
);
|
|
1221
|
+
this.logger.error("_recoverFailedTopUp: failed to recover token", error);
|
|
1199
1222
|
}
|
|
1200
1223
|
}
|
|
1201
1224
|
/**
|
|
@@ -1248,9 +1271,9 @@ var BalanceManager = class _BalanceManager {
|
|
|
1248
1271
|
apiKey: data.api_key
|
|
1249
1272
|
};
|
|
1250
1273
|
} else {
|
|
1251
|
-
|
|
1274
|
+
this.logger.warn(`getTokenBalance: status=${response.status}`);
|
|
1252
1275
|
const data = await response.json();
|
|
1253
|
-
|
|
1276
|
+
this.logger.warn("getTokenBalance: FAILED", data);
|
|
1254
1277
|
const isInvalidApiKey = response.status === 401 && data?.detail?.error?.code === "invalid_api_key" && data?.detail?.error?.message?.includes("proofs already spent");
|
|
1255
1278
|
return {
|
|
1256
1279
|
amount: -1,
|
|
@@ -1261,7 +1284,7 @@ var BalanceManager = class _BalanceManager {
|
|
|
1261
1284
|
};
|
|
1262
1285
|
}
|
|
1263
1286
|
} catch (error) {
|
|
1264
|
-
|
|
1287
|
+
this.logger.error("getTokenBalance error", error);
|
|
1265
1288
|
}
|
|
1266
1289
|
return { amount: -1, reserved: 0, unit: "sat", apiKey: "" };
|
|
1267
1290
|
}
|