@routstr/sdk 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,4 @@
1
1
  import { createStore } from 'zustand/vanilla';
2
- import { getDecodedToken } from '@cashu/cashu-ts';
3
-
4
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
- }) : x)(function(x) {
7
- if (typeof require !== "undefined") return require.apply(this, arguments);
8
- throw Error('Dynamic require of "' + x + '" is not supported');
9
- });
10
2
 
11
3
  // storage/drivers/localStorage.ts
12
4
  var canUseLocalStorage = () => {
@@ -120,38 +112,54 @@ var createMemoryDriver = (seed) => {
120
112
  var isBun = () => {
121
113
  return typeof process.versions.bun !== "undefined";
122
114
  };
123
- var createDatabase = (dbPath) => {
115
+ var cachedDbModule = null;
116
+ var loadDatabase = async (dbPath) => {
124
117
  if (isBun()) {
125
118
  throw new Error(
126
- "SQLite driver not supported in Bun. Use createMemoryDriver() instead."
119
+ "SQLite driver not supported in Bun. Use createBunSqliteDriver() instead."
127
120
  );
128
121
  }
129
- let Database = null;
130
122
  try {
131
- Database = __require("better-sqlite3");
123
+ if (!cachedDbModule) {
124
+ cachedDbModule = (await import('better-sqlite3')).default;
125
+ }
126
+ return new cachedDbModule(dbPath);
132
127
  } catch (error) {
133
128
  throw new Error(
134
129
  `better-sqlite3 is required for sqlite storage. Install it to use sqlite storage. (${error})`
135
130
  );
136
131
  }
137
- return new Database(dbPath);
138
132
  };
139
133
  var createSqliteDriver = (options = {}) => {
140
134
  const dbPath = options.dbPath || "routstr.sqlite";
141
135
  const tableName = options.tableName || "sdk_storage";
142
- const db = createDatabase(dbPath);
143
- db.exec(
144
- `CREATE TABLE IF NOT EXISTS ${tableName} (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
145
- );
146
- const selectStmt = db.prepare(`SELECT value FROM ${tableName} WHERE key = ?`);
147
- const upsertStmt = db.prepare(
148
- `INSERT INTO ${tableName} (key, value) VALUES (?, ?)
136
+ let db;
137
+ let selectStmt;
138
+ let upsertStmt;
139
+ let deleteStmt;
140
+ const initDb = async () => {
141
+ if (!db) {
142
+ db = await loadDatabase(dbPath);
143
+ db.exec(
144
+ `CREATE TABLE IF NOT EXISTS ${tableName} (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
145
+ );
146
+ selectStmt = db.prepare(`SELECT value FROM ${tableName} WHERE key = ?`);
147
+ upsertStmt = db.prepare(
148
+ `INSERT INTO ${tableName} (key, value) VALUES (?, ?)
149
149
  ON CONFLICT(key) DO UPDATE SET value = excluded.value`
150
- );
151
- const deleteStmt = db.prepare(`DELETE FROM ${tableName} WHERE key = ?`);
150
+ );
151
+ deleteStmt = db.prepare(`DELETE FROM ${tableName} WHERE key = ?`);
152
+ }
153
+ };
154
+ const ensureInit = async () => {
155
+ if (!db) {
156
+ await initDb();
157
+ }
158
+ };
152
159
  return {
153
160
  async getItem(key, defaultValue) {
154
161
  try {
162
+ await ensureInit();
155
163
  const row = selectStmt.get(key);
156
164
  if (!row || typeof row.value !== "string") return defaultValue;
157
165
  try {
@@ -169,6 +177,7 @@ var createSqliteDriver = (options = {}) => {
169
177
  },
170
178
  async setItem(key, value) {
171
179
  try {
180
+ await ensureInit();
172
181
  upsertStmt.run(key, JSON.stringify(value));
173
182
  } catch (error) {
174
183
  console.error(`SQLite setItem failed for key "${key}":`, error);
@@ -176,6 +185,7 @@ var createSqliteDriver = (options = {}) => {
176
185
  },
177
186
  async removeItem(key) {
178
187
  try {
188
+ await ensureInit();
179
189
  deleteStmt.run(key);
180
190
  } catch (error) {
181
191
  console.error(`SQLite removeItem failed for key "${key}":`, error);
@@ -183,6 +193,54 @@ var createSqliteDriver = (options = {}) => {
183
193
  }
184
194
  };
185
195
  };
196
+ async function createBunSqliteDriver(dbPath) {
197
+ const SQLite = (await import(
198
+ /* webpackIgnore: true */
199
+ 'bun:sqlite'
200
+ )).default;
201
+ const db = new SQLite(dbPath);
202
+ db.run(`
203
+ CREATE TABLE IF NOT EXISTS sdk_storage (
204
+ key TEXT PRIMARY KEY,
205
+ value TEXT NOT NULL
206
+ )
207
+ `);
208
+ return {
209
+ async getItem(key, defaultValue) {
210
+ try {
211
+ const row = db.query("SELECT value FROM sdk_storage WHERE key = ?").get(key);
212
+ if (!row || typeof row.value !== "string") return defaultValue;
213
+ try {
214
+ return JSON.parse(row.value);
215
+ } catch (parseError) {
216
+ if (typeof defaultValue === "string") {
217
+ return row.value;
218
+ }
219
+ throw parseError;
220
+ }
221
+ } catch (error) {
222
+ console.error(`SQLite getItem failed for key "${key}":`, error);
223
+ return defaultValue;
224
+ }
225
+ },
226
+ async setItem(key, value) {
227
+ try {
228
+ db.query(
229
+ "INSERT INTO sdk_storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
230
+ ).run(key, JSON.stringify(value));
231
+ } catch (error) {
232
+ console.error(`SQLite setItem failed for key "${key}":`, error);
233
+ }
234
+ },
235
+ async removeItem(key) {
236
+ try {
237
+ db.query("DELETE FROM sdk_storage WHERE key = ?").run(key);
238
+ } catch (error) {
239
+ console.error(`SQLite removeItem failed for key "${key}":`, error);
240
+ }
241
+ }
242
+ };
243
+ }
186
244
 
187
245
  // storage/drivers/indexedDB.ts
188
246
  var isBrowser = typeof indexedDB !== "undefined";
@@ -288,14 +346,17 @@ var SDK_STORAGE_KEYS = {
288
346
  INFO_FROM_ALL_PROVIDERS: "info_from_all_providers",
289
347
  LAST_MODELS_UPDATE: "lastModelsUpdate",
290
348
  LAST_BASE_URLS_UPDATE: "lastBaseUrlsUpdate",
291
- LOCAL_CASHU_TOKENS: "local_cashu_tokens",
292
349
  API_KEYS: "api_keys",
293
350
  CHILD_KEYS: "child_keys",
351
+ XCASHU_TOKENS: "xcashu_tokens",
294
352
  ROUTSTR21_MODELS: "routstr21Models",
295
353
  LAST_ROUTSTR21_MODELS_UPDATE: "lastRoutstr21ModelsUpdate",
296
354
  CACHED_RECEIVE_TOKENS: "cached_receive_tokens",
297
355
  USAGE_TRACKING: "usage_tracking",
298
- CLIENT_IDS: "client_ids"
356
+ CLIENT_IDS: "client_ids",
357
+ FAILED_PROVIDERS: "failed_providers",
358
+ LAST_FAILED: "last_failed",
359
+ PROVIDERS_ON_COOLDOWN: "providers_on_cooldown"
299
360
  };
300
361
 
301
362
  // storage/usageTracking/indexedDB.ts
@@ -481,21 +542,23 @@ var normalizeBaseUrl2 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUr
481
542
  var isBun2 = () => {
482
543
  return typeof process.versions.bun !== "undefined";
483
544
  };
484
- var createDatabase2 = (dbPath) => {
545
+ var cachedDbModule2 = null;
546
+ var loadDatabase2 = async (dbPath) => {
485
547
  if (isBun2()) {
486
548
  throw new Error(
487
549
  "SQLite driver not supported in Bun. Use createMemoryDriver() instead."
488
550
  );
489
551
  }
490
- let Database = null;
491
552
  try {
492
- Database = __require("better-sqlite3");
553
+ if (!cachedDbModule2) {
554
+ cachedDbModule2 = (await import('better-sqlite3')).default;
555
+ }
556
+ return new cachedDbModule2(dbPath);
493
557
  } catch (error) {
494
558
  throw new Error(
495
559
  `better-sqlite3 is required for sqlite usage tracking. Install it to use sqlite storage. (${error})`
496
560
  );
497
561
  }
498
- return new Database(dbPath);
499
562
  };
500
563
  var buildWhereClause = (options = {}) => {
501
564
  const clauses = [];
@@ -532,38 +595,49 @@ var buildWhereClause = (options = {}) => {
532
595
  var createSqliteUsageTrackingDriver = (options = {}) => {
533
596
  const dbPath = options.dbPath || "routstr.sqlite";
534
597
  const tableName = options.tableName || "usage_tracking";
535
- const db = createDatabase2(dbPath);
536
598
  const legacyStorageDriver = options.legacyStorageDriver;
537
- db.exec(`
538
- CREATE TABLE IF NOT EXISTS ${tableName} (
539
- id TEXT PRIMARY KEY,
540
- timestamp INTEGER NOT NULL,
541
- model_id TEXT NOT NULL,
542
- base_url TEXT NOT NULL,
543
- request_id TEXT NOT NULL,
544
- cost REAL NOT NULL,
545
- sats_cost REAL NOT NULL,
546
- prompt_tokens INTEGER NOT NULL,
547
- completion_tokens INTEGER NOT NULL,
548
- total_tokens INTEGER NOT NULL,
549
- client TEXT,
550
- session_id TEXT,
551
- tags TEXT
552
- );
553
- CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
554
- CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
555
- CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
556
- CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
557
- CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
558
- `);
559
- const insertStmt = db.prepare(`
560
- INSERT OR REPLACE INTO ${tableName} (
561
- id, timestamp, model_id, base_url, request_id,
562
- cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
563
- client, session_id, tags
564
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
565
- `);
599
+ let db;
600
+ let insertStmt;
566
601
  let migrationComplete = false;
602
+ const initDb = async () => {
603
+ if (!db) {
604
+ db = await loadDatabase2(dbPath);
605
+ db.exec(`
606
+ CREATE TABLE IF NOT EXISTS ${tableName} (
607
+ id TEXT PRIMARY KEY,
608
+ timestamp INTEGER NOT NULL,
609
+ model_id TEXT NOT NULL,
610
+ base_url TEXT NOT NULL,
611
+ request_id TEXT NOT NULL,
612
+ cost REAL NOT NULL,
613
+ sats_cost REAL NOT NULL,
614
+ prompt_tokens INTEGER NOT NULL,
615
+ completion_tokens INTEGER NOT NULL,
616
+ total_tokens INTEGER NOT NULL,
617
+ client TEXT,
618
+ session_id TEXT,
619
+ tags TEXT
620
+ );
621
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
622
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
623
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
624
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
625
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
626
+ `);
627
+ insertStmt = db.prepare(`
628
+ INSERT OR REPLACE INTO ${tableName} (
629
+ id, timestamp, model_id, base_url, request_id,
630
+ cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
631
+ client, session_id, tags
632
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
633
+ `);
634
+ }
635
+ };
636
+ const ensureInit = async () => {
637
+ if (!db) {
638
+ await initDb();
639
+ }
640
+ };
567
641
  const appendOne = (entry) => {
568
642
  insertStmt.run(
569
643
  entry.id,
@@ -621,19 +695,23 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
621
695
  });
622
696
  return {
623
697
  async migrate() {
698
+ await ensureInit();
624
699
  await ensureMigrated();
625
700
  },
626
701
  async append(entry) {
702
+ await ensureInit();
627
703
  await ensureMigrated();
628
704
  appendOne(entry);
629
705
  },
630
706
  async appendMany(entries) {
707
+ await ensureInit();
631
708
  await ensureMigrated();
632
709
  for (const entry of entries) {
633
710
  appendOne(entry);
634
711
  }
635
712
  },
636
713
  async list(options2 = {}) {
714
+ await ensureInit();
637
715
  await ensureMigrated();
638
716
  const { sql, params } = buildWhereClause(options2);
639
717
  const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
@@ -646,6 +724,7 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
646
724
  return rows.map(mapRow);
647
725
  },
648
726
  async count(options2 = {}) {
727
+ await ensureInit();
649
728
  await ensureMigrated();
650
729
  const { sql, params } = buildWhereClause(options2);
651
730
  const stmt = db.prepare(`SELECT COUNT(*) as count FROM ${tableName} ${sql}`);
@@ -653,20 +732,197 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
653
732
  return Number(row?.count ?? 0);
654
733
  },
655
734
  async deleteOlderThan(timestamp) {
735
+ await ensureInit();
656
736
  await ensureMigrated();
657
737
  const stmt = db.prepare(`DELETE FROM ${tableName} WHERE timestamp < ?`);
658
738
  const result = stmt.run(timestamp);
659
739
  return result.changes;
660
740
  },
661
741
  async clear() {
742
+ await ensureInit();
662
743
  await ensureMigrated();
663
744
  db.prepare(`DELETE FROM ${tableName}`).run();
664
745
  }
665
746
  };
666
747
  };
667
748
 
668
- // storage/usageTracking/memory.ts
749
+ // storage/usageTracking/bunSqlite.ts
750
+ var MIGRATION_MARKER_KEY3 = "usage_tracking_migration_v1";
669
751
  var normalizeBaseUrl3 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
752
+ var buildWhereClause2 = (options = {}) => {
753
+ const clauses = [];
754
+ const params = [];
755
+ if (typeof options.before === "number") {
756
+ clauses.push("timestamp < ?");
757
+ params.push(options.before);
758
+ }
759
+ if (typeof options.after === "number") {
760
+ clauses.push("timestamp > ?");
761
+ params.push(options.after);
762
+ }
763
+ if (options.modelId) {
764
+ clauses.push("model_id = ?");
765
+ params.push(options.modelId);
766
+ }
767
+ if (options.baseUrl) {
768
+ clauses.push("base_url = ?");
769
+ params.push(normalizeBaseUrl3(options.baseUrl));
770
+ }
771
+ if (options.sessionId) {
772
+ clauses.push("session_id = ?");
773
+ params.push(options.sessionId);
774
+ }
775
+ if (options.client) {
776
+ clauses.push("client = ?");
777
+ params.push(options.client);
778
+ }
779
+ return {
780
+ sql: clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "",
781
+ params
782
+ };
783
+ };
784
+ var createBunSqliteUsageTrackingDriver = (options = {}) => {
785
+ const dbPath = options.dbPath || "routstr.sqlite";
786
+ const tableName = options.tableName || "usage_tracking";
787
+ const legacyStorageDriver = options.legacyStorageDriver;
788
+ const SQLiteDatabase = options.sqlite?.Database;
789
+ let migrationPromise = null;
790
+ if (!SQLiteDatabase) {
791
+ throw new Error(
792
+ "Bun SQLite Database constructor is required. Pass { sqlite: { Database } } when creating the driver."
793
+ );
794
+ }
795
+ const db = new SQLiteDatabase(dbPath);
796
+ db.run(`
797
+ CREATE TABLE IF NOT EXISTS ${tableName} (
798
+ id TEXT PRIMARY KEY,
799
+ timestamp INTEGER NOT NULL,
800
+ model_id TEXT NOT NULL,
801
+ base_url TEXT NOT NULL,
802
+ request_id TEXT NOT NULL,
803
+ cost REAL NOT NULL,
804
+ sats_cost REAL NOT NULL,
805
+ prompt_tokens INTEGER NOT NULL,
806
+ completion_tokens INTEGER NOT NULL,
807
+ total_tokens INTEGER NOT NULL,
808
+ client TEXT,
809
+ session_id TEXT,
810
+ tags TEXT
811
+ )
812
+ `);
813
+ db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp)`);
814
+ db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id)`);
815
+ db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url)`);
816
+ const appendOne = (entry) => {
817
+ db.query(`
818
+ INSERT OR REPLACE INTO ${tableName} (
819
+ id, timestamp, model_id, base_url, request_id,
820
+ cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
821
+ client, session_id, tags
822
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
823
+ `).run(
824
+ entry.id,
825
+ entry.timestamp,
826
+ entry.modelId,
827
+ normalizeBaseUrl3(entry.baseUrl),
828
+ entry.requestId,
829
+ entry.cost,
830
+ entry.satsCost,
831
+ entry.promptTokens,
832
+ entry.completionTokens,
833
+ entry.totalTokens,
834
+ entry.client ?? null,
835
+ entry.sessionId ?? null,
836
+ JSON.stringify(entry.tags ?? [])
837
+ );
838
+ };
839
+ const mapRow = (row) => ({
840
+ id: row.id,
841
+ timestamp: row.timestamp,
842
+ modelId: row.model_id,
843
+ baseUrl: row.base_url,
844
+ requestId: row.request_id,
845
+ cost: row.cost,
846
+ satsCost: row.sats_cost,
847
+ promptTokens: row.prompt_tokens,
848
+ completionTokens: row.completion_tokens,
849
+ totalTokens: row.total_tokens,
850
+ client: row.client ?? void 0,
851
+ sessionId: row.session_id ?? void 0,
852
+ tags: typeof row.tags === "string" ? JSON.parse(row.tags) : void 0
853
+ });
854
+ const ensureMigrated = async () => {
855
+ if (!legacyStorageDriver) return;
856
+ if (!migrationPromise) {
857
+ migrationPromise = (async () => {
858
+ const migrated = await legacyStorageDriver.getItem(
859
+ MIGRATION_MARKER_KEY3,
860
+ false
861
+ );
862
+ if (migrated) return;
863
+ const legacyEntries = await legacyStorageDriver.getItem(
864
+ SDK_STORAGE_KEYS.USAGE_TRACKING,
865
+ []
866
+ );
867
+ if (legacyEntries.length > 0) {
868
+ for (const entry of legacyEntries) {
869
+ appendOne(entry);
870
+ }
871
+ await legacyStorageDriver.removeItem(SDK_STORAGE_KEYS.USAGE_TRACKING);
872
+ }
873
+ await legacyStorageDriver.setItem(MIGRATION_MARKER_KEY3, true);
874
+ })();
875
+ }
876
+ await migrationPromise;
877
+ };
878
+ return {
879
+ async migrate() {
880
+ await ensureMigrated();
881
+ },
882
+ async append(entry) {
883
+ await ensureMigrated();
884
+ appendOne(entry);
885
+ },
886
+ async appendMany(entries) {
887
+ await ensureMigrated();
888
+ for (const entry of entries) {
889
+ appendOne(entry);
890
+ }
891
+ },
892
+ async list(options2 = {}) {
893
+ await ensureMigrated();
894
+ const { sql, params } = buildWhereClause2(options2);
895
+ const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
896
+ const query = `SELECT * FROM ${tableName} ${sql} ORDER BY timestamp DESC${limitSql}`;
897
+ let rows;
898
+ if (typeof options2.limit === "number") {
899
+ rows = db.query(query).all(...params, options2.limit);
900
+ } else {
901
+ rows = db.query(query).all(...params);
902
+ }
903
+ return rows.map(mapRow);
904
+ },
905
+ async count(options2 = {}) {
906
+ const { sql, params } = buildWhereClause2(options2);
907
+ const query = `SELECT COUNT(*) as count FROM ${tableName} ${sql}`;
908
+ const row = db.query(query).get(...params);
909
+ return Number(row?.count ?? 0);
910
+ },
911
+ async deleteOlderThan(timestamp) {
912
+ await ensureMigrated();
913
+ const before = timestamp;
914
+ const result = db.query(`DELETE FROM ${tableName} WHERE timestamp < ?`).run(before);
915
+ return result.changes ?? 0;
916
+ },
917
+ async clear() {
918
+ await ensureMigrated();
919
+ db.query(`DELETE FROM ${tableName}`).run();
920
+ }
921
+ };
922
+ };
923
+
924
+ // storage/usageTracking/memory.ts
925
+ var normalizeBaseUrl4 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
670
926
  var matchesFilters2 = (entry, options = {}) => {
671
927
  if (typeof options.before === "number" && entry.timestamp >= options.before) {
672
928
  return false;
@@ -677,7 +933,7 @@ var matchesFilters2 = (entry, options = {}) => {
677
933
  if (options.modelId && entry.modelId !== options.modelId) {
678
934
  return false;
679
935
  }
680
- if (options.baseUrl && normalizeBaseUrl3(entry.baseUrl) !== normalizeBaseUrl3(options.baseUrl)) {
936
+ if (options.baseUrl && normalizeBaseUrl4(entry.baseUrl) !== normalizeBaseUrl4(options.baseUrl)) {
681
937
  return false;
682
938
  }
683
939
  if (options.sessionId && entry.sessionId !== options.sessionId) {
@@ -691,18 +947,18 @@ var matchesFilters2 = (entry, options = {}) => {
691
947
  var createMemoryUsageTrackingDriver = (seed = []) => {
692
948
  const store = /* @__PURE__ */ new Map();
693
949
  for (const entry of seed) {
694
- store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl3(entry.baseUrl) });
950
+ store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
695
951
  }
696
952
  return {
697
953
  async migrate() {
698
954
  return;
699
955
  },
700
956
  async append(entry) {
701
- store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl3(entry.baseUrl) });
957
+ store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
702
958
  },
703
959
  async appendMany(entries) {
704
960
  for (const entry of entries) {
705
- store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl3(entry.baseUrl) });
961
+ store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
706
962
  }
707
963
  },
708
964
  async list(options = {}) {
@@ -730,20 +986,7 @@ var createMemoryUsageTrackingDriver = (seed = []) => {
730
986
  }
731
987
  };
732
988
  };
733
- var normalizeBaseUrl4 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
734
- var getCashuTokenBalance = (token) => {
735
- try {
736
- const decoded = getDecodedToken(token);
737
- const unitDivisor = decoded.unit === "msat" ? 1e3 : 1;
738
- let sum = 0;
739
- for (const proof of decoded.proofs) {
740
- sum += proof.amount / unitDivisor;
741
- }
742
- return sum;
743
- } catch {
744
- return 0;
745
- }
746
- };
989
+ var normalizeBaseUrl5 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
747
990
  var createEmptyStore = (driver) => createStore((set, get) => ({
748
991
  modelsFromAllProviders: {},
749
992
  lastUsedModel: null,
@@ -753,17 +996,20 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
753
996
  mintsFromAllProviders: {},
754
997
  infoFromAllProviders: {},
755
998
  lastModelsUpdate: {},
756
- cachedTokens: [],
757
999
  apiKeys: [],
758
1000
  childKeys: [],
1001
+ xcashuTokens: {},
759
1002
  routstr21Models: [],
760
1003
  lastRoutstr21ModelsUpdate: null,
761
1004
  cachedReceiveTokens: [],
762
1005
  clientIds: [],
1006
+ failedProviders: [],
1007
+ lastFailed: {},
1008
+ providersOnCooldown: [],
763
1009
  setModelsFromAllProviders: (value) => {
764
1010
  const normalized = {};
765
1011
  for (const [baseUrl, models] of Object.entries(value)) {
766
- normalized[normalizeBaseUrl4(baseUrl)] = models;
1012
+ normalized[normalizeBaseUrl5(baseUrl)] = models;
767
1013
  }
768
1014
  void driver.setItem(
769
1015
  SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
@@ -776,7 +1022,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
776
1022
  set({ lastUsedModel: value });
777
1023
  },
778
1024
  setBaseUrlsList: (value) => {
779
- const normalized = value.map((url) => normalizeBaseUrl4(url));
1025
+ const normalized = value.map((url) => normalizeBaseUrl5(url));
780
1026
  void driver.setItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, normalized);
781
1027
  set({ baseUrlsList: normalized });
782
1028
  },
@@ -785,14 +1031,14 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
785
1031
  set({ lastBaseUrlsUpdate: value });
786
1032
  },
787
1033
  setDisabledProviders: (value) => {
788
- const normalized = value.map((url) => normalizeBaseUrl4(url));
1034
+ const normalized = value.map((url) => normalizeBaseUrl5(url));
789
1035
  void driver.setItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, normalized);
790
1036
  set({ disabledProviders: normalized });
791
1037
  },
792
1038
  setMintsFromAllProviders: (value) => {
793
1039
  const normalized = {};
794
1040
  for (const [baseUrl, mints] of Object.entries(value)) {
795
- normalized[normalizeBaseUrl4(baseUrl)] = mints.map(
1041
+ normalized[normalizeBaseUrl5(baseUrl)] = mints.map(
796
1042
  (mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint
797
1043
  );
798
1044
  }
@@ -805,7 +1051,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
805
1051
  setInfoFromAllProviders: (value) => {
806
1052
  const normalized = {};
807
1053
  for (const [baseUrl, info] of Object.entries(value)) {
808
- normalized[normalizeBaseUrl4(baseUrl)] = info;
1054
+ normalized[normalizeBaseUrl5(baseUrl)] = info;
809
1055
  }
810
1056
  void driver.setItem(SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS, normalized);
811
1057
  set({ infoFromAllProviders: normalized });
@@ -813,30 +1059,17 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
813
1059
  setLastModelsUpdate: (value) => {
814
1060
  const normalized = {};
815
1061
  for (const [baseUrl, timestamp] of Object.entries(value)) {
816
- normalized[normalizeBaseUrl4(baseUrl)] = timestamp;
1062
+ normalized[normalizeBaseUrl5(baseUrl)] = timestamp;
817
1063
  }
818
1064
  void driver.setItem(SDK_STORAGE_KEYS.LAST_MODELS_UPDATE, normalized);
819
1065
  set({ lastModelsUpdate: normalized });
820
1066
  },
821
- setCachedTokens: (value) => {
822
- set((state) => {
823
- const updates = typeof value === "function" ? value(state.cachedTokens) : value;
824
- const normalized = updates.map((entry) => ({
825
- ...entry,
826
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
827
- balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
828
- lastUsed: entry.lastUsed ?? null
829
- }));
830
- void driver.setItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, normalized);
831
- return { cachedTokens: normalized };
832
- });
833
- },
834
1067
  setApiKeys: (value) => {
835
1068
  set((state) => {
836
1069
  const updates = typeof value === "function" ? value(state.apiKeys) : value;
837
1070
  const normalized = updates.map((entry) => ({
838
1071
  ...entry,
839
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
1072
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
840
1073
  balance: entry.balance ?? 0,
841
1074
  lastUsed: entry.lastUsed ?? null
842
1075
  }));
@@ -848,7 +1081,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
848
1081
  set((state) => {
849
1082
  const updates = typeof value === "function" ? value(state.childKeys) : value;
850
1083
  const normalized = updates.map((entry) => ({
851
- parentBaseUrl: normalizeBaseUrl4(entry.parentBaseUrl),
1084
+ parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
852
1085
  childKey: entry.childKey,
853
1086
  balance: entry.balance ?? 0,
854
1087
  balanceLimit: entry.balanceLimit,
@@ -859,6 +1092,30 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
859
1092
  return { childKeys: normalized };
860
1093
  });
861
1094
  },
1095
+ setXcashuTokens: (value) => {
1096
+ const normalized = {};
1097
+ for (const [baseUrl, tokens] of Object.entries(value)) {
1098
+ normalized[normalizeBaseUrl5(baseUrl)] = tokens.map((entry) => ({
1099
+ ...entry,
1100
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
1101
+ createdAt: entry.createdAt ?? Date.now(),
1102
+ tryCount: entry.tryCount ?? 0
1103
+ }));
1104
+ }
1105
+ void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, normalized);
1106
+ set({ xcashuTokens: normalized });
1107
+ },
1108
+ updateXcashuTokenTryCount: (token, tryCount) => {
1109
+ const currentTokens = get().xcashuTokens;
1110
+ const updatedTokens = {};
1111
+ for (const [baseUrl, tokens] of Object.entries(currentTokens)) {
1112
+ updatedTokens[baseUrl] = tokens.map(
1113
+ (entry) => entry.token === token ? { ...entry, tryCount } : entry
1114
+ );
1115
+ }
1116
+ void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, updatedTokens);
1117
+ set({ xcashuTokens: updatedTokens });
1118
+ },
862
1119
  setRoutstr21Models: (value) => {
863
1120
  void driver.setItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, value);
864
1121
  set({ routstr21Models: value });
@@ -888,6 +1145,71 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
888
1145
  void driver.setItem(SDK_STORAGE_KEYS.CLIENT_IDS, normalized);
889
1146
  return { clientIds: normalized };
890
1147
  });
1148
+ },
1149
+ // ========== Failure Tracking ==========
1150
+ setFailedProviders: (value) => {
1151
+ const normalized = value.map((url) => normalizeBaseUrl5(url));
1152
+ void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, normalized);
1153
+ set({ failedProviders: normalized });
1154
+ },
1155
+ addFailedProvider: (baseUrl) => {
1156
+ const normalized = normalizeBaseUrl5(baseUrl);
1157
+ const current = get().failedProviders;
1158
+ if (!current.includes(normalized)) {
1159
+ const updated = [...current, normalized];
1160
+ void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
1161
+ set({ failedProviders: updated });
1162
+ }
1163
+ },
1164
+ removeFailedProvider: (baseUrl) => {
1165
+ const normalized = normalizeBaseUrl5(baseUrl);
1166
+ const current = get().failedProviders;
1167
+ const updated = current.filter((url) => url !== normalized);
1168
+ void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
1169
+ set({ failedProviders: updated });
1170
+ },
1171
+ setLastFailed: (value) => {
1172
+ const normalized = {};
1173
+ for (const [baseUrl, timestamp] of Object.entries(value)) {
1174
+ normalized[normalizeBaseUrl5(baseUrl)] = timestamp;
1175
+ }
1176
+ void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, normalized);
1177
+ set({ lastFailed: normalized });
1178
+ },
1179
+ setLastFailedTimestamp: (baseUrl, timestamp) => {
1180
+ const normalized = normalizeBaseUrl5(baseUrl);
1181
+ const current = get().lastFailed;
1182
+ const updated = { ...current, [normalized]: timestamp };
1183
+ void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, updated);
1184
+ set({ lastFailed: updated });
1185
+ },
1186
+ setProvidersOnCooldown: (value) => {
1187
+ const normalized = value.map((entry) => ({
1188
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
1189
+ timestamp: entry.timestamp
1190
+ }));
1191
+ void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, normalized);
1192
+ set({ providersOnCooldown: normalized });
1193
+ },
1194
+ addProviderOnCooldown: (baseUrl, timestamp) => {
1195
+ const normalized = normalizeBaseUrl5(baseUrl);
1196
+ const current = get().providersOnCooldown;
1197
+ if (!current.some((entry) => entry.baseUrl === normalized)) {
1198
+ const updated = [...current, { baseUrl: normalized, timestamp }];
1199
+ void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
1200
+ set({ providersOnCooldown: updated });
1201
+ }
1202
+ },
1203
+ removeProviderFromCooldown: (baseUrl) => {
1204
+ const normalized = normalizeBaseUrl5(baseUrl);
1205
+ const current = get().providersOnCooldown;
1206
+ const updated = current.filter((entry) => entry.baseUrl !== normalized);
1207
+ void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
1208
+ set({ providersOnCooldown: updated });
1209
+ },
1210
+ clearProvidersOnCooldown: () => {
1211
+ void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, []);
1212
+ set({ providersOnCooldown: [] });
891
1213
  }
892
1214
  }));
893
1215
  var hydrateStoreFromDriver = async (store, driver) => {
@@ -900,13 +1222,16 @@ var hydrateStoreFromDriver = async (store, driver) => {
900
1222
  rawMints,
901
1223
  rawInfo,
902
1224
  rawLastModelsUpdate,
903
- rawCachedTokens,
904
1225
  rawApiKeys,
905
1226
  rawChildKeys,
1227
+ rawXcashuTokens,
906
1228
  rawRoutstr21Models,
907
1229
  rawLastRoutstr21ModelsUpdate,
908
1230
  rawCachedReceiveTokens,
909
- rawClientIds
1231
+ rawClientIds,
1232
+ rawFailedProviders,
1233
+ rawLastFailed,
1234
+ rawProvidersOnCooldown
910
1235
  ] = await Promise.all([
911
1236
  driver.getItem(
912
1237
  SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
@@ -928,65 +1253,73 @@ var hydrateStoreFromDriver = async (store, driver) => {
928
1253
  SDK_STORAGE_KEYS.LAST_MODELS_UPDATE,
929
1254
  {}
930
1255
  ),
931
- driver.getItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, []),
932
1256
  driver.getItem(SDK_STORAGE_KEYS.API_KEYS, []),
933
1257
  driver.getItem(SDK_STORAGE_KEYS.CHILD_KEYS, []),
1258
+ driver.getItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, {}),
934
1259
  driver.getItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, []),
935
1260
  driver.getItem(
936
1261
  SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
937
1262
  null
938
1263
  ),
939
1264
  driver.getItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, []),
940
- driver.getItem(SDK_STORAGE_KEYS.CLIENT_IDS, [])
1265
+ driver.getItem(SDK_STORAGE_KEYS.CLIENT_IDS, []),
1266
+ driver.getItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, []),
1267
+ driver.getItem(SDK_STORAGE_KEYS.LAST_FAILED, {}),
1268
+ driver.getItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, [])
941
1269
  ]);
942
1270
  const modelsFromAllProviders = Object.fromEntries(
943
1271
  Object.entries(rawModels).map(([baseUrl, models]) => [
944
- normalizeBaseUrl4(baseUrl),
1272
+ normalizeBaseUrl5(baseUrl),
945
1273
  models
946
1274
  ])
947
1275
  );
948
- const baseUrlsList = rawBaseUrls.map((url) => normalizeBaseUrl4(url));
1276
+ const baseUrlsList = rawBaseUrls.map((url) => normalizeBaseUrl5(url));
949
1277
  const disabledProviders = rawDisabledProviders.map(
950
- (url) => normalizeBaseUrl4(url)
1278
+ (url) => normalizeBaseUrl5(url)
951
1279
  );
952
1280
  const mintsFromAllProviders = Object.fromEntries(
953
1281
  Object.entries(rawMints).map(([baseUrl, mints]) => [
954
- normalizeBaseUrl4(baseUrl),
1282
+ normalizeBaseUrl5(baseUrl),
955
1283
  mints.map((mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint)
956
1284
  ])
957
1285
  );
958
1286
  const infoFromAllProviders = Object.fromEntries(
959
1287
  Object.entries(rawInfo).map(([baseUrl, info]) => [
960
- normalizeBaseUrl4(baseUrl),
1288
+ normalizeBaseUrl5(baseUrl),
961
1289
  info
962
1290
  ])
963
1291
  );
964
1292
  const lastModelsUpdate = Object.fromEntries(
965
1293
  Object.entries(rawLastModelsUpdate).map(([baseUrl, timestamp]) => [
966
- normalizeBaseUrl4(baseUrl),
1294
+ normalizeBaseUrl5(baseUrl),
967
1295
  timestamp
968
1296
  ])
969
1297
  );
970
- const cachedTokens = rawCachedTokens.map((entry) => ({
971
- ...entry,
972
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
973
- balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
974
- lastUsed: entry.lastUsed ?? null
975
- }));
976
1298
  const apiKeys = rawApiKeys.map((entry) => ({
977
1299
  ...entry,
978
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
1300
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
979
1301
  balance: entry.balance ?? 0,
980
1302
  lastUsed: entry.lastUsed ?? null
981
1303
  }));
982
1304
  const childKeys = rawChildKeys.map((entry) => ({
983
- parentBaseUrl: normalizeBaseUrl4(entry.parentBaseUrl),
1305
+ parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
984
1306
  childKey: entry.childKey,
985
1307
  balance: entry.balance ?? 0,
986
1308
  balanceLimit: entry.balanceLimit,
987
1309
  validityDate: entry.validityDate,
988
1310
  createdAt: entry.createdAt ?? Date.now()
989
1311
  }));
1312
+ const xcashuTokens = Object.fromEntries(
1313
+ Object.entries(rawXcashuTokens).map(([baseUrl, tokens]) => [
1314
+ normalizeBaseUrl5(baseUrl),
1315
+ tokens.map((entry) => ({
1316
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
1317
+ token: entry.token,
1318
+ createdAt: entry.createdAt ?? Date.now(),
1319
+ tryCount: entry.tryCount ?? 0
1320
+ }))
1321
+ ])
1322
+ );
990
1323
  const routstr21Models = rawRoutstr21Models;
991
1324
  const lastRoutstr21ModelsUpdate = rawLastRoutstr21ModelsUpdate;
992
1325
  const cachedReceiveTokens = rawCachedReceiveTokens?.map((entry) => ({
@@ -1000,6 +1333,17 @@ var hydrateStoreFromDriver = async (store, driver) => {
1000
1333
  createdAt: entry.createdAt ?? Date.now(),
1001
1334
  lastUsed: entry.lastUsed ?? null
1002
1335
  }));
1336
+ const failedProviders = rawFailedProviders.map((url) => normalizeBaseUrl5(url));
1337
+ const lastFailed = Object.fromEntries(
1338
+ Object.entries(rawLastFailed).map(([baseUrl, timestamp]) => [
1339
+ normalizeBaseUrl5(baseUrl),
1340
+ timestamp
1341
+ ])
1342
+ );
1343
+ const providersOnCooldown = rawProvidersOnCooldown.map((entry) => ({
1344
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
1345
+ timestamp: entry.timestamp
1346
+ }));
1003
1347
  store.setState({
1004
1348
  modelsFromAllProviders,
1005
1349
  lastUsedModel,
@@ -1009,13 +1353,16 @@ var hydrateStoreFromDriver = async (store, driver) => {
1009
1353
  mintsFromAllProviders,
1010
1354
  infoFromAllProviders,
1011
1355
  lastModelsUpdate,
1012
- cachedTokens,
1013
1356
  apiKeys,
1014
1357
  childKeys,
1358
+ xcashuTokens,
1015
1359
  routstr21Models,
1016
1360
  lastRoutstr21ModelsUpdate,
1017
1361
  cachedReceiveTokens,
1018
- clientIds
1362
+ clientIds,
1363
+ failedProviders,
1364
+ lastFailed,
1365
+ providersOnCooldown
1019
1366
  });
1020
1367
  };
1021
1368
  var createSdkStore = ({
@@ -1035,12 +1382,12 @@ var createDiscoveryAdapterFromStore = (store) => ({
1035
1382
  getCachedProviderInfo: () => store.getState().infoFromAllProviders,
1036
1383
  setCachedProviderInfo: (info) => store.getState().setInfoFromAllProviders(info),
1037
1384
  getProviderLastUpdate: (baseUrl) => {
1038
- const normalized = normalizeBaseUrl4(baseUrl);
1385
+ const normalized = normalizeBaseUrl5(baseUrl);
1039
1386
  const timestamps = store.getState().lastModelsUpdate;
1040
1387
  return timestamps[normalized] || null;
1041
1388
  },
1042
1389
  setProviderLastUpdate: (baseUrl, timestamp) => {
1043
- const normalized = normalizeBaseUrl4(baseUrl);
1390
+ const normalized = normalizeBaseUrl5(baseUrl);
1044
1391
  const timestamps = { ...store.getState().lastModelsUpdate };
1045
1392
  timestamps[normalized] = timestamp;
1046
1393
  store.getState().setLastModelsUpdate(timestamps);
@@ -1058,59 +1405,6 @@ var createDiscoveryAdapterFromStore = (store) => ({
1058
1405
  setRoutstr21ModelsLastUpdate: (timestamp) => store.getState().setRoutstr21ModelsLastUpdate(timestamp)
1059
1406
  });
1060
1407
  var createStorageAdapterFromStore = (store) => ({
1061
- getToken: (baseUrl) => {
1062
- const normalized = normalizeBaseUrl4(baseUrl);
1063
- const entry = store.getState().cachedTokens.find((token) => token.baseUrl === normalized);
1064
- if (!entry) return null;
1065
- const next = store.getState().cachedTokens.map(
1066
- (token) => token.baseUrl === normalized ? { ...token, lastUsed: Date.now() } : token
1067
- );
1068
- store.getState().setCachedTokens(next);
1069
- return entry.token;
1070
- },
1071
- setToken: (baseUrl, token) => {
1072
- const normalized = normalizeBaseUrl4(baseUrl);
1073
- const tokens = store.getState().cachedTokens;
1074
- const balance = getCashuTokenBalance(token);
1075
- const existingIndex = tokens.findIndex(
1076
- (entry) => entry.baseUrl === normalized
1077
- );
1078
- if (existingIndex !== -1) {
1079
- throw new Error(`Token already exists for baseUrl: ${normalized}`);
1080
- }
1081
- const next = [...tokens];
1082
- next.push({
1083
- baseUrl: normalized,
1084
- token,
1085
- balance,
1086
- lastUsed: Date.now()
1087
- });
1088
- store.getState().setCachedTokens(next);
1089
- },
1090
- removeToken: (baseUrl) => {
1091
- const normalized = normalizeBaseUrl4(baseUrl);
1092
- const next = store.getState().cachedTokens.filter((entry) => entry.baseUrl !== normalized);
1093
- store.getState().setCachedTokens(next);
1094
- },
1095
- updateTokenBalance: (baseUrl, balance) => {
1096
- const normalized = normalizeBaseUrl4(baseUrl);
1097
- const tokens = store.getState().cachedTokens;
1098
- const next = tokens.map(
1099
- (entry) => entry.baseUrl === normalized ? { ...entry, balance } : entry
1100
- );
1101
- store.getState().setCachedTokens(next);
1102
- },
1103
- getCachedTokenDistribution: () => {
1104
- const cachedTokens = store.getState().cachedTokens;
1105
- const distributionMap = {};
1106
- for (const entry of cachedTokens) {
1107
- const sum = entry.balance || 0;
1108
- if (sum > 0) {
1109
- distributionMap[entry.baseUrl] = (distributionMap[entry.baseUrl] || 0) + sum;
1110
- }
1111
- }
1112
- return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
1113
- },
1114
1408
  getApiKeyDistribution: () => {
1115
1409
  const apiKeys = store.getState().apiKeys;
1116
1410
  const distributionMap = {};
@@ -1123,28 +1417,24 @@ var createStorageAdapterFromStore = (store) => ({
1123
1417
  return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
1124
1418
  },
1125
1419
  saveProviderInfo: (baseUrl, info) => {
1126
- const normalized = normalizeBaseUrl4(baseUrl);
1420
+ const normalized = normalizeBaseUrl5(baseUrl);
1127
1421
  const next = { ...store.getState().infoFromAllProviders };
1128
1422
  next[normalized] = info;
1129
1423
  store.getState().setInfoFromAllProviders(next);
1130
1424
  },
1131
1425
  getProviderInfo: (baseUrl) => {
1132
- const normalized = normalizeBaseUrl4(baseUrl);
1426
+ const normalized = normalizeBaseUrl5(baseUrl);
1133
1427
  return store.getState().infoFromAllProviders[normalized] || null;
1134
1428
  },
1135
1429
  // ========== API Keys (for apikeys mode) ==========
1136
1430
  getApiKey: (baseUrl) => {
1137
- const normalized = normalizeBaseUrl4(baseUrl);
1431
+ const normalized = normalizeBaseUrl5(baseUrl);
1138
1432
  const entry = store.getState().apiKeys.find((key) => key.baseUrl === normalized);
1139
1433
  if (!entry) return null;
1140
- const next = store.getState().apiKeys.map(
1141
- (key) => key.baseUrl === normalized ? { ...key, lastUsed: Date.now() } : key
1142
- );
1143
- store.getState().setApiKeys(next);
1144
1434
  return entry;
1145
1435
  },
1146
1436
  setApiKey: (baseUrl, key) => {
1147
- const normalized = normalizeBaseUrl4(baseUrl);
1437
+ const normalized = normalizeBaseUrl5(baseUrl);
1148
1438
  const keys = store.getState().apiKeys;
1149
1439
  const existingIndex = keys.findIndex(
1150
1440
  (entry) => entry.baseUrl === normalized
@@ -1162,15 +1452,15 @@ var createStorageAdapterFromStore = (store) => ({
1162
1452
  store.getState().setApiKeys(next);
1163
1453
  },
1164
1454
  updateApiKeyBalance: (baseUrl, balance) => {
1165
- const normalized = normalizeBaseUrl4(baseUrl);
1455
+ const normalized = normalizeBaseUrl5(baseUrl);
1166
1456
  const keys = store.getState().apiKeys;
1167
1457
  const next = keys.map(
1168
- (entry) => entry.baseUrl === normalized ? { ...entry, balance } : entry
1458
+ (entry) => entry.baseUrl === normalized ? { ...entry, balance, lastUsed: Date.now() } : entry
1169
1459
  );
1170
1460
  store.getState().setApiKeys(next);
1171
1461
  },
1172
1462
  removeApiKey: (baseUrl) => {
1173
- const normalized = normalizeBaseUrl4(baseUrl);
1463
+ const normalized = normalizeBaseUrl5(baseUrl);
1174
1464
  const next = store.getState().apiKeys.filter((entry) => entry.baseUrl !== normalized);
1175
1465
  store.getState().setApiKeys(next);
1176
1466
  },
@@ -1184,7 +1474,7 @@ var createStorageAdapterFromStore = (store) => ({
1184
1474
  },
1185
1475
  // ========== Child Keys ==========
1186
1476
  getChildKey: (parentBaseUrl) => {
1187
- const normalized = normalizeBaseUrl4(parentBaseUrl);
1477
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
1188
1478
  const entry = store.getState().childKeys.find((key) => key.parentBaseUrl === normalized);
1189
1479
  if (!entry) return null;
1190
1480
  return {
@@ -1197,7 +1487,7 @@ var createStorageAdapterFromStore = (store) => ({
1197
1487
  };
1198
1488
  },
1199
1489
  setChildKey: (parentBaseUrl, childKey, balance, validityDate, balanceLimit) => {
1200
- const normalized = normalizeBaseUrl4(parentBaseUrl);
1490
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
1201
1491
  const keys = store.getState().childKeys;
1202
1492
  const existingIndex = keys.findIndex(
1203
1493
  (entry) => entry.parentBaseUrl === normalized
@@ -1228,7 +1518,7 @@ var createStorageAdapterFromStore = (store) => ({
1228
1518
  }
1229
1519
  },
1230
1520
  updateChildKeyBalance: (parentBaseUrl, balance) => {
1231
- const normalized = normalizeBaseUrl4(parentBaseUrl);
1521
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
1232
1522
  const keys = store.getState().childKeys;
1233
1523
  const next = keys.map(
1234
1524
  (entry) => entry.parentBaseUrl === normalized ? { ...entry, balance } : entry
@@ -1236,7 +1526,7 @@ var createStorageAdapterFromStore = (store) => ({
1236
1526
  store.getState().setChildKeys(next);
1237
1527
  },
1238
1528
  removeChildKey: (parentBaseUrl) => {
1239
- const normalized = normalizeBaseUrl4(parentBaseUrl);
1529
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
1240
1530
  const next = store.getState().childKeys.filter((entry) => entry.parentBaseUrl !== normalized);
1241
1531
  store.getState().setChildKeys(next);
1242
1532
  },
@@ -1255,20 +1545,60 @@ var createStorageAdapterFromStore = (store) => ({
1255
1545
  },
1256
1546
  setCachedReceiveTokens: (tokens) => {
1257
1547
  store.getState().setCachedReceiveTokens(tokens);
1548
+ },
1549
+ // ========== XCashu Tokens (multiple tokens per baseUrl) ==========
1550
+ getXcashuTokens: () => {
1551
+ return store.getState().xcashuTokens;
1552
+ },
1553
+ getXcashuTokensForBaseUrl: (baseUrl) => {
1554
+ const normalized = normalizeBaseUrl5(baseUrl);
1555
+ return store.getState().xcashuTokens[normalized] || [];
1556
+ },
1557
+ addXcashuToken: (baseUrl, token) => {
1558
+ const normalized = normalizeBaseUrl5(baseUrl);
1559
+ const tokens = store.getState().xcashuTokens;
1560
+ const existing = tokens[normalized] || [];
1561
+ const next = { ...tokens };
1562
+ next[normalized] = [
1563
+ ...existing,
1564
+ { baseUrl: normalized, token, createdAt: Date.now(), tryCount: 0 }
1565
+ ];
1566
+ store.getState().setXcashuTokens(next);
1567
+ },
1568
+ removeXcashuToken: (baseUrl, token) => {
1569
+ const normalized = normalizeBaseUrl5(baseUrl);
1570
+ const tokens = store.getState().xcashuTokens;
1571
+ const existing = tokens[normalized] || [];
1572
+ const next = { ...tokens };
1573
+ next[normalized] = existing.filter((entry) => entry.token !== token);
1574
+ if (next[normalized].length === 0) {
1575
+ delete next[normalized];
1576
+ }
1577
+ store.getState().setXcashuTokens(next);
1578
+ },
1579
+ clearXcashuTokensForBaseUrl: (baseUrl) => {
1580
+ const normalized = normalizeBaseUrl5(baseUrl);
1581
+ const tokens = store.getState().xcashuTokens;
1582
+ const next = { ...tokens };
1583
+ delete next[normalized];
1584
+ store.getState().setXcashuTokens(next);
1585
+ },
1586
+ updateXcashuTokenTryCount: (token, tryCount) => {
1587
+ store.getState().updateXcashuTokenTryCount(token, tryCount);
1258
1588
  }
1259
1589
  });
1260
1590
  var createProviderRegistryFromStore = (store) => ({
1261
1591
  getModelsForProvider: (baseUrl) => {
1262
- const normalized = normalizeBaseUrl4(baseUrl);
1592
+ const normalized = normalizeBaseUrl5(baseUrl);
1263
1593
  return store.getState().modelsFromAllProviders[normalized] || [];
1264
1594
  },
1265
1595
  getDisabledProviders: () => store.getState().disabledProviders,
1266
1596
  getProviderMints: (baseUrl) => {
1267
- const normalized = normalizeBaseUrl4(baseUrl);
1597
+ const normalized = normalizeBaseUrl5(baseUrl);
1268
1598
  return store.getState().mintsFromAllProviders[normalized] || [];
1269
1599
  },
1270
1600
  getProviderInfo: async (baseUrl) => {
1271
- const normalized = normalizeBaseUrl4(baseUrl);
1601
+ const normalized = normalizeBaseUrl5(baseUrl);
1272
1602
  const cached = store.getState().infoFromAllProviders[normalized];
1273
1603
  if (cached) return cached;
1274
1604
  try {
@@ -1343,7 +1673,7 @@ var getDefaultUsageTrackingDriver = () => {
1343
1673
  return defaultUsageTrackingDriver;
1344
1674
  }
1345
1675
  if (isBun3()) {
1346
- defaultUsageTrackingDriver = createMemoryUsageTrackingDriver();
1676
+ defaultUsageTrackingDriver = createBunSqliteUsageTrackingDriver();
1347
1677
  return defaultUsageTrackingDriver;
1348
1678
  }
1349
1679
  if (isNode()) {
@@ -1355,10 +1685,13 @@ var getDefaultUsageTrackingDriver = () => {
1355
1685
  defaultUsageTrackingDriver = createMemoryUsageTrackingDriver();
1356
1686
  return defaultUsageTrackingDriver;
1357
1687
  };
1688
+ var setDefaultUsageTrackingDriver = (driver) => {
1689
+ defaultUsageTrackingDriver = driver;
1690
+ };
1358
1691
  var getDefaultDiscoveryAdapter = async () => createDiscoveryAdapterFromStore(await getDefaultSdkStore());
1359
1692
  var getDefaultStorageAdapter = async () => createStorageAdapterFromStore(await getDefaultSdkStore());
1360
1693
  var getDefaultProviderRegistry = async () => createProviderRegistryFromStore(await getDefaultSdkStore());
1361
1694
 
1362
- export { SDK_STORAGE_KEYS, createDiscoveryAdapterFromStore, createIndexedDBDriver, createIndexedDBUsageTrackingDriver, createMemoryDriver, createMemoryUsageTrackingDriver, createProviderRegistryFromStore, createSdkStore, createSqliteDriver, createSqliteUsageTrackingDriver, createStorageAdapterFromStore, getDefaultDiscoveryAdapter, getDefaultProviderRegistry, getDefaultSdkDriver, getDefaultSdkStore, getDefaultStorageAdapter, getDefaultUsageTrackingDriver, localStorageDriver };
1695
+ export { SDK_STORAGE_KEYS, createBunSqliteDriver, createBunSqliteUsageTrackingDriver, createDiscoveryAdapterFromStore, createIndexedDBDriver, createIndexedDBUsageTrackingDriver, createMemoryDriver, createMemoryUsageTrackingDriver, createProviderRegistryFromStore, createSdkStore, createSqliteDriver, createSqliteUsageTrackingDriver, createStorageAdapterFromStore, getDefaultDiscoveryAdapter, getDefaultProviderRegistry, getDefaultSdkDriver, getDefaultSdkStore, getDefaultStorageAdapter, getDefaultUsageTrackingDriver, localStorageDriver, setDefaultUsageTrackingDriver };
1363
1696
  //# sourceMappingURL=index.mjs.map
1364
1697
  //# sourceMappingURL=index.mjs.map