@kheopskit/core 5.3.0 → 6.0.0-rc.1

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 +432 -0
  2. package/MIGRATING_TO_V6.md +840 -0
  3. package/README.md +629 -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 +187 -106
  39. package/dist/polkadot.js.map +1 -1
  40. package/dist/polkadot.mjs +180 -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-Yor672md.mjs +215 -0
  59. package/dist/types-Yor672md.mjs.map +1 -0
  60. package/dist/types-lkMXVJNG.d.mts +685 -0
  61. package/dist/types-lkMXVJNG.d.ts +685 -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 +1 @@
1
- {"version":3,"file":"index.mjs","names":["PLATFORM_ORDER"],"sources":["../src/api/appKit.ts","../src/api/config.ts","../src/utils/sortAccounts.ts","../src/utils/sortWallets.ts","../src/api/platform.ts","../src/api/hydration.ts","../src/utils/createHydrationBuffer.ts","../src/utils/logObservable.ts","../src/api/accounts.ts","../src/utils/createStore.ts","../src/api/compactStore.ts","../src/api/store.ts","../src/api/reconnectPolicy.ts","../src/api/wallets.ts","../src/api/kheopskit.ts"],"sourcesContent":["import {\n\tBehaviorSubject,\n\tdistinctUntilChanged,\n\tfrom,\n\tmap,\n\tObservable,\n\tof,\n\tshareReplay,\n\tswitchMap,\n\ttap,\n} from \"rxjs\";\nimport { clearCachedObservablesByPrefix } from \"../utils/getCachedObservable\";\nimport { WALLET_CONNECT_WALLET_ID } from \"../utils/WalletId\";\nimport type {\n\tAppKitInstance,\n\tKheopskitConfig,\n\tWalletConnectWallet,\n\tWalletPlatform,\n} from \"./types\";\n\n/**\n * Dynamically import @reown/appkit/core to avoid loading browser-only code\n * during SSR or in edge runtimes like Cloudflare Workers.\n * The AppKit library uses Lit for web components which requires document.\n */\nconst loadAppKit = async () => {\n\ttry {\n\t\tconst { createAppKit } = await import(\"@reown/appkit/core\");\n\t\treturn createAppKit;\n\t} catch (cause) {\n\t\tconsole.error(\n\t\t\t\"[kheopskit] WalletConnect is configured but @reown/appkit could not be loaded. \" +\n\t\t\t\t\"Install it with `pnpm add @reown/appkit` (or remove config.walletConnect). \" +\n\t\t\t\t\"WalletConnect wallets are disabled; injected wallets still work.\",\n\t\t\tcause,\n\t\t);\n\t\treturn null;\n\t}\n};\n\nconst WALLET_CONNECT_ICON =\n\t\"data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjQwMCIgdmlld0JveD0iMCAwIDQwMCA0MDAiIHdpZHRoPSI0MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxjbGlwUGF0aCBpZD0iYSI+PHBhdGggZD0ibTAgMGg0MDB2NDAwaC00MDB6Ii8+PC9jbGlwUGF0aD48ZyBjbGlwLXBhdGg9InVybCgjYSkiPjxjaXJjbGUgY3g9IjIwMCIgY3k9IjIwMCIgZmlsbD0iIzMzOTZmZiIgcj0iMTk5LjUiIHN0cm9rZT0iIzY2YjFmZiIvPjxwYXRoIGQ9Im0xMjIuNTE5IDE0OC45NjVjNDIuNzkxLTQxLjcyOSAxMTIuMTcxLTQxLjcyOSAxNTQuOTYyIDBsNS4xNSA1LjAyMmMyLjE0IDIuMDg2IDIuMTQgNS40NjkgMCA3LjU1NWwtMTcuNjE3IDE3LjE4Yy0xLjA3IDEuMDQzLTIuODA0IDEuMDQzLTMuODc0IDBsLTcuMDg3LTYuOTExYy0yOS44NTMtMjkuMTExLTc4LjI1My0yOS4xMTEtMTA4LjEwNiAwbC03LjU5IDcuNDAxYy0xLjA3IDEuMDQzLTIuODA0IDEuMDQzLTMuODc0IDBsLTE3LjYxNy0xNy4xOGMtMi4xNC0yLjA4Ni0yLjE0LTUuNDY5IDAtNy41NTV6bTE5MS4zOTcgMzUuNTI5IDE1LjY3OSAxNS4yOWMyLjE0IDIuMDg2IDIuMTQgNS40NjkgMCA3LjU1NWwtNzAuNyA2OC45NDRjLTIuMTM5IDIuMDg3LTUuNjA4IDIuMDg3LTcuNzQ4IDBsLTUwLjE3OC00OC45MzFjLS41MzUtLjUyMi0xLjQwMi0uNTIyLTEuOTM3IDBsLTUwLjE3OCA0OC45MzFjLTIuMTM5IDIuMDg3LTUuNjA4IDIuMDg3LTcuNzQ4IDBsLTcwLjcwMTUtNjguOTQ1Yy0yLjEzOTYtMi4wODYtMi4xMzk2LTUuNDY5IDAtNy41NTVsMTUuNjc5NS0xNS4yOWMyLjEzOTYtMi4wODYgNS42MDg1LTIuMDg2IDcuNzQ4MSAwbDUwLjE3ODkgNDguOTMyYy41MzUuNTIyIDEuNDAyLjUyMiAxLjkzNyAwbDUwLjE3Ny00OC45MzJjMi4xMzktMi4wODcgNS42MDgtMi4wODcgNy43NDggMGw1MC4xNzkgNDguOTMyYy41MzUuNTIyIDEuNDAyLjUyMiAxLjkzNyAwbDUwLjE3OS00OC45MzFjMi4xMzktMi4wODcgNS42MDgtMi4wODcgNy43NDggMHoiIGZpbGw9IiNmZmYiLz48L2c+PC9zdmc+\";\n\n// Once it exists, the appKit object should never be recreated. Anchored on\n// globalThis so it stays a single instance even if this module is duplicated\n// across bundle chunks (e.g. CJS subpath entries).\nconst APPKIT_SYMBOL = Symbol.for(\"kheopskit.cachedAppKit\");\n// The projectId AppKit was first initialised with. AppKit is a process-wide\n// singleton, so a later call with a different WalletConnect config is silently\n// ignored — we keep this to warn loudly instead of letting it pass unnoticed.\nconst APPKIT_PROJECT_ID_SYMBOL = Symbol.for(\"kheopskit.cachedAppKitProjectId\");\ntype AppKitGlobal = Record<\n\tsymbol,\n\tObservable<WalletConnectWallet | null> | string | undefined\n>;\nconst getCachedAppKit = ():\n\t| Observable<WalletConnectWallet | null>\n\t| undefined =>\n\t(globalThis as unknown as AppKitGlobal)[APPKIT_SYMBOL] as\n\t\t| Observable<WalletConnectWallet | null>\n\t\t| undefined;\nconst getCachedAppKitProjectId = (): string | undefined =>\n\t(globalThis as unknown as AppKitGlobal)[APPKIT_PROJECT_ID_SYMBOL] as\n\t\t| string\n\t\t| undefined;\nconst setCachedAppKit = (\n\tvalue: Observable<WalletConnectWallet | null> | undefined,\n\tprojectId?: string,\n): void => {\n\t(globalThis as unknown as AppKitGlobal)[APPKIT_SYMBOL] = value;\n\t(globalThis as unknown as AppKitGlobal)[APPKIT_PROJECT_ID_SYMBOL] = projectId;\n};\n\n/**\n * Clears the cached AppKit observable.\n * Use when configuration changes or for testing purposes.\n * Note: This does NOT destroy the appKit instance created by Reown.\n */\nexport const resetAppKitCache = (): void => {\n\tsetCachedAppKit(undefined);\n};\n\n/**\n * Drops a WalletConnect namespace's cached account observables. Called when a\n * namespace transitions to disconnected — including external disconnects (from\n * the wallet app), which flip status via `subscribeProviders` without ever\n * calling `disconnect()` — so a later reconnect rebuilds the account observables\n * against the fresh session instead of a stale closure.\n *\n * Keys are `accounts:<walletId>:...`; the trailing colon scopes the prefix to\n * this wallet and avoids matching a sibling whose id is a string prefix.\n */\nconst dropAccountsCache = (platform: WalletPlatform): void => {\n\tclearCachedObservablesByPrefix(\n\t\t`accounts:${WALLET_CONNECT_WALLET_ID}:${platform}:`,\n\t);\n};\n\n/**\n * The single, platform-less WalletConnect connector for the given config — or\n * `null` when WalletConnect isn't configured, on the server, or when\n * `@reown/appkit` isn't installed.\n *\n * @remarks\n * The AppKit instance is a process-wide singleton (Reown AppKit itself cannot\n * be instantiated twice). The **first** call with a `walletConnect` config wins;\n * later calls with a *different* `walletConnect` config reuse that first\n * instance. Call {@link resetAppKitCache} before re-initialising if the\n * WalletConnect config must change.\n *\n * One WalletConnect session is shared across every namespace, and a namespace\n * can only be established during the initial pairing — it can't be added to a\n * live session afterwards. So this exposes ONE connector (not one per platform):\n * `connect()` opens the modal; the wallet approves whichever namespaces it\n * supports in that single pairing, and `platforms` reflects what the live\n * session carries. Per-namespace accounts are derived by each platform plugin.\n */\nexport const getWalletConnectWallet$ = (\n\tconfig: KheopskitConfig,\n): Observable<WalletConnectWallet | null> => {\n\tif (!config.walletConnect) return of(null);\n\n\t// SSR guard - don't try to load AppKit on the server\n\tif (typeof window === \"undefined\") return of(null);\n\n\tconst walletConnect = config.walletConnect;\n\n\tconst cachedProjectId = getCachedAppKitProjectId();\n\tif (\n\t\tcachedProjectId !== undefined &&\n\t\tcachedProjectId !== walletConnect.projectId\n\t) {\n\t\tconsole.warn(\n\t\t\t\"[kheopskit] WalletConnect is already initialised with projectId %s; \" +\n\t\t\t\t\"AppKit is a process-wide singleton, so the first configuration wins and \" +\n\t\t\t\t\"projectId %s is ignored. Call resetAppKitCache() before re-initialising \" +\n\t\t\t\t\"if the WalletConnect config must change.\",\n\t\t\tcachedProjectId,\n\t\t\twalletConnect.projectId,\n\t\t);\n\t}\n\n\tlet cachedAppKit = getCachedAppKit();\n\tif (!cachedAppKit) {\n\t\t// Dynamic import avoids loading @reown/appkit at module-eval time (SSR /\n\t\t// edge runtimes like Cloudflare Workers).\n\t\tcachedAppKit = from(loadAppKit()).pipe(\n\t\t\tswitchMap((createAppKit) => {\n\t\t\t\t// @reown/appkit missing (optional peer dep) — degrade gracefully.\n\t\t\t\tif (!createAppKit) return of<WalletConnectWallet | null>(null);\n\t\t\t\treturn new Observable<WalletConnectWallet | null>((subscriber) => {\n\t\t\t\t\tconst appKit = createAppKit({\n\t\t\t\t\t\tprojectId: walletConnect.projectId,\n\t\t\t\t\t\tmetadata: walletConnect.metadata,\n\t\t\t\t\t\t// Loosely typed in WalletConnectConfig to keep @reown/appkit's\n\t\t\t\t\t\t// types out of core; forwarded to AppKit verbatim.\n\t\t\t\t\t\tnetworks: walletConnect.networks as never,\n\t\t\t\t\t\tthemeMode: walletConnect.themeMode,\n\t\t\t\t\t\tthemeVariables: walletConnect.themeVariables as never,\n\t\t\t\t\t\tuniversalProviderConfigOverride: {\n\t\t\t\t\t\t\tmethods: {\n\t\t\t\t\t\t\t\tpolkadot: [\"polkadot_signTransaction\", \"polkadot_signMessage\"],\n\t\t\t\t\t\t\t\tsolana: [\n\t\t\t\t\t\t\t\t\t\"solana_signTransaction\",\n\t\t\t\t\t\t\t\t\t\"solana_signMessage\",\n\t\t\t\t\t\t\t\t\t\"solana_signAndSendTransaction\",\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tallWallets: \"HIDE\",\n\t\t\t\t\t\tdebug: config.debug,\n\t\t\t\t\t\tallowUnsupportedChain: true,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Exposed on the wallet as the (decoupled) AppKitInstance escape hatch.\n\t\t\t\t\tconst appKitInstance = appKit as unknown as AppKitInstance;\n\n\t\t\t\t\tconst status$ = new BehaviorSubject({\n\t\t\t\t\t\tisPolkadotConnected: false,\n\t\t\t\t\t\tisEthereumConnected: false,\n\t\t\t\t\t\tisSolanaConnected: false,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst unsubProviders = appKit.subscribeProviders((providers) => {\n\t\t\t\t\t\tstatus$.next({\n\t\t\t\t\t\t\tisPolkadotConnected: !!providers.polkadot,\n\t\t\t\t\t\t\tisEthereumConnected: !!providers.eip155,\n\t\t\t\t\t\t\tisSolanaConnected: !!providers.solana,\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tconst namespaceOf: Record<WalletPlatform, string> = {\n\t\t\t\t\t\tpolkadot: \"polkadot\",\n\t\t\t\t\t\tethereum: \"eip155\",\n\t\t\t\t\t\tsolana: \"solana\",\n\t\t\t\t\t};\n\t\t\t\t\tconst allPlatforms: WalletPlatform[] = [\n\t\t\t\t\t\t\"polkadot\",\n\t\t\t\t\t\t\"ethereum\",\n\t\t\t\t\t\t\"solana\",\n\t\t\t\t\t];\n\t\t\t\t\tconst enabledPlatforms = allPlatforms.filter((p) =>\n\t\t\t\t\t\t(appKit.chainNamespaces as string[]).includes(namespaceOf[p]),\n\t\t\t\t\t);\n\n\t\t\t\t\tlet prevConnected = {\n\t\t\t\t\t\tpolkadot: false,\n\t\t\t\t\t\tethereum: false,\n\t\t\t\t\t\tsolana: false,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst sub = status$\n\t\t\t\t\t\t.pipe(\n\t\t\t\t\t\t\tmap((s) => ({\n\t\t\t\t\t\t\t\tpolkadot: s.isPolkadotConnected,\n\t\t\t\t\t\t\t\tethereum: s.isEthereumConnected,\n\t\t\t\t\t\t\t\tsolana: s.isSolanaConnected,\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\tdistinctUntilChanged(\n\t\t\t\t\t\t\t\t(a, b) =>\n\t\t\t\t\t\t\t\t\ta.polkadot === b.polkadot &&\n\t\t\t\t\t\t\t\t\ta.ethereum === b.ethereum &&\n\t\t\t\t\t\t\t\t\ta.solana === b.solana,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\ttap((connected) => {\n\t\t\t\t\t\t\t\t// Drop caches for namespaces that just went disconnected.\n\t\t\t\t\t\t\t\tfor (const platform of allPlatforms)\n\t\t\t\t\t\t\t\t\tif (prevConnected[platform] && !connected[platform])\n\t\t\t\t\t\t\t\t\t\tdropAccountsCache(platform);\n\t\t\t\t\t\t\t\tprevConnected = connected;\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tmap((connected): WalletConnectWallet => {\n\t\t\t\t\t\t\t\tconst platforms = enabledPlatforms.filter((p) => connected[p]);\n\t\t\t\t\t\t\t\tconst isConnected = platforms.length > 0;\n\t\t\t\t\t\t\t\tconst walletInfo = appKit.getWalletInfo();\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tid: WALLET_CONNECT_WALLET_ID,\n\t\t\t\t\t\t\t\t\ttype: \"walletconnect\",\n\t\t\t\t\t\t\t\t\tplatforms,\n\t\t\t\t\t\t\t\t\tappKit: appKitInstance,\n\t\t\t\t\t\t\t\t\tname: walletInfo?.name ?? \"WalletConnect\",\n\t\t\t\t\t\t\t\t\ticon: walletInfo?.icon ?? WALLET_CONNECT_ICON,\n\t\t\t\t\t\t\t\t\t// One shared session: connecting opens the modal; the wallet\n\t\t\t\t\t\t\t\t\t// approves namespaces in that single pairing. Disconnect is\n\t\t\t\t\t\t\t\t\t// session-wide; re-pair to change the approved set.\n\t\t\t\t\t\t\t\t\tconnect: async () => {\n\t\t\t\t\t\t\t\t\t\tif (!isConnected) await appKit.open();\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tdisconnect: async () => {\n\t\t\t\t\t\t\t\t\t\tif (isConnected) await appKit.disconnect();\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tisConnected,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.subscribe(subscriber);\n\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tsub.unsubscribe();\n\t\t\t\t\t\tunsubProviders();\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}),\n\t\t\t// refCount:false keeps the AppKit instance alive for the process lifetime\n\t\t\t// once created: createAppKit runs at most once (Reown AppKit cannot be\n\t\t\t// instantiated twice). With refCount:true the producer would re-run\n\t\t\t// createAppKit whenever every subscriber drained and a new one\n\t\t\t// re-subscribed — e.g. a React unmount/remount or StrictMode's\n\t\t\t// mount→unmount→remount — throwing on the duplicate Lit web components and\n\t\t\t// WalletConnect modal singleton. The replayed connector value also keeps\n\t\t\t// the wallet list stable across such teardown/rebuild cycles.\n\t\t\tshareReplay({ refCount: false, bufferSize: 1 }),\n\t\t);\n\t\tsetCachedAppKit(cachedAppKit, walletConnect.projectId);\n\t}\n\n\treturn cachedAppKit;\n};\n","import type { KheopskitConfig, KheopskitPlatform } from \"./types\";\n\n/**\n * Default storage key for persisting wallet connection state.\n * Can be overridden via config.storageKey to avoid conflicts\n * when running multiple dapps on the same domain.\n */\nexport const DEFAULT_STORAGE_KEY = \"kheopskit\";\n\nconst DEFAULTS = {\n\tautoReconnect: true,\n\tdebug: false,\n\tstorageKey: DEFAULT_STORAGE_KEY,\n\thydrationGracePeriod: 500,\n} satisfies Omit<KheopskitConfig, \"platforms\" | \"walletConnect\">;\n\nexport const resolveConfig = <\n\tconst P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>(\n\tconfig?: Partial<KheopskitConfig<P>>,\n): KheopskitConfig<P> => {\n\tconst platforms = (config?.platforms ?? []) as P;\n\n\t// Guard the v4 breaking change: platforms are plugin instances, not strings.\n\t// Catches JS callers (no tsc) and gives agents a fix that names the doc.\n\tconst invalidPlatforms = (platforms as readonly unknown[]).filter(\n\t\t(p) =>\n\t\t\ttypeof p !== \"object\" ||\n\t\t\tp === null ||\n\t\t\ttypeof (p as { getWallets$?: unknown }).getWallets$ !== \"function\",\n\t);\n\tif (invalidPlatforms.length > 0) {\n\t\tthrow new Error(\n\t\t\t\"[kheopskit] config.platforms must contain plugin instances created by the \" +\n\t\t\t\t\"per-platform factories (e.g. platforms: [polkadot(), ethereum(), solana()] \" +\n\t\t\t\t'imported from \"@kheopskit/core/<platform>\"). ' +\n\t\t\t\t`Invalid entries: ${JSON.stringify(invalidPlatforms)}. ` +\n\t\t\t\t'String platform names like \"polkadot\" were removed in v4 — see MIGRATING_TO_V4.md.',\n\t\t);\n\t}\n\n\tif (platforms.length === 0) {\n\t\tconsole.warn(\n\t\t\t\"[kheopskit] No platforms configured; wallets and accounts will be empty. \" +\n\t\t\t\t'Pass e.g. platforms: [polkadot()] from \"@kheopskit/core/polkadot\".',\n\t\t);\n\t}\n\n\treturn Object.assign({}, DEFAULTS, config, { platforms });\n};\n","import type { BaseWalletAccount, WalletPlatform } from \"../api/types\";\n\nconst PLATFORM_ORDER: Record<WalletPlatform, number> = {\n\tpolkadot: 0,\n\tethereum: 1,\n\tsolana: 2,\n};\n\n// Group accounts by wallet, surfacing Talisman first (case-insensitive).\nconst byWalletName = (a1: BaseWalletAccount, a2: BaseWalletAccount) => {\n\tif (a1.walletName.toLowerCase() === \"talisman\") return -1;\n\tif (a2.walletName.toLowerCase() === \"talisman\") return 1;\n\treturn a1.walletName.localeCompare(a2.walletName);\n};\n\nexport const sortAccounts = (a1: BaseWalletAccount, a2: BaseWalletAccount) => {\n\t// Sort by platform first: polkadot, then ethereum, then solana\n\tif (a1.platform !== a2.platform)\n\t\treturn PLATFORM_ORDER[a1.platform] - PLATFORM_ORDER[a2.platform];\n\n\t// Then group by wallet name\n\tif (a1.walletName !== a2.walletName) return byWalletName(a1, a2);\n\n\t// Polkadot accounts expose a friendly name; fall back to address\n\tif (a1.platform === \"polkadot\" && a2.platform === \"polkadot\")\n\t\treturn a1.name !== a2.name\n\t\t\t? (a1.name ?? \"\").localeCompare(a2.name ?? \"\")\n\t\t\t: a1.address.localeCompare(a2.address);\n\n\t// Ethereum and Solana accounts disambiguate by id\n\treturn a1.id.localeCompare(a2.id);\n};\n","import {\n\ttype BaseWallet,\n\tisWalletConnectWallet,\n\ttype WalletConnectWallet,\n\ttype WalletPlatform,\n} from \"../api/types\";\n\nconst PLATFORM_ORDER: Record<WalletPlatform, number> = {\n\tpolkadot: 0,\n\tethereum: 1,\n\tsolana: 2,\n};\n\n// The platform-less WalletConnect connector sorts after all platform wallets.\nconst orderOf = (wallet: BaseWallet | WalletConnectWallet) =>\n\tisWalletConnectWallet(wallet) ? 3 : PLATFORM_ORDER[wallet.platform];\n\nexport const sortWallets = (\n\tw1: BaseWallet | WalletConnectWallet,\n\tw2: BaseWallet | WalletConnectWallet,\n) => {\n\t// Sort by platform first: polkadot, then ethereum, then solana, then WC\n\tconst o1 = orderOf(w1);\n\tconst o2 = orderOf(w2);\n\tif (o1 !== o2) return o1 - o2;\n\n\t// Sort by name, but Talisman first\n\tif (w1.name.toLowerCase() === \"talisman\") return -1;\n\tif (w2.name.toLowerCase() === \"talisman\") return 1;\n\n\treturn w1.name.localeCompare(w2.name);\n};\n","import type { CachedAccount, KheopskitPlatform } from \"./types\";\n\n/**\n * Whether a cached account should survive SSR hydration, per its platform\n * plugin's `acceptsCachedAccount` hook. Plugins without the hook (and platforms\n * with no enabled plugin) accept all — matching the pre-plugin behavior where\n * only Polkadot accounts were filtered (by key type).\n */\nexport const acceptsCachedAccount = (\n\tcached: CachedAccount,\n\tplatforms: readonly KheopskitPlatform[],\n): boolean => {\n\tconst plugin = platforms.find((p) => p.platform === cached.platform);\n\treturn plugin?.acceptsCachedAccount?.(cached) ?? true;\n};\n","import { hydrateAccount, hydrateWallet } from \"../utils/hydrateState\";\nimport { getCachedIcon } from \"../utils/iconCache\";\nimport { sortAccounts } from \"../utils/sortAccounts\";\nimport { sortWallets } from \"../utils/sortWallets\";\nimport { acceptsCachedAccount } from \"./platform\";\nimport type { KheopskitStore } from \"./store\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tKheopskitPlatform,\n\tWalletConnectWallet,\n} from \"./types\";\n\n/** Result of {@link getHydratedSnapshot}: placeholder wallets and accounts built from the cache. */\nexport type HydratedSnapshot = {\n\twallets: (BaseWallet | WalletConnectWallet)[];\n\taccounts: BaseWalletAccount[];\n};\n\nexport type GetHydratedSnapshotOptions = {\n\t/**\n\t * Enrich wallets that have no icon from the localStorage icon cache.\n\t *\n\t * Must stay `false` for any snapshot that has to match server-rendered markup\n\t * (React's `getServerSnapshot` runs on the client during hydration, where the\n\t * icon cache is populated — enriching there would diverge from the server,\n\t * which always sees an empty cache).\n\t */\n\ticons?: boolean;\n};\n\n/**\n * Builds the cached-state snapshot every consumer must agree on: read the\n * store's cached state, hydrate wallets/accounts into placeholders, filter\n * accounts through each platform plugin's `acceptsCachedAccount` hook, and sort\n * with the same comparators the live pipeline uses.\n *\n * This is the single implementation behind the observable's initial seed and\n * both React snapshot sources (`serverValue`/`initialValue`). They must produce\n * the same shape in the same order or the UI flickers/reorders on reload — by\n * sharing this helper, that agreement holds by construction.\n */\nexport const getHydratedSnapshot = (\n\tstore: KheopskitStore,\n\tplatforms: readonly KheopskitPlatform[],\n\toptions: GetHydratedSnapshotOptions = {},\n): HydratedSnapshot => {\n\tconst cached = store.getCachedState();\n\n\tconst wallets = cached.wallets\n\t\t.map((cachedWallet) => {\n\t\t\tconst wallet = hydrateWallet(cachedWallet);\n\t\t\t// Some wallets (e.g. Ethereum) have no SSR-safe icon; optionally fill it\n\t\t\t// from the localStorage cache.\n\t\t\tif (!options.icons || wallet.icon) return wallet;\n\t\t\tconst icon = getCachedIcon(wallet.id);\n\t\t\treturn icon ? { ...wallet, icon } : wallet;\n\t\t})\n\t\t.sort(sortWallets);\n\n\tconst accounts = cached.accounts\n\t\t.filter((account) => acceptsCachedAccount(account, platforms))\n\t\t.map(hydrateAccount)\n\t\t.sort(sortAccounts);\n\n\treturn { wallets, accounts };\n};\n","import {\n\tBehaviorSubject,\n\tcombineLatest,\n\tfilter,\n\tmap,\n\tObservable,\n\tSubscription,\n\tshareReplay,\n\tstartWith,\n\ttake,\n\ttimer,\n} from \"rxjs\";\n\ntype HydrationBufferResult<T> = {\n\titems: T[];\n\tisHydrating: boolean;\n};\n\n/**\n * Core hydration buffer logic shared between wallets and accounts.\n *\n * During the grace period:\n * - Emits cached items immediately (before any live emissions)\n * - As live items arrive, merges them using the provided merge function\n *\n * After the grace period (and convergence, if provided):\n * - Only live items are returned\n * - isHydrating becomes false\n *\n * If an `isConverged` function is provided, hydration ends only when BOTH\n * the grace period has elapsed AND the live items have converged with cached\n * items (e.g., all previously-connected wallets have reconnected).\n * A max timeout (6x grace period) prevents infinite hydration.\n *\n * @param cachedItems - Initial cached items from storage\n * @param liveItems$ - Observable of live items as they become available\n * @param gracePeriodMs - Time in ms to wait before syncing to live state\n * @param mergeFn - Function to merge live and cached items during hydration\n * @param isConverged - Optional function to check if live items have caught up to cached items\n */\nconst createBufferCore = <T>(\n\tcachedItems: T[],\n\tliveItems$: Observable<T[]>,\n\tgracePeriodMs: number,\n\tmergeFn: (liveItems: T[], cachedItems: T[]) => T[],\n\tisConverged?: (liveItems: T[], cachedItems: T[]) => boolean,\n): Observable<HydrationBufferResult<T>> => {\n\t// If no grace period or no cached items, just pass through live items\n\tif (gracePeriodMs <= 0 || cachedItems.length === 0) {\n\t\treturn liveItems$.pipe(map((items) => ({ items, isHydrating: false })));\n\t}\n\n\t// Wrap in an Observable to properly manage all subscriptions\n\treturn new Observable<HydrationBufferResult<T>>((subscriber) => {\n\t\tconst subscriptions = new Subscription();\n\n\t\t// Track whether we're still in the hydration grace period\n\t\t// Using BehaviorSubject to keep a stateful value that doesn't complete\n\t\tconst isHydrating$ = new BehaviorSubject(true);\n\n\t\t// Use startWith to emit cached items immediately before any live emissions\n\t\tconst liveWithInitial$ = liveItems$.pipe(startWith([] as T[]));\n\n\t\tif (isConverged) {\n\t\t\t// With convergence check: hydration ends when timer fires AND live state has caught up\n\t\t\tconst timerFired$ = timer(gracePeriodMs).pipe(\n\t\t\t\tmap(() => true),\n\t\t\t\tstartWith(false),\n\t\t\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t\t);\n\n\t\t\t// End hydration when timer has fired AND convergence is met\n\t\t\tsubscriptions.add(\n\t\t\t\tcombineLatest([liveWithInitial$, timerFired$])\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\tfilter(([, timerFired]) => timerFired),\n\t\t\t\t\t\tfilter(([liveItems]) => isConverged(liveItems, cachedItems)),\n\t\t\t\t\t\ttake(1),\n\t\t\t\t\t)\n\t\t\t\t\t.subscribe(() => {\n\t\t\t\t\t\tisHydrating$.next(false);\n\t\t\t\t\t}),\n\t\t\t);\n\n\t\t\t// Max timeout (6x grace period) to prevent infinite hydration\n\t\t\t// e.g., if auto-reconnect fails, we still end hydration\n\t\t\tsubscriptions.add(\n\t\t\t\ttimer(gracePeriodMs * 6).subscribe(() => {\n\t\t\t\t\tif (isHydrating$.value) {\n\t\t\t\t\t\tisHydrating$.next(false);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\t// Without convergence check: end hydration on timer only\n\t\t\tsubscriptions.add(\n\t\t\t\ttimer(gracePeriodMs).subscribe(() => {\n\t\t\t\t\tisHydrating$.next(false);\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tsubscriptions.add(\n\t\t\tcombineLatest([liveWithInitial$, isHydrating$])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([liveItems, isHydrating]) => {\n\t\t\t\t\t\tif (!isHydrating) {\n\t\t\t\t\t\t\t// Hydration complete - return only live items\n\t\t\t\t\t\t\treturn { items: liveItems, isHydrating: false };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems: mergeFn(liveItems, cachedItems),\n\t\t\t\t\t\t\tisHydrating: true,\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\t\t);\n\n\t\treturn () => {\n\t\t\tsubscriptions.unsubscribe();\n\t\t\tisHydrating$.complete();\n\t\t};\n\t});\n};\n\n/**\n * Creates a hydration buffer that merges cached items with live items.\n *\n * During hydration, cached items take precedence over live items with the same key.\n * This preserves the cached connected state (e.g., isConnected: true) while\n * auto-reconnect is still in progress. New live items not in the cache are added.\n *\n * @param cachedItems - Initial cached items from storage\n * @param liveItems$ - Observable of live items as they become available\n * @param gracePeriodMs - Time in ms to wait before syncing to live state\n * @param getKey - Function to extract a unique key from an item\n * @param isConverged - Optional function to check if live items have caught up to cached items\n * @param mergeItem - Optional function to merge a live item with its cached counterpart\n * @param transformCachedOnly - Optional function to transform cached items not yet in the live stream\n */\nexport const createHydrationBuffer = <T>(\n\tcachedItems: T[],\n\tliveItems$: Observable<T[]>,\n\tgracePeriodMs: number,\n\tgetKey: (item: T) => string,\n\tisConverged?: (liveItems: T[], cachedItems: T[]) => boolean,\n\tmergeItem?: (liveItem: T, cachedItem: T) => T,\n\ttransformCachedOnly?: (cachedItem: T) => T,\n): Observable<HydrationBufferResult<T>> => {\n\treturn createBufferCore(\n\t\tcachedItems,\n\t\tliveItems$,\n\t\tgracePeriodMs,\n\t\t(liveItems, cached) => {\n\t\t\tconst cachedByKey = new Map(cached.map((item) => [getKey(item), item]));\n\t\t\tconst liveKeys = new Set(liveItems.map(getKey));\n\n\t\t\t// For items in both live and cached, prefer cached (preserves connected state)\n\t\t\t// but allow mergeItem to customize how they're combined\n\t\t\t// For items only in live (newly discovered), use the live version\n\t\t\tconst mergedItems: T[] = liveItems.map((liveItem) => {\n\t\t\t\tconst key = getKey(liveItem);\n\t\t\t\tconst cachedItem = cachedByKey.get(key);\n\t\t\t\tif (!cachedItem) return liveItem;\n\t\t\t\treturn mergeItem ? mergeItem(liveItem, cachedItem) : cachedItem;\n\t\t\t});\n\n\t\t\t// Add cached items not yet in the live stream (e.g., extensions not yet detected)\n\t\t\tfor (const cachedItem of cached) {\n\t\t\t\tif (!liveKeys.has(getKey(cachedItem))) {\n\t\t\t\t\tconst transformed = transformCachedOnly\n\t\t\t\t\t\t? transformCachedOnly(cachedItem)\n\t\t\t\t\t\t: cachedItem;\n\t\t\t\t\tmergedItems.push(transformed);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mergedItems;\n\t\t},\n\t\tisConverged,\n\t);\n};\n\n/**\n * Creates a hydration buffer specifically for accounts, which need special handling.\n *\n * Accounts are grouped by wallet - when a wallet provides its account list,\n * we replace all cached accounts for that wallet with the live ones.\n * Cached accounts for wallets that haven't provided accounts yet are preserved.\n *\n * @param cachedAccounts - Initial cached accounts from storage\n * @param liveAccounts$ - Observable of live accounts as they become available\n * @param gracePeriodMs - Time in ms to wait before syncing to live state\n * @param getWalletId - Function to extract the wallet ID from an account\n * @param isConverged - Optional function to check if live accounts have caught up to cached accounts\n */\nexport const createAccountHydrationBuffer = <T>(\n\tcachedAccounts: T[],\n\tliveAccounts$: Observable<T[]>,\n\tgracePeriodMs: number,\n\tgetWalletId: (account: T) => string,\n\tisConverged?: (liveAccounts: T[], cachedAccounts: T[]) => boolean,\n): Observable<HydrationBufferResult<T>> => {\n\treturn createBufferCore(\n\t\tcachedAccounts,\n\t\tliveAccounts$,\n\t\tgracePeriodMs,\n\t\t(liveAccounts, cached) => {\n\t\t\tconst walletsWithLiveAccounts = new Set(liveAccounts.map(getWalletId));\n\t\t\tconst mergedAccounts: T[] = [...liveAccounts];\n\n\t\t\tfor (const cachedAccount of cached) {\n\t\t\t\tif (!walletsWithLiveAccounts.has(getWalletId(cachedAccount))) {\n\t\t\t\t\tmergedAccounts.push(cachedAccount);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mergedAccounts;\n\t\t},\n\t\tisConverged,\n\t);\n};\n","import { type MonoTypeOperatorFunction, tap } from \"rxjs\";\n\ntype Opts = {\n\tprintValue?: boolean;\n\tenabled?: boolean;\n};\n\nexport const logObservable = <T>(\n\tlabel: string,\n\topts?: Opts,\n): MonoTypeOperatorFunction<T> =>\n\ttap((value) => {\n\t\tconst { printValue = false, enabled = true } = opts || {};\n\n\t\tif (!label || !enabled) return;\n\n\t\tconst text = `[kheopskit] observable ${label} emit`;\n\n\t\tif (printValue) console.debug(text, value);\n\t\telse console.debug(text);\n\t});\n","import { combineLatest, map, Observable, of, shareReplay } from \"rxjs\";\nimport { sortAccounts } from \"../utils/sortAccounts\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tKheopskitConfig,\n\tWalletConnectWallet,\n} from \"./types\";\nimport { isWalletConnectWallet } from \"./types\";\n\nexport const getAccounts$ = (\n\tconfig: KheopskitConfig,\n\twallets: Observable<(BaseWallet | WalletConnectWallet)[]>,\n) => {\n\treturn new Observable<BaseWalletAccount[]>((subscriber) => {\n\t\t// Each plugin gets its own platform's (injected) wallets plus the shared\n\t\t// WalletConnect connector; it derives WC accounts only for the namespaces\n\t\t// the session carries.\n\t\tconst sources = config.platforms.map((plugin) =>\n\t\t\tplugin.getAccounts$(\n\t\t\t\twallets.pipe(\n\t\t\t\t\tmap((ws) =>\n\t\t\t\t\t\tws.filter(\n\t\t\t\t\t\t\t(w) => isWalletConnectWallet(w) || w.platform === plugin.platform,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t\tconst accounts$ = sources.length\n\t\t\t? combineLatest(sources).pipe(\n\t\t\t\t\tmap((accounts) => accounts.flat().sort(sortAccounts)),\n\t\t\t\t)\n\t\t\t: of<BaseWalletAccount[]>([]);\n\n\t\tconst sub = accounts$.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n};\n","import { BehaviorSubject } from \"rxjs\";\nimport { type SyncableStorage, safeLocalStorage } from \"./storage\";\n\nexport const createStore = <T>(\n\tkey: string,\n\tdefaultValue: T,\n\tstorage: SyncableStorage = safeLocalStorage,\n) => {\n\tconst subject = new BehaviorSubject<T>(\n\t\tgetStoredData(key, defaultValue, storage),\n\t);\n\n\t// Cross-tab sync via storage.subscribe (uses storage event for localStorage, BroadcastChannel for cookies)\n\t// Only subscribe if window is available (client-side) and storage supports it\n\tlet unsubscribeStorage: (() => void) | undefined;\n\tif (typeof window !== \"undefined\" && storage.subscribe) {\n\t\tunsubscribeStorage = storage.subscribe(key, (newValue) => {\n\t\t\tsubject.next(parseData(newValue, defaultValue));\n\t\t});\n\t}\n\n\tconst update = (val: T) => {\n\t\tsetStoredData(key, val, storage);\n\t\tsubject.next(val);\n\t};\n\n\treturn {\n\t\tobservable: subject.asObservable(),\n\t\tset: (val: T) => update(val),\n\t\tmutate: (transform: (prev: T) => T) =>\n\t\t\tupdate(transform(subject.getValue())),\n\t\tget: () => structuredClone(subject.getValue()),\n\t\t/**\n\t\t * Cleanup subscriptions. Call this when the store is no longer needed.\n\t\t */\n\t\tdestroy: () => {\n\t\t\tunsubscribeStorage?.();\n\t\t\tsubject.complete();\n\t\t},\n\t};\n};\n\nconst parseData = <T>(str: string | null, defaultValue: T): T => {\n\ttry {\n\t\tif (str) return JSON.parse(str);\n\t} catch {\n\t\t// invalid data\n\t}\n\treturn defaultValue;\n};\n\nconst getStoredData = <T>(\n\tkey: string,\n\tdefaultValue: T,\n\tstorage: SyncableStorage,\n): T => {\n\tconst str = storage.getItem(key);\n\treturn parseData(str, defaultValue);\n};\n\nconst setStoredData = <T>(key: string, val: T, storage: SyncableStorage) => {\n\tconst str = JSON.stringify(val);\n\tstorage.setItem(key, str);\n};\n","import { isWalletPlatform } from \"../utils/isWalletPlatform\";\nimport { cookieStorage } from \"../utils/storage\";\nimport { getWalletAccountId } from \"../utils/WalletAccountId\";\nimport {\n\tisValidWalletId,\n\tparseWalletId,\n\tWALLET_CONNECT_WALLET_ID,\n\ttype WalletId,\n} from \"../utils/WalletId\";\nimport type {\n\tCachedAccount,\n\tCachedWallet,\n\tKheopskitStoreData,\n\tWalletPlatform,\n} from \"./types\";\n\n/**\n * Compact wire format for the cookie-persisted store (`CompactStoreV1`).\n *\n * Cookies are size-constrained (~4KB per cookie, sent on every request), so the\n * persisted {@link KheopskitStoreData} is encoded as terse tuples with\n * single-letter keys instead of raw JSON. This module owns that format: the\n * encoder, the defensive decoder, and the lazy migration from the legacy\n * verbose-JSON cookies written by older versions.\n *\n * Any change here is a compatibility question — new fields must be optional and\n * decoding must keep accepting everything older versions wrote (or degrade to\n * \"start fresh\", never throw).\n */\n\n// wallet type: 0=injected, 1=walletconnect\ntype CompactWalletEntry = [WalletId, string, 0 | 1, 0 | 1];\ntype CompactPolkadotAccountType = 0 | 1 | 2 | 3;\n// platform: 0=polkadot, 1=ethereum, 2=solana\ntype CompactPlatformCode = 0 | 1 | 2;\ntype CompactAccountEntry = [\n\tWalletId,\n\tstring,\n\tstring | null,\n\tnumber | null,\n\tCompactPolkadotAccountType | null,\n\t// Platform code. Newly written entries always include it (the WalletConnect\n\t// connector's walletId is platform-less, so platform can't be derived from\n\t// it); absent in entries written by older versions, where it's derived from\n\t// the walletId instead.\n\t(CompactPlatformCode | null)?,\n];\n\ntype CompactStoreV1 = {\n\tv: 1;\n\t// autoReconnect\n\tr?: WalletId[];\n\t// wallets: [id, name, isConnected(0|1), type(0=injected,1=walletconnect)?]\n\tw?: CompactWalletEntry[];\n\t// accounts: [walletId, address, name?, chainId?, polkadotType?, platform?]\n\ta?: CompactAccountEntry[];\n};\n\nconst EMPTY_STORE_DATA: KheopskitStoreData = {};\n\nconst toCompactPolkadotAccountType = (\n\ttype: CachedAccount[\"polkadotAccountType\"],\n): CompactPolkadotAccountType | null => {\n\tswitch (type) {\n\t\tcase \"sr25519\":\n\t\t\treturn 0;\n\t\tcase \"ed25519\":\n\t\t\treturn 1;\n\t\tcase \"ecdsa\":\n\t\t\treturn 2;\n\t\tcase \"ethereum\":\n\t\t\treturn 3;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n\nconst fromCompactPolkadotAccountType = (\n\ttype: CompactPolkadotAccountType | null | undefined,\n): CachedAccount[\"polkadotAccountType\"] => {\n\tswitch (type) {\n\t\tcase 0:\n\t\t\treturn \"sr25519\";\n\t\tcase 1:\n\t\t\treturn \"ed25519\";\n\t\tcase 2:\n\t\t\treturn \"ecdsa\";\n\t\tcase 3:\n\t\t\treturn \"ethereum\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n};\n\nconst toCompactPlatform = (platform: WalletPlatform): CompactPlatformCode => {\n\tswitch (platform) {\n\t\tcase \"polkadot\":\n\t\t\treturn 0;\n\t\tcase \"ethereum\":\n\t\t\treturn 1;\n\t\tcase \"solana\":\n\t\t\treturn 2;\n\t}\n};\n\nconst fromCompactPlatform = (\n\tcode: CompactPlatformCode | null | undefined,\n): WalletPlatform | undefined => {\n\tswitch (code) {\n\t\tcase 0:\n\t\t\treturn \"polkadot\";\n\t\tcase 1:\n\t\t\treturn \"ethereum\";\n\t\tcase 2:\n\t\t\treturn \"solana\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n};\n\nconst isCompactStore = (value: unknown): value is CompactStoreV1 => {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tif (\"cachedWallets\" in value || \"cachedAccounts\" in value) return false;\n\treturn \"v\" in value || \"w\" in value || \"a\" in value || \"r\" in value;\n};\n\nconst toCompactStore = (data: KheopskitStoreData): CompactStoreV1 => {\n\tconst wallets = data.cachedWallets?.map(\n\t\t(wallet): CompactWalletEntry => [\n\t\t\twallet.id,\n\t\t\twallet.name,\n\t\t\twallet.isConnected ? 1 : 0,\n\t\t\twallet.type === \"walletconnect\" ? 1 : 0,\n\t\t],\n\t);\n\n\tconst accounts = data.cachedAccounts?.map(\n\t\t(account): CompactAccountEntry => [\n\t\t\taccount.walletId,\n\t\t\taccount.address,\n\t\t\taccount.name ?? null,\n\t\t\taccount.chainId ?? null,\n\t\t\ttoCompactPolkadotAccountType(account.polkadotAccountType),\n\t\t\ttoCompactPlatform(account.platform),\n\t\t],\n\t);\n\n\treturn {\n\t\tv: 1,\n\t\tr: data.autoReconnect,\n\t\tw: wallets?.length ? wallets : undefined,\n\t\ta: accounts?.length ? accounts : undefined,\n\t};\n};\n\nconst fromCompactStore = (data: CompactStoreV1): KheopskitStoreData => {\n\tconst walletNameMap = new Map<WalletId, string>();\n\n\t// Decode defensively: a compact payload may be malformed (older/corrupt\n\t// cookie, hand-edited). Skip entries with an unparseable wallet id rather\n\t// than throwing, which would crash store initialisation.\n\tconst wallets: CachedWallet[] = [];\n\tfor (const item of Array.isArray(data.w) ? data.w : []) {\n\t\tif (!Array.isArray(item)) continue;\n\t\tconst [id, name, isConnected, type] = item;\n\t\tif (!isValidWalletId(id)) continue;\n\t\tconst isWalletConnect = id === WALLET_CONNECT_WALLET_ID;\n\t\tconst walletType = type === 1 ? \"walletconnect\" : \"injected\";\n\t\t// Keep id/type consistent: the platform-less connector uses the fixed WC\n\t\t// id; everything else is a platform-prefixed injected wallet. Drop stale\n\t\t// mismatches (e.g. per-platform WC ids from older versions).\n\t\tif (isWalletConnect !== (walletType === \"walletconnect\")) continue;\n\t\twalletNameMap.set(id, name);\n\t\twallets.push({\n\t\t\tid,\n\t\t\tplatform: isWalletConnect ? undefined : parseWalletId(id).platform,\n\t\t\ttype: walletType,\n\t\t\tname,\n\t\t\tisConnected: isConnected === 1,\n\t\t});\n\t}\n\n\tconst accounts: CachedAccount[] = [];\n\tfor (const item of Array.isArray(data.a) ? data.a : []) {\n\t\tif (!Array.isArray(item)) continue;\n\t\tconst [\n\t\t\twalletId,\n\t\t\taddress,\n\t\t\tname,\n\t\t\tchainId,\n\t\t\tpolkadotAccountType,\n\t\t\tplatformCode,\n\t\t] = item;\n\t\tif (!isValidWalletId(walletId) || typeof address !== \"string\" || !address)\n\t\t\tcontinue;\n\t\t// Prefer the explicit platform code; fall back to deriving it from the\n\t\t// walletId for entries written before the code existed (never WC ones).\n\t\tconst platform =\n\t\t\tplatformCode != null\n\t\t\t\t? fromCompactPlatform(platformCode)\n\t\t\t\t: walletId === WALLET_CONNECT_WALLET_ID\n\t\t\t\t\t? undefined\n\t\t\t\t\t: parseWalletId(walletId).platform;\n\t\tif (!isWalletPlatform(platform)) continue;\n\t\taccounts.push({\n\t\t\tid: getWalletAccountId(walletId, address),\n\t\t\tplatform,\n\t\t\taddress,\n\t\t\tname: name ?? undefined,\n\t\t\tchainId: chainId ?? undefined,\n\t\t\tpolkadotAccountType:\n\t\t\t\tplatform === \"polkadot\"\n\t\t\t\t\t? fromCompactPolkadotAccountType(polkadotAccountType)\n\t\t\t\t\t: undefined,\n\t\t\twalletId,\n\t\t\twalletName: walletNameMap.get(walletId) ?? walletId,\n\t\t});\n\t}\n\n\treturn {\n\t\tautoReconnect: data.r,\n\t\tcachedWallets: wallets,\n\t\tcachedAccounts: accounts,\n\t};\n};\n\nconst decodeStore = (raw: string, fallback: KheopskitStoreData) => {\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\tif (isCompactStore(parsed)) return fromCompactStore(parsed);\n\t\treturn parsed as KheopskitStoreData;\n\t} catch {\n\t\treturn fallback;\n\t}\n};\n\nconst encodeStore = (data: KheopskitStoreData): string =>\n\tJSON.stringify(toCompactStore(data));\n\n/**\n * Cookie storage that transparently encodes/decodes {@link CompactStoreV1},\n * migrating legacy verbose-JSON cookies to the compact format on first read.\n */\nexport const createCompactCookieStorage = (initialCookies?: string) => {\n\tconst base = cookieStorage(initialCookies);\n\n\treturn {\n\t\tgetItem: (key: string) => {\n\t\t\tconst raw = base.getItem(key);\n\t\t\tif (!raw) return null;\n\t\t\tconst expanded = decodeStore(raw, EMPTY_STORE_DATA);\n\t\t\tif (typeof document !== \"undefined\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\t\t\t\tif (!isCompactStore(parsed)) {\n\t\t\t\t\t\tbase.setItem(key, encodeStore(expanded));\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore malformed cookie during migration\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn JSON.stringify(expanded);\n\t\t},\n\t\tsetItem: (key: string, value: string) => {\n\t\t\tconst expanded = decodeStore(value, EMPTY_STORE_DATA);\n\t\t\tbase.setItem(key, encodeStore(expanded));\n\t\t},\n\t\tremoveItem: base.removeItem,\n\t\tsubscribe: (key: string, callback: (value: string | null) => void) => {\n\t\t\tconst unsubscribe = base.subscribe?.(key, (value) => {\n\t\t\t\tif (!value) {\n\t\t\t\t\tcallback(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst expanded = decodeStore(value, EMPTY_STORE_DATA);\n\t\t\t\tcallback(JSON.stringify(expanded));\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tunsubscribe?.();\n\t\t\t};\n\t\t},\n\t};\n};\n","import { uniq } from \"lodash-es\";\nimport { createStore } from \"../utils/createStore\";\nimport { isWalletPlatform } from \"../utils/isWalletPlatform\";\nimport { safeLocalStorage } from \"../utils/storage\";\nimport {\n\tisValidWalletId,\n\tparseWalletId,\n\tWALLET_CONNECT_WALLET_ID,\n\ttype WalletId,\n} from \"../utils/WalletId\";\nimport { createCompactCookieStorage } from \"./compactStore\";\nimport { DEFAULT_STORAGE_KEY } from \"./config\";\nimport type {\n\tCachedAccount,\n\tCachedWallet,\n\tKheopskitStore,\n\tKheopskitStoreData,\n} from \"./types\";\n\nexport type { KheopskitStore } from \"./types\";\n\nconst DEFAULT_SETTINGS: KheopskitStoreData = {};\n\n/**\n * Validates a cached wallet read from persisted storage. Cached state may have\n * been written by an older (or corrupted) version with a different shape, so we\n * drop anything that wouldn't survive hydration/sort rather than letting it\n * throw at render time. Only the fields downstream code relies on are checked.\n */\nconst isValidCachedWallet = (value: unknown): value is CachedWallet => {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst w = value as Record<string, unknown>;\n\tif (!isValidWalletId(w.id)) return false;\n\tif (typeof w.name !== \"string\" || typeof w.isConnected !== \"boolean\")\n\t\treturn false;\n\t// The WalletConnect connector is platform-less with a fixed id; drop stale\n\t// per-platform WC entries written by older versions.\n\tif (w.type === \"walletconnect\")\n\t\treturn w.id === WALLET_CONNECT_WALLET_ID && w.platform === undefined;\n\treturn w.type === \"injected\" && isWalletPlatform(w.platform);\n};\n\n/** Validates a cached account read from persisted storage. See {@link isValidCachedWallet}. */\nconst isValidCachedAccount = (value: unknown): value is CachedAccount => {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst a = value as Record<string, unknown>;\n\treturn (\n\t\ttypeof a.id === \"string\" &&\n\t\t!!a.id &&\n\t\tisWalletPlatform(a.platform) &&\n\t\ttypeof a.address === \"string\" &&\n\t\t!!a.address &&\n\t\tisValidWalletId(a.walletId) &&\n\t\ttypeof a.walletName === \"string\"\n\t);\n};\n\ntype CreateKheopskitStoreOptions = {\n\t/**\n\t * Cookie string for SSR hydration.\n\t * When provided, uses cookieStorage instead of localStorage.\n\t */\n\tssrCookies?: string;\n\t/**\n\t * Custom storage key to namespace the stored data.\n\t * @default \"kheopskit\"\n\t */\n\tstorageKey?: string;\n};\n\n/**\n * Creates a kheopskit store with the appropriate storage backend.\n * Uses cookieStorage when ssrCookies is provided (for SSR hydration),\n * otherwise falls back to safeLocalStorage.\n *\n * @param options - Configuration options for the store\n */\nexport const createKheopskitStore = (\n\toptions: CreateKheopskitStoreOptions = {},\n): KheopskitStore => {\n\tconst { ssrCookies, storageKey = DEFAULT_STORAGE_KEY } = options;\n\tconst storage =\n\t\tssrCookies !== undefined\n\t\t\t? createCompactCookieStorage(ssrCookies)\n\t\t\t: safeLocalStorage;\n\tconst store = createStore(storageKey, DEFAULT_SETTINGS, storage);\n\n\tconst addEnabledWalletId = (walletId: WalletId) => {\n\t\tparseWalletId(walletId); // validate walletId\n\t\tstore.mutate((prev) => ({\n\t\t\t...prev,\n\t\t\tautoReconnect: uniq((prev.autoReconnect ?? []).concat(walletId)),\n\t\t}));\n\t};\n\n\tconst removeEnabledWalletId = (walletId: WalletId) => {\n\t\tstore.mutate((prev) => ({\n\t\t\t...prev,\n\t\t\tautoReconnect: uniq(\n\t\t\t\t(prev.autoReconnect ?? []).filter((id) => id !== walletId),\n\t\t\t),\n\t\t}));\n\t};\n\n\tconst getCachedState = () => {\n\t\t// `store.get()` returns whatever JSON was persisted — it may be from an\n\t\t// older version, a different shape, or outright corrupt. Read defensively:\n\t\t// coerce non-objects/arrays to empty and drop any entry that fails\n\t\t// validation, so stale cache degrades to \"start fresh\" instead of throwing\n\t\t// during hydration (which renders eagerly, so a throw blanks the dapp).\n\t\tconst data = store.get() as Partial<KheopskitStoreData> | null | undefined;\n\t\tconst cachedWallets = Array.isArray(data?.cachedWallets)\n\t\t\t? data.cachedWallets\n\t\t\t: [];\n\t\tconst cachedAccounts = Array.isArray(data?.cachedAccounts)\n\t\t\t? data.cachedAccounts\n\t\t\t: [];\n\t\treturn {\n\t\t\twallets: cachedWallets.filter(isValidCachedWallet),\n\t\t\taccounts: cachedAccounts.filter(isValidCachedAccount),\n\t\t};\n\t};\n\n\tconst setCachedState = (\n\t\twallets: CachedWallet[],\n\t\taccounts: CachedAccount[],\n\t) => {\n\t\tstore.mutate((prev) => ({\n\t\t\t...prev,\n\t\t\tcachedWallets: wallets,\n\t\t\tcachedAccounts: accounts,\n\t\t}));\n\t};\n\n\treturn {\n\t\tobservable: store.observable,\n\t\taddEnabledWalletId,\n\t\tremoveEnabledWalletId,\n\t\tgetCachedState,\n\t\tsetCachedState,\n\t};\n};\n\n/**\n * Cached default store instance, anchored on globalThis so it stays a single\n * instance even if this module is duplicated across bundle chunks (e.g. CJS\n * subpath entries). Lazily initialized on first access to be SSR-safe.\n */\nconst DEFAULT_STORE_SYMBOL = Symbol.for(\"kheopskit.defaultStore\");\n\n/**\n * Gets the default store, creating it on first access.\n * Uses localStorage on client, noop on server.\n * Lazily initialized to avoid SSR issues with module-level code.\n */\nexport const getDefaultStore = (): KheopskitStore => {\n\tconst g = globalThis as unknown as Record<symbol, KheopskitStore | undefined>;\n\tif (!g[DEFAULT_STORE_SYMBOL]) {\n\t\tg[DEFAULT_STORE_SYMBOL] = createKheopskitStore();\n\t}\n\treturn g[DEFAULT_STORE_SYMBOL];\n};\n","/**\n * Bookkeeping for wallet auto-reconnect attempts.\n *\n * Tracks wallets currently reconnecting (to avoid duplicate concurrent\n * attempts) and those already reconnected (so we don't fight a later manual\n * disconnect). A failed attempt is retried when the wallet next re-emits\n * (e.g. a late-injecting extension that isn't ready on first sight), but only\n * up to `maxAttempts`: a wallet whose connect() keeps rejecting (a permission\n * permanently denied, a buggy provider) must not be re-attempted on every\n * wallets$ emission — the stream re-emits frequently (polkadot polling,\n * mipd/wallet-standard register events).\n */\nexport type ReconnectPolicyOptions = {\n\t/** @default 3 */\n\tmaxAttempts?: number;\n};\n\nexport const createReconnectPolicy = ({\n\tmaxAttempts = 3,\n}: ReconnectPolicyOptions = {}) => {\n\tconst reconnecting = new Set<string>();\n\tconst reconnected = new Set<string>();\n\tconst failedAttempts = new Map<string, number>();\n\n\tconst shouldAttempt = (walletId: string): boolean =>\n\t\t!reconnecting.has(walletId) &&\n\t\t!reconnected.has(walletId) &&\n\t\t(failedAttempts.get(walletId) ?? 0) < maxAttempts;\n\n\t/**\n\t * Runs `connect` under the policy. Resolves `false` without connecting when\n\t * an attempt is already in flight, the wallet already reconnected, or it\n\t * exhausted its attempts; resolves `true` on success. A rejection from\n\t * `connect` is recorded as a failed attempt and rethrown for the caller to\n\t * report.\n\t */\n\tconst attempt = async (\n\t\twalletId: string,\n\t\tconnect: () => Promise<unknown>,\n\t): Promise<boolean> => {\n\t\tif (!shouldAttempt(walletId)) return false;\n\n\t\treconnecting.add(walletId);\n\t\ttry {\n\t\t\tawait connect();\n\t\t\treconnected.add(walletId);\n\t\t\tfailedAttempts.delete(walletId);\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tfailedAttempts.set(walletId, (failedAttempts.get(walletId) ?? 0) + 1);\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\treconnecting.delete(walletId);\n\t\t}\n\t};\n\n\treturn { shouldAttempt, attempt };\n};\n","import {\n\tcombineLatest,\n\tfilter,\n\tmap,\n\tmergeMap,\n\tObservable,\n\tof,\n\tshareReplay,\n\ttake,\n} from \"rxjs\";\nimport { sortWallets } from \"../utils/sortWallets\";\nimport { getWalletConnectWallet$ } from \"./appKit\";\nimport { createReconnectPolicy } from \"./reconnectPolicy\";\nimport type { KheopskitStore } from \"./store\";\nimport type {\n\tBaseWallet,\n\tKheopskitConfig,\n\tPlatformContext,\n\tWalletConnectWallet,\n} from \"./types\";\n\nexport const getWallets$ = (config: KheopskitConfig, store: KheopskitStore) => {\n\t// lock the list of wallets to auto reconnect on first call\n\tconst autoReconnectWalletIds$ = store.observable.pipe(\n\t\tmap((s) => s.autoReconnect ?? []),\n\t\ttake(1),\n\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t);\n\n\treturn new Observable<(BaseWallet | WalletConnectWallet)[]>((subscriber) => {\n\t\tconst ctx: PlatformContext = { config, store };\n\t\tconst observables = config.platforms.map((plugin) =>\n\t\t\tplugin.getWallets$(ctx),\n\t\t);\n\n\t\tconst platformWallets$ = observables.length\n\t\t\t? combineLatest(observables).pipe(map((wallets) => wallets.flat()))\n\t\t\t: of<BaseWallet[]>([]);\n\n\t\t// The single, platform-less WalletConnect connector is appended here (not\n\t\t// emitted per platform). It sorts last (see sortWallets).\n\t\tconst wallets$ = combineLatest([\n\t\t\tplatformWallets$,\n\t\t\tgetWalletConnectWallet$(config),\n\t\t]).pipe(\n\t\t\tmap(([platformWallets, walletConnect]) => {\n\t\t\t\tconst all: (BaseWallet | WalletConnectWallet)[] = walletConnect\n\t\t\t\t\t? [...platformWallets, walletConnect]\n\t\t\t\t\t: platformWallets;\n\t\t\t\treturn all.sort(sortWallets);\n\t\t\t}),\n\t\t\t// Note: No startWith([]) here - the hydration buffer handles initial state\n\t\t);\n\n\t\tconst reconnectPolicy = createReconnectPolicy();\n\n\t\tconst subAutoReconnect = combineLatest([wallets$, autoReconnectWalletIds$])\n\t\t\t.pipe(\n\t\t\t\tfilter(([, walletIds]) => config.autoReconnect && !!walletIds?.length),\n\t\t\t\tmergeMap(([wallets, walletIds]) =>\n\t\t\t\t\twallets.filter((wallet) => walletIds?.includes(wallet.id)),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.subscribe(async (wallet) => {\n\t\t\t\tif (wallet.isConnected) return;\n\t\t\t\ttry {\n\t\t\t\t\tawait reconnectPolicy.attempt(wallet.id, () => wallet.connect());\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\"Failed to reconnect wallet %s\", wallet.id, { err });\n\t\t\t\t}\n\t\t\t});\n\n\t\tconst subWallets = wallets$.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsubAutoReconnect.unsubscribe();\n\t\t\tsubWallets.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n};\n","import {\n\tcombineLatest,\n\tdebounceTime,\n\tdistinctUntilChanged,\n\tfilter,\n\tmap,\n\tObservable,\n\tshareReplay,\n\tthrottleTime,\n} from \"rxjs\";\nimport {\n\tcreateAccountHydrationBuffer,\n\tcreateHydrationBuffer,\n} from \"../utils/createHydrationBuffer\";\nimport { serializeAccount, serializeWallet } from \"../utils/hydrateState\";\nimport { getCachedIcon, setCachedIcons } from \"../utils/iconCache\";\nimport { logObservable } from \"../utils/logObservable\";\nimport { sortAccounts } from \"../utils/sortAccounts\";\nimport { sortWallets } from \"../utils/sortWallets\";\nimport { getAccounts$ } from \"./accounts\";\nimport { resolveConfig } from \"./config\";\nimport { getHydratedSnapshot } from \"./hydration\";\nimport { createKheopskitStore } from \"./store\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tKheopskitConfig,\n\tKheopskitPlatform,\n\tKheopskitState,\n\tWalletConnectWallet,\n} from \"./types\";\nimport { isWalletConnectWallet } from \"./types\";\nimport { getWallets$ } from \"./wallets\";\n\nexport type { KheopskitConfig, KheopskitState } from \"./types\";\n\n/** Options for {@link getKheopskit$}. */\nexport type GetKheopskitOptions = {\n\t/**\n\t * Cookie string for SSR hydration. When provided, state is read from cookies\n\t * instead of localStorage so the server can hydrate without a flash. Pass the\n\t * request's `cookie` header.\n\t */\n\tssrCookies?: string;\n\t/**\n\t * An existing store to reuse instead of creating one. Advanced escape hatch —\n\t * most callers omit it. (`@kheopskit/react` passes its provider-scoped store.)\n\t */\n\tstore?: ReturnType<typeof createKheopskitStore>;\n};\n\nexport const getKheopskit$ = <\n\tconst P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>(\n\tconfig?: Partial<KheopskitConfig<P>>,\n\toptions: GetKheopskitOptions = {},\n): Observable<KheopskitState<P>> => {\n\tconst { ssrCookies, store: existingStore } = options;\n\tconst kc = resolveConfig(config);\n\tconst store =\n\t\texistingStore ??\n\t\tcreateKheopskitStore({ ssrCookies, storageKey: kc.storageKey });\n\n\tif (kc.debug) console.debug(\"[kheopskit] config\", kc);\n\n\t// Warn about SSR environment without cookies\n\tif (kc.debug && typeof window === \"undefined\" && ssrCookies === undefined) {\n\t\tconsole.warn(\n\t\t\t\"[kheopskit] Running on server without `ssrCookies`. \" +\n\t\t\t\t\"Wallet state will not be hydrated. Pass cookies for SSR support.\",\n\t\t);\n\t}\n\n\t// Get cached state for hydration (same snapshot the React provider builds)\n\tconst { wallets: cachedWallets, accounts: cachedAccounts } =\n\t\tgetHydratedSnapshot(store, kc.platforms, { icons: true });\n\n\tif (kc.debug && cachedWallets.length > 0) {\n\t\tconsole.debug(\"[kheopskit] hydrating from cache:\", {\n\t\t\twallets: cachedWallets.length,\n\t\t\taccounts: cachedAccounts.length,\n\t\t});\n\t}\n\n\treturn new Observable<KheopskitState>((subscriber) => {\n\t\t// Get live wallets and accounts\n\t\tconst liveWallets$ = getWallets$(kc, store);\n\t\tconst liveAccounts$ = getAccounts$(kc, liveWallets$);\n\n\t\t// Apply hydration buffer to wallets\n\t\tconst bufferedWallets$ = createHydrationBuffer(\n\t\t\tcachedWallets,\n\t\t\tliveWallets$,\n\t\t\tkc.hydrationGracePeriod,\n\t\t\t(w) => w.id,\n\t\t\t// Hydration converges when all cached-connected wallets are connected in live\n\t\t\t(liveWallets, cached) => {\n\t\t\t\tconst cachedConnectedIds = new Set(\n\t\t\t\t\tcached.filter((w) => w.isConnected).map((w) => w.id),\n\t\t\t\t);\n\t\t\t\tif (cachedConnectedIds.size === 0) return true;\n\t\t\t\treturn [...cachedConnectedIds].every((id) =>\n\t\t\t\t\tliveWallets.some((w) => w.id === id && w.isConnected),\n\t\t\t\t);\n\t\t\t},\n\t\t\t// Merge: prefer cached isConnected state but get icon from cache or live\n\t\t\t(live, cached) => ({\n\t\t\t\t...cached,\n\t\t\t\t// Priority: cached icon > localStorage cache > live icon\n\t\t\t\ticon: cached.icon || getCachedIcon(cached.id) || live.icon,\n\t\t\t\t// Use live wallet's connect/disconnect functions\n\t\t\t\tconnect: live.connect,\n\t\t\t\tdisconnect: live.disconnect,\n\t\t\t}),\n\t\t\t// Transform cached-only items: add icon from localStorage cache\n\t\t\t(cached) => ({\n\t\t\t\t...cached,\n\t\t\t\ticon: cached.icon || getCachedIcon(cached.id) || \"\",\n\t\t\t}),\n\t\t);\n\n\t\t// Apply hydration buffer to accounts\n\t\tconst bufferedAccounts$ = createAccountHydrationBuffer(\n\t\t\tcachedAccounts,\n\t\t\tliveAccounts$,\n\t\t\tkc.hydrationGracePeriod,\n\t\t\t(a) => a.walletId,\n\t\t\t// Hydration converges when all wallets with cached accounts have provided live accounts\n\t\t\t(liveAccounts, cached) => {\n\t\t\t\tconst cachedWalletIds = new Set(cached.map((a) => a.walletId));\n\t\t\t\tif (cachedWalletIds.size === 0) return true;\n\t\t\t\tconst liveWalletIds = new Set(liveAccounts.map((a) => a.walletId));\n\t\t\t\treturn [...cachedWalletIds].every((id) => liveWalletIds.has(id));\n\t\t\t},\n\t\t);\n\n\t\t// Share the buffered streams so the main and persistence subscriptions\n\t\t// below reuse a single hydration pipeline (timers, isHydrating state)\n\t\t// instead of running the buffering twice.\n\t\tconst sharedWallets$ = bufferedWallets$.pipe(\n\t\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t);\n\t\tconst sharedAccounts$ = bufferedAccounts$.pipe(\n\t\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t);\n\n\t\t// Combine buffered wallets and accounts\n\t\tconst subscription = combineLatest({\n\t\t\twallets: sharedWallets$,\n\t\t\taccounts: sharedAccounts$,\n\t\t})\n\t\t\t.pipe(\n\t\t\t\tmap(({ wallets, accounts }) => {\n\t\t\t\t\tif (kc.debug) {\n\t\t\t\t\t\tconsole.debug(\"[kheopskit] hydration state\", {\n\t\t\t\t\t\t\twalletsHydrating: wallets.isHydrating,\n\t\t\t\t\t\t\taccountsHydrating: accounts.isHydrating,\n\t\t\t\t\t\t\twalletsConnected: wallets.items.filter((w) => w.isConnected)\n\t\t\t\t\t\t\t\t.length,\n\t\t\t\t\t\t\twalletsTotal: wallets.items.length,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// Sort on every emission with the same comparators used for the\n\t\t\t\t\t// cached initial snapshot. The hydration buffers append cached-only\n\t\t\t\t\t// items after live ones (and reconnects land out of order), so\n\t\t\t\t\t// without this the list visibly reorders as wallets come back.\n\t\t\t\t\treturn {\n\t\t\t\t\t\tconfig: kc,\n\t\t\t\t\t\twallets: [...wallets.items].sort(sortWallets),\n\t\t\t\t\t\taccounts: [...accounts.items].sort(sortAccounts),\n\t\t\t\t\t\tisHydrating: wallets.isHydrating || accounts.isHydrating,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\t// Persist state snapshot when hydration completes and state stabilizes\n\t\tconst persistSub = combineLatest({\n\t\t\twallets: sharedWallets$,\n\t\t\taccounts: sharedAccounts$,\n\t\t})\n\t\t\t.pipe(\n\t\t\t\t// Wait for hydration to complete\n\t\t\t\tfilter(\n\t\t\t\t\t({ wallets, accounts }) =>\n\t\t\t\t\t\t!wallets.isHydrating && !accounts.isHydrating,\n\t\t\t\t),\n\t\t\t\t// Debounce to avoid excessive writes\n\t\t\t\tdebounceTime(1000),\n\t\t\t\t// Only persist if the serialized snapshot would actually change.\n\t\t\t\t// Compare the persisted fields (not just ids): an Ethereum chain switch\n\t\t\t\t// keeps the same account id but changes the cached chainId, so an\n\t\t\t\t// id-only comparator would skip persisting it.\n\t\t\t\tdistinctUntilChanged((prev, curr) => {\n\t\t\t\t\tconst prevWalletKeys = prev.wallets.items.map(walletPersistKey);\n\t\t\t\t\tconst currWalletKeys = curr.wallets.items.map(walletPersistKey);\n\t\t\t\t\tconst prevAccountKeys = prev.accounts.items.map(accountChangeKey);\n\t\t\t\t\tconst currAccountKeys = curr.accounts.items.map(accountChangeKey);\n\t\t\t\t\treturn (\n\t\t\t\t\t\tarraysEqual(prevWalletKeys, currWalletKeys) &&\n\t\t\t\t\t\tarraysEqual(prevAccountKeys, currAccountKeys)\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.subscribe(({ wallets, accounts }) => {\n\t\t\t\t// Cache ALL wallets to avoid wallet list flash on reload\n\t\t\t\t// Only accounts from connected wallets are cached\n\t\t\t\tconst connectedWalletIds = new Set(\n\t\t\t\t\twallets.items.filter((w) => w.isConnected).map((w) => w.id),\n\t\t\t\t);\n\t\t\t\tconst relevantAccounts = accounts.items.filter((a) =>\n\t\t\t\t\tconnectedWalletIds.has(a.walletId),\n\t\t\t\t);\n\n\t\t\t\tif (kc.debug) {\n\t\t\t\t\tconsole.debug(\"[kheopskit] persisting state snapshot:\", {\n\t\t\t\t\t\twallets: wallets.items.length,\n\t\t\t\t\t\taccounts: relevantAccounts.length,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tstore.setCachedState(\n\t\t\t\t\twallets.items.map(serializeWallet),\n\t\t\t\t\trelevantAccounts.map(serializeAccount),\n\t\t\t\t);\n\n\t\t\t\t// Cache wallet icons in localStorage (separate from cookies for size)\n\t\t\t\tconst icons: Record<string, string> = {};\n\t\t\t\tfor (const wallet of wallets.items) {\n\t\t\t\t\tif (wallet.icon) {\n\t\t\t\t\t\ticons[wallet.id] = wallet.icon;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetCachedIcons(icons);\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tsubscription.unsubscribe();\n\t\t\tpersistSub.unsubscribe();\n\t\t};\n\t}).pipe(\n\t\tdistinctUntilChanged(statesEqual),\n\t\tthrottleTime(16, undefined, { leading: true, trailing: true }), // ~1 frame at 60fps\n\t\tlogObservable(\"kheopskit$\", { enabled: kc.debug, printValue: true }),\n\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t// The runtime objects are the concrete per-plugin wallet/account types;\n\t\t// recover the precise KheopskitState<P> the caller's plugins imply.\n\t) as unknown as Observable<KheopskitState<P>>;\n};\n\nconst arraysEqual = (a: string[], b: string[]) =>\n\ta.length === b.length && a.every((v, i) => v === b[i]);\n\n// Mutable per-platform account fields that can change without the account id\n// changing. Declared locally (not imported from the platform packages) so this\n// core entry stays free of platform SDK types — see check:isolation.\ntype EthereumAccountFields = { chainId?: number };\ntype PolkadotAccountFields = { type?: string };\ntype SolanaAccountFields = { chains?: string[] };\n\n/**\n * A signature of an account covering its id plus the platform-specific fields\n * that can change without the id changing (Ethereum chainId, Polkadot key type,\n * Solana clusters). Used to detect both UI-relevant changes and changes worth\n * re-persisting, so the two comparators can't drift apart.\n */\nconst accountChangeKey = (account: BaseWalletAccount): string => {\n\tswitch (account.platform) {\n\t\tcase \"ethereum\":\n\t\t\treturn `${account.id}|${(account as EthereumAccountFields).chainId ?? \"\"}`;\n\t\tcase \"polkadot\":\n\t\t\treturn `${account.id}|${(account as PolkadotAccountFields).type ?? \"\"}`;\n\t\tcase \"solana\":\n\t\t\treturn `${account.id}|${((account as SolanaAccountFields).chains ?? []).join(\",\")}`;\n\t\tdefault:\n\t\t\treturn account.id;\n\t}\n};\n\n/** Platforms a wallet's live session carries (only the WalletConnect connector). */\nconst walletPlatforms = (wallet: BaseWallet | WalletConnectWallet): string =>\n\tisWalletConnectWallet(wallet) ? wallet.platforms.join(\",\") : \"\";\n\n/** Fields persisted to the cache for a wallet (icon is stored separately). */\nconst walletPersistKey = (wallet: BaseWallet | WalletConnectWallet): string =>\n\t`${wallet.id}|${wallet.isConnected ? 1 : 0}|${wallet.name}`;\n\n/**\n * UI-significant signature of a wallet: the persisted fields plus icon and the\n * WalletConnect connector's `platforms` array, which drive what the UI shows but\n * aren't part of the id (icon and platforms can arrive asynchronously after\n * connect without isConnected flipping).\n */\nconst walletUiKey = (wallet: BaseWallet | WalletConnectWallet): string =>\n\t`${walletPersistKey(wallet)}|${wallet.icon}|${walletPlatforms(wallet)}`;\n\n/**\n * Equality check for KheopskitState to prevent unnecessary emissions. Compares\n * the UI-significant signature of every wallet and account, in order.\n */\nconst statesEqual = (a: KheopskitState, b: KheopskitState): boolean =>\n\ta.isHydrating === b.isHydrating &&\n\ta.wallets.length === b.wallets.length &&\n\ta.accounts.length === b.accounts.length &&\n\ta.wallets.every((w, i) => {\n\t\tconst other = b.wallets[i];\n\t\treturn !!other && walletUiKey(w) === walletUiKey(other);\n\t}) &&\n\ta.accounts.every((acc, i) => {\n\t\tconst other = b.accounts[i];\n\t\treturn !!other && accountChangeKey(acc) === accountChangeKey(other);\n\t});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["PLATFORM_ORDER"],"sources":["../src/api/config.ts","../src/utils/sortAccounts.ts","../src/utils/sortWallets.ts","../src/api/platform.ts","../src/api/reconnectPolicy.ts","../src/api/hydration.ts","../src/utils/createHydrationBuffer.ts","../src/utils/logObservable.ts","../src/api/accounts.ts","../src/utils/createStore.ts","../src/api/compactStore.ts","../src/api/store.ts","../src/api/wallets.ts","../src/api/kheopskit.ts"],"sourcesContent":["import { KheopskitError } from \"./errors\";\nimport type { KheopskitConfig, KheopskitPlatform } from \"./types\";\n\n/**\n * Default storage key for persisting wallet connection state.\n * Can be overridden via config.storageKey to avoid conflicts\n * when running multiple dapps on the same domain.\n */\nexport const DEFAULT_STORAGE_KEY = \"kheopskit\";\n\nconst DEFAULTS = {\n\tautoReconnect: true,\n\tdebug: false,\n\tstorageKey: DEFAULT_STORAGE_KEY,\n\thydrationGracePeriod: 500,\n\thydrationTimeout: 3000,\n} satisfies Omit<KheopskitConfig, \"platforms\" | \"walletConnect\">;\n\nexport const resolveConfig = <\n\tconst P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>(\n\tconfig?: Partial<KheopskitConfig<P>>,\n): KheopskitConfig<P> => {\n\tconst platforms = (config?.platforms ?? []) as P;\n\n\t// Guard the v4 breaking change: platforms are plugin instances, not strings.\n\t// Catches JS callers (no tsc) and gives agents a fix that names the doc.\n\tconst invalidPlatforms = (platforms as readonly unknown[]).filter(\n\t\t(p) =>\n\t\t\ttypeof p !== \"object\" ||\n\t\t\tp === null ||\n\t\t\ttypeof (p as { getWallets$?: unknown }).getWallets$ !== \"function\",\n\t);\n\tif (invalidPlatforms.length > 0) {\n\t\tthrow new Error(\n\t\t\t\"[kheopskit] config.platforms must contain plugin instances created by the \" +\n\t\t\t\t\"per-platform factories (e.g. platforms: [polkadot(), ethereum(), solana()] \" +\n\t\t\t\t'imported from \"@kheopskit/core/<platform>\"). ' +\n\t\t\t\t`Invalid entries: ${JSON.stringify(invalidPlatforms)}. ` +\n\t\t\t\t'String platform names like \"polkadot\" were removed in v4 — see MIGRATING_TO_V4.md.',\n\t\t);\n\t}\n\n\tif (\n\t\tconfig?.walletConnect !== undefined &&\n\t\ttypeof (config.walletConnect as { getWallet$?: unknown } | null)\n\t\t\t?.getWallet$ !== \"function\"\n\t) {\n\t\tthrow new KheopskitError(\n\t\t\t\"INVALID_CONFIG\",\n\t\t\t\"config.walletConnect must be created by walletConnect() imported from \" +\n\t\t\t\t'\"@kheopskit/core/walletconnect\", e.g. walletConnect: walletConnect({ projectId, metadata, networks }). ' +\n\t\t\t\t\"Raw WalletConnect options were removed in v6, see MIGRATING_TO_V6.md.\",\n\t\t);\n\t}\n\n\tif (platforms.length === 0) {\n\t\tconsole.warn(\n\t\t\t\"[kheopskit] No platforms configured; wallets and accounts will be empty. \" +\n\t\t\t\t'Pass e.g. platforms: [polkadot()] from \"@kheopskit/core/polkadot\".',\n\t\t);\n\t}\n\n\treturn Object.assign({}, DEFAULTS, config, { platforms });\n};\n","import type { BaseWalletAccount, WalletPlatform } from \"../api/types\";\n\nconst PLATFORM_ORDER: Record<WalletPlatform, number> = {\n\tpolkadot: 0,\n\tethereum: 1,\n\tsolana: 2,\n};\n\nconst byPlatform = (a1: BaseWalletAccount, a2: BaseWalletAccount) =>\n\tPLATFORM_ORDER[a1.platform] - PLATFORM_ORDER[a2.platform];\n\n// Group accounts by wallet, surfacing Talisman first (case-insensitive).\nconst byWalletName = (a1: BaseWalletAccount, a2: BaseWalletAccount) => {\n\tif (a1.walletName === a2.walletName) return 0;\n\tif (a1.walletName.toLowerCase() === \"talisman\") return -1;\n\tif (a2.walletName.toLowerCase() === \"talisman\") return 1;\n\treturn a1.walletName.localeCompare(a2.walletName);\n};\n\nexport const sortAccounts = (a1: BaseWalletAccount, a2: BaseWalletAccount) =>\n\tbyPlatform(a1, a2) || byWalletName(a1, a2);\n","import {\n\ttype BaseWallet,\n\tisWalletConnectWallet,\n\ttype WalletConnectWallet,\n\ttype WalletPlatform,\n} from \"../api/types\";\n\nconst PLATFORM_ORDER: Record<WalletPlatform, number> = {\n\tpolkadot: 0,\n\tethereum: 1,\n\tsolana: 2,\n};\n\n// The platform-less WalletConnect connector sorts after all platform wallets.\nconst orderOf = (wallet: BaseWallet | WalletConnectWallet) =>\n\tisWalletConnectWallet(wallet) ? 3 : PLATFORM_ORDER[wallet.platform];\n\nexport const sortWallets = (\n\tw1: BaseWallet | WalletConnectWallet,\n\tw2: BaseWallet | WalletConnectWallet,\n) => {\n\t// Sort by platform first: polkadot, then ethereum, then solana, then WC\n\tconst o1 = orderOf(w1);\n\tconst o2 = orderOf(w2);\n\tif (o1 !== o2) return o1 - o2;\n\n\t// Sort by name, but Talisman first\n\tif (w1.name.toLowerCase() === \"talisman\") return -1;\n\tif (w2.name.toLowerCase() === \"talisman\") return 1;\n\n\treturn w1.name.localeCompare(w2.name);\n};\n","import type { CachedAccount, KheopskitPlatform } from \"./types\";\n\n/**\n * Whether a cached account should survive SSR hydration, per its platform\n * plugin's `acceptsCachedAccount` hook. Plugins without the hook (and platforms\n * with no enabled plugin) accept all — matching the pre-plugin behavior where\n * only Polkadot accounts were filtered (by key type).\n */\nexport const acceptsCachedAccount = (\n\tcached: CachedAccount,\n\tplatforms: readonly KheopskitPlatform[],\n): boolean => {\n\tconst plugin = platforms.find((p) => p.platform === cached.platform);\n\treturn plugin?.acceptsCachedAccount?.(cached) ?? true;\n};\n","import type { BaseWallet, KheopskitConfig } from \"./types\";\n\n// `maxAttempts` caps retries: wallets$ re-emits on every discovery change, so a\n// connect that always rejects would otherwise be re-attempted on each one.\nexport type ReconnectPolicyOptions = {\n\t/** @default 3 */\n\tmaxAttempts?: number;\n};\n\ntype ReconnectAttemptState =\n\t| { kind: \"pending\" }\n\t| { kind: \"reconnected\" }\n\t| { kind: \"settled\" }\n\t| { kind: \"failed\"; attempts: number };\n\nexport const createReconnectPolicy = ({\n\tmaxAttempts = 3,\n}: ReconnectPolicyOptions = {}) => {\n\tconst states = new Map<string, ReconnectAttemptState>();\n\n\tconst shouldAttempt = (walletId: string): boolean => {\n\t\tconst state = states.get(walletId);\n\t\tif (!state) return true;\n\t\treturn state.kind === \"failed\" && state.attempts < maxAttempts;\n\t};\n\n\tconst attempt = async (\n\t\twalletId: string,\n\t\tconnect: () => Promise<unknown>,\n\t): Promise<boolean> => {\n\t\tif (!shouldAttempt(walletId)) return false;\n\n\t\tconst before = states.get(walletId);\n\t\tstates.set(walletId, { kind: \"pending\" });\n\t\tconst recordOutcome = (outcome: ReconnectAttemptState) => {\n\t\t\tif (states.get(walletId)?.kind !== \"settled\")\n\t\t\t\tstates.set(walletId, outcome);\n\t\t};\n\t\ttry {\n\t\t\tawait connect();\n\t\t\trecordOutcome({ kind: \"reconnected\" });\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconst attempts = before?.kind === \"failed\" ? before.attempts + 1 : 1;\n\t\t\trecordOutcome({ kind: \"failed\", attempts });\n\t\t\tthrow err;\n\t\t}\n\t};\n\n\tconst settle = (walletId: string) => {\n\t\tstates.set(walletId, { kind: \"settled\" });\n\t};\n\n\treturn { shouldAttempt, attempt, settle };\n};\n\n// Shared by the first-frame snapshot and the live attempt: both must evaluate\n// `autoReconnect` identically or the server and client markup diverge.\nexport const reconnectAccepts = (\n\tautoReconnect: KheopskitConfig[\"autoReconnect\"],\n\twallet: BaseWallet,\n): boolean =>\n\ttypeof autoReconnect === \"function\" ? autoReconnect(wallet) : autoReconnect;\n","import { hydrateAccount, hydrateWallet } from \"../utils/hydrateState\";\nimport { getCachedIcon } from \"../utils/iconCache\";\nimport { sortAccounts } from \"../utils/sortAccounts\";\nimport { sortWallets } from \"../utils/sortWallets\";\nimport { acceptsCachedAccount } from \"./platform\";\nimport { reconnectAccepts } from \"./reconnectPolicy\";\nimport type { KheopskitStore } from \"./store\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tKheopskitConfig,\n\tWalletConnectWallet,\n} from \"./types\";\nimport { isInjectedWallet } from \"./types\";\n\n/** Result of {@link getHydratedSnapshot}: placeholder wallets and accounts built from the cache. */\nexport type HydratedSnapshot = {\n\twallets: (BaseWallet | WalletConnectWallet)[];\n\taccounts: BaseWalletAccount[];\n};\n\nexport type GetHydratedSnapshotOptions = {\n\t/**\n\t * Enrich wallets that have no icon from the localStorage icon cache.\n\t *\n\t * Must stay `false` for any snapshot that has to match server-rendered markup\n\t * (React's `getServerSnapshot` runs on the client during hydration, where the\n\t * icon cache is populated — enriching there would diverge from the server,\n\t * which always sees an empty cache).\n\t */\n\ticons?: boolean;\n};\n\n/**\n * Builds the cached-state snapshot every consumer must agree on: read the\n * store's cached state, hydrate wallets/accounts into placeholders, apply the\n * `autoReconnect` rule (a cached connected wallet it rejects becomes\n * `disconnected` and loses its cached accounts), filter accounts through each\n * platform plugin's `acceptsCachedAccount` hook, and sort with the same\n * comparators the live pipeline uses.\n *\n * This is the single implementation behind the observable's initial seed and\n * both React snapshot sources (`serverValue`/`initialValue`). They must produce\n * the same shape in the same order or the UI flickers/reorders on reload — by\n * sharing this helper, that agreement holds by construction.\n */\nexport const getHydratedSnapshot = (\n\tstore: KheopskitStore,\n\tconfig: Pick<KheopskitConfig, \"platforms\" | \"autoReconnect\">,\n\toptions: GetHydratedSnapshotOptions = {},\n): HydratedSnapshot => {\n\tconst cached = store.getCachedState();\n\n\tconst wallets = cached.wallets\n\t\t.map(hydrateWallet)\n\t\t.map((wallet) =>\n\t\t\twallet.status === \"connecting\" &&\n\t\t\tisInjectedWallet(wallet) &&\n\t\t\t!reconnectAccepts(config.autoReconnect, wallet)\n\t\t\t\t? { ...wallet, status: \"disconnected\" as const }\n\t\t\t\t: wallet,\n\t\t)\n\t\t.map((wallet) => {\n\t\t\t// Some wallets (e.g. Ethereum) have no SSR-safe icon; optionally fill it\n\t\t\t// from the localStorage cache.\n\t\t\tif (!options.icons || wallet.icon) return wallet;\n\t\t\tconst icon = getCachedIcon(wallet.id);\n\t\t\treturn icon ? { ...wallet, icon } : wallet;\n\t\t})\n\t\t.sort(sortWallets);\n\n\tconst disconnected = new Set(\n\t\twallets.filter((w) => w.status === \"disconnected\").map((w) => w.id),\n\t);\n\n\tconst accounts = cached.accounts\n\t\t.filter((account) => !disconnected.has(account.walletId))\n\t\t.filter((account) => acceptsCachedAccount(account, config.platforms))\n\t\t.map(hydrateAccount)\n\t\t.sort(sortAccounts);\n\n\treturn { wallets, accounts };\n};\n","import {\n\tBehaviorSubject,\n\tcombineLatest,\n\tfilter,\n\tmap,\n\tObservable,\n\tSubscription,\n\tstartWith,\n\ttake,\n\ttimer,\n} from \"rxjs\";\n\ntype HydrationBufferResult<T> = {\n\titems: T[];\n\tisHydrating: boolean;\n};\n\nconst createBufferCore = <L, C>(\n\tcachedItems: C[],\n\tliveItems$: Observable<L[]>,\n\tgracePeriodMs: number,\n\ttimeoutMs: number,\n\tmergeFn: (liveItems: L[], cachedItems: C[]) => (L | C)[],\n\tsettled$?: Observable<boolean>,\n): Observable<HydrationBufferResult<L | C>> => {\n\tif (gracePeriodMs <= 0 || cachedItems.length === 0) {\n\t\treturn liveItems$.pipe(map((items) => ({ items, isHydrating: false })));\n\t}\n\n\treturn new Observable<HydrationBufferResult<L | C>>((subscriber) => {\n\t\tconst subscriptions = new Subscription();\n\t\tconst isHydrating$ = new BehaviorSubject(true);\n\t\tconst endHydration = () => {\n\t\t\tif (isHydrating$.value) isHydrating$.next(false);\n\t\t};\n\n\t\tconst graceElapsed$ = timer(gracePeriodMs).pipe(\n\t\t\tmap(() => true),\n\t\t\tstartWith(false),\n\t\t);\n\t\tconst ended$: Observable<unknown> = settled$\n\t\t\t? combineLatest([graceElapsed$, settled$]).pipe(\n\t\t\t\t\tfilter(([graceElapsed, settled]) => graceElapsed && settled),\n\t\t\t\t\ttake(1),\n\t\t\t\t)\n\t\t\t: timer(gracePeriodMs);\n\t\tsubscriptions.add(ended$.subscribe(endHydration));\n\t\tsubscriptions.add(timer(timeoutMs).subscribe(endHydration));\n\n\t\tsubscriptions.add(\n\t\t\tcombineLatest([liveItems$.pipe(startWith([] as L[])), isHydrating$])\n\t\t\t\t.pipe(\n\t\t\t\t\tmap(([liveItems, isHydrating]) =>\n\t\t\t\t\t\tisHydrating\n\t\t\t\t\t\t\t? { items: mergeFn(liveItems, cachedItems), isHydrating }\n\t\t\t\t\t\t\t: { items: liveItems, isHydrating },\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.subscribe(subscriber),\n\t\t);\n\n\t\treturn () => {\n\t\t\tsubscriptions.unsubscribe();\n\t\t\tisHydrating$.complete();\n\t\t};\n\t});\n};\n\n/**\n * Creates a hydration buffer that merges cached items with live items.\n *\n * During hydration, cached items take precedence over live items with the same key.\n * This preserves the cached connected state (e.g., isConnected: true) while\n * auto-reconnect is still in progress. New live items not in the cache are added.\n *\n * @param cachedItems - Initial cached items from storage\n * @param liveItems$ - Observable of live items as they become available\n * @param gracePeriodMs - Minimum time in ms the cached items are shown\n * @param timeoutMs - Upper bound in ms on hydration\n * @param getKey - Function to extract a unique key from an item\n * @param settled$ - Whether the live state has caught up with the cache\n * @param mergeItem - Optional function to merge a live item with its cached counterpart\n * @param transformCachedOnly - Optional function to transform cached items not yet in the live stream\n */\nexport const createHydrationBuffer = <L, C>(\n\tcachedItems: C[],\n\tliveItems$: Observable<L[]>,\n\tgracePeriodMs: number,\n\ttimeoutMs: number,\n\tgetKey: (item: L | C) => string,\n\tsettled$?: Observable<boolean>,\n\tmergeItem?: (liveItem: L, cachedItem: C) => L | C,\n\ttransformCachedOnly?: (cachedItem: C) => C,\n): Observable<HydrationBufferResult<L | C>> => {\n\treturn createBufferCore(\n\t\tcachedItems,\n\t\tliveItems$,\n\t\tgracePeriodMs,\n\t\ttimeoutMs,\n\t\t(liveItems, cached) => {\n\t\t\tconst cachedByKey = new Map(cached.map((item) => [getKey(item), item]));\n\t\t\tconst liveKeys = new Set(liveItems.map(getKey));\n\n\t\t\t// For items in both live and cached, prefer cached (preserves connected state)\n\t\t\t// but allow mergeItem to customize how they're combined\n\t\t\t// For items only in live (newly discovered), use the live version\n\t\t\tconst mergedItems: (L | C)[] = liveItems.map((liveItem) => {\n\t\t\t\tconst key = getKey(liveItem);\n\t\t\t\tconst cachedItem = cachedByKey.get(key);\n\t\t\t\tif (!cachedItem) return liveItem;\n\t\t\t\treturn mergeItem ? mergeItem(liveItem, cachedItem) : cachedItem;\n\t\t\t});\n\n\t\t\t// Add cached items not yet in the live stream (e.g., extensions not yet detected)\n\t\t\tfor (const cachedItem of cached) {\n\t\t\t\tif (!liveKeys.has(getKey(cachedItem))) {\n\t\t\t\t\tconst transformed = transformCachedOnly\n\t\t\t\t\t\t? transformCachedOnly(cachedItem)\n\t\t\t\t\t\t: cachedItem;\n\t\t\t\t\tmergedItems.push(transformed);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mergedItems;\n\t\t},\n\t\tsettled$,\n\t);\n};\n\n/**\n * Creates a hydration buffer specifically for accounts, which need special handling.\n *\n * Accounts are grouped by wallet - when a wallet provides its account list,\n * we replace all cached accounts for that wallet with the live ones.\n * Cached accounts for wallets that haven't provided accounts yet are preserved.\n *\n * @param cachedAccounts - Initial cached accounts from storage\n * @param liveAccounts$ - Observable of live accounts as they become available\n * @param gracePeriodMs - Minimum time in ms the cached accounts are shown\n * @param timeoutMs - Upper bound in ms on hydration\n * @param getWalletId - Function to extract the wallet ID from an account\n * @param settled$ - Whether the live state has caught up with the cache\n */\nexport const createAccountHydrationBuffer = <T>(\n\tcachedAccounts: T[],\n\tliveAccounts$: Observable<T[]>,\n\tgracePeriodMs: number,\n\ttimeoutMs: number,\n\tgetWalletId: (account: T) => string,\n\tsettled$?: Observable<boolean>,\n): Observable<HydrationBufferResult<T>> => {\n\treturn createBufferCore(\n\t\tcachedAccounts,\n\t\tliveAccounts$,\n\t\tgracePeriodMs,\n\t\ttimeoutMs,\n\t\t(liveAccounts, cached) => {\n\t\t\tconst walletsWithLiveAccounts = new Set(liveAccounts.map(getWalletId));\n\t\t\tconst mergedAccounts: T[] = [...liveAccounts];\n\n\t\t\tfor (const cachedAccount of cached) {\n\t\t\t\tif (!walletsWithLiveAccounts.has(getWalletId(cachedAccount))) {\n\t\t\t\t\tmergedAccounts.push(cachedAccount);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn mergedAccounts;\n\t\t},\n\t\tsettled$,\n\t);\n};\n","import { type MonoTypeOperatorFunction, tap } from \"rxjs\";\n\ntype Opts = {\n\tprintValue?: boolean;\n\tenabled?: boolean;\n};\n\nexport const logObservable = <T>(\n\tlabel: string,\n\topts?: Opts,\n): MonoTypeOperatorFunction<T> =>\n\ttap((value) => {\n\t\tconst { printValue = false, enabled = true } = opts || {};\n\n\t\tif (!label || !enabled) return;\n\n\t\tconst text = `[kheopskit] observable ${label} emit`;\n\n\t\tif (printValue) console.debug(text, value);\n\t\telse console.debug(text);\n\t});\n","import { combineLatest, map, Observable, of, shareReplay } from \"rxjs\";\nimport { sortAccounts } from \"../utils/sortAccounts\";\nimport { framesOf, type PlatformAccountsFrame } from \"./platformAccounts\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tKheopskitConfig,\n\tWalletConnectWallet,\n} from \"./types\";\nimport { isWalletConnectWallet } from \"./types\";\n\nexport type AccountsFrame = PlatformAccountsFrame<BaseWalletAccount>;\n\nexport const getAccounts$ = (\n\tconfig: KheopskitConfig,\n\twallets: Observable<(BaseWallet | WalletConnectWallet)[]>,\n) => {\n\treturn new Observable<AccountsFrame>((subscriber) => {\n\t\t// Each plugin gets its own platform's (injected) wallets plus the shared\n\t\t// WalletConnect connector; it derives WC accounts only for the namespaces\n\t\t// the session carries.\n\t\tconst sources = config.platforms.map((plugin) =>\n\t\t\tframesOf(\n\t\t\t\tplugin.getAccounts$(\n\t\t\t\t\twallets.pipe(\n\t\t\t\t\t\tmap((ws) =>\n\t\t\t\t\t\t\tws.filter(\n\t\t\t\t\t\t\t\t(w) =>\n\t\t\t\t\t\t\t\t\tisWalletConnectWallet(w) || w.platform === plugin.platform,\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),\n\t\t);\n\n\t\tconst frames$ = sources.length\n\t\t\t? combineLatest(sources).pipe(\n\t\t\t\t\tmap((frames) => ({\n\t\t\t\t\t\taccounts: frames\n\t\t\t\t\t\t\t.flatMap((frame) => frame.accounts)\n\t\t\t\t\t\t\t.sort(sortAccounts),\n\t\t\t\t\t\tanswered: frames.flatMap((frame) => frame.answered),\n\t\t\t\t\t})),\n\t\t\t\t)\n\t\t\t: of<AccountsFrame>({ accounts: [], answered: [] });\n\n\t\tconst sub = frames$.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n};\n","import { BehaviorSubject, Observable } from \"rxjs\";\nimport { type SyncableStorage, safeLocalStorage } from \"./storage\";\n\nexport const createStore = <T>(\n\tkey: string,\n\tdefaultValue: T,\n\tstorage: SyncableStorage = safeLocalStorage,\n\tnormalize: (value: T) => T = (value) => value,\n) => {\n\tconst read = (str: string | null) => normalize(parseData(str, defaultValue));\n\tconst syncsAcrossTabs =\n\t\ttypeof window !== \"undefined\" && storage.subscribe !== undefined;\n\tconst subject = new BehaviorSubject<T>(read(storage.getItem(key)));\n\tlet observers = 0;\n\tlet stopSync: (() => void) | undefined;\n\n\tconst latestValue = () => {\n\t\tif (syncsAcrossTabs && observers === 0)\n\t\t\tsubject.next(read(storage.getItem(key)));\n\t\treturn subject.getValue();\n\t};\n\n\tconst observable = new Observable<T>((subscriber) => {\n\t\tif (observers === 0 && syncsAcrossTabs) {\n\t\t\tlatestValue();\n\t\t\tstopSync = storage.subscribe?.(key, (newValue) => {\n\t\t\t\tsubject.next(read(newValue));\n\t\t\t});\n\t\t}\n\t\tobservers++;\n\t\tconst subscription = subject.subscribe(subscriber);\n\t\treturn () => {\n\t\t\tsubscription.unsubscribe();\n\t\t\tobservers--;\n\t\t\tif (observers === 0) stopSync?.();\n\t\t};\n\t});\n\n\tconst update = (val: T) => {\n\t\tpersistBestEffort(key, val, storage);\n\t\tsubject.next(val);\n\t};\n\n\treturn {\n\t\tobservable,\n\t\tset: (val: T) => update(val),\n\t\tmutate: (transform: (prev: T) => T) => update(transform(latestValue())),\n\t\tget: () => structuredClone(latestValue()),\n\t\tdestroy: () => subject.complete(),\n\t};\n};\n\nconst parseData = <T>(str: string | null, defaultValue: T): T => {\n\ttry {\n\t\tif (str) return JSON.parse(str);\n\t} catch {\n\t\t// invalid data\n\t}\n\treturn defaultValue;\n};\n\nconst persistBestEffort = <T>(\n\tkey: string,\n\tval: T,\n\tstorage: SyncableStorage,\n) => {\n\tconst str = JSON.stringify(val);\n\ttry {\n\t\tstorage.setItem(key, str);\n\t} catch {}\n};\n","import { isWalletPlatform } from \"../utils/isWalletPlatform\";\nimport { cookieStorage } from \"../utils/storage\";\nimport { getWalletAccountId } from \"../utils/WalletAccountId\";\nimport {\n\tisValidWalletId,\n\tparseWalletId,\n\tWALLET_CONNECT_WALLET_ID,\n\ttype WalletId,\n} from \"../utils/WalletId\";\nimport type {\n\tCachedAccount,\n\tCachedWallet,\n\tKheopskitStoreData,\n\tWalletPlatform,\n} from \"./types\";\n\n/**\n * Compact wire format for the cookie-persisted store (`CompactStoreV1`).\n *\n * Cookies are size-constrained (~4KB per cookie, sent on every request), so the\n * persisted {@link KheopskitStoreData} is encoded as terse tuples with\n * single-letter keys instead of raw JSON. This module owns that format: the\n * encoder, the defensive decoder, and the lazy migration from the legacy\n * verbose-JSON cookies written by older versions.\n *\n * Any change here is a compatibility question — new fields must be optional and\n * decoding must keep accepting everything older versions wrote (or degrade to\n * \"start fresh\", never throw).\n */\n\n// wallet type: 0=injected, 1=walletconnect\ntype CompactWalletEntry = [WalletId, string, 0 | 1, 0 | 1];\ntype CompactPolkadotAccountType = 0 | 1 | 2 | 3;\n// platform: 0=polkadot, 1=ethereum, 2=solana\ntype CompactPlatformCode = 0 | 1 | 2;\ntype CompactAccountEntry = [\n\tWalletId,\n\tstring,\n\tstring | null,\n\tnumber | null,\n\tCompactPolkadotAccountType | null,\n\t// Platform code. Newly written entries always include it (the WalletConnect\n\t// connector's walletId is platform-less, so platform can't be derived from\n\t// it); absent in entries written by older versions, where it's derived from\n\t// the walletId instead.\n\t(CompactPlatformCode | null)?,\n];\n\ntype CompactStoreV1 = {\n\tv: 1;\n\t// remembered\n\tr?: WalletId[];\n\t// wallets: [id, name, isConnected(0|1), type(0=injected,1=walletconnect)?]\n\tw?: CompactWalletEntry[];\n\t// accounts: [walletId, address, name?, chainId?, polkadotType?, platform?]\n\ta?: CompactAccountEntry[];\n};\n\nconst EMPTY_STORE_DATA: KheopskitStoreData = {};\n\ntype PreV6StoreData = KheopskitStoreData & { autoReconnect?: unknown };\n\nexport const migratePreV6StoreData = (\n\tdata: PreV6StoreData,\n): KheopskitStoreData => {\n\tif (data?.autoReconnect === undefined) return data;\n\tconst { autoReconnect, ...rest } = data;\n\treturn rest.remembered === undefined && Array.isArray(autoReconnect)\n\t\t? { ...rest, remembered: autoReconnect }\n\t\t: rest;\n};\n\nconst toCompactPolkadotAccountType = (\n\ttype: CachedAccount[\"polkadotAccountType\"],\n): CompactPolkadotAccountType | null => {\n\tswitch (type) {\n\t\tcase \"sr25519\":\n\t\t\treturn 0;\n\t\tcase \"ed25519\":\n\t\t\treturn 1;\n\t\tcase \"ecdsa\":\n\t\t\treturn 2;\n\t\tcase \"ethereum\":\n\t\t\treturn 3;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n\nconst fromCompactPolkadotAccountType = (\n\ttype: CompactPolkadotAccountType | null | undefined,\n): CachedAccount[\"polkadotAccountType\"] => {\n\tswitch (type) {\n\t\tcase 0:\n\t\t\treturn \"sr25519\";\n\t\tcase 1:\n\t\t\treturn \"ed25519\";\n\t\tcase 2:\n\t\t\treturn \"ecdsa\";\n\t\tcase 3:\n\t\t\treturn \"ethereum\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n};\n\nconst toCompactPlatform = (platform: WalletPlatform): CompactPlatformCode => {\n\tswitch (platform) {\n\t\tcase \"polkadot\":\n\t\t\treturn 0;\n\t\tcase \"ethereum\":\n\t\t\treturn 1;\n\t\tcase \"solana\":\n\t\t\treturn 2;\n\t}\n};\n\nconst fromCompactPlatform = (\n\tcode: CompactPlatformCode | null | undefined,\n): WalletPlatform | undefined => {\n\tswitch (code) {\n\t\tcase 0:\n\t\t\treturn \"polkadot\";\n\t\tcase 1:\n\t\t\treturn \"ethereum\";\n\t\tcase 2:\n\t\t\treturn \"solana\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n};\n\nconst isCompactStore = (value: unknown): value is CompactStoreV1 => {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tif (\"cachedWallets\" in value || \"cachedAccounts\" in value) return false;\n\treturn \"v\" in value || \"w\" in value || \"a\" in value || \"r\" in value;\n};\n\nconst toCompactStore = (data: KheopskitStoreData): CompactStoreV1 => {\n\tconst wallets = data.cachedWallets?.map(\n\t\t(wallet): CompactWalletEntry => [\n\t\t\twallet.id,\n\t\t\twallet.name,\n\t\t\twallet.isConnected ? 1 : 0,\n\t\t\twallet.type === \"walletconnect\" ? 1 : 0,\n\t\t],\n\t);\n\n\tconst accounts = data.cachedAccounts?.map(\n\t\t(account): CompactAccountEntry => [\n\t\t\taccount.walletId,\n\t\t\taccount.address,\n\t\t\taccount.name ?? null,\n\t\t\taccount.chainId ?? null,\n\t\t\ttoCompactPolkadotAccountType(account.polkadotAccountType),\n\t\t\ttoCompactPlatform(account.platform),\n\t\t],\n\t);\n\n\treturn {\n\t\tv: 1,\n\t\tr: data.remembered,\n\t\tw: wallets?.length ? wallets : undefined,\n\t\ta: accounts?.length ? accounts : undefined,\n\t};\n};\n\nconst fromCompactStore = (data: CompactStoreV1): KheopskitStoreData => {\n\tconst walletNameMap = new Map<WalletId, string>();\n\n\t// Decode defensively: a compact payload may be malformed (older/corrupt\n\t// cookie, hand-edited). Skip entries with an unparseable wallet id rather\n\t// than throwing, which would crash store initialisation.\n\tconst wallets: CachedWallet[] = [];\n\tfor (const item of Array.isArray(data.w) ? data.w : []) {\n\t\tif (!Array.isArray(item)) continue;\n\t\tconst [id, name, isConnected, type] = item;\n\t\tif (!isValidWalletId(id)) continue;\n\t\tconst isWalletConnect = id === WALLET_CONNECT_WALLET_ID;\n\t\tconst walletType = type === 1 ? \"walletconnect\" : \"injected\";\n\t\t// Keep id/type consistent: the platform-less connector uses the fixed WC\n\t\t// id; everything else is a platform-prefixed injected wallet. Drop stale\n\t\t// mismatches (e.g. per-platform WC ids from older versions).\n\t\tif (isWalletConnect !== (walletType === \"walletconnect\")) continue;\n\t\twalletNameMap.set(id, name);\n\t\twallets.push({\n\t\t\tid,\n\t\t\tplatform: isWalletConnect ? undefined : parseWalletId(id).platform,\n\t\t\ttype: walletType,\n\t\t\tname,\n\t\t\tisConnected: isConnected === 1,\n\t\t});\n\t}\n\n\tconst accounts: CachedAccount[] = [];\n\tfor (const item of Array.isArray(data.a) ? data.a : []) {\n\t\tif (!Array.isArray(item)) continue;\n\t\tconst [\n\t\t\twalletId,\n\t\t\taddress,\n\t\t\tname,\n\t\t\tchainId,\n\t\t\tpolkadotAccountType,\n\t\t\tplatformCode,\n\t\t] = item;\n\t\tif (!isValidWalletId(walletId) || typeof address !== \"string\" || !address)\n\t\t\tcontinue;\n\t\t// Prefer the explicit platform code; fall back to deriving it from the\n\t\t// walletId for entries written before the code existed (never WC ones).\n\t\tconst platform =\n\t\t\tplatformCode != null\n\t\t\t\t? fromCompactPlatform(platformCode)\n\t\t\t\t: walletId === WALLET_CONNECT_WALLET_ID\n\t\t\t\t\t? undefined\n\t\t\t\t\t: parseWalletId(walletId).platform;\n\t\tif (!isWalletPlatform(platform)) continue;\n\t\taccounts.push({\n\t\t\tid: getWalletAccountId(walletId, address),\n\t\t\tplatform,\n\t\t\taddress,\n\t\t\tname: name ?? undefined,\n\t\t\tchainId: chainId ?? undefined,\n\t\t\tpolkadotAccountType:\n\t\t\t\tplatform === \"polkadot\"\n\t\t\t\t\t? fromCompactPolkadotAccountType(polkadotAccountType)\n\t\t\t\t\t: undefined,\n\t\t\twalletId,\n\t\t\twalletName: walletNameMap.get(walletId) ?? walletId,\n\t\t});\n\t}\n\n\treturn {\n\t\tremembered: data.r,\n\t\tcachedWallets: wallets,\n\t\tcachedAccounts: accounts,\n\t};\n};\n\nconst decodeStore = (raw: string, fallback: KheopskitStoreData) => {\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\tif (isCompactStore(parsed)) return fromCompactStore(parsed);\n\t\treturn migratePreV6StoreData(parsed as PreV6StoreData);\n\t} catch {\n\t\treturn fallback;\n\t}\n};\n\nconst encodeStore = (data: KheopskitStoreData): string =>\n\tJSON.stringify(toCompactStore(data));\n\n/**\n * Cookie storage that transparently encodes/decodes {@link CompactStoreV1},\n * migrating legacy verbose-JSON cookies to the compact format on first read.\n */\nexport const createCompactCookieStorage = (initialCookies?: string) => {\n\tconst base = cookieStorage(initialCookies);\n\n\treturn {\n\t\tgetItem: (key: string) => {\n\t\t\tconst raw = base.getItem(key);\n\t\t\tif (!raw) return null;\n\t\t\tconst expanded = decodeStore(raw, EMPTY_STORE_DATA);\n\t\t\tif (typeof document !== \"undefined\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\t\t\t\tif (!isCompactStore(parsed)) {\n\t\t\t\t\t\tbase.setItem(key, encodeStore(expanded));\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore malformed cookie during migration\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn JSON.stringify(expanded);\n\t\t},\n\t\tsetItem: (key: string, value: string) => {\n\t\t\tconst expanded = decodeStore(value, EMPTY_STORE_DATA);\n\t\t\tbase.setItem(key, encodeStore(expanded));\n\t\t},\n\t\tremoveItem: base.removeItem,\n\t\tsubscribe: (key: string, callback: (value: string | null) => void) => {\n\t\t\tconst unsubscribe = base.subscribe?.(key, (value) => {\n\t\t\t\tif (!value) {\n\t\t\t\t\tcallback(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst expanded = decodeStore(value, EMPTY_STORE_DATA);\n\t\t\t\tcallback(JSON.stringify(expanded));\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tunsubscribe?.();\n\t\t\t};\n\t\t},\n\t};\n};\n","import { uniq } from \"lodash-es\";\nimport { createStore } from \"../utils/createStore\";\nimport { isWalletPlatform } from \"../utils/isWalletPlatform\";\nimport { type SyncableStorage, safeLocalStorage } from \"../utils/storage\";\nimport {\n\tisValidWalletId,\n\tparseWalletId,\n\tWALLET_CONNECT_WALLET_ID,\n\ttype WalletId,\n} from \"../utils/WalletId\";\nimport {\n\tcreateCompactCookieStorage,\n\tmigratePreV6StoreData,\n} from \"./compactStore\";\nimport { DEFAULT_STORAGE_KEY } from \"./config\";\nimport type {\n\tCachedAccount,\n\tCachedWallet,\n\tKheopskitStore,\n\tKheopskitStoreData,\n} from \"./types\";\n\nexport type { KheopskitStore } from \"./types\";\n\nconst DEFAULT_SETTINGS: KheopskitStoreData = {};\n\n/**\n * Validates a cached wallet read from persisted storage. Cached state may have\n * been written by an older (or corrupted) version with a different shape, so we\n * drop anything that wouldn't survive hydration/sort rather than letting it\n * throw at render time. Only the fields downstream code relies on are checked.\n */\nconst isValidCachedWallet = (value: unknown): value is CachedWallet => {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst w = value as Record<string, unknown>;\n\tif (!isValidWalletId(w.id)) return false;\n\tif (typeof w.name !== \"string\" || typeof w.isConnected !== \"boolean\")\n\t\treturn false;\n\t// The WalletConnect connector is platform-less with a fixed id; drop stale\n\t// per-platform WC entries written by older versions.\n\tif (w.type === \"walletconnect\")\n\t\treturn w.id === WALLET_CONNECT_WALLET_ID && w.platform === undefined;\n\treturn w.type === \"injected\" && isWalletPlatform(w.platform);\n};\n\n/** Validates a cached account read from persisted storage. See {@link isValidCachedWallet}. */\nconst isValidCachedAccount = (value: unknown): value is CachedAccount => {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst a = value as Record<string, unknown>;\n\treturn (\n\t\ttypeof a.id === \"string\" &&\n\t\t!!a.id &&\n\t\tisWalletPlatform(a.platform) &&\n\t\ttypeof a.address === \"string\" &&\n\t\t!!a.address &&\n\t\tisValidWalletId(a.walletId) &&\n\t\ttypeof a.walletName === \"string\"\n\t);\n};\n\ntype CreateKheopskitStoreOptions = {\n\t/**\n\t * Storage backend to persist into. When provided, it takes precedence over\n\t * `ssrCookies` and localStorage.\n\t */\n\tstorage?: SyncableStorage;\n\t/**\n\t * Cookie string for SSR hydration.\n\t * When provided, uses cookieStorage instead of localStorage.\n\t */\n\tssrCookies?: string;\n\t/**\n\t * Custom storage key to namespace the stored data.\n\t * @default \"kheopskit\"\n\t */\n\tstorageKey?: string;\n};\n\n/**\n * Creates a kheopskit store with the appropriate storage backend.\n * Uses the given `storage` when provided, else cookieStorage when ssrCookies is\n * provided (for SSR hydration), otherwise safeLocalStorage.\n *\n * @param options - Configuration options for the store\n */\nexport const createKheopskitStore = (\n\toptions: CreateKheopskitStoreOptions = {},\n): KheopskitStore => {\n\tconst { ssrCookies, storageKey = DEFAULT_STORAGE_KEY } = options;\n\tconst storage =\n\t\toptions.storage ??\n\t\t(ssrCookies !== undefined\n\t\t\t? createCompactCookieStorage(ssrCookies)\n\t\t\t: safeLocalStorage);\n\tconst store = createStore(\n\t\tstorageKey,\n\t\tDEFAULT_SETTINGS,\n\t\tstorage,\n\t\tmigratePreV6StoreData,\n\t);\n\n\tconst rememberWallet = (walletId: WalletId) => {\n\t\tparseWalletId(walletId); // validate walletId\n\t\tstore.mutate((prev) => ({\n\t\t\t...prev,\n\t\t\tremembered: uniq((prev.remembered ?? []).concat(walletId)),\n\t\t}));\n\t};\n\n\tconst forgetWallet = (walletId: WalletId) => {\n\t\tstore.mutate((prev) => ({\n\t\t\t...prev,\n\t\t\tremembered: uniq((prev.remembered ?? []).filter((id) => id !== walletId)),\n\t\t}));\n\t};\n\n\tconst getCachedState = () => {\n\t\t// `store.get()` returns whatever JSON was persisted — it may be from an\n\t\t// older version, a different shape, or outright corrupt. Read defensively:\n\t\t// coerce non-objects/arrays to empty and drop any entry that fails\n\t\t// validation, so stale cache degrades to \"start fresh\" instead of throwing\n\t\t// during hydration (which renders eagerly, so a throw blanks the dapp).\n\t\tconst data = store.get() as Partial<KheopskitStoreData> | null | undefined;\n\t\tconst cachedWallets = Array.isArray(data?.cachedWallets)\n\t\t\t? data.cachedWallets\n\t\t\t: [];\n\t\tconst cachedAccounts = Array.isArray(data?.cachedAccounts)\n\t\t\t? data.cachedAccounts\n\t\t\t: [];\n\t\treturn {\n\t\t\twallets: cachedWallets.filter(isValidCachedWallet),\n\t\t\taccounts: cachedAccounts.filter(isValidCachedAccount),\n\t\t};\n\t};\n\n\tconst setCachedState = (\n\t\twallets: CachedWallet[],\n\t\taccounts: CachedAccount[],\n\t) => {\n\t\tstore.mutate((prev) => ({\n\t\t\t...prev,\n\t\t\tcachedWallets: wallets,\n\t\t\tcachedAccounts: accounts,\n\t\t}));\n\t};\n\n\treturn {\n\t\tobservable: store.observable,\n\t\trememberWallet,\n\t\tforgetWallet,\n\t\tgetCachedState,\n\t\tsetCachedState,\n\t\tdestroy: store.destroy,\n\t};\n};\n\n/**\n * Cached default store instance, anchored on globalThis so it stays a single\n * instance even if this module is duplicated across bundle chunks (e.g. CJS\n * subpath entries). Lazily initialized on first access to be SSR-safe.\n */\nconst DEFAULT_STORE_SYMBOL = Symbol.for(\"kheopskit.defaultStore\");\n\n/**\n * Gets the default store, creating it on first access.\n * Uses localStorage on client, noop on server.\n * Lazily initialized to avoid SSR issues with module-level code.\n */\nexport const getDefaultStore = (): KheopskitStore => {\n\tconst g = globalThis as unknown as Record<symbol, KheopskitStore | undefined>;\n\tif (!g[DEFAULT_STORE_SYMBOL]) {\n\t\tg[DEFAULT_STORE_SYMBOL] = createKheopskitStore();\n\t}\n\treturn g[DEFAULT_STORE_SYMBOL];\n};\n","import {\n\tcombineLatest,\n\tfilter,\n\tmap,\n\tmergeMap,\n\tObservable,\n\tof,\n\tshareReplay,\n\ttake,\n\ttap,\n} from \"rxjs\";\nimport { sortWallets } from \"../utils/sortWallets\";\nimport { KheopskitError } from \"./errors\";\nimport { createReconnectPolicy, reconnectAccepts } from \"./reconnectPolicy\";\nimport type { KheopskitStore } from \"./store\";\nimport type {\n\tBaseWallet,\n\tConnectOptions,\n\tKheopskitConfig,\n\tPlatformContext,\n\tWalletConnectWallet,\n} from \"./types\";\nimport { isInjectedWallet } from \"./types\";\n\nexport const getWallets$ = (config: KheopskitConfig, store: KheopskitStore) => {\n\t// lock the list of wallets to auto reconnect on first call\n\tconst rememberedWalletIds$ = store.observable.pipe(\n\t\tmap((s) => s.remembered ?? []),\n\t\ttake(1),\n\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t);\n\n\treturn new Observable<(BaseWallet | WalletConnectWallet)[]>((subscriber) => {\n\t\tconst ctx: PlatformContext = { config, store };\n\t\tconst observables = config.platforms.map((plugin) =>\n\t\t\tplugin.getWallets$(ctx),\n\t\t);\n\n\t\tconst reconnectPolicy = createReconnectPolicy();\n\n\t\tconst settleOnUserCall = <W extends BaseWallet>(wallet: W): W => ({\n\t\t\t...wallet,\n\t\t\tconnect: (options?: ConnectOptions) => {\n\t\t\t\treconnectPolicy.settle(wallet.id);\n\t\t\t\treturn wallet.connect(options);\n\t\t\t},\n\t\t\tdisconnect: () => {\n\t\t\t\treconnectPolicy.settle(wallet.id);\n\t\t\t\treturn wallet.disconnect();\n\t\t\t},\n\t\t});\n\n\t\tconst platformWallets$ = observables.length\n\t\t\t? combineLatest(observables).pipe(map((wallets) => wallets.flat()))\n\t\t\t: of<BaseWallet[]>([]);\n\n\t\t// The single, platform-less WalletConnect connector is appended here (not\n\t\t// emitted per platform). It sorts last (see sortWallets).\n\t\tconst walletConnect$ = config.walletConnect?.getWallet$(ctx);\n\t\tconst unsortedWallets$: Observable<(BaseWallet | WalletConnectWallet)[]> =\n\t\t\twalletConnect$\n\t\t\t\t? combineLatest([platformWallets$, walletConnect$]).pipe(\n\t\t\t\t\t\tmap(([platformWallets, walletConnect]) =>\n\t\t\t\t\t\t\twalletConnect\n\t\t\t\t\t\t\t\t? [...platformWallets, walletConnect]\n\t\t\t\t\t\t\t\t: platformWallets,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t: platformWallets$;\n\t\tconst rawWallets$ = unsortedWallets$.pipe(\n\t\t\tmap((all) => all.sort(sortWallets)),\n\t\t);\n\n\t\tconst wallets$ = rawWallets$.pipe(\n\t\t\tmap((wallets) =>\n\t\t\t\twallets.map((wallet) =>\n\t\t\t\t\tisInjectedWallet(wallet) ? settleOnUserCall(wallet) : wallet,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t\tconst reconnect = async (wallet: BaseWallet) => {\n\t\t\ttry {\n\t\t\t\tawait reconnectPolicy.attempt(wallet.id, () => wallet.connect());\n\t\t\t} catch (err) {\n\t\t\t\tif (subscriber.closed) return;\n\t\t\t\tif (err instanceof KheopskitError) {\n\t\t\t\t\tif (err.code === \"USER_REJECTED\") store.forgetWallet(wallet.id);\n\t\t\t\t\tif (err.code === \"USER_REJECTED\" || err.code === \"ABORTED\")\n\t\t\t\t\t\treconnectPolicy.settle(wallet.id);\n\t\t\t\t}\n\t\t\t\tif (config.debug)\n\t\t\t\t\tconsole.debug(\"[kheopskit] reconnect of %s failed\", wallet.id, err);\n\t\t\t}\n\t\t};\n\n\t\tconst subWallets = wallets$.subscribe(subscriber);\n\t\tif (subscriber.closed) return subWallets;\n\n\t\tconst subAutoReconnect = combineLatest([rawWallets$, rememberedWalletIds$])\n\t\t\t.pipe(\n\t\t\t\tfilter(\n\t\t\t\t\t([, walletIds]) =>\n\t\t\t\t\t\tconfig.autoReconnect !== false && walletIds.length > 0,\n\t\t\t\t),\n\t\t\t\tmergeMap(([wallets, walletIds]) =>\n\t\t\t\t\twallets\n\t\t\t\t\t\t.filter(isInjectedWallet)\n\t\t\t\t\t\t.filter((wallet) => walletIds.includes(wallet.id)),\n\t\t\t\t),\n\t\t\t\ttap((wallet) => {\n\t\t\t\t\tif (wallet.status === \"connected\") reconnectPolicy.settle(wallet.id);\n\t\t\t\t}),\n\t\t\t\tfilter(\n\t\t\t\t\t(wallet) =>\n\t\t\t\t\t\twallet.status === \"disconnected\" &&\n\t\t\t\t\t\treconnectAccepts(config.autoReconnect, wallet),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.subscribe(reconnect);\n\n\t\treturn () => {\n\t\t\tsubAutoReconnect.unsubscribe();\n\t\t\tsubWallets.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n};\n","import {\n\tasapScheduler,\n\tcombineLatest,\n\tdebounceTime,\n\tdistinctUntilChanged,\n\tfilter,\n\tmap,\n\tObservable,\n\tof,\n\tshareReplay,\n\tstartWith,\n\tswitchMap,\n\ttake,\n\ttap,\n} from \"rxjs\";\nimport {\n\tcreateAccountHydrationBuffer,\n\tcreateHydrationBuffer,\n} from \"../utils/createHydrationBuffer\";\nimport { serializeAccount, serializeWallet } from \"../utils/hydrateState\";\nimport { getCachedIcon, setCachedIcons } from \"../utils/iconCache\";\nimport { logObservable } from \"../utils/logObservable\";\nimport { pageLoaded$ } from \"../utils/pageLoad\";\nimport { sortAccounts } from \"../utils/sortAccounts\";\nimport { sortWallets } from \"../utils/sortWallets\";\nimport type { WalletId } from \"../utils/WalletId\";\nimport { type AccountsFrame, getAccounts$ } from \"./accounts\";\nimport { resolveConfig } from \"./config\";\nimport { abortedError, walletPendingError } from \"./errors\";\nimport { getHydratedSnapshot } from \"./hydration\";\nimport { createKheopskitStore } from \"./store\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tCachedAccount,\n\tCachedWallet,\n\tKheopskitConfig,\n\tKheopskitPlatform,\n\tKheopskitState,\n\tWalletConnectWallet,\n} from \"./types\";\nimport { isInjectedWallet, isWalletConnectWallet } from \"./types\";\nimport { getWallets$ } from \"./wallets\";\n\nexport type { KheopskitConfig, KheopskitState } from \"./types\";\n\n/** Options for {@link getKheopskit$}. */\nexport type GetKheopskitOptions = {\n\t/**\n\t * Cookie string for SSR hydration. When provided, state is read from cookies\n\t * instead of localStorage so the server can hydrate without a flash. Pass the\n\t * request's `cookie` header.\n\t */\n\tssrCookies?: string;\n\t/**\n\t * An existing store to reuse instead of creating one.\n\t */\n\tstore?: ReturnType<typeof createKheopskitStore>;\n};\n\nexport const getKheopskit$ = <\n\tconst P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n>(\n\tconfig?: Partial<KheopskitConfig<P>>,\n\toptions: GetKheopskitOptions = {},\n): Observable<KheopskitState<P>> => {\n\tconst { ssrCookies, store: existingStore } = options;\n\tconst kc = resolveConfig(config);\n\tconst store =\n\t\texistingStore ??\n\t\tcreateKheopskitStore({ ssrCookies, storageKey: kc.storageKey });\n\n\tif (kc.debug) console.debug(\"[kheopskit] config\", kc);\n\n\t// Warn about SSR environment without cookies\n\tif (kc.debug && typeof window === \"undefined\" && ssrCookies === undefined) {\n\t\tconsole.warn(\n\t\t\t\"[kheopskit] Running on server without `ssrCookies`. \" +\n\t\t\t\t\"Wallet state will not be hydrated. Pass cookies for SSR support.\",\n\t\t);\n\t}\n\n\t// Get cached state for hydration (same snapshot the React provider builds)\n\tconst { wallets: cachedWallets, accounts: cachedAccounts } =\n\t\tgetHydratedSnapshot(store, kc, { icons: true });\n\n\tif (kc.debug && cachedWallets.length > 0) {\n\t\tconsole.debug(\"[kheopskit] hydrating from cache:\", {\n\t\t\twallets: cachedWallets.length,\n\t\t\taccounts: cachedAccounts.length,\n\t\t});\n\t}\n\n\treturn new Observable<KheopskitState>((subscriber) => {\n\t\tlet latest: KheopskitState | undefined;\n\t\tlet closed = false;\n\t\tconst waiters = new Set<StateWaiter>();\n\t\tconst liveWaiters = new Set<(state: KheopskitState | undefined) => void>();\n\t\tconst wrapped = new WeakMap<\n\t\t\tBaseWallet | WalletConnectWallet,\n\t\t\tBaseWallet | WalletConnectWallet\n\t\t>();\n\n\t\tconst abandon = (waiter: StateWaiter) => {\n\t\t\twaiters.delete(waiter);\n\t\t\tif (waiter.isConnected)\n\t\t\t\twaiter.reject(abortedError(waiter.walletId, \"connect\"));\n\t\t\telse waiter.resolve();\n\t\t};\n\n\t\tconst settleIn = (waiter: StateWaiter, state: KheopskitState) => {\n\t\t\tconst wallet = state.wallets.find((w) => w.id === waiter.walletId);\n\t\t\tif (!wallet || wallet.isConnected === waiter.isConnected) {\n\t\t\t\twaiters.delete(waiter);\n\t\t\t\twaiter.resolve();\n\t\t\t}\n\t\t};\n\n\t\tconst supersede = (walletId: WalletId, isConnected: boolean) => {\n\t\t\tfor (const waiter of waiters)\n\t\t\t\tif (waiter.walletId === walletId && waiter.isConnected !== isConnected)\n\t\t\t\t\tabandon(waiter);\n\t\t};\n\n\t\tconst whenState = (walletId: WalletId, isConnected: boolean) =>\n\t\t\tnew Promise<void>((resolve, reject) => {\n\t\t\t\tconst waiter = { walletId, isConnected, resolve, reject };\n\t\t\t\twaiters.add(waiter);\n\t\t\t\tif (latest) settleIn(waiter, latest);\n\t\t\t\tif (closed && waiters.has(waiter)) abandon(waiter);\n\t\t\t});\n\n\t\tconst whenLive = (walletId: WalletId, signal: AbortSignal | undefined) =>\n\t\t\tnew Promise<BaseWallet | WalletConnectWallet>((resolve, reject) => {\n\t\t\t\tconst settle = (finish: () => void) => {\n\t\t\t\t\tliveWaiters.delete(check);\n\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tfinish();\n\t\t\t\t};\n\t\t\t\tconst onAbort = () =>\n\t\t\t\t\tsettle(() => reject(abortedError(walletId, \"connect\")));\n\t\t\t\tconst check = (state: KheopskitState | undefined) => {\n\t\t\t\t\tif (!state) return onAbort();\n\t\t\t\t\tconst live = state.wallets.find(\n\t\t\t\t\t\t(w) => w.id === walletId && !w.isPlaceholder,\n\t\t\t\t\t);\n\t\t\t\t\tif (live) settle(() => resolve(live));\n\t\t\t\t\telse if (!state.isHydrating)\n\t\t\t\t\t\tsettle(() => reject(walletPendingError(walletId)));\n\t\t\t\t};\n\t\t\t\tif (closed || signal?.aborted) return onAbort();\n\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\tliveWaiters.add(check);\n\t\t\t\tif (latest) check(latest);\n\t\t\t});\n\n\t\tconst deferToLive = (\n\t\t\tplaceholder: BaseWallet | WalletConnectWallet,\n\t\t): BaseWallet | WalletConnectWallet => ({\n\t\t\t...placeholder,\n\t\t\tconnect: async (options) => {\n\t\t\t\tconst live = await whenLive(placeholder.id, options?.signal);\n\t\t\t\tif (closed) throw abortedError(placeholder.id, \"connect\");\n\t\t\t\tawait live.connect(options);\n\t\t\t},\n\t\t});\n\n\t\tconst settleWithState = (\n\t\t\twallet: BaseWallet | WalletConnectWallet,\n\t\t): BaseWallet | WalletConnectWallet => {\n\t\t\tconst existing = wrapped.get(wallet);\n\t\t\tif (existing) return existing;\n\t\t\tif (wallet.isPlaceholder) {\n\t\t\t\tconst deferred = deferToLive(wallet);\n\t\t\t\twrapped.set(wallet, deferred);\n\t\t\t\treturn deferred;\n\t\t\t}\n\t\t\tif (!isInjectedWallet(wallet)) return wallet;\n\t\t\tconst settled: BaseWallet = {\n\t\t\t\t...wallet,\n\t\t\t\tconnect: async (options) => {\n\t\t\t\t\tif (closed) throw abortedError(wallet.id, \"connect\");\n\t\t\t\t\tawait wallet.connect(options);\n\t\t\t\t\tsupersede(wallet.id, true);\n\t\t\t\t\tawait whenState(wallet.id, true);\n\t\t\t\t},\n\t\t\t\tdisconnect: async () => {\n\t\t\t\t\tif (closed) throw abortedError(wallet.id, \"disconnect\");\n\t\t\t\t\tawait wallet.disconnect();\n\t\t\t\t\tsupersede(wallet.id, false);\n\t\t\t\t\tawait whenState(wallet.id, false);\n\t\t\t\t},\n\t\t\t};\n\t\t\twrapped.set(wallet, settled);\n\t\t\treturn settled;\n\t\t};\n\n\t\t// Get live wallets and accounts\n\t\tconst liveWallets$ = getWallets$(kc, store);\n\t\tconst accountFrames$ = getAccounts$(kc, liveWallets$);\n\t\tconst liveAccounts$ = accountFrames$.pipe(\n\t\t\tmap(({ accounts }) => accounts.map(asLive)),\n\t\t);\n\n\t\tconst isDiscovering$ = pageLoaded$.pipe(\n\t\t\tswitchMap((loaded) =>\n\t\t\t\tloaded\n\t\t\t\t\t? liveWallets$.pipe(\n\t\t\t\t\t\t\ttake(1),\n\t\t\t\t\t\t\tmap(() => false),\n\t\t\t\t\t\t)\n\t\t\t\t\t: of(true),\n\t\t\t),\n\t\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t);\n\n\t\tconst reconnecting = cachedWallets.filter((w) => w.status === \"connecting\");\n\t\tconst hydrationSettled$ = combineLatest([\n\t\t\tliveWallets$,\n\t\t\taccountFrames$.pipe(startWith(noAnswerYet)),\n\t\t\tisDiscovering$,\n\t\t\tstore.observable.pipe(\n\t\t\t\tmap((s) => s.remembered ?? []),\n\t\t\t\ttake(1),\n\t\t\t),\n\t\t]).pipe(\n\t\t\tmap(\n\t\t\t\t([wallets, { accounts, answered }, isDiscovering, remembered]) =>\n\t\t\t\t\t!isDiscovering &&\n\t\t\t\t\treconnecting.every((cached) =>\n\t\t\t\t\t\treconnectSettled(cached, {\n\t\t\t\t\t\t\twallets,\n\t\t\t\t\t\t\taccounts,\n\t\t\t\t\t\t\tanswered,\n\t\t\t\t\t\t\tcachedAccounts,\n\t\t\t\t\t\t\tremembered,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t),\n\t\t\tdebounceTime(0, asapScheduler),\n\t\t\tdistinctUntilChanged(),\n\t\t);\n\n\t\t// Apply hydration buffer to wallets\n\t\tconst bufferedWallets$ = createHydrationBuffer(\n\t\t\tcachedWallets,\n\t\t\tliveWallets$.pipe(map((wallets) => wallets.map(asLive))),\n\t\t\tkc.hydrationGracePeriod,\n\t\t\tkc.hydrationTimeout,\n\t\t\t(w) => w.id,\n\t\t\thydrationSettled$,\n\t\t\t(live, cached) => {\n\t\t\t\tconst status = sessionRestoring(live, cached)\n\t\t\t\t\t? \"connecting\"\n\t\t\t\t\t: live.status;\n\t\t\t\treturn {\n\t\t\t\t\t...live,\n\t\t\t\t\tstatus,\n\t\t\t\t\tisConnected: status === \"connected\",\n\t\t\t\t\ticon: cached.icon || getCachedIcon(cached.id) || live.icon,\n\t\t\t\t};\n\t\t\t},\n\t\t\t// Transform cached-only items: add icon from localStorage cache\n\t\t\t(cached) => ({\n\t\t\t\t...cached,\n\t\t\t\ticon: cached.icon || getCachedIcon(cached.id) || \"\",\n\t\t\t}),\n\t\t);\n\n\t\t// Apply hydration buffer to accounts\n\t\tconst bufferedAccounts$ = createAccountHydrationBuffer(\n\t\t\tcachedAccounts,\n\t\t\tliveAccounts$,\n\t\t\tkc.hydrationGracePeriod,\n\t\t\tkc.hydrationTimeout,\n\t\t\t(a) => a.walletId,\n\t\t\thydrationSettled$,\n\t\t);\n\n\t\t// Share the buffered streams so the main and persistence subscriptions\n\t\t// below reuse a single hydration pipeline (timers, isHydrating state)\n\t\t// instead of running the buffering twice.\n\t\tconst sharedWallets$ = bufferedWallets$.pipe(\n\t\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t);\n\t\tconst sharedAccounts$ = bufferedAccounts$.pipe(\n\t\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t);\n\n\t\t// Combine buffered wallets and accounts\n\t\tconst subscription = combineLatest({\n\t\t\twallets: sharedWallets$,\n\t\t\taccounts: sharedAccounts$,\n\t\t\tisDiscovering: isDiscovering$,\n\t\t})\n\t\t\t.pipe(\n\t\t\t\tmap(({ wallets, accounts, isDiscovering }) => {\n\t\t\t\t\tif (kc.debug) {\n\t\t\t\t\t\tconsole.debug(\"[kheopskit] hydration state\", {\n\t\t\t\t\t\t\twalletsHydrating: wallets.isHydrating,\n\t\t\t\t\t\t\taccountsHydrating: accounts.isHydrating,\n\t\t\t\t\t\t\tisDiscovering,\n\t\t\t\t\t\t\twalletsConnected: wallets.items.filter((w) => w.isConnected)\n\t\t\t\t\t\t\t\t.length,\n\t\t\t\t\t\t\twalletsTotal: wallets.items.length,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// Sort on every emission with the same comparators used for the\n\t\t\t\t\t// cached initial snapshot. The hydration buffers append cached-only\n\t\t\t\t\t// items after live ones (and reconnects land out of order), so\n\t\t\t\t\t// without this the list visibly reorders as wallets come back.\n\t\t\t\t\treturn {\n\t\t\t\t\t\tconfig: kc,\n\t\t\t\t\t\twallets: [...wallets.items].sort(sortWallets).map(settleWithState),\n\t\t\t\t\t\taccounts: [...accounts.items].sort(sortAccounts),\n\t\t\t\t\t\tisHydrating: wallets.isHydrating || accounts.isHydrating,\n\t\t\t\t\t\tisDiscovering,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t\tdebounceTime(0, asapScheduler),\n\t\t\t\tdistinctUntilChanged(statesEqual),\n\t\t\t\ttap((state) => {\n\t\t\t\t\tlatest = state;\n\t\t\t\t\tfor (const check of liveWaiters) check(state);\n\t\t\t\t\tfor (const waiter of waiters) settleIn(waiter, state);\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\t// Persist state snapshot when hydration completes and state stabilizes\n\t\tconst persistSub = combineLatest({\n\t\t\twallets: sharedWallets$,\n\t\t\taccounts: sharedAccounts$,\n\t\t})\n\t\t\t.pipe(\n\t\t\t\t// Wait for hydration to complete\n\t\t\t\tfilter(\n\t\t\t\t\t({ wallets, accounts }) =>\n\t\t\t\t\t\t!wallets.isHydrating && !accounts.isHydrating,\n\t\t\t\t),\n\t\t\t\t// Debounce to avoid excessive writes\n\t\t\t\tdebounceTime(1000),\n\t\t\t\t// Only persist if the serialized snapshot would actually change.\n\t\t\t\t// Compare the persisted fields (not just ids): an Ethereum chain switch\n\t\t\t\t// keeps the same account id but changes the cached chainId, so an\n\t\t\t\t// id-only comparator would skip persisting it.\n\t\t\t\tdistinctUntilChanged((prev, curr) => {\n\t\t\t\t\tconst prevWalletKeys = prev.wallets.items.map(persistedWalletKey);\n\t\t\t\t\tconst currWalletKeys = curr.wallets.items.map(persistedWalletKey);\n\t\t\t\t\tconst prevAccountKeys = prev.accounts.items.map(accountChangeKey);\n\t\t\t\t\tconst currAccountKeys = curr.accounts.items.map(accountChangeKey);\n\t\t\t\t\treturn (\n\t\t\t\t\t\tarraysEqual(prevWalletKeys, currWalletKeys) &&\n\t\t\t\t\t\tarraysEqual(prevAccountKeys, currAccountKeys)\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.subscribe(({ wallets, accounts }) => {\n\t\t\t\tconst snapshot = persistedSnapshot(\n\t\t\t\t\twallets.items,\n\t\t\t\t\taccounts.items,\n\t\t\t\t\tstore.getCachedState(),\n\t\t\t\t);\n\n\t\t\t\tif (kc.debug) {\n\t\t\t\t\tconsole.debug(\"[kheopskit] persisting state snapshot:\", {\n\t\t\t\t\t\twallets: snapshot.wallets.length,\n\t\t\t\t\t\taccounts: snapshot.accounts.length,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tstore.setCachedState(snapshot.wallets, snapshot.accounts);\n\n\t\t\t\t// Cache wallet icons in localStorage (separate from cookies for size)\n\t\t\t\tconst icons: Record<string, string> = {};\n\t\t\t\tfor (const wallet of wallets.items) {\n\t\t\t\t\tif (wallet.icon) {\n\t\t\t\t\t\ticons[wallet.id] = wallet.icon;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetCachedIcons(icons);\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tsubscription.unsubscribe();\n\t\t\tpersistSub.unsubscribe();\n\t\t\tclosed = true;\n\t\t\tfor (const waiter of waiters) abandon(waiter);\n\t\t\tfor (const check of liveWaiters) check(undefined);\n\t\t};\n\t}).pipe(\n\t\tlogObservable(\"kheopskit$\", { enabled: kc.debug, printValue: true }),\n\t\tshareReplay({ bufferSize: 1, refCount: true }),\n\t\t// The runtime objects are the concrete per-plugin wallet/account types;\n\t\t// recover the precise KheopskitState<P> the caller's plugins imply.\n\t) as unknown as Observable<KheopskitState<P>>;\n};\n\ntype StateWaiter = {\n\twalletId: WalletId;\n\tisConnected: boolean;\n\tresolve: () => void;\n\treject: (error: unknown) => void;\n};\n\n// AppKit restores a cached WalletConnect session on its own and reports nothing\n// until it has; an injected wallet reports its attempt from its first emission.\nconst sessionRestoring = (\n\tlive: BaseWallet | WalletConnectWallet,\n\tcached: BaseWallet | WalletConnectWallet,\n): boolean =>\n\tisWalletConnectWallet(live) &&\n\tlive.status === \"disconnected\" &&\n\tcached.status === \"connecting\";\n\nconst flagged = new WeakMap<object, object>();\n\nconst asLive = <T extends object>(item: T): T & { isPlaceholder: false } => {\n\tconst existing = flagged.get(item);\n\tif (existing) return existing as T & { isPlaceholder: false };\n\tconst live = { ...item, isPlaceholder: false as const };\n\tflagged.set(item, live);\n\treturn live;\n};\n\nconst noAnswerYet: AccountsFrame = { accounts: [], answered: [] };\n\n/**\n * A remembered wallet that reads disconnected without an error is still\n * waiting for its reconnect: getWallets$ emits the wallet list before its\n * connect() flips the status to connecting.\n */\nconst reconnectSettled = (\n\tcached: BaseWallet | WalletConnectWallet,\n\tlive: AccountsFrame & {\n\t\twallets: (BaseWallet | WalletConnectWallet)[];\n\t\tcachedAccounts: BaseWalletAccount[];\n\t\tremembered: WalletId[];\n\t},\n): boolean => {\n\tconst wallet = live.wallets.find((w) => w.id === cached.id);\n\tif (!wallet) return true;\n\tconst status = sessionRestoring(wallet, cached)\n\t\t? \"connecting\"\n\t\t: wallet.status;\n\tif (status === \"connecting\") return false;\n\tif (status === \"disconnected\")\n\t\treturn wallet.error !== undefined || !live.remembered.includes(cached.id);\n\treturn (\n\t\tlive.answered.includes(cached.id) ||\n\t\t!live.cachedAccounts.some((a) => a.walletId === cached.id) ||\n\t\tlive.accounts.some((a) => a.walletId === cached.id)\n\t);\n};\n\n/**\n * A wallet still connecting keeps its previous cache entry and accounts:\n * written live it would read isConnected: false with no accounts, and the\n * next load would hydrate it as disconnected without placeholders while its\n * reconnect runs.\n */\nconst persistedSnapshot = (\n\twallets: (BaseWallet | WalletConnectWallet)[],\n\taccounts: BaseWalletAccount[],\n\tprevious: { wallets: CachedWallet[]; accounts: CachedAccount[] },\n): { wallets: CachedWallet[]; accounts: CachedAccount[] } => {\n\tconst connecting = new Set(\n\t\twallets.filter((w) => w.status === \"connecting\").map((w) => w.id),\n\t);\n\tconst connected = new Set(\n\t\twallets.filter((w) => w.isConnected).map((w) => w.id),\n\t);\n\tconst previousWallets = new Map(previous.wallets.map((w) => [w.id, w]));\n\treturn {\n\t\twallets: wallets.map(\n\t\t\t(w) =>\n\t\t\t\t(connecting.has(w.id) && previousWallets.get(w.id)) ||\n\t\t\t\tserializeWallet(w),\n\t\t),\n\t\taccounts: [\n\t\t\t...accounts\n\t\t\t\t.filter((a) => connected.has(a.walletId))\n\t\t\t\t.map(serializeAccount),\n\t\t\t...previous.accounts.filter((a) => connecting.has(a.walletId)),\n\t\t],\n\t};\n};\n\nconst arraysEqual = (a: string[], b: string[]) =>\n\ta.length === b.length && a.every((v, i) => v === b[i]);\n\n// Mutable per-platform account fields that can change without the account id\n// changing. Declared locally (not imported from the platform packages) so this\n// core entry stays free of platform SDK types — see check:isolation.\ntype EthereumAccountFields = { chainId?: number };\ntype PolkadotAccountFields = { type?: string };\ntype SolanaAccountFields = { chains?: string[] };\n\n/**\n * A signature of an account covering its id, its name, plus the\n * platform-specific fields that can change without the id changing (Ethereum\n * chainId, Polkadot key type, Solana clusters). Used to detect both UI-relevant\n * changes and changes worth re-persisting, so the two comparators can't drift\n * apart.\n */\nconst accountChangeKey = (account: BaseWalletAccount): string =>\n\t`${account.name ?? \"\"}|${accountPlatformKey(account)}`;\n\nconst accountPlatformKey = (account: BaseWalletAccount): string => {\n\tswitch (account.platform) {\n\t\tcase \"ethereum\":\n\t\t\treturn `${account.id}|${(account as EthereumAccountFields).chainId ?? \"\"}`;\n\t\tcase \"polkadot\":\n\t\t\treturn `${account.id}|${(account as PolkadotAccountFields).type ?? \"\"}`;\n\t\tcase \"solana\":\n\t\t\treturn `${account.id}|${((account as SolanaAccountFields).chains ?? []).join(\",\")}`;\n\t\tdefault:\n\t\t\treturn account.id;\n\t}\n};\n\n/** Platforms a wallet's live session carries (only the WalletConnect connector). */\nconst walletPlatforms = (wallet: BaseWallet | WalletConnectWallet): string =>\n\tisWalletConnectWallet(wallet) ? wallet.platforms.join(\",\") : \"\";\n\n/** Fields persisted to the cache for a wallet (icon is stored separately). */\nconst walletPersistKey = (wallet: BaseWallet | WalletConnectWallet): string =>\n\t`${wallet.id}|${wallet.isConnected ? 1 : 0}|${wallet.name}`;\n\n/**\n * What decides a cache write: the persisted fields plus `status`, because a\n * wallet whose kept entry was written while connecting must be rewritten live\n * once its reconnect fails, and `isConnected` reads false on both sides.\n */\nconst persistedWalletKey = (wallet: BaseWallet | WalletConnectWallet): string =>\n\t`${walletPersistKey(wallet)}|${wallet.status}`;\n\n/**\n * UI-significant signature of a wallet: the persisted fields plus icon and the\n * WalletConnect connector's `platforms` array, which drive what the UI shows but\n * aren't part of the id (icon and platforms can arrive asynchronously after\n * connect without isConnected flipping).\n */\nconst walletUiKey = (wallet: BaseWallet | WalletConnectWallet): string =>\n\t`${walletPersistKey(wallet)}|${wallet.status}|${wallet.error?.code ?? \"\"}|${wallet.icon}|${walletPlatforms(wallet)}`;\n\n/**\n * Equality check for KheopskitState to prevent unnecessary emissions. Compares\n * the UI-significant signature of every wallet and account, in order.\n */\nconst statesEqual = (a: KheopskitState, b: KheopskitState): boolean =>\n\ta.isHydrating === b.isHydrating &&\n\ta.isDiscovering === b.isDiscovering &&\n\ta.wallets.length === b.wallets.length &&\n\ta.accounts.length === b.accounts.length &&\n\ta.wallets.every((w, i) => {\n\t\tconst other = b.wallets[i];\n\t\treturn (\n\t\t\t!!other &&\n\t\t\tw.isPlaceholder === other.isPlaceholder &&\n\t\t\twalletUiKey(w) === walletUiKey(other)\n\t\t);\n\t}) &&\n\ta.accounts.every((acc, i) => {\n\t\tconst other = b.accounts[i];\n\t\treturn (\n\t\t\t!!other &&\n\t\t\tacc.isPlaceholder === other.isPlaceholder &&\n\t\t\taccountChangeKey(acc) === accountChangeKey(other)\n\t\t);\n\t});\n"],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ import { i as abortedError, s as toConnectError } from "./types-Yor672md.mjs";
2
+ import { BehaviorSubject, Observable, combineLatest, distinctUntilChanged, map, shareReplay, tap } from "rxjs";
3
+ //#region src/api/injectedWallets.ts
4
+ /**
5
+ * Compare two wallet arrays by their relevant properties (not functions).
6
+ * Shared by every platform's injected-wallets stream.
7
+ */
8
+ const walletsEqual = (a, b) => {
9
+ if (a.length !== b.length) return false;
10
+ return a.every((w, i) => w.id === b[i]?.id && w.status === b[i]?.status && w.error === b[i]?.error && w.name === b[i]?.name);
11
+ };
12
+ const join = (connecting, walletId, signal) => {
13
+ if (!signal) {
14
+ connecting.anchored = true;
15
+ return connecting.promise;
16
+ }
17
+ connecting.waiting++;
18
+ return new Promise((resolve, reject) => {
19
+ const leave = () => {
20
+ if (connecting.answered) return;
21
+ reject(abortedError(walletId, "connect"));
22
+ connecting.waiting--;
23
+ if (!connecting.anchored && connecting.waiting === 0) connecting.abort();
24
+ };
25
+ signal.addEventListener("abort", leave, { once: true });
26
+ connecting.promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", leave));
27
+ });
28
+ };
29
+ /**
30
+ * The shared engine behind every platform's injected-wallets stream: tracks
31
+ * each wallet's connection (pending attempt or live handle), shares one
32
+ * in-flight connect per wallet, persists connected ids to the store for
33
+ * auto-reconnect, and re-emits the wallet list whenever the registry or
34
+ * connection state changes.
35
+ */
36
+ const createInjectedWallets$ = (store, adapter) => new Observable((subscriber) => {
37
+ const connections$ = new BehaviorSubject(/* @__PURE__ */ new Map());
38
+ const teardown = new AbortController();
39
+ let present = /* @__PURE__ */ new Set();
40
+ const abortConnectsOfSourcesThatLeft = (sources) => {
41
+ present = new Set(sources.map((source) => adapter.getWalletId(source)));
42
+ for (const [walletId, connection] of connections$.value) if (connection.status === "connecting" && !present.has(walletId)) connection.abort();
43
+ };
44
+ const setConnection = (walletId, connection) => {
45
+ const next = new Map(connections$.value);
46
+ if (connection) next.set(walletId, connection);
47
+ else next.delete(walletId);
48
+ connections$.next(next);
49
+ };
50
+ const startConnect = (source, walletId, signal) => {
51
+ const controller = new AbortController();
52
+ const connecting = {
53
+ status: "connecting",
54
+ promise: new Promise((resolve, reject) => {
55
+ controller.signal.addEventListener("abort", () => {
56
+ setConnection(walletId, void 0);
57
+ reject(abortedError(walletId, "connect"));
58
+ }, { once: true });
59
+ new Promise((res) => res(adapter.connect(source, walletId))).then((handle) => {
60
+ connecting.answered = true;
61
+ if (controller.signal.aborted) {
62
+ adapter.releaseAbandonedHandle?.(handle, walletId);
63
+ return;
64
+ }
65
+ setConnection(walletId, {
66
+ status: "connected",
67
+ handle
68
+ });
69
+ resolve();
70
+ store.rememberWallet(walletId);
71
+ }, (error) => {
72
+ connecting.answered = true;
73
+ if (controller.signal.aborted) return;
74
+ const connectError = toConnectError(error, walletId, adapter.isUserRejection ?? (() => false));
75
+ setConnection(walletId, {
76
+ status: "disconnected",
77
+ error: connectError
78
+ });
79
+ reject(connectError);
80
+ });
81
+ }),
82
+ anchored: false,
83
+ waiting: 0,
84
+ answered: false,
85
+ abort: () => {
86
+ if (connections$.value.get(walletId) === connecting) controller.abort();
87
+ }
88
+ };
89
+ setConnection(walletId, connecting);
90
+ return join(connecting, walletId, signal);
91
+ };
92
+ const untilSettled = (disconnecting, walletId, signal) => new Promise((resolve, reject) => {
93
+ const signals = signal ? [teardown.signal, signal] : [teardown.signal];
94
+ const settle = () => {
95
+ for (const s of signals) s.removeEventListener("abort", settle);
96
+ if (signals.some((s) => s.aborted)) reject(abortedError(walletId, "connect"));
97
+ else resolve();
98
+ };
99
+ if (signals.some((s) => s.aborted)) return settle();
100
+ for (const s of signals) s.addEventListener("abort", settle, { once: true });
101
+ disconnecting.then(settle, settle);
102
+ });
103
+ const connect = (source, walletId, options) => {
104
+ if (teardown.signal.aborted || !present.has(walletId)) return Promise.reject(abortedError(walletId, "connect"));
105
+ const current = connections$.value.get(walletId);
106
+ if (current?.status === "connected") {
107
+ if (!current.disconnecting) return Promise.resolve();
108
+ return untilSettled(current.disconnecting, walletId, options?.signal).then(() => connect(source, walletId, options));
109
+ }
110
+ if (options?.signal?.aborted) return Promise.reject(abortedError(walletId, "connect"));
111
+ if (current?.status === "connecting") return join(current, walletId, options?.signal);
112
+ return startConnect(source, walletId, options?.signal);
113
+ };
114
+ const disconnect = (source, walletId) => {
115
+ const current = connections$.value.get(walletId);
116
+ if (!current || current.status === "disconnected") return Promise.resolve();
117
+ if (current.status === "connecting") {
118
+ current.abort();
119
+ return Promise.resolve();
120
+ }
121
+ if (current.disconnecting) return current.disconnecting;
122
+ store.forgetWallet(walletId);
123
+ const disconnecting = (async () => {
124
+ try {
125
+ await adapter.disconnect?.(source, walletId);
126
+ } catch (error) {
127
+ if (!teardown.signal.aborted) {
128
+ setConnection(walletId, {
129
+ status: "connected",
130
+ handle: current.handle
131
+ });
132
+ store.rememberWallet(walletId);
133
+ }
134
+ throw error;
135
+ }
136
+ if (teardown.signal.aborted) return;
137
+ setConnection(walletId, void 0);
138
+ adapter.onDisconnected?.(walletId);
139
+ })();
140
+ setConnection(walletId, {
141
+ ...current,
142
+ disconnecting
143
+ });
144
+ return disconnecting;
145
+ };
146
+ const sub = combineLatest([adapter.sources$, connections$]).pipe(tap(([sources]) => abortConnectsOfSourcesThatLeft(sources)), map(([sources, connections]) => sources.map((source) => {
147
+ const walletId = adapter.getWalletId(source);
148
+ const connection = connections.get(walletId);
149
+ const connected = connection?.status === "connected" ? connection : void 0;
150
+ return adapter.buildWallet({
151
+ source,
152
+ walletId,
153
+ handle: connected?.handle,
154
+ status: connection?.status ?? "disconnected",
155
+ error: connection?.status === "disconnected" ? connection.error : void 0,
156
+ isConnected: connected !== void 0,
157
+ connect: (options) => connect(source, walletId, options),
158
+ disconnect: () => disconnect(source, walletId)
159
+ });
160
+ })), distinctUntilChanged(walletsEqual)).subscribe(subscriber);
161
+ return () => {
162
+ teardown.abort();
163
+ for (const connection of connections$.value.values()) if (connection.status === "connecting") connection.abort();
164
+ sub.unsubscribe();
165
+ };
166
+ }).pipe(shareReplay({
167
+ refCount: true,
168
+ bufferSize: 1
169
+ }));
170
+ //#endregion
171
+ export { createInjectedWallets$ as t };
172
+
173
+ //# sourceMappingURL=injectedWallets-48L-AL1I.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injectedWallets-48L-AL1I.mjs","names":[],"sources":["../src/api/injectedWallets.ts"],"sourcesContent":["import {\n\tBehaviorSubject,\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tshareReplay,\n\ttap,\n} from \"rxjs\";\nimport type { WalletId } from \"../utils/WalletId\";\nimport { abortedError, type KheopskitError, toConnectError } from \"./errors\";\nimport type { KheopskitStore } from \"./store\";\nimport type { BaseWallet, ConnectOptions, WalletStatus } from \"./types\";\n\n/**\n * Compare two wallet arrays by their relevant properties (not functions).\n * Shared by every platform's injected-wallets stream.\n */\nconst walletsEqual = <\n\tW extends Pick<BaseWallet, \"id\" | \"status\" | \"error\" | \"name\">,\n>(\n\ta: W[],\n\tb: W[],\n): boolean => {\n\tif (a.length !== b.length) return false;\n\treturn a.every(\n\t\t(w, i) =>\n\t\t\tw.id === b[i]?.id &&\n\t\t\tw.status === b[i]?.status &&\n\t\t\tw.error === b[i]?.error &&\n\t\t\tw.name === b[i]?.name,\n\t);\n};\n\n/**\n * The platform-specific surface of an injected-wallets stream. Everything else\n * — the connect/disconnect state machine, the connected-ids bookkeeping, the\n * store persistence, change detection and sharing — is owned by\n * {@link createInjectedWallets$}.\n *\n * @typeParam TSource - a wallet as the platform's registry reports it\n * @typeParam TWallet - the platform's wallet type\n * @typeParam THandle - live connection handle retained while connected\n */\nexport type InjectedWalletsAdapter<\n\tTSource,\n\tTWallet extends BaseWallet,\n\tTHandle = void,\n> = {\n\t/** Live registry of the platform's injected wallets (emits `[]` during SSR). */\n\tsources$: Observable<readonly TSource[]>;\n\t/** Stable wallet id for a registry entry. */\n\tgetWalletId: (source: TSource) => WalletId;\n\t/**\n\t * Platform connect call. The resolved value is retained as the wallet's\n\t * live handle until disconnect.\n\t */\n\tconnect: (source: TSource, walletId: WalletId) => Promise<THandle>;\n\t/** `true` maps the platform's rejection to `USER_REJECTED`; absent means never. */\n\tisUserRejection?: (error: unknown) => boolean;\n\treleaseAbandonedHandle?: (handle: THandle, walletId: WalletId) => void;\n\t/**\n\t * Optional platform disconnect call, awaited before local state clears so a\n\t * failed disconnect rejects without desyncing the connected list.\n\t */\n\tdisconnect?: (source: TSource, walletId: WalletId) => Promise<void>;\n\t/**\n\t * Runs after a disconnect fully applied — the place to drop cached account\n\t * observables so a later reconnect rebuilds them against a fresh handle.\n\t */\n\tonDisconnected?: (walletId: WalletId) => void;\n\t/** Build the platform wallet object for one registry entry. */\n\tbuildWallet: (args: {\n\t\tsource: TSource;\n\t\twalletId: WalletId;\n\t\t/** Live connection handle; `undefined` while disconnected. */\n\t\thandle: THandle | undefined;\n\t\tstatus: WalletStatus;\n\t\terror: KheopskitError | undefined;\n\t\tisConnected: boolean;\n\t\tconnect: (options?: ConnectOptions) => Promise<void>;\n\t\tdisconnect: () => Promise<void>;\n\t}) => TWallet;\n};\n\ntype Connecting = {\n\tstatus: \"connecting\";\n\tpromise: Promise<void>;\n\tanchored: boolean;\n\twaiting: number;\n\tanswered: boolean;\n\tabort: () => void;\n};\n\ntype Connection<THandle> =\n\t| Connecting\n\t| { status: \"connected\"; handle: THandle; disconnecting?: Promise<void> }\n\t| { status: \"disconnected\"; error: KheopskitError };\n\nconst join = (\n\tconnecting: Connecting,\n\twalletId: WalletId,\n\tsignal: AbortSignal | undefined,\n): Promise<void> => {\n\tif (!signal) {\n\t\tconnecting.anchored = true;\n\t\treturn connecting.promise;\n\t}\n\tconnecting.waiting++;\n\treturn new Promise<void>((resolve, reject) => {\n\t\tconst leave = () => {\n\t\t\tif (connecting.answered) return;\n\t\t\treject(abortedError(walletId, \"connect\"));\n\t\t\tconnecting.waiting--;\n\t\t\tif (!connecting.anchored && connecting.waiting === 0) connecting.abort();\n\t\t};\n\t\tsignal.addEventListener(\"abort\", leave, { once: true });\n\t\tconnecting.promise\n\t\t\t.then(resolve, reject)\n\t\t\t.finally(() => signal.removeEventListener(\"abort\", leave));\n\t});\n};\n\n/**\n * The shared engine behind every platform's injected-wallets stream: tracks\n * each wallet's connection (pending attempt or live handle), shares one\n * in-flight connect per wallet, persists connected ids to the store for\n * auto-reconnect, and re-emits the wallet list whenever the registry or\n * connection state changes.\n */\nexport const createInjectedWallets$ = <\n\tTSource,\n\tTWallet extends BaseWallet,\n\tTHandle = void,\n>(\n\tstore: KheopskitStore,\n\tadapter: InjectedWalletsAdapter<TSource, TWallet, THandle>,\n): Observable<TWallet[]> =>\n\tnew Observable<TWallet[]>((subscriber) => {\n\t\tconst connections$ = new BehaviorSubject<\n\t\t\tReadonlyMap<WalletId, Connection<THandle>>\n\t\t>(new Map());\n\t\tconst teardown = new AbortController();\n\t\tlet present = new Set<WalletId>();\n\n\t\tconst abortConnectsOfSourcesThatLeft = (sources: readonly TSource[]) => {\n\t\t\tpresent = new Set(sources.map((source) => adapter.getWalletId(source)));\n\t\t\tfor (const [walletId, connection] of connections$.value)\n\t\t\t\tif (connection.status === \"connecting\" && !present.has(walletId))\n\t\t\t\t\tconnection.abort();\n\t\t};\n\n\t\tconst setConnection = (\n\t\t\twalletId: WalletId,\n\t\t\tconnection: Connection<THandle> | undefined,\n\t\t) => {\n\t\t\tconst next = new Map(connections$.value);\n\t\t\tif (connection) next.set(walletId, connection);\n\t\t\telse next.delete(walletId);\n\t\t\tconnections$.next(next);\n\t\t};\n\n\t\tconst startConnect = (\n\t\t\tsource: TSource,\n\t\t\twalletId: WalletId,\n\t\t\tsignal: AbortSignal | undefined,\n\t\t): Promise<void> => {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst promise = new Promise<void>((resolve, reject) => {\n\t\t\t\tcontroller.signal.addEventListener(\n\t\t\t\t\t\"abort\",\n\t\t\t\t\t() => {\n\t\t\t\t\t\tsetConnection(walletId, undefined);\n\t\t\t\t\t\treject(abortedError(walletId, \"connect\"));\n\t\t\t\t\t},\n\t\t\t\t\t{ once: true },\n\t\t\t\t);\n\t\t\t\tnew Promise<THandle>((res) =>\n\t\t\t\t\tres(adapter.connect(source, walletId)),\n\t\t\t\t).then(\n\t\t\t\t\t(handle) => {\n\t\t\t\t\t\tconnecting.answered = true;\n\t\t\t\t\t\tif (controller.signal.aborted) {\n\t\t\t\t\t\t\tadapter.releaseAbandonedHandle?.(handle, walletId);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsetConnection(walletId, { status: \"connected\", handle });\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t\tstore.rememberWallet(walletId);\n\t\t\t\t\t},\n\t\t\t\t\t(error) => {\n\t\t\t\t\t\tconnecting.answered = true;\n\t\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\t\tconst connectError = toConnectError(\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\twalletId,\n\t\t\t\t\t\t\tadapter.isUserRejection ?? (() => false),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsetConnection(walletId, {\n\t\t\t\t\t\t\tstatus: \"disconnected\",\n\t\t\t\t\t\t\terror: connectError,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treject(connectError);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t});\n\t\t\tconst connecting: Connecting = {\n\t\t\t\tstatus: \"connecting\",\n\t\t\t\tpromise,\n\t\t\t\tanchored: false,\n\t\t\t\twaiting: 0,\n\t\t\t\tanswered: false,\n\t\t\t\tabort: () => {\n\t\t\t\t\tif (connections$.value.get(walletId) === connecting)\n\t\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t};\n\t\t\tsetConnection(walletId, connecting);\n\t\t\treturn join(connecting, walletId, signal);\n\t\t};\n\n\t\tconst untilSettled = (\n\t\t\tdisconnecting: Promise<void>,\n\t\t\twalletId: WalletId,\n\t\t\tsignal: AbortSignal | undefined,\n\t\t): Promise<void> =>\n\t\t\tnew Promise<void>((resolve, reject) => {\n\t\t\t\tconst signals = signal ? [teardown.signal, signal] : [teardown.signal];\n\t\t\t\tconst settle = () => {\n\t\t\t\t\tfor (const s of signals) s.removeEventListener(\"abort\", settle);\n\t\t\t\t\tif (signals.some((s) => s.aborted))\n\t\t\t\t\t\treject(abortedError(walletId, \"connect\"));\n\t\t\t\t\telse resolve();\n\t\t\t\t};\n\t\t\t\tif (signals.some((s) => s.aborted)) return settle();\n\t\t\t\tfor (const s of signals)\n\t\t\t\t\ts.addEventListener(\"abort\", settle, { once: true });\n\t\t\t\tdisconnecting.then(settle, settle);\n\t\t\t});\n\n\t\tconst connect = (\n\t\t\tsource: TSource,\n\t\t\twalletId: WalletId,\n\t\t\toptions?: ConnectOptions,\n\t\t): Promise<void> => {\n\t\t\tif (teardown.signal.aborted || !present.has(walletId))\n\t\t\t\treturn Promise.reject(abortedError(walletId, \"connect\"));\n\t\t\tconst current = connections$.value.get(walletId);\n\t\t\tif (current?.status === \"connected\") {\n\t\t\t\tif (!current.disconnecting) return Promise.resolve();\n\t\t\t\treturn untilSettled(\n\t\t\t\t\tcurrent.disconnecting,\n\t\t\t\t\twalletId,\n\t\t\t\t\toptions?.signal,\n\t\t\t\t).then(() => connect(source, walletId, options));\n\t\t\t}\n\t\t\tif (options?.signal?.aborted)\n\t\t\t\treturn Promise.reject(abortedError(walletId, \"connect\"));\n\t\t\tif (current?.status === \"connecting\")\n\t\t\t\treturn join(current, walletId, options?.signal);\n\t\t\treturn startConnect(source, walletId, options?.signal);\n\t\t};\n\n\t\tconst disconnect = (source: TSource, walletId: WalletId): Promise<void> => {\n\t\t\tconst current = connections$.value.get(walletId);\n\t\t\tif (!current || current.status === \"disconnected\")\n\t\t\t\treturn Promise.resolve();\n\t\t\tif (current.status === \"connecting\") {\n\t\t\t\tcurrent.abort();\n\t\t\t\treturn Promise.resolve();\n\t\t\t}\n\t\t\tif (current.disconnecting) return current.disconnecting;\n\n\t\t\tstore.forgetWallet(walletId);\n\t\t\tconst disconnecting = (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait adapter.disconnect?.(source, walletId);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!teardown.signal.aborted) {\n\t\t\t\t\t\tsetConnection(walletId, {\n\t\t\t\t\t\t\tstatus: \"connected\",\n\t\t\t\t\t\t\thandle: current.handle,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tstore.rememberWallet(walletId);\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (teardown.signal.aborted) return;\n\t\t\t\tsetConnection(walletId, undefined);\n\t\t\t\tadapter.onDisconnected?.(walletId);\n\t\t\t})();\n\t\t\tsetConnection(walletId, { ...current, disconnecting });\n\t\t\treturn disconnecting;\n\t\t};\n\n\t\tconst sub = combineLatest([adapter.sources$, connections$])\n\t\t\t.pipe(\n\t\t\t\ttap(([sources]) => abortConnectsOfSourcesThatLeft(sources)),\n\t\t\t\tmap(([sources, connections]) =>\n\t\t\t\t\tsources.map((source): TWallet => {\n\t\t\t\t\t\tconst walletId = adapter.getWalletId(source);\n\t\t\t\t\t\tconst connection = connections.get(walletId);\n\t\t\t\t\t\tconst connected =\n\t\t\t\t\t\t\tconnection?.status === \"connected\" ? connection : undefined;\n\t\t\t\t\t\treturn adapter.buildWallet({\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\twalletId,\n\t\t\t\t\t\t\thandle: connected?.handle,\n\t\t\t\t\t\t\tstatus: connection?.status ?? \"disconnected\",\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\tconnection?.status === \"disconnected\"\n\t\t\t\t\t\t\t\t\t? connection.error\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\tisConnected: connected !== undefined,\n\t\t\t\t\t\t\tconnect: (options) => connect(source, walletId, options),\n\t\t\t\t\t\t\tdisconnect: () => disconnect(source, walletId),\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tdistinctUntilChanged(walletsEqual),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tteardown.abort();\n\t\t\tfor (const connection of connections$.value.values())\n\t\t\t\tif (connection.status === \"connecting\") connection.abort();\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n"],"mappings":"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"}