@owney/sdk 0.6.6-beta.6 → 0.6.6-beta.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
@@ -599,33 +599,17 @@ var clearSession = (address, chainId) => {
599
599
  } catch {
600
600
  }
601
601
  };
602
- var SESSION_KEY_PREFIX = "owney.zyfai.sessionkey";
603
- var buildSessionKeyKey = (address, chainId) => `${SESSION_KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
604
- var wasSessionKeyActivated = (address, chainId) => {
605
- const store = storage();
606
- if (!store) return false;
607
- try {
608
- return store.getItem(buildSessionKeyKey(address, chainId)) === "1";
609
- } catch {
610
- return false;
611
- }
612
- };
613
- var markSessionKeyActivated = (address, chainId) => {
614
- const store = storage();
615
- if (!store) return;
616
- try {
617
- store.setItem(buildSessionKeyKey(address, chainId), "1");
618
- } catch {
619
- }
620
- };
621
602
 
622
603
  // src/agents/zyfai/autoSelect.ts
623
- function buildAutoSelectUpdate(current, asset) {
624
- if (current.autoSelectProtocols === true) return null;
604
+ function buildAutoSelectUpdate(current, asset, chainId) {
605
+ const chains = current.chains ?? [];
606
+ const chainMissing = chainId !== void 0 && !chains.includes(chainId);
607
+ if (current.autoSelectProtocols === true && !chainMissing) return null;
608
+ const nextChains = chainMissing ? [...chains, chainId] : chains;
625
609
  return {
626
610
  asset,
627
611
  autoSelectProtocols: true,
628
- ...current.chains ? { chains: current.chains } : {}
612
+ ...nextChains.length ? { chains: nextChains } : {}
629
613
  };
630
614
  }
631
615
 
@@ -893,38 +877,45 @@ var ZyfaiAgent = class {
893
877
  );
894
878
  }
895
879
  }
896
- await this.ensureSessionKey(address, validChainId);
880
+ await this.ensureSessionKey(state, address, validChainId);
897
881
  }
898
882
  /**
899
- * Ensures a session key is active for THIS chain.
883
+ * Ensures the user has an active session key, creating one if absent.
900
884
  *
901
- * The Zyfai SDK tracks session-key state with a single global boolean — the
902
- * in-memory `hasActiveSessionKey` and the `/users/me` field of the same name
903
- * are neither chain-scoped. Once a key is activated on one chain, both
904
- * `getUserDetails()` and the SDK's own `createSessionKey` guard report
905
- * "active" on every other chain, so a deposit on a freshly-used chain runs
906
- * without a valid session key and reverts. See [[zyfai-per-chain-session-key]].
885
+ * The Zyfai session key is a single **per-user** record, not per-chain: its
886
+ * config (`/session-keys/config`) spans every supported chain and is signed
887
+ * in one shot, and the backend rejects `POST /session-keys/add` with 400
888
+ * "User already has an active session key" if one exists. So we must NOT try
889
+ * to (re)create a key per chain — that 400s and blocks the deposit. We only
890
+ * create when the user has none.
907
891
  *
908
- * We keep our own per-(address, chainId) record of activated chains (in
909
- * localStorage). On a miss we clear the SDK's global guard so
910
- * `createSessionKey` actually signs and activates for THIS chain.
892
+ * The one wrapper-side hardening that IS needed: a chain/account switch can
893
+ * fire the provider's `accountsChanged` → `disconnectAccount`, tearing down
894
+ * the zyfai connection (walletClient + authenticatedUserId both null) while
895
+ * our own `connectAuth` guard still believes this chain is connected and
896
+ * early-returns without reconnecting. `createSessionKey` then fails with
897
+ * "No account connected". Detect that and reconnect first.
911
898
  *
912
- * Cost: on a chain we've never recorded (e.g. a key created on another device
913
- * or a prior app version), this forces one `createSessionKey` — an extra
914
- * wallet signature, idempotent on the backend. A prompt-free variant would
915
- * read the session-validator module state on-chain instead of self-tracking.
899
+ * NOTE: whether a globally-active session key actually authorizes activity on
900
+ * a freshly-deployed Safe on a new chain is a backend/zyf question — the
901
+ * wrapper cannot force per-chain activation given the global 400 guard.
902
+ * See [[zyfai-per-chain-session-key]].
916
903
  */
917
- async ensureSessionKey(address, chainId) {
918
- if (wasSessionKeyActivated(address, chainId)) return;
904
+ async ensureSessionKey(state, address, chainId) {
919
905
  const internals = this.sdk;
920
- internals.hasActiveSessionKey = false;
921
- try {
922
- await this.sdk.createSessionKey(address, chainId);
923
- } catch (error) {
924
- if (!isAlreadyActiveSessionKeyError(error)) throw error;
925
- internals.hasActiveSessionKey = true;
906
+ if (!internals.walletClient || internals.authenticatedUserId === null) {
907
+ this.connectedChainId = null;
908
+ await this.connectAuth(state, chainId);
909
+ }
910
+ const user = await this.sdk.getUserDetails();
911
+ if (!user.hasActiveSessionKey) {
912
+ try {
913
+ await this.sdk.createSessionKey(address, chainId);
914
+ } catch (error) {
915
+ if (!isAlreadyActiveSessionKeyError(error)) throw error;
916
+ internals.hasActiveSessionKey = true;
917
+ }
926
918
  }
927
- markSessionKeyActivated(address, chainId);
928
919
  }
929
920
  /** Connect + resolve smart wallet address for read operations. */
930
921
  async resolveSmartWallet(state, chainId) {
@@ -1074,7 +1065,7 @@ var ZyfaiAgent = class {
1074
1065
  await this.connectAuth(state, chainId);
1075
1066
  const validChainId = isValidChainId(chainId);
1076
1067
  const raw = await this.sdk.getUserDetails();
1077
- await this.ensureSessionKey(this.getAddress(), validChainId);
1068
+ await this.ensureSessionKey(state, this.getAddress(), validChainId);
1078
1069
  return mapUserProfile(raw, this.connectedAddress);
1079
1070
  }
1080
1071
  async ensureAutoSelectProtocols(state, chainId, asset) {
@@ -1085,7 +1076,8 @@ var ZyfaiAgent = class {
1085
1076
  autoSelectProtocols: current.autoSelectProtocols,
1086
1077
  chains: current.chains
1087
1078
  },
1088
- asset
1079
+ asset,
1080
+ isValidChainId(chainId)
1089
1081
  );
1090
1082
  if (!update) return false;
1091
1083
  await this.sdk.updateUserProfile(update);
package/dist/index.js CHANGED
@@ -567,33 +567,17 @@ var clearSession = (address, chainId) => {
567
567
  } catch {
568
568
  }
569
569
  };
570
- var SESSION_KEY_PREFIX = "owney.zyfai.sessionkey";
571
- var buildSessionKeyKey = (address, chainId) => `${SESSION_KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
572
- var wasSessionKeyActivated = (address, chainId) => {
573
- const store = storage();
574
- if (!store) return false;
575
- try {
576
- return store.getItem(buildSessionKeyKey(address, chainId)) === "1";
577
- } catch {
578
- return false;
579
- }
580
- };
581
- var markSessionKeyActivated = (address, chainId) => {
582
- const store = storage();
583
- if (!store) return;
584
- try {
585
- store.setItem(buildSessionKeyKey(address, chainId), "1");
586
- } catch {
587
- }
588
- };
589
570
 
590
571
  // src/agents/zyfai/autoSelect.ts
591
- function buildAutoSelectUpdate(current, asset) {
592
- if (current.autoSelectProtocols === true) return null;
572
+ function buildAutoSelectUpdate(current, asset, chainId) {
573
+ const chains = current.chains ?? [];
574
+ const chainMissing = chainId !== void 0 && !chains.includes(chainId);
575
+ if (current.autoSelectProtocols === true && !chainMissing) return null;
576
+ const nextChains = chainMissing ? [...chains, chainId] : chains;
593
577
  return {
594
578
  asset,
595
579
  autoSelectProtocols: true,
596
- ...current.chains ? { chains: current.chains } : {}
580
+ ...nextChains.length ? { chains: nextChains } : {}
597
581
  };
598
582
  }
599
583
 
@@ -861,38 +845,45 @@ var ZyfaiAgent = class {
861
845
  );
862
846
  }
863
847
  }
864
- await this.ensureSessionKey(address, validChainId);
848
+ await this.ensureSessionKey(state, address, validChainId);
865
849
  }
866
850
  /**
867
- * Ensures a session key is active for THIS chain.
851
+ * Ensures the user has an active session key, creating one if absent.
868
852
  *
869
- * The Zyfai SDK tracks session-key state with a single global boolean — the
870
- * in-memory `hasActiveSessionKey` and the `/users/me` field of the same name
871
- * are neither chain-scoped. Once a key is activated on one chain, both
872
- * `getUserDetails()` and the SDK's own `createSessionKey` guard report
873
- * "active" on every other chain, so a deposit on a freshly-used chain runs
874
- * without a valid session key and reverts. See [[zyfai-per-chain-session-key]].
853
+ * The Zyfai session key is a single **per-user** record, not per-chain: its
854
+ * config (`/session-keys/config`) spans every supported chain and is signed
855
+ * in one shot, and the backend rejects `POST /session-keys/add` with 400
856
+ * "User already has an active session key" if one exists. So we must NOT try
857
+ * to (re)create a key per chain — that 400s and blocks the deposit. We only
858
+ * create when the user has none.
875
859
  *
876
- * We keep our own per-(address, chainId) record of activated chains (in
877
- * localStorage). On a miss we clear the SDK's global guard so
878
- * `createSessionKey` actually signs and activates for THIS chain.
860
+ * The one wrapper-side hardening that IS needed: a chain/account switch can
861
+ * fire the provider's `accountsChanged` → `disconnectAccount`, tearing down
862
+ * the zyfai connection (walletClient + authenticatedUserId both null) while
863
+ * our own `connectAuth` guard still believes this chain is connected and
864
+ * early-returns without reconnecting. `createSessionKey` then fails with
865
+ * "No account connected". Detect that and reconnect first.
879
866
  *
880
- * Cost: on a chain we've never recorded (e.g. a key created on another device
881
- * or a prior app version), this forces one `createSessionKey` — an extra
882
- * wallet signature, idempotent on the backend. A prompt-free variant would
883
- * read the session-validator module state on-chain instead of self-tracking.
867
+ * NOTE: whether a globally-active session key actually authorizes activity on
868
+ * a freshly-deployed Safe on a new chain is a backend/zyf question — the
869
+ * wrapper cannot force per-chain activation given the global 400 guard.
870
+ * See [[zyfai-per-chain-session-key]].
884
871
  */
885
- async ensureSessionKey(address, chainId) {
886
- if (wasSessionKeyActivated(address, chainId)) return;
872
+ async ensureSessionKey(state, address, chainId) {
887
873
  const internals = this.sdk;
888
- internals.hasActiveSessionKey = false;
889
- try {
890
- await this.sdk.createSessionKey(address, chainId);
891
- } catch (error) {
892
- if (!isAlreadyActiveSessionKeyError(error)) throw error;
893
- internals.hasActiveSessionKey = true;
874
+ if (!internals.walletClient || internals.authenticatedUserId === null) {
875
+ this.connectedChainId = null;
876
+ await this.connectAuth(state, chainId);
877
+ }
878
+ const user = await this.sdk.getUserDetails();
879
+ if (!user.hasActiveSessionKey) {
880
+ try {
881
+ await this.sdk.createSessionKey(address, chainId);
882
+ } catch (error) {
883
+ if (!isAlreadyActiveSessionKeyError(error)) throw error;
884
+ internals.hasActiveSessionKey = true;
885
+ }
894
886
  }
895
- markSessionKeyActivated(address, chainId);
896
887
  }
897
888
  /** Connect + resolve smart wallet address for read operations. */
898
889
  async resolveSmartWallet(state, chainId) {
@@ -1042,7 +1033,7 @@ var ZyfaiAgent = class {
1042
1033
  await this.connectAuth(state, chainId);
1043
1034
  const validChainId = isValidChainId(chainId);
1044
1035
  const raw = await this.sdk.getUserDetails();
1045
- await this.ensureSessionKey(this.getAddress(), validChainId);
1036
+ await this.ensureSessionKey(state, this.getAddress(), validChainId);
1046
1037
  return mapUserProfile(raw, this.connectedAddress);
1047
1038
  }
1048
1039
  async ensureAutoSelectProtocols(state, chainId, asset) {
@@ -1053,7 +1044,8 @@ var ZyfaiAgent = class {
1053
1044
  autoSelectProtocols: current.autoSelectProtocols,
1054
1045
  chains: current.chains
1055
1046
  },
1056
- asset
1047
+ asset,
1048
+ isValidChainId(chainId)
1057
1049
  );
1058
1050
  if (!update) return false;
1059
1051
  await this.sdk.updateUserProfile(update);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.6.6-beta.6",
3
+ "version": "0.6.6-beta.7",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",