@owney/sdk 0.6.7 → 0.6.8-beta.2

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,7 +535,8 @@ var storage = () => {
535
535
  return null;
536
536
  }
537
537
  };
538
- var buildKey = (address, chainId) => `${KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
538
+ var buildKey = (address) => `${KEY_PREFIX}:${address.toLowerCase()}`;
539
+ var legacyKeyPrefix = (address) => `${KEY_PREFIX}:${address.toLowerCase()}:`;
539
540
  var isJwtExpired = (token) => {
540
541
  const parts = token.split(".");
541
542
  if (parts.length !== 3) return false;
@@ -552,9 +553,37 @@ var isJwtExpired = (token) => {
552
553
  };
553
554
  var memorySessions = /* @__PURE__ */ new Map();
554
555
  var isFreshSession = (session) => !!session && !!session.token && !isJwtExpired(session.token);
555
- var readSession = (address, chainId) => {
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) => {
556
585
  if (typeof window === "undefined") return null;
557
- const key = buildKey(address, chainId);
586
+ const key = buildKey(address);
558
587
  const store = storage();
559
588
  let raw = null;
560
589
  try {
@@ -575,14 +604,19 @@ var readSession = (address, chainId) => {
575
604
  }
576
605
  return null;
577
606
  }
607
+ const legacy = readLegacySession(store, address);
608
+ if (legacy) {
609
+ writeSession(address, _chainId, legacy);
610
+ return legacy;
611
+ }
578
612
  const cached = memorySessions.get(key);
579
613
  if (isFreshSession(cached)) return cached;
580
614
  if (cached) memorySessions.delete(key);
581
615
  return null;
582
616
  };
583
- var writeSession = (address, chainId, session) => {
617
+ var writeSession = (address, _chainId, session) => {
584
618
  if (typeof window === "undefined") return;
585
- const key = buildKey(address, chainId);
619
+ const key = buildKey(address);
586
620
  memorySessions.set(key, session);
587
621
  const store = storage();
588
622
  try {
@@ -590,14 +624,15 @@ var writeSession = (address, chainId, session) => {
590
624
  } catch {
591
625
  }
592
626
  };
593
- var clearSession = (address, chainId) => {
594
- const key = buildKey(address, chainId);
627
+ var clearSession = (address, _chainId) => {
628
+ const key = buildKey(address);
595
629
  memorySessions.delete(key);
596
630
  const store = storage();
597
631
  try {
598
632
  store?.removeItem(key);
599
633
  } catch {
600
634
  }
635
+ readLegacySession(store, address);
601
636
  };
602
637
 
603
638
  // src/agents/zyfai/autoSelect.ts
@@ -686,11 +721,15 @@ var ZyfaiAgent = class {
686
721
  // successful decode is cached forever; failures are NOT cached so a transient
687
722
  // RPC error retries on the next fetch.
688
723
  withdrawAmountCache = /* @__PURE__ */ new Map();
689
- constructor(apiKey, rpcUrls) {
724
+ constructor(apiKey, rpcUrls, referralSource) {
690
725
  this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
691
726
  this.sdk = new import_sdk.ZyfaiSDK({
692
727
  apiKey,
693
- rpcUrls: this.rpcUrls
728
+ rpcUrls: this.rpcUrls,
729
+ // Forwarded to /auth/login by the SDK's own SIWE handshake, so
730
+ // attribution survives without the AppKit SIWX config (which carried it
731
+ // via `createOwneySIWX({ referralSource })` when apps used the modal).
732
+ referralSource
694
733
  });
695
734
  this.installAuthCache();
696
735
  }
@@ -1012,7 +1051,14 @@ var ZyfaiAgent = class {
1012
1051
  amount
1013
1052
  );
1014
1053
  const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
1015
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1054
+ try {
1055
+ await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1056
+ } catch (logError) {
1057
+ console.warn(
1058
+ "[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
1059
+ logError
1060
+ );
1061
+ }
1016
1062
  return { txHash, smartWallet: wallet.address, amount };
1017
1063
  }
1018
1064
  const raw = await this.sdk.depositFunds(
@@ -1494,18 +1540,29 @@ function makeSponsoredDepositCallback(deps) {
1494
1540
  const wallet = deps.getWalletClient(cid);
1495
1541
  const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
1496
1542
  const validAfter = 0n;
1497
- const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
1543
+ const validBefore = BigInt(
1544
+ Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
1545
+ );
1498
1546
  const nonce = randomAuthNonce();
1499
1547
  const typedData = buildTransferWithAuthorizationTypedData({
1500
1548
  token,
1501
1549
  chainId: cid,
1502
1550
  tokenName,
1503
1551
  tokenVersion,
1504
- message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
1552
+ message: {
1553
+ from: deps.ownerAddress,
1554
+ to: smartWallet,
1555
+ value: BigInt(amount),
1556
+ validAfter,
1557
+ validBefore,
1558
+ nonce
1559
+ }
1505
1560
  });
1506
- const authSignature = await wallet.signTypedData(
1507
- { account: deps.ownerAddress, ...typedData }
1508
- );
1561
+ const authSignature = await wallet.signTypedData({
1562
+ account: deps.ownerAddress,
1563
+ ...typedData
1564
+ });
1565
+ deps.onApproved?.();
1509
1566
  const result = await post({
1510
1567
  baseUrl: deps.baseUrl,
1511
1568
  apiKey: deps.apiKey,
@@ -1589,7 +1646,10 @@ function makeSponsoredWethCallback(deps) {
1589
1646
  const cid = chainId;
1590
1647
  const token = deps.tokenAddressByChain[cid];
1591
1648
  if (!token) {
1592
- throw new OwneyError("CHAIN_UNSUPPORTED", `No sponsored WETH configured for chain ${chainId}`);
1649
+ throw new OwneyError(
1650
+ "CHAIN_UNSUPPORTED",
1651
+ `No sponsored WETH configured for chain ${chainId}`
1652
+ );
1593
1653
  }
1594
1654
  const amountWei = BigInt(amount);
1595
1655
  const pub = deps.getPublicClient(cid);
@@ -1601,9 +1661,15 @@ function makeSponsoredWethCallback(deps) {
1601
1661
  { token, chainId: cid, allowance: allowance.toString(), amount }
1602
1662
  );
1603
1663
  }
1604
- const relayer = await get({ baseUrl: deps.baseUrl, apiKey: deps.apiKey, chainId: cid });
1664
+ const relayer = await get({
1665
+ baseUrl: deps.baseUrl,
1666
+ apiKey: deps.apiKey,
1667
+ chainId: cid
1668
+ });
1605
1669
  const nonce = randomPermit2Nonce();
1606
- const deadline = BigInt(Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS);
1670
+ const deadline = BigInt(
1671
+ Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
1672
+ );
1607
1673
  const typedData = buildPermitTransferFromTypedData({
1608
1674
  chainId: cid,
1609
1675
  message: {
@@ -1614,9 +1680,11 @@ function makeSponsoredWethCallback(deps) {
1614
1680
  }
1615
1681
  });
1616
1682
  const wallet = deps.getWalletClient(cid);
1617
- const signature = await wallet.signTypedData(
1618
- { account: deps.ownerAddress, ...typedData }
1619
- );
1683
+ const signature = await wallet.signTypedData({
1684
+ account: deps.ownerAddress,
1685
+ ...typedData
1686
+ });
1687
+ deps.onApproved?.();
1620
1688
  const result = await post({
1621
1689
  baseUrl: deps.baseUrl,
1622
1690
  apiKey: deps.apiKey,
@@ -1687,6 +1755,7 @@ var OwneySDK = class {
1687
1755
  apiKey;
1688
1756
  zyfaiRpcUrls;
1689
1757
  routingApiBaseUrl;
1758
+ referralSource;
1690
1759
  cachedSponsoredCallback = null;
1691
1760
  cachedWethSponsoredCallback = null;
1692
1761
  initializingAgentsPromise = null;
@@ -1694,6 +1763,7 @@ var OwneySDK = class {
1694
1763
  this.apiKey = config.apiKey;
1695
1764
  this.zyfaiRpcUrls = config.zyfaiRpcUrls;
1696
1765
  this.routingApiBaseUrl = config.routingApiBaseUrl;
1766
+ this.referralSource = config.referralSource;
1697
1767
  }
1698
1768
  /**
1699
1769
  * Establish connection state for all subsequent SDK calls.
@@ -1777,14 +1847,16 @@ var OwneySDK = class {
1777
1847
  * provider with viem `custom(provider)` to read token meta and sign the
1778
1848
  * `TransferWithAuthorization`, then POSTs to the sponsor API.
1779
1849
  */
1780
- getDefaultSponsoredCallback() {
1781
- if (this.cachedSponsoredCallback) return this.cachedSponsoredCallback;
1850
+ getDefaultSponsoredCallback(onApproved) {
1851
+ if (!onApproved && this.cachedSponsoredCallback)
1852
+ return this.cachedSponsoredCallback;
1782
1853
  const provider = this.requireConnectedProvider();
1783
1854
  const owner = this.state.walletAddress;
1784
- this.cachedSponsoredCallback = makeSponsoredDepositCallback({
1855
+ const callback = makeSponsoredDepositCallback({
1785
1856
  apiKey: this.apiKey,
1786
1857
  baseUrl: this.routingApiBaseUrl,
1787
1858
  ownerAddress: owner,
1859
+ onApproved,
1788
1860
  tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
1789
1861
  // Casts work around viem's chain-narrowed Client vs the generic
1790
1862
  // PublicClient/WalletClient param types — structurally identical at
@@ -1799,7 +1871,8 @@ var OwneySDK = class {
1799
1871
  transport: (0, import_viem5.custom)(provider)
1800
1872
  })
1801
1873
  });
1802
- return this.cachedSponsoredCallback;
1874
+ if (!onApproved) this.cachedSponsoredCallback = callback;
1875
+ return callback;
1803
1876
  }
1804
1877
  /**
1805
1878
  * Lazily builds (and caches) the default Permit2 sponsored WETH deposit
@@ -1807,15 +1880,16 @@ var OwneySDK = class {
1807
1880
  * deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
1808
1881
  * `PermitTransferFrom` instead of an EIP-3009 authorization.
1809
1882
  */
1810
- getDefaultWethSponsoredCallback() {
1811
- if (this.cachedWethSponsoredCallback)
1883
+ getDefaultWethSponsoredCallback(onApproved) {
1884
+ if (!onApproved && this.cachedWethSponsoredCallback)
1812
1885
  return this.cachedWethSponsoredCallback;
1813
1886
  const provider = this.requireConnectedProvider();
1814
1887
  const owner = this.state.walletAddress;
1815
- this.cachedWethSponsoredCallback = makeSponsoredWethCallback({
1888
+ const callback = makeSponsoredWethCallback({
1816
1889
  apiKey: this.apiKey,
1817
1890
  baseUrl: this.routingApiBaseUrl,
1818
1891
  ownerAddress: owner,
1892
+ onApproved,
1819
1893
  tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
1820
1894
  // Casts work around viem's chain-narrowed Client vs the generic
1821
1895
  // PublicClient/WalletClient param types — structurally identical at
@@ -1830,7 +1904,8 @@ var OwneySDK = class {
1830
1904
  transport: (0, import_viem5.custom)(provider)
1831
1905
  })
1832
1906
  });
1833
- return this.cachedWethSponsoredCallback;
1907
+ if (!onApproved) this.cachedWethSponsoredCallback = callback;
1908
+ return callback;
1834
1909
  }
1835
1910
  getAgent(agentId) {
1836
1911
  const agent = this.agents.get(agentId);
@@ -1877,7 +1952,7 @@ var OwneySDK = class {
1877
1952
  }
1878
1953
  createAgent(agentId, key) {
1879
1954
  if (agentId === "zyfai") {
1880
- return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1955
+ return new ZyfaiAgent(key, this.zyfaiRpcUrls, this.referralSource);
1881
1956
  }
1882
1957
  return null;
1883
1958
  }
@@ -1976,13 +2051,13 @@ var OwneySDK = class {
1976
2051
  * @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
1977
2052
  */
1978
2053
  async deposit(options) {
1979
- const { amount, asset, depositCallback, agentId } = options;
2054
+ const { amount, asset, depositCallback, agentId, onApproved } = options;
1980
2055
  if (BigInt(amount) === 0n) {
1981
2056
  return { agentResults: {} };
1982
2057
  }
1983
2058
  const state = this.requireState();
1984
2059
  const chainId = this.requireChainId();
1985
- const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback() : this.getDefaultSponsoredCallback());
2060
+ const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
1986
2061
  if (agentId) {
1987
2062
  if (this.isAgentDisabled(agentId)) {
1988
2063
  throw new OwneyError(
@@ -2763,11 +2838,39 @@ var storage2 = () => {
2763
2838
  return null;
2764
2839
  }
2765
2840
  };
2766
- var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2841
+ var buildKey2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}`;
2842
+ var legacyKeyPrefix2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}:`;
2767
2843
  var memorySiwxSessions = /* @__PURE__ */ new Map();
2844
+ var readLegacySiwxSession = (store, address) => {
2845
+ if (!store) return null;
2846
+ const prefix = legacyKeyPrefix2(address);
2847
+ const legacyKeys = [];
2848
+ try {
2849
+ for (let i = 0; i < store.length; i++) {
2850
+ const key = store.key(i);
2851
+ if (key?.startsWith(prefix)) legacyKeys.push(key);
2852
+ }
2853
+ } catch {
2854
+ return null;
2855
+ }
2856
+ let adopted = null;
2857
+ for (const key of legacyKeys) {
2858
+ if (!adopted) {
2859
+ try {
2860
+ adopted = JSON.parse(store.getItem(key) ?? "");
2861
+ } catch {
2862
+ }
2863
+ }
2864
+ try {
2865
+ store.removeItem(key);
2866
+ } catch {
2867
+ }
2868
+ }
2869
+ return adopted;
2870
+ };
2768
2871
  var readSiwxSession = (address, chainId) => {
2769
2872
  if (typeof window === "undefined") return null;
2770
- const key = buildKey2(address, chainId);
2873
+ const key = buildKey2(address);
2771
2874
  const store = storage2();
2772
2875
  let raw = null;
2773
2876
  try {
@@ -2787,11 +2890,16 @@ var readSiwxSession = (address, chainId) => {
2787
2890
  return null;
2788
2891
  }
2789
2892
  }
2893
+ const legacy = readLegacySiwxSession(store, address);
2894
+ if (legacy) {
2895
+ writeSiwxSession(address, chainId, legacy);
2896
+ return legacy;
2897
+ }
2790
2898
  return memorySiwxSessions.get(key) ?? null;
2791
2899
  };
2792
- var writeSiwxSession = (address, chainId, session) => {
2900
+ var writeSiwxSession = (address, _chainId, session) => {
2793
2901
  if (typeof window === "undefined") return;
2794
- const key = buildKey2(address, chainId);
2902
+ const key = buildKey2(address);
2795
2903
  memorySiwxSessions.set(key, session);
2796
2904
  const store = storage2();
2797
2905
  try {
@@ -2799,14 +2907,15 @@ var writeSiwxSession = (address, chainId, session) => {
2799
2907
  } catch {
2800
2908
  }
2801
2909
  };
2802
- var clearSiwxSession = (address, chainId) => {
2803
- const key = buildKey2(address, chainId);
2910
+ var clearSiwxSession = (address, _chainId) => {
2911
+ const key = buildKey2(address);
2804
2912
  memorySiwxSessions.delete(key);
2805
2913
  const store = storage2();
2806
2914
  try {
2807
2915
  store?.removeItem(key);
2808
2916
  } catch {
2809
2917
  }
2918
+ readLegacySiwxSession(store, address);
2810
2919
  };
2811
2920
 
2812
2921
  // src/agents/zyfai/zyfai.siwx.ts
@@ -2870,9 +2979,12 @@ function buildSIWXConfig(deps) {
2870
2979
  }
2871
2980
  if (!stored) return [];
2872
2981
  const session = {
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,
2982
+ // `stored.data` is kept AppKit-free in the cache, so narrow at the
2983
+ // boundary. Echo the REQUESTED chain rather than the one originally
2984
+ // signed: the Zyfai JWT is account-scoped (no chain claim), so one
2985
+ // signature is valid for every chain, and AppKit would otherwise treat
2986
+ // the session as not covering the active network and re-prompt.
2987
+ data: { ...stored.data, chainId },
2876
2988
  message: stored.message,
2877
2989
  signature: stored.signature
2878
2990
  };
package/dist/index.d.cts CHANGED
@@ -15,6 +15,12 @@ interface OwneySDKConfig {
15
15
  * e.g. "http://localhost:3000", when testing sponsor changes.
16
16
  */
17
17
  routingApiBaseUrl?: string;
18
+ /**
19
+ * Optional attribution tag forwarded to Zyfai's /auth/login when the SDK
20
+ * authenticates (e.g. "delos"). Replaces the equivalent option on
21
+ * `createOwneySIWX` for apps that don't use the AppKit SIWX modal.
22
+ */
23
+ referralSource?: string;
18
24
  }
19
25
  interface ConnectionState {
20
26
  provider: any;
@@ -92,6 +98,7 @@ type DepositOptions = {
92
98
  asset: Asset;
93
99
  depositCallback?: DepositCallback;
94
100
  agentId?: AgentId;
101
+ onApproved?: () => void;
95
102
  };
96
103
 
97
104
  interface OwneyDepositResult {
@@ -313,6 +320,7 @@ declare class OwneySDK {
313
320
  private apiKey;
314
321
  private zyfaiRpcUrls?;
315
322
  private routingApiBaseUrl?;
323
+ private referralSource?;
316
324
  private cachedSponsoredCallback;
317
325
  private cachedWethSponsoredCallback;
318
326
  private initializingAgentsPromise;
package/dist/index.d.ts CHANGED
@@ -15,6 +15,12 @@ interface OwneySDKConfig {
15
15
  * e.g. "http://localhost:3000", when testing sponsor changes.
16
16
  */
17
17
  routingApiBaseUrl?: string;
18
+ /**
19
+ * Optional attribution tag forwarded to Zyfai's /auth/login when the SDK
20
+ * authenticates (e.g. "delos"). Replaces the equivalent option on
21
+ * `createOwneySIWX` for apps that don't use the AppKit SIWX modal.
22
+ */
23
+ referralSource?: string;
18
24
  }
19
25
  interface ConnectionState {
20
26
  provider: any;
@@ -92,6 +98,7 @@ type DepositOptions = {
92
98
  asset: Asset;
93
99
  depositCallback?: DepositCallback;
94
100
  agentId?: AgentId;
101
+ onApproved?: () => void;
95
102
  };
96
103
 
97
104
  interface OwneyDepositResult {
@@ -313,6 +320,7 @@ declare class OwneySDK {
313
320
  private apiKey;
314
321
  private zyfaiRpcUrls?;
315
322
  private routingApiBaseUrl?;
323
+ private referralSource?;
316
324
  private cachedSponsoredCallback;
317
325
  private cachedWethSponsoredCallback;
318
326
  private initializingAgentsPromise;
package/dist/index.js CHANGED
@@ -503,7 +503,8 @@ var storage = () => {
503
503
  return null;
504
504
  }
505
505
  };
506
- var buildKey = (address, chainId) => `${KEY_PREFIX}:${address.toLowerCase()}:${chainId}`;
506
+ var buildKey = (address) => `${KEY_PREFIX}:${address.toLowerCase()}`;
507
+ var legacyKeyPrefix = (address) => `${KEY_PREFIX}:${address.toLowerCase()}:`;
507
508
  var isJwtExpired = (token) => {
508
509
  const parts = token.split(".");
509
510
  if (parts.length !== 3) return false;
@@ -520,9 +521,37 @@ var isJwtExpired = (token) => {
520
521
  };
521
522
  var memorySessions = /* @__PURE__ */ new Map();
522
523
  var isFreshSession = (session) => !!session && !!session.token && !isJwtExpired(session.token);
523
- var readSession = (address, chainId) => {
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) => {
524
553
  if (typeof window === "undefined") return null;
525
- const key = buildKey(address, chainId);
554
+ const key = buildKey(address);
526
555
  const store = storage();
527
556
  let raw = null;
528
557
  try {
@@ -543,14 +572,19 @@ var readSession = (address, chainId) => {
543
572
  }
544
573
  return null;
545
574
  }
575
+ const legacy = readLegacySession(store, address);
576
+ if (legacy) {
577
+ writeSession(address, _chainId, legacy);
578
+ return legacy;
579
+ }
546
580
  const cached = memorySessions.get(key);
547
581
  if (isFreshSession(cached)) return cached;
548
582
  if (cached) memorySessions.delete(key);
549
583
  return null;
550
584
  };
551
- var writeSession = (address, chainId, session) => {
585
+ var writeSession = (address, _chainId, session) => {
552
586
  if (typeof window === "undefined") return;
553
- const key = buildKey(address, chainId);
587
+ const key = buildKey(address);
554
588
  memorySessions.set(key, session);
555
589
  const store = storage();
556
590
  try {
@@ -558,14 +592,15 @@ var writeSession = (address, chainId, session) => {
558
592
  } catch {
559
593
  }
560
594
  };
561
- var clearSession = (address, chainId) => {
562
- const key = buildKey(address, chainId);
595
+ var clearSession = (address, _chainId) => {
596
+ const key = buildKey(address);
563
597
  memorySessions.delete(key);
564
598
  const store = storage();
565
599
  try {
566
600
  store?.removeItem(key);
567
601
  } catch {
568
602
  }
603
+ readLegacySession(store, address);
569
604
  };
570
605
 
571
606
  // src/agents/zyfai/autoSelect.ts
@@ -654,11 +689,15 @@ var ZyfaiAgent = class {
654
689
  // successful decode is cached forever; failures are NOT cached so a transient
655
690
  // RPC error retries on the next fetch.
656
691
  withdrawAmountCache = /* @__PURE__ */ new Map();
657
- constructor(apiKey, rpcUrls) {
692
+ constructor(apiKey, rpcUrls, referralSource) {
658
693
  this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
659
694
  this.sdk = new ZyfaiSDK({
660
695
  apiKey,
661
- rpcUrls: this.rpcUrls
696
+ rpcUrls: this.rpcUrls,
697
+ // Forwarded to /auth/login by the SDK's own SIWE handshake, so
698
+ // attribution survives without the AppKit SIWX config (which carried it
699
+ // via `createOwneySIWX({ referralSource })` when apps used the modal).
700
+ referralSource
662
701
  });
663
702
  this.installAuthCache();
664
703
  }
@@ -980,7 +1019,14 @@ var ZyfaiAgent = class {
980
1019
  amount
981
1020
  );
982
1021
  const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
983
- await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1022
+ try {
1023
+ await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
1024
+ } catch (logError) {
1025
+ console.warn(
1026
+ "[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
1027
+ logError
1028
+ );
1029
+ }
984
1030
  return { txHash, smartWallet: wallet.address, amount };
985
1031
  }
986
1032
  const raw = await this.sdk.depositFunds(
@@ -1466,18 +1512,29 @@ function makeSponsoredDepositCallback(deps) {
1466
1512
  const wallet = deps.getWalletClient(cid);
1467
1513
  const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
1468
1514
  const validAfter = 0n;
1469
- const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
1515
+ const validBefore = BigInt(
1516
+ Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
1517
+ );
1470
1518
  const nonce = randomAuthNonce();
1471
1519
  const typedData = buildTransferWithAuthorizationTypedData({
1472
1520
  token,
1473
1521
  chainId: cid,
1474
1522
  tokenName,
1475
1523
  tokenVersion,
1476
- message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
1524
+ message: {
1525
+ from: deps.ownerAddress,
1526
+ to: smartWallet,
1527
+ value: BigInt(amount),
1528
+ validAfter,
1529
+ validBefore,
1530
+ nonce
1531
+ }
1477
1532
  });
1478
- const authSignature = await wallet.signTypedData(
1479
- { account: deps.ownerAddress, ...typedData }
1480
- );
1533
+ const authSignature = await wallet.signTypedData({
1534
+ account: deps.ownerAddress,
1535
+ ...typedData
1536
+ });
1537
+ deps.onApproved?.();
1481
1538
  const result = await post({
1482
1539
  baseUrl: deps.baseUrl,
1483
1540
  apiKey: deps.apiKey,
@@ -1561,7 +1618,10 @@ function makeSponsoredWethCallback(deps) {
1561
1618
  const cid = chainId;
1562
1619
  const token = deps.tokenAddressByChain[cid];
1563
1620
  if (!token) {
1564
- throw new OwneyError("CHAIN_UNSUPPORTED", `No sponsored WETH configured for chain ${chainId}`);
1621
+ throw new OwneyError(
1622
+ "CHAIN_UNSUPPORTED",
1623
+ `No sponsored WETH configured for chain ${chainId}`
1624
+ );
1565
1625
  }
1566
1626
  const amountWei = BigInt(amount);
1567
1627
  const pub = deps.getPublicClient(cid);
@@ -1573,9 +1633,15 @@ function makeSponsoredWethCallback(deps) {
1573
1633
  { token, chainId: cid, allowance: allowance.toString(), amount }
1574
1634
  );
1575
1635
  }
1576
- const relayer = await get({ baseUrl: deps.baseUrl, apiKey: deps.apiKey, chainId: cid });
1636
+ const relayer = await get({
1637
+ baseUrl: deps.baseUrl,
1638
+ apiKey: deps.apiKey,
1639
+ chainId: cid
1640
+ });
1577
1641
  const nonce = randomPermit2Nonce();
1578
- const deadline = BigInt(Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS);
1642
+ const deadline = BigInt(
1643
+ Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
1644
+ );
1579
1645
  const typedData = buildPermitTransferFromTypedData({
1580
1646
  chainId: cid,
1581
1647
  message: {
@@ -1586,9 +1652,11 @@ function makeSponsoredWethCallback(deps) {
1586
1652
  }
1587
1653
  });
1588
1654
  const wallet = deps.getWalletClient(cid);
1589
- const signature = await wallet.signTypedData(
1590
- { account: deps.ownerAddress, ...typedData }
1591
- );
1655
+ const signature = await wallet.signTypedData({
1656
+ account: deps.ownerAddress,
1657
+ ...typedData
1658
+ });
1659
+ deps.onApproved?.();
1592
1660
  const result = await post({
1593
1661
  baseUrl: deps.baseUrl,
1594
1662
  apiKey: deps.apiKey,
@@ -1659,6 +1727,7 @@ var OwneySDK = class {
1659
1727
  apiKey;
1660
1728
  zyfaiRpcUrls;
1661
1729
  routingApiBaseUrl;
1730
+ referralSource;
1662
1731
  cachedSponsoredCallback = null;
1663
1732
  cachedWethSponsoredCallback = null;
1664
1733
  initializingAgentsPromise = null;
@@ -1666,6 +1735,7 @@ var OwneySDK = class {
1666
1735
  this.apiKey = config.apiKey;
1667
1736
  this.zyfaiRpcUrls = config.zyfaiRpcUrls;
1668
1737
  this.routingApiBaseUrl = config.routingApiBaseUrl;
1738
+ this.referralSource = config.referralSource;
1669
1739
  }
1670
1740
  /**
1671
1741
  * Establish connection state for all subsequent SDK calls.
@@ -1749,14 +1819,16 @@ var OwneySDK = class {
1749
1819
  * provider with viem `custom(provider)` to read token meta and sign the
1750
1820
  * `TransferWithAuthorization`, then POSTs to the sponsor API.
1751
1821
  */
1752
- getDefaultSponsoredCallback() {
1753
- if (this.cachedSponsoredCallback) return this.cachedSponsoredCallback;
1822
+ getDefaultSponsoredCallback(onApproved) {
1823
+ if (!onApproved && this.cachedSponsoredCallback)
1824
+ return this.cachedSponsoredCallback;
1754
1825
  const provider = this.requireConnectedProvider();
1755
1826
  const owner = this.state.walletAddress;
1756
- this.cachedSponsoredCallback = makeSponsoredDepositCallback({
1827
+ const callback = makeSponsoredDepositCallback({
1757
1828
  apiKey: this.apiKey,
1758
1829
  baseUrl: this.routingApiBaseUrl,
1759
1830
  ownerAddress: owner,
1831
+ onApproved,
1760
1832
  tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
1761
1833
  // Casts work around viem's chain-narrowed Client vs the generic
1762
1834
  // PublicClient/WalletClient param types — structurally identical at
@@ -1771,7 +1843,8 @@ var OwneySDK = class {
1771
1843
  transport: custom(provider)
1772
1844
  })
1773
1845
  });
1774
- return this.cachedSponsoredCallback;
1846
+ if (!onApproved) this.cachedSponsoredCallback = callback;
1847
+ return callback;
1775
1848
  }
1776
1849
  /**
1777
1850
  * Lazily builds (and caches) the default Permit2 sponsored WETH deposit
@@ -1779,15 +1852,16 @@ var OwneySDK = class {
1779
1852
  * deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
1780
1853
  * `PermitTransferFrom` instead of an EIP-3009 authorization.
1781
1854
  */
1782
- getDefaultWethSponsoredCallback() {
1783
- if (this.cachedWethSponsoredCallback)
1855
+ getDefaultWethSponsoredCallback(onApproved) {
1856
+ if (!onApproved && this.cachedWethSponsoredCallback)
1784
1857
  return this.cachedWethSponsoredCallback;
1785
1858
  const provider = this.requireConnectedProvider();
1786
1859
  const owner = this.state.walletAddress;
1787
- this.cachedWethSponsoredCallback = makeSponsoredWethCallback({
1860
+ const callback = makeSponsoredWethCallback({
1788
1861
  apiKey: this.apiKey,
1789
1862
  baseUrl: this.routingApiBaseUrl,
1790
1863
  ownerAddress: owner,
1864
+ onApproved,
1791
1865
  tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
1792
1866
  // Casts work around viem's chain-narrowed Client vs the generic
1793
1867
  // PublicClient/WalletClient param types — structurally identical at
@@ -1802,7 +1876,8 @@ var OwneySDK = class {
1802
1876
  transport: custom(provider)
1803
1877
  })
1804
1878
  });
1805
- return this.cachedWethSponsoredCallback;
1879
+ if (!onApproved) this.cachedWethSponsoredCallback = callback;
1880
+ return callback;
1806
1881
  }
1807
1882
  getAgent(agentId) {
1808
1883
  const agent = this.agents.get(agentId);
@@ -1849,7 +1924,7 @@ var OwneySDK = class {
1849
1924
  }
1850
1925
  createAgent(agentId, key) {
1851
1926
  if (agentId === "zyfai") {
1852
- return new ZyfaiAgent(key, this.zyfaiRpcUrls);
1927
+ return new ZyfaiAgent(key, this.zyfaiRpcUrls, this.referralSource);
1853
1928
  }
1854
1929
  return null;
1855
1930
  }
@@ -1948,13 +2023,13 @@ var OwneySDK = class {
1948
2023
  * @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
1949
2024
  */
1950
2025
  async deposit(options) {
1951
- const { amount, asset, depositCallback, agentId } = options;
2026
+ const { amount, asset, depositCallback, agentId, onApproved } = options;
1952
2027
  if (BigInt(amount) === 0n) {
1953
2028
  return { agentResults: {} };
1954
2029
  }
1955
2030
  const state = this.requireState();
1956
2031
  const chainId = this.requireChainId();
1957
- const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback() : this.getDefaultSponsoredCallback());
2032
+ const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
1958
2033
  if (agentId) {
1959
2034
  if (this.isAgentDisabled(agentId)) {
1960
2035
  throw new OwneyError(
@@ -2735,11 +2810,39 @@ var storage2 = () => {
2735
2810
  return null;
2736
2811
  }
2737
2812
  };
2738
- var buildKey2 = (address, chainId) => `${KEY_PREFIX2}:${address.toLowerCase()}:${chainId}`;
2813
+ var buildKey2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}`;
2814
+ var legacyKeyPrefix2 = (address) => `${KEY_PREFIX2}:${address.toLowerCase()}:`;
2739
2815
  var memorySiwxSessions = /* @__PURE__ */ new Map();
2816
+ var readLegacySiwxSession = (store, address) => {
2817
+ if (!store) return null;
2818
+ const prefix = legacyKeyPrefix2(address);
2819
+ const legacyKeys = [];
2820
+ try {
2821
+ for (let i = 0; i < store.length; i++) {
2822
+ const key = store.key(i);
2823
+ if (key?.startsWith(prefix)) legacyKeys.push(key);
2824
+ }
2825
+ } catch {
2826
+ return null;
2827
+ }
2828
+ let adopted = null;
2829
+ for (const key of legacyKeys) {
2830
+ if (!adopted) {
2831
+ try {
2832
+ adopted = JSON.parse(store.getItem(key) ?? "");
2833
+ } catch {
2834
+ }
2835
+ }
2836
+ try {
2837
+ store.removeItem(key);
2838
+ } catch {
2839
+ }
2840
+ }
2841
+ return adopted;
2842
+ };
2740
2843
  var readSiwxSession = (address, chainId) => {
2741
2844
  if (typeof window === "undefined") return null;
2742
- const key = buildKey2(address, chainId);
2845
+ const key = buildKey2(address);
2743
2846
  const store = storage2();
2744
2847
  let raw = null;
2745
2848
  try {
@@ -2759,11 +2862,16 @@ var readSiwxSession = (address, chainId) => {
2759
2862
  return null;
2760
2863
  }
2761
2864
  }
2865
+ const legacy = readLegacySiwxSession(store, address);
2866
+ if (legacy) {
2867
+ writeSiwxSession(address, chainId, legacy);
2868
+ return legacy;
2869
+ }
2762
2870
  return memorySiwxSessions.get(key) ?? null;
2763
2871
  };
2764
- var writeSiwxSession = (address, chainId, session) => {
2872
+ var writeSiwxSession = (address, _chainId, session) => {
2765
2873
  if (typeof window === "undefined") return;
2766
- const key = buildKey2(address, chainId);
2874
+ const key = buildKey2(address);
2767
2875
  memorySiwxSessions.set(key, session);
2768
2876
  const store = storage2();
2769
2877
  try {
@@ -2771,14 +2879,15 @@ var writeSiwxSession = (address, chainId, session) => {
2771
2879
  } catch {
2772
2880
  }
2773
2881
  };
2774
- var clearSiwxSession = (address, chainId) => {
2775
- const key = buildKey2(address, chainId);
2882
+ var clearSiwxSession = (address, _chainId) => {
2883
+ const key = buildKey2(address);
2776
2884
  memorySiwxSessions.delete(key);
2777
2885
  const store = storage2();
2778
2886
  try {
2779
2887
  store?.removeItem(key);
2780
2888
  } catch {
2781
2889
  }
2890
+ readLegacySiwxSession(store, address);
2782
2891
  };
2783
2892
 
2784
2893
  // src/agents/zyfai/zyfai.siwx.ts
@@ -2842,9 +2951,12 @@ function buildSIWXConfig(deps) {
2842
2951
  }
2843
2952
  if (!stored) return [];
2844
2953
  const session = {
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,
2954
+ // `stored.data` is kept AppKit-free in the cache, so narrow at the
2955
+ // boundary. Echo the REQUESTED chain rather than the one originally
2956
+ // signed: the Zyfai JWT is account-scoped (no chain claim), so one
2957
+ // signature is valid for every chain, and AppKit would otherwise treat
2958
+ // the session as not covering the active network and re-prompt.
2959
+ data: { ...stored.data, chainId },
2848
2960
  message: stored.message,
2849
2961
  signature: stored.signature
2850
2962
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.6.7",
3
+ "version": "0.6.8-beta.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",