@kheopskit/core 5.3.0 → 6.0.0-rc.0

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +426 -0
  2. package/MIGRATING_TO_V6.md +837 -0
  3. package/README.md +628 -12
  4. package/dist/ethereum.d.mts +12 -6
  5. package/dist/ethereum.d.ts +12 -6
  6. package/dist/ethereum.js +13 -10
  7. package/dist/ethereum.js.map +1 -1
  8. package/dist/ethereum.mjs +7 -4
  9. package/dist/ethereum.mjs.map +1 -1
  10. package/dist/{iconCache-pP2ES4pJ.mjs → iconCache-C-U3IEbP.mjs} +21 -40
  11. package/dist/iconCache-C-U3IEbP.mjs.map +1 -0
  12. package/dist/{iconCache-DUtkJlaX.js → iconCache-FR4iy6go.js} +21 -40
  13. package/dist/iconCache-FR4iy6go.js.map +1 -0
  14. package/dist/index.d.mts +17 -63
  15. package/dist/index.d.ts +17 -63
  16. package/dist/index.js +387 -373
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +384 -369
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/injectedWallets-48L-AL1I.mjs +173 -0
  21. package/dist/injectedWallets-48L-AL1I.mjs.map +1 -0
  22. package/dist/injectedWallets-Dy8YGKL-.js +178 -0
  23. package/dist/injectedWallets-Dy8YGKL-.js.map +1 -0
  24. package/dist/internal.d.mts +3 -27
  25. package/dist/internal.d.ts +3 -27
  26. package/dist/internal.js +2 -2
  27. package/dist/internal.mjs +2 -2
  28. package/dist/pageLoad-BZ7o8p5R.mjs +24 -0
  29. package/dist/pageLoad-BZ7o8p5R.mjs.map +1 -0
  30. package/dist/pageLoad-D1wLeuFG.js +28 -0
  31. package/dist/pageLoad-D1wLeuFG.js.map +1 -0
  32. package/dist/platformAccounts-BjIeRcFN.js +321 -0
  33. package/dist/platformAccounts-BjIeRcFN.js.map +1 -0
  34. package/dist/platformAccounts-yyRUrnel.mjs +256 -0
  35. package/dist/platformAccounts-yyRUrnel.mjs.map +1 -0
  36. package/dist/polkadot.d.mts +127 -11
  37. package/dist/polkadot.d.ts +127 -11
  38. package/dist/polkadot.js +170 -106
  39. package/dist/polkadot.js.map +1 -1
  40. package/dist/polkadot.mjs +163 -99
  41. package/dist/polkadot.mjs.map +1 -1
  42. package/dist/solana.d.mts +11 -5
  43. package/dist/solana.d.ts +11 -5
  44. package/dist/solana.js +18 -15
  45. package/dist/solana.js.map +1 -1
  46. package/dist/solana.mjs +7 -4
  47. package/dist/solana.mjs.map +1 -1
  48. package/dist/storage-D3AwNgqc.d.mts +27 -0
  49. package/dist/storage-D3AwNgqc.d.ts +27 -0
  50. package/dist/testing.d.mts +71 -0
  51. package/dist/testing.d.ts +71 -0
  52. package/dist/testing.js +136 -0
  53. package/dist/testing.js.map +1 -0
  54. package/dist/testing.mjs +131 -0
  55. package/dist/testing.mjs.map +1 -0
  56. package/dist/{types-DKU-SNio.js → types-BWHvNFlN.js} +149 -2
  57. package/dist/types-BWHvNFlN.js.map +1 -0
  58. package/dist/types-Dkyt9bf4.d.mts +683 -0
  59. package/dist/types-Dkyt9bf4.d.ts +683 -0
  60. package/dist/types-Yor672md.mjs +215 -0
  61. package/dist/types-Yor672md.mjs.map +1 -0
  62. package/dist/walletconnect.d.mts +41 -0
  63. package/dist/walletconnect.d.ts +41 -0
  64. package/dist/walletconnect.js +219 -0
  65. package/dist/walletconnect.js.map +1 -0
  66. package/dist/walletconnect.mjs +216 -0
  67. package/dist/walletconnect.mjs.map +1 -0
  68. package/package.json +30 -6
  69. package/dist/errors-BLFP1dQI.mjs +0 -181
  70. package/dist/errors-BLFP1dQI.mjs.map +0 -1
  71. package/dist/errors-DYWVPHrR.js +0 -222
  72. package/dist/errors-DYWVPHrR.js.map +0 -1
  73. package/dist/iconCache-DUtkJlaX.js.map +0 -1
  74. package/dist/iconCache-pP2ES4pJ.mjs.map +0 -1
  75. package/dist/injectedWallets-BqR-_aAy.js +0 -148
  76. package/dist/injectedWallets-BqR-_aAy.js.map +0 -1
  77. package/dist/injectedWallets-Uz4hPuoW.mjs +0 -119
  78. package/dist/injectedWallets-Uz4hPuoW.mjs.map +0 -1
  79. package/dist/types-AxUDtkR-.d.mts +0 -338
  80. package/dist/types-AxUDtkR-.d.ts +0 -338
  81. package/dist/types-DKU-SNio.js.map +0 -1
  82. package/dist/types-jnifAAA0.mjs +0 -104
  83. package/dist/types-jnifAAA0.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { C as WalletId, D as WalletAccountId, S as isWalletConnectWallet, _ as WalletConnectWallet, c as KheopskitPlatform, x as isInjectedWallet } from "./types-AxUDtkR-.mjs";
1
+ import { E as isWalletConnectWallet, N as WalletAccountId, T as isInjectedWallet, b as WalletConnectWallet, k as WalletId, l as KheopskitPlatform, m as PlaceholderWallet, p as Placeholder, r as BaseWallet } from "./types-Dkyt9bf4.mjs";
2
2
  import { Account, CustomTransport, EIP1193Provider, WalletClient } from "viem";
3
3
  //#region src/utils/isEthereumAddress.d.ts
4
4
  /**
@@ -11,7 +11,8 @@ import { Account, CustomTransport, EIP1193Provider, WalletClient } from "viem";
11
11
  export declare const isEthereumAddress: (address: string) => boolean;
12
12
  //#endregion
13
13
  //#region src/api/ethereum/types.d.ts
14
- type EthereumInjectedWallet = {
14
+ type LiveEthereumInjectedWallet = {
15
+ isPlaceholder?: false;
15
16
  platform: "ethereum";
16
17
  type: "injected";
17
18
  id: WalletId;
@@ -24,19 +25,23 @@ type EthereumInjectedWallet = {
24
25
  provider: EIP1193Provider;
25
26
  name: string;
26
27
  icon: string;
28
+ status: BaseWallet["status"];
29
+ error?: BaseWallet["error"];
27
30
  isConnected: boolean;
28
- connect: () => Promise<void>;
29
- disconnect: () => Promise<void>;
31
+ connect: BaseWallet["connect"];
32
+ disconnect: BaseWallet["disconnect"];
30
33
  };
34
+ type EthereumInjectedWallet = LiveEthereumInjectedWallet | PlaceholderWallet<LiveEthereumInjectedWallet, "sourceId" | "provider">;
31
35
  type EthereumWallet = EthereumInjectedWallet;
32
- type EthereumAccount = {
36
+ type LiveEthereumAccount = {
37
+ isPlaceholder?: false;
33
38
  id: WalletAccountId;
34
39
  platform: "ethereum";
35
40
  /**
36
41
  * Signing surface for this account: a viem {@link WalletClient} bound to the
37
42
  * wallet's provider (sign/send via viem actions). Per-platform signing
38
43
  * surfaces differ — Solana exposes `signer`/`getSigner(chain)`, Polkadot
39
- * exposes `polkadotSigner`. Absent while `state.isHydrating` is `true`.
44
+ * exposes `polkadotSigner`. Absent on a placeholder.
40
45
  */
41
46
  client: WalletClient<CustomTransport, undefined, Account, undefined>;
42
47
  address: `0x${string}`;
@@ -45,6 +50,7 @@ type EthereumAccount = {
45
50
  walletName: string;
46
51
  walletId: WalletId;
47
52
  };
53
+ type EthereumAccount = LiveEthereumAccount | Placeholder<LiveEthereumAccount, "client">;
48
54
  //#endregion
49
55
  //#region src/api/ethereum/plugin.d.ts
50
56
  /**
@@ -1,4 +1,4 @@
1
- import { C as WalletId, D as WalletAccountId, S as isWalletConnectWallet, _ as WalletConnectWallet, c as KheopskitPlatform, x as isInjectedWallet } from "./types-AxUDtkR-.js";
1
+ import { E as isWalletConnectWallet, N as WalletAccountId, T as isInjectedWallet, b as WalletConnectWallet, k as WalletId, l as KheopskitPlatform, m as PlaceholderWallet, p as Placeholder, r as BaseWallet } from "./types-Dkyt9bf4.js";
2
2
  import { Account, CustomTransport, EIP1193Provider, WalletClient } from "viem";
3
3
  //#region src/utils/isEthereumAddress.d.ts
4
4
  /**
@@ -11,7 +11,8 @@ import { Account, CustomTransport, EIP1193Provider, WalletClient } from "viem";
11
11
  export declare const isEthereumAddress: (address: string) => boolean;
12
12
  //#endregion
13
13
  //#region src/api/ethereum/types.d.ts
14
- type EthereumInjectedWallet = {
14
+ type LiveEthereumInjectedWallet = {
15
+ isPlaceholder?: false;
15
16
  platform: "ethereum";
16
17
  type: "injected";
17
18
  id: WalletId;
@@ -24,19 +25,23 @@ type EthereumInjectedWallet = {
24
25
  provider: EIP1193Provider;
25
26
  name: string;
26
27
  icon: string;
28
+ status: BaseWallet["status"];
29
+ error?: BaseWallet["error"];
27
30
  isConnected: boolean;
28
- connect: () => Promise<void>;
29
- disconnect: () => Promise<void>;
31
+ connect: BaseWallet["connect"];
32
+ disconnect: BaseWallet["disconnect"];
30
33
  };
34
+ type EthereumInjectedWallet = LiveEthereumInjectedWallet | PlaceholderWallet<LiveEthereumInjectedWallet, "sourceId" | "provider">;
31
35
  type EthereumWallet = EthereumInjectedWallet;
32
- type EthereumAccount = {
36
+ type LiveEthereumAccount = {
37
+ isPlaceholder?: false;
33
38
  id: WalletAccountId;
34
39
  platform: "ethereum";
35
40
  /**
36
41
  * Signing surface for this account: a viem {@link WalletClient} bound to the
37
42
  * wallet's provider (sign/send via viem actions). Per-platform signing
38
43
  * surfaces differ — Solana exposes `signer`/`getSigner(chain)`, Polkadot
39
- * exposes `polkadotSigner`. Absent while `state.isHydrating` is `true`.
44
+ * exposes `polkadotSigner`. Absent on a placeholder.
40
45
  */
41
46
  client: WalletClient<CustomTransport, undefined, Account, undefined>;
42
47
  address: `0x${string}`;
@@ -45,6 +50,7 @@ type EthereumAccount = {
45
50
  walletName: string;
46
51
  walletId: WalletId;
47
52
  };
53
+ type EthereumAccount = LiveEthereumAccount | Placeholder<LiveEthereumAccount, "client">;
48
54
  //#endregion
49
55
  //#region src/api/ethereum/plugin.d.ts
50
56
  /**
package/dist/ethereum.js CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_types = require("./types-DKU-SNio.js");
3
- const require_errors = require("./errors-DYWVPHrR.js");
4
- const require_injectedWallets = require("./injectedWallets-BqR-_aAy.js");
2
+ const require_types = require("./types-BWHvNFlN.js");
3
+ const require_platformAccounts = require("./platformAccounts-BjIeRcFN.js");
4
+ const require_injectedWallets = require("./injectedWallets-Dy8YGKL-.js");
5
5
  let rxjs = require("rxjs");
6
6
  let viem = require("viem");
7
7
  let mipd = require("mipd");
@@ -33,7 +33,7 @@ const getInjectedWalletAccounts$ = (wallet) => {
33
33
  transport: (0, viem.custom)(wallet.provider)
34
34
  });
35
35
  return {
36
- id: require_errors.getWalletAccountId(wallet.id, address),
36
+ id: require_platformAccounts.getWalletAccountId(wallet.id, address),
37
37
  platform: "ethereum",
38
38
  client,
39
39
  address: (0, viem.getAddress)(address),
@@ -94,7 +94,7 @@ const getWalletConnectAccounts$ = (wallet) => {
94
94
  const session = provider.session;
95
95
  if (!session) return [];
96
96
  const addresses = /* @__PURE__ */ new Set();
97
- for (const raw of require_injectedWallets.getCaip10Addresses(require_injectedWallets.getSessionCaip10s(session, "eip155"))) try {
97
+ for (const raw of require_platformAccounts.getCaip10Addresses(require_platformAccounts.getSessionCaip10s(session, "eip155"))) try {
98
98
  addresses.add((0, viem.getAddress)(raw));
99
99
  } catch {}
100
100
  return [...addresses];
@@ -102,7 +102,7 @@ const getWalletConnectAccounts$ = (wallet) => {
102
102
  const readCaipNetworkId = () => {
103
103
  const session = provider.session;
104
104
  if (!session) return void 0;
105
- for (const account of require_injectedWallets.getSessionCaip10s(session, "eip155")) {
105
+ for (const account of require_platformAccounts.getSessionCaip10s(session, "eip155")) {
106
106
  const ref = account.split(":")[1];
107
107
  if (ref) return `eip155:${ref}`;
108
108
  }
@@ -127,7 +127,7 @@ const getWalletConnectAccounts$ = (wallet) => {
127
127
  transport
128
128
  });
129
129
  return {
130
- id: require_errors.getWalletAccountId(wallet.id, addr),
130
+ id: require_platformAccounts.getWalletAccountId(wallet.id, addr),
131
131
  platform: "ethereum",
132
132
  walletName: wallet.name,
133
133
  walletId: wallet.id,
@@ -148,7 +148,7 @@ const getWalletConnectAccounts$ = (wallet) => {
148
148
  bufferSize: 1
149
149
  })));
150
150
  };
151
- const getEthereumAccounts$ = (ethereumWallets) => require_injectedWallets.createPlatformAccounts$({
151
+ const getEthereumAccounts$ = (ethereumWallets) => require_platformAccounts.createPlatformAccounts$({
152
152
  wallets$: ethereumWallets,
153
153
  getInjectedAccounts$: getInjectedWalletAccounts$,
154
154
  getWalletConnectAccounts$,
@@ -185,14 +185,17 @@ const getEthereumWallets$ = (store) => require_injectedWallets.createInjectedWal
185
185
  connect: async (pd) => {
186
186
  await pd.provider.request({ method: "eth_requestAccounts" });
187
187
  },
188
+ isUserRejection: require_types.isEip1193UserRejection,
188
189
  onDisconnected: (walletId) => require_types.clearCachedObservable(`accounts:${walletId}`),
189
- buildWallet: ({ source: pd, walletId, isConnected, connect, disconnect }) => ({
190
+ buildWallet: ({ source: pd, walletId, status, error, isConnected, connect, disconnect }) => ({
190
191
  platform: "ethereum",
191
192
  type: "injected",
192
193
  id: walletId,
193
194
  name: pd.info.name,
194
195
  icon: pd.info.icon,
195
196
  provider: pd.provider,
197
+ status,
198
+ error,
196
199
  isConnected,
197
200
  sourceId: pd.info.rdns,
198
201
  connect,
@@ -217,7 +220,7 @@ const ethereum = () => ({
217
220
  });
218
221
  //#endregion
219
222
  exports.ethereum = ethereum;
220
- exports.isEthereumAddress = require_errors.isEthereumAddress;
223
+ exports.isEthereumAddress = require_platformAccounts.isEthereumAddress;
221
224
  exports.isInjectedWallet = require_types.isInjectedWallet;
222
225
  exports.isWalletConnectWallet = require_types.isWalletConnectWallet;
223
226
 
@@ -1 +1 @@
1
- {"version":3,"file":"ethereum.js","names":["of","getCachedObservable$","Observable","ReplaySubject","createWalletClient","custom","getWalletAccountId","getAddress","combineLatest","map","shareReplay","getCaip10Addresses","getSessionCaip10s","distinctUntilChanged","createPlatformAccounts$","Observable","createMipdStore","shareReplay","createInjectedWallets$","getWalletId","clearCachedObservable"],"sources":["../src/api/ethereum/accounts.ts","../src/api/ethereum/wallets.ts","../src/api/ethereum/plugin.ts"],"sourcesContent":["import {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tReplaySubject,\n\tshareReplay,\n} from \"rxjs\";\nimport {\n\tcreateWalletClient,\n\tcustom,\n\ttype EIP1193Provider,\n\tgetAddress,\n} from \"viem\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport {\n\tcreatePlatformAccounts$,\n\tgetCaip10Addresses,\n\tgetSessionCaip10s,\n} from \"../platformAccounts\";\nimport type { WalletConnectWallet } from \"../types\";\nimport type {\n\tEthereumAccount,\n\tEthereumInjectedWallet,\n\tEthereumWallet,\n} from \"./types\";\n\nconst normalizeEvmChainId = (value: unknown): number | undefined => {\n\tlet raw = value;\n\n\tif (typeof raw === \"string\" && raw.startsWith(\"eip155:\")) {\n\t\traw = raw.slice(\"eip155:\".length);\n\t}\n\n\tif (typeof raw === \"bigint\") {\n\t\treturn raw >= 0n ? Number(raw) : undefined;\n\t}\n\n\tif (typeof raw === \"number\") {\n\t\treturn Number.isInteger(raw) && raw >= 0 ? raw : undefined;\n\t}\n\n\tif (typeof raw === \"string\") {\n\t\tconst normalized = raw.trim().toLowerCase();\n\t\tif (!normalized) return undefined;\n\t\tconst parsed = normalized.startsWith(\"0x\")\n\t\t\t? Number.parseInt(normalized, 16)\n\t\t\t: Number.parseInt(normalized, 10);\n\t\treturn Number.isNaN(parsed) ? undefined : parsed;\n\t}\n\n\treturn undefined;\n};\n\nconst toCaipNetworkId = (value: unknown): string | undefined => {\n\tconst chainId = normalizeEvmChainId(value);\n\treturn chainId === undefined ? undefined : `eip155:${chainId}`;\n};\n\nconst getInjectedWalletAccounts$ = (\n\twallet: EthereumInjectedWallet,\n): Observable<EthereumAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\t\t\tconst chainId$ = new ReplaySubject<number | undefined>(1);\n\n\t\t\tconst getAccount = (\n\t\t\t\taddress: string,\n\t\t\t\tchainId: number | undefined,\n\t\t\t): EthereumAccount => {\n\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\taccount: address as `0x${string}`,\n\t\t\t\t\ttransport: custom(wallet.provider as EIP1193Provider),\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tid: getWalletAccountId(wallet.id, address),\n\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\tclient,\n\t\t\t\t\taddress: getAddress(address),\n\t\t\t\t\tchainId,\n\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = (addrs: string[]) => {\n\t\t\t\taddresses$.next(addrs);\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainIdHex: unknown) => {\n\t\t\t\tchainId$.next(normalizeEvmChainId(chainIdHex));\n\t\t\t};\n\n\t\t\tconst handleDisconnect = () => {\n\t\t\t\tchainId$.next(undefined);\n\t\t\t};\n\n\t\t\t// Subscribe to provider events\n\t\t\twallet.provider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\twallet.provider.on(\"chainChanged\", handleChainChanged);\n\t\t\twallet.provider.on(\"disconnect\", handleDisconnect);\n\n\t\t\t// Fetch initial values\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_accounts\" })\n\t\t\t\t.then((addrs: string[]) => addresses$.next(addrs))\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconsole.error(\"Failed to get accounts\", err);\n\t\t\t\t\taddresses$.next([]);\n\t\t\t\t});\n\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => chainId$.next(undefined));\n\n\t\t\t// Combine addresses + chainId into account list\n\t\t\tconst sub = combineLatest([addresses$, chainId$])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([addresses, chainId]) =>\n\t\t\t\t\t\taddresses.map((addr) => getAccount(addr, chainId)),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\twallet.provider.removeListener(\n\t\t\t\t\t\"accountsChanged\",\n\t\t\t\t\thandleAccountsChanged,\n\t\t\t\t);\n\t\t\t\twallet.provider.removeListener(\"chainChanged\", handleChainChanged);\n\t\t\t\twallet.provider.removeListener(\"disconnect\", handleDisconnect);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst wrapWalletConnectProvider = (\n\tprovider: EIP1193Provider,\n\tsessionTopic: string,\n\tcaipNetworkId: string | undefined,\n): EIP1193Provider => {\n\treturn new Proxy(provider, {\n\t\tget(target, prop, receiver) {\n\t\t\tif (prop !== \"request\") return Reflect.get(target, prop, receiver);\n\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: EIP-1193 request args\n\t\t\treturn (args: any) => {\n\t\t\t\tif (!args || typeof args !== \"object\" || !args.method)\n\t\t\t\t\treturn target.request(args);\n\t\t\t\t// Build a new object rather than mutating the caller's args: the\n\t\t\t\t// EIP-1193 request object is owned by viem and may be frozen or reused.\n\t\t\t\tconst next = { ...args };\n\t\t\t\tif (next.topic === undefined) next.topic = sessionTopic;\n\t\t\t\tif (next.chainId === undefined && caipNetworkId !== undefined)\n\t\t\t\t\tnext.chainId = caipNetworkId;\n\t\t\t\t// WalletConnect's UniversalProvider reads the target CAIP chain id from\n\t\t\t\t// the SECOND positional argument of `request(args, chainId)`, not from a\n\t\t\t\t// field on the args object. This AppKit instance has no native eip155\n\t\t\t\t// adapter, so the provider has no default chain — without the positional\n\t\t\t\t// chain id every call is rejected (\"Unsupported chains\" / \"Method not\n\t\t\t\t// found\"). Pass it positionally so the request routes to the session's\n\t\t\t\t// chain.\n\t\t\t\treturn (\n\t\t\t\t\ttarget.request as (a: unknown, chainId?: string) => Promise<unknown>\n\t\t\t\t)(next, caipNetworkId);\n\t\t\t};\n\t\t},\n\t});\n};\n\nconst sameAddresses = (a: string[], b: string[]) =>\n\ta.length === b.length && a.every((addr, i) => addr === b[i]);\n\nconst getWalletConnectAccounts$ = (\n\twallet: WalletConnectWallet,\n): Observable<EthereumAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"eip155\");\n\n\tif (!wallet.platforms.includes(\"ethereum\") || !provider?.session)\n\t\treturn of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:ethereum:`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst caipNetworkId$ = new ReplaySubject<string | undefined>(1);\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\n\t\t\t// AppKit's getAccount(\"eip155\").allAccounts is empty because this AppKit\n\t\t\t// instance has no native eip155 adapter — eip155 runs through the\n\t\t\t// WalletConnect UniversalProvider, so the session is the source of truth\n\t\t\t// (mirrors the polkadot/solana AppKit paths). Accounts are CAIP-10 strings\n\t\t\t// (\"eip155:<chainRef>:<address>\"), one entry per chain, so dedupe to unique\n\t\t\t// addresses. Read live on each change so switching/adding accounts is\n\t\t\t// reflected.\n\t\t\tconst readAddresses = (): string[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\t\t\t\tconst addresses = new Set<string>();\n\t\t\t\tfor (const raw of getCaip10Addresses(\n\t\t\t\t\tgetSessionCaip10s(session, \"eip155\"),\n\t\t\t\t)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\taddresses.add(getAddress(raw));\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// skip malformed CAIP-10 address\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn [...addresses];\n\t\t\t};\n\n\t\t\t// Derive the CAIP network id from the session's eip155 CAIP-10 accounts\n\t\t\t// (\"eip155:<ref>:<addr>\") as a synchronous fallback for eth_chainId.\n\t\t\tconst readCaipNetworkId = (): string | undefined => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return undefined;\n\t\t\t\tfor (const account of getSessionCaip10s(session, \"eip155\")) {\n\t\t\t\t\tconst ref = account.split(\":\")[1];\n\t\t\t\t\tif (ref) return `eip155:${ref}`;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainId: unknown) => {\n\t\t\t\tconst caipNetworkId = toCaipNetworkId(chainId);\n\t\t\t\tif (caipNetworkId) {\n\t\t\t\t\tcaipNetworkId$.next(caipNetworkId);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = () => addresses$.next(readAddresses());\n\n\t\t\tprovider.on(\"chainChanged\", handleChainChanged);\n\t\t\tprovider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\tprovider.on(\"session_update\", handleAccountsChanged);\n\t\t\t// Seed the chain id from the session synchronously so the account list can\n\t\t\t// surface even if eth_chainId never resolves; eth_chainId then refines it.\n\t\t\t// Without this seed, combineLatest below never fires when eth_chainId\n\t\t\t// rejects or returns an unparseable value, and the accounts silently never\n\t\t\t// appear (the injected path seeds undefined on failure for the same reason).\n\t\t\tcaipNetworkId$.next(readCaipNetworkId());\n\t\t\tprovider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => {});\n\t\t\taddresses$.next(readAddresses());\n\n\t\t\tconst sub = combineLatest([\n\t\t\t\tcaipNetworkId$.pipe(distinctUntilChanged()),\n\t\t\t\taddresses$.pipe(distinctUntilChanged(sameAddresses)),\n\t\t\t])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([caipNetworkId, addresses]) => {\n\t\t\t\t\t\tconst chainId = normalizeEvmChainId(caipNetworkId);\n\t\t\t\t\t\tconst transport = custom(\n\t\t\t\t\t\t\twrapWalletConnectProvider(\n\t\t\t\t\t\t\t\tprovider as unknown as EIP1193Provider,\n\t\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: legacy\n\t\t\t\t\t\t\t\tprovider.session!.topic,\n\t\t\t\t\t\t\t\tcaipNetworkId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn addresses.map((addr): EthereumAccount => {\n\t\t\t\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\t\t\t\taccount: addr as `0x${string}`,\n\t\t\t\t\t\t\t\ttransport,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tid: getWalletAccountId(wallet.id, addr),\n\t\t\t\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t\t\t\taddress: addr as `0x${string}`,\n\t\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\t\tchainId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"chainChanged\", handleChainChanged);\n\t\t\t\tprovider.off(\"accountsChanged\", handleAccountsChanged);\n\t\t\t\tprovider.off(\"session_update\", handleAccountsChanged);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getEthereumAccounts$ = (\n\tethereumWallets: Observable<(EthereumWallet | WalletConnectWallet)[]>,\n) =>\n\tcreatePlatformAccounts$({\n\t\twallets$: ethereumWallets,\n\t\tgetInjectedAccounts$: getInjectedWalletAccounts$,\n\t\tgetWalletConnectAccounts$,\n\t\t// Re-emit on chain switches, not just account id changes.\n\t\taccountChangeKey: (account) => `${account.id}|${account.chainId ?? \"\"}`,\n\t});\n","import {\n\tcreateStore as createMipdStore,\n\ttype EIP6963ProviderDetail,\n} from \"mipd\";\nimport { Observable, shareReplay } from \"rxjs\";\nimport type { EIP1193Provider } from \"viem\";\nimport { clearCachedObservable } from \"../../utils/getCachedObservable\";\nimport { getWalletId } from \"../../utils/WalletId\";\nimport { createInjectedWallets$ } from \"../injectedWallets\";\nimport type { KheopskitStore } from \"../store\";\nimport type { EthereumInjectedWallet } from \"./types\";\n\n/**\n * Observable that emits EIP-6963 provider details from injected wallets.\n * Returns empty array during SSR since browser wallet APIs are not available.\n */\nconst providersDetails$ = new Observable<EIP6963ProviderDetail[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - mipd requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst mipdStore = createMipdStore();\n\n\t\tconst unsubscribe = mipdStore.subscribe((providerDetails) => {\n\t\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\t\t});\n\n\t\tconst providerDetails = mipdStore.getProviders();\n\n\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tmipdStore.destroy();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\n// The shared WalletConnect connector is emitted once by core (see\n// `getWallets$`), not per platform — so this returns only injected wallets.\nexport const getEthereumWallets$ = (store: KheopskitStore) =>\n\tcreateInjectedWallets$<EIP6963ProviderDetail, EthereumInjectedWallet>(store, {\n\t\tsources$: providersDetails$,\n\t\tgetWalletId: (pd) => getWalletId(\"ethereum\", pd.info.rdns),\n\t\tconnect: async (pd) => {\n\t\t\tawait (pd.provider as EIP1193Provider).request({\n\t\t\t\tmethod: \"eth_requestAccounts\",\n\t\t\t});\n\t\t},\n\t\t// Drop the cached account observable so a later reconnect rebuilds it\n\t\t// against the current provider, not a stale closure.\n\t\tonDisconnected: (walletId) => clearCachedObservable(`accounts:${walletId}`),\n\t\tbuildWallet: ({\n\t\t\tsource: pd,\n\t\t\twalletId,\n\t\t\tisConnected,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}) => ({\n\t\t\tplatform: \"ethereum\",\n\t\t\ttype: \"injected\",\n\t\t\tid: walletId,\n\t\t\tname: pd.info.name,\n\t\t\ticon: pd.info.icon,\n\t\t\tprovider: pd.provider as EIP1193Provider,\n\t\t\tisConnected,\n\t\t\tsourceId: pd.info.rdns,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}),\n\t});\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getEthereumAccounts$ } from \"./accounts\";\nimport type { EthereumAccount, EthereumWallet } from \"./types\";\nimport { getEthereumWallets$ } from \"./wallets\";\n\n/**\n * Ethereum platform plugin. Pass to `getKheopskit$({ platforms: [ethereum()] })`.\n *\n * @example\n * ```ts\n * import { ethereum } from \"@kheopskit/core/ethereum\";\n * ethereum();\n * ```\n */\nexport const ethereum = (): KheopskitPlatform<\n\t\"ethereum\",\n\tEthereumWallet,\n\tEthereumAccount\n> => ({\n\tplatform: \"ethereum\",\n\tgetWallets$: (ctx: PlatformContext) => getEthereumWallets$(ctx.store),\n\tgetAccounts$: (wallets$) => getEthereumAccounts$(wallets$),\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"ethereum.js","names":["of","getCachedObservable$","Observable","ReplaySubject","createWalletClient","custom","getWalletAccountId","getAddress","combineLatest","map","shareReplay","getCaip10Addresses","getSessionCaip10s","distinctUntilChanged","createPlatformAccounts$","Observable","createMipdStore","shareReplay","createInjectedWallets$","getWalletId","isEip1193UserRejection","clearCachedObservable"],"sources":["../src/api/ethereum/accounts.ts","../src/api/ethereum/wallets.ts","../src/api/ethereum/plugin.ts"],"sourcesContent":["import {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tReplaySubject,\n\tshareReplay,\n} from \"rxjs\";\nimport {\n\tcreateWalletClient,\n\tcustom,\n\ttype EIP1193Provider,\n\tgetAddress,\n} from \"viem\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport {\n\tcreatePlatformAccounts$,\n\tgetCaip10Addresses,\n\tgetSessionCaip10s,\n\ttype LiveWalletConnectWallet,\n} from \"../platformAccounts\";\nimport type { WalletConnectWallet } from \"../types\";\nimport type {\n\tEthereumAccount,\n\tEthereumInjectedWallet,\n\tEthereumWallet,\n} from \"./types\";\n\nconst normalizeEvmChainId = (value: unknown): number | undefined => {\n\tlet raw = value;\n\n\tif (typeof raw === \"string\" && raw.startsWith(\"eip155:\")) {\n\t\traw = raw.slice(\"eip155:\".length);\n\t}\n\n\tif (typeof raw === \"bigint\") {\n\t\treturn raw >= 0n ? Number(raw) : undefined;\n\t}\n\n\tif (typeof raw === \"number\") {\n\t\treturn Number.isInteger(raw) && raw >= 0 ? raw : undefined;\n\t}\n\n\tif (typeof raw === \"string\") {\n\t\tconst normalized = raw.trim().toLowerCase();\n\t\tif (!normalized) return undefined;\n\t\tconst parsed = normalized.startsWith(\"0x\")\n\t\t\t? Number.parseInt(normalized, 16)\n\t\t\t: Number.parseInt(normalized, 10);\n\t\treturn Number.isNaN(parsed) ? undefined : parsed;\n\t}\n\n\treturn undefined;\n};\n\nconst toCaipNetworkId = (value: unknown): string | undefined => {\n\tconst chainId = normalizeEvmChainId(value);\n\treturn chainId === undefined ? undefined : `eip155:${chainId}`;\n};\n\nconst getInjectedWalletAccounts$ = (\n\twallet: EthereumInjectedWallet,\n): Observable<EthereumAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\t\t\tconst chainId$ = new ReplaySubject<number | undefined>(1);\n\n\t\t\tconst getAccount = (\n\t\t\t\taddress: string,\n\t\t\t\tchainId: number | undefined,\n\t\t\t): EthereumAccount => {\n\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\taccount: address as `0x${string}`,\n\t\t\t\t\ttransport: custom(wallet.provider as EIP1193Provider),\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tid: getWalletAccountId(wallet.id, address),\n\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\tclient,\n\t\t\t\t\taddress: getAddress(address),\n\t\t\t\t\tchainId,\n\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = (addrs: string[]) => {\n\t\t\t\taddresses$.next(addrs);\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainIdHex: unknown) => {\n\t\t\t\tchainId$.next(normalizeEvmChainId(chainIdHex));\n\t\t\t};\n\n\t\t\tconst handleDisconnect = () => {\n\t\t\t\tchainId$.next(undefined);\n\t\t\t};\n\n\t\t\t// Subscribe to provider events\n\t\t\twallet.provider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\twallet.provider.on(\"chainChanged\", handleChainChanged);\n\t\t\twallet.provider.on(\"disconnect\", handleDisconnect);\n\n\t\t\t// Fetch initial values\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_accounts\" })\n\t\t\t\t.then((addrs: string[]) => addresses$.next(addrs))\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconsole.error(\"Failed to get accounts\", err);\n\t\t\t\t\taddresses$.next([]);\n\t\t\t\t});\n\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => chainId$.next(undefined));\n\n\t\t\t// Combine addresses + chainId into account list\n\t\t\tconst sub = combineLatest([addresses$, chainId$])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([addresses, chainId]) =>\n\t\t\t\t\t\taddresses.map((addr) => getAccount(addr, chainId)),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\twallet.provider.removeListener(\n\t\t\t\t\t\"accountsChanged\",\n\t\t\t\t\thandleAccountsChanged,\n\t\t\t\t);\n\t\t\t\twallet.provider.removeListener(\"chainChanged\", handleChainChanged);\n\t\t\t\twallet.provider.removeListener(\"disconnect\", handleDisconnect);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst wrapWalletConnectProvider = (\n\tprovider: EIP1193Provider,\n\tsessionTopic: string,\n\tcaipNetworkId: string | undefined,\n): EIP1193Provider => {\n\treturn new Proxy(provider, {\n\t\tget(target, prop, receiver) {\n\t\t\tif (prop !== \"request\") return Reflect.get(target, prop, receiver);\n\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: EIP-1193 request args\n\t\t\treturn (args: any) => {\n\t\t\t\tif (!args || typeof args !== \"object\" || !args.method)\n\t\t\t\t\treturn target.request(args);\n\t\t\t\t// Build a new object rather than mutating the caller's args: the\n\t\t\t\t// EIP-1193 request object is owned by viem and may be frozen or reused.\n\t\t\t\tconst next = { ...args };\n\t\t\t\tif (next.topic === undefined) next.topic = sessionTopic;\n\t\t\t\tif (next.chainId === undefined && caipNetworkId !== undefined)\n\t\t\t\t\tnext.chainId = caipNetworkId;\n\t\t\t\t// WalletConnect's UniversalProvider reads the target CAIP chain id from\n\t\t\t\t// the SECOND positional argument of `request(args, chainId)`, not from a\n\t\t\t\t// field on the args object. This AppKit instance has no native eip155\n\t\t\t\t// adapter, so the provider has no default chain — without the positional\n\t\t\t\t// chain id every call is rejected (\"Unsupported chains\" / \"Method not\n\t\t\t\t// found\"). Pass it positionally so the request routes to the session's\n\t\t\t\t// chain.\n\t\t\t\treturn (\n\t\t\t\t\ttarget.request as (a: unknown, chainId?: string) => Promise<unknown>\n\t\t\t\t)(next, caipNetworkId);\n\t\t\t};\n\t\t},\n\t});\n};\n\nconst sameAddresses = (a: string[], b: string[]) =>\n\ta.length === b.length && a.every((addr, i) => addr === b[i]);\n\nconst getWalletConnectAccounts$ = (\n\twallet: LiveWalletConnectWallet,\n): Observable<EthereumAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"eip155\");\n\n\tif (!wallet.platforms.includes(\"ethereum\") || !provider?.session)\n\t\treturn of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:ethereum:`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst caipNetworkId$ = new ReplaySubject<string | undefined>(1);\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\n\t\t\t// AppKit's getAccount(\"eip155\").allAccounts is empty because this AppKit\n\t\t\t// instance has no native eip155 adapter — eip155 runs through the\n\t\t\t// WalletConnect UniversalProvider, so the session is the source of truth\n\t\t\t// (mirrors the polkadot/solana AppKit paths). Accounts are CAIP-10 strings\n\t\t\t// (\"eip155:<chainRef>:<address>\"), one entry per chain, so dedupe to unique\n\t\t\t// addresses. Read live on each change so switching/adding accounts is\n\t\t\t// reflected.\n\t\t\tconst readAddresses = (): string[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\t\t\t\tconst addresses = new Set<string>();\n\t\t\t\tfor (const raw of getCaip10Addresses(\n\t\t\t\t\tgetSessionCaip10s(session, \"eip155\"),\n\t\t\t\t)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\taddresses.add(getAddress(raw));\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// skip malformed CAIP-10 address\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn [...addresses];\n\t\t\t};\n\n\t\t\t// Derive the CAIP network id from the session's eip155 CAIP-10 accounts\n\t\t\t// (\"eip155:<ref>:<addr>\") as a synchronous fallback for eth_chainId.\n\t\t\tconst readCaipNetworkId = (): string | undefined => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return undefined;\n\t\t\t\tfor (const account of getSessionCaip10s(session, \"eip155\")) {\n\t\t\t\t\tconst ref = account.split(\":\")[1];\n\t\t\t\t\tif (ref) return `eip155:${ref}`;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainId: unknown) => {\n\t\t\t\tconst caipNetworkId = toCaipNetworkId(chainId);\n\t\t\t\tif (caipNetworkId) {\n\t\t\t\t\tcaipNetworkId$.next(caipNetworkId);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = () => addresses$.next(readAddresses());\n\n\t\t\tprovider.on(\"chainChanged\", handleChainChanged);\n\t\t\tprovider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\tprovider.on(\"session_update\", handleAccountsChanged);\n\t\t\t// Seed the chain id from the session synchronously so the account list can\n\t\t\t// surface even if eth_chainId never resolves; eth_chainId then refines it.\n\t\t\t// Without this seed, combineLatest below never fires when eth_chainId\n\t\t\t// rejects or returns an unparseable value, and the accounts silently never\n\t\t\t// appear (the injected path seeds undefined on failure for the same reason).\n\t\t\tcaipNetworkId$.next(readCaipNetworkId());\n\t\t\tprovider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => {});\n\t\t\taddresses$.next(readAddresses());\n\n\t\t\tconst sub = combineLatest([\n\t\t\t\tcaipNetworkId$.pipe(distinctUntilChanged()),\n\t\t\t\taddresses$.pipe(distinctUntilChanged(sameAddresses)),\n\t\t\t])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([caipNetworkId, addresses]) => {\n\t\t\t\t\t\tconst chainId = normalizeEvmChainId(caipNetworkId);\n\t\t\t\t\t\tconst transport = custom(\n\t\t\t\t\t\t\twrapWalletConnectProvider(\n\t\t\t\t\t\t\t\tprovider as unknown as EIP1193Provider,\n\t\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: legacy\n\t\t\t\t\t\t\t\tprovider.session!.topic,\n\t\t\t\t\t\t\t\tcaipNetworkId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn addresses.map((addr): EthereumAccount => {\n\t\t\t\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\t\t\t\taccount: addr as `0x${string}`,\n\t\t\t\t\t\t\t\ttransport,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tid: getWalletAccountId(wallet.id, addr),\n\t\t\t\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t\t\t\taddress: addr as `0x${string}`,\n\t\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\t\tchainId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"chainChanged\", handleChainChanged);\n\t\t\t\tprovider.off(\"accountsChanged\", handleAccountsChanged);\n\t\t\t\tprovider.off(\"session_update\", handleAccountsChanged);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getEthereumAccounts$ = (\n\tethereumWallets: Observable<(EthereumWallet | WalletConnectWallet)[]>,\n) =>\n\tcreatePlatformAccounts$({\n\t\twallets$: ethereumWallets,\n\t\tgetInjectedAccounts$: getInjectedWalletAccounts$,\n\t\tgetWalletConnectAccounts$,\n\t\t// Re-emit on chain switches, not just account id changes.\n\t\taccountChangeKey: (account) => `${account.id}|${account.chainId ?? \"\"}`,\n\t});\n","import {\n\tcreateStore as createMipdStore,\n\ttype EIP6963ProviderDetail,\n} from \"mipd\";\nimport { Observable, shareReplay } from \"rxjs\";\nimport type { EIP1193Provider } from \"viem\";\nimport { clearCachedObservable } from \"../../utils/getCachedObservable\";\nimport { getWalletId } from \"../../utils/WalletId\";\nimport { isEip1193UserRejection } from \"../errors\";\nimport { createInjectedWallets$ } from \"../injectedWallets\";\nimport type { KheopskitStore } from \"../store\";\nimport type { EthereumInjectedWallet } from \"./types\";\n\n/**\n * Observable that emits EIP-6963 provider details from injected wallets.\n * Returns empty array during SSR since browser wallet APIs are not available.\n */\nconst providersDetails$ = new Observable<EIP6963ProviderDetail[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - mipd requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst mipdStore = createMipdStore();\n\n\t\tconst unsubscribe = mipdStore.subscribe((providerDetails) => {\n\t\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\t\t});\n\n\t\tconst providerDetails = mipdStore.getProviders();\n\n\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tmipdStore.destroy();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\n// The shared WalletConnect connector is emitted once by core (see\n// `getWallets$`), not per platform — so this returns only injected wallets.\nexport const getEthereumWallets$ = (store: KheopskitStore) =>\n\tcreateInjectedWallets$<EIP6963ProviderDetail, EthereumInjectedWallet>(store, {\n\t\tsources$: providersDetails$,\n\t\tgetWalletId: (pd) => getWalletId(\"ethereum\", pd.info.rdns),\n\t\tconnect: async (pd) => {\n\t\t\tawait (pd.provider as EIP1193Provider).request({\n\t\t\t\tmethod: \"eth_requestAccounts\",\n\t\t\t});\n\t\t},\n\t\tisUserRejection: isEip1193UserRejection,\n\t\t// Drop the cached account observable so a later reconnect rebuilds it\n\t\t// against the current provider, not a stale closure.\n\t\tonDisconnected: (walletId) => clearCachedObservable(`accounts:${walletId}`),\n\t\tbuildWallet: ({\n\t\t\tsource: pd,\n\t\t\twalletId,\n\t\t\tstatus,\n\t\t\terror,\n\t\t\tisConnected,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}) => ({\n\t\t\tplatform: \"ethereum\",\n\t\t\ttype: \"injected\",\n\t\t\tid: walletId,\n\t\t\tname: pd.info.name,\n\t\t\ticon: pd.info.icon,\n\t\t\tprovider: pd.provider as EIP1193Provider,\n\t\t\tstatus,\n\t\t\terror,\n\t\t\tisConnected,\n\t\t\tsourceId: pd.info.rdns,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}),\n\t});\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getEthereumAccounts$ } from \"./accounts\";\nimport type { EthereumAccount, EthereumWallet } from \"./types\";\nimport { getEthereumWallets$ } from \"./wallets\";\n\n/**\n * Ethereum platform plugin. Pass to `getKheopskit$({ platforms: [ethereum()] })`.\n *\n * @example\n * ```ts\n * import { ethereum } from \"@kheopskit/core/ethereum\";\n * ethereum();\n * ```\n */\nexport const ethereum = (): KheopskitPlatform<\n\t\"ethereum\",\n\tEthereumWallet,\n\tEthereumAccount\n> => ({\n\tplatform: \"ethereum\",\n\tgetWallets$: (ctx: PlatformContext) => getEthereumWallets$(ctx.store),\n\tgetAccounts$: (wallets$) => getEthereumAccounts$(wallets$),\n});\n"],"mappings":"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"}
package/dist/ethereum.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { d as getCachedObservable$, i as getWalletId, l as clearCachedObservable, n as isWalletConnectWallet, t as isInjectedWallet } from "./types-jnifAAA0.mjs";
2
- import { n as getWalletAccountId, s as isEthereumAddress } from "./errors-BLFP1dQI.mjs";
3
- import { i as getSessionCaip10s, n as createPlatformAccounts$, r as getCaip10Addresses, t as createInjectedWallets$ } from "./injectedWallets-Uz4hPuoW.mjs";
1
+ import { _ as getCachedObservable$, a as isEip1193UserRejection, h as clearCachedObservable, n as isWalletConnectWallet, t as isInjectedWallet, u as getWalletId } from "./types-Yor672md.mjs";
2
+ import { d as isEthereumAddress, i as getSessionCaip10s, o as getWalletAccountId, r as getCaip10Addresses, t as createPlatformAccounts$ } from "./platformAccounts-yyRUrnel.mjs";
3
+ import { t as createInjectedWallets$ } from "./injectedWallets-48L-AL1I.mjs";
4
4
  import { Observable, ReplaySubject, combineLatest, distinctUntilChanged, map, of, shareReplay } from "rxjs";
5
5
  import { createWalletClient, custom, getAddress } from "viem";
6
6
  import { createStore } from "mipd";
@@ -184,14 +184,17 @@ const getEthereumWallets$ = (store) => createInjectedWallets$(store, {
184
184
  connect: async (pd) => {
185
185
  await pd.provider.request({ method: "eth_requestAccounts" });
186
186
  },
187
+ isUserRejection: isEip1193UserRejection,
187
188
  onDisconnected: (walletId) => clearCachedObservable(`accounts:${walletId}`),
188
- buildWallet: ({ source: pd, walletId, isConnected, connect, disconnect }) => ({
189
+ buildWallet: ({ source: pd, walletId, status, error, isConnected, connect, disconnect }) => ({
189
190
  platform: "ethereum",
190
191
  type: "injected",
191
192
  id: walletId,
192
193
  name: pd.info.name,
193
194
  icon: pd.info.icon,
194
195
  provider: pd.provider,
196
+ status,
197
+ error,
195
198
  isConnected,
196
199
  sourceId: pd.info.rdns,
197
200
  connect,
@@ -1 +1 @@
1
- {"version":3,"file":"ethereum.mjs","names":["createMipdStore"],"sources":["../src/api/ethereum/accounts.ts","../src/api/ethereum/wallets.ts","../src/api/ethereum/plugin.ts"],"sourcesContent":["import {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tReplaySubject,\n\tshareReplay,\n} from \"rxjs\";\nimport {\n\tcreateWalletClient,\n\tcustom,\n\ttype EIP1193Provider,\n\tgetAddress,\n} from \"viem\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport {\n\tcreatePlatformAccounts$,\n\tgetCaip10Addresses,\n\tgetSessionCaip10s,\n} from \"../platformAccounts\";\nimport type { WalletConnectWallet } from \"../types\";\nimport type {\n\tEthereumAccount,\n\tEthereumInjectedWallet,\n\tEthereumWallet,\n} from \"./types\";\n\nconst normalizeEvmChainId = (value: unknown): number | undefined => {\n\tlet raw = value;\n\n\tif (typeof raw === \"string\" && raw.startsWith(\"eip155:\")) {\n\t\traw = raw.slice(\"eip155:\".length);\n\t}\n\n\tif (typeof raw === \"bigint\") {\n\t\treturn raw >= 0n ? Number(raw) : undefined;\n\t}\n\n\tif (typeof raw === \"number\") {\n\t\treturn Number.isInteger(raw) && raw >= 0 ? raw : undefined;\n\t}\n\n\tif (typeof raw === \"string\") {\n\t\tconst normalized = raw.trim().toLowerCase();\n\t\tif (!normalized) return undefined;\n\t\tconst parsed = normalized.startsWith(\"0x\")\n\t\t\t? Number.parseInt(normalized, 16)\n\t\t\t: Number.parseInt(normalized, 10);\n\t\treturn Number.isNaN(parsed) ? undefined : parsed;\n\t}\n\n\treturn undefined;\n};\n\nconst toCaipNetworkId = (value: unknown): string | undefined => {\n\tconst chainId = normalizeEvmChainId(value);\n\treturn chainId === undefined ? undefined : `eip155:${chainId}`;\n};\n\nconst getInjectedWalletAccounts$ = (\n\twallet: EthereumInjectedWallet,\n): Observable<EthereumAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\t\t\tconst chainId$ = new ReplaySubject<number | undefined>(1);\n\n\t\t\tconst getAccount = (\n\t\t\t\taddress: string,\n\t\t\t\tchainId: number | undefined,\n\t\t\t): EthereumAccount => {\n\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\taccount: address as `0x${string}`,\n\t\t\t\t\ttransport: custom(wallet.provider as EIP1193Provider),\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tid: getWalletAccountId(wallet.id, address),\n\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\tclient,\n\t\t\t\t\taddress: getAddress(address),\n\t\t\t\t\tchainId,\n\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = (addrs: string[]) => {\n\t\t\t\taddresses$.next(addrs);\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainIdHex: unknown) => {\n\t\t\t\tchainId$.next(normalizeEvmChainId(chainIdHex));\n\t\t\t};\n\n\t\t\tconst handleDisconnect = () => {\n\t\t\t\tchainId$.next(undefined);\n\t\t\t};\n\n\t\t\t// Subscribe to provider events\n\t\t\twallet.provider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\twallet.provider.on(\"chainChanged\", handleChainChanged);\n\t\t\twallet.provider.on(\"disconnect\", handleDisconnect);\n\n\t\t\t// Fetch initial values\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_accounts\" })\n\t\t\t\t.then((addrs: string[]) => addresses$.next(addrs))\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconsole.error(\"Failed to get accounts\", err);\n\t\t\t\t\taddresses$.next([]);\n\t\t\t\t});\n\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => chainId$.next(undefined));\n\n\t\t\t// Combine addresses + chainId into account list\n\t\t\tconst sub = combineLatest([addresses$, chainId$])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([addresses, chainId]) =>\n\t\t\t\t\t\taddresses.map((addr) => getAccount(addr, chainId)),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\twallet.provider.removeListener(\n\t\t\t\t\t\"accountsChanged\",\n\t\t\t\t\thandleAccountsChanged,\n\t\t\t\t);\n\t\t\t\twallet.provider.removeListener(\"chainChanged\", handleChainChanged);\n\t\t\t\twallet.provider.removeListener(\"disconnect\", handleDisconnect);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst wrapWalletConnectProvider = (\n\tprovider: EIP1193Provider,\n\tsessionTopic: string,\n\tcaipNetworkId: string | undefined,\n): EIP1193Provider => {\n\treturn new Proxy(provider, {\n\t\tget(target, prop, receiver) {\n\t\t\tif (prop !== \"request\") return Reflect.get(target, prop, receiver);\n\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: EIP-1193 request args\n\t\t\treturn (args: any) => {\n\t\t\t\tif (!args || typeof args !== \"object\" || !args.method)\n\t\t\t\t\treturn target.request(args);\n\t\t\t\t// Build a new object rather than mutating the caller's args: the\n\t\t\t\t// EIP-1193 request object is owned by viem and may be frozen or reused.\n\t\t\t\tconst next = { ...args };\n\t\t\t\tif (next.topic === undefined) next.topic = sessionTopic;\n\t\t\t\tif (next.chainId === undefined && caipNetworkId !== undefined)\n\t\t\t\t\tnext.chainId = caipNetworkId;\n\t\t\t\t// WalletConnect's UniversalProvider reads the target CAIP chain id from\n\t\t\t\t// the SECOND positional argument of `request(args, chainId)`, not from a\n\t\t\t\t// field on the args object. This AppKit instance has no native eip155\n\t\t\t\t// adapter, so the provider has no default chain — without the positional\n\t\t\t\t// chain id every call is rejected (\"Unsupported chains\" / \"Method not\n\t\t\t\t// found\"). Pass it positionally so the request routes to the session's\n\t\t\t\t// chain.\n\t\t\t\treturn (\n\t\t\t\t\ttarget.request as (a: unknown, chainId?: string) => Promise<unknown>\n\t\t\t\t)(next, caipNetworkId);\n\t\t\t};\n\t\t},\n\t});\n};\n\nconst sameAddresses = (a: string[], b: string[]) =>\n\ta.length === b.length && a.every((addr, i) => addr === b[i]);\n\nconst getWalletConnectAccounts$ = (\n\twallet: WalletConnectWallet,\n): Observable<EthereumAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"eip155\");\n\n\tif (!wallet.platforms.includes(\"ethereum\") || !provider?.session)\n\t\treturn of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:ethereum:`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst caipNetworkId$ = new ReplaySubject<string | undefined>(1);\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\n\t\t\t// AppKit's getAccount(\"eip155\").allAccounts is empty because this AppKit\n\t\t\t// instance has no native eip155 adapter — eip155 runs through the\n\t\t\t// WalletConnect UniversalProvider, so the session is the source of truth\n\t\t\t// (mirrors the polkadot/solana AppKit paths). Accounts are CAIP-10 strings\n\t\t\t// (\"eip155:<chainRef>:<address>\"), one entry per chain, so dedupe to unique\n\t\t\t// addresses. Read live on each change so switching/adding accounts is\n\t\t\t// reflected.\n\t\t\tconst readAddresses = (): string[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\t\t\t\tconst addresses = new Set<string>();\n\t\t\t\tfor (const raw of getCaip10Addresses(\n\t\t\t\t\tgetSessionCaip10s(session, \"eip155\"),\n\t\t\t\t)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\taddresses.add(getAddress(raw));\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// skip malformed CAIP-10 address\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn [...addresses];\n\t\t\t};\n\n\t\t\t// Derive the CAIP network id from the session's eip155 CAIP-10 accounts\n\t\t\t// (\"eip155:<ref>:<addr>\") as a synchronous fallback for eth_chainId.\n\t\t\tconst readCaipNetworkId = (): string | undefined => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return undefined;\n\t\t\t\tfor (const account of getSessionCaip10s(session, \"eip155\")) {\n\t\t\t\t\tconst ref = account.split(\":\")[1];\n\t\t\t\t\tif (ref) return `eip155:${ref}`;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainId: unknown) => {\n\t\t\t\tconst caipNetworkId = toCaipNetworkId(chainId);\n\t\t\t\tif (caipNetworkId) {\n\t\t\t\t\tcaipNetworkId$.next(caipNetworkId);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = () => addresses$.next(readAddresses());\n\n\t\t\tprovider.on(\"chainChanged\", handleChainChanged);\n\t\t\tprovider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\tprovider.on(\"session_update\", handleAccountsChanged);\n\t\t\t// Seed the chain id from the session synchronously so the account list can\n\t\t\t// surface even if eth_chainId never resolves; eth_chainId then refines it.\n\t\t\t// Without this seed, combineLatest below never fires when eth_chainId\n\t\t\t// rejects or returns an unparseable value, and the accounts silently never\n\t\t\t// appear (the injected path seeds undefined on failure for the same reason).\n\t\t\tcaipNetworkId$.next(readCaipNetworkId());\n\t\t\tprovider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => {});\n\t\t\taddresses$.next(readAddresses());\n\n\t\t\tconst sub = combineLatest([\n\t\t\t\tcaipNetworkId$.pipe(distinctUntilChanged()),\n\t\t\t\taddresses$.pipe(distinctUntilChanged(sameAddresses)),\n\t\t\t])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([caipNetworkId, addresses]) => {\n\t\t\t\t\t\tconst chainId = normalizeEvmChainId(caipNetworkId);\n\t\t\t\t\t\tconst transport = custom(\n\t\t\t\t\t\t\twrapWalletConnectProvider(\n\t\t\t\t\t\t\t\tprovider as unknown as EIP1193Provider,\n\t\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: legacy\n\t\t\t\t\t\t\t\tprovider.session!.topic,\n\t\t\t\t\t\t\t\tcaipNetworkId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn addresses.map((addr): EthereumAccount => {\n\t\t\t\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\t\t\t\taccount: addr as `0x${string}`,\n\t\t\t\t\t\t\t\ttransport,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tid: getWalletAccountId(wallet.id, addr),\n\t\t\t\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t\t\t\taddress: addr as `0x${string}`,\n\t\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\t\tchainId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"chainChanged\", handleChainChanged);\n\t\t\t\tprovider.off(\"accountsChanged\", handleAccountsChanged);\n\t\t\t\tprovider.off(\"session_update\", handleAccountsChanged);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getEthereumAccounts$ = (\n\tethereumWallets: Observable<(EthereumWallet | WalletConnectWallet)[]>,\n) =>\n\tcreatePlatformAccounts$({\n\t\twallets$: ethereumWallets,\n\t\tgetInjectedAccounts$: getInjectedWalletAccounts$,\n\t\tgetWalletConnectAccounts$,\n\t\t// Re-emit on chain switches, not just account id changes.\n\t\taccountChangeKey: (account) => `${account.id}|${account.chainId ?? \"\"}`,\n\t});\n","import {\n\tcreateStore as createMipdStore,\n\ttype EIP6963ProviderDetail,\n} from \"mipd\";\nimport { Observable, shareReplay } from \"rxjs\";\nimport type { EIP1193Provider } from \"viem\";\nimport { clearCachedObservable } from \"../../utils/getCachedObservable\";\nimport { getWalletId } from \"../../utils/WalletId\";\nimport { createInjectedWallets$ } from \"../injectedWallets\";\nimport type { KheopskitStore } from \"../store\";\nimport type { EthereumInjectedWallet } from \"./types\";\n\n/**\n * Observable that emits EIP-6963 provider details from injected wallets.\n * Returns empty array during SSR since browser wallet APIs are not available.\n */\nconst providersDetails$ = new Observable<EIP6963ProviderDetail[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - mipd requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst mipdStore = createMipdStore();\n\n\t\tconst unsubscribe = mipdStore.subscribe((providerDetails) => {\n\t\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\t\t});\n\n\t\tconst providerDetails = mipdStore.getProviders();\n\n\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tmipdStore.destroy();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\n// The shared WalletConnect connector is emitted once by core (see\n// `getWallets$`), not per platform — so this returns only injected wallets.\nexport const getEthereumWallets$ = (store: KheopskitStore) =>\n\tcreateInjectedWallets$<EIP6963ProviderDetail, EthereumInjectedWallet>(store, {\n\t\tsources$: providersDetails$,\n\t\tgetWalletId: (pd) => getWalletId(\"ethereum\", pd.info.rdns),\n\t\tconnect: async (pd) => {\n\t\t\tawait (pd.provider as EIP1193Provider).request({\n\t\t\t\tmethod: \"eth_requestAccounts\",\n\t\t\t});\n\t\t},\n\t\t// Drop the cached account observable so a later reconnect rebuilds it\n\t\t// against the current provider, not a stale closure.\n\t\tonDisconnected: (walletId) => clearCachedObservable(`accounts:${walletId}`),\n\t\tbuildWallet: ({\n\t\t\tsource: pd,\n\t\t\twalletId,\n\t\t\tisConnected,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}) => ({\n\t\t\tplatform: \"ethereum\",\n\t\t\ttype: \"injected\",\n\t\t\tid: walletId,\n\t\t\tname: pd.info.name,\n\t\t\ticon: pd.info.icon,\n\t\t\tprovider: pd.provider as EIP1193Provider,\n\t\t\tisConnected,\n\t\t\tsourceId: pd.info.rdns,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}),\n\t});\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getEthereumAccounts$ } from \"./accounts\";\nimport type { EthereumAccount, EthereumWallet } from \"./types\";\nimport { getEthereumWallets$ } from \"./wallets\";\n\n/**\n * Ethereum platform plugin. Pass to `getKheopskit$({ platforms: [ethereum()] })`.\n *\n * @example\n * ```ts\n * import { ethereum } from \"@kheopskit/core/ethereum\";\n * ethereum();\n * ```\n */\nexport const ethereum = (): KheopskitPlatform<\n\t\"ethereum\",\n\tEthereumWallet,\n\tEthereumAccount\n> => ({\n\tplatform: \"ethereum\",\n\tgetWallets$: (ctx: PlatformContext) => getEthereumWallets$(ctx.store),\n\tgetAccounts$: (wallets$) => getEthereumAccounts$(wallets$),\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"ethereum.mjs","names":["createMipdStore"],"sources":["../src/api/ethereum/accounts.ts","../src/api/ethereum/wallets.ts","../src/api/ethereum/plugin.ts"],"sourcesContent":["import {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tReplaySubject,\n\tshareReplay,\n} from \"rxjs\";\nimport {\n\tcreateWalletClient,\n\tcustom,\n\ttype EIP1193Provider,\n\tgetAddress,\n} from \"viem\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport {\n\tcreatePlatformAccounts$,\n\tgetCaip10Addresses,\n\tgetSessionCaip10s,\n\ttype LiveWalletConnectWallet,\n} from \"../platformAccounts\";\nimport type { WalletConnectWallet } from \"../types\";\nimport type {\n\tEthereumAccount,\n\tEthereumInjectedWallet,\n\tEthereumWallet,\n} from \"./types\";\n\nconst normalizeEvmChainId = (value: unknown): number | undefined => {\n\tlet raw = value;\n\n\tif (typeof raw === \"string\" && raw.startsWith(\"eip155:\")) {\n\t\traw = raw.slice(\"eip155:\".length);\n\t}\n\n\tif (typeof raw === \"bigint\") {\n\t\treturn raw >= 0n ? Number(raw) : undefined;\n\t}\n\n\tif (typeof raw === \"number\") {\n\t\treturn Number.isInteger(raw) && raw >= 0 ? raw : undefined;\n\t}\n\n\tif (typeof raw === \"string\") {\n\t\tconst normalized = raw.trim().toLowerCase();\n\t\tif (!normalized) return undefined;\n\t\tconst parsed = normalized.startsWith(\"0x\")\n\t\t\t? Number.parseInt(normalized, 16)\n\t\t\t: Number.parseInt(normalized, 10);\n\t\treturn Number.isNaN(parsed) ? undefined : parsed;\n\t}\n\n\treturn undefined;\n};\n\nconst toCaipNetworkId = (value: unknown): string | undefined => {\n\tconst chainId = normalizeEvmChainId(value);\n\treturn chainId === undefined ? undefined : `eip155:${chainId}`;\n};\n\nconst getInjectedWalletAccounts$ = (\n\twallet: EthereumInjectedWallet,\n): Observable<EthereumAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\t\t\tconst chainId$ = new ReplaySubject<number | undefined>(1);\n\n\t\t\tconst getAccount = (\n\t\t\t\taddress: string,\n\t\t\t\tchainId: number | undefined,\n\t\t\t): EthereumAccount => {\n\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\taccount: address as `0x${string}`,\n\t\t\t\t\ttransport: custom(wallet.provider as EIP1193Provider),\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tid: getWalletAccountId(wallet.id, address),\n\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\tclient,\n\t\t\t\t\taddress: getAddress(address),\n\t\t\t\t\tchainId,\n\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = (addrs: string[]) => {\n\t\t\t\taddresses$.next(addrs);\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainIdHex: unknown) => {\n\t\t\t\tchainId$.next(normalizeEvmChainId(chainIdHex));\n\t\t\t};\n\n\t\t\tconst handleDisconnect = () => {\n\t\t\t\tchainId$.next(undefined);\n\t\t\t};\n\n\t\t\t// Subscribe to provider events\n\t\t\twallet.provider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\twallet.provider.on(\"chainChanged\", handleChainChanged);\n\t\t\twallet.provider.on(\"disconnect\", handleDisconnect);\n\n\t\t\t// Fetch initial values\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_accounts\" })\n\t\t\t\t.then((addrs: string[]) => addresses$.next(addrs))\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconsole.error(\"Failed to get accounts\", err);\n\t\t\t\t\taddresses$.next([]);\n\t\t\t\t});\n\n\t\t\twallet.provider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => chainId$.next(undefined));\n\n\t\t\t// Combine addresses + chainId into account list\n\t\t\tconst sub = combineLatest([addresses$, chainId$])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([addresses, chainId]) =>\n\t\t\t\t\t\taddresses.map((addr) => getAccount(addr, chainId)),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\twallet.provider.removeListener(\n\t\t\t\t\t\"accountsChanged\",\n\t\t\t\t\thandleAccountsChanged,\n\t\t\t\t);\n\t\t\t\twallet.provider.removeListener(\"chainChanged\", handleChainChanged);\n\t\t\t\twallet.provider.removeListener(\"disconnect\", handleDisconnect);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst wrapWalletConnectProvider = (\n\tprovider: EIP1193Provider,\n\tsessionTopic: string,\n\tcaipNetworkId: string | undefined,\n): EIP1193Provider => {\n\treturn new Proxy(provider, {\n\t\tget(target, prop, receiver) {\n\t\t\tif (prop !== \"request\") return Reflect.get(target, prop, receiver);\n\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: EIP-1193 request args\n\t\t\treturn (args: any) => {\n\t\t\t\tif (!args || typeof args !== \"object\" || !args.method)\n\t\t\t\t\treturn target.request(args);\n\t\t\t\t// Build a new object rather than mutating the caller's args: the\n\t\t\t\t// EIP-1193 request object is owned by viem and may be frozen or reused.\n\t\t\t\tconst next = { ...args };\n\t\t\t\tif (next.topic === undefined) next.topic = sessionTopic;\n\t\t\t\tif (next.chainId === undefined && caipNetworkId !== undefined)\n\t\t\t\t\tnext.chainId = caipNetworkId;\n\t\t\t\t// WalletConnect's UniversalProvider reads the target CAIP chain id from\n\t\t\t\t// the SECOND positional argument of `request(args, chainId)`, not from a\n\t\t\t\t// field on the args object. This AppKit instance has no native eip155\n\t\t\t\t// adapter, so the provider has no default chain — without the positional\n\t\t\t\t// chain id every call is rejected (\"Unsupported chains\" / \"Method not\n\t\t\t\t// found\"). Pass it positionally so the request routes to the session's\n\t\t\t\t// chain.\n\t\t\t\treturn (\n\t\t\t\t\ttarget.request as (a: unknown, chainId?: string) => Promise<unknown>\n\t\t\t\t)(next, caipNetworkId);\n\t\t\t};\n\t\t},\n\t});\n};\n\nconst sameAddresses = (a: string[], b: string[]) =>\n\ta.length === b.length && a.every((addr, i) => addr === b[i]);\n\nconst getWalletConnectAccounts$ = (\n\twallet: LiveWalletConnectWallet,\n): Observable<EthereumAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"eip155\");\n\n\tif (!wallet.platforms.includes(\"ethereum\") || !provider?.session)\n\t\treturn of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:ethereum:`, () =>\n\t\tnew Observable<EthereumAccount[]>((subscriber) => {\n\t\t\tconst caipNetworkId$ = new ReplaySubject<string | undefined>(1);\n\t\t\tconst addresses$ = new ReplaySubject<string[]>(1);\n\n\t\t\t// AppKit's getAccount(\"eip155\").allAccounts is empty because this AppKit\n\t\t\t// instance has no native eip155 adapter — eip155 runs through the\n\t\t\t// WalletConnect UniversalProvider, so the session is the source of truth\n\t\t\t// (mirrors the polkadot/solana AppKit paths). Accounts are CAIP-10 strings\n\t\t\t// (\"eip155:<chainRef>:<address>\"), one entry per chain, so dedupe to unique\n\t\t\t// addresses. Read live on each change so switching/adding accounts is\n\t\t\t// reflected.\n\t\t\tconst readAddresses = (): string[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\t\t\t\tconst addresses = new Set<string>();\n\t\t\t\tfor (const raw of getCaip10Addresses(\n\t\t\t\t\tgetSessionCaip10s(session, \"eip155\"),\n\t\t\t\t)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\taddresses.add(getAddress(raw));\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// skip malformed CAIP-10 address\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn [...addresses];\n\t\t\t};\n\n\t\t\t// Derive the CAIP network id from the session's eip155 CAIP-10 accounts\n\t\t\t// (\"eip155:<ref>:<addr>\") as a synchronous fallback for eth_chainId.\n\t\t\tconst readCaipNetworkId = (): string | undefined => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return undefined;\n\t\t\t\tfor (const account of getSessionCaip10s(session, \"eip155\")) {\n\t\t\t\t\tconst ref = account.split(\":\")[1];\n\t\t\t\t\tif (ref) return `eip155:${ref}`;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t};\n\n\t\t\tconst handleChainChanged = (chainId: unknown) => {\n\t\t\t\tconst caipNetworkId = toCaipNetworkId(chainId);\n\t\t\t\tif (caipNetworkId) {\n\t\t\t\t\tcaipNetworkId$.next(caipNetworkId);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst handleAccountsChanged = () => addresses$.next(readAddresses());\n\n\t\t\tprovider.on(\"chainChanged\", handleChainChanged);\n\t\t\tprovider.on(\"accountsChanged\", handleAccountsChanged);\n\t\t\tprovider.on(\"session_update\", handleAccountsChanged);\n\t\t\t// Seed the chain id from the session synchronously so the account list can\n\t\t\t// surface even if eth_chainId never resolves; eth_chainId then refines it.\n\t\t\t// Without this seed, combineLatest below never fires when eth_chainId\n\t\t\t// rejects or returns an unparseable value, and the accounts silently never\n\t\t\t// appear (the injected path seeds undefined on failure for the same reason).\n\t\t\tcaipNetworkId$.next(readCaipNetworkId());\n\t\t\tprovider\n\t\t\t\t.request({ method: \"eth_chainId\" })\n\t\t\t\t.then(handleChainChanged)\n\t\t\t\t.catch(() => {});\n\t\t\taddresses$.next(readAddresses());\n\n\t\t\tconst sub = combineLatest([\n\t\t\t\tcaipNetworkId$.pipe(distinctUntilChanged()),\n\t\t\t\taddresses$.pipe(distinctUntilChanged(sameAddresses)),\n\t\t\t])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([caipNetworkId, addresses]) => {\n\t\t\t\t\t\tconst chainId = normalizeEvmChainId(caipNetworkId);\n\t\t\t\t\t\tconst transport = custom(\n\t\t\t\t\t\t\twrapWalletConnectProvider(\n\t\t\t\t\t\t\t\tprovider as unknown as EIP1193Provider,\n\t\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: legacy\n\t\t\t\t\t\t\t\tprovider.session!.topic,\n\t\t\t\t\t\t\t\tcaipNetworkId,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn addresses.map((addr): EthereumAccount => {\n\t\t\t\t\t\t\tconst client = createWalletClient({\n\t\t\t\t\t\t\t\taccount: addr as `0x${string}`,\n\t\t\t\t\t\t\t\ttransport,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tid: getWalletAccountId(wallet.id, addr),\n\t\t\t\t\t\t\t\tplatform: \"ethereum\",\n\t\t\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t\t\t\taddress: addr as `0x${string}`,\n\t\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\t\tchainId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"chainChanged\", handleChainChanged);\n\t\t\t\tprovider.off(\"accountsChanged\", handleAccountsChanged);\n\t\t\t\tprovider.off(\"session_update\", handleAccountsChanged);\n\t\t\t\tsub.unsubscribe();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getEthereumAccounts$ = (\n\tethereumWallets: Observable<(EthereumWallet | WalletConnectWallet)[]>,\n) =>\n\tcreatePlatformAccounts$({\n\t\twallets$: ethereumWallets,\n\t\tgetInjectedAccounts$: getInjectedWalletAccounts$,\n\t\tgetWalletConnectAccounts$,\n\t\t// Re-emit on chain switches, not just account id changes.\n\t\taccountChangeKey: (account) => `${account.id}|${account.chainId ?? \"\"}`,\n\t});\n","import {\n\tcreateStore as createMipdStore,\n\ttype EIP6963ProviderDetail,\n} from \"mipd\";\nimport { Observable, shareReplay } from \"rxjs\";\nimport type { EIP1193Provider } from \"viem\";\nimport { clearCachedObservable } from \"../../utils/getCachedObservable\";\nimport { getWalletId } from \"../../utils/WalletId\";\nimport { isEip1193UserRejection } from \"../errors\";\nimport { createInjectedWallets$ } from \"../injectedWallets\";\nimport type { KheopskitStore } from \"../store\";\nimport type { EthereumInjectedWallet } from \"./types\";\n\n/**\n * Observable that emits EIP-6963 provider details from injected wallets.\n * Returns empty array during SSR since browser wallet APIs are not available.\n */\nconst providersDetails$ = new Observable<EIP6963ProviderDetail[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - mipd requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst mipdStore = createMipdStore();\n\n\t\tconst unsubscribe = mipdStore.subscribe((providerDetails) => {\n\t\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\t\t});\n\n\t\tconst providerDetails = mipdStore.getProviders();\n\n\t\tsubscriber.next(providerDetails as EIP6963ProviderDetail[]);\n\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tmipdStore.destroy();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\n// The shared WalletConnect connector is emitted once by core (see\n// `getWallets$`), not per platform — so this returns only injected wallets.\nexport const getEthereumWallets$ = (store: KheopskitStore) =>\n\tcreateInjectedWallets$<EIP6963ProviderDetail, EthereumInjectedWallet>(store, {\n\t\tsources$: providersDetails$,\n\t\tgetWalletId: (pd) => getWalletId(\"ethereum\", pd.info.rdns),\n\t\tconnect: async (pd) => {\n\t\t\tawait (pd.provider as EIP1193Provider).request({\n\t\t\t\tmethod: \"eth_requestAccounts\",\n\t\t\t});\n\t\t},\n\t\tisUserRejection: isEip1193UserRejection,\n\t\t// Drop the cached account observable so a later reconnect rebuilds it\n\t\t// against the current provider, not a stale closure.\n\t\tonDisconnected: (walletId) => clearCachedObservable(`accounts:${walletId}`),\n\t\tbuildWallet: ({\n\t\t\tsource: pd,\n\t\t\twalletId,\n\t\t\tstatus,\n\t\t\terror,\n\t\t\tisConnected,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}) => ({\n\t\t\tplatform: \"ethereum\",\n\t\t\ttype: \"injected\",\n\t\t\tid: walletId,\n\t\t\tname: pd.info.name,\n\t\t\ticon: pd.info.icon,\n\t\t\tprovider: pd.provider as EIP1193Provider,\n\t\t\tstatus,\n\t\t\terror,\n\t\t\tisConnected,\n\t\t\tsourceId: pd.info.rdns,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t}),\n\t});\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getEthereumAccounts$ } from \"./accounts\";\nimport type { EthereumAccount, EthereumWallet } from \"./types\";\nimport { getEthereumWallets$ } from \"./wallets\";\n\n/**\n * Ethereum platform plugin. Pass to `getKheopskit$({ platforms: [ethereum()] })`.\n *\n * @example\n * ```ts\n * import { ethereum } from \"@kheopskit/core/ethereum\";\n * ethereum();\n * ```\n */\nexport const ethereum = (): KheopskitPlatform<\n\t\"ethereum\",\n\tEthereumWallet,\n\tEthereumAccount\n> => ({\n\tplatform: \"ethereum\",\n\tgetWallets$: (ctx: PlatformContext) => getEthereumWallets$(ctx.store),\n\tgetAccounts$: (wallets$) => getEthereumAccounts$(wallets$),\n});\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as isWalletConnectWallet, o as parseWalletId } from "./types-jnifAAA0.mjs";
1
+ import { c as walletPendingError, f as parseWalletId, n as isWalletConnectWallet } from "./types-Yor672md.mjs";
2
2
  import { t as POLKADOT_EXTENSIONS } from "./polkadotExtensions-BoVKhNU_.mjs";
3
3
  //#region src/utils/hydrateState.ts
4
4
  /**
@@ -14,35 +14,22 @@ const lookupWalletIcon = (platform, identifier) => {
14
14
  if (platform === "polkadot") return POLKADOT_EXTENSIONS[identifier]?.icon ?? "";
15
15
  return "";
16
16
  };
17
- /**
18
- * Error thrown when trying to use a placeholder wallet that hasn't fully loaded yet.
19
- */
20
- var PendingWalletError = class extends Error {
21
- constructor(walletId) {
22
- super(`Wallet ${walletId} is still loading. Wait for isHydrating to be false before calling connect/disconnect.`);
23
- this.name = "PendingWalletError";
24
- }
25
- };
26
- /**
27
- * Converts a CachedWallet to a placeholder wallet for SSR hydration display.
28
- *
29
- * The placeholder carries only the SDK-free {@link BaseWallet} fields; the real
30
- * wallet (with its injected provider/extension/standard-wallet handle) replaces
31
- * it once it loads. connect/disconnect throw until then.
32
- */
33
17
  const hydrateWallet = (cached) => {
34
- const throwPending = () => {
35
- throw new PendingWalletError(cached.id);
18
+ const connect = async () => {
19
+ throw walletPendingError(cached.id);
36
20
  };
21
+ const disconnect = async () => {};
37
22
  if (cached.type === "walletconnect") return {
38
23
  id: cached.id,
39
24
  type: "walletconnect",
40
25
  platforms: [],
41
26
  name: cached.name,
42
27
  icon: "",
43
- isConnected: cached.isConnected,
44
- connect: throwPending,
45
- disconnect: throwPending
28
+ status: cached.isConnected ? "connecting" : "disconnected",
29
+ isPlaceholder: true,
30
+ isConnected: false,
31
+ connect,
32
+ disconnect
46
33
  };
47
34
  const { platform, identifier } = parseWalletId(cached.id);
48
35
  return {
@@ -51,30 +38,24 @@ const hydrateWallet = (cached) => {
51
38
  type: cached.type,
52
39
  name: cached.name,
53
40
  icon: lookupWalletIcon(platform, identifier),
54
- isConnected: cached.isConnected,
55
- connect: throwPending,
56
- disconnect: throwPending
41
+ status: cached.isConnected ? "connecting" : "disconnected",
42
+ isPlaceholder: true,
43
+ isConnected: false,
44
+ connect,
45
+ disconnect
57
46
  };
58
47
  };
59
- /**
60
- * Converts a CachedAccount to a placeholder account for SSR hydration display.
61
- *
62
- * The placeholder carries the SDK-free {@link BaseWalletAccount} fields plus the
63
- * plain, serializable platform data that lives in the cache — Ethereum `chainId`
64
- * and the Polkadot key `type`. Those render immediately on reload (no blank →
65
- * value flicker) and match what the live account will report. Only the SDK
66
- * handles (`client`/`signer`/`txCreator`) are absent until the real account
67
- * replaces this placeholder; signing stays gated on `isHydrating` until then.
68
- */
69
48
  const hydrateAccount = (cached) => ({
70
49
  id: cached.id,
50
+ isPlaceholder: true,
71
51
  platform: cached.platform,
72
52
  address: cached.address,
73
53
  name: cached.name,
74
54
  walletId: cached.walletId,
75
55
  walletName: cached.walletName,
76
56
  ...cached.platform === "ethereum" && { chainId: cached.chainId },
77
- ...cached.platform === "polkadot" && { type: cached.polkadotAccountType }
57
+ ...cached.platform === "polkadot" && { type: cached.polkadotAccountType },
58
+ ...cached.platform === "solana" && { chains: [] }
78
59
  });
79
60
  /**
80
61
  * Converts a wallet to a CachedWallet for storage.
@@ -158,14 +139,14 @@ const getSafeLocalStorage = () => {
158
139
  };
159
140
  /**
160
141
  * @deprecated Use getSafeLocalStorage() instead. This is kept for backward compatibility.
161
- * Returns a proxy that lazily initializes on first method call.
142
+ * Returns a proxy that lazily initializes on first use.
162
143
  */
163
144
  const safeLocalStorage = {
164
145
  getItem: (key) => getSafeLocalStorage().getItem(key),
165
146
  setItem: (key, value) => getSafeLocalStorage().setItem(key, value),
166
147
  removeItem: (key) => getSafeLocalStorage().removeItem(key),
167
- subscribe: (key, callback) => {
168
- return getSafeLocalStorage().subscribe?.(key, callback) ?? (() => {});
148
+ get subscribe() {
149
+ return getSafeLocalStorage().subscribe;
169
150
  }
170
151
  };
171
152
  /**
@@ -340,4 +321,4 @@ const setCachedIcons = (icons) => {
340
321
  //#endregion
341
322
  export { safeLocalStorage as a, serializeAccount as c, getSafeLocalStorage as i, serializeWallet as l, setCachedIcons as n, hydrateAccount as o, cookieStorage as r, hydrateWallet as s, getCachedIcon as t };
342
323
 
343
- //# sourceMappingURL=iconCache-pP2ES4pJ.mjs.map
324
+ //# sourceMappingURL=iconCache-C-U3IEbP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iconCache-C-U3IEbP.mjs","names":[],"sources":["../src/utils/hydrateState.ts","../src/utils/storage.ts","../src/utils/iconCache.ts"],"sourcesContent":["import { walletPendingError } from \"../api/errors\";\nimport {\n\ttype BaseWallet,\n\ttype BaseWalletAccount,\n\ttype CachedAccount,\n\ttype CachedWallet,\n\tisWalletConnectWallet,\n\ttype PolkadotAccountType,\n\ttype WalletConnectWallet,\n} from \"../api/types\";\nimport { POLKADOT_EXTENSIONS } from \"./polkadotExtensions\";\nimport type { WalletAccountId } from \"./WalletAccountId\";\nimport { parseWalletId, type WalletId } from \"./WalletId\";\n\n/**\n * Looks up the icon for a wallet from known Polkadot extensions only.\n * Ethereum icons will be populated from the localStorage icon cache via the merge function.\n *\n * Note: We DON'T use localStorage icon cache here because hydrateWallet is called\n * during SSR (server) and client hydration. localStorage isn't available on server,\n * so using it would cause a hydration mismatch. Icons for Ethereum wallets will be\n * populated when the hydration buffer merges cached wallets with live wallets.\n */\nconst lookupWalletIcon = (platform: string, identifier: string): string => {\n\t// Only Polkadot extensions have hardcoded icons that are safe for SSR\n\tif (platform === \"polkadot\") {\n\t\treturn POLKADOT_EXTENSIONS[identifier]?.icon ?? \"\";\n\t}\n\t// Ethereum icons come from localStorage or live wallets - not here\n\treturn \"\";\n};\n\ntype PlaceholderOf<W> = W & { isPlaceholder: true; isConnected: false };\n\nexport const hydrateWallet = (\n\tcached: CachedWallet,\n): PlaceholderOf<BaseWallet | WalletConnectWallet> => {\n\tconst connect = async () => {\n\t\tthrow walletPendingError(cached.id);\n\t};\n\tconst disconnect = async () => {};\n\n\tif (cached.type === \"walletconnect\") {\n\t\treturn {\n\t\t\tid: cached.id,\n\t\t\ttype: \"walletconnect\",\n\t\t\tplatforms: [],\n\t\t\tname: cached.name,\n\t\t\ticon: \"\",\n\t\t\tstatus: cached.isConnected ? \"connecting\" : \"disconnected\",\n\t\t\tisPlaceholder: true,\n\t\t\tisConnected: false,\n\t\t\tconnect,\n\t\t\tdisconnect,\n\t\t};\n\t}\n\n\tconst { platform, identifier } = parseWalletId(cached.id);\n\n\treturn {\n\t\tid: cached.id,\n\t\tplatform: cached.platform as BaseWallet[\"platform\"],\n\t\ttype: cached.type,\n\t\tname: cached.name,\n\t\ticon: lookupWalletIcon(platform, identifier),\n\t\tstatus: cached.isConnected ? \"connecting\" : \"disconnected\",\n\t\tisPlaceholder: true,\n\t\tisConnected: false,\n\t\tconnect,\n\t\tdisconnect,\n\t};\n};\n\nexport const hydrateAccount = (\n\tcached: CachedAccount,\n): BaseWalletAccount & { isPlaceholder: true } => ({\n\tid: cached.id as WalletAccountId,\n\tisPlaceholder: true,\n\tplatform: cached.platform,\n\taddress: cached.address,\n\tname: cached.name,\n\twalletId: cached.walletId,\n\twalletName: cached.walletName,\n\t// Spread (not direct keys) so the extra platform fields don't trip the\n\t// excess-property check against BaseWalletAccount; they're read back via the\n\t// platform-specific account types once narrowed by `platform`.\n\t...(cached.platform === \"ethereum\" && { chainId: cached.chainId }),\n\t...(cached.platform === \"polkadot\" && {\n\t\ttype: cached.polkadotAccountType,\n\t}),\n\t...(cached.platform === \"solana\" && { chains: [] }),\n});\n\n/**\n * Converts a wallet to a CachedWallet for storage.\n * Only extracts the serializable properties needed for hydration.\n */\nexport const serializeWallet = (\n\twallet: BaseWallet | WalletConnectWallet,\n): CachedWallet => ({\n\tid: wallet.id,\n\t// The WalletConnect connector has no platform.\n\tplatform: isWalletConnectWallet(wallet) ? undefined : wallet.platform,\n\ttype: wallet.type,\n\tname: wallet.name,\n\t// Note: icon is NOT stored to save cookie space\n\tisConnected: wallet.isConnected,\n});\n\n/**\n * Converts an account to a CachedAccount for storage.\n * Only extracts the serializable properties needed for hydration. Platform-only\n * fields (Ethereum chainId, Polkadot key type) are read defensively so this\n * stays SDK-free.\n */\nexport const serializeAccount = (\n\taccount: BaseWalletAccount,\n): CachedAccount => ({\n\tid: account.id,\n\tplatform: account.platform,\n\taddress: account.address,\n\tname: account.name,\n\tchainId:\n\t\taccount.platform === \"ethereum\"\n\t\t\t? (account as { chainId?: number }).chainId\n\t\t\t: undefined,\n\tpolkadotAccountType:\n\t\taccount.platform === \"polkadot\"\n\t\t\t? (account as { type?: PolkadotAccountType }).type\n\t\t\t: undefined,\n\twalletId: account.walletId as WalletId,\n\twalletName: account.walletName,\n});\n","export type Storage = {\n\tgetItem: (key: string) => string | null;\n\tsetItem: (key: string, value: string) => void;\n\tremoveItem: (key: string) => void;\n};\n\n/**\n * Extended storage interface with cross-tab sync support.\n */\nexport type SyncableStorage = Storage & {\n\t/**\n\t * Subscribe to storage changes from other tabs.\n\t * Returns an unsubscribe function.\n\t */\n\tsubscribe?: (\n\t\tkey: string,\n\t\tcallback: (value: string | null) => void,\n\t) => () => void;\n};\n\n/**\n * A no-op storage implementation that does nothing.\n * Useful for testing or SSR environments where no storage is needed.\n */\nexport const noopStorage: SyncableStorage = {\n\tgetItem: () => null,\n\tsetItem: () => {},\n\tremoveItem: () => {},\n};\n\n/**\n * Cached localStorage wrapper instance.\n * Lazily initialized on first access to avoid SSR issues.\n */\nlet _safeLocalStorage: SyncableStorage | null = null;\n\n/**\n * Creates the localStorage wrapper, testing for availability.\n * Returns noopStorage if localStorage is unavailable (SSR, private browsing, etc.)\n */\nconst createSafeLocalStorage = (): SyncableStorage => {\n\tif (typeof window === \"undefined\") return noopStorage;\n\n\ttry {\n\t\t// Test that localStorage is accessible (may throw in private browsing)\n\t\tconst testKey = \"__kheopskit_test__\";\n\t\twindow.localStorage.setItem(testKey, testKey);\n\t\twindow.localStorage.removeItem(testKey);\n\n\t\treturn {\n\t\t\tgetItem: (key: string) => window.localStorage.getItem(key),\n\t\t\tsetItem: (key: string, value: string) =>\n\t\t\t\twindow.localStorage.setItem(key, value),\n\t\t\tremoveItem: (key: string) => window.localStorage.removeItem(key),\n\t\t\tsubscribe: (key: string, callback: (value: string | null) => void) => {\n\t\t\t\tconst handler = (event: StorageEvent) => {\n\t\t\t\t\tif (event.key === key) {\n\t\t\t\t\t\tcallback(event.newValue);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\twindow.addEventListener(\"storage\", handler);\n\t\t\t\treturn () => window.removeEventListener(\"storage\", handler);\n\t\t\t},\n\t\t};\n\t} catch {\n\t\treturn noopStorage;\n\t}\n};\n\n/**\n * A safe localStorage wrapper that falls back to noopStorage\n * when localStorage is not available (e.g., during SSR).\n * Includes cross-tab sync via the native 'storage' event.\n *\n * Lazily initialized on first access to be SSR-safe.\n */\nexport const getSafeLocalStorage = (): SyncableStorage => {\n\tif (_safeLocalStorage === null) {\n\t\t_safeLocalStorage = createSafeLocalStorage();\n\t}\n\treturn _safeLocalStorage;\n};\n\n/**\n * @deprecated Use getSafeLocalStorage() instead. This is kept for backward compatibility.\n * Returns a proxy that lazily initializes on first use.\n */\nexport const safeLocalStorage: SyncableStorage = {\n\tgetItem: (key: string) => getSafeLocalStorage().getItem(key),\n\tsetItem: (key: string, value: string) =>\n\t\tgetSafeLocalStorage().setItem(key, value),\n\tremoveItem: (key: string) => getSafeLocalStorage().removeItem(key),\n\tget subscribe() {\n\t\treturn getSafeLocalStorage().subscribe;\n\t},\n};\n\n/**\n * Parse a cookie string to extract the value for a specific key.\n * @param cookieString - The full cookie header string (e.g., document.cookie or req.headers.cookie)\n * @param key - The cookie key to find\n * @returns The cookie value or null if not found\n */\nexport const parseCookie = (\n\tcookieString: string | undefined,\n\tkey: string,\n): string | null => {\n\tif (!cookieString) return null;\n\n\tfor (const cookie of cookieString.split(\";\")) {\n\t\tconst [k, ...v] = cookie.split(\"=\");\n\t\tconst cookieKey = k?.trim();\n\t\tif (cookieKey === key) {\n\t\t\ttry {\n\t\t\t\treturn decodeURIComponent(v.join(\"=\").trim());\n\t\t\t} catch {\n\t\t\t\treturn null; // Malformed cookie value\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n};\n\n/**\n * Maximum recommended size for cookie storage (3KB to stay well under 4KB limit).\n *\n * @remarks\n * Cookie storage is subject to browser limits (typically 4KB per cookie).\n * When users connect many wallets, the auto-reconnect list may exceed this limit.\n * If this happens:\n * - A console warning will be logged\n * - Some browsers may silently reject the cookie\n * - Consider using fewer simultaneous wallet connections\n *\n * The stored data includes wallet IDs in format `platform:identifier`\n * (e.g., `polkadot:talisman`, `ethereum:io.metamask`).\n */\nexport const COOKIE_MAX_SIZE = 3 * 1024;\n\n/**\n * BroadcastChannel name for cross-tab cookie sync.\n */\nconst BROADCAST_CHANNEL_NAME = \"kheopskit-storage-sync\";\n\n/**\n * Singleton BroadcastChannel for cross-tab cookie sync.\n * Created once and shared across all cookieStorage instances.\n */\nlet sharedBroadcastChannel: BroadcastChannel | null = null;\n\nconst getBroadcastChannel = (): BroadcastChannel | null => {\n\tif (sharedBroadcastChannel) return sharedBroadcastChannel;\n\tif (typeof BroadcastChannel === \"undefined\") return null;\n\n\ttry {\n\t\tsharedBroadcastChannel = new BroadcastChannel(BROADCAST_CHANNEL_NAME);\n\t} catch {\n\t\t// BroadcastChannel not supported or failed\n\t}\n\treturn sharedBroadcastChannel;\n};\n\n/**\n * Check if the current connection is secure (HTTPS).\n * Must be called at runtime (inside methods) to work correctly after SSR hydration.\n */\nconst isSecureConnection = (): boolean =>\n\ttypeof window !== \"undefined\" && window.location.protocol === \"https:\";\n\n/**\n * A cookie-based storage implementation for SSR environments.\n * Reads cookies from an optional initial cookie string (for SSR hydration),\n * writes to document.cookie on the client.\n *\n * Features:\n * - Secure flag automatically added for HTTPS connections\n * - Cross-tab synchronization via BroadcastChannel API\n * - Size limit warning when data exceeds recommended limits\n *\n * @param initialCookies - Optional cookie string for server-side hydration\n */\nexport const cookieStorage = (initialCookies?: string): SyncableStorage => {\n\treturn {\n\t\tgetItem: (key: string) => {\n\t\t\t// On server, use initialCookies. On client, read from document.cookie\n\t\t\tconst cookieString =\n\t\t\t\ttypeof document !== \"undefined\" ? document.cookie : initialCookies;\n\t\t\treturn parseCookie(cookieString, key);\n\t\t},\n\t\tsetItem: (key: string, value: string) => {\n\t\t\tif (typeof document === \"undefined\") return;\n\n\t\t\t// Warn if value exceeds recommended size\n\t\t\tconst encodedValue = encodeURIComponent(value);\n\t\t\tif (encodedValue.length > COOKIE_MAX_SIZE) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[kheopskit] Cookie value for \"${key}\" exceeds recommended size limit (${encodedValue.length} > ${COOKIE_MAX_SIZE} bytes). ` +\n\t\t\t\t\t\t\"This may cause issues with cookie storage. Consider reducing the number of connected wallets.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Set cookie with 1 year expiry\n\t\t\tconst expires = new Date();\n\t\t\texpires.setFullYear(expires.getFullYear() + 1);\n\n\t\t\t// Build cookie string with security attributes\n\t\t\tlet cookieStr = `${key}=${encodedValue};expires=${expires.toUTCString()};path=/;SameSite=Lax`;\n\t\t\tif (isSecureConnection()) {\n\t\t\t\tcookieStr += \";Secure\";\n\t\t\t}\n\n\t\t\t// biome-ignore lint: necessary for cookie storage - direct cookie assignment is the standard API\n\t\t\tdocument.cookie = cookieStr;\n\n\t\t\t// Broadcast change to other tabs\n\t\t\tgetBroadcastChannel()?.postMessage({ type: \"set\", key, value });\n\t\t},\n\t\tremoveItem: (key: string) => {\n\t\t\tif (typeof document === \"undefined\") return;\n\n\t\t\t// Build delete cookie string\n\t\t\tlet cookieStr = `${key}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/;SameSite=Lax`;\n\t\t\tif (isSecureConnection()) {\n\t\t\t\tcookieStr += \";Secure\";\n\t\t\t}\n\n\t\t\t// biome-ignore lint: necessary for cookie storage - direct cookie assignment is the standard API\n\t\t\tdocument.cookie = cookieStr;\n\n\t\t\t// Broadcast change to other tabs\n\t\t\tgetBroadcastChannel()?.postMessage({ type: \"remove\", key });\n\t\t},\n\t\tsubscribe: (key: string, callback: (value: string | null) => void) => {\n\t\t\tconst channel = getBroadcastChannel();\n\t\t\tif (!channel) return () => {};\n\n\t\t\tconst handler = (event: MessageEvent) => {\n\t\t\t\tconst data = event.data as {\n\t\t\t\t\ttype: string;\n\t\t\t\t\tkey: string;\n\t\t\t\t\tvalue?: string;\n\t\t\t\t};\n\t\t\t\tif (data.key === key) {\n\t\t\t\t\tif (data.type === \"set\") {\n\t\t\t\t\t\tcallback(data.value ?? null);\n\t\t\t\t\t} else if (data.type === \"remove\") {\n\t\t\t\t\t\tcallback(null);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tchannel.addEventListener(\"message\", handler);\n\t\t\treturn () => {\n\t\t\t\tchannel.removeEventListener(\"message\", handler);\n\t\t\t};\n\t\t},\n\t};\n};\n\n/**\n * Cleanup the shared BroadcastChannel used for cross-tab cookie sync.\n * Call this when you're done using cookie storage (e.g., in tests or when unmounting).\n *\n * @remarks\n * In normal browser usage, you typically don't need to call this -\n * the channel will be cleaned up when the page is closed.\n * This is primarily useful for testing environments where multiple\n * test runs may accumulate channels.\n */\nexport const cleanupBroadcastChannel = (): void => {\n\tif (sharedBroadcastChannel) {\n\t\tsharedBroadcastChannel.close();\n\t\tsharedBroadcastChannel = null;\n\t}\n};\n","import { safeLocalStorage } from \"./storage\";\n\n/**\n * Storage key for the icon cache in localStorage.\n */\nconst ICON_CACHE_KEY = \"kheopskit-icons\";\n\n/**\n * Icon cache type: a map of wallet ID to icon data URI or URL.\n */\ntype IconCache = Record<string, string>;\n\n/**\n * In-memory cache to avoid repeated localStorage reads.\n */\nlet memoryCache: IconCache | null = null;\n\n/**\n * Loads the icon cache from localStorage.\n */\nconst loadCache = (): IconCache => {\n\tif (memoryCache !== null) return memoryCache;\n\n\ttry {\n\t\tconst stored = safeLocalStorage.getItem(ICON_CACHE_KEY);\n\t\tmemoryCache = stored ? (JSON.parse(stored) as IconCache) : {};\n\t} catch {\n\t\tmemoryCache = {};\n\t}\n\treturn memoryCache;\n};\n\n/**\n * Saves the icon cache to localStorage.\n */\nconst saveCache = (cache: IconCache): void => {\n\ttry {\n\t\tsafeLocalStorage.setItem(ICON_CACHE_KEY, JSON.stringify(cache));\n\t\tmemoryCache = cache;\n\t} catch {\n\t\t// localStorage may be full or unavailable\n\t}\n};\n\n/**\n * Gets a cached icon for a wallet.\n * @param walletId - The wallet ID (e.g., \"ethereum:io.talisman\")\n * @returns The cached icon data URI, or undefined if not cached\n */\nexport const getCachedIcon = (walletId: string): string | undefined => {\n\tconst cache = loadCache();\n\treturn cache[walletId] || undefined;\n};\n\n/**\n * Sets multiple cached icons at once.\n * More efficient than calling setCachedIcon multiple times.\n * @param icons - Map of wallet ID to icon\n */\nexport const setCachedIcons = (icons: Record<string, string>): void => {\n\tconst cache = loadCache();\n\tlet changed = false;\n\n\tfor (const [walletId, icon] of Object.entries(icons)) {\n\t\tif (icon && cache[walletId] !== icon) {\n\t\t\tcache[walletId] = icon;\n\t\t\tchanged = true;\n\t\t}\n\t}\n\n\tif (changed) {\n\t\tsaveCache(cache);\n\t}\n};\n"],"mappings":"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"}