@owney/sdk 0.6.7-beta.2 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -535,8 +535,7 @@ var storage = () => {
535
535
  return null;
536
536
  }
537
537
  };
538
- var buildKey = (address) => `${KEY_PREFIX}:${address.toLowerCase()}`;
539
- var legacyKeyPrefix = (address) => `${KEY_PREFIX}:${address.toLowerCase()}:`;
538
+ var buildKey = (address, chainId) => `${KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
540
539
  var isJwtExpired = (token) => {
541
540
  const parts = token.split(".");
542
541
  if (parts.length !== 3) return false;
@@ -553,37 +552,9 @@ var isJwtExpired = (token) => {
553
552
  };
554
553
  var memorySessions = /* @__PURE__ */ new Map();
555
554
  var isFreshSession = (session) => !!session && !!session.token && !isJwtExpired(session.token);
556
- var readLegacySession = (store, address) => {
557
- if (!store) return null;
558
- const prefix = legacyKeyPrefix(address);
559
- const legacyKeys = [];
560
- try {
561
- for (let i = 0; i < store.length; i++) {
562
- const key = store.key(i);
563
- if (key?.startsWith(prefix)) legacyKeys.push(key);
564
- }
565
- } catch {
566
- return null;
567
- }
568
- let adopted = null;
569
- for (const key of legacyKeys) {
570
- if (!adopted) {
571
- try {
572
- const parsed = JSON.parse(store.getItem(key) ?? "");
573
- if (isFreshSession(parsed)) adopted = parsed;
574
- } catch {
575
- }
576
- }
577
- try {
578
- store.removeItem(key);
579
- } catch {
580
- }
581
- }
582
- return adopted;
583
- };
584
- var readSession = (address, _chainId) => {
555
+ var readSession = (address, chainId) => {
585
556
  if (typeof window === "undefined") return null;
586
- const key = buildKey(address);
557
+ const key = buildKey(address, chainId);
587
558
  const store = storage();
588
559
  let raw = null;
589
560
  try {
@@ -604,19 +575,14 @@ var readSession = (address, _chainId) => {
604
575
  }
605
576
  return null;
606
577
  }
607
- const legacy = readLegacySession(store, address);
608
- if (legacy) {
609
- writeSession(address, _chainId, legacy);
610
- return legacy;
611
- }
612
578
  const cached = memorySessions.get(key);
613
579
  if (isFreshSession(cached)) return cached;
614
580
  if (cached) memorySessions.delete(key);
615
581
  return null;
616
582
  };
617
- var writeSession = (address, _chainId, session) => {
583
+ var writeSession = (address, chainId, session) => {
618
584
  if (typeof window === "undefined") return;
619
- const key = buildKey(address);
585
+ const key = buildKey(address, chainId);
620
586
  memorySessions.set(key, session);
621
587
  const store = storage();
622
588
  try {
@@ -624,15 +590,14 @@ var writeSession = (address, _chainId, session) => {
624
590
  } catch {
625
591
  }
626
592
  };
627
- var clearSession = (address, _chainId) => {
628
- const key = buildKey(address);
593
+ var clearSession = (address, chainId) => {
594
+ const key = buildKey(address, chainId);
629
595
  memorySessions.delete(key);
630
596
  const store = storage();
631
597
  try {
632
598
  store?.removeItem(key);
633
599
  } catch {
634
600
  }
635
- readLegacySession(store, address);
636
601
  };
637
602
 
638
603
  // src/agents/zyfai/autoSelect.ts
@@ -648,6 +613,18 @@ function buildAutoSelectUpdate(current, asset, chainId) {
648
613
  };
649
614
  }
650
615
 
616
+ // src/agents/zyfai/protocol-merge.ts
617
+ function buildProtocolMergeUpdate(available, current, asset) {
618
+ const enabled = current.protocols ?? [];
619
+ const enabledSet = new Set(enabled);
620
+ const missing = available.filter((p) => !enabledSet.has(p.id));
621
+ if (missing.length === 0) return null;
622
+ return {
623
+ asset,
624
+ protocols: [.../* @__PURE__ */ new Set([...enabled, ...missing.map((p) => p.id)])]
625
+ };
626
+ }
627
+
651
628
  // src/agents/zyfai/zyfai.agent.ts
652
629
  var DEFAULT_ZYFAI_RPC_URLS = {
653
630
  8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
@@ -952,6 +929,34 @@ var ZyfaiAgent = class {
952
929
  }
953
930
  }
954
931
  }
932
+ /**
933
+ * Sync newly-available protocols onto an existing user's profile at wallet
934
+ * connection. Zyfai's own protocol sync (`updateUserProtocols`) runs only when
935
+ * a session key is created, so existing users — who already have one — never
936
+ * pick up protocols Zyfai adds later. This closes that gap idempotently:
937
+ * it diffs available-vs-enabled by protocol id and writes the full union
938
+ * back, or does nothing when none are missing.
939
+ *
940
+ * Non-fatal: a sync failure must never block activation. Only "USDC" / "WETH"
941
+ * are modeled per-asset by the Zyfai profile API, so other assets are skipped.
942
+ */
943
+ async ensureProtocolsSynced(chainId, asset) {
944
+ if (asset !== "USDC" && asset !== "WETH") return;
945
+ try {
946
+ const [current, { protocols: available }] = await Promise.all([
947
+ this.sdk.getUserDetails(asset),
948
+ this.sdk.getAvailableProtocols(chainId)
949
+ ]);
950
+ const update = buildProtocolMergeUpdate(available, current, asset);
951
+ if (!update) return;
952
+ await this.sdk.updateUserProfile(update);
953
+ } catch (error) {
954
+ console.warn(
955
+ "[zyfai] ensureProtocolsSynced failed (non-fatal):",
956
+ error instanceof Error ? error.message : String(error)
957
+ );
958
+ }
959
+ }
955
960
  /** Connect + resolve smart wallet address for read operations. */
956
961
  async resolveSmartWallet(state, chainId) {
957
962
  await this.connectAuth(state, chainId);
@@ -983,6 +988,11 @@ var ZyfaiAgent = class {
983
988
  async activateAgent(state, chainId) {
984
989
  try {
985
990
  await this.connectAuth(state, chainId);
991
+ const validChainId = isValidChainId(chainId);
992
+ await Promise.all([
993
+ this.ensureProtocolsSynced(validChainId, "USDC"),
994
+ this.ensureProtocolsSynced(validChainId, "WETH")
995
+ ]);
986
996
  } catch (error) {
987
997
  throw error;
988
998
  }
@@ -2753,39 +2763,11 @@ var storage2 = () => {
2753
2763
  return null;
2754
2764
  }
2755
2765
  };
2756
- var buildKey2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}`;
2757
- var legacyKeyPrefix2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}:`;
2766
+ var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2758
2767
  var memorySiwxSessions = /* @__PURE__ */ new Map();
2759
- var readLegacySiwxSession = (store, address) => {
2760
- if (!store) return null;
2761
- const prefix = legacyKeyPrefix2(address);
2762
- const legacyKeys = [];
2763
- try {
2764
- for (let i = 0; i < store.length; i++) {
2765
- const key = store.key(i);
2766
- if (key?.startsWith(prefix)) legacyKeys.push(key);
2767
- }
2768
- } catch {
2769
- return null;
2770
- }
2771
- let adopted = null;
2772
- for (const key of legacyKeys) {
2773
- if (!adopted) {
2774
- try {
2775
- adopted = JSON.parse(store.getItem(key) ?? "");
2776
- } catch {
2777
- }
2778
- }
2779
- try {
2780
- store.removeItem(key);
2781
- } catch {
2782
- }
2783
- }
2784
- return adopted;
2785
- };
2786
2768
  var readSiwxSession = (address, chainId) => {
2787
2769
  if (typeof window === "undefined") return null;
2788
- const key = buildKey2(address);
2770
+ const key = buildKey2(address, chainId);
2789
2771
  const store = storage2();
2790
2772
  let raw = null;
2791
2773
  try {
@@ -2805,16 +2787,11 @@ var readSiwxSession = (address, chainId) => {
2805
2787
  return null;
2806
2788
  }
2807
2789
  }
2808
- const legacy = readLegacySiwxSession(store, address);
2809
- if (legacy) {
2810
- writeSiwxSession(address, chainId, legacy);
2811
- return legacy;
2812
- }
2813
2790
  return memorySiwxSessions.get(key) ?? null;
2814
2791
  };
2815
- var writeSiwxSession = (address, _chainId, session) => {
2792
+ var writeSiwxSession = (address, chainId, session) => {
2816
2793
  if (typeof window === "undefined") return;
2817
- const key = buildKey2(address);
2794
+ const key = buildKey2(address, chainId);
2818
2795
  memorySiwxSessions.set(key, session);
2819
2796
  const store = storage2();
2820
2797
  try {
@@ -2822,15 +2799,14 @@ var writeSiwxSession = (address, _chainId, session) => {
2822
2799
  } catch {
2823
2800
  }
2824
2801
  };
2825
- var clearSiwxSession = (address, _chainId) => {
2826
- const key = buildKey2(address);
2802
+ var clearSiwxSession = (address, chainId) => {
2803
+ const key = buildKey2(address, chainId);
2827
2804
  memorySiwxSessions.delete(key);
2828
2805
  const store = storage2();
2829
2806
  try {
2830
2807
  store?.removeItem(key);
2831
2808
  } catch {
2832
2809
  }
2833
- readLegacySiwxSession(store, address);
2834
2810
  };
2835
2811
 
2836
2812
  // src/agents/zyfai/zyfai.siwx.ts
@@ -2894,12 +2870,9 @@ function buildSIWXConfig(deps) {
2894
2870
  }
2895
2871
  if (!stored) return [];
2896
2872
  const session = {
2897
- // `stored.data` is kept AppKit-free in the cache, so narrow at the
2898
- // boundary. Echo the REQUESTED chain rather than the one originally
2899
- // signed: the Zyfai JWT is account-scoped (no chain claim), so one
2900
- // signature is valid for every chain, and AppKit would otherwise treat
2901
- // the session as not covering the active network and re-prompt.
2902
- data: { ...stored.data, chainId },
2873
+ // `stored.data.chainId` is a plain string in the cache (kept AppKit-free);
2874
+ // it always holds a valid CaipNetworkId here, so narrow at the boundary.
2875
+ data: stored.data,
2903
2876
  message: stored.message,
2904
2877
  signature: stored.signature
2905
2878
  };
package/dist/index.js CHANGED
@@ -503,8 +503,7 @@ var storage = () => {
503
503
  return null;
504
504
  }
505
505
  };
506
- var buildKey = (address) => `${KEY_PREFIX}:${address.toLowerCase()}`;
507
- var legacyKeyPrefix = (address) => `${KEY_PREFIX}:${address.toLowerCase()}:`;
506
+ var buildKey = (address, chainId) => `${KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
508
507
  var isJwtExpired = (token) => {
509
508
  const parts = token.split(".");
510
509
  if (parts.length !== 3) return false;
@@ -521,37 +520,9 @@ var isJwtExpired = (token) => {
521
520
  };
522
521
  var memorySessions = /* @__PURE__ */ new Map();
523
522
  var isFreshSession = (session) => !!session && !!session.token && !isJwtExpired(session.token);
524
- var readLegacySession = (store, address) => {
525
- if (!store) return null;
526
- const prefix = legacyKeyPrefix(address);
527
- const legacyKeys = [];
528
- try {
529
- for (let i = 0; i < store.length; i++) {
530
- const key = store.key(i);
531
- if (key?.startsWith(prefix)) legacyKeys.push(key);
532
- }
533
- } catch {
534
- return null;
535
- }
536
- let adopted = null;
537
- for (const key of legacyKeys) {
538
- if (!adopted) {
539
- try {
540
- const parsed = JSON.parse(store.getItem(key) ?? "");
541
- if (isFreshSession(parsed)) adopted = parsed;
542
- } catch {
543
- }
544
- }
545
- try {
546
- store.removeItem(key);
547
- } catch {
548
- }
549
- }
550
- return adopted;
551
- };
552
- var readSession = (address, _chainId) => {
523
+ var readSession = (address, chainId) => {
553
524
  if (typeof window === "undefined") return null;
554
- const key = buildKey(address);
525
+ const key = buildKey(address, chainId);
555
526
  const store = storage();
556
527
  let raw = null;
557
528
  try {
@@ -572,19 +543,14 @@ var readSession = (address, _chainId) => {
572
543
  }
573
544
  return null;
574
545
  }
575
- const legacy = readLegacySession(store, address);
576
- if (legacy) {
577
- writeSession(address, _chainId, legacy);
578
- return legacy;
579
- }
580
546
  const cached = memorySessions.get(key);
581
547
  if (isFreshSession(cached)) return cached;
582
548
  if (cached) memorySessions.delete(key);
583
549
  return null;
584
550
  };
585
- var writeSession = (address, _chainId, session) => {
551
+ var writeSession = (address, chainId, session) => {
586
552
  if (typeof window === "undefined") return;
587
- const key = buildKey(address);
553
+ const key = buildKey(address, chainId);
588
554
  memorySessions.set(key, session);
589
555
  const store = storage();
590
556
  try {
@@ -592,15 +558,14 @@ var writeSession = (address, _chainId, session) => {
592
558
  } catch {
593
559
  }
594
560
  };
595
- var clearSession = (address, _chainId) => {
596
- const key = buildKey(address);
561
+ var clearSession = (address, chainId) => {
562
+ const key = buildKey(address, chainId);
597
563
  memorySessions.delete(key);
598
564
  const store = storage();
599
565
  try {
600
566
  store?.removeItem(key);
601
567
  } catch {
602
568
  }
603
- readLegacySession(store, address);
604
569
  };
605
570
 
606
571
  // src/agents/zyfai/autoSelect.ts
@@ -616,6 +581,18 @@ function buildAutoSelectUpdate(current, asset, chainId) {
616
581
  };
617
582
  }
618
583
 
584
+ // src/agents/zyfai/protocol-merge.ts
585
+ function buildProtocolMergeUpdate(available, current, asset) {
586
+ const enabled = current.protocols ?? [];
587
+ const enabledSet = new Set(enabled);
588
+ const missing = available.filter((p) => !enabledSet.has(p.id));
589
+ if (missing.length === 0) return null;
590
+ return {
591
+ asset,
592
+ protocols: [.../* @__PURE__ */ new Set([...enabled, ...missing.map((p) => p.id)])]
593
+ };
594
+ }
595
+
619
596
  // src/agents/zyfai/zyfai.agent.ts
620
597
  var DEFAULT_ZYFAI_RPC_URLS = {
621
598
  8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
@@ -920,6 +897,34 @@ var ZyfaiAgent = class {
920
897
  }
921
898
  }
922
899
  }
900
+ /**
901
+ * Sync newly-available protocols onto an existing user's profile at wallet
902
+ * connection. Zyfai's own protocol sync (`updateUserProtocols`) runs only when
903
+ * a session key is created, so existing users — who already have one — never
904
+ * pick up protocols Zyfai adds later. This closes that gap idempotently:
905
+ * it diffs available-vs-enabled by protocol id and writes the full union
906
+ * back, or does nothing when none are missing.
907
+ *
908
+ * Non-fatal: a sync failure must never block activation. Only "USDC" / "WETH"
909
+ * are modeled per-asset by the Zyfai profile API, so other assets are skipped.
910
+ */
911
+ async ensureProtocolsSynced(chainId, asset) {
912
+ if (asset !== "USDC" && asset !== "WETH") return;
913
+ try {
914
+ const [current, { protocols: available }] = await Promise.all([
915
+ this.sdk.getUserDetails(asset),
916
+ this.sdk.getAvailableProtocols(chainId)
917
+ ]);
918
+ const update = buildProtocolMergeUpdate(available, current, asset);
919
+ if (!update) return;
920
+ await this.sdk.updateUserProfile(update);
921
+ } catch (error) {
922
+ console.warn(
923
+ "[zyfai] ensureProtocolsSynced failed (non-fatal):",
924
+ error instanceof Error ? error.message : String(error)
925
+ );
926
+ }
927
+ }
923
928
  /** Connect + resolve smart wallet address for read operations. */
924
929
  async resolveSmartWallet(state, chainId) {
925
930
  await this.connectAuth(state, chainId);
@@ -951,6 +956,11 @@ var ZyfaiAgent = class {
951
956
  async activateAgent(state, chainId) {
952
957
  try {
953
958
  await this.connectAuth(state, chainId);
959
+ const validChainId = isValidChainId(chainId);
960
+ await Promise.all([
961
+ this.ensureProtocolsSynced(validChainId, "USDC"),
962
+ this.ensureProtocolsSynced(validChainId, "WETH")
963
+ ]);
954
964
  } catch (error) {
955
965
  throw error;
956
966
  }
@@ -2725,39 +2735,11 @@ var storage2 = () => {
2725
2735
  return null;
2726
2736
  }
2727
2737
  };
2728
- var buildKey2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}`;
2729
- var legacyKeyPrefix2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}:`;
2738
+ var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2730
2739
  var memorySiwxSessions = /* @__PURE__ */ new Map();
2731
- var readLegacySiwxSession = (store, address) => {
2732
- if (!store) return null;
2733
- const prefix = legacyKeyPrefix2(address);
2734
- const legacyKeys = [];
2735
- try {
2736
- for (let i = 0; i < store.length; i++) {
2737
- const key = store.key(i);
2738
- if (key?.startsWith(prefix)) legacyKeys.push(key);
2739
- }
2740
- } catch {
2741
- return null;
2742
- }
2743
- let adopted = null;
2744
- for (const key of legacyKeys) {
2745
- if (!adopted) {
2746
- try {
2747
- adopted = JSON.parse(store.getItem(key) ?? "");
2748
- } catch {
2749
- }
2750
- }
2751
- try {
2752
- store.removeItem(key);
2753
- } catch {
2754
- }
2755
- }
2756
- return adopted;
2757
- };
2758
2740
  var readSiwxSession = (address, chainId) => {
2759
2741
  if (typeof window === "undefined") return null;
2760
- const key = buildKey2(address);
2742
+ const key = buildKey2(address, chainId);
2761
2743
  const store = storage2();
2762
2744
  let raw = null;
2763
2745
  try {
@@ -2777,16 +2759,11 @@ var readSiwxSession = (address, chainId) => {
2777
2759
  return null;
2778
2760
  }
2779
2761
  }
2780
- const legacy = readLegacySiwxSession(store, address);
2781
- if (legacy) {
2782
- writeSiwxSession(address, chainId, legacy);
2783
- return legacy;
2784
- }
2785
2762
  return memorySiwxSessions.get(key) ?? null;
2786
2763
  };
2787
- var writeSiwxSession = (address, _chainId, session) => {
2764
+ var writeSiwxSession = (address, chainId, session) => {
2788
2765
  if (typeof window === "undefined") return;
2789
- const key = buildKey2(address);
2766
+ const key = buildKey2(address, chainId);
2790
2767
  memorySiwxSessions.set(key, session);
2791
2768
  const store = storage2();
2792
2769
  try {
@@ -2794,15 +2771,14 @@ var writeSiwxSession = (address, _chainId, session) => {
2794
2771
  } catch {
2795
2772
  }
2796
2773
  };
2797
- var clearSiwxSession = (address, _chainId) => {
2798
- const key = buildKey2(address);
2774
+ var clearSiwxSession = (address, chainId) => {
2775
+ const key = buildKey2(address, chainId);
2799
2776
  memorySiwxSessions.delete(key);
2800
2777
  const store = storage2();
2801
2778
  try {
2802
2779
  store?.removeItem(key);
2803
2780
  } catch {
2804
2781
  }
2805
- readLegacySiwxSession(store, address);
2806
2782
  };
2807
2783
 
2808
2784
  // src/agents/zyfai/zyfai.siwx.ts
@@ -2866,12 +2842,9 @@ function buildSIWXConfig(deps) {
2866
2842
  }
2867
2843
  if (!stored) return [];
2868
2844
  const session = {
2869
- // `stored.data` is kept AppKit-free in the cache, so narrow at the
2870
- // boundary. Echo the REQUESTED chain rather than the one originally
2871
- // signed: the Zyfai JWT is account-scoped (no chain claim), so one
2872
- // signature is valid for every chain, and AppKit would otherwise treat
2873
- // the session as not covering the active network and re-prompt.
2874
- data: { ...stored.data, chainId },
2845
+ // `stored.data.chainId` is a plain string in the cache (kept AppKit-free);
2846
+ // it always holds a valid CaipNetworkId here, so narrow at the boundary.
2847
+ data: stored.data,
2875
2848
  message: stored.message,
2876
2849
  signature: stored.signature
2877
2850
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.6.7-beta.2",
3
+ "version": "0.6.7",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "test:watch": "vitest"
24
24
  },
25
25
  "dependencies": {
26
- "@zyfai/sdk": "0.2.40",
26
+ "@zyfai/sdk": "^0.2.41",
27
27
  "siwe": "^3.0.0",
28
28
  "viem": "^2.48.1"
29
29
  },