routstrd 0.4.10 → 0.4.11

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.
@@ -34170,7 +34170,7 @@ var init_hpke_noble = __esm(() => {
34170
34170
  priv2 = Symbol();
34171
34171
  });
34172
34172
 
34173
- // node_modules/ehbp/dist/esm/protocol.js
34173
+ // node_modules/tinfoil/node_modules/ehbp/dist/esm/protocol.js
34174
34174
  var PROTOCOL, HPKE_CONFIG;
34175
34175
  var init_protocol = __esm(() => {
34176
34176
  PROTOCOL = {
@@ -34188,7 +34188,7 @@ var init_protocol = __esm(() => {
34188
34188
  };
34189
34189
  });
34190
34190
 
34191
- // node_modules/ehbp/dist/esm/derive.js
34191
+ // node_modules/tinfoil/node_modules/ehbp/dist/esm/derive.js
34192
34192
  async function deriveResponseKeys(exportedSecret, requestEnc, responseNonce) {
34193
34193
  if (exportedSecret.length !== EXPORT_LENGTH) {
34194
34194
  throw new Error(`exported secret must be ${EXPORT_LENGTH} bytes, got ${exportedSecret.length}`);
@@ -34224,11 +34224,6 @@ function computeNonce(nonceBase, seq) {
34224
34224
  }
34225
34225
  return nonce;
34226
34226
  }
34227
- async function encryptChunk(km, seq, plaintext) {
34228
- const nonce = computeNonce(km.nonceBase, seq);
34229
- const ciphertext = await aead.Seal(km.keyBytes, nonce, new Uint8Array(0), plaintext);
34230
- return ciphertext;
34231
- }
34232
34227
  async function decryptChunk(km, seq, ciphertext) {
34233
34228
  const nonce = computeNonce(km.nonceBase, seq);
34234
34229
  const plaintext = await aead.Open(km.keyBytes, nonce, new Uint8Array(0), ciphertext);
@@ -34259,7 +34254,7 @@ var init_derive = __esm(() => {
34259
34254
  RESPONSE_NONCE_LABEL = new TextEncoder().encode("nonce");
34260
34255
  });
34261
34256
 
34262
- // node_modules/ehbp/dist/esm/errors.js
34257
+ // node_modules/tinfoil/node_modules/ehbp/dist/esm/errors.js
34263
34258
  var EhbpError, KeyConfigMismatchError, ProtocolError, DecryptionError;
34264
34259
  var init_errors = __esm(() => {
34265
34260
  EhbpError = class EhbpError extends Error {
@@ -34292,7 +34287,7 @@ var init_errors = __esm(() => {
34292
34287
  };
34293
34288
  });
34294
34289
 
34295
- // node_modules/ehbp/dist/esm/request-options.js
34290
+ // node_modules/tinfoil/node_modules/ehbp/dist/esm/request-options.js
34296
34291
  function forwardedRequestInit(source) {
34297
34292
  const forwarded = {};
34298
34293
  if (!source) {
@@ -34326,7 +34321,7 @@ var init_request_options = __esm(() => {
34326
34321
  ];
34327
34322
  });
34328
34323
 
34329
- // node_modules/ehbp/dist/esm/identity.js
34324
+ // node_modules/tinfoil/node_modules/ehbp/dist/esm/identity.js
34330
34325
  function createSuite() {
34331
34326
  return new CipherSuite(KEM_DHKEM_X25519_HKDF_SHA256, KDF_HKDF_SHA256, AEAD_AES_256_GCM);
34332
34327
  }
@@ -34612,7 +34607,7 @@ var init_identity = __esm(() => {
34612
34607
  MAX_RESPONSE_CHUNK_BYTES = 64 * 1024 * 1024;
34613
34608
  });
34614
34609
 
34615
- // node_modules/ehbp/dist/esm/client.js
34610
+ // node_modules/tinfoil/node_modules/ehbp/dist/esm/client.js
34616
34611
  class Transport {
34617
34612
  serverIdentity;
34618
34613
  serverHost;
@@ -34763,9 +34758,6 @@ class Transport {
34763
34758
  return this.request(url2, { ...init, method: "DELETE" });
34764
34759
  }
34765
34760
  }
34766
- async function createTransport(serverURL, init) {
34767
- return Transport.create(serverURL, init);
34768
- }
34769
34761
  var MAX_PROBLEM_DETAILS_BYTES;
34770
34762
  var init_client3 = __esm(() => {
34771
34763
  init_identity();
@@ -34776,35 +34768,7 @@ var init_client3 = __esm(() => {
34776
34768
  MAX_PROBLEM_DETAILS_BYTES = 64 * 1024;
34777
34769
  });
34778
34770
 
34779
- // node_modules/ehbp/dist/esm/index.js
34780
- var exports_esm = {};
34781
- __export(exports_esm, {
34782
- serializeSessionRecoveryToken: () => serializeSessionRecoveryToken,
34783
- hexToBytes: () => hexToBytes8,
34784
- extractSessionRecoveryToken: () => extractSessionRecoveryToken,
34785
- encryptChunk: () => encryptChunk,
34786
- deserializeSessionRecoveryToken: () => deserializeSessionRecoveryToken,
34787
- deriveResponseKeys: () => deriveResponseKeys,
34788
- decryptResponseWithToken: () => decryptResponseWithToken,
34789
- decryptChunk: () => decryptChunk,
34790
- createTransport: () => createTransport,
34791
- computeNonce: () => computeNonce,
34792
- bytesToHex: () => bytesToHex8,
34793
- Transport: () => Transport,
34794
- RESPONSE_NONCE_LENGTH: () => RESPONSE_NONCE_LENGTH,
34795
- ProtocolError: () => ProtocolError,
34796
- PROTOCOL: () => PROTOCOL,
34797
- KeyConfigMismatchError: () => KeyConfigMismatchError,
34798
- Identity: () => Identity,
34799
- HPKE_REQUEST_INFO: () => HPKE_REQUEST_INFO,
34800
- HPKE_CONFIG: () => HPKE_CONFIG,
34801
- EhbpError: () => EhbpError,
34802
- EXPORT_LENGTH: () => EXPORT_LENGTH,
34803
- EXPORT_LABEL: () => EXPORT_LABEL,
34804
- DecryptionError: () => DecryptionError,
34805
- AES_GCM_NONCE_LENGTH: () => AES_GCM_NONCE_LENGTH,
34806
- AES256_KEY_LENGTH: () => AES256_KEY_LENGTH
34807
- });
34771
+ // node_modules/tinfoil/node_modules/ehbp/dist/esm/index.js
34808
34772
  var init_esm3 = __esm(() => {
34809
34773
  init_identity();
34810
34774
  init_identity();
@@ -64619,6 +64583,650 @@ var init_dist10 = __esm(() => {
64619
64583
  init_openai();
64620
64584
  });
64621
64585
 
64586
+ // node_modules/ehbp/dist/esm/protocol.js
64587
+ var PROTOCOL2, HPKE_CONFIG2;
64588
+ var init_protocol2 = __esm(() => {
64589
+ PROTOCOL2 = {
64590
+ ENCAPSULATED_KEY_HEADER: "Ehbp-Encapsulated-Key",
64591
+ RESPONSE_NONCE_HEADER: "Ehbp-Response-Nonce",
64592
+ KEYS_MEDIA_TYPE: "application/ohttp-keys",
64593
+ KEYS_PATH: "/.well-known/hpke-keys",
64594
+ PROBLEM_JSON_MEDIA_TYPE: "application/problem+json",
64595
+ KEY_CONFIG_PROBLEM_TYPE: "urn:ietf:params:ehbp:error:key-config"
64596
+ };
64597
+ HPKE_CONFIG2 = {
64598
+ KEM: 32,
64599
+ KDF: 1,
64600
+ AEAD: 2
64601
+ };
64602
+ });
64603
+
64604
+ // node_modules/ehbp/dist/esm/derive.js
64605
+ async function deriveResponseKeys2(exportedSecret, requestEnc, responseNonce) {
64606
+ if (exportedSecret.length !== EXPORT_LENGTH2) {
64607
+ throw new Error(`exported secret must be ${EXPORT_LENGTH2} bytes, got ${exportedSecret.length}`);
64608
+ }
64609
+ if (requestEnc.length !== REQUEST_ENC_LENGTH2) {
64610
+ throw new Error(`request enc must be ${REQUEST_ENC_LENGTH2} bytes, got ${requestEnc.length}`);
64611
+ }
64612
+ if (responseNonce.length !== RESPONSE_NONCE_LENGTH2) {
64613
+ throw new Error(`response nonce must be ${RESPONSE_NONCE_LENGTH2} bytes, got ${responseNonce.length}`);
64614
+ }
64615
+ const salt = new Uint8Array(requestEnc.length + responseNonce.length);
64616
+ salt.set(requestEnc, 0);
64617
+ salt.set(responseNonce, requestEnc.length);
64618
+ const prk = await kdf2.Extract(salt, exportedSecret);
64619
+ const keyBytes = await kdf2.Expand(prk, RESPONSE_KEY_LABEL2, AES256_KEY_LENGTH2);
64620
+ const nonceBase = await kdf2.Expand(prk, RESPONSE_NONCE_LABEL2, AES_GCM_NONCE_LENGTH2);
64621
+ return { keyBytes, nonceBase };
64622
+ }
64623
+ function computeNonce2(nonceBase, seq) {
64624
+ if (nonceBase.length !== AES_GCM_NONCE_LENGTH2) {
64625
+ throw new Error(`nonce base must be ${AES_GCM_NONCE_LENGTH2} bytes`);
64626
+ }
64627
+ if (!Number.isInteger(seq) || seq < 0 || seq >= 4294967296) {
64628
+ throw new Error(`sequence number must be an integer in range [0, 2^32): got ${seq}`);
64629
+ }
64630
+ const nonce = new Uint8Array(AES_GCM_NONCE_LENGTH2);
64631
+ nonce.set(nonceBase);
64632
+ for (let i4 = 0;i4 < 8; i4++) {
64633
+ const shift = i4 * 8;
64634
+ if (shift < 32) {
64635
+ nonce[AES_GCM_NONCE_LENGTH2 - 1 - i4] ^= seq >>> shift & 255;
64636
+ }
64637
+ }
64638
+ return nonce;
64639
+ }
64640
+ async function encryptChunk2(km, seq, plaintext) {
64641
+ const nonce = computeNonce2(km.nonceBase, seq);
64642
+ const ciphertext = await aead2.Seal(km.keyBytes, nonce, new Uint8Array(0), plaintext);
64643
+ return ciphertext;
64644
+ }
64645
+ async function decryptChunk2(km, seq, ciphertext) {
64646
+ const nonce = computeNonce2(km.nonceBase, seq);
64647
+ const plaintext = await aead2.Open(km.keyBytes, nonce, new Uint8Array(0), ciphertext);
64648
+ return plaintext;
64649
+ }
64650
+ function hexToBytes10(hex6) {
64651
+ if (hex6.length % 2 !== 0) {
64652
+ throw new Error("Hex string must have even length");
64653
+ }
64654
+ if (!/^[0-9a-fA-F]*$/.test(hex6)) {
64655
+ throw new Error("Invalid hex character");
64656
+ }
64657
+ const bytes6 = new Uint8Array(hex6.length / 2);
64658
+ for (let i4 = 0;i4 < bytes6.length; i4++) {
64659
+ bytes6[i4] = parseInt(hex6.substring(i4 * 2, i4 * 2 + 2), 16);
64660
+ }
64661
+ return bytes6;
64662
+ }
64663
+ function bytesToHex12(bytes6) {
64664
+ return Array.from(bytes6).map((b) => b.toString(16).padStart(2, "0")).join("");
64665
+ }
64666
+ var kdf2, aead2, HPKE_REQUEST_INFO2 = "ehbp request", EXPORT_LABEL2 = "ehbp response", EXPORT_LENGTH2 = 32, RESPONSE_NONCE_LENGTH2 = 32, AES256_KEY_LENGTH2 = 32, AES_GCM_NONCE_LENGTH2 = 12, REQUEST_ENC_LENGTH2 = 32, RESPONSE_KEY_LABEL2, RESPONSE_NONCE_LABEL2;
64667
+ var init_derive2 = __esm(() => {
64668
+ init_hpke_noble();
64669
+ kdf2 = KDF_HKDF_SHA256();
64670
+ aead2 = AEAD_AES_256_GCM();
64671
+ RESPONSE_KEY_LABEL2 = new TextEncoder().encode("key");
64672
+ RESPONSE_NONCE_LABEL2 = new TextEncoder().encode("nonce");
64673
+ });
64674
+
64675
+ // node_modules/ehbp/dist/esm/errors.js
64676
+ var EhbpError2, KeyConfigMismatchError2, ProtocolError2, DecryptionError2;
64677
+ var init_errors6 = __esm(() => {
64678
+ EhbpError2 = class EhbpError2 extends Error {
64679
+ constructor(message, options) {
64680
+ super(message);
64681
+ this.name = "EhbpError";
64682
+ if (options?.cause)
64683
+ this.cause = options.cause;
64684
+ }
64685
+ };
64686
+ KeyConfigMismatchError2 = class KeyConfigMismatchError2 extends EhbpError2 {
64687
+ title;
64688
+ constructor(title) {
64689
+ super(title || "Server key configuration mismatch");
64690
+ this.name = "KeyConfigMismatchError";
64691
+ this.title = title || "";
64692
+ }
64693
+ };
64694
+ ProtocolError2 = class ProtocolError2 extends EhbpError2 {
64695
+ constructor(message, options) {
64696
+ super(message, options);
64697
+ this.name = "ProtocolError";
64698
+ }
64699
+ };
64700
+ DecryptionError2 = class DecryptionError2 extends EhbpError2 {
64701
+ constructor(message, options) {
64702
+ super(message, options);
64703
+ this.name = "DecryptionError";
64704
+ }
64705
+ };
64706
+ });
64707
+
64708
+ // node_modules/ehbp/dist/esm/request-options.js
64709
+ function forwardedRequestInit2(source) {
64710
+ const forwarded = {};
64711
+ if (!source) {
64712
+ return forwarded;
64713
+ }
64714
+ const record2 = source;
64715
+ const target = forwarded;
64716
+ for (const key of FORWARDED_INIT_KEYS2) {
64717
+ const value = record2[key];
64718
+ if (value !== undefined) {
64719
+ target[key] = value;
64720
+ }
64721
+ }
64722
+ if (forwarded.mode === "navigate") {
64723
+ delete forwarded.mode;
64724
+ }
64725
+ return forwarded;
64726
+ }
64727
+ var FORWARDED_INIT_KEYS2;
64728
+ var init_request_options2 = __esm(() => {
64729
+ FORWARDED_INIT_KEYS2 = [
64730
+ "cache",
64731
+ "credentials",
64732
+ "integrity",
64733
+ "keepalive",
64734
+ "mode",
64735
+ "redirect",
64736
+ "referrer",
64737
+ "referrerPolicy",
64738
+ "signal"
64739
+ ];
64740
+ });
64741
+
64742
+ // node_modules/ehbp/dist/esm/identity.js
64743
+ function createSuite2() {
64744
+ return new CipherSuite(KEM_DHKEM_X25519_HKDF_SHA256, KDF_HKDF_SHA256, AEAD_AES_256_GCM);
64745
+ }
64746
+
64747
+ class Identity3 {
64748
+ suite;
64749
+ publicKey;
64750
+ privateKey;
64751
+ constructor(suite, publicKey, privateKey) {
64752
+ this.suite = suite;
64753
+ this.publicKey = publicKey;
64754
+ this.privateKey = privateKey;
64755
+ }
64756
+ static async generate() {
64757
+ const suite = createSuite2();
64758
+ const { publicKey, privateKey } = await suite.GenerateKeyPair(true);
64759
+ return new Identity3(suite, publicKey, privateKey);
64760
+ }
64761
+ static async fromJSON(json3) {
64762
+ const data = JSON.parse(json3);
64763
+ const suite = createSuite2();
64764
+ const publicKey = await suite.DeserializePublicKey(new Uint8Array(data.publicKey));
64765
+ const privateKey = await suite.DeserializePrivateKey(new Uint8Array(data.privateKey), true);
64766
+ return new Identity3(suite, publicKey, privateKey);
64767
+ }
64768
+ async toJSON() {
64769
+ const publicKeyBytes = await this.suite.SerializePublicKey(this.publicKey);
64770
+ const privateKeyBytes = await this.suite.SerializePrivateKey(this.privateKey);
64771
+ return JSON.stringify({
64772
+ publicKey: Array.from(publicKeyBytes),
64773
+ privateKey: Array.from(privateKeyBytes)
64774
+ });
64775
+ }
64776
+ getPublicKey() {
64777
+ return this.publicKey;
64778
+ }
64779
+ async getPublicKeyHex() {
64780
+ const exported = await this.suite.SerializePublicKey(this.publicKey);
64781
+ return bytesToHex12(exported);
64782
+ }
64783
+ getPrivateKey() {
64784
+ return this.privateKey;
64785
+ }
64786
+ async marshalConfig() {
64787
+ const kemId = HPKE_CONFIG2.KEM;
64788
+ const kdfId = HPKE_CONFIG2.KDF;
64789
+ const aeadId = HPKE_CONFIG2.AEAD;
64790
+ const publicKeyBytes = await this.suite.SerializePublicKey(this.publicKey);
64791
+ const keyId = 0;
64792
+ const publicKeySize = publicKeyBytes.length;
64793
+ const cipherSuitesSize = 2 + 2;
64794
+ const buffer = new Uint8Array(1 + 2 + publicKeySize + 2 + cipherSuitesSize);
64795
+ let offset = 0;
64796
+ buffer[offset++] = keyId;
64797
+ buffer[offset++] = kemId >> 8 & 255;
64798
+ buffer[offset++] = kemId & 255;
64799
+ buffer.set(publicKeyBytes, offset);
64800
+ offset += publicKeySize;
64801
+ buffer[offset++] = cipherSuitesSize >> 8 & 255;
64802
+ buffer[offset++] = cipherSuitesSize & 255;
64803
+ buffer[offset++] = kdfId >> 8 & 255;
64804
+ buffer[offset++] = kdfId & 255;
64805
+ buffer[offset++] = aeadId >> 8 & 255;
64806
+ buffer[offset++] = aeadId & 255;
64807
+ return buffer;
64808
+ }
64809
+ static async unmarshalPublicConfig(data) {
64810
+ let offset = 0;
64811
+ const keyId = data[offset++];
64812
+ const kemId = data[offset++] << 8 | data[offset++];
64813
+ const publicKeySize = 32;
64814
+ const publicKeyBytes = data.slice(offset, offset + publicKeySize);
64815
+ offset += publicKeySize;
64816
+ const cipherSuitesLength = data[offset++] << 8 | data[offset++];
64817
+ const suites = [];
64818
+ const cipherSuitesEnd = offset + cipherSuitesLength;
64819
+ while (offset < cipherSuitesEnd) {
64820
+ const kdfId = data[offset++] << 8 | data[offset++];
64821
+ const aeadId = data[offset++] << 8 | data[offset++];
64822
+ suites.push({ kdfId, aeadId });
64823
+ }
64824
+ if (suites.length === 0) {
64825
+ throw new ProtocolError2("No cipher suites found in config");
64826
+ }
64827
+ const firstSuite = suites[0];
64828
+ if (firstSuite.kdfId !== HPKE_CONFIG2.KDF || firstSuite.aeadId !== HPKE_CONFIG2.AEAD) {
64829
+ throw new ProtocolError2(`Unsupported cipher suite: KDF=0x${firstSuite.kdfId.toString(16)}, AEAD=0x${firstSuite.aeadId.toString(16)}`);
64830
+ }
64831
+ return Identity3.fromPublicKeyBytes(publicKeyBytes);
64832
+ }
64833
+ static async fromPublicKeyHex(publicKeyHex) {
64834
+ const publicKeyBytes = hexToBytes10(publicKeyHex);
64835
+ if (publicKeyBytes.length !== 32) {
64836
+ throw new ProtocolError2(`Invalid public key length: expected 32, got ${publicKeyBytes.length}`);
64837
+ }
64838
+ return Identity3.fromPublicKeyBytes(publicKeyBytes);
64839
+ }
64840
+ static async fromPublicKeyBytes(publicKeyBytes) {
64841
+ const suite = createSuite2();
64842
+ const publicKey = await suite.DeserializePublicKey(publicKeyBytes);
64843
+ const placeholderPrivateKey = await suite.DeserializePrivateKey(new Uint8Array(32), false);
64844
+ return new Identity3(suite, publicKey, placeholderPrivateKey);
64845
+ }
64846
+ async encryptRequestWithContext(request) {
64847
+ const body = await request.arrayBuffer();
64848
+ if (body.byteLength === 0) {
64849
+ return {
64850
+ request: new Request(request.url, {
64851
+ ...forwardedRequestInit2(request),
64852
+ method: request.method,
64853
+ headers: request.headers,
64854
+ body: null
64855
+ }),
64856
+ context: null
64857
+ };
64858
+ }
64859
+ const infoBytes = new TextEncoder().encode(HPKE_REQUEST_INFO2);
64860
+ const { encapsulatedSecret, ctx } = await this.suite.SetupSender(this.publicKey, {
64861
+ info: infoBytes
64862
+ });
64863
+ const context = {
64864
+ senderContext: ctx,
64865
+ requestEnc: encapsulatedSecret
64866
+ };
64867
+ const headers = new Headers(request.headers);
64868
+ headers.set(PROTOCOL2.ENCAPSULATED_KEY_HEADER, bytesToHex12(context.requestEnc));
64869
+ const encrypted = await ctx.Seal(new Uint8Array(body));
64870
+ const chunkLength = new Uint8Array(4);
64871
+ new DataView(chunkLength.buffer).setUint32(0, encrypted.byteLength, false);
64872
+ const chunkedData = new Uint8Array(4 + encrypted.byteLength);
64873
+ chunkedData.set(chunkLength, 0);
64874
+ chunkedData.set(encrypted, 4);
64875
+ return {
64876
+ request: new Request(request.url, {
64877
+ ...forwardedRequestInit2(request),
64878
+ method: request.method,
64879
+ headers,
64880
+ body: chunkedData,
64881
+ duplex: "half"
64882
+ }),
64883
+ context
64884
+ };
64885
+ }
64886
+ async decryptResponseWithContext(response, context) {
64887
+ const token = await extractSessionRecoveryToken2(context);
64888
+ return decryptResponseWithToken2(response, token);
64889
+ }
64890
+ }
64891
+ async function extractSessionRecoveryToken2(context) {
64892
+ const exportLabelBytes = new TextEncoder().encode(EXPORT_LABEL2);
64893
+ const exportedSecret = new Uint8Array(await context.senderContext.Export(exportLabelBytes, EXPORT_LENGTH2));
64894
+ return {
64895
+ exportedSecret,
64896
+ requestEnc: new Uint8Array(context.requestEnc)
64897
+ };
64898
+ }
64899
+ function serializeSessionRecoveryToken2(token) {
64900
+ return JSON.stringify({
64901
+ exportedSecret: bytesToHex12(token.exportedSecret),
64902
+ requestEnc: bytesToHex12(token.requestEnc)
64903
+ });
64904
+ }
64905
+ function deserializeSessionRecoveryToken2(json3) {
64906
+ const parsed = JSON.parse(json3);
64907
+ return {
64908
+ exportedSecret: hexToBytes10(parsed.exportedSecret),
64909
+ requestEnc: hexToBytes10(parsed.requestEnc)
64910
+ };
64911
+ }
64912
+ async function decryptResponseWithToken2(response, token, onStreamError, onStreamComplete) {
64913
+ const responseNonceHex = response.headers.get(PROTOCOL2.RESPONSE_NONCE_HEADER);
64914
+ if (!response.body && !responseNonceHex) {
64915
+ return response;
64916
+ }
64917
+ if (!responseNonceHex) {
64918
+ throw new ProtocolError2(`Missing ${PROTOCOL2.RESPONSE_NONCE_HEADER} header`);
64919
+ }
64920
+ const responseNonce = hexToBytes10(responseNonceHex);
64921
+ if (responseNonce.length !== RESPONSE_NONCE_LENGTH2) {
64922
+ throw new ProtocolError2(`Invalid response nonce length`);
64923
+ }
64924
+ if (!response.body) {
64925
+ onStreamComplete?.();
64926
+ return response;
64927
+ }
64928
+ const km = await deriveResponseKeys2(token.exportedSecret, token.requestEnc, responseNonce);
64929
+ const decryptedStream = createDecryptStream2(response.body, km, onStreamError, onStreamComplete);
64930
+ const headers = new Headers(response.headers);
64931
+ headers.delete("content-length");
64932
+ headers.delete("transfer-encoding");
64933
+ return new Response(decryptedStream, {
64934
+ status: response.status,
64935
+ statusText: response.statusText,
64936
+ headers
64937
+ });
64938
+ }
64939
+ function createDecryptStream2(body, km, onStreamError, onStreamComplete) {
64940
+ let buffer = new Uint8Array(0);
64941
+ let seq = 0;
64942
+ const reader = body.getReader();
64943
+ let consumerCancelled = false;
64944
+ return new ReadableStream({
64945
+ async pull(controller) {
64946
+ const fail = (error53) => {
64947
+ try {
64948
+ onStreamError?.();
64949
+ } catch {}
64950
+ try {
64951
+ controller.error(error53);
64952
+ } finally {
64953
+ reader.cancel(error53).catch(() => {});
64954
+ }
64955
+ };
64956
+ while (true) {
64957
+ if (buffer.length >= 4) {
64958
+ const chunkLength = (buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]) >>> 0;
64959
+ if (chunkLength === 0) {
64960
+ buffer = buffer.slice(4);
64961
+ continue;
64962
+ }
64963
+ if (chunkLength > MAX_RESPONSE_CHUNK_BYTES2) {
64964
+ fail(new ProtocolError2("response chunk exceeds maximum allowed size"));
64965
+ return;
64966
+ }
64967
+ if (buffer.length >= 4 + chunkLength) {
64968
+ const ciphertext = buffer.slice(4, 4 + chunkLength);
64969
+ buffer = buffer.slice(4 + chunkLength);
64970
+ try {
64971
+ const plaintext = await decryptChunk2(km, seq++, ciphertext);
64972
+ controller.enqueue(plaintext);
64973
+ return;
64974
+ } catch (error53) {
64975
+ fail(new DecryptionError2(`Decryption failed at chunk ${seq - 1}`, { cause: error53 }));
64976
+ return;
64977
+ }
64978
+ }
64979
+ }
64980
+ let result;
64981
+ try {
64982
+ result = await reader.read();
64983
+ } catch (error53) {
64984
+ if (consumerCancelled) {
64985
+ return;
64986
+ }
64987
+ fail(error53 instanceof Error ? error53 : new Error("Encrypted response read failed", {
64988
+ cause: error53
64989
+ }));
64990
+ return;
64991
+ }
64992
+ const { done, value } = result;
64993
+ if (done) {
64994
+ if (consumerCancelled) {
64995
+ return;
64996
+ }
64997
+ if (buffer.length !== 0) {
64998
+ fail(new ProtocolError2("truncated encrypted response chunk"));
64999
+ } else {
65000
+ onStreamComplete?.();
65001
+ controller.close();
65002
+ }
65003
+ return;
65004
+ }
65005
+ const newBuffer = new Uint8Array(buffer.length + value.length);
65006
+ newBuffer.set(buffer);
65007
+ newBuffer.set(value, buffer.length);
65008
+ buffer = newBuffer;
65009
+ }
65010
+ },
65011
+ cancel(reason) {
65012
+ consumerCancelled = true;
65013
+ return reader.cancel(reason);
65014
+ }
65015
+ });
65016
+ }
65017
+ var MAX_RESPONSE_CHUNK_BYTES2;
65018
+ var init_identity2 = __esm(() => {
65019
+ init_hpke();
65020
+ init_hpke_noble();
65021
+ init_protocol2();
65022
+ init_derive2();
65023
+ init_errors6();
65024
+ init_request_options2();
65025
+ MAX_RESPONSE_CHUNK_BYTES2 = 64 * 1024 * 1024;
65026
+ });
65027
+
65028
+ // node_modules/ehbp/dist/esm/client.js
65029
+ class Transport2 {
65030
+ serverIdentity;
65031
+ serverHost;
65032
+ _lastSessionRecoveryToken;
65033
+ requestGeneration = 0;
65034
+ constructor(serverIdentity, serverHost) {
65035
+ this.serverIdentity = serverIdentity;
65036
+ this.serverHost = serverHost;
65037
+ }
65038
+ getSessionRecoveryToken() {
65039
+ if (!this._lastSessionRecoveryToken) {
65040
+ throw new Error("No session recovery token available \u2014 no request has been made yet");
65041
+ }
65042
+ return this._lastSessionRecoveryToken;
65043
+ }
65044
+ static async create(serverURL, init) {
65045
+ const url3 = new URL(serverURL);
65046
+ const serverHost = url3.host;
65047
+ const keysURL = new URL(PROTOCOL2.KEYS_PATH, serverURL);
65048
+ const response = await fetch(keysURL.toString(), init);
65049
+ if (!response.ok) {
65050
+ throw new Error(`Failed to get server public key: ${response.status}`);
65051
+ }
65052
+ const contentType = response.headers.get("content-type");
65053
+ if (contentType !== PROTOCOL2.KEYS_MEDIA_TYPE) {
65054
+ throw new Error(`Invalid content type: ${contentType}`);
65055
+ }
65056
+ const keysData = new Uint8Array(await response.arrayBuffer());
65057
+ const serverIdentity = await Identity3.unmarshalPublicConfig(keysData);
65058
+ return new Transport2(serverIdentity, serverHost);
65059
+ }
65060
+ static isProblemJSONContentType(contentType) {
65061
+ if (!contentType) {
65062
+ return false;
65063
+ }
65064
+ const mediaType = contentType.split(";", 1)[0]?.trim().toLowerCase() ?? "";
65065
+ return mediaType === PROTOCOL2.PROBLEM_JSON_MEDIA_TYPE;
65066
+ }
65067
+ static async checkKeyConfigMismatch(response) {
65068
+ if (response.status !== 422)
65069
+ return;
65070
+ if (!Transport2.isProblemJSONContentType(response.headers.get("content-type")))
65071
+ return;
65072
+ let problem;
65073
+ try {
65074
+ const clone2 = response.clone();
65075
+ if (!clone2.body)
65076
+ return;
65077
+ const reader = clone2.body.getReader();
65078
+ const chunks = [];
65079
+ let length2 = 0;
65080
+ while (true) {
65081
+ const { done, value } = await reader.read();
65082
+ if (done)
65083
+ break;
65084
+ length2 += value.byteLength;
65085
+ if (length2 > MAX_PROBLEM_DETAILS_BYTES2) {
65086
+ reader.cancel().catch(() => {});
65087
+ return;
65088
+ }
65089
+ chunks.push(value);
65090
+ }
65091
+ const body = new Uint8Array(length2);
65092
+ let offset = 0;
65093
+ for (const chunk of chunks) {
65094
+ body.set(chunk, offset);
65095
+ offset += chunk.byteLength;
65096
+ }
65097
+ problem = JSON.parse(new TextDecoder().decode(body));
65098
+ } catch {
65099
+ return;
65100
+ }
65101
+ if (problem?.type === PROTOCOL2.KEY_CONFIG_PROBLEM_TYPE) {
65102
+ throw new KeyConfigMismatchError2(typeof problem.title === "string" ? problem.title : undefined);
65103
+ }
65104
+ }
65105
+ static async shouldDecryptResponse(response) {
65106
+ if (response.headers.has(PROTOCOL2.RESPONSE_NONCE_HEADER)) {
65107
+ return true;
65108
+ }
65109
+ await Transport2.checkKeyConfigMismatch(response);
65110
+ if (!response.ok) {
65111
+ return false;
65112
+ }
65113
+ throw new ProtocolError2(`Missing ${PROTOCOL2.RESPONSE_NONCE_HEADER} header`);
65114
+ }
65115
+ getServerIdentity() {
65116
+ return this.serverIdentity;
65117
+ }
65118
+ getServerPublicKey() {
65119
+ return this.serverIdentity.getPublicKey();
65120
+ }
65121
+ async getServerPublicKeyHex() {
65122
+ return this.serverIdentity.getPublicKeyHex();
65123
+ }
65124
+ async request(input, init) {
65125
+ const generation = ++this.requestGeneration;
65126
+ this._lastSessionRecoveryToken = undefined;
65127
+ const inputUrl = input instanceof Request ? input.url : String(input);
65128
+ if (inputUrl.startsWith("data:") || inputUrl.startsWith("blob:")) {
65129
+ return fetch(input, init);
65130
+ }
65131
+ const normalizedRequest = new Request(input, init);
65132
+ const requestBodyBytes = await normalizedRequest.arrayBuffer();
65133
+ const requestBody = requestBodyBytes.byteLength > 0 ? requestBodyBytes : null;
65134
+ const url3 = new URL(normalizedRequest.url);
65135
+ url3.host = this.serverHost;
65136
+ const request = new Request(url3.toString(), {
65137
+ ...forwardedRequestInit2(normalizedRequest),
65138
+ method: normalizedRequest.method,
65139
+ headers: normalizedRequest.headers,
65140
+ body: requestBody,
65141
+ duplex: "half"
65142
+ });
65143
+ const { request: encryptedRequest, context } = await this.serverIdentity.encryptRequestWithContext(request);
65144
+ const token = context ? await extractSessionRecoveryToken2(context) : undefined;
65145
+ const response = await fetch(encryptedRequest);
65146
+ if (!token) {
65147
+ return response;
65148
+ }
65149
+ const shouldDecrypt = await Transport2.shouldDecryptResponse(response);
65150
+ if (!shouldDecrypt) {
65151
+ return response;
65152
+ }
65153
+ let streamTerminated = false;
65154
+ const clearToken = () => {
65155
+ streamTerminated = true;
65156
+ if (this.requestGeneration === generation) {
65157
+ this._lastSessionRecoveryToken = undefined;
65158
+ }
65159
+ };
65160
+ const decryptedResponse = await decryptResponseWithToken2(response, token, clearToken, clearToken);
65161
+ if (this.requestGeneration === generation) {
65162
+ this._lastSessionRecoveryToken = streamTerminated ? undefined : token;
65163
+ }
65164
+ return decryptedResponse;
65165
+ }
65166
+ async get(url3, init) {
65167
+ return this.request(url3, { ...init, method: "GET" });
65168
+ }
65169
+ async post(url3, body, init) {
65170
+ return this.request(url3, { ...init, method: "POST", body });
65171
+ }
65172
+ async put(url3, body, init) {
65173
+ return this.request(url3, { ...init, method: "PUT", body });
65174
+ }
65175
+ async delete(url3, init) {
65176
+ return this.request(url3, { ...init, method: "DELETE" });
65177
+ }
65178
+ }
65179
+ async function createTransport2(serverURL, init) {
65180
+ return Transport2.create(serverURL, init);
65181
+ }
65182
+ var MAX_PROBLEM_DETAILS_BYTES2;
65183
+ var init_client5 = __esm(() => {
65184
+ init_identity2();
65185
+ init_identity2();
65186
+ init_protocol2();
65187
+ init_request_options2();
65188
+ init_errors6();
65189
+ MAX_PROBLEM_DETAILS_BYTES2 = 64 * 1024;
65190
+ });
65191
+
65192
+ // node_modules/ehbp/dist/esm/index.js
65193
+ var exports_esm = {};
65194
+ __export(exports_esm, {
65195
+ serializeSessionRecoveryToken: () => serializeSessionRecoveryToken2,
65196
+ hexToBytes: () => hexToBytes10,
65197
+ extractSessionRecoveryToken: () => extractSessionRecoveryToken2,
65198
+ encryptChunk: () => encryptChunk2,
65199
+ deserializeSessionRecoveryToken: () => deserializeSessionRecoveryToken2,
65200
+ deriveResponseKeys: () => deriveResponseKeys2,
65201
+ decryptResponseWithToken: () => decryptResponseWithToken2,
65202
+ decryptChunk: () => decryptChunk2,
65203
+ createTransport: () => createTransport2,
65204
+ computeNonce: () => computeNonce2,
65205
+ bytesToHex: () => bytesToHex12,
65206
+ Transport: () => Transport2,
65207
+ RESPONSE_NONCE_LENGTH: () => RESPONSE_NONCE_LENGTH2,
65208
+ ProtocolError: () => ProtocolError2,
65209
+ PROTOCOL: () => PROTOCOL2,
65210
+ KeyConfigMismatchError: () => KeyConfigMismatchError2,
65211
+ Identity: () => Identity3,
65212
+ HPKE_REQUEST_INFO: () => HPKE_REQUEST_INFO2,
65213
+ HPKE_CONFIG: () => HPKE_CONFIG2,
65214
+ EhbpError: () => EhbpError2,
65215
+ EXPORT_LENGTH: () => EXPORT_LENGTH2,
65216
+ EXPORT_LABEL: () => EXPORT_LABEL2,
65217
+ DecryptionError: () => DecryptionError2,
65218
+ AES_GCM_NONCE_LENGTH: () => AES_GCM_NONCE_LENGTH2,
65219
+ AES256_KEY_LENGTH: () => AES256_KEY_LENGTH2
65220
+ });
65221
+ var init_esm4 = __esm(() => {
65222
+ init_identity2();
65223
+ init_identity2();
65224
+ init_client5();
65225
+ init_protocol2();
65226
+ init_errors6();
65227
+ init_derive2();
65228
+ });
65229
+
64622
65230
  // node_modules/applesauce-sqlite/node_modules/applesauce-core/dist/factories/types.js
64623
65231
  var init_types4 = () => {};
64624
65232
 
@@ -64999,20 +65607,20 @@ __export(exports_utils3, {
64999
65607
  numberToBytesLE: () => numberToBytesLE5,
65000
65608
  numberToBytesBE: () => numberToBytesBE5,
65001
65609
  hexToNumber: () => hexToNumber5,
65002
- hexToBytes: () => hexToBytes10,
65610
+ hexToBytes: () => hexToBytes11,
65003
65611
  equalBytes: () => equalBytes7,
65004
65612
  ensureBytes: () => ensureBytes4,
65005
65613
  createHmacDrbg: () => createHmacDrbg5,
65006
65614
  concatBytes: () => concatBytes12,
65007
65615
  bytesToNumberLE: () => bytesToNumberLE5,
65008
65616
  bytesToNumberBE: () => bytesToNumberBE5,
65009
- bytesToHex: () => bytesToHex12,
65617
+ bytesToHex: () => bytesToHex13,
65010
65618
  bitSet: () => bitSet3,
65011
65619
  bitMask: () => bitMask5,
65012
65620
  bitLen: () => bitLen5,
65013
65621
  bitGet: () => bitGet3
65014
65622
  });
65015
- function bytesToHex12(bytes7) {
65623
+ function bytesToHex13(bytes7) {
65016
65624
  if (!u8a8(bytes7))
65017
65625
  throw new Error("Uint8Array expected");
65018
65626
  let hex6 = "";
@@ -65030,7 +65638,7 @@ function hexToNumber5(hex6) {
65030
65638
  throw new Error("hex string expected, got " + typeof hex6);
65031
65639
  return BigInt(hex6 === "" ? "0" : `0x${hex6}`);
65032
65640
  }
65033
- function hexToBytes10(hex6) {
65641
+ function hexToBytes11(hex6) {
65034
65642
  if (typeof hex6 !== "string")
65035
65643
  throw new Error("hex string expected, got " + typeof hex6);
65036
65644
  const len = hex6.length;
@@ -65048,27 +65656,27 @@ function hexToBytes10(hex6) {
65048
65656
  return array2;
65049
65657
  }
65050
65658
  function bytesToNumberBE5(bytes7) {
65051
- return hexToNumber5(bytesToHex12(bytes7));
65659
+ return hexToNumber5(bytesToHex13(bytes7));
65052
65660
  }
65053
65661
  function bytesToNumberLE5(bytes7) {
65054
65662
  if (!u8a8(bytes7))
65055
65663
  throw new Error("Uint8Array expected");
65056
- return hexToNumber5(bytesToHex12(Uint8Array.from(bytes7).reverse()));
65664
+ return hexToNumber5(bytesToHex13(Uint8Array.from(bytes7).reverse()));
65057
65665
  }
65058
65666
  function numberToBytesBE5(n, len) {
65059
- return hexToBytes10(n.toString(16).padStart(len * 2, "0"));
65667
+ return hexToBytes11(n.toString(16).padStart(len * 2, "0"));
65060
65668
  }
65061
65669
  function numberToBytesLE5(n, len) {
65062
65670
  return numberToBytesBE5(n, len).reverse();
65063
65671
  }
65064
65672
  function numberToVarBytesBE3(n) {
65065
- return hexToBytes10(numberToHexUnpadded5(n));
65673
+ return hexToBytes11(numberToHexUnpadded5(n));
65066
65674
  }
65067
65675
  function ensureBytes4(title, hex6, expectedLength) {
65068
65676
  let res;
65069
65677
  if (typeof hex6 === "string") {
65070
65678
  try {
65071
- res = hexToBytes10(hex6);
65679
+ res = hexToBytes11(hex6);
65072
65680
  } catch (e13) {
65073
65681
  throw new Error(`${title} must be valid hex string, got "${hex6}". Cause: ${e13}`);
65074
65682
  }
@@ -65634,7 +66242,7 @@ function weierstrassPoints3(opts) {
65634
66242
  const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
65635
66243
  if (lengths && typeof key !== "bigint") {
65636
66244
  if (key instanceof Uint8Array)
65637
- key = bytesToHex12(key);
66245
+ key = bytesToHex13(key);
65638
66246
  if (typeof key !== "string" || !lengths.includes(key.length))
65639
66247
  throw new Error("Invalid key");
65640
66248
  key = key.padStart(nByteLength * 2, "0");
@@ -65925,7 +66533,7 @@ function weierstrassPoints3(opts) {
65925
66533
  return toBytes9(Point4, this, isCompressed);
65926
66534
  }
65927
66535
  toHex(isCompressed = true) {
65928
- return bytesToHex12(this.toRawBytes(isCompressed));
66536
+ return bytesToHex13(this.toRawBytes(isCompressed));
65929
66537
  }
65930
66538
  }
65931
66539
  Point4.BASE = new Point4(CURVE.Gx, CURVE.Gy, Fp5.ONE);
@@ -66003,7 +66611,7 @@ function weierstrass5(curveDef) {
66003
66611
  }
66004
66612
  }
66005
66613
  });
66006
- const numToNByteStr = (num2) => bytesToHex12(numberToBytesBE5(num2, CURVE.nByteLength));
66614
+ const numToNByteStr = (num2) => bytesToHex13(numberToBytesBE5(num2, CURVE.nByteLength));
66007
66615
  function isBiggerThanHalfOrder(number10) {
66008
66616
  const HALF = CURVE_ORDER >> _1n27;
66009
66617
  return number10 > HALF;
@@ -66064,13 +66672,13 @@ function weierstrass5(curveDef) {
66064
66672
  return this.hasHighS() ? new Signature(this.r, modN3(-this.s), this.recovery) : this;
66065
66673
  }
66066
66674
  toDERRawBytes() {
66067
- return hexToBytes10(this.toDERHex());
66675
+ return hexToBytes11(this.toDERHex());
66068
66676
  }
66069
66677
  toDERHex() {
66070
66678
  return DER5.hexFromSig({ r: this.r, s: this.s });
66071
66679
  }
66072
66680
  toCompactRawBytes() {
66073
- return hexToBytes10(this.toCompactHex());
66681
+ return hexToBytes11(this.toCompactHex());
66074
66682
  }
66075
66683
  toCompactHex() {
66076
66684
  return numToNByteStr(this.r) + numToNByteStr(this.s);
@@ -66565,7 +67173,7 @@ var init_cryptoNode5 = __esm(() => {
66565
67173
  });
66566
67174
 
66567
67175
  // node_modules/applesauce-sqlite/node_modules/applesauce-core/node_modules/nostr-tools/node_modules/@noble/hashes/esm/utils.js
66568
- function bytesToHex13(bytes7) {
67176
+ function bytesToHex14(bytes7) {
66569
67177
  if (!u8a9(bytes7))
66570
67178
  throw new Error("Uint8Array expected");
66571
67179
  let hex6 = "";
@@ -66574,7 +67182,7 @@ function bytesToHex13(bytes7) {
66574
67182
  }
66575
67183
  return hex6;
66576
67184
  }
66577
- function hexToBytes11(hex6) {
67185
+ function hexToBytes12(hex6) {
66578
67186
  if (typeof hex6 !== "string")
66579
67187
  throw new Error("hex string expected, got " + typeof hex6);
66580
67188
  const len = hex6.length;
@@ -67256,7 +67864,7 @@ function genBech324(encoding2) {
67256
67864
  return { encode: encode5, decode: decode4, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };
67257
67865
  }
67258
67866
  var gcd4 = (a, b) => !b ? a : gcd4(b, a % b), radix2carry4 = (from7, to) => from7 + (to - gcd4(from7, to)), base164, base324, base32hex4, base32crockford4, base647, base64url6, genBase584 = (abc) => chain4(radix6(58), alphabet4(abc), join5("")), base584, base58flickr4, base58xrp4, XMR_BLOCK_LEN3, base58xmr3, BECH_ALPHABET4, POLYMOD_GENERATORS4, bech324, bech32m4, utf83, hex6, CODERS3, coderTypeError3;
67259
- var init_esm4 = __esm(() => {
67867
+ var init_esm5 = __esm(() => {
67260
67868
  /*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
67261
67869
  base164 = chain4(radix24(4), alphabet4("0123456789ABCDEF"), join5(""));
67262
67870
  base324 = chain4(radix24(5), alphabet4("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), padding4(5), join5(""));
@@ -67352,7 +67960,7 @@ function output8(out, instance) {
67352
67960
  var init__assert6 = () => {};
67353
67961
 
67354
67962
  // node_modules/applesauce-sqlite/node_modules/applesauce-core/node_modules/nostr-tools/node_modules/@noble/ciphers/esm/utils.js
67355
- function bytesToHex14(bytes9) {
67963
+ function bytesToHex15(bytes9) {
67356
67964
  bytes8(bytes9);
67357
67965
  let hex7 = "";
67358
67966
  for (let i4 = 0;i4 < bytes9.length; i4++) {
@@ -67369,7 +67977,7 @@ function asciiToBase164(char) {
67369
67977
  return char - (asciis4._a - 10);
67370
67978
  return;
67371
67979
  }
67372
- function hexToBytes12(hex7) {
67980
+ function hexToBytes13(hex7) {
67373
67981
  if (typeof hex7 !== "string")
67374
67982
  throw new Error("hex string expected, got " + typeof hex7);
67375
67983
  const hl = hex7.length;
@@ -68999,7 +69607,7 @@ function serializeEvent4(evt) {
68999
69607
  }
69000
69608
  function getEventHash4(event3) {
69001
69609
  let eventHash = sha2569(utf8Encoder5.encode(serializeEvent4(event3)));
69002
- return bytesToHex13(eventHash);
69610
+ return bytesToHex14(eventHash);
69003
69611
  }
69004
69612
  function isRegularKind4(kind) {
69005
69613
  return kind < 1e4 && kind !== 0 && kind !== 3;
@@ -69164,7 +69772,7 @@ function decode4(code) {
69164
69772
  return {
69165
69773
  type: "nprofile",
69166
69774
  data: {
69167
- pubkey: bytesToHex13(tlv[0][0]),
69775
+ pubkey: bytesToHex14(tlv[0][0]),
69168
69776
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder5.decode(d)) : []
69169
69777
  }
69170
69778
  };
@@ -69182,10 +69790,10 @@ function decode4(code) {
69182
69790
  return {
69183
69791
  type: "nevent",
69184
69792
  data: {
69185
- id: bytesToHex13(tlv[0][0]),
69793
+ id: bytesToHex14(tlv[0][0]),
69186
69794
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder5.decode(d)) : [],
69187
- author: tlv[2]?.[0] ? bytesToHex13(tlv[2][0]) : undefined,
69188
- kind: tlv[3]?.[0] ? parseInt(bytesToHex13(tlv[3][0]), 16) : undefined
69795
+ author: tlv[2]?.[0] ? bytesToHex14(tlv[2][0]) : undefined,
69796
+ kind: tlv[3]?.[0] ? parseInt(bytesToHex14(tlv[3][0]), 16) : undefined
69189
69797
  }
69190
69798
  };
69191
69799
  }
@@ -69205,8 +69813,8 @@ function decode4(code) {
69205
69813
  type: "naddr",
69206
69814
  data: {
69207
69815
  identifier: utf8Decoder5.decode(tlv[0][0]),
69208
- pubkey: bytesToHex13(tlv[2][0]),
69209
- kind: parseInt(bytesToHex13(tlv[3][0]), 16),
69816
+ pubkey: bytesToHex14(tlv[2][0]),
69817
+ kind: parseInt(bytesToHex14(tlv[3][0]), 16),
69210
69818
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder5.decode(d)) : []
69211
69819
  }
69212
69820
  };
@@ -69215,7 +69823,7 @@ function decode4(code) {
69215
69823
  return { type: prefix, data };
69216
69824
  case "npub":
69217
69825
  case "note":
69218
- return { type: prefix, data: bytesToHex13(data) };
69826
+ return { type: prefix, data: bytesToHex14(data) };
69219
69827
  default:
69220
69828
  throw new Error(`unknown prefix ${prefix}`);
69221
69829
  }
@@ -69239,10 +69847,10 @@ function nsecEncode2(key) {
69239
69847
  return encodeBytes2("nsec", key);
69240
69848
  }
69241
69849
  function npubEncode3(hex7) {
69242
- return encodeBytes2("npub", hexToBytes11(hex7));
69850
+ return encodeBytes2("npub", hexToBytes12(hex7));
69243
69851
  }
69244
69852
  function noteEncode2(hex7) {
69245
- return encodeBytes2("note", hexToBytes11(hex7));
69853
+ return encodeBytes2("note", hexToBytes12(hex7));
69246
69854
  }
69247
69855
  function encodeBech322(prefix, data) {
69248
69856
  let words = bech324.toWords(data);
@@ -69253,7 +69861,7 @@ function encodeBytes2(prefix, bytes9) {
69253
69861
  }
69254
69862
  function nprofileEncode2(profile3) {
69255
69863
  let data = encodeTLV2({
69256
- 0: [hexToBytes11(profile3.pubkey)],
69864
+ 0: [hexToBytes12(profile3.pubkey)],
69257
69865
  1: (profile3.relays || []).map((url3) => utf8Encoder5.encode(url3))
69258
69866
  });
69259
69867
  return encodeBech322("nprofile", data);
@@ -69264,9 +69872,9 @@ function neventEncode2(event3) {
69264
69872
  kindArray = integerToUint8Array2(event3.kind);
69265
69873
  }
69266
69874
  let data = encodeTLV2({
69267
- 0: [hexToBytes11(event3.id)],
69875
+ 0: [hexToBytes12(event3.id)],
69268
69876
  1: (event3.relays || []).map((url3) => utf8Encoder5.encode(url3)),
69269
- 2: event3.author ? [hexToBytes11(event3.author)] : [],
69877
+ 2: event3.author ? [hexToBytes12(event3.author)] : [],
69270
69878
  3: kindArray ? [new Uint8Array(kindArray)] : []
69271
69879
  });
69272
69880
  return encodeBech322("nevent", data);
@@ -69277,7 +69885,7 @@ function naddrEncode2(addr) {
69277
69885
  let data = encodeTLV2({
69278
69886
  0: [utf8Encoder5.encode(addr.identifier)],
69279
69887
  1: (addr.relays || []).map((url3) => utf8Encoder5.encode(url3)),
69280
- 2: [hexToBytes11(addr.pubkey)],
69888
+ 2: [hexToBytes12(addr.pubkey)],
69281
69889
  3: [new Uint8Array(kind)]
69282
69890
  });
69283
69891
  return encodeBech322("naddr", data);
@@ -69296,7 +69904,7 @@ function encodeTLV2(tlv) {
69296
69904
  return concatBytes13(...entries);
69297
69905
  }
69298
69906
  function encrypt5(secretKey, pubkey, text) {
69299
- const privkey = secretKey instanceof Uint8Array ? bytesToHex13(secretKey) : secretKey;
69907
+ const privkey = secretKey instanceof Uint8Array ? bytesToHex14(secretKey) : secretKey;
69300
69908
  const key = secp256k14.getSharedSecret(privkey, "02" + pubkey);
69301
69909
  const normalizedKey = getNormalizedX2(key);
69302
69910
  let iv = Uint8Array.from(randomBytes8(16));
@@ -69307,7 +69915,7 @@ function encrypt5(secretKey, pubkey, text) {
69307
69915
  return `${ctb64}?iv=${ivb64}`;
69308
69916
  }
69309
69917
  function decrypt4(secretKey, pubkey, data) {
69310
- const privkey = secretKey instanceof Uint8Array ? bytesToHex13(secretKey) : secretKey;
69918
+ const privkey = secretKey instanceof Uint8Array ? bytesToHex14(secretKey) : secretKey;
69311
69919
  let [ctb64, ivb64] = data.split("?iv=");
69312
69920
  let key = secp256k14.getSharedSecret(privkey, "02" + pubkey);
69313
69921
  let normalizedKey = getNormalizedX2(key);
@@ -69496,7 +70104,7 @@ function minePow2(unsigned, difficulty) {
69496
70104
  return event3;
69497
70105
  }
69498
70106
  function fastEventHash2(evt) {
69499
- return bytesToHex13(sha2569(utf8Encoder5.encode(JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]))));
70107
+ return bytesToHex14(sha2569(utf8Encoder5.encode(JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]))));
69500
70108
  }
69501
70109
  function getConversationKey2(privkeyA, pubkeyB) {
69502
70110
  const sharedX = secp256k14.getSharedSecret(privkeyA, "02" + pubkeyB).subarray(1, 33);
@@ -70244,7 +70852,7 @@ function validateEventMethodTag2(event3, method) {
70244
70852
  }
70245
70853
  function hashPayload3(payload) {
70246
70854
  const hash8 = sha2569(utf8Encoder5.encode(JSON.stringify(payload)));
70247
- return bytesToHex13(hash8);
70855
+ return bytesToHex14(hash8);
70248
70856
  }
70249
70857
  function validateEventPayloadTag2(event3, payload) {
70250
70858
  const payloadTag = event3.tags.find((t) => t[0] === "payload");
@@ -70331,13 +70939,13 @@ var __defProp3, __export3 = (target, all) => {
70331
70939
  return schnorr4.utils.randomPrivateKey();
70332
70940
  }
70333
70941
  getPublicKey(secretKey) {
70334
- return bytesToHex13(schnorr4.getPublicKey(secretKey));
70942
+ return bytesToHex14(schnorr4.getPublicKey(secretKey));
70335
70943
  }
70336
70944
  finalizeEvent(t, secretKey) {
70337
70945
  const event3 = t;
70338
- event3.pubkey = bytesToHex13(schnorr4.getPublicKey(secretKey));
70946
+ event3.pubkey = bytesToHex14(schnorr4.getPublicKey(secretKey));
70339
70947
  event3.id = getEventHash4(event3);
70340
- event3.sig = bytesToHex13(schnorr4.sign(getEventHash4(event3), secretKey));
70948
+ event3.sig = bytesToHex14(schnorr4.sign(getEventHash4(event3), secretKey));
70341
70949
  event3[verifiedSymbol6] = true;
70342
70950
  return event3;
70343
70951
  }
@@ -70960,7 +71568,7 @@ var __defProp3, __export3 = (target, all) => {
70960
71568
  insert(timestamp, id) {
70961
71569
  if (this.sealed)
70962
71570
  throw Error("already sealed");
70963
- const idb = hexToBytes12(id);
71571
+ const idb = hexToBytes13(id);
70964
71572
  if (idb.byteLength !== ID_SIZE3)
70965
71573
  throw Error("bad id size for added item");
70966
71574
  this.items.push({ timestamp, id: idb });
@@ -71053,10 +71661,10 @@ var __defProp3, __export3 = (target, all) => {
71053
71661
  let output9 = new WrappedBuffer3;
71054
71662
  output9.extend(new Uint8Array([PROTOCOL_VERSION3]));
71055
71663
  this.splitRange(0, this.storage.size(), this._bound(Number.MAX_VALUE), output9);
71056
- return bytesToHex14(output9.unwrap());
71664
+ return bytesToHex15(output9.unwrap());
71057
71665
  }
71058
71666
  reconcile(queryMsg, onhave, onneed) {
71059
- const query2 = new WrappedBuffer3(hexToBytes12(queryMsg));
71667
+ const query2 = new WrappedBuffer3(hexToBytes13(queryMsg));
71060
71668
  this.lastTimestampIn = this.lastTimestampOut = 0;
71061
71669
  let fullOutput = new WrappedBuffer3;
71062
71670
  fullOutput.extend(new Uint8Array([PROTOCOL_VERSION3]));
@@ -71099,22 +71707,22 @@ var __defProp3, __export3 = (target, all) => {
71099
71707
  let theirElems = {};
71100
71708
  for (let i22 = 0;i22 < numIds; i22++) {
71101
71709
  let e13 = getBytes4(query2, ID_SIZE3);
71102
- theirElems[bytesToHex14(e13)] = e13;
71710
+ theirElems[bytesToHex15(e13)] = e13;
71103
71711
  }
71104
71712
  skip2 = true;
71105
71713
  this.storage.iterate(lower, upper, (item) => {
71106
71714
  let k2 = item.id;
71107
- const id = bytesToHex14(k2);
71715
+ const id = bytesToHex15(k2);
71108
71716
  if (!theirElems[id]) {
71109
71717
  onhave?.(id);
71110
71718
  } else {
71111
- delete theirElems[bytesToHex14(k2)];
71719
+ delete theirElems[bytesToHex15(k2)];
71112
71720
  }
71113
71721
  return true;
71114
71722
  });
71115
71723
  if (onneed) {
71116
71724
  for (let v3 of Object.values(theirElems)) {
71117
- onneed(bytesToHex14(v3));
71725
+ onneed(bytesToHex15(v3));
71118
71726
  }
71119
71727
  }
71120
71728
  } else {
@@ -71132,7 +71740,7 @@ var __defProp3, __export3 = (target, all) => {
71132
71740
  prevIndex = upper;
71133
71741
  prevBound = currBound;
71134
71742
  }
71135
- return fullOutput.length === 1 ? null : bytesToHex14(fullOutput.unwrap());
71743
+ return fullOutput.length === 1 ? null : bytesToHex15(fullOutput.unwrap());
71136
71744
  }
71137
71745
  splitRange(lower, upper, upperBound, o) {
71138
71746
  let numElems = upper - lower;
@@ -71285,17 +71893,17 @@ var __defProp3, __export3 = (target, all) => {
71285
71893
  this.subscription.close();
71286
71894
  }
71287
71895
  }, nip98_exports2, _authorizationScheme3 = "Nostr ";
71288
- var init_esm5 = __esm(() => {
71896
+ var init_esm6 = __esm(() => {
71289
71897
  init_secp256k12();
71290
71898
  init_utils16();
71291
71899
  init_sha2564();
71292
71900
  init_utils16();
71293
71901
  init_utils16();
71294
- init_esm4();
71902
+ init_esm5();
71295
71903
  init_utils16();
71296
71904
  init_secp256k12();
71297
71905
  init_aes3();
71298
- init_esm4();
71906
+ init_esm5();
71299
71907
  init_utils16();
71300
71908
  init_sha2564();
71301
71909
  init_chacha2();
@@ -71305,13 +71913,13 @@ var init_esm5 = __esm(() => {
71305
71913
  init_hmac6();
71306
71914
  init_sha2564();
71307
71915
  init_utils16();
71308
- init_esm4();
71309
- init_esm4();
71916
+ init_esm5();
71917
+ init_esm5();
71310
71918
  init_utils17();
71311
71919
  init_sha2564();
71312
71920
  init_sha2564();
71313
71921
  init_utils16();
71314
- init_esm4();
71922
+ init_esm5();
71315
71923
  __defProp3 = Object.defineProperty;
71316
71924
  verifiedSymbol6 = Symbol("verified");
71317
71925
  utils_exports2 = {};
@@ -71319,8 +71927,8 @@ var init_esm5 = __esm(() => {
71319
71927
  Queue: () => Queue2,
71320
71928
  QueueNode: () => QueueNode2,
71321
71929
  binarySearch: () => binarySearch3,
71322
- bytesToHex: () => bytesToHex13,
71323
- hexToBytes: () => hexToBytes11,
71930
+ bytesToHex: () => bytesToHex14,
71931
+ hexToBytes: () => hexToBytes12,
71324
71932
  insertEventIntoAscendingList: () => insertEventIntoAscendingList3,
71325
71933
  insertEventIntoDescendingList: () => insertEventIntoDescendingList3,
71326
71934
  normalizeURL: () => normalizeURL3,
@@ -71685,20 +72293,20 @@ function serializeEvent5(evt) {
71685
72293
  }
71686
72294
  function getEventHash5(event3) {
71687
72295
  let eventHash = sha2569(utf8Encoder6.encode(serializeEvent5(event3)));
71688
- return bytesToHex13(eventHash);
72296
+ return bytesToHex14(eventHash);
71689
72297
  }
71690
72298
  var verifiedSymbol7, isRecord5 = (obj2) => obj2 instanceof Object, utf8Decoder6, utf8Encoder6, JS5 = class {
71691
72299
  generateSecretKey() {
71692
72300
  return schnorr4.utils.randomPrivateKey();
71693
72301
  }
71694
72302
  getPublicKey(secretKey) {
71695
- return bytesToHex13(schnorr4.getPublicKey(secretKey));
72303
+ return bytesToHex14(schnorr4.getPublicKey(secretKey));
71696
72304
  }
71697
72305
  finalizeEvent(t, secretKey) {
71698
72306
  const event3 = t;
71699
- event3.pubkey = bytesToHex13(schnorr4.getPublicKey(secretKey));
72307
+ event3.pubkey = bytesToHex14(schnorr4.getPublicKey(secretKey));
71700
72308
  event3.id = getEventHash5(event3);
71701
- event3.sig = bytesToHex13(schnorr4.sign(getEventHash5(event3), secretKey));
72309
+ event3.sig = bytesToHex14(schnorr4.sign(getEventHash5(event3), secretKey));
71702
72310
  event3[verifiedSymbol7] = true;
71703
72311
  return event3;
71704
72312
  }
@@ -71824,7 +72432,7 @@ function getReplaceableIdentifier2(event3) {
71824
72432
  }
71825
72433
  var EventStoreSymbol2, EventUIDSymbol2, ReplaceableAddressSymbol2, FromCacheSymbol2, ReplaceableIdentifierSymbol2;
71826
72434
  var init_event3 = __esm(() => {
71827
- init_esm5();
72435
+ init_esm6();
71828
72436
  init_kinds2();
71829
72437
  init_utils18();
71830
72438
  EventStoreSymbol2 = Symbol.for("event-store");
@@ -71906,7 +72514,7 @@ var processTags2 = (tags3, ...fns) => {
71906
72514
 
71907
72515
  // node_modules/applesauce-sqlite/node_modules/applesauce-core/node_modules/nostr-tools/lib/esm/nip19.js
71908
72516
  function npubEncode4(hex7) {
71909
- return encodeBytes3("npub", hexToBytes11(hex7));
72517
+ return encodeBytes3("npub", hexToBytes12(hex7));
71910
72518
  }
71911
72519
  function encodeBech323(prefix, data) {
71912
72520
  let words = bech324.toWords(data);
@@ -71917,7 +72525,7 @@ function encodeBytes3(prefix, bytes9) {
71917
72525
  }
71918
72526
  function nprofileEncode3(profile3) {
71919
72527
  let data = encodeTLV3({
71920
- 0: [hexToBytes11(profile3.pubkey)],
72528
+ 0: [hexToBytes12(profile3.pubkey)],
71921
72529
  1: (profile3.relays || []).map((url3) => utf8Encoder8.encode(url3))
71922
72530
  });
71923
72531
  return encodeBech323("nprofile", data);
@@ -71938,7 +72546,7 @@ function encodeTLV3(tlv) {
71938
72546
  var utf8Decoder8, utf8Encoder8, Bech32MaxSize3 = 5000;
71939
72547
  var init_nip19 = __esm(() => {
71940
72548
  init_utils16();
71941
- init_esm4();
72549
+ init_esm5();
71942
72550
  init_utils16();
71943
72551
  utf8Decoder8 = new TextDecoder("utf-8");
71944
72552
  utf8Encoder8 = new TextEncoder;
@@ -74614,7 +75222,7 @@ var init_models3 = __esm(() => {
74614
75222
 
74615
75223
  // node_modules/applesauce-sqlite/node_modules/applesauce-core/dist/operations/client.js
74616
75224
  var NEVER_ATTACH_CLIENT_TAG2;
74617
- var init_client5 = __esm(() => {
75225
+ var init_client6 = __esm(() => {
74618
75226
  init_event3();
74619
75227
  init_pointers2();
74620
75228
  init_tags2();
@@ -74628,7 +75236,7 @@ var init_hidden_content4 = __esm(() => {
74628
75236
 
74629
75237
  // node_modules/applesauce-sqlite/node_modules/applesauce-core/dist/operations/index.js
74630
75238
  var init_operations2 = __esm(() => {
74631
- init_client5();
75239
+ init_client6();
74632
75240
  init_content5();
74633
75241
  init_encrypted_content5();
74634
75242
  init_event4();
@@ -90915,49 +91523,6 @@ var ModelManager = class _ModelManager {
90915
91523
  }
90916
91524
  }
90917
91525
  };
90918
- var AuditLogger = class _AuditLogger {
90919
- static instance = null;
90920
- static getInstance() {
90921
- if (!_AuditLogger.instance) {
90922
- _AuditLogger.instance = new _AuditLogger;
90923
- }
90924
- return _AuditLogger.instance;
90925
- }
90926
- async log(entry) {
90927
- const fullEntry = {
90928
- ...entry,
90929
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
90930
- };
90931
- const logLine = JSON.stringify(fullEntry) + `
90932
- `;
90933
- if (typeof window === "undefined") {
90934
- try {
90935
- const fs = await import("fs");
90936
- const path2 = await import("path");
90937
- const logPath = path2.join(process.cwd(), "audit.log");
90938
- fs.appendFileSync(logPath, logLine);
90939
- } catch (error53) {
90940
- console.error("[AuditLogger] Failed to write to file:", error53);
90941
- }
90942
- } else {
90943
- console.log("[AUDIT]", logLine.trim());
90944
- }
90945
- }
90946
- async logBalanceSnapshot(action, amounts, options) {
90947
- await this.log({
90948
- action,
90949
- totalBalance: amounts.totalBalance,
90950
- providerBalances: amounts.providerBalances,
90951
- mintBalances: amounts.mintBalances,
90952
- amount: options?.amount,
90953
- mintUrl: options?.mintUrl,
90954
- baseUrl: options?.baseUrl,
90955
- status: options?.status ?? "success",
90956
- details: options?.details
90957
- });
90958
- }
90959
- };
90960
- var auditLogger = AuditLogger.getInstance();
90961
91526
  function isNetworkErrorMessage(message) {
90962
91527
  return message.includes("NetworkError when attempting to fetch resource") || message.includes("Failed to fetch") || message.includes("Load failed") || message.includes("Unable to connect") || message.includes("Was there a typo in the url or port") || message.includes("ERR_TLS_CERT_ALTNAME_INVALID") || message.includes("ERR_TLS_CERT_NOT_YET_VALID") || message.includes("ERR_TLS_CERT_EXPIRED") || message.includes("UNABLE_TO_VERIFY_LEAF_SIGNATURE") || message.includes("SELF_SIGNED_CERT_IN_CHAIN");
90963
91528
  }
@@ -90992,7 +91557,7 @@ var CashuSpender = class _CashuSpender {
90992
91557
  debugLevel = "WARN";
90993
91558
  logger;
90994
91559
  static MAX_REFUND_RETRIES = 3;
90995
- static REFUND_RETRY_INTERVAL_MS = 120000;
91560
+ static REFUND_RETRY_INTERVAL_MS = 2 * 60 * 1000;
90996
91561
  _refundRetryInterval = null;
90997
91562
  async receiveToken(token) {
90998
91563
  try {
@@ -91060,10 +91625,6 @@ var CashuSpender = class _CashuSpender {
91060
91625
  mintBalances: normalizedMintBalances
91061
91626
  };
91062
91627
  }
91063
- async _logTransaction(action, options) {
91064
- const balanceState = await this._getBalanceState();
91065
- await auditLogger.logBalanceSnapshot(action, balanceState, options);
91066
- }
91067
91628
  get isBusy() {
91068
91629
  return this._isBusy;
91069
91630
  }
@@ -91212,12 +91773,6 @@ var CashuSpender = class _CashuSpender {
91212
91773
  if (token) {
91213
91774
  this._log("DEBUG", `[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`);
91214
91775
  }
91215
- this._logTransaction("spend", {
91216
- amount: spentAmount,
91217
- mintUrl: selectedMintUrl || mintUrl,
91218
- baseUrl,
91219
- status: "success"
91220
- });
91221
91776
  this._log("DEBUG", `[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`);
91222
91777
  const units = this.walletAdapter.getMintUnits();
91223
91778
  return {
@@ -91258,12 +91813,6 @@ var CashuSpender = class _CashuSpender {
91258
91813
  const newBalance = balanceForBaseUrl + topUpResult.toppedUpAmount;
91259
91814
  const units = this.walletAdapter.getMintUnits();
91260
91815
  const unit = units[mintUrl] || "sat";
91261
- this._logTransaction("topup", {
91262
- amount: topUpResult.toppedUpAmount,
91263
- mintUrl,
91264
- baseUrl,
91265
- status: "success"
91266
- });
91267
91816
  return {
91268
91817
  token: apiKeyEntry.key,
91269
91818
  status: "success",
@@ -91620,7 +92169,7 @@ var BalanceManager = class _BalanceManager {
91620
92169
  if (!forceRefund) {
91621
92170
  const apiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
91622
92171
  if (apiKeyEntry?.lastUsed) {
91623
- const fiveMinutesAgo = Date.now() - 300000;
92172
+ const fiveMinutesAgo = Date.now() - 5 * 60 * 1000;
91624
92173
  if (apiKeyEntry.lastUsed > fiveMinutesAgo) {
91625
92174
  this.logger.log(`refundApiKey: skipping ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1000)}s ago`);
91626
92175
  return {
@@ -92274,13 +92823,18 @@ var isOnionUrl = (url3) => {
92274
92823
  return trimmed.includes(TOR_ONION_SUFFIX);
92275
92824
  }
92276
92825
  };
92277
- var USER_CACHE_SECRET_FIELD2 = "user_cache_secret";
92278
- var USER_CACHE_SECRET_ENV2 = "TINFOIL_USER_CACHE_SECRET";
92279
- var USER_CACHE_SECRET_PATHS2 = [
92826
+ var OPENAI_JSON_BODY_PATHS = [
92280
92827
  "/chat/completions",
92281
92828
  "/completions",
92282
92829
  "/responses"
92283
92830
  ];
92831
+ function isOpenAiJsonBodyPath(pathname) {
92832
+ const path2 = (pathname.split("?")[0] ?? "").replace(/\/+$/, "");
92833
+ return OPENAI_JSON_BODY_PATHS.some((suffix) => path2.endsWith(suffix));
92834
+ }
92835
+ var USER_CACHE_SECRET_FIELD2 = "user_cache_secret";
92836
+ var USER_CACHE_SECRET_ENV2 = "TINFOIL_USER_CACHE_SECRET";
92837
+ var USER_CACHE_SECRET_PATHS2 = OPENAI_JSON_BODY_PATHS;
92284
92838
  var USER_CACHE_SECRET_DIR_NAME2 = ".tinfoil";
92285
92839
  var USER_CACHE_SECRET_FILE_NAME2 = "user_cache_secret";
92286
92840
  function newUserCacheSecret2() {
@@ -92657,7 +93211,7 @@ async function isEhbpKeyConfigMismatchResponse(response, protocol) {
92657
93211
  }
92658
93212
  }
92659
93213
  async function fetchTinfoilEhbpOnce(context, options, normalized, ehbp, userCacheSecret) {
92660
- const { Identity: Identity3, PROTOCOL: PROTOCOL2, decryptResponseWithToken: decryptResponseWithToken2, extractSessionRecoveryToken: extractSessionRecoveryToken2 } = ehbp;
93214
+ const { Identity: Identity4, PROTOCOL: PROTOCOL3, decryptResponseWithToken: decryptResponseWithToken3, extractSessionRecoveryToken: extractSessionRecoveryToken3 } = ehbp;
92661
93215
  const resolved = resolveOptions(options);
92662
93216
  const baseURL = context.client.getBaseURL() ?? resolved.baseUrl;
92663
93217
  const enclaveURL = context.client.getEnclaveURL();
@@ -92685,7 +93239,7 @@ async function fetchTinfoilEhbpOnce(context, options, normalized, ehbp, userCach
92685
93239
  }
92686
93240
  }
92687
93241
  }
92688
- const serverIdentity = await Identity3.fromPublicKeyHex(context.verification.hpkePublicKey);
93242
+ const serverIdentity = await Identity4.fromPublicKeyHex(context.verification.hpkePublicKey);
92689
93243
  const request = new Request(targetUrl.toString(), {
92690
93244
  method,
92691
93245
  headers,
@@ -92700,18 +93254,18 @@ async function fetchTinfoilEhbpOnce(context, options, normalized, ehbp, userCach
92700
93254
  if (!requestContext) {
92701
93255
  return response;
92702
93256
  }
92703
- if (await isEhbpKeyConfigMismatchResponse(response, PROTOCOL2)) {
93257
+ if (await isEhbpKeyConfigMismatchResponse(response, PROTOCOL3)) {
92704
93258
  throw new ehbp.KeyConfigMismatchError("EHBP key configuration mismatch");
92705
93259
  }
92706
- if (!response.headers.get(PROTOCOL2.RESPONSE_NONCE_HEADER)) {
93260
+ if (!response.headers.get(PROTOCOL3.RESPONSE_NONCE_HEADER)) {
92707
93261
  return response;
92708
93262
  }
92709
- const token = await extractSessionRecoveryToken2(requestContext);
92710
- return await decryptResponseWithToken2(response, token);
93263
+ const token = await extractSessionRecoveryToken3(requestContext);
93264
+ return await decryptResponseWithToken3(response, token);
92711
93265
  }
92712
93266
  async function fetchTinfoilPreservingPlaintextErrors(options, input, init) {
92713
93267
  const context = await prepareTinfoilClient(options);
92714
- const ehbp = await Promise.resolve().then(() => (init_esm3(), exports_esm));
93268
+ const ehbp = await Promise.resolve().then(() => (init_esm4(), exports_esm));
92715
93269
  const normalized = normalizeFetchArgs(input, init);
92716
93270
  const userCacheSecret = await resolveUserCacheSecret2({
92717
93271
  explicit: options.userCacheSecret,
@@ -92826,6 +93380,10 @@ function getImageResolutionFromDataUrl(dataUrl) {
92826
93380
  function calculateImageTokens(width, height, detail = "auto") {
92827
93381
  if (detail === "low")
92828
93382
  return 85;
93383
+ if (detail === "original") {
93384
+ const patches = Math.ceil(width / IMAGE_PATCH_PX) * Math.ceil(height / IMAGE_PATCH_PX);
93385
+ return Math.ceil(Math.min(patches, MAX_IMAGE_PATCHES) * 1.2);
93386
+ }
92829
93387
  let w2 = width;
92830
93388
  let h2 = height;
92831
93389
  if (w2 > 2048 || h2 > 2048) {
@@ -92853,6 +93411,238 @@ function calculateImageTokens(width, height, detail = "auto") {
92853
93411
  const numTiles = tilesWidth * tilesHeight;
92854
93412
  return 85 + 170 * numTiles;
92855
93413
  }
93414
+ var IMAGE_PATCH_PX = 32;
93415
+ var MAX_IMAGE_PATCHES = 30000;
93416
+ var MAX_TILED_IMAGE_TOKENS = 765;
93417
+ var MAX_ORIGINAL_IMAGE_TOKENS = Math.ceil(MAX_IMAGE_PATCHES * 1.2);
93418
+ function worstCaseImageTokensForDetail(detail) {
93419
+ if (detail === "low")
93420
+ return 85;
93421
+ if (detail === "original")
93422
+ return MAX_ORIGINAL_IMAGE_TOKENS;
93423
+ return MAX_TILED_IMAGE_TOKENS;
93424
+ }
93425
+ function estimateImageTokensForUrl(url3, detail) {
93426
+ if (!url3 || typeof url3 !== "string")
93427
+ return 0;
93428
+ if (url3.startsWith("data:")) {
93429
+ const res = getImageResolutionFromDataUrl(url3);
93430
+ if (res) {
93431
+ return calculateImageTokens(res.width, res.height, detail);
93432
+ }
93433
+ return worstCaseImageTokensForDetail(detail);
93434
+ }
93435
+ return worstCaseImageTokensForDetail(detail);
93436
+ }
93437
+ function estimateInputImageTokens(item) {
93438
+ const detail = typeof item?.detail === "string" && item?.detail ? item.detail : "auto";
93439
+ const url3 = typeof item?.image_url === "string" ? item.image_url : item?.image_url?.url;
93440
+ const fromUrl = estimateImageTokensForUrl(url3, detail);
93441
+ if (fromUrl > 0 || !item?.file_id)
93442
+ return fromUrl;
93443
+ return worstCaseImageTokensForDetail(detail);
93444
+ }
93445
+ function countImageTokensInMessages(apiMessages) {
93446
+ let total = 0;
93447
+ for (const msg of apiMessages ?? []) {
93448
+ const content2 = msg?.content;
93449
+ if (!Array.isArray(content2))
93450
+ continue;
93451
+ for (const part of content2) {
93452
+ if (!part || typeof part !== "object")
93453
+ continue;
93454
+ if (part.type === "image_url") {
93455
+ const detail = typeof part.image_url?.detail === "string" && part.image_url?.detail ? part.image_url.detail : "auto";
93456
+ const url3 = typeof part.image_url === "string" ? part.image_url : part.image_url?.url;
93457
+ total += estimateImageTokensForUrl(url3, detail);
93458
+ } else if (part.type === "input_image") {
93459
+ total += estimateInputImageTokens(part);
93460
+ }
93461
+ }
93462
+ }
93463
+ return total;
93464
+ }
93465
+ function countImageTokensInResponsesInput(input) {
93466
+ if (!Array.isArray(input))
93467
+ return 0;
93468
+ let total = 0;
93469
+ for (const item of input) {
93470
+ if (!item || typeof item !== "object")
93471
+ continue;
93472
+ if (item.type === "input_image") {
93473
+ total += estimateInputImageTokens(item);
93474
+ continue;
93475
+ }
93476
+ if (Array.isArray(item.content)) {
93477
+ for (const part of item.content) {
93478
+ if (part && typeof part === "object" && part.type === "input_image") {
93479
+ total += estimateInputImageTokens(part);
93480
+ }
93481
+ }
93482
+ }
93483
+ }
93484
+ return total;
93485
+ }
93486
+ function safeStringifyCompact(value) {
93487
+ try {
93488
+ return JSON.stringify(value);
93489
+ } catch {
93490
+ return null;
93491
+ }
93492
+ }
93493
+ function textLength(value) {
93494
+ if (typeof value === "string")
93495
+ return value.length;
93496
+ if (value !== null && typeof value === "object") {
93497
+ return safeStringifyCompact(value)?.length ?? 0;
93498
+ }
93499
+ return 0;
93500
+ }
93501
+ function countMessageTextChars(apiMessages) {
93502
+ let total = 0;
93503
+ for (const msg of apiMessages ?? []) {
93504
+ if (!msg || typeof msg !== "object")
93505
+ continue;
93506
+ const content2 = msg.content;
93507
+ if (typeof content2 === "string") {
93508
+ total += content2.length;
93509
+ } else if (Array.isArray(content2)) {
93510
+ for (const part of content2) {
93511
+ if (part && typeof part === "object" && part.type === "text") {
93512
+ total += textLength(part.text);
93513
+ }
93514
+ }
93515
+ }
93516
+ const toolCalls = msg.tool_calls;
93517
+ if (Array.isArray(toolCalls)) {
93518
+ for (const call of toolCalls) {
93519
+ const fn = call?.function;
93520
+ if (!fn || typeof fn !== "object")
93521
+ continue;
93522
+ total += textLength(fn.name);
93523
+ total += textLength(fn.arguments);
93524
+ }
93525
+ }
93526
+ }
93527
+ return total;
93528
+ }
93529
+ function countResponsesInputTextChars(input) {
93530
+ if (!Array.isArray(input))
93531
+ return 0;
93532
+ let total = 0;
93533
+ for (const item of input) {
93534
+ if (!item || typeof item !== "object")
93535
+ continue;
93536
+ const itemType = item.type;
93537
+ if (itemType === "input_text") {
93538
+ total += textLength(item.text);
93539
+ continue;
93540
+ }
93541
+ if (itemType === "function_call") {
93542
+ total += textLength(item.arguments);
93543
+ continue;
93544
+ }
93545
+ if (itemType === "function_call_output") {
93546
+ total += textLength(item.output);
93547
+ continue;
93548
+ }
93549
+ if (itemType === "reasoning") {
93550
+ const summary = item.summary;
93551
+ if (Array.isArray(summary)) {
93552
+ for (const part of summary) {
93553
+ if (part && typeof part === "object") {
93554
+ total += textLength(part.text);
93555
+ }
93556
+ }
93557
+ }
93558
+ }
93559
+ const content2 = item.content;
93560
+ if (typeof content2 === "string") {
93561
+ total += content2.length;
93562
+ } else if (Array.isArray(content2)) {
93563
+ for (const part of content2) {
93564
+ if (!part || typeof part !== "object")
93565
+ continue;
93566
+ total += textLength(part.text);
93567
+ if (typeof part.refusal === "string") {
93568
+ total += part.refusal.length;
93569
+ }
93570
+ }
93571
+ }
93572
+ }
93573
+ return total;
93574
+ }
93575
+ var NODE_TOLERANCE_PERCENT = 1;
93576
+ function sumStringChars(node) {
93577
+ if (typeof node === "string")
93578
+ return node.length;
93579
+ if (Array.isArray(node)) {
93580
+ return node.reduce((total, item) => total + sumStringChars(item), 0);
93581
+ }
93582
+ if (node && typeof node === "object") {
93583
+ let total = 0;
93584
+ for (const [key, value] of Object.entries(node)) {
93585
+ total += key.length + sumStringChars(value);
93586
+ }
93587
+ return total;
93588
+ }
93589
+ return 0;
93590
+ }
93591
+ function countPromptTokenIds(node) {
93592
+ if (typeof node === "number" && Number.isInteger(node))
93593
+ return 1;
93594
+ if (Array.isArray(node)) {
93595
+ return node.reduce((total, item) => total + countPromptTokenIds(item), 0);
93596
+ }
93597
+ return 0;
93598
+ }
93599
+ function estimateNodePromptTokens(body) {
93600
+ return Math.floor(sumStringChars(body) / 3) + countPromptTokenIds(body?.prompt);
93601
+ }
93602
+ function nodeGateSats(model2, satsPricing, requestBody, imageTokens) {
93603
+ const maxCost = satsPricing?.max_cost;
93604
+ if (typeof maxCost !== "number" || !Number.isFinite(maxCost))
93605
+ return 0;
93606
+ const toleranceFactor = 1 - NODE_TOLERANCE_PERCENT / 100;
93607
+ const promptPrice = typeof satsPricing.prompt === "number" ? satsPricing.prompt : 0;
93608
+ const completionPrice = typeof satsPricing.completion === "number" ? satsPricing.completion : 0;
93609
+ let gateMsats = Math.max(1, Math.floor(maxCost * 1000 * toleranceFactor));
93610
+ let promptAllowanceSats = typeof satsPricing.max_prompt_cost === "number" ? satsPricing.max_prompt_cost * toleranceFactor : 0;
93611
+ const topProvider = model2?.top_provider;
93612
+ const providerContextLength = topProvider?.context_length;
93613
+ const providerMaxCompletion = topProvider?.max_completion_tokens;
93614
+ let promptTokenLimit;
93615
+ if (topProvider && (providerContextLength || providerMaxCompletion)) {
93616
+ if (providerContextLength && providerMaxCompletion) {
93617
+ promptTokenLimit = Math.max(0, providerContextLength - providerMaxCompletion);
93618
+ } else if (providerContextLength) {
93619
+ promptTokenLimit = providerContextLength;
93620
+ } else {
93621
+ promptTokenLimit = 0;
93622
+ }
93623
+ } else if (model2?.context_length) {
93624
+ promptTokenLimit = model2.context_length;
93625
+ }
93626
+ if (promptTokenLimit !== undefined) {
93627
+ promptAllowanceSats = promptTokenLimit * promptPrice * toleranceFactor;
93628
+ }
93629
+ const promptTokens = estimateNodePromptTokens(requestBody) + (Array.isArray(requestBody?.messages) ? imageTokens : 0);
93630
+ if (promptTokens > 0) {
93631
+ const unusedPromptBudget = promptAllowanceSats - promptTokens * promptPrice;
93632
+ if (unusedPromptBudget > 0) {
93633
+ gateMsats -= Math.floor(unusedPromptBudget * 1000);
93634
+ }
93635
+ }
93636
+ const rawMaxTokens = requestBody?.max_tokens;
93637
+ const parsedMaxTokens = typeof rawMaxTokens === "number" ? rawMaxTokens : typeof rawMaxTokens === "string" && rawMaxTokens.trim() !== "" ? Number(rawMaxTokens) : NaN;
93638
+ if (Number.isFinite(parsedMaxTokens) && parsedMaxTokens > 0 && typeof satsPricing?.max_completion_cost === "number" && completionPrice > 0 && !isTinfoilModel(model2.id)) {
93639
+ const unusedCompletionBudget = satsPricing.max_completion_cost * toleranceFactor - parsedMaxTokens * completionPrice;
93640
+ if (unusedCompletionBudget > 0) {
93641
+ gateMsats -= Math.floor(unusedCompletionBudget * 1000);
93642
+ }
93643
+ }
93644
+ return Math.max(gateMsats, 1) / 1000;
93645
+ }
92856
93646
  var ProviderManager = class _ProviderManager {
92857
93647
  constructor(discoveryAdapter, store, logger3) {
92858
93648
  this.discoveryAdapter = discoveryAdapter;
@@ -93095,35 +93885,45 @@ ${ranking}`);
93095
93885
  }
93096
93886
  return providerMints.includes(mintUrl);
93097
93887
  }
93098
- getRequiredSatsForModel(model2, apiMessages, maxTokens) {
93888
+ getRequiredSatsForModel(model2, apiMessages, maxTokens, requestBody) {
93099
93889
  try {
93890
+ const body = requestBody ?? {};
93100
93891
  let imageTokens = 0;
93101
- if (apiMessages) {
93102
- for (const msg of apiMessages) {
93103
- const content2 = msg?.content;
93104
- if (Array.isArray(content2)) {
93105
- for (const part of content2) {
93106
- const isImage = part && typeof part === "object" && part.type === "image_url";
93107
- const url3 = isImage ? typeof part.image_url === "string" ? part.image_url : part.image_url?.url : undefined;
93108
- if (url3 && typeof url3 === "string" && url3.startsWith("data:")) {
93109
- const res = getImageResolutionFromDataUrl(url3);
93110
- if (res) {
93111
- const tokensFromImage = calculateImageTokens(res.width, res.height);
93112
- imageTokens += tokensFromImage;
93113
- } else {}
93114
- }
93115
- }
93116
- }
93892
+ let textChars = 0;
93893
+ let sawPromptShape = false;
93894
+ let textEstimateUnknown = false;
93895
+ if (Array.isArray(apiMessages) && apiMessages.length > 0) {
93896
+ sawPromptShape = true;
93897
+ imageTokens += countImageTokensInMessages(apiMessages);
93898
+ textChars += countMessageTextChars(apiMessages);
93899
+ }
93900
+ const responsesInput = body.input;
93901
+ if (!sawPromptShape) {
93902
+ if (Array.isArray(responsesInput)) {
93903
+ sawPromptShape = true;
93904
+ imageTokens += countImageTokensInResponsesInput(responsesInput);
93905
+ textChars += countResponsesInputTextChars(responsesInput);
93906
+ } else if (typeof responsesInput === "string") {
93907
+ sawPromptShape = true;
93908
+ textChars += responsesInput.length;
93909
+ }
93910
+ }
93911
+ const instructions = body.instructions;
93912
+ if (typeof instructions === "string" && instructions) {
93913
+ sawPromptShape = true;
93914
+ textChars += instructions.length;
93915
+ }
93916
+ const tools = body.tools;
93917
+ if (Array.isArray(tools) && tools.length > 0) {
93918
+ sawPromptShape = true;
93919
+ const serialized = safeStringifyCompact(tools);
93920
+ if (serialized === null) {
93921
+ textEstimateUnknown = true;
93922
+ } else {
93923
+ textChars += serialized.length;
93117
93924
  }
93118
93925
  }
93119
- const apiMessagesNoImages = apiMessages ? apiMessages.map((m) => {
93120
- if (Array.isArray(m?.content)) {
93121
- const filtered = m.content.filter((p) => !(p && typeof p === "object" && p.type === "image_url"));
93122
- return { ...m, content: filtered };
93123
- }
93124
- return m;
93125
- }) : undefined;
93126
- const approximateTokens = apiMessagesNoImages ? Math.ceil(JSON.stringify(apiMessagesNoImages, null, 2).length / 2.84) : 1e4;
93926
+ const approximateTokens = textEstimateUnknown ? 1e4 : sawPromptShape ? Math.ceil(textChars / 2.84) : 1e4;
93127
93927
  const totalInputTokens = approximateTokens + imageTokens;
93128
93928
  const sp = model2?.sats_pricing;
93129
93929
  if (!sp) {
@@ -93138,11 +93938,17 @@ ${ranking}`);
93138
93938
  if (maxTokens !== undefined && sp.completion && !isTinfoilModel(model2.id)) {
93139
93939
  completionCost = sp.completion * maxTokens;
93140
93940
  }
93141
- const totalEstimatedCosts = (promptCosts + completionCost + requestFee) * 1.05;
93941
+ const componentEstimate = (promptCosts + completionCost + requestFee) * 1.05;
93942
+ const gateEstimate = nodeGateSats(model2, sp, body, imageTokens) * 1.05;
93943
+ let totalEstimatedCosts = Math.max(componentEstimate, gateEstimate);
93944
+ if (typeof sp.max_cost === "number" && totalEstimatedCosts > sp.max_cost) {
93945
+ return sp.max_cost;
93946
+ }
93142
93947
  return totalEstimatedCosts;
93143
93948
  } catch (e13) {
93144
93949
  this.logger.error("getRequiredSatsForModel error:", e13);
93145
- return 0;
93950
+ const sp = model2?.sats_pricing;
93951
+ return sp?.max_cost ?? 50;
93146
93952
  }
93147
93953
  }
93148
93954
  };
@@ -94556,7 +95362,6 @@ var RoutstrClient = class {
94556
95362
  const satsSpent = await this._handlePostResponseBalanceUpdate({
94557
95363
  token: prepared.tokenUsed,
94558
95364
  baseUrl: prepared.baseUrlUsed,
94559
- mintUrl: params.mintUrl,
94560
95365
  initialTokenBalance: prepared.tokenBalanceInSats,
94561
95366
  initialTokenBalanceUnknown: prepared.tokenBalanceUnknown,
94562
95367
  fallbackSatsSpent: usage?.satsCost,
@@ -94612,17 +95417,22 @@ var RoutstrClient = class {
94612
95417
  messageCount: requestMessages.length,
94613
95418
  maxTokens: requestMaxTokens
94614
95419
  });
94615
- requiredSats = this.providerManager.getRequiredSatsForModel(selectedModel, requestMessages, requestMaxTokens);
95420
+ requiredSats = this.providerManager.getRequiredSatsForModel(selectedModel, requestMessages, requestMaxTokens, requestBodyForPricing);
94616
95421
  }
94617
95422
  }
94618
95423
  let requestBody = body;
94619
95424
  if (body && typeof body === "object") {
94620
95425
  const bodyObj = body;
94621
- if (!bodyObj.stream) {
95426
+ if (isOpenAiJsonBodyPath(requestPath) && !bodyObj.stream) {
94622
95427
  requestBody = { ...bodyObj, stream: false };
94623
95428
  }
94624
95429
  }
94625
95430
  const baseHeaders = this._buildBaseHeaders();
95431
+ for (const [name16, value] of Object.entries(headers)) {
95432
+ if (name16.toLowerCase() === "x-routstr-model-path") {
95433
+ baseHeaders["x-routstr-model-path"] = value;
95434
+ }
95435
+ }
94626
95436
  const tinfoilEnabled = Boolean(modelId && isTinfoilModel(modelId));
94627
95437
  if (tinfoilEnabled) {
94628
95438
  this._log("DEBUG", `[RoutstrClient] Attesting Tinfoil model ${modelId} before spend`);
@@ -95128,7 +95938,7 @@ var RoutstrClient = class {
95128
95938
  this._log("DEBUG", `[RoutstrClient] _handleErrorResponse: Failing over to next provider: ${nextProvider}, model: ${selectedModel.id}`);
95129
95939
  const newModel = await this.providerManager.getModelForProvider(nextProvider, selectedModel.id) ?? selectedModel;
95130
95940
  const messagesForPricing = Array.isArray(body?.messages) ? body.messages : [];
95131
- const newRequiredSats = this.providerManager.getRequiredSatsForModel(newModel, messagesForPricing, params.maxTokens);
95941
+ const newRequiredSats = this.providerManager.getRequiredSatsForModel(newModel, messagesForPricing, params.maxTokens, body && typeof body === "object" ? body : undefined);
95132
95942
  if (params.tinfoilEnabled) {
95133
95943
  this._log("DEBUG", `[RoutstrClient] _handleErrorResponse: Attesting Tinfoil failover provider ${nextProvider} before spend`);
95134
95944
  await prepareTinfoilClient({ baseUrl: nextProvider });
@@ -95253,7 +96063,6 @@ var RoutstrClient = class {
95253
96063
  const {
95254
96064
  token,
95255
96065
  baseUrl,
95256
- mintUrl,
95257
96066
  initialTokenBalance,
95258
96067
  initialTokenBalanceUnknown,
95259
96068
  fallbackSatsSpent,
@@ -95812,6 +96621,20 @@ function makeConsoleLogger2(prefix) {
95812
96621
  };
95813
96622
  }
95814
96623
  var consoleLogger2 = makeConsoleLogger2();
96624
+ var InsufficientBalanceError2 = class extends Error {
96625
+ constructor(required2, available, maxMintBalance = 0, maxMintUrl = "", customMessage) {
96626
+ super(customMessage ?? `Insufficient balance: need ${required2} sats, have ${available} sats available. ` + (maxMintBalance > 0 ? `Largest mint balance: ${maxMintBalance} sats from ${maxMintUrl}` : ""));
96627
+ this.required = required2;
96628
+ this.available = available;
96629
+ this.maxMintBalance = maxMintBalance;
96630
+ this.maxMintUrl = maxMintUrl;
96631
+ this.name = "InsufficientBalanceError";
96632
+ }
96633
+ required;
96634
+ available;
96635
+ maxMintBalance;
96636
+ maxMintUrl;
96637
+ };
95815
96638
  var ProviderBootstrapError2 = class extends Error {
95816
96639
  constructor(failedProviders, message) {
95817
96640
  super(message || `Failed to bootstrap providers. Tried: ${failedProviders.join(", ")}`);
@@ -95826,6 +96649,47 @@ var NoProvidersAvailableError2 = class extends Error {
95826
96649
  this.name = "NoProvidersAvailableError";
95827
96650
  }
95828
96651
  };
96652
+ var CoreErrorType2 = {
96653
+ TOKEN_ALREADY_SPENT: "token_already_spent",
96654
+ INVALID_TOKEN: "invalid_token",
96655
+ MINT_ERROR: "mint_error",
96656
+ MINT_UNREACHABLE: "mint_unreachable",
96657
+ CASHU_ERROR: "cashu_error",
96658
+ INSUFFICIENT_QUOTA: "insufficient_quota",
96659
+ MINIMUM_BALANCE_REQUIRED: "minimum_balance_required",
96660
+ TOKEN_CONSUMED: "token_consumed",
96661
+ API_ERROR: "api_error",
96662
+ PAYMENT_ERROR: "payment_error"
96663
+ };
96664
+ var CoreErrorCode2 = {
96665
+ TOKEN_ALREADY_SPENT: "cashu_token_already_spent",
96666
+ INVALID_CASHU_TOKEN: "invalid_cashu_token",
96667
+ CASHU_TOKEN_SWAP_FEES_EXCEED_AMOUNT: "cashu_token_swap_fees_exceed_amount",
96668
+ CASHU_FOREIGN_MINT_SWAP_FAILED: "cashu_foreign_mint_swap_failed",
96669
+ CASHU_MINT_UNREACHABLE: "cashu_mint_unreachable",
96670
+ CASHU_TOKEN_REDEMPTION_FAILED: "cashu_token_redemption_failed",
96671
+ CASHU_TOKEN_ZERO_VALUE: "cashu_token_zero_value",
96672
+ CASHU_TOKEN_CONSUMED: "cashu_token_consumed",
96673
+ INTERNAL_ERROR: "internal_error",
96674
+ INVALID_API_KEY: "invalid_api_key",
96675
+ INSUFFICIENT_BALANCE: "insufficient_balance",
96676
+ BALANCE_LIMIT_EXCEEDED: "balance_limit_exceeded"
96677
+ };
96678
+ function isInvalidTokenError2(parsed) {
96679
+ return parsed.type === CoreErrorType2.INVALID_TOKEN && parsed.code === CoreErrorCode2.INVALID_CASHU_TOKEN;
96680
+ }
96681
+ function isCashuRedemptionError2(parsed) {
96682
+ return parsed.type === CoreErrorType2.CASHU_ERROR && (parsed.code === CoreErrorCode2.CASHU_TOKEN_REDEMPTION_FAILED || parsed.code === CoreErrorCode2.CASHU_TOKEN_ZERO_VALUE);
96683
+ }
96684
+ function isTokenConsumedError2(parsed) {
96685
+ return parsed.type === CoreErrorType2.TOKEN_CONSUMED && parsed.code === CoreErrorCode2.CASHU_TOKEN_CONSUMED;
96686
+ }
96687
+ function isCoreInternalError2(parsed) {
96688
+ return parsed.type === CoreErrorType2.API_ERROR && parsed.code === CoreErrorCode2.INTERNAL_ERROR;
96689
+ }
96690
+ function isHandledRedemptionError2(parsed) {
96691
+ return isInvalidTokenError2(parsed) || isCashuRedemptionError2(parsed) || isTokenConsumedError2(parsed) || isCoreInternalError2(parsed);
96692
+ }
95829
96693
  var DEFAULT_NOSTR_RELAYS2 = [
95830
96694
  "wss://relay.damus.io",
95831
96695
  "wss://nos.lol",
@@ -96549,49 +97413,535 @@ var ModelManager2 = class _ModelManager2 {
96549
97413
  }
96550
97414
  }
96551
97415
  };
96552
- var AuditLogger2 = class _AuditLogger2 {
96553
- static instance = null;
96554
- static getInstance() {
96555
- if (!_AuditLogger2.instance) {
96556
- _AuditLogger2.instance = new _AuditLogger2;
97416
+ function isNetworkErrorMessage2(message) {
97417
+ return message.includes("NetworkError when attempting to fetch resource") || message.includes("Failed to fetch") || message.includes("Load failed") || message.includes("Unable to connect") || message.includes("Was there a typo in the url or port") || message.includes("ERR_TLS_CERT_ALTNAME_INVALID") || message.includes("ERR_TLS_CERT_NOT_YET_VALID") || message.includes("ERR_TLS_CERT_EXPIRED") || message.includes("UNABLE_TO_VERIFY_LEAF_SIGNATURE") || message.includes("SELF_SIGNED_CERT_IN_CHAIN");
97418
+ }
97419
+ function getBalanceInSats2(balance, unit) {
97420
+ return unit === "msat" ? balance / 1000 : balance;
97421
+ }
97422
+ var CashuSpender2 = class _CashuSpender2 {
97423
+ constructor(walletAdapter, storageAdapter, _discoveryAdapter, balanceManager, logger5) {
97424
+ this.walletAdapter = walletAdapter;
97425
+ this.storageAdapter = storageAdapter;
97426
+ this._discoveryAdapter = _discoveryAdapter;
97427
+ this.balanceManager = balanceManager;
97428
+ this.logger = (logger5 ?? consoleLogger2).child("CashuSpender");
97429
+ }
97430
+ walletAdapter;
97431
+ storageAdapter;
97432
+ _discoveryAdapter;
97433
+ balanceManager;
97434
+ _isBusy = false;
97435
+ debugLevel = "WARN";
97436
+ logger;
97437
+ static MAX_REFUND_RETRIES = 3;
97438
+ static REFUND_RETRY_INTERVAL_MS = 2 * 60 * 1000;
97439
+ _refundRetryInterval = null;
97440
+ async receiveToken(token) {
97441
+ try {
97442
+ const result = await this.walletAdapter.receiveToken(token);
97443
+ return result;
97444
+ } catch (error53) {
97445
+ const errorMessage = error53 instanceof Error ? error53.message : String(error53);
97446
+ if (errorMessage.includes("Failed to fetch mint")) {
97447
+ const cachedTokens = this.storageAdapter.getCachedReceiveTokens();
97448
+ const existingIndex = cachedTokens.findIndex((t) => t.token === token);
97449
+ if (existingIndex === -1) {
97450
+ const { amount: amount2, unit: unit2 } = this._decodeTokenAmount(token);
97451
+ this.storageAdapter.setCachedReceiveTokens([
97452
+ ...cachedTokens,
97453
+ {
97454
+ token,
97455
+ amount: amount2,
97456
+ unit: unit2,
97457
+ createdAt: Date.now()
97458
+ }
97459
+ ]);
97460
+ }
97461
+ }
97462
+ const { amount, unit } = this._decodeTokenAmount(token);
97463
+ return { success: false, amount, unit, message: errorMessage };
96557
97464
  }
96558
- return _AuditLogger2.instance;
96559
97465
  }
96560
- async log(entry) {
96561
- const fullEntry = {
96562
- ...entry,
96563
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
97466
+ _decodeTokenAmount(token) {
97467
+ try {
97468
+ const metadata = ur(token);
97469
+ const unit = metadata.unit || "sat";
97470
+ return { amount: metadata.amount, unit };
97471
+ } catch {
97472
+ return { amount: 0, unit: "sat" };
97473
+ }
97474
+ }
97475
+ async _getBalanceState() {
97476
+ if (this.balanceManager) {
97477
+ return this.balanceManager.getBalanceState();
97478
+ }
97479
+ const mintBalances = await this.walletAdapter.getBalances();
97480
+ const units = this.walletAdapter.getMintUnits();
97481
+ let totalMintBalance = 0;
97482
+ const normalizedMintBalances = {};
97483
+ for (const url4 in mintBalances) {
97484
+ const balance = mintBalances[url4];
97485
+ const unit = units[url4];
97486
+ const balanceInSats = getBalanceInSats2(balance, unit);
97487
+ normalizedMintBalances[url4] = balanceInSats;
97488
+ totalMintBalance += balanceInSats;
97489
+ }
97490
+ const providerBalances = {};
97491
+ let totalProviderBalance = 0;
97492
+ const apiKeys = this.storageAdapter.getAllApiKeys();
97493
+ for (const apiKey of apiKeys) {
97494
+ if (!providerBalances[apiKey.baseUrl]) {
97495
+ providerBalances[apiKey.baseUrl] = 0;
97496
+ }
97497
+ providerBalances[apiKey.baseUrl] += apiKey.balance;
97498
+ totalProviderBalance += apiKey.balance;
97499
+ }
97500
+ return {
97501
+ totalBalance: totalMintBalance + totalProviderBalance,
97502
+ providerBalances,
97503
+ mintBalances: normalizedMintBalances
96564
97504
  };
96565
- const logLine = JSON.stringify(fullEntry) + `
96566
- `;
96567
- if (typeof window === "undefined") {
97505
+ }
97506
+ get isBusy() {
97507
+ return this._isBusy;
97508
+ }
97509
+ getDebugLevel() {
97510
+ return this.debugLevel;
97511
+ }
97512
+ setDebugLevel(level) {
97513
+ this.debugLevel = level;
97514
+ }
97515
+ _log(level, ...args) {
97516
+ const levelPriority = {
97517
+ DEBUG: 0,
97518
+ WARN: 1,
97519
+ ERROR: 2
97520
+ };
97521
+ if (levelPriority[level] >= levelPriority[this.debugLevel]) {
97522
+ switch (level) {
97523
+ case "DEBUG":
97524
+ this.logger.log(...args);
97525
+ break;
97526
+ case "WARN":
97527
+ this.logger.warn(...args);
97528
+ break;
97529
+ case "ERROR":
97530
+ this.logger.error(...args);
97531
+ break;
97532
+ }
97533
+ }
97534
+ }
97535
+ async spend(options) {
97536
+ const {
97537
+ mintUrl,
97538
+ amount,
97539
+ baseUrl,
97540
+ reuseToken = false,
97541
+ p2pkPubkey,
97542
+ excludeMints = [],
97543
+ retryCount = 0
97544
+ } = options;
97545
+ this._isBusy = true;
97546
+ try {
97547
+ const result = await this._spendInternal({
97548
+ mintUrl,
97549
+ amount,
97550
+ baseUrl,
97551
+ reuseToken,
97552
+ p2pkPubkey,
97553
+ excludeMints,
97554
+ retryCount
97555
+ });
97556
+ if (result.status === "failed" || !result.token) {
97557
+ const errorMsg = result.error || `Insufficient balance. Need ${amount} sats.`;
97558
+ if (this._isNetworkError(errorMsg)) {
97559
+ throw new Error(`Your mint ${mintUrl} is unreachable or is blocking your IP. Please try again later or switch mints.`);
97560
+ }
97561
+ if (result.errorDetails) {
97562
+ throw new InsufficientBalanceError2(result.errorDetails.required, result.errorDetails.available, result.errorDetails.maxMintBalance, result.errorDetails.maxMintUrl);
97563
+ }
97564
+ throw new Error(errorMsg);
97565
+ }
97566
+ return result;
97567
+ } finally {
97568
+ this._isBusy = false;
97569
+ }
97570
+ }
97571
+ _isNetworkError(message) {
97572
+ return isNetworkErrorMessage2(message) || message.includes("Your mint") && message.includes("unreachable");
97573
+ }
97574
+ async _spendInternal(options) {
97575
+ let {
97576
+ mintUrl,
97577
+ amount,
97578
+ baseUrl,
97579
+ reuseToken,
97580
+ p2pkPubkey,
97581
+ excludeMints,
97582
+ retryCount
97583
+ } = options;
97584
+ this._log("DEBUG", `[CashuSpender] _spendInternal: amount=${amount}, mintUrl=${mintUrl}, baseUrl=${baseUrl}, reuseToken=${reuseToken}`);
97585
+ let adjustedAmount = Math.ceil(amount);
97586
+ if (!adjustedAmount || isNaN(adjustedAmount)) {
97587
+ this._log("ERROR", `[CashuSpender] _spendInternal: Invalid amount: ${amount}`);
97588
+ return {
97589
+ token: null,
97590
+ status: "failed",
97591
+ balance: 0,
97592
+ error: "Please enter a valid amount"
97593
+ };
97594
+ }
97595
+ if (reuseToken && baseUrl) {
97596
+ this._log("DEBUG", `[CashuSpender] _spendInternal: Attempting to reuse token for ${baseUrl}`);
97597
+ const existingResult = await this._tryReuseToken(baseUrl, adjustedAmount, mintUrl);
97598
+ if (existingResult) {
97599
+ this._log("DEBUG", `[CashuSpender] _spendInternal: Successfully reused token, balance: ${existingResult.balance}`);
97600
+ return existingResult;
97601
+ }
97602
+ this._log("DEBUG", `[CashuSpender] _spendInternal: Could not reuse token, will create new token`);
97603
+ }
97604
+ const balanceState = await this._getBalanceState();
97605
+ const totalAvailableBalance = balanceState.totalBalance;
97606
+ this._log("DEBUG", `[CashuSpender] _spendInternal: totalAvailableBalance=${totalAvailableBalance}, adjustedAmount=${adjustedAmount}`);
97607
+ if (totalAvailableBalance < adjustedAmount) {
97608
+ this._log("ERROR", `[CashuSpender] _spendInternal: Insufficient balance, have=${totalAvailableBalance}, need=${adjustedAmount}`);
97609
+ return this._createInsufficientBalanceError(adjustedAmount, balanceState.mintBalances, totalAvailableBalance);
97610
+ }
97611
+ let token = null;
97612
+ let selectedMintUrl;
97613
+ let spentAmount = adjustedAmount;
97614
+ if (this.balanceManager) {
97615
+ const tokenResult = await this.balanceManager.createProviderToken({
97616
+ mintUrl,
97617
+ baseUrl,
97618
+ amount: adjustedAmount,
97619
+ p2pkPubkey,
97620
+ excludeMints,
97621
+ retryCount
97622
+ });
97623
+ if (!tokenResult.success || !tokenResult.token) {
97624
+ if ((tokenResult.error || "").includes("Insufficient balance")) {
97625
+ return this._createInsufficientBalanceError(adjustedAmount, balanceState.mintBalances, totalAvailableBalance);
97626
+ }
97627
+ return {
97628
+ token: null,
97629
+ status: "failed",
97630
+ balance: 0,
97631
+ error: tokenResult.error || "Failed to create token"
97632
+ };
97633
+ }
97634
+ token = tokenResult.token;
97635
+ selectedMintUrl = tokenResult.selectedMintUrl;
97636
+ spentAmount = tokenResult.amountSpent || adjustedAmount;
97637
+ } else {
96568
97638
  try {
96569
- const fs = await import("fs");
96570
- const path2 = await import("path");
96571
- const logPath = path2.join(process.cwd(), "audit.log");
96572
- fs.appendFileSync(logPath, logLine);
97639
+ token = await this.walletAdapter.sendToken(mintUrl, adjustedAmount, p2pkPubkey);
97640
+ selectedMintUrl = mintUrl;
96573
97641
  } catch (error53) {
96574
- console.error("[AuditLogger] Failed to write to file:", error53);
97642
+ const errorMsg = error53 instanceof Error ? error53.message : String(error53);
97643
+ return {
97644
+ token: null,
97645
+ status: "failed",
97646
+ balance: 0,
97647
+ error: `Error generating token: ${errorMsg}`
97648
+ };
96575
97649
  }
96576
- } else {
96577
- console.log("[AUDIT]", logLine.trim());
96578
97650
  }
97651
+ if (token) {
97652
+ this._log("DEBUG", `[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`);
97653
+ }
97654
+ this._log("DEBUG", `[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`);
97655
+ const units = this.walletAdapter.getMintUnits();
97656
+ return {
97657
+ token,
97658
+ status: "success",
97659
+ balance: spentAmount,
97660
+ unit: (selectedMintUrl ? units[selectedMintUrl] : units[mintUrl]) || "sat",
97661
+ selectedMintUrl: selectedMintUrl || mintUrl
97662
+ };
96579
97663
  }
96580
- async logBalanceSnapshot(action, amounts, options) {
96581
- await this.log({
96582
- action,
96583
- totalBalance: amounts.totalBalance,
96584
- providerBalances: amounts.providerBalances,
96585
- mintBalances: amounts.mintBalances,
96586
- amount: options?.amount,
96587
- mintUrl: options?.mintUrl,
96588
- baseUrl: options?.baseUrl,
96589
- status: options?.status ?? "success",
96590
- details: options?.details
96591
- });
97664
+ async _tryReuseToken(baseUrl, amount, mintUrl) {
97665
+ const apiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
97666
+ if (!apiKeyEntry)
97667
+ return null;
97668
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
97669
+ const balanceForBaseUrl = apiKeyDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
97670
+ this._log("DEBUG", "Reusing API key", balanceForBaseUrl, amount);
97671
+ if (balanceForBaseUrl > amount) {
97672
+ const units = this.walletAdapter.getMintUnits();
97673
+ const unit = units[mintUrl] || "sat";
97674
+ return {
97675
+ token: apiKeyEntry.key,
97676
+ status: "success",
97677
+ balance: balanceForBaseUrl,
97678
+ unit
97679
+ };
97680
+ }
97681
+ if (this.balanceManager) {
97682
+ const topUpAmount = Math.ceil(amount * 1.2 - balanceForBaseUrl);
97683
+ const topUpResult = await this.balanceManager.topUp({
97684
+ mintUrl,
97685
+ baseUrl,
97686
+ amount: topUpAmount,
97687
+ token: apiKeyEntry.key
97688
+ });
97689
+ this._log("DEBUG", "TOPUP ", topUpResult);
97690
+ if (topUpResult.success && topUpResult.toppedUpAmount) {
97691
+ const newBalance = balanceForBaseUrl + topUpResult.toppedUpAmount;
97692
+ const units = this.walletAdapter.getMintUnits();
97693
+ const unit = units[mintUrl] || "sat";
97694
+ return {
97695
+ token: apiKeyEntry.key,
97696
+ status: "success",
97697
+ balance: newBalance,
97698
+ unit
97699
+ };
97700
+ }
97701
+ const providerBalance = await this._getProviderTokenBalance(baseUrl, apiKeyEntry.key);
97702
+ this._log("DEBUG", providerBalance);
97703
+ if (providerBalance <= 0) {
97704
+ this.storageAdapter.removeApiKey(baseUrl);
97705
+ }
97706
+ }
97707
+ return null;
97708
+ }
97709
+ async refundXcashuTokens(mintUrl, excludeBaseUrls) {
97710
+ const results = [];
97711
+ const xcashuTokens = this.storageAdapter.getXcashuTokens();
97712
+ const excludedUrls = new Set(excludeBaseUrls || []);
97713
+ for (const [baseUrl, tokens] of Object.entries(xcashuTokens)) {
97714
+ if (excludedUrls.has(baseUrl))
97715
+ continue;
97716
+ for (const xcashuToken of tokens) {
97717
+ try {
97718
+ if (!this.balanceManager) {
97719
+ throw new Error("BalanceManager not available for xcashu refund");
97720
+ }
97721
+ const fetchResult = await this.balanceManager.fetchRefundToken(baseUrl, xcashuToken.token, true);
97722
+ if (!fetchResult.success && fetchResult.status === 425) {
97723
+ results.push({
97724
+ baseUrl,
97725
+ token: xcashuToken.token,
97726
+ success: false,
97727
+ error: fetchResult.error
97728
+ });
97729
+ this._log("WARN", `[CashuSpender] refundXcashuTokens: 425 "Refund is pending" for ${baseUrl}; leaving token in store, tryCount untouched`);
97730
+ continue;
97731
+ }
97732
+ if (!fetchResult.success && fetchResult.parsedError?.type === CoreErrorType2.TOKEN_ALREADY_SPENT) {
97733
+ this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
97734
+ results.push({
97735
+ baseUrl,
97736
+ token: xcashuToken.token,
97737
+ success: false,
97738
+ error: fetchResult.error
97739
+ });
97740
+ this._log("WARN", `[CashuSpender] refundXcashuTokens: token_already_spent for ${baseUrl}; removing permanently-spent xcashu token from store`);
97741
+ continue;
97742
+ }
97743
+ if (!fetchResult.success && fetchResult.parsedError && isHandledRedemptionError2(fetchResult.parsedError)) {
97744
+ const directReceive = await this.receiveToken(xcashuToken.token);
97745
+ if (directReceive.success) {
97746
+ this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
97747
+ results.push({
97748
+ baseUrl,
97749
+ token: xcashuToken.token,
97750
+ success: true
97751
+ });
97752
+ this._log("DEBUG", `[CashuSpender] refundXcashuTokens: provider returned ${fetchResult.parsedError.type}/${fetchResult.parsedError.code}; recovered original token directly, amount=${directReceive.amount}`);
97753
+ continue;
97754
+ }
97755
+ this._log("WARN", `[CashuSpender] refundXcashuTokens: provider returned ${fetchResult.parsedError.type}/${fetchResult.parsedError.code}; direct original-token recovery also failed: ${directReceive.message ?? "unknown error"}`);
97756
+ }
97757
+ if (!fetchResult.success && fetchResult.status === 404 && (fetchResult.error || "").includes("Refund not found")) {
97758
+ const currentTryCount = xcashuToken.tryCount ?? 0;
97759
+ const newTryCount = currentTryCount + 1;
97760
+ if (newTryCount >= _CashuSpender2.MAX_REFUND_RETRIES) {
97761
+ this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
97762
+ this._log("WARN", `[CashuSpender] refundXcashuTokens: 404 "Refund not found" for ${baseUrl} after ${newTryCount} retries; removing unrefundable xcashu token from store`);
97763
+ } else {
97764
+ this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
97765
+ this._log("WARN", `[CashuSpender] refundXcashuTokens: 404 "Refund not found" for ${baseUrl}; tryCount=${newTryCount}/${_CashuSpender2.MAX_REFUND_RETRIES}, will retry in ${_CashuSpender2.REFUND_RETRY_INTERVAL_MS / 1000}s`);
97766
+ this._startRefundRetryInterval(mintUrl);
97767
+ }
97768
+ results.push({
97769
+ baseUrl,
97770
+ token: xcashuToken.token,
97771
+ success: false,
97772
+ error: fetchResult.error
97773
+ });
97774
+ continue;
97775
+ }
97776
+ if (!fetchResult.success || !fetchResult.token) {
97777
+ throw new Error(fetchResult.error || "Failed to fetch refund token from provider");
97778
+ }
97779
+ const receiveResult = await this.receiveToken(fetchResult.token);
97780
+ if (receiveResult.success) {
97781
+ this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
97782
+ results.push({
97783
+ baseUrl,
97784
+ token: xcashuToken.token,
97785
+ success: true
97786
+ });
97787
+ this._log("DEBUG", `[CashuSpender] refundXcashuTokens: Successfully refunded xcashu token for ${baseUrl}, amount=${receiveResult.amount}`);
97788
+ } else {
97789
+ const currentTryCount = xcashuToken.tryCount ?? 0;
97790
+ const newTryCount = currentTryCount + 1;
97791
+ this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
97792
+ results.push({
97793
+ baseUrl,
97794
+ token: xcashuToken.token,
97795
+ success: false,
97796
+ error: receiveResult.message ?? "Refund failed"
97797
+ });
97798
+ this._log("DEBUG", `[CashuSpender] refundXcashuTokens: Failed to receive refund token for ${baseUrl}, incremented tryCount to ${newTryCount}: ${receiveResult.message}`);
97799
+ }
97800
+ } catch (error53) {
97801
+ const currentTryCount = xcashuToken.tryCount ?? 0;
97802
+ const newTryCount = currentTryCount + 1;
97803
+ this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
97804
+ const errorMessage = error53 instanceof Error ? error53.message : String(error53);
97805
+ results.push({
97806
+ baseUrl,
97807
+ token: xcashuToken.token,
97808
+ success: false,
97809
+ error: errorMessage
97810
+ });
97811
+ this._log("ERROR", `[CashuSpender] refundXcashuTokens: Exception during refund for ${baseUrl}: ${errorMessage}, incremented tryCount to ${newTryCount}`);
97812
+ }
97813
+ }
97814
+ }
97815
+ return results;
97816
+ }
97817
+ _startRefundRetryInterval(mintUrl) {
97818
+ if (this._refundRetryInterval)
97819
+ return;
97820
+ this._log("DEBUG", `[CashuSpender] Starting refund retry interval (every ${_CashuSpender2.REFUND_RETRY_INTERVAL_MS / 1000}s)`);
97821
+ this._refundRetryInterval = setInterval(async () => {
97822
+ const remainingTokens = this.storageAdapter.getXcashuTokens();
97823
+ const hasTokens = Object.values(remainingTokens).some((tokens) => tokens.length > 0);
97824
+ if (!hasTokens) {
97825
+ this._stopRefundRetryInterval();
97826
+ return;
97827
+ }
97828
+ try {
97829
+ await this.refundXcashuTokens(mintUrl);
97830
+ } catch (error53) {
97831
+ this._log("ERROR", `[CashuSpender] Refund retry interval error: ${error53 instanceof Error ? error53.message : String(error53)}`);
97832
+ }
97833
+ }, _CashuSpender2.REFUND_RETRY_INTERVAL_MS);
97834
+ }
97835
+ _stopRefundRetryInterval() {
97836
+ if (this._refundRetryInterval) {
97837
+ clearInterval(this._refundRetryInterval);
97838
+ this._refundRetryInterval = null;
97839
+ this._log("DEBUG", `[CashuSpender] Stopped refund retry interval`);
97840
+ }
97841
+ }
97842
+ async refundProviders(mintUrl, forceRefund) {
97843
+ const results = [];
97844
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
97845
+ for (const apiKeyEntry of apiKeyDistribution) {
97846
+ const apiKeyEntryFull = this.storageAdapter.getApiKey(apiKeyEntry.baseUrl);
97847
+ if (apiKeyEntryFull && this.balanceManager) {
97848
+ try {
97849
+ const balanceResult = await this.balanceManager.getTokenBalance(apiKeyEntryFull.key, apiKeyEntry.baseUrl);
97850
+ if (balanceResult.isInvalidApiKey) {
97851
+ this.logger.warn(`refundProviders: ${apiKeyEntry.baseUrl} returned invalid API key; removing local key and treating as success`);
97852
+ this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
97853
+ results.push({
97854
+ baseUrl: apiKeyEntry.baseUrl,
97855
+ success: true
97856
+ });
97857
+ continue;
97858
+ }
97859
+ if (balanceResult.amount >= 0 && !balanceResult.balanceUnknown) {
97860
+ const balanceSat = balanceResult.unit === "msat" ? Math.floor(balanceResult.amount / 1000) : balanceResult.amount;
97861
+ const reservedSat = balanceResult.unit === "msat" ? Math.floor(balanceResult.reserved / 1000) : balanceResult.reserved;
97862
+ this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, balanceSat, reservedSat);
97863
+ } else {
97864
+ this.logger.warn(`refundProviders: balance refresh for ${apiKeyEntry.baseUrl} returned negative amount; keeping stale local balance=${apiKeyEntryFull.balance}`);
97865
+ }
97866
+ } catch (error53) {
97867
+ this.logger.warn(`refundProviders: balance refresh threw for ${apiKeyEntry.baseUrl}; proceeding with stale local balance`, error53);
97868
+ }
97869
+ const refreshedEntry = this.storageAdapter.getApiKey(apiKeyEntry.baseUrl);
97870
+ if (!refreshedEntry) {
97871
+ continue;
97872
+ }
97873
+ const refundResult = await this.balanceManager.refundApiKey({
97874
+ mintUrl,
97875
+ baseUrl: apiKeyEntry.baseUrl,
97876
+ apiKey: refreshedEntry.key,
97877
+ forceRefund
97878
+ });
97879
+ if (refundResult.success) {
97880
+ this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
97881
+ } else {
97882
+ const currentEntry = this.storageAdapter.getApiKey(apiKeyEntry.baseUrl);
97883
+ this.logger.warn(`refundProviders: refund failed for ${apiKeyEntry.baseUrl}; currentEntry=${Boolean(currentEntry)} balance=${currentEntry?.balance ?? "none"}. Touching lastUsed to rate-limit retries.`);
97884
+ if (currentEntry) {
97885
+ this.storageAdapter.touchApiKeyLastUsed(apiKeyEntry.baseUrl);
97886
+ }
97887
+ }
97888
+ results.push({
97889
+ baseUrl: apiKeyEntry.baseUrl,
97890
+ success: refundResult.success
97891
+ });
97892
+ } else {
97893
+ this.logger.warn(`refundProviders: cannot refund ${apiKeyEntry.baseUrl}; apiKeyEntryFull=${Boolean(apiKeyEntryFull)} balanceManager=${Boolean(this.balanceManager)}`);
97894
+ results.push({
97895
+ baseUrl: apiKeyEntry.baseUrl,
97896
+ success: false
97897
+ });
97898
+ }
97899
+ }
97900
+ return results;
97901
+ }
97902
+ _createInsufficientBalanceError(required2, normalizedBalances, availableBalance) {
97903
+ let maxBalance = 0;
97904
+ let maxMintUrl = "";
97905
+ for (const mintUrl in normalizedBalances) {
97906
+ const balanceInSats = normalizedBalances[mintUrl];
97907
+ if (balanceInSats > maxBalance) {
97908
+ maxBalance = balanceInSats;
97909
+ maxMintUrl = mintUrl;
97910
+ }
97911
+ }
97912
+ const error53 = new InsufficientBalanceError2(required2, availableBalance ?? maxBalance, maxBalance, maxMintUrl);
97913
+ return {
97914
+ token: null,
97915
+ status: "failed",
97916
+ balance: 0,
97917
+ error: error53.message,
97918
+ errorDetails: {
97919
+ required: required2,
97920
+ available: availableBalance ?? maxBalance,
97921
+ maxMintBalance: maxBalance,
97922
+ maxMintUrl
97923
+ }
97924
+ };
97925
+ }
97926
+ async _getProviderTokenBalance(baseUrl, token) {
97927
+ try {
97928
+ const response = await fetch(`${baseUrl}v1/wallet/info`, {
97929
+ headers: {
97930
+ Authorization: `Bearer ${token}`
97931
+ }
97932
+ });
97933
+ if (response.ok) {
97934
+ const data = await response.json();
97935
+ return data.balance / 1000;
97936
+ }
97937
+ } catch {
97938
+ return 0;
97939
+ }
97940
+ return 0;
96592
97941
  }
96593
97942
  };
96594
- var auditLogger2 = AuditLogger2.getInstance();
97943
+ var MAX_IMAGE_PATCHES2 = 30000;
97944
+ var MAX_ORIGINAL_IMAGE_TOKENS2 = Math.ceil(MAX_IMAGE_PATCHES2 * 1.2);
96595
97945
  var createBunPersistentEventDatabase = async (dbPath) => {
96596
97946
  const { BunSqliteEventDatabase: BunSqliteEventDatabase2 } = await Promise.resolve().then(() => (init_bun(), exports_bun));
96597
97947
  return new BunSqliteEventDatabase2(dbPath);
@@ -100997,14 +102347,14 @@ __export(exports_utils4, {
100997
102347
  numberToBytesLE: () => numberToBytesLE6,
100998
102348
  numberToBytesBE: () => numberToBytesBE6,
100999
102349
  hexToNumber: () => hexToNumber6,
101000
- hexToBytes: () => hexToBytes13,
102350
+ hexToBytes: () => hexToBytes14,
101001
102351
  equalBytes: () => equalBytes9,
101002
102352
  ensureBytes: () => ensureBytes5,
101003
102353
  createHmacDrbg: () => createHmacDrbg6,
101004
102354
  concatBytes: () => concatBytes15,
101005
102355
  bytesToNumberLE: () => bytesToNumberLE6,
101006
102356
  bytesToNumberBE: () => bytesToNumberBE6,
101007
- bytesToHex: () => bytesToHex15,
102357
+ bytesToHex: () => bytesToHex16,
101008
102358
  bitSet: () => bitSet4,
101009
102359
  bitMask: () => bitMask6,
101010
102360
  bitLen: () => bitLen6,
@@ -101016,7 +102366,7 @@ var _1n29 = BigInt(1);
101016
102366
  var _2n23 = BigInt(2);
101017
102367
  var u8a11 = (a) => a instanceof Uint8Array;
101018
102368
  var hexes11 = /* @__PURE__ */ Array.from({ length: 256 }, (_3, i6) => i6.toString(16).padStart(2, "0"));
101019
- function bytesToHex15(bytes10) {
102369
+ function bytesToHex16(bytes10) {
101020
102370
  if (!u8a11(bytes10))
101021
102371
  throw new Error("Uint8Array expected");
101022
102372
  let hex7 = "";
@@ -101034,7 +102384,7 @@ function hexToNumber6(hex7) {
101034
102384
  throw new Error("hex string expected, got " + typeof hex7);
101035
102385
  return BigInt(hex7 === "" ? "0" : `0x${hex7}`);
101036
102386
  }
101037
- function hexToBytes13(hex7) {
102387
+ function hexToBytes14(hex7) {
101038
102388
  if (typeof hex7 !== "string")
101039
102389
  throw new Error("hex string expected, got " + typeof hex7);
101040
102390
  const len = hex7.length;
@@ -101052,27 +102402,27 @@ function hexToBytes13(hex7) {
101052
102402
  return array2;
101053
102403
  }
101054
102404
  function bytesToNumberBE6(bytes10) {
101055
- return hexToNumber6(bytesToHex15(bytes10));
102405
+ return hexToNumber6(bytesToHex16(bytes10));
101056
102406
  }
101057
102407
  function bytesToNumberLE6(bytes10) {
101058
102408
  if (!u8a11(bytes10))
101059
102409
  throw new Error("Uint8Array expected");
101060
- return hexToNumber6(bytesToHex15(Uint8Array.from(bytes10).reverse()));
102410
+ return hexToNumber6(bytesToHex16(Uint8Array.from(bytes10).reverse()));
101061
102411
  }
101062
102412
  function numberToBytesBE6(n, len) {
101063
- return hexToBytes13(n.toString(16).padStart(len * 2, "0"));
102413
+ return hexToBytes14(n.toString(16).padStart(len * 2, "0"));
101064
102414
  }
101065
102415
  function numberToBytesLE6(n, len) {
101066
102416
  return numberToBytesBE6(n, len).reverse();
101067
102417
  }
101068
102418
  function numberToVarBytesBE4(n) {
101069
- return hexToBytes13(numberToHexUnpadded6(n));
102419
+ return hexToBytes14(numberToHexUnpadded6(n));
101070
102420
  }
101071
102421
  function ensureBytes5(title, hex7, expectedLength) {
101072
102422
  let res;
101073
102423
  if (typeof hex7 === "string") {
101074
102424
  try {
101075
- res = hexToBytes13(hex7);
102425
+ res = hexToBytes14(hex7);
101076
102426
  } catch (e29) {
101077
102427
  throw new Error(`${title} must be valid hex string, got "${hex7}". Cause: ${e29}`);
101078
102428
  }
@@ -101683,7 +103033,7 @@ function weierstrassPoints4(opts) {
101683
103033
  const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
101684
103034
  if (lengths && typeof key !== "bigint") {
101685
103035
  if (key instanceof Uint8Array)
101686
- key = bytesToHex15(key);
103036
+ key = bytesToHex16(key);
101687
103037
  if (typeof key !== "string" || !lengths.includes(key.length))
101688
103038
  throw new Error("Invalid key");
101689
103039
  key = key.padStart(nByteLength * 2, "0");
@@ -101974,7 +103324,7 @@ function weierstrassPoints4(opts) {
101974
103324
  return toBytes12(Point5, this, isCompressed);
101975
103325
  }
101976
103326
  toHex(isCompressed = true) {
101977
- return bytesToHex15(this.toRawBytes(isCompressed));
103327
+ return bytesToHex16(this.toRawBytes(isCompressed));
101978
103328
  }
101979
103329
  }
101980
103330
  Point5.BASE = new Point5(CURVE.Gx, CURVE.Gy, Fp6.ONE);
@@ -102052,7 +103402,7 @@ function weierstrass6(curveDef) {
102052
103402
  }
102053
103403
  }
102054
103404
  });
102055
- const numToNByteStr = (num2) => bytesToHex15(numberToBytesBE6(num2, CURVE.nByteLength));
103405
+ const numToNByteStr = (num2) => bytesToHex16(numberToBytesBE6(num2, CURVE.nByteLength));
102056
103406
  function isBiggerThanHalfOrder(number13) {
102057
103407
  const HALF = CURVE_ORDER >> _1n32;
102058
103408
  return number13 > HALF;
@@ -102113,13 +103463,13 @@ function weierstrass6(curveDef) {
102113
103463
  return this.hasHighS() ? new Signature(this.r, modN4(-this.s), this.recovery) : this;
102114
103464
  }
102115
103465
  toDERRawBytes() {
102116
- return hexToBytes13(this.toDERHex());
103466
+ return hexToBytes14(this.toDERHex());
102117
103467
  }
102118
103468
  toDERHex() {
102119
103469
  return DER6.hexFromSig({ r: this.r, s: this.s });
102120
103470
  }
102121
103471
  toCompactRawBytes() {
102122
- return hexToBytes13(this.toCompactHex());
103472
+ return hexToBytes14(this.toCompactHex());
102123
103473
  }
102124
103474
  toCompactHex() {
102125
103475
  return numToNByteStr(this.r) + numToNByteStr(this.s);
@@ -102545,7 +103895,7 @@ var isLE11 = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
102545
103895
  if (!isLE11)
102546
103896
  throw new Error("Non little-endian hardware is not supported");
102547
103897
  var hexes12 = Array.from({ length: 256 }, (v4, i6) => i6.toString(16).padStart(2, "0"));
102548
- function bytesToHex16(bytes10) {
103898
+ function bytesToHex17(bytes10) {
102549
103899
  if (!u8a12(bytes10))
102550
103900
  throw new Error("Uint8Array expected");
102551
103901
  let hex7 = "";
@@ -102554,7 +103904,7 @@ function bytesToHex16(bytes10) {
102554
103904
  }
102555
103905
  return hex7;
102556
103906
  }
102557
- function hexToBytes14(hex7) {
103907
+ function hexToBytes15(hex7) {
102558
103908
  if (typeof hex7 !== "string")
102559
103909
  throw new Error("hex string expected, got " + typeof hex7);
102560
103910
  const len = hex7.length;
@@ -103322,7 +104672,7 @@ var isLE12 = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
103322
104672
  if (!isLE12)
103323
104673
  throw new Error("Non little-endian hardware is not supported");
103324
104674
  var hexes13 = /* @__PURE__ */ Array.from({ length: 256 }, (_3, i6) => i6.toString(16).padStart(2, "0"));
103325
- function bytesToHex17(bytes12) {
104675
+ function bytesToHex18(bytes12) {
103326
104676
  bytes11(bytes12);
103327
104677
  let hex8 = "";
103328
104678
  for (let i6 = 0;i6 < bytes12.length; i6++) {
@@ -103340,7 +104690,7 @@ function asciiToBase165(char) {
103340
104690
  return char - (asciis5._a - 10);
103341
104691
  return;
103342
104692
  }
103343
- function hexToBytes15(hex8) {
104693
+ function hexToBytes16(hex8) {
103344
104694
  if (typeof hex8 !== "string")
103345
104695
  throw new Error("hex string expected, got " + typeof hex8);
103346
104696
  const hl = hex8.length;
@@ -104883,8 +106233,8 @@ __export4(utils_exports3, {
104883
106233
  Queue: () => Queue3,
104884
106234
  QueueNode: () => QueueNode3,
104885
106235
  binarySearch: () => binarySearch5,
104886
- bytesToHex: () => bytesToHex16,
104887
- hexToBytes: () => hexToBytes14,
106236
+ bytesToHex: () => bytesToHex17,
106237
+ hexToBytes: () => hexToBytes15,
104888
106238
  insertEventIntoAscendingList: () => insertEventIntoAscendingList5,
104889
106239
  insertEventIntoDescendingList: () => insertEventIntoDescendingList5,
104890
106240
  normalizeURL: () => normalizeURL5,
@@ -105010,13 +106360,13 @@ var JS6 = class {
105010
106360
  return schnorr5.utils.randomPrivateKey();
105011
106361
  }
105012
106362
  getPublicKey(secretKey) {
105013
- return bytesToHex16(schnorr5.getPublicKey(secretKey));
106363
+ return bytesToHex17(schnorr5.getPublicKey(secretKey));
105014
106364
  }
105015
106365
  finalizeEvent(t, secretKey) {
105016
106366
  const event7 = t;
105017
- event7.pubkey = bytesToHex16(schnorr5.getPublicKey(secretKey));
106367
+ event7.pubkey = bytesToHex17(schnorr5.getPublicKey(secretKey));
105018
106368
  event7.id = getEventHash6(event7);
105019
- event7.sig = bytesToHex16(schnorr5.sign(getEventHash6(event7), secretKey));
106369
+ event7.sig = bytesToHex17(schnorr5.sign(getEventHash6(event7), secretKey));
105020
106370
  event7[verifiedSymbol9] = true;
105021
106371
  return event7;
105022
106372
  }
@@ -105045,7 +106395,7 @@ function serializeEvent6(evt) {
105045
106395
  }
105046
106396
  function getEventHash6(event7) {
105047
106397
  let eventHash = sha25611(utf8Encoder9.encode(serializeEvent6(event7)));
105048
- return bytesToHex16(eventHash);
106398
+ return bytesToHex17(eventHash);
105049
106399
  }
105050
106400
  var i6 = new JS6;
105051
106401
  var generateSecretKey6 = i6.generateSecretKey;
@@ -105893,7 +107243,7 @@ function decode6(code) {
105893
107243
  return {
105894
107244
  type: "nprofile",
105895
107245
  data: {
105896
- pubkey: bytesToHex16(tlv[0][0]),
107246
+ pubkey: bytesToHex17(tlv[0][0]),
105897
107247
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder9.decode(d)) : []
105898
107248
  }
105899
107249
  };
@@ -105911,10 +107261,10 @@ function decode6(code) {
105911
107261
  return {
105912
107262
  type: "nevent",
105913
107263
  data: {
105914
- id: bytesToHex16(tlv[0][0]),
107264
+ id: bytesToHex17(tlv[0][0]),
105915
107265
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder9.decode(d)) : [],
105916
- author: tlv[2]?.[0] ? bytesToHex16(tlv[2][0]) : undefined,
105917
- kind: tlv[3]?.[0] ? parseInt(bytesToHex16(tlv[3][0]), 16) : undefined
107266
+ author: tlv[2]?.[0] ? bytesToHex17(tlv[2][0]) : undefined,
107267
+ kind: tlv[3]?.[0] ? parseInt(bytesToHex17(tlv[3][0]), 16) : undefined
105918
107268
  }
105919
107269
  };
105920
107270
  }
@@ -105934,8 +107284,8 @@ function decode6(code) {
105934
107284
  type: "naddr",
105935
107285
  data: {
105936
107286
  identifier: utf8Decoder9.decode(tlv[0][0]),
105937
- pubkey: bytesToHex16(tlv[2][0]),
105938
- kind: parseInt(bytesToHex16(tlv[3][0]), 16),
107287
+ pubkey: bytesToHex17(tlv[2][0]),
107288
+ kind: parseInt(bytesToHex17(tlv[3][0]), 16),
105939
107289
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder9.decode(d)) : []
105940
107290
  }
105941
107291
  };
@@ -105944,7 +107294,7 @@ function decode6(code) {
105944
107294
  return { type: prefix, data };
105945
107295
  case "npub":
105946
107296
  case "note":
105947
- return { type: prefix, data: bytesToHex16(data) };
107297
+ return { type: prefix, data: bytesToHex17(data) };
105948
107298
  default:
105949
107299
  throw new Error(`unknown prefix ${prefix}`);
105950
107300
  }
@@ -105968,10 +107318,10 @@ function nsecEncode4(key) {
105968
107318
  return encodeBytes4("nsec", key);
105969
107319
  }
105970
107320
  function npubEncode5(hex8) {
105971
- return encodeBytes4("npub", hexToBytes14(hex8));
107321
+ return encodeBytes4("npub", hexToBytes15(hex8));
105972
107322
  }
105973
107323
  function noteEncode4(hex8) {
105974
- return encodeBytes4("note", hexToBytes14(hex8));
107324
+ return encodeBytes4("note", hexToBytes15(hex8));
105975
107325
  }
105976
107326
  function encodeBech324(prefix, data) {
105977
107327
  let words = bech325.toWords(data);
@@ -105982,7 +107332,7 @@ function encodeBytes4(prefix, bytes12) {
105982
107332
  }
105983
107333
  function nprofileEncode4(profile6) {
105984
107334
  let data = encodeTLV4({
105985
- 0: [hexToBytes14(profile6.pubkey)],
107335
+ 0: [hexToBytes15(profile6.pubkey)],
105986
107336
  1: (profile6.relays || []).map((url4) => utf8Encoder9.encode(url4))
105987
107337
  });
105988
107338
  return encodeBech324("nprofile", data);
@@ -105993,9 +107343,9 @@ function neventEncode4(event7) {
105993
107343
  kindArray = integerToUint8Array3(event7.kind);
105994
107344
  }
105995
107345
  let data = encodeTLV4({
105996
- 0: [hexToBytes14(event7.id)],
107346
+ 0: [hexToBytes15(event7.id)],
105997
107347
  1: (event7.relays || []).map((url4) => utf8Encoder9.encode(url4)),
105998
- 2: event7.author ? [hexToBytes14(event7.author)] : [],
107348
+ 2: event7.author ? [hexToBytes15(event7.author)] : [],
105999
107349
  3: kindArray ? [new Uint8Array(kindArray)] : []
106000
107350
  });
106001
107351
  return encodeBech324("nevent", data);
@@ -106006,7 +107356,7 @@ function naddrEncode4(addr) {
106006
107356
  let data = encodeTLV4({
106007
107357
  0: [utf8Encoder9.encode(addr.identifier)],
106008
107358
  1: (addr.relays || []).map((url4) => utf8Encoder9.encode(url4)),
106009
- 2: [hexToBytes14(addr.pubkey)],
107359
+ 2: [hexToBytes15(addr.pubkey)],
106010
107360
  3: [new Uint8Array(kind)]
106011
107361
  });
106012
107362
  return encodeBech324("naddr", data);
@@ -106030,7 +107380,7 @@ __export4(nip04_exports3, {
106030
107380
  encrypt: () => encrypt7
106031
107381
  });
106032
107382
  function encrypt7(secretKey, pubkey2, text) {
106033
- const privkey = secretKey instanceof Uint8Array ? bytesToHex16(secretKey) : secretKey;
107383
+ const privkey = secretKey instanceof Uint8Array ? bytesToHex17(secretKey) : secretKey;
106034
107384
  const key = secp256k15.getSharedSecret(privkey, "02" + pubkey2);
106035
107385
  const normalizedKey = getNormalizedX3(key);
106036
107386
  let iv = Uint8Array.from(randomBytes10(16));
@@ -106041,7 +107391,7 @@ function encrypt7(secretKey, pubkey2, text) {
106041
107391
  return `${ctb64}?iv=${ivb64}`;
106042
107392
  }
106043
107393
  function decrypt6(secretKey, pubkey2, data) {
106044
- const privkey = secretKey instanceof Uint8Array ? bytesToHex16(secretKey) : secretKey;
107394
+ const privkey = secretKey instanceof Uint8Array ? bytesToHex17(secretKey) : secretKey;
106045
107395
  let [ctb64, ivb64] = data.split("?iv=");
106046
107396
  let key = secp256k15.getSharedSecret(privkey, "02" + pubkey2);
106047
107397
  let normalizedKey = getNormalizedX3(key);
@@ -106264,7 +107614,7 @@ function minePow3(unsigned, difficulty) {
106264
107614
  return event7;
106265
107615
  }
106266
107616
  function fastEventHash3(evt) {
106267
- return bytesToHex16(sha25611(utf8Encoder9.encode(JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]))));
107617
+ return bytesToHex17(sha25611(utf8Encoder9.encode(JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]))));
106268
107618
  }
106269
107619
  var nip17_exports3 = {};
106270
107620
  __export4(nip17_exports3, {
@@ -107238,7 +108588,7 @@ var NegentropyStorageVector4 = class {
107238
108588
  insert(timestamp, id) {
107239
108589
  if (this.sealed)
107240
108590
  throw Error("already sealed");
107241
- const idb = hexToBytes15(id);
108591
+ const idb = hexToBytes16(id);
107242
108592
  if (idb.byteLength !== ID_SIZE4)
107243
108593
  throw Error("bad id size for added item");
107244
108594
  this.items.push({ timestamp, id: idb });
@@ -107332,10 +108682,10 @@ var Negentropy4 = class {
107332
108682
  let output12 = new WrappedBuffer4;
107333
108683
  output12.extend(new Uint8Array([PROTOCOL_VERSION4]));
107334
108684
  this.splitRange(0, this.storage.size(), this._bound(Number.MAX_VALUE), output12);
107335
- return bytesToHex17(output12.unwrap());
108685
+ return bytesToHex18(output12.unwrap());
107336
108686
  }
107337
108687
  reconcile(queryMsg, onhave, onneed) {
107338
- const query2 = new WrappedBuffer4(hexToBytes15(queryMsg));
108688
+ const query2 = new WrappedBuffer4(hexToBytes16(queryMsg));
107339
108689
  this.lastTimestampIn = this.lastTimestampOut = 0;
107340
108690
  let fullOutput = new WrappedBuffer4;
107341
108691
  fullOutput.extend(new Uint8Array([PROTOCOL_VERSION4]));
@@ -107378,22 +108728,22 @@ var Negentropy4 = class {
107378
108728
  let theirElems = {};
107379
108729
  for (let i22 = 0;i22 < numIds; i22++) {
107380
108730
  let e29 = getBytes5(query2, ID_SIZE4);
107381
- theirElems[bytesToHex17(e29)] = e29;
108731
+ theirElems[bytesToHex18(e29)] = e29;
107382
108732
  }
107383
108733
  skip3 = true;
107384
108734
  this.storage.iterate(lower, upper, (item) => {
107385
108735
  let k3 = item.id;
107386
- const id = bytesToHex17(k3);
108736
+ const id = bytesToHex18(k3);
107387
108737
  if (!theirElems[id]) {
107388
108738
  onhave?.(id);
107389
108739
  } else {
107390
- delete theirElems[bytesToHex17(k3)];
108740
+ delete theirElems[bytesToHex18(k3)];
107391
108741
  }
107392
108742
  return true;
107393
108743
  });
107394
108744
  if (onneed) {
107395
108745
  for (let v4 of Object.values(theirElems)) {
107396
- onneed(bytesToHex17(v4));
108746
+ onneed(bytesToHex18(v4));
107397
108747
  }
107398
108748
  }
107399
108749
  } else {
@@ -107411,7 +108761,7 @@ var Negentropy4 = class {
107411
108761
  prevIndex = upper;
107412
108762
  prevBound = currBound;
107413
108763
  }
107414
- return fullOutput.length === 1 ? null : bytesToHex17(fullOutput.unwrap());
108764
+ return fullOutput.length === 1 ? null : bytesToHex18(fullOutput.unwrap());
107415
108765
  }
107416
108766
  splitRange(lower, upper, upperBound, o) {
107417
108767
  let numElems = upper - lower;
@@ -107661,7 +109011,7 @@ function validateEventMethodTag3(event7, method) {
107661
109011
  }
107662
109012
  function hashPayload4(payload) {
107663
109013
  const hash10 = sha25611(utf8Encoder9.encode(JSON.stringify(payload)));
107664
- return bytesToHex16(hash10);
109014
+ return bytesToHex17(hash10);
107665
109015
  }
107666
109016
  function validateEventPayloadTag3(event7, payload) {
107667
109017
  const payloadTag = event7.tags.find((t) => t[0] === "payload");
@@ -107731,13 +109081,13 @@ var JS7 = class {
107731
109081
  return schnorr5.utils.randomPrivateKey();
107732
109082
  }
107733
109083
  getPublicKey(secretKey) {
107734
- return bytesToHex16(schnorr5.getPublicKey(secretKey));
109084
+ return bytesToHex17(schnorr5.getPublicKey(secretKey));
107735
109085
  }
107736
109086
  finalizeEvent(t, secretKey) {
107737
109087
  const event7 = t;
107738
- event7.pubkey = bytesToHex16(schnorr5.getPublicKey(secretKey));
109088
+ event7.pubkey = bytesToHex17(schnorr5.getPublicKey(secretKey));
107739
109089
  event7.id = getEventHash7(event7);
107740
- event7.sig = bytesToHex16(schnorr5.sign(getEventHash7(event7), secretKey));
109090
+ event7.sig = bytesToHex17(schnorr5.sign(getEventHash7(event7), secretKey));
107741
109091
  event7[verifiedSymbol10] = true;
107742
109092
  return event7;
107743
109093
  }
@@ -107766,7 +109116,7 @@ function serializeEvent7(evt) {
107766
109116
  }
107767
109117
  function getEventHash7(event7) {
107768
109118
  let eventHash = sha25611(utf8Encoder10.encode(serializeEvent7(event7)));
107769
- return bytesToHex16(eventHash);
109119
+ return bytesToHex17(eventHash);
107770
109120
  }
107771
109121
  var i7 = new JS7;
107772
109122
  var generateSecretKey7 = i7.generateSecretKey;
@@ -108003,7 +109353,7 @@ var utf8Decoder12 = new TextDecoder("utf-8");
108003
109353
  var utf8Encoder12 = new TextEncoder;
108004
109354
  var Bech32MaxSize5 = 5000;
108005
109355
  function npubEncode6(hex8) {
108006
- return encodeBytes5("npub", hexToBytes14(hex8));
109356
+ return encodeBytes5("npub", hexToBytes15(hex8));
108007
109357
  }
108008
109358
  function encodeBech325(prefix, data) {
108009
109359
  let words = bech325.toWords(data);
@@ -108014,7 +109364,7 @@ function encodeBytes5(prefix, bytes12) {
108014
109364
  }
108015
109365
  function nprofileEncode5(profile6) {
108016
109366
  let data = encodeTLV5({
108017
- 0: [hexToBytes14(profile6.pubkey)],
109367
+ 0: [hexToBytes15(profile6.pubkey)],
108018
109368
  1: (profile6.relays || []).map((url4) => utf8Encoder12.encode(url4))
108019
109369
  });
108020
109370
  return encodeBech325("nprofile", data);
@@ -111009,7 +112359,7 @@ class NotImplementedError extends WalletBaseError {
111009
112359
  code = "NOT_IMPLEMENTED";
111010
112360
  }
111011
112361
 
111012
- class InsufficientBalanceError2 extends WalletBaseError {
112362
+ class InsufficientBalanceError3 extends WalletBaseError {
111013
112363
  code = "INSUFFICIENT_BALANCE";
111014
112364
  }
111015
112365
 
@@ -111051,7 +112401,7 @@ function createWalletError(code, message) {
111051
112401
  case "NOT_IMPLEMENTED":
111052
112402
  return new NotImplementedError(message);
111053
112403
  case "INSUFFICIENT_BALANCE":
111054
- return new InsufficientBalanceError2(message);
112404
+ return new InsufficientBalanceError3(message);
111055
112405
  case "QUOTA_EXCEEDED":
111056
112406
  return new QuotaExceededError(message);
111057
112407
  case "RESTRICTED":
@@ -126995,7 +128345,7 @@ function rotl5(word, shift) {
126995
128345
  }
126996
128346
  var hasHexBuiltin4 = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function")();
126997
128347
  var hexes14 = /* @__PURE__ */ Array.from({ length: 256 }, (_4, i8) => i8.toString(16).padStart(2, "0"));
126998
- function bytesToHex18(bytes12) {
128348
+ function bytesToHex19(bytes12) {
126999
128349
  abytes7(bytes12);
127000
128350
  if (hasHexBuiltin4)
127001
128351
  return bytes12.toHex();
@@ -127015,7 +128365,7 @@ function asciiToBase166(ch) {
127015
128365
  return ch - (asciis6.a - 10);
127016
128366
  return;
127017
128367
  }
127018
- function hexToBytes16(hex8) {
128368
+ function hexToBytes17(hex8) {
127019
128369
  if (typeof hex8 !== "string")
127020
128370
  throw new Error("hex string expected, got " + typeof hex8);
127021
128371
  if (hasHexBuiltin4)
@@ -127774,15 +129124,15 @@ function hexToNumber7(hex8) {
127774
129124
  return hex8 === "" ? _0n35 : BigInt("0x" + hex8);
127775
129125
  }
127776
129126
  function bytesToNumberBE7(bytes12) {
127777
- return hexToNumber7(bytesToHex18(bytes12));
129127
+ return hexToNumber7(bytesToHex19(bytes12));
127778
129128
  }
127779
129129
  function bytesToNumberLE7(bytes12) {
127780
- return hexToNumber7(bytesToHex18(copyBytes4(abytes7(bytes12)).reverse()));
129130
+ return hexToNumber7(bytesToHex19(copyBytes4(abytes7(bytes12)).reverse()));
127781
129131
  }
127782
129132
  function numberToBytesBE7(n, len) {
127783
129133
  anumber6(len);
127784
129134
  n = abignumber2(n);
127785
- const res = hexToBytes16(n.toString(16).padStart(len * 2, "0"));
129135
+ const res = hexToBytes17(n.toString(16).padStart(len * 2, "0"));
127786
129136
  if (res.length !== len)
127787
129137
  throw new Error("number too large");
127788
129138
  return res;
@@ -128870,7 +130220,7 @@ function weierstrass7(params, extraOpts = {}) {
128870
130220
  return P3;
128871
130221
  }
128872
130222
  static fromHex(hex8) {
128873
- return Point6.fromBytes(hexToBytes16(hex8));
130223
+ return Point6.fromBytes(hexToBytes17(hex8));
128874
130224
  }
128875
130225
  get x() {
128876
130226
  return this.toAffine().x;
@@ -129063,7 +130413,7 @@ function weierstrass7(params, extraOpts = {}) {
129063
130413
  return encodePoint(Point6, this, isCompressed);
129064
130414
  }
129065
130415
  toHex(isCompressed = true) {
129066
- return bytesToHex18(this.toBytes(isCompressed));
130416
+ return bytesToHex19(this.toBytes(isCompressed));
129067
130417
  }
129068
130418
  toString() {
129069
130419
  return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
@@ -129218,7 +130568,7 @@ function ecdsa3(Point6, hash10, ecdsaOpts = {}) {
129218
130568
  return new Signature(Fn5.fromBytes(r), Fn5.fromBytes(s), recid);
129219
130569
  }
129220
130570
  static fromHex(hex8, format) {
129221
- return this.fromBytes(hexToBytes16(hex8), format);
130571
+ return this.fromBytes(hexToBytes17(hex8), format);
129222
130572
  }
129223
130573
  assertRecovery() {
129224
130574
  const { recovery } = this;
@@ -129253,7 +130603,7 @@ function ecdsa3(Point6, hash10, ecdsaOpts = {}) {
129253
130603
  toBytes(format = defaultSigOpts.format) {
129254
130604
  validateSigFormat3(format);
129255
130605
  if (format === "der")
129256
- return hexToBytes16(DER7.hexFromSig(this));
130606
+ return hexToBytes17(DER7.hexFromSig(this));
129257
130607
  const { r, s } = this;
129258
130608
  const rb = Fn5.toBytes(r);
129259
130609
  const sb = Fn5.toBytes(s);
@@ -129264,7 +130614,7 @@ function ecdsa3(Point6, hash10, ecdsaOpts = {}) {
129264
130614
  return concatBytes17(rb, sb);
129265
130615
  }
129266
130616
  toHex(format) {
129267
- return bytesToHex18(this.toBytes(format));
130617
+ return bytesToHex19(this.toBytes(format));
129268
130618
  }
129269
130619
  }
129270
130620
  const bits2int = ecdsaOpts.bits2int || function bits2int_def(bytes12) {
@@ -131124,8 +132474,8 @@ function validateEvent9(event11) {
131124
132474
  var utils_exports4 = {};
131125
132475
  __export5(utils_exports4, {
131126
132476
  binarySearch: () => binarySearch7,
131127
- bytesToHex: () => bytesToHex18,
131128
- hexToBytes: () => hexToBytes16,
132477
+ bytesToHex: () => bytesToHex19,
132478
+ hexToBytes: () => hexToBytes17,
131129
132479
  insertEventIntoAscendingList: () => insertEventIntoAscendingList7,
131130
132480
  insertEventIntoDescendingList: () => insertEventIntoDescendingList7,
131131
132481
  mergeReverseSortedLists: () => mergeReverseSortedLists,
@@ -131254,13 +132604,13 @@ var JS8 = class {
131254
132604
  return schnorr6.utils.randomSecretKey();
131255
132605
  }
131256
132606
  getPublicKey(secretKey) {
131257
- return bytesToHex18(schnorr6.getPublicKey(secretKey));
132607
+ return bytesToHex19(schnorr6.getPublicKey(secretKey));
131258
132608
  }
131259
132609
  finalizeEvent(t, secretKey) {
131260
132610
  const event11 = t;
131261
- event11.pubkey = bytesToHex18(schnorr6.getPublicKey(secretKey));
132611
+ event11.pubkey = bytesToHex19(schnorr6.getPublicKey(secretKey));
131262
132612
  event11.id = getEventHash8(event11);
131263
- event11.sig = bytesToHex18(schnorr6.sign(hexToBytes16(getEventHash8(event11)), secretKey));
132613
+ event11.sig = bytesToHex19(schnorr6.sign(hexToBytes17(getEventHash8(event11)), secretKey));
131264
132614
  event11[verifiedSymbol11] = true;
131265
132615
  return event11;
131266
132616
  }
@@ -131273,7 +132623,7 @@ var JS8 = class {
131273
132623
  event11[verifiedSymbol11] = false;
131274
132624
  return false;
131275
132625
  }
131276
- const valid = schnorr6.verify(hexToBytes16(event11.sig), hexToBytes16(hash10), hexToBytes16(event11.pubkey));
132626
+ const valid = schnorr6.verify(hexToBytes17(event11.sig), hexToBytes17(hash10), hexToBytes17(event11.pubkey));
131277
132627
  event11[verifiedSymbol11] = valid;
131278
132628
  return valid;
131279
132629
  } catch (err) {
@@ -131289,7 +132639,7 @@ function serializeEvent8(evt) {
131289
132639
  }
131290
132640
  function getEventHash8(event11) {
131291
132641
  let eventHash = sha25612(utf8Encoder13.encode(serializeEvent8(event11)));
131292
- return bytesToHex18(eventHash);
132642
+ return bytesToHex19(eventHash);
131293
132643
  }
131294
132644
  var i8 = new JS8;
131295
132645
  var generateSecretKey8 = i8.generateSecretKey;
@@ -132356,7 +133706,7 @@ function decode8(code) {
132356
133706
  return {
132357
133707
  type: "nprofile",
132358
133708
  data: {
132359
- pubkey: bytesToHex18(tlv[0][0]),
133709
+ pubkey: bytesToHex19(tlv[0][0]),
132360
133710
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder13.decode(d)) : []
132361
133711
  }
132362
133712
  };
@@ -132374,10 +133724,10 @@ function decode8(code) {
132374
133724
  return {
132375
133725
  type: "nevent",
132376
133726
  data: {
132377
- id: bytesToHex18(tlv[0][0]),
133727
+ id: bytesToHex19(tlv[0][0]),
132378
133728
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder13.decode(d)) : [],
132379
- author: tlv[2]?.[0] ? bytesToHex18(tlv[2][0]) : undefined,
132380
- kind: tlv[3]?.[0] ? parseInt(bytesToHex18(tlv[3][0]), 16) : undefined
133729
+ author: tlv[2]?.[0] ? bytesToHex19(tlv[2][0]) : undefined,
133730
+ kind: tlv[3]?.[0] ? parseInt(bytesToHex19(tlv[3][0]), 16) : undefined
132381
133731
  }
132382
133732
  };
132383
133733
  }
@@ -132397,8 +133747,8 @@ function decode8(code) {
132397
133747
  type: "naddr",
132398
133748
  data: {
132399
133749
  identifier: utf8Decoder13.decode(tlv[0][0]),
132400
- pubkey: bytesToHex18(tlv[2][0]),
132401
- kind: parseInt(bytesToHex18(tlv[3][0]), 16),
133750
+ pubkey: bytesToHex19(tlv[2][0]),
133751
+ kind: parseInt(bytesToHex19(tlv[3][0]), 16),
132402
133752
  relays: tlv[1] ? tlv[1].map((d) => utf8Decoder13.decode(d)) : []
132403
133753
  }
132404
133754
  };
@@ -132407,7 +133757,7 @@ function decode8(code) {
132407
133757
  return { type: prefix, data };
132408
133758
  case "npub":
132409
133759
  case "note":
132410
- return { type: prefix, data: bytesToHex18(data) };
133760
+ return { type: prefix, data: bytesToHex19(data) };
132411
133761
  default:
132412
133762
  throw new Error(`unknown prefix ${prefix}`);
132413
133763
  }
@@ -132433,10 +133783,10 @@ function nsecEncode6(key) {
132433
133783
  return encodeBytes6("nsec", key);
132434
133784
  }
132435
133785
  function npubEncode7(hex9) {
132436
- return encodeBytes6("npub", hexToBytes16(hex9));
133786
+ return encodeBytes6("npub", hexToBytes17(hex9));
132437
133787
  }
132438
133788
  function noteEncode6(hex9) {
132439
- return encodeBytes6("note", hexToBytes16(hex9));
133789
+ return encodeBytes6("note", hexToBytes17(hex9));
132440
133790
  }
132441
133791
  function encodeBech326(prefix, data) {
132442
133792
  let words = bech326.toWords(data);
@@ -132447,7 +133797,7 @@ function encodeBytes6(prefix, bytes12) {
132447
133797
  }
132448
133798
  function nprofileEncode6(profile9) {
132449
133799
  let data = encodeTLV6({
132450
- 0: [hexToBytes16(profile9.pubkey)],
133800
+ 0: [hexToBytes17(profile9.pubkey)],
132451
133801
  1: (profile9.relays || []).map((url5) => utf8Encoder13.encode(url5))
132452
133802
  });
132453
133803
  return encodeBech326("nprofile", data);
@@ -132458,9 +133808,9 @@ function neventEncode6(event11) {
132458
133808
  kindArray = integerToUint8Array4(event11.kind);
132459
133809
  }
132460
133810
  let data = encodeTLV6({
132461
- 0: [hexToBytes16(event11.id)],
133811
+ 0: [hexToBytes17(event11.id)],
132462
133812
  1: (event11.relays || []).map((url5) => utf8Encoder13.encode(url5)),
132463
- 2: event11.author ? [hexToBytes16(event11.author)] : [],
133813
+ 2: event11.author ? [hexToBytes17(event11.author)] : [],
132464
133814
  3: kindArray ? [new Uint8Array(kindArray)] : []
132465
133815
  });
132466
133816
  return encodeBech326("nevent", data);
@@ -132471,7 +133821,7 @@ function naddrEncode6(addr) {
132471
133821
  let data = encodeTLV6({
132472
133822
  0: [utf8Encoder13.encode(addr.identifier)],
132473
133823
  1: (addr.relays || []).map((url5) => utf8Encoder13.encode(url5)),
132474
- 2: [hexToBytes16(addr.pubkey)],
133824
+ 2: [hexToBytes17(addr.pubkey)],
132475
133825
  3: [new Uint8Array(kind)]
132476
133826
  });
132477
133827
  return encodeBech326("naddr", data);
@@ -132495,8 +133845,8 @@ __export5(nip04_exports4, {
132495
133845
  encrypt: () => encrypt9
132496
133846
  });
132497
133847
  function encrypt9(secretKey, pubkey3, text) {
132498
- const privkey = secretKey instanceof Uint8Array ? secretKey : hexToBytes16(secretKey);
132499
- const key = secp256k16.getSharedSecret(privkey, hexToBytes16("02" + pubkey3));
133848
+ const privkey = secretKey instanceof Uint8Array ? secretKey : hexToBytes17(secretKey);
133849
+ const key = secp256k16.getSharedSecret(privkey, hexToBytes17("02" + pubkey3));
132500
133850
  const normalizedKey = getNormalizedX4(key);
132501
133851
  let iv = Uint8Array.from(randomBytes11(16));
132502
133852
  let plaintext = utf8Encoder13.encode(text);
@@ -132506,9 +133856,9 @@ function encrypt9(secretKey, pubkey3, text) {
132506
133856
  return `${ctb64}?iv=${ivb64}`;
132507
133857
  }
132508
133858
  function decrypt8(secretKey, pubkey3, data) {
132509
- const privkey = secretKey instanceof Uint8Array ? secretKey : hexToBytes16(secretKey);
133859
+ const privkey = secretKey instanceof Uint8Array ? secretKey : hexToBytes17(secretKey);
132510
133860
  let [ctb64, ivb64] = data.split("?iv=");
132511
- let key = secp256k16.getSharedSecret(privkey, hexToBytes16("02" + pubkey3));
133861
+ let key = secp256k16.getSharedSecret(privkey, hexToBytes17("02" + pubkey3));
132512
133862
  let normalizedKey = getNormalizedX4(key);
132513
133863
  let iv = base649.decode(ivb64);
132514
133864
  let ciphertext = base649.decode(ctb64);
@@ -132736,7 +134086,7 @@ function minePow4(unsigned, difficulty) {
132736
134086
  tag2[1] = (++count).toString();
132737
134087
  const hash10 = sha25612(utf8Encoder13.encode(JSON.stringify([0, event11.pubkey, event11.created_at, event11.kind, event11.tags, event11.content])));
132738
134088
  if (getPowFromBytes(hash10) >= difficulty) {
132739
- event11.id = bytesToHex18(hash10);
134089
+ event11.id = bytesToHex19(hash10);
132740
134090
  break;
132741
134091
  }
132742
134092
  }
@@ -132770,7 +134120,7 @@ var minPlaintextSize4 = 1;
132770
134120
  var maxPlaintextSize4 = 4294967295;
132771
134121
  var extendedPrefixThreshold = 65536;
132772
134122
  function getConversationKey4(privkeyA, pubkeyB) {
132773
- const sharedX = secp256k16.getSharedSecret(privkeyA, hexToBytes16("02" + pubkeyB)).subarray(1, 33);
134123
+ const sharedX = secp256k16.getSharedSecret(privkeyA, hexToBytes17("02" + pubkeyB)).subarray(1, 33);
132774
134124
  return extract5(sha25612, sharedX, utf8Encoder13.encode("nip44-v2"));
132775
134125
  }
132776
134126
  function getMessageKeys4(conversationKey, nonce) {
@@ -133877,7 +135227,7 @@ var NegentropyStorageVector5 = class {
133877
135227
  insert(timestamp, id) {
133878
135228
  if (this.sealed)
133879
135229
  throw Error("already sealed");
133880
- const idb = hexToBytes16(id);
135230
+ const idb = hexToBytes17(id);
133881
135231
  if (idb.byteLength !== ID_SIZE5)
133882
135232
  throw Error("bad id size for added item");
133883
135233
  this.items.push({ timestamp, id: idb });
@@ -133971,10 +135321,10 @@ var Negentropy5 = class {
133971
135321
  let output12 = new WrappedBuffer5;
133972
135322
  output12.extend(new Uint8Array([PROTOCOL_VERSION5]));
133973
135323
  this.splitRange(0, this.storage.size(), this._bound(Number.MAX_VALUE), output12);
133974
- return bytesToHex18(output12.unwrap());
135324
+ return bytesToHex19(output12.unwrap());
133975
135325
  }
133976
135326
  reconcile(queryMsg, onhave, onneed) {
133977
- const query2 = new WrappedBuffer5(hexToBytes16(queryMsg));
135327
+ const query2 = new WrappedBuffer5(hexToBytes17(queryMsg));
133978
135328
  this.lastTimestampIn = this.lastTimestampOut = 0;
133979
135329
  let fullOutput = new WrappedBuffer5;
133980
135330
  fullOutput.extend(new Uint8Array([PROTOCOL_VERSION5]));
@@ -134017,22 +135367,22 @@ var Negentropy5 = class {
134017
135367
  let theirElems = {};
134018
135368
  for (let i22 = 0;i22 < numIds; i22++) {
134019
135369
  let e43 = getBytes6(query2, ID_SIZE5);
134020
- theirElems[bytesToHex18(e43)] = e43;
135370
+ theirElems[bytesToHex19(e43)] = e43;
134021
135371
  }
134022
135372
  skip4 = true;
134023
135373
  this.storage.iterate(lower, upper, (item) => {
134024
135374
  let k4 = item.id;
134025
- const id = bytesToHex18(k4);
135375
+ const id = bytesToHex19(k4);
134026
135376
  if (!theirElems[id]) {
134027
135377
  onhave?.(id);
134028
135378
  } else {
134029
- delete theirElems[bytesToHex18(k4)];
135379
+ delete theirElems[bytesToHex19(k4)];
134030
135380
  }
134031
135381
  return true;
134032
135382
  });
134033
135383
  if (onneed) {
134034
135384
  for (let v4 of Object.values(theirElems)) {
134035
- onneed(bytesToHex18(v4));
135385
+ onneed(bytesToHex19(v4));
134036
135386
  }
134037
135387
  }
134038
135388
  } else {
@@ -134050,7 +135400,7 @@ var Negentropy5 = class {
134050
135400
  prevIndex = upper;
134051
135401
  prevBound = currBound;
134052
135402
  }
134053
- return fullOutput.length === 1 ? null : bytesToHex18(fullOutput.unwrap());
135403
+ return fullOutput.length === 1 ? null : bytesToHex19(fullOutput.unwrap());
134054
135404
  }
134055
135405
  splitRange(lower, upper, upperBound, o) {
134056
135406
  let numElems = upper - lower;
@@ -134300,7 +135650,7 @@ function validateEventMethodTag4(event11, method) {
134300
135650
  }
134301
135651
  function hashPayload5(payload) {
134302
135652
  const hash10 = sha25612(utf8Encoder13.encode(JSON.stringify(payload)));
134303
- return bytesToHex18(hash10);
135653
+ return bytesToHex19(hash10);
134304
135654
  }
134305
135655
  function validateEventPayloadTag4(event11, payload) {
134306
135656
  const payloadTag = event11.tags.find((t) => t[0] === "payload");
@@ -134336,7 +135686,7 @@ async function validateEvent25(event11, url5, method, body) {
134336
135686
 
134337
135687
  // src/utils/nip98.ts
134338
135688
  var NIP98_KIND = 27235;
134339
- function hexToBytes17(hex9) {
135689
+ function hexToBytes18(hex9) {
134340
135690
  const normalized = hex9.trim().toLowerCase();
134341
135691
  if (!/^[a-f0-9]{64}$/.test(normalized)) {
134342
135692
  throw new Error("Expected a 64-char hex private key or an nsec private key.");
@@ -134359,7 +135709,7 @@ function parseSecretKey(value) {
134359
135709
  }
134360
135710
  return decoded.data;
134361
135711
  }
134362
- return hexToBytes17(trimmed);
135712
+ return hexToBytes18(trimmed);
134363
135713
  }
134364
135714
  async function sha256Hex(data) {
134365
135715
  const digest = await crypto.subtle.digest("SHA-256", new Uint8Array(data));
@@ -134543,6 +135893,75 @@ Installing routstr models in opencode.json...`);
134543
135893
  import { existsSync as existsSync5, mkdirSync as mkdirSync5 } from "fs";
134544
135894
  import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
134545
135895
  import { dirname as dirname3 } from "path";
135896
+ var PI_THINKING_LEVELS = [
135897
+ "off",
135898
+ "minimal",
135899
+ "low",
135900
+ "medium",
135901
+ "high",
135902
+ "xhigh",
135903
+ "max"
135904
+ ];
135905
+ var THINKING_LEVEL_VALUES = {
135906
+ off: "none",
135907
+ minimal: "minimal",
135908
+ low: "low",
135909
+ medium: "medium",
135910
+ high: "high",
135911
+ xhigh: "xhigh",
135912
+ max: "max"
135913
+ };
135914
+ function deriveThinkingFields(model4) {
135915
+ const reasoning = model4.reasoning;
135916
+ if (!reasoning)
135917
+ return null;
135918
+ const supported = (reasoning.supported_efforts ?? []).filter((effort) => typeof effort === "string").map((effort) => effort.trim().toLowerCase()).filter(Boolean);
135919
+ if (supported.length === 0)
135920
+ return null;
135921
+ const allowed = new Set(supported);
135922
+ if (reasoning.mandatory === true)
135923
+ allowed.delete("none");
135924
+ const thinkingLevelMap = {};
135925
+ for (const level of PI_THINKING_LEVELS) {
135926
+ const value = THINKING_LEVEL_VALUES[level];
135927
+ thinkingLevelMap[level] = allowed.has(value) ? value : null;
135928
+ }
135929
+ return { reasoning: true, thinkingLevelMap };
135930
+ }
135931
+ var isDeepSeekModel = (id) => id.startsWith("deepseek");
135932
+ function buildPiModelEntry(model4, previous) {
135933
+ const entry = { id: model4.id };
135934
+ if (model4.context_length !== undefined && model4.context_length > 0) {
135935
+ entry.contextWindow = model4.context_length;
135936
+ }
135937
+ if (model4.name) {
135938
+ entry.name = model4.name;
135939
+ }
135940
+ const mods = model4.architecture?.input_modalities ?? [];
135941
+ const input = [];
135942
+ if (mods.includes("text"))
135943
+ input.push("text");
135944
+ if (mods.includes("image"))
135945
+ input.push("image");
135946
+ entry.input = input;
135947
+ const derived = deriveThinkingFields(model4);
135948
+ if (derived) {
135949
+ entry.reasoning = derived.reasoning;
135950
+ entry.thinkingLevelMap = derived.thinkingLevelMap;
135951
+ } else {
135952
+ if (previous?.reasoning !== undefined)
135953
+ entry.reasoning = previous.reasoning;
135954
+ if (previous?.thinkingLevelMap !== undefined) {
135955
+ entry.thinkingLevelMap = previous.thinkingLevelMap;
135956
+ }
135957
+ }
135958
+ if (isDeepSeekModel(model4.id)) {
135959
+ entry.compat = { ...previous?.compat ?? {}, supportsDeveloperRole: false };
135960
+ } else if (previous?.compat !== undefined) {
135961
+ entry.compat = previous.compat;
135962
+ }
135963
+ return entry;
135964
+ }
134546
135965
  async function installPiIntegration(config2, apiKey, integrationConfig) {
134547
135966
  const { name: name16, configPath } = integrationConfig;
134548
135967
  console.log(`
@@ -134571,30 +135990,7 @@ Installing routstr models in pi models.json...`);
134571
135990
  return;
134572
135991
  }
134573
135992
  const existingModels = new Map((piConfig.providers["routstr"]?.models ?? []).map((m) => [m.id, m]));
134574
- const providerModels = models.map((model4) => {
134575
- const previous = existingModels.get(model4.id);
134576
- const entry = { id: model4.id };
134577
- if (model4.context_length !== undefined && model4.context_length > 0) {
134578
- entry.contextWindow = model4.context_length;
134579
- }
134580
- if (model4.name) {
134581
- entry.name = model4.name;
134582
- }
134583
- const mods = model4.architecture?.input_modalities ?? [];
134584
- const input = [];
134585
- if (mods.includes("text"))
134586
- input.push("text");
134587
- if (mods.includes("image"))
134588
- input.push("image");
134589
- entry.input = input;
134590
- if (previous?.reasoning !== undefined)
134591
- entry.reasoning = previous.reasoning;
134592
- if (previous?.thinkingLevelMap !== undefined)
134593
- entry.thinkingLevelMap = previous.thinkingLevelMap;
134594
- if (previous?.compat !== undefined)
134595
- entry.compat = previous.compat;
134596
- return entry;
134597
- });
135993
+ const providerModels = models.map((model4) => buildPiModelEntry(model4, existingModels.get(model4.id)));
134598
135994
  piConfig.providers["routstr"] = {
134599
135995
  baseUrl,
134600
135996
  api: "openai-completions",
@@ -135188,6 +136584,32 @@ async function getUsageSummary(driver, clients, tzOffsetMinutes, clientFilter) {
135188
136584
  return summary;
135189
136585
  }
135190
136586
 
136587
+ // src/daemon/http/request-body.ts
136588
+ var OPENAI_JSON_BODY_PATH_SUFFIXES = [
136589
+ "/chat/completions",
136590
+ "/completions",
136591
+ "/responses"
136592
+ ];
136593
+ function isOpenAiJsonBodyPath2(pathname) {
136594
+ const path2 = (pathname.split("?")[0] ?? "").replace(/\/+$/, "");
136595
+ return OPENAI_JSON_BODY_PATH_SUFFIXES.some((suffix) => path2.endsWith(suffix));
136596
+ }
136597
+ function applyDefaultOutputTokenLimit(pathname, body, maxTokens) {
136598
+ if (!(maxTokens > 0) || !isOpenAiJsonBodyPath2(pathname)) {
136599
+ return false;
136600
+ }
136601
+ if (pathname.split("?")[0].replace(/\/+$/, "").endsWith("/responses")) {
136602
+ if (typeof body.max_output_tokens === "number")
136603
+ return false;
136604
+ body.max_output_tokens = maxTokens;
136605
+ return true;
136606
+ }
136607
+ if (typeof body.max_tokens === "number")
136608
+ return false;
136609
+ body.max_tokens = maxTokens;
136610
+ return true;
136611
+ }
136612
+
135191
136613
  // src/daemon/http/index.ts
135192
136614
  var HOP_BY_HOP_HEADERS = new Set([
135193
136615
  "connection",
@@ -136425,16 +137847,7 @@ function createDaemonRequestHandler(deps) {
136425
137847
  sendJson(res, 400, { error: "Missing required 'model' field." });
136426
137848
  return;
136427
137849
  }
136428
- if (deps.maxTokens > 0) {
136429
- const isResponsesPath = url5.pathname.includes("/responses");
136430
- if (isResponsesPath) {
136431
- if (typeof bodyObj.max_output_tokens !== "number") {
136432
- bodyObj.max_output_tokens = deps.maxTokens;
136433
- }
136434
- } else if (typeof bodyObj.max_tokens !== "number") {
136435
- bodyObj.max_tokens = deps.maxTokens;
136436
- }
136437
- }
137850
+ applyDefaultOutputTokenLimit(url5.pathname, bodyObj, deps.maxTokens);
136438
137851
  const forcedProvider = url5.searchParams.get("provider") || req.headers["x-routstr-provider"] || deps.provider || undefined;
136439
137852
  const incomingHeaders = {};
136440
137853
  for (const [key, value] of Object.entries(req.headers)) {
@@ -137649,7 +139062,7 @@ var SqliteKeysetRepository = class {
137649
139062
  await this.db.run("DELETE FROM coco_cashu_keysets WHERE mintUrl = ? AND id = ?", [mintUrl, keysetId]);
137650
139063
  }
137651
139064
  };
137652
- function hexToBytes18(hexString) {
139065
+ function hexToBytes19(hexString) {
137653
139066
  if (!/^[0-9a-fA-F]+$/.test(hexString))
137654
139067
  throw new Error(`Invalid hex string: contains non-hex characters`);
137655
139068
  if (hexString.length % 2 !== 0)
@@ -137659,7 +139072,7 @@ function hexToBytes18(hexString) {
137659
139072
  throw new Error(`Failed to parse hex string`);
137660
139073
  return new Uint8Array(matches.map((byte) => parseInt(byte, 16)));
137661
139074
  }
137662
- function bytesToHex20(bytes12) {
139075
+ function bytesToHex21(bytes12) {
137663
139076
  return Array.from(bytes12).map((b2) => b2.toString(16).padStart(2, "0")).join("");
137664
139077
  }
137665
139078
  var SqliteKeyRingRepository = class {
@@ -137672,7 +139085,7 @@ var SqliteKeyRingRepository = class {
137672
139085
  if (!row)
137673
139086
  return null;
137674
139087
  try {
137675
- const secretKeyBytes = hexToBytes18(row.secretKey);
139088
+ const secretKeyBytes = hexToBytes19(row.secretKey);
137676
139089
  return {
137677
139090
  publicKeyHex: row.publicKey,
137678
139091
  secretKey: secretKeyBytes,
@@ -137683,7 +139096,7 @@ var SqliteKeyRingRepository = class {
137683
139096
  }
137684
139097
  }
137685
139098
  async setPersistedKeyPair(keyPair) {
137686
- const secretKeyHex = bytesToHex20(keyPair.secretKey);
139099
+ const secretKeyHex = bytesToHex21(keyPair.secretKey);
137687
139100
  await this.db.run(`INSERT INTO coco_cashu_keypairs (publicKey, secretKey, createdAt, derivationIndex)
137688
139101
  VALUES (?, ?, ?, ?)
137689
139102
  ON CONFLICT(publicKey) DO UPDATE SET
@@ -137701,7 +139114,7 @@ var SqliteKeyRingRepository = class {
137701
139114
  async getAllPersistedKeyPairs() {
137702
139115
  return (await this.db.all("SELECT publicKey, secretKey, derivationIndex FROM coco_cashu_keypairs")).map((row) => {
137703
139116
  try {
137704
- const secretKeyBytes = hexToBytes18(row.secretKey);
139117
+ const secretKeyBytes = hexToBytes19(row.secretKey);
137705
139118
  return {
137706
139119
  publicKeyHex: row.publicKey,
137707
139120
  secretKey: secretKeyBytes,
@@ -137717,7 +139130,7 @@ var SqliteKeyRingRepository = class {
137717
139130
  if (!row)
137718
139131
  return null;
137719
139132
  try {
137720
- const secretKeyBytes = hexToBytes18(row.secretKey);
139133
+ const secretKeyBytes = hexToBytes19(row.secretKey);
137721
139134
  return {
137722
139135
  publicKeyHex: row.publicKey,
137723
139136
  secretKey: secretKeyBytes,
@@ -139146,13 +140559,13 @@ var JS9 = class {
139146
140559
  return schnorr6.utils.randomSecretKey();
139147
140560
  }
139148
140561
  getPublicKey(secretKey) {
139149
- return bytesToHex18(schnorr6.getPublicKey(secretKey));
140562
+ return bytesToHex19(schnorr6.getPublicKey(secretKey));
139150
140563
  }
139151
140564
  finalizeEvent(t, secretKey) {
139152
140565
  const event11 = t;
139153
- event11.pubkey = bytesToHex18(schnorr6.getPublicKey(secretKey));
140566
+ event11.pubkey = bytesToHex19(schnorr6.getPublicKey(secretKey));
139154
140567
  event11.id = getEventHash9(event11);
139155
- event11.sig = bytesToHex18(schnorr6.sign(hexToBytes16(getEventHash9(event11)), secretKey));
140568
+ event11.sig = bytesToHex19(schnorr6.sign(hexToBytes17(getEventHash9(event11)), secretKey));
139156
140569
  event11[verifiedSymbol12] = true;
139157
140570
  return event11;
139158
140571
  }
@@ -139165,7 +140578,7 @@ var JS9 = class {
139165
140578
  event11[verifiedSymbol12] = false;
139166
140579
  return false;
139167
140580
  }
139168
- const valid = schnorr6.verify(hexToBytes16(event11.sig), hexToBytes16(hash10), hexToBytes16(event11.pubkey));
140581
+ const valid = schnorr6.verify(hexToBytes17(event11.sig), hexToBytes17(hash10), hexToBytes17(event11.pubkey));
139169
140582
  event11[verifiedSymbol12] = valid;
139170
140583
  return valid;
139171
140584
  } catch (err) {
@@ -139181,7 +140594,7 @@ function serializeEvent9(evt) {
139181
140594
  }
139182
140595
  function getEventHash9(event11) {
139183
140596
  let eventHash = sha25612(utf8Encoder14.encode(serializeEvent9(event11)));
139184
- return bytesToHex18(eventHash);
140597
+ return bytesToHex19(eventHash);
139185
140598
  }
139186
140599
  var i9 = new JS9;
139187
140600
  var generateSecretKey9 = i9.generateSecretKey;
@@ -139209,7 +140622,7 @@ async function getToken6(loginUrl, httpMethod, sign4, includeAuthorizationScheme
139209
140622
  }
139210
140623
  function hashPayload6(payload) {
139211
140624
  const hash10 = sha25612(utf8Encoder14.encode(JSON.stringify(payload)));
139212
- return bytesToHex18(hash10);
140625
+ return bytesToHex19(hash10);
139213
140626
  }
139214
140627
 
139215
140628
  // node_modules/npubcash-sdk/dist/npc-sdk.mjs
@@ -155929,6 +157342,44 @@ function legacyCocodPidPath() {
155929
157342
  return process.env.COCOD_PID || join11(legacyCocodDir(), "cocod.pid");
155930
157343
  }
155931
157344
 
157345
+ // src/daemon/wallet/trusted-mints.ts
157346
+ var DEFAULT_MINT_URL = "https://mint.cubabitcoin.org";
157347
+ var DEFAULT_TRUSTED_MINT_URLS = [
157348
+ DEFAULT_MINT_URL,
157349
+ "https://mint.minibits.cash/Bitcoin"
157350
+ ];
157351
+ function safeNormalizeMintUrl(mintUrl) {
157352
+ try {
157353
+ return normalizeMintUrl(mintUrl);
157354
+ } catch {
157355
+ return mintUrl;
157356
+ }
157357
+ }
157358
+ async function seedTrustedMints(wallet, defaultMintUrl, options = {}) {
157359
+ const seeds = options.seeds ?? DEFAULT_TRUSTED_MINT_URLS;
157360
+ const target = safeNormalizeMintUrl(defaultMintUrl);
157361
+ const trusted = new Set(wallet.trustedMints.map(safeNormalizeMintUrl));
157362
+ const attempted = new Set;
157363
+ for (const seed of [defaultMintUrl, ...seeds]) {
157364
+ const mintUrl = safeNormalizeMintUrl(seed);
157365
+ if (attempted.has(mintUrl))
157366
+ continue;
157367
+ attempted.add(mintUrl);
157368
+ if (trusted.has(mintUrl))
157369
+ continue;
157370
+ const isDefault = mintUrl === target;
157371
+ try {
157372
+ options.onProgress?.(`Adding ${isDefault ? "default" : "trusted"} mint: ${mintUrl}`);
157373
+ await wallet.addMint(mintUrl);
157374
+ trusted.add(mintUrl);
157375
+ } catch (error53) {
157376
+ if (isDefault)
157377
+ throw error53;
157378
+ options.onError?.(`Could not add trusted mint ${mintUrl}`, error53);
157379
+ }
157380
+ }
157381
+ }
157382
+
155932
157383
  // src/daemon/wallet/coco-client.ts
155933
157384
  var NPC_DEFAULT_BASE_URL = "https://npubx.cash";
155934
157385
  var STALE_SOCKET_ERROR_CODES = new Set([
@@ -155937,7 +157388,6 @@ var STALE_SOCKET_ERROR_CODES = new Set([
155937
157388
  "FailedToOpenSocket"
155938
157389
  ]);
155939
157390
  var STARTUP_LOG_PREFIX = "[routstrd:start]";
155940
- var DEFAULT_MINT_URL = "https://mint.cubabitcoin.org";
155941
157391
  function startupProgress(message) {
155942
157392
  logger5.info(message);
155943
157393
  console.log(`${STARTUP_LOG_PREFIX} ${message}`);
@@ -156596,10 +158046,15 @@ async function createCocoClient(options = {}) {
156596
158046
  const trustedMints = await coco.mint.getAllTrustedMints();
156597
158047
  const configuredDefault = walletConfig.defaultMintUrl;
156598
158048
  const defaultMintUrl = normalizeMintUrl(configuredDefault || trustedMints[0]?.mintUrl || DEFAULT_MINT_URL);
156599
- if (!trustedMints.some((mint) => mint.mintUrl === defaultMintUrl)) {
156600
- startupProgress(`Adding default mint: ${defaultMintUrl}`);
156601
- await coco.mint.addMint(defaultMintUrl, { trusted: true });
156602
- }
158049
+ await seedTrustedMints({
158050
+ trustedMints: trustedMints.map((mint) => mint.mintUrl),
158051
+ addMint: (mintUrl) => coco.mint.addMint(mintUrl, { trusted: true })
158052
+ }, defaultMintUrl, {
158053
+ onProgress: startupProgress,
158054
+ onError: (message, error53) => logger5.warn(message, {
158055
+ error: error53 instanceof Error ? error53.message : String(error53)
158056
+ })
158057
+ });
156603
158058
  walletConfig.defaultMintUrl = defaultMintUrl;
156604
158059
  if (configuredDefault !== defaultMintUrl) {
156605
158060
  saveConfig(walletConfig, configFile);