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