@kheopskit/core 1.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/MIGRATING_TO_V4.md +259 -0
  2. package/README.md +67 -0
  3. package/dist/chunk-4ENHC7G4.js +210 -0
  4. package/dist/chunk-4ENHC7G4.js.map +1 -0
  5. package/dist/chunk-6XAZANB5.mjs +450 -0
  6. package/dist/chunk-6XAZANB5.mjs.map +1 -0
  7. package/dist/chunk-7QSGAJ4A.mjs +210 -0
  8. package/dist/chunk-7QSGAJ4A.mjs.map +1 -0
  9. package/dist/chunk-B4L6GAYD.js +179 -0
  10. package/dist/chunk-B4L6GAYD.js.map +1 -0
  11. package/dist/chunk-BWUUHUDK.mjs +24 -0
  12. package/dist/chunk-BWUUHUDK.mjs.map +1 -0
  13. package/dist/chunk-D3EQMFZ2.js +24 -0
  14. package/dist/chunk-D3EQMFZ2.js.map +1 -0
  15. package/dist/chunk-XQWJM3KC.js +450 -0
  16. package/dist/chunk-XQWJM3KC.js.map +1 -0
  17. package/dist/chunk-YDLCHYHH.mjs +179 -0
  18. package/dist/chunk-YDLCHYHH.mjs.map +1 -0
  19. package/dist/ethereum.d.mts +61 -0
  20. package/dist/ethereum.d.ts +61 -0
  21. package/dist/ethereum.js +351 -0
  22. package/dist/ethereum.js.map +1 -0
  23. package/dist/ethereum.mjs +351 -0
  24. package/dist/ethereum.mjs.map +1 -0
  25. package/dist/getCachedObservable-C4E8dfMp.d.mts +20 -0
  26. package/dist/getCachedObservable-C4E8dfMp.d.ts +20 -0
  27. package/dist/index.d.mts +55 -267
  28. package/dist/index.d.ts +55 -267
  29. package/dist/index.js +327 -1355
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +263 -1325
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/internal.d.mts +86 -0
  34. package/dist/internal.d.ts +86 -0
  35. package/dist/internal.js +32 -0
  36. package/dist/internal.js.map +1 -0
  37. package/dist/internal.mjs +32 -0
  38. package/dist/internal.mjs.map +1 -0
  39. package/dist/polkadot.d.mts +70 -0
  40. package/dist/polkadot.d.ts +70 -0
  41. package/dist/polkadot.js +303 -0
  42. package/dist/polkadot.js.map +1 -0
  43. package/dist/polkadot.mjs +303 -0
  44. package/dist/polkadot.mjs.map +1 -0
  45. package/dist/solana.d.mts +98 -0
  46. package/dist/solana.d.ts +98 -0
  47. package/dist/solana.js +461 -0
  48. package/dist/solana.js.map +1 -0
  49. package/dist/solana.mjs +461 -0
  50. package/dist/solana.mjs.map +1 -0
  51. package/dist/types-C7V7DGlg.d.mts +349 -0
  52. package/dist/types-C7V7DGlg.d.ts +349 -0
  53. package/package.json +104 -18
package/dist/index.mjs CHANGED
@@ -1,479 +1,225 @@
1
- // src/utils/getCachedObservable.ts
2
- var CACHE = /* @__PURE__ */ new Map();
3
- var getCachedObservable$ = (key, create) => {
4
- if (!CACHE.has(key)) CACHE.set(key, create());
5
- return CACHE.get(key);
6
- };
7
- var clearCachedObservable = (key) => {
8
- CACHE.delete(key);
9
- };
10
- var clearAllCachedObservables = () => {
11
- CACHE.clear();
12
- };
13
-
14
- // src/utils/polkadotExtensions.ts
15
- var POLKADOT_EXTENSIONS = {
16
- talisman: {
17
- name: "Talisman",
18
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8cGF0aCBmaWxsPSIjZGRmZTc2IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wIDcwLjI1YzAgMjEuMjU1IDAgMzEuODgzIDQuNDYzIDM5Ljg1MmEzNSAzNSAwIDAgMCAxMy40MzUgMTMuNDM1QzI1Ljg2NyAxMjggMzYuNDk1IDEyOCA1Ny43NSAxMjhoMTIuNWMyMS4yNTUgMCAzMS44ODMgMCAzOS44NTItNC40NjNhMzUgMzUgMCAwIDAgMTMuNDM1LTEzLjQzNUMxMjggMTAyLjEzMyAxMjggOTEuNTA1IDEyOCA3MC4yNXYtMTIuNWMwLTIxLjI1NSAwLTMxLjg4My00LjQ2My0zOS44NTJhMzUgMzUgMCAwIDAtMTMuNDM1LTEzLjQzNUMxMDIuMTMzIDAgOTEuNTA1IDAgNzAuMjUgMGgtMTIuNUMzNi40OTUgMCAyNS44NjcgMCAxNy44OTggNC40NjNBMzUgMzUgMCAwIDAgNC40NjMgMTcuODk4QzAgMjUuODY3IDAgMzYuNDk1IDAgNTcuNzVaIi8+CiAgICA8cGF0aCBmaWxsPSIjZWE1NzUwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Im0zMy44NzkgMzUuMTE3LS41IDE5LjE2NWM4LjEwNyA0LjE2OCAxNS43NSA0LjA3NSAyNC43NCAyLjA2MyAzLjU2LTEuMzk3IDYuMDU2LTEuNzAyIDkuNTExIDAgOS4wNjcgMi44MTYgMTYuOTY5IDEuOTUgMjUuMTg1LTIuMjQzbC0uNDg1LTE5LjE4N2MwLTEwLjgwNS03LjAwNC0xNC45NjItMTQuNjMyLTEyLjczOS0uNzc5LjIzMi0xLjk0NCAxLjI3NC0xLjk0NCAyLjIwN2wtLjE4MSAxOC43MzNhMS43NyAxLjc3IDAgMSAxLTMuNTM4LS4wMTVWMjAuMDY3YTguODM4IDguODM4IDAgMCAwLTE3LjY3NSAwVjQzLjFhMS43NyAxLjc3IDAgMSAxLTMuNTM4LjAxNWwtLjE3Ni0xOC43NDNjMC0uOTIzLTEuMTA5LTEuOTYtMS44ODItMi4xOTItOC44LTIuNjEtMTQuODggMi41MzgtMTQuODggMTIuOTM2Wm0yLjQ3NSAyMy44NDNhNDguNDMgNDguNDMgMCAwIDEtNS4yMDktMi4yNTRjLTQuNzMtMi4yNjktMTIuMDk1LTEuNTYyLTE3LjA3MiA0LjExMS0yLjI3NCAyLjYtLjUxNSA2LjM2IDIuNzcgNy40NDggMS41ODMuNTI2IDMuMDE3IDEuNDEzIDQuMzUzIDIuNDA4bC40NjQuMzM2YzQuMTMyIDIuOTY1IDYuNzkzIDcuNDA2IDcuMDU2IDEyLjQ4NmwuMjUzIDQuODEyYTMxLjYxNiAzMS42MTYgMCAwIDAgMTkuNDI4IDI1Ljk1OSAzOC41OSAzOC41OSAwIDAgMCAyOS4zMjcgMCAzMS42MTYgMzEuNjE2IDAgMCAwIDE5LjQyOS0yNS45NTljLjA0Ni0uODI1LjA2MS0xLjY1LjA1MS0yLjQ2NWwuMTI0LTIuMzQ3Yy4yNjMtNS4wOCAyLjkyNC05LjUyIDcuMDU2LTEyLjQ4NmwuNDY0LS4zMzZjMS4zNC0uOTk1IDIuNzctMS44ODIgNC4zNTMtMi40MDggMy4yODUtMS4wODkgNS4wNS00Ljg0OSAyLjc3LTcuNDQ4LTQuOTc4LTUuNjczLTEyLjM0My02LjM3NS0xNy4wNzItNC4xMS0xLjcxOC44MjUtMy40MzUgMS42NS01LjIxIDIuMjUzbC0zLjYyIDEuMjM4LS4wMS4wNDFjLTYuNjU0IDEuODQyLTEyLjEyIDEuODQ3LTE4LjM5OC0uNzQyLTMuMTc3LTEuMzEtNi4zOC0xLjU1OC05LjQ4IDAtNS45NjcgMS44NTYtMTIuMDQ4IDIuNjQtMTguMjA2LjcwMWwtMy42MjYtMS4yMzhabTI2LjY2NSA0NC43MzJjMTMuMzkgMCAyNC4yNDEtMTUuNTk2IDI0LjI0MS0xNS41OTZTNzYuNDEgNzIuNDk5IDYzLjAyIDcyLjQ5OWMtMTMuMzg1IDAtMjQuMjM2IDE1LjU5Ny0yNC4yMzYgMTUuNTk3czEwLjg1MSAxNS41OTYgMjQuMjQgMTUuNTk2Wm0xMC44ODMtMTUuNTk2YzAgNi4wMS00Ljg3MiAxMC44ODItMTAuODgzIDEwLjg4Mi02LjAxIDAtMTAuODgyLTQuODcyLTEwLjg4Mi0xMC44ODJzNC44NzItMTAuODgzIDEwLjg4Mi0xMC44ODMgMTAuODgzIDQuODcyIDEwLjg4MyAxMC44ODNabS0xMC44ODMgNC45MzZhNC45MzYgNC45MzYgMCAxIDAgMC05Ljg3MiA0LjkzNiA0LjkzNiAwIDAgMCAwIDkuODcyWiIvPgo8L3N2Zz4K"
19
- },
20
- "polkadot-js": {
21
- name: "Polkadot.js",
22
- icon: "data:image/svg+xml;base64,ICA8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEwNi4yIDEwNi4yIj4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPgogICAgICA8ZyBpZD0iTGF5ZXJfMS0yIiBkYXRhLW5hbWU9IkxheWVyIDEiPgogICAgICAgIDxjaXJjbGUgY3g9IjUzLjEiIGN5PSI1My4xIiByPSI1My4xIiBmaWxsPSIjZjI5MjM1IiAvPgogICAgICAgIDxwYXRoCiAgICAgICAgICBmaWxsPSIjZmZmIgogICAgICAgICAgZD0iTTU0LjQ3IDEzLjc2YTI4Ljg1IDI4Ljg1IDAgMDAtMjguNzMgMjguNzMgMjkuMzQgMjkuMzQgMCAwMDEuNTIgOS4zNCA0IDQgMCAxMDcuNDktMi41MkExOC42NyAxOC42NyAwIDAxMzMuNjMgNDJhMjAuNzIgMjAuNzIgMCAxMTIyIDIxLjMxcy00IC4yNS02IC40OWMtLjc0LjExLTEuNDguMjYtMi4yLjQ0YS4yOC4yOCAwIDAxLS4zOCAwIC4yNy4yNyAwIDAxMC0uMzJsLjYzLTMuNDEgMy43OS0xN2EzLjk0IDMuOTQgMCAxMC03LjcxLTEuNjVzLTkgNDEuNy05IDQyLjA4YTMuNzkgMy43OSAwIDAwMi43NCA0LjZoLjI4YTMuNzggMy43OCAwIDAwNC42MS0yLjcxLjQzLjQzIDAgMDAwLS4xMXYtLjE5Yy4xMS0uNDkgMS4yNS02IDEuMjUtNmExMC4yMyAxMC4yMyAwIDAxOC40Ni04Yy44Ny0uMTMgNC41My0uMzggNC41My0uMzhhMjguNzEgMjguNzEgMCAwMC0yLjExLTU3LjI3eiIKICAgICAgICAvPgogICAgICAgIDxwYXRoCiAgICAgICAgICBmaWxsPSIjZmZmIgogICAgICAgICAgZD0iTTU2LjIxIDgwYTQuNzggNC43OCAwIDAwLTUuNjYgMy43MS4yNC4yNCAwIDAxMCAuMDggNC43NyA0Ljc3IDAgMDAzLjY1IDUuNjdoLjE0QTQuNyA0LjcgMCAwMDYwIDg2di0uMzJBNSA1IDAgMDA1Ni4yMSA4MHoiCiAgICAgICAgLz4KICAgICAgPC9nPgogICAgPC9nPgogIDwvc3ZnPg=="
23
- },
24
- "subwallet-js": {
25
- name: "SubWallet",
26
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYwIiBoZWlnaHQ9IjE2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNODAgNGM1Ny42MyAwIDc2IDE4LjM3IDc2IDc2IDAgNTcuNjMtMTguMzcgNzYtNzYgNzYtNTcuNjMgMC03Ni0xOC4zNy03Ni03NkM0IDIyLjM3IDIyLjM3IDQgODAgNFoiIGZpbGw9InVybCgjYSkiLz48ZyBjbGlwLXBhdGg9InVybCgjYikiPjxwYXRoIGQ9Ik0xMTIuNjE1IDY2LjcyVjUzLjM5OEw1OC43NiAzMiA0OCAzNy40MTJsLjA1NyA0MS40NjQgNDAuMjkyIDE2LjA3LTIxLjUyIDkuMDc1di03LjAxOEw1Ni45NSA5My4wM2wtOC44OTMgNC4xNjN2MjUuMzk1TDU4Ljc2OSAxMjhsNTMuODQ2LTI0LjA2MlY4Ni44NjlMNjQuMTU0IDY3LjY1N1Y1NmwzOC40NDkgMTUuMjE2IDEwLjAxMi00LjQ5NloiIGZpbGw9IiNmZmYiLz48L2c+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iODAiIHkxPSI0IiB4Mj0iODAiIHkyPSIxNTYiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjMDA0QkZGIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNENFQUFDIi8+PC9saW5lYXJHcmFkaWVudD48Y2xpcFBhdGggaWQ9ImIiPjxwYXRoIGZpbGw9IiNmZmYiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4IDMyKSIgZD0iTTAgMGg2NC42MTV2OTZIMHoiLz48L2NsaXBQYXRoPjwvZGVmcz48L3N2Zz4="
27
- },
28
- enkrypt: {
29
- name: "Enkrypt",
30
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODEiIGhlaWdodD0iODEiIHZpZXdCb3g9IjAgMCA4MSA4MSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNy4wMDU3IDE3LjAwNjJDMTguOTMwMyAxNS4wODE2IDIxLjU0MDUgMTQuMDAwNCAyNC4yNjIyIDE0LjAwMDRMNjcuMzI5NiAxNFYyMS44NzQxQzY3LjMyOTYgMjMuODMwNSA2Ni41NTIzIDI1LjcwNjcgNjUuMTY5IDI3LjA5QzYzLjc4NTcgMjguNDczMyA2MS45MDk1IDI5LjI1MDQgNTkuOTUzMiAyOS4yNTA0SDM5LjcwNDVDMzYuOTgyOCAyOS4yNTA0IDM0LjM3MjYgMzAuMzMxNiAzMi40NDggMzIuMjU2MUMzMC41MjM1IDM0LjE4MDcgMjkuNDQyMyAzNi43OTA5IDI5LjQ0MjMgMzkuNTEyNlY0Mi4xMjQyQzI5LjQ0MjMgNDQuODQ1OSAzMC41MjM1IDQ3LjQ1NjEgMzIuNDQ4IDQ5LjM4MDZDMzQuMzcyNiA1MS4zMDUxIDM2Ljk4MjggNTIuMzg2MyAzOS43MDQ1IDUyLjM4NjNINTkuOTUzMkM2MS45MDk1IDUyLjM4NjMgNjMuNzg1NyA1My4xNjM1IDY1LjE2OSA1NC41NDY4QzY2LjU1MjMgNTUuOTMwMSA2Ny4zMjk2IDU3LjgwNjMgNjcuMzI5NiA1OS43NjI2VjY3LjMzSDI0LjI2MjJDMjEuNTQwNSA2Ny4zMyAxOC45MzAzIDY2LjI0ODggMTcuMDA1NyA2NC4zMjQzQzE1LjA4MTIgNjIuMzk5NyAxNCA1OS43ODk1IDE0IDU3LjA2NzhWMjQuMjYyNkMxNCAyMS41NDA5IDE1LjA4MTIgMTguOTMwNyAxNy4wMDU3IDE3LjAwNjJaTTQwLjE0NzkgMzMuNTQyM0g2MC45MTU3QzY0LjQ1OCAzMy41NDIzIDY3LjMyOTUgMzYuNDEzOCA2Ny4zMjk1IDM5Ljk1NjFWNDEuNjgxNkM2Ny4zMjk1IDQ1LjIyMzggNjQuNDU4IDQ4LjA5NTQgNjAuOTE1NyA0OC4wOTU0SDQwLjE0NzlDMzYuNjA1NyA0OC4wOTU0IDMzLjczNDEgNDUuMjIzOCAzMy43MzQxIDQxLjY4MTZWMzkuOTU2MUMzMy43MzQxIDM2LjQxMzggMzYuNjA1NyAzMy41NDIzIDQwLjE0NzkgMzMuNTQyM1oiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl8yODdfMjM1OSkiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8yODdfMjM1OSIgeDE9IjE5LjM2MDIiIHkxPSIxNCIgeDI9IjU2Ljc2OTYiIHkyPSI2OS44MDA1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiNDNTQ5RkYiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNjU0QkZGIi8+CjwvbGluZWFyR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg=="
31
- }
32
- };
33
-
34
- // src/utils/isWalletPlatform.ts
35
- var isWalletPlatform = (platform) => typeof platform === "string" && ["polkadot", "ethereum"].includes(platform);
36
-
37
- // src/utils/WalletId.ts
38
- var getWalletId = (platform, identifier) => {
39
- if (!isWalletPlatform(platform)) throw new Error("Invalid platform");
40
- if (!identifier) throw new Error("Invalid name");
41
- return `${platform}:${identifier}`;
42
- };
43
- var parseWalletId = (walletId) => {
44
- if (!walletId) throw new Error("Invalid walletId");
45
- const [platform, identifier] = walletId.split(":");
46
- if (!isWalletPlatform(platform)) throw new Error("Invalid platform");
47
- if (!identifier) throw new Error("Invalid address");
48
- return { platform, identifier };
49
- };
50
-
51
- // src/utils/hydrateState.ts
52
- var lookupWalletIcon = (platform, identifier) => {
53
- if (platform === "polkadot") {
54
- return POLKADOT_EXTENSIONS[identifier]?.icon ?? "";
55
- }
56
- return "";
57
- };
58
- var PendingWalletError = class extends Error {
59
- constructor(walletId) {
60
- super(
61
- `Wallet ${walletId} is still loading. Wait for isHydrating to be false before calling connect/disconnect.`
62
- );
63
- this.name = "PendingWalletError";
64
- }
65
- };
66
- var hydrateWallet = (cached) => {
67
- const { platform, identifier } = parseWalletId(cached.id);
68
- const throwPending = () => {
69
- throw new PendingWalletError(cached.id);
70
- };
71
- const icon = lookupWalletIcon(platform, identifier);
72
- if (platform === "polkadot") {
73
- return {
74
- id: cached.id,
75
- platform: "polkadot",
76
- type: "injected",
77
- extensionId: identifier,
78
- extension: void 0,
79
- name: cached.name,
80
- icon,
81
- isConnected: cached.isConnected,
82
- connect: throwPending,
83
- disconnect: throwPending
84
- };
85
- }
86
- if (platform === "ethereum") {
87
- return {
88
- id: cached.id,
89
- platform: "ethereum",
90
- type: "injected",
91
- providerId: identifier,
92
- provider: {},
93
- // Placeholder - will be replaced by real wallet
94
- name: cached.name,
95
- icon,
96
- isConnected: cached.isConnected,
97
- connect: throwPending,
98
- disconnect: throwPending
99
- };
100
- }
101
- throw new Error(`Unknown platform: ${platform}`);
102
- };
103
- var hydrateAccount = (cached) => {
104
- if (cached.platform === "polkadot") {
105
- return {
106
- id: cached.id,
107
- platform: "polkadot",
108
- type: cached.polkadotAccountType ?? "sr25519",
109
- address: cached.address,
110
- name: cached.name,
111
- walletId: cached.walletId,
112
- walletName: cached.walletName,
113
- // PolkadotSigner is required but we can't provide a real one
114
- // This is a placeholder that will be replaced by the real account
115
- polkadotSigner: {}
116
- };
117
- }
118
- if (cached.platform === "ethereum") {
119
- return {
120
- id: cached.id,
121
- platform: "ethereum",
122
- address: cached.address,
123
- chainId: cached.chainId,
124
- walletId: cached.walletId,
125
- walletName: cached.walletName,
126
- isWalletDefault: false,
127
- client: {}
128
- // Placeholder
129
- };
130
- }
131
- throw new Error(`Unknown platform: ${cached.platform}`);
132
- };
133
- var serializeWallet = (wallet) => ({
134
- id: wallet.id,
135
- platform: wallet.platform,
136
- type: wallet.type,
137
- name: wallet.name,
138
- // Note: icon is NOT stored to save cookie space
139
- isConnected: wallet.isConnected
140
- });
141
- var serializeAccount = (account) => ({
142
- id: account.id,
143
- platform: account.platform,
144
- address: account.address,
145
- name: "name" in account ? account.name : void 0,
146
- chainId: account.platform === "ethereum" ? account.chainId : void 0,
147
- polkadotAccountType: account.platform === "polkadot" ? account.type : void 0,
148
- walletId: account.walletId,
149
- walletName: account.walletName
150
- });
151
-
152
- // src/utils/storage.ts
153
- var noopStorage = {
154
- getItem: () => null,
155
- setItem: () => {
156
- },
157
- removeItem: () => {
158
- }
159
- };
160
- var _safeLocalStorage = null;
161
- var createSafeLocalStorage = () => {
162
- if (typeof window === "undefined") return noopStorage;
163
- try {
164
- const testKey = "__kheopskit_test__";
165
- window.localStorage.setItem(testKey, testKey);
166
- window.localStorage.removeItem(testKey);
167
- return {
168
- getItem: (key) => window.localStorage.getItem(key),
169
- setItem: (key, value) => window.localStorage.setItem(key, value),
170
- removeItem: (key) => window.localStorage.removeItem(key),
171
- subscribe: (key, callback) => {
172
- const handler = (event) => {
173
- if (event.key === key) {
174
- callback(event.newValue);
175
- }
176
- };
177
- window.addEventListener("storage", handler);
178
- return () => window.removeEventListener("storage", handler);
179
- }
180
- };
181
- } catch {
182
- return noopStorage;
183
- }
184
- };
185
- var getSafeLocalStorage = () => {
186
- if (_safeLocalStorage === null) {
187
- _safeLocalStorage = createSafeLocalStorage();
188
- }
189
- return _safeLocalStorage;
190
- };
191
- var safeLocalStorage = {
192
- getItem: (key) => getSafeLocalStorage().getItem(key),
193
- setItem: (key, value) => getSafeLocalStorage().setItem(key, value),
194
- removeItem: (key) => getSafeLocalStorage().removeItem(key),
195
- subscribe: (key, callback) => {
196
- const storage = getSafeLocalStorage();
197
- return storage.subscribe?.(key, callback) ?? (() => {
198
- });
199
- }
200
- };
201
- var parseCookie = (cookieString, key) => {
202
- if (!cookieString) return null;
203
- for (const cookie of cookieString.split(";")) {
204
- const [k, ...v] = cookie.split("=");
205
- const cookieKey = k?.trim();
206
- if (cookieKey === key) {
207
- try {
208
- return decodeURIComponent(v.join("=").trim());
209
- } catch {
210
- return null;
211
- }
212
- }
213
- }
214
- return null;
215
- };
216
- var COOKIE_MAX_SIZE = 3 * 1024;
217
- var BROADCAST_CHANNEL_NAME = "kheopskit-storage-sync";
218
- var sharedBroadcastChannel = null;
219
- var getBroadcastChannel = () => {
220
- if (sharedBroadcastChannel) return sharedBroadcastChannel;
221
- if (typeof BroadcastChannel === "undefined") return null;
222
- try {
223
- sharedBroadcastChannel = new BroadcastChannel(BROADCAST_CHANNEL_NAME);
224
- } catch {
225
- }
226
- return sharedBroadcastChannel;
227
- };
228
- var isSecureConnection = () => typeof window !== "undefined" && window.location.protocol === "https:";
229
- var cookieStorage = (initialCookies) => {
230
- return {
231
- getItem: (key) => {
232
- const cookieString = typeof document !== "undefined" ? document.cookie : initialCookies;
233
- return parseCookie(cookieString, key);
234
- },
235
- setItem: (key, value) => {
236
- if (typeof document === "undefined") return;
237
- const encodedValue = encodeURIComponent(value);
238
- if (encodedValue.length > COOKIE_MAX_SIZE) {
239
- console.warn(
240
- `[kheopskit] Cookie value for "${key}" exceeds recommended size limit (${encodedValue.length} > ${COOKIE_MAX_SIZE} bytes). This may cause issues with cookie storage. Consider reducing the number of connected wallets.`
241
- );
242
- }
243
- const expires = /* @__PURE__ */ new Date();
244
- expires.setFullYear(expires.getFullYear() + 1);
245
- let cookieStr = `${key}=${encodedValue};expires=${expires.toUTCString()};path=/;SameSite=Lax`;
246
- if (isSecureConnection()) {
247
- cookieStr += ";Secure";
248
- }
249
- document.cookie = cookieStr;
250
- getBroadcastChannel()?.postMessage({ type: "set", key, value });
251
- },
252
- removeItem: (key) => {
253
- if (typeof document === "undefined") return;
254
- let cookieStr = `${key}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/;SameSite=Lax`;
255
- if (isSecureConnection()) {
256
- cookieStr += ";Secure";
257
- }
258
- document.cookie = cookieStr;
259
- getBroadcastChannel()?.postMessage({ type: "remove", key });
260
- },
261
- subscribe: (key, callback) => {
262
- const channel = getBroadcastChannel();
263
- if (!channel) return () => {
264
- };
265
- const handler = (event) => {
266
- const data = event.data;
267
- if (data.key === key) {
268
- if (data.type === "set") {
269
- callback(data.value ?? null);
270
- } else if (data.type === "remove") {
271
- callback(null);
272
- }
273
- }
274
- };
275
- channel.addEventListener("message", handler);
276
- return () => {
277
- channel.removeEventListener("message", handler);
278
- };
279
- }
280
- };
281
- };
282
-
283
- // src/utils/iconCache.ts
284
- var ICON_CACHE_KEY = "kheopskit-icons";
285
- var memoryCache = null;
286
- var loadCache = () => {
287
- if (memoryCache !== null) return memoryCache;
288
- try {
289
- const stored = safeLocalStorage.getItem(ICON_CACHE_KEY);
290
- memoryCache = stored ? JSON.parse(stored) : {};
291
- } catch {
292
- memoryCache = {};
293
- }
294
- return memoryCache;
295
- };
296
- var saveCache = (cache) => {
297
- try {
298
- safeLocalStorage.setItem(ICON_CACHE_KEY, JSON.stringify(cache));
299
- memoryCache = cache;
300
- } catch {
301
- }
302
- };
303
- var getCachedIcon = (walletId) => {
304
- const cache = loadCache();
305
- return cache[walletId] || void 0;
306
- };
307
- var setCachedIcons = (icons) => {
308
- const cache = loadCache();
309
- let changed = false;
310
- for (const [walletId, icon] of Object.entries(icons)) {
311
- if (icon && cache[walletId] !== icon) {
312
- cache[walletId] = icon;
313
- changed = true;
314
- }
315
- }
316
- if (changed) {
317
- saveCache(cache);
318
- }
319
- };
1
+ import {
2
+ acceptsCachedAccount,
3
+ getCachedIcon,
4
+ hydrateAccount,
5
+ hydrateWallet,
6
+ serializeAccount,
7
+ serializeWallet,
8
+ setCachedIcons,
9
+ sortAccounts,
10
+ sortWallets
11
+ } from "./chunk-YDLCHYHH.mjs";
12
+ import "./chunk-BWUUHUDK.mjs";
13
+ import {
14
+ DEFAULT_STORAGE_KEY,
15
+ KheopskitError,
16
+ createKheopskitStore,
17
+ getDefaultStore,
18
+ getWalletAccountId,
19
+ isValidAddress,
20
+ parseWalletAccountId,
21
+ resolveConfig,
22
+ store
23
+ } from "./chunk-6XAZANB5.mjs";
24
+ import {
25
+ WALLET_CONNECT_WALLET_ID,
26
+ clearAllCachedObservables,
27
+ clearCachedObservablesByPrefix,
28
+ getWalletId,
29
+ isInjectedWallet,
30
+ isValidWalletId,
31
+ isWalletConnectWallet,
32
+ parseWalletId
33
+ } from "./chunk-7QSGAJ4A.mjs";
320
34
 
321
35
  // src/api/appKit.ts
322
36
  import {
323
37
  BehaviorSubject,
324
- combineLatest,
325
38
  distinctUntilChanged,
326
39
  from,
327
40
  map,
328
41
  Observable,
329
42
  of,
330
43
  shareReplay,
331
- switchMap
44
+ switchMap,
45
+ tap
332
46
  } from "rxjs";
333
47
  var loadAppKit = async () => {
334
- const { createAppKit } = await import("@reown/appkit/core");
335
- return createAppKit;
48
+ try {
49
+ const { createAppKit } = await import("@reown/appkit/core");
50
+ return createAppKit;
51
+ } catch (cause) {
52
+ console.error(
53
+ "[kheopskit] WalletConnect is configured but @reown/appkit could not be loaded. Install it with `pnpm add @reown/appkit` (or remove config.walletConnect). WalletConnect wallets are disabled; injected wallets still work.",
54
+ cause
55
+ );
56
+ return null;
57
+ }
336
58
  };
337
59
  var WALLET_CONNECT_ICON = "data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjQwMCIgdmlld0JveD0iMCAwIDQwMCA0MDAiIHdpZHRoPSI0MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxjbGlwUGF0aCBpZD0iYSI+PHBhdGggZD0ibTAgMGg0MDB2NDAwaC00MDB6Ii8+PC9jbGlwUGF0aD48ZyBjbGlwLXBhdGg9InVybCgjYSkiPjxjaXJjbGUgY3g9IjIwMCIgY3k9IjIwMCIgZmlsbD0iIzMzOTZmZiIgcj0iMTk5LjUiIHN0cm9rZT0iIzY2YjFmZiIvPjxwYXRoIGQ9Im0xMjIuNTE5IDE0OC45NjVjNDIuNzkxLTQxLjcyOSAxMTIuMTcxLTQxLjcyOSAxNTQuOTYyIDBsNS4xNSA1LjAyMmMyLjE0IDIuMDg2IDIuMTQgNS40NjkgMCA3LjU1NWwtMTcuNjE3IDE3LjE4Yy0xLjA3IDEuMDQzLTIuODA0IDEuMDQzLTMuODc0IDBsLTcuMDg3LTYuOTExYy0yOS44NTMtMjkuMTExLTc4LjI1My0yOS4xMTEtMTA4LjEwNiAwbC03LjU5IDcuNDAxYy0xLjA3IDEuMDQzLTIuODA0IDEuMDQzLTMuODc0IDBsLTE3LjYxNy0xNy4xOGMtMi4xNC0yLjA4Ni0yLjE0LTUuNDY5IDAtNy41NTV6bTE5MS4zOTcgMzUuNTI5IDE1LjY3OSAxNS4yOWMyLjE0IDIuMDg2IDIuMTQgNS40NjkgMCA3LjU1NWwtNzAuNyA2OC45NDRjLTIuMTM5IDIuMDg3LTUuNjA4IDIuMDg3LTcuNzQ4IDBsLTUwLjE3OC00OC45MzFjLS41MzUtLjUyMi0xLjQwMi0uNTIyLTEuOTM3IDBsLTUwLjE3OCA0OC45MzFjLTIuMTM5IDIuMDg3LTUuNjA4IDIuMDg3LTcuNzQ4IDBsLTcwLjcwMTUtNjguOTQ1Yy0yLjEzOTYtMi4wODYtMi4xMzk2LTUuNDY5IDAtNy41NTVsMTUuNjc5NS0xNS4yOWMyLjEzOTYtMi4wODYgNS42MDg1LTIuMDg2IDcuNzQ4MSAwbDUwLjE3ODkgNDguOTMyYy41MzUuNTIyIDEuNDAyLjUyMiAxLjkzNyAwbDUwLjE3Ny00OC45MzJjMi4xMzktMi4wODcgNS42MDgtMi4wODcgNy43NDggMGw1MC4xNzkgNDguOTMyYy41MzUuNTIyIDEuNDAyLjUyMiAxLjkzNyAwbDUwLjE3OS00OC45MzFjMi4xMzktMi4wODcgNS42MDgtMi4wODcgNy43NDggMHoiIGZpbGw9IiNmZmYiLz48L2c+PC9zdmc+";
338
- var cachedAppKit = null;
60
+ var APPKIT_SYMBOL = /* @__PURE__ */ Symbol.for("kheopskit.cachedAppKit");
61
+ var APPKIT_PROJECT_ID_SYMBOL = /* @__PURE__ */ Symbol.for("kheopskit.cachedAppKitProjectId");
62
+ var getCachedAppKit = () => globalThis[APPKIT_SYMBOL];
63
+ var getCachedAppKitProjectId = () => globalThis[APPKIT_PROJECT_ID_SYMBOL];
64
+ var setCachedAppKit = (value, projectId) => {
65
+ globalThis[APPKIT_SYMBOL] = value;
66
+ globalThis[APPKIT_PROJECT_ID_SYMBOL] = projectId;
67
+ };
339
68
  var resetAppKitCache = () => {
340
- cachedAppKit = null;
69
+ setCachedAppKit(void 0);
70
+ };
71
+ var dropAccountsCache = (platform) => {
72
+ clearCachedObservablesByPrefix(
73
+ `accounts:${WALLET_CONNECT_WALLET_ID}:${platform}:`
74
+ );
341
75
  };
342
- var getAppKitWallets$ = (config) => {
343
- if (!config.walletConnect) return of({});
344
- if (typeof window === "undefined") return of({});
76
+ var getWalletConnectWallet$ = (config) => {
77
+ if (!config.walletConnect) return of(null);
78
+ if (typeof window === "undefined") return of(null);
345
79
  const walletConnect = config.walletConnect;
80
+ const cachedProjectId = getCachedAppKitProjectId();
81
+ if (cachedProjectId !== void 0 && cachedProjectId !== walletConnect.projectId) {
82
+ console.warn(
83
+ "[kheopskit] WalletConnect is already initialised with projectId %s; AppKit is a process-wide singleton, so the first configuration wins and projectId %s is ignored. Call resetAppKitCache() before re-initialising if the WalletConnect config must change.",
84
+ cachedProjectId,
85
+ walletConnect.projectId
86
+ );
87
+ }
88
+ let cachedAppKit = getCachedAppKit();
346
89
  if (!cachedAppKit) {
347
90
  cachedAppKit = from(loadAppKit()).pipe(
348
91
  switchMap((createAppKit) => {
92
+ if (!createAppKit) return of(null);
349
93
  return new Observable((subscriber) => {
350
94
  const appKit = createAppKit({
351
95
  projectId: walletConnect.projectId,
352
96
  metadata: walletConnect.metadata,
97
+ // Loosely typed in WalletConnectConfig to keep @reown/appkit's
98
+ // types out of core; forwarded to AppKit verbatim.
353
99
  networks: walletConnect.networks,
354
100
  themeMode: walletConnect.themeMode,
355
101
  themeVariables: walletConnect.themeVariables,
356
102
  universalProviderConfigOverride: {
357
103
  methods: {
358
- polkadot: ["polkadot_signTransaction", "polkadot_signMessage"]
104
+ polkadot: ["polkadot_signTransaction", "polkadot_signMessage"],
105
+ solana: [
106
+ "solana_signTransaction",
107
+ "solana_signMessage",
108
+ "solana_signAndSendTransaction"
109
+ ]
359
110
  }
360
111
  },
361
112
  allWallets: "HIDE",
362
113
  debug: config.debug,
363
114
  allowUnsupportedChain: true
364
115
  });
116
+ const appKitInstance = appKit;
365
117
  const status$ = new BehaviorSubject({
366
118
  isPolkadotConnected: false,
367
- isEthereumConnected: false
119
+ isEthereumConnected: false,
120
+ isSolanaConnected: false
368
121
  });
369
122
  const unsubProviders = appKit.subscribeProviders((providers) => {
370
123
  status$.next({
371
124
  isPolkadotConnected: !!providers.polkadot,
372
- isEthereumConnected: !!providers.eip155
125
+ isEthereumConnected: !!providers.eip155,
126
+ isSolanaConnected: !!providers.solana
373
127
  });
374
128
  });
375
- const polkadotWallet$ = appKit.chainNamespaces.includes("polkadot") ? status$.pipe(
376
- map((s) => s.isPolkadotConnected),
377
- distinctUntilChanged(),
378
- map((isConnected) => {
129
+ const namespaceOf = {
130
+ polkadot: "polkadot",
131
+ ethereum: "eip155",
132
+ solana: "solana"
133
+ };
134
+ const allPlatforms = [
135
+ "polkadot",
136
+ "ethereum",
137
+ "solana"
138
+ ];
139
+ const enabledPlatforms = allPlatforms.filter(
140
+ (p) => appKit.chainNamespaces.includes(namespaceOf[p])
141
+ );
142
+ let prevConnected = {
143
+ polkadot: false,
144
+ ethereum: false,
145
+ solana: false
146
+ };
147
+ const sub = status$.pipe(
148
+ map((s) => ({
149
+ polkadot: s.isPolkadotConnected,
150
+ ethereum: s.isEthereumConnected,
151
+ solana: s.isSolanaConnected
152
+ })),
153
+ distinctUntilChanged(
154
+ (a, b) => a.polkadot === b.polkadot && a.ethereum === b.ethereum && a.solana === b.solana
155
+ ),
156
+ tap((connected) => {
157
+ for (const platform of allPlatforms)
158
+ if (prevConnected[platform] && !connected[platform])
159
+ dropAccountsCache(platform);
160
+ prevConnected = connected;
161
+ }),
162
+ map((connected) => {
163
+ const platforms = enabledPlatforms.filter((p) => connected[p]);
164
+ const isConnected = platforms.length > 0;
379
165
  const walletInfo = appKit.getWalletInfo();
380
166
  return {
381
- id: getWalletId("polkadot", "walletconnect"),
382
- platform: "polkadot",
383
- type: "appKit",
384
- appKit,
385
- // todo maybe we dont want to expose the appKit instance
167
+ id: WALLET_CONNECT_WALLET_ID,
168
+ type: "walletconnect",
169
+ platforms,
170
+ appKit: appKitInstance,
386
171
  name: walletInfo?.name ?? "WalletConnect",
387
172
  icon: walletInfo?.icon ?? WALLET_CONNECT_ICON,
173
+ // One shared session: connecting opens the modal; the wallet
174
+ // approves namespaces in that single pairing. Disconnect is
175
+ // session-wide; re-pair to change the approved set.
388
176
  connect: async () => {
389
177
  if (!isConnected) await appKit.open();
390
178
  },
391
- disconnect: () => {
392
- if (isConnected) appKit.disconnect();
179
+ disconnect: async () => {
180
+ if (isConnected) await appKit.disconnect();
393
181
  },
394
182
  isConnected
395
183
  };
396
184
  })
397
- ) : of(void 0);
398
- const ethereumWallet$ = appKit.chainNamespaces.includes("eip155") ? status$.pipe(
399
- map((s) => s.isEthereumConnected),
400
- distinctUntilChanged(),
401
- map((isConnected) => {
402
- const walletInfo = appKit.getWalletInfo();
403
- return {
404
- id: getWalletId("ethereum", "walletconnect"),
405
- platform: "ethereum",
406
- type: "appKit",
407
- appKit,
408
- name: walletInfo?.name ?? "WalletConnect",
409
- icon: walletInfo?.icon ?? WALLET_CONNECT_ICON,
410
- connect: () => appKit.open(),
411
- disconnect: () => appKit.disconnect(),
412
- isConnected
413
- };
414
- })
415
- ) : of(void 0);
416
- const sub = combineLatest({
417
- polkadot: polkadotWallet$,
418
- ethereum: ethereumWallet$
419
- }).subscribe(subscriber);
185
+ ).subscribe(subscriber);
420
186
  return () => {
421
187
  sub.unsubscribe();
422
188
  unsubProviders();
423
189
  };
424
190
  });
425
191
  }),
426
- shareReplay({ refCount: true, bufferSize: 1 })
192
+ // refCount:false keeps the AppKit instance alive for the process lifetime
193
+ // once created: createAppKit runs at most once (Reown AppKit cannot be
194
+ // instantiated twice). With refCount:true the producer would re-run
195
+ // createAppKit whenever every subscriber drained and a new one
196
+ // re-subscribed — e.g. a React unmount/remount or StrictMode's
197
+ // mount→unmount→remount — throwing on the duplicate Lit web components and
198
+ // WalletConnect modal singleton. The replayed connector value also keeps
199
+ // the wallet list stable across such teardown/rebuild cycles.
200
+ shareReplay({ refCount: false, bufferSize: 1 })
427
201
  );
202
+ setCachedAppKit(cachedAppKit, walletConnect.projectId);
428
203
  }
429
204
  return cachedAppKit;
430
205
  };
431
206
 
432
- // src/api/config.ts
433
- var DEFAULT_STORAGE_KEY = "kheopskit";
434
- var DEFAULT_CONFIG = {
435
- autoReconnect: true,
436
- platforms: ["polkadot"],
437
- polkadotAccountTypes: ["sr25519", "ed25519", "ecdsa"],
438
- debug: false,
439
- storageKey: DEFAULT_STORAGE_KEY,
440
- hydrationGracePeriod: 500
441
- };
442
- var VALID_POLKADOT_ACCOUNT_TYPES = /* @__PURE__ */ new Set([
443
- "sr25519",
444
- "ed25519",
445
- "ecdsa",
446
- "ethereum"
447
- ]);
448
- var resolveConfig = (config) => {
449
- const resolved = Object.assign({}, DEFAULT_CONFIG, config);
450
- const invalid = resolved.polkadotAccountTypes.filter(
451
- (t) => !VALID_POLKADOT_ACCOUNT_TYPES.has(t)
452
- );
453
- if (invalid.length > 0) {
454
- console.warn(
455
- `[kheopskit] Unknown polkadotAccountTypes: ${JSON.stringify(invalid)}. Valid values: "sr25519", "ed25519", "ecdsa", "ethereum".`
456
- );
457
- }
458
- return resolved;
459
- };
460
-
461
207
  // src/api/kheopskit.ts
462
208
  import {
463
- combineLatest as combineLatest9,
209
+ combineLatest as combineLatest4,
464
210
  debounceTime,
465
- distinctUntilChanged as distinctUntilChanged6,
211
+ distinctUntilChanged as distinctUntilChanged2,
466
212
  filter as filter3,
467
- map as map9,
468
- Observable as Observable9,
469
- shareReplay as shareReplay9,
213
+ map as map5,
214
+ Observable as Observable5,
215
+ shareReplay as shareReplay5,
470
216
  throttleTime
471
217
  } from "rxjs";
472
218
 
473
219
  // src/utils/createHydrationBuffer.ts
474
220
  import {
475
221
  BehaviorSubject as BehaviorSubject2,
476
- combineLatest as combineLatest2,
222
+ combineLatest,
477
223
  filter,
478
224
  map as map2,
479
225
  Observable as Observable2,
@@ -498,7 +244,7 @@ var createBufferCore = (cachedItems, liveItems$, gracePeriodMs, mergeFn, isConve
498
244
  shareReplay2({ bufferSize: 1, refCount: true })
499
245
  );
500
246
  subscriptions.add(
501
- combineLatest2([liveWithInitial$, timerFired$]).pipe(
247
+ combineLatest([liveWithInitial$, timerFired$]).pipe(
502
248
  filter(([, timerFired]) => timerFired),
503
249
  filter(([liveItems]) => isConverged(liveItems, cachedItems)),
504
250
  take(1)
@@ -521,7 +267,7 @@ var createBufferCore = (cachedItems, liveItems$, gracePeriodMs, mergeFn, isConve
521
267
  );
522
268
  }
523
269
  subscriptions.add(
524
- combineLatest2([liveWithInitial$, isHydrating$]).pipe(
270
+ combineLatest([liveWithInitial$, isHydrating$]).pipe(
525
271
  map2(([liveItems, isHydrating]) => {
526
272
  if (!isHydrating) {
527
273
  return { items: liveItems, isHydrating: false };
@@ -584,8 +330,8 @@ var createAccountHydrationBuffer = (cachedAccounts, liveAccounts$, gracePeriodMs
584
330
  };
585
331
 
586
332
  // src/utils/logObservable.ts
587
- import { tap } from "rxjs";
588
- var logObservable = (label, opts) => tap((value) => {
333
+ import { tap as tap2 } from "rxjs";
334
+ var logObservable = (label, opts) => tap2((value) => {
589
335
  const { printValue = false, enabled = true } = opts || {};
590
336
  if (!label || !enabled) return;
591
337
  const text = `[kheopskit] observable ${label} emit`;
@@ -594,925 +340,86 @@ var logObservable = (label, opts) => tap((value) => {
594
340
  });
595
341
 
596
342
  // src/api/accounts.ts
597
- import { combineLatest as combineLatest5, map as map5, Observable as Observable5, of as of4, shareReplay as shareReplay5 } from "rxjs";
598
-
599
- // src/utils/sortAccounts.ts
600
- var sortAccounts = (a1, a2) => {
601
- if (a1.platform === "polkadot") {
602
- if (a2.platform === "polkadot") {
603
- if (a1.walletName !== a2.walletName) {
604
- if (a1.walletName === "talisman") return -1;
605
- if (a2.walletName === "talisman") return 1;
606
- return a1.walletName.localeCompare(a2.walletName);
607
- }
608
- return a1.name !== a2.name ? (a1.name ?? "").localeCompare(a2.name ?? "") : a1.address.localeCompare(a2.address);
609
- }
610
- return -1;
611
- }
612
- if (a2.platform === "ethereum") {
613
- if (a1.walletName !== a2.walletName) {
614
- if (a1.walletName === "Talisman") return -1;
615
- if (a2.walletName === "Talisman") return 1;
616
- return a1.walletName.localeCompare(a2.walletName);
617
- }
618
- return a1.id.localeCompare(a2.id);
619
- }
620
- return 0;
621
- };
622
-
623
- // src/api/ethereum/accounts.ts
624
- import {
625
- combineLatest as combineLatest3,
626
- distinctUntilChanged as distinctUntilChanged2,
627
- map as map3,
628
- Observable as Observable3,
629
- of as of2,
630
- ReplaySubject,
631
- shareReplay as shareReplay3,
632
- switchMap as switchMap2
633
- } from "rxjs";
634
- import {
635
- createWalletClient,
636
- custom,
637
- getAddress
638
- } from "viem";
639
-
640
- // src/utils/createStore.ts
641
- import { BehaviorSubject as BehaviorSubject3 } from "rxjs";
642
- var createStore = (key, defaultValue, storage = safeLocalStorage) => {
643
- const subject = new BehaviorSubject3(
644
- getStoredData(key, defaultValue, storage)
645
- );
646
- let unsubscribeStorage;
647
- if (typeof window !== "undefined" && storage.subscribe) {
648
- unsubscribeStorage = storage.subscribe(key, (newValue) => {
649
- subject.next(parseData(newValue, defaultValue));
650
- });
651
- }
652
- const update = (val) => {
653
- setStoredData(key, val, storage);
654
- subject.next(val);
655
- };
656
- return {
657
- observable: subject.asObservable(),
658
- set: (val) => update(val),
659
- mutate: (transform) => update(transform(subject.getValue())),
660
- get: () => structuredClone(subject.getValue()),
661
- /**
662
- * Cleanup subscriptions. Call this when the store is no longer needed.
663
- */
664
- destroy: () => {
665
- unsubscribeStorage?.();
666
- subject.complete();
667
- }
668
- };
669
- };
670
- var parseData = (str, defaultValue) => {
671
- try {
672
- if (str) return JSON.parse(str);
673
- } catch {
674
- }
675
- return defaultValue;
676
- };
677
- var getStoredData = (key, defaultValue, storage) => {
678
- const str = storage.getItem(key);
679
- return parseData(str, defaultValue);
680
- };
681
- var setStoredData = (key, val, storage) => {
682
- const str = JSON.stringify(val);
683
- storage.setItem(key, str);
684
- };
685
-
686
- // src/utils/isEthereumAddress.ts
687
- import { isAddress } from "viem";
688
- var isEthereumAddress = (address) => isAddress(address);
689
-
690
- // src/utils/isSs58Address.ts
691
- import { AccountId } from "polkadot-api";
692
- var accountIdEncoder = AccountId().enc;
693
- var isSs58Address = (address) => {
694
- try {
695
- if (!address) return false;
696
- accountIdEncoder(address);
697
- return true;
698
- } catch {
699
- return false;
700
- }
701
- };
702
-
703
- // src/utils/isValidAddress.ts
704
- var isValidAddress = (address) => {
705
- return address.startsWith("0x") ? isEthereumAddress(address) : isSs58Address(address);
706
- };
707
-
708
- // src/utils/WalletAccountId.ts
709
- var getWalletAccountId = (walletId, address) => {
710
- if (!walletId) throw new Error("Missing walletId");
711
- if (!isValidAddress(address)) throw new Error("Invalid address");
712
- return `${walletId}::${address}`;
713
- };
714
-
715
- // src/api/ethereum/accounts.ts
716
- var normalizeEvmChainId = (value) => {
717
- let raw = value;
718
- if (typeof raw === "string" && raw.startsWith("eip155:")) {
719
- raw = raw.slice("eip155:".length);
720
- }
721
- if (typeof raw === "bigint") {
722
- return raw >= 0n ? Number(raw) : void 0;
723
- }
724
- if (typeof raw === "number") {
725
- return Number.isInteger(raw) && raw >= 0 ? raw : void 0;
726
- }
727
- if (typeof raw === "string") {
728
- const normalized = raw.trim().toLowerCase();
729
- if (!normalized) return void 0;
730
- const parsed = normalized.startsWith("0x") ? Number.parseInt(normalized, 16) : Number.parseInt(normalized, 10);
731
- return Number.isNaN(parsed) ? void 0 : parsed;
732
- }
733
- return void 0;
734
- };
735
- var toCaipNetworkId = (value) => {
736
- const chainId = normalizeEvmChainId(value);
737
- return chainId === void 0 ? void 0 : `eip155:${chainId}`;
738
- };
739
- var getInjectedWalletAccounts$ = (wallet) => {
740
- if (!wallet.isConnected) return of2([]);
741
- return getCachedObservable$(
742
- `accounts:${wallet.id}`,
743
- () => new Observable3((subscriber) => {
744
- const addresses$ = new ReplaySubject(1);
745
- const chainId$ = new ReplaySubject(1);
746
- const getAccount = (address, i, chainId) => {
747
- const client = createWalletClient({
748
- account: address,
749
- transport: custom(wallet.provider)
750
- });
751
- return {
752
- id: getWalletAccountId(wallet.id, address),
753
- platform: "ethereum",
754
- client,
755
- address: getAddress(address),
756
- chainId,
757
- walletName: wallet.name,
758
- walletId: wallet.id,
759
- isWalletDefault: i === 0
760
- };
761
- };
762
- const handleAccountsChanged = (addrs) => {
763
- addresses$.next(addrs);
764
- };
765
- const handleChainChanged = (chainIdHex) => {
766
- chainId$.next(normalizeEvmChainId(chainIdHex));
767
- };
768
- const handleDisconnect = () => {
769
- chainId$.next(void 0);
770
- };
771
- wallet.provider.on("accountsChanged", handleAccountsChanged);
772
- wallet.provider.on("chainChanged", handleChainChanged);
773
- wallet.provider.on("disconnect", handleDisconnect);
774
- wallet.provider.request({ method: "eth_accounts" }).then((addrs) => addresses$.next(addrs)).catch((err) => {
775
- console.error("Failed to get accounts", err);
776
- addresses$.next([]);
777
- });
778
- wallet.provider.request({ method: "eth_chainId" }).then(handleChainChanged).catch(() => chainId$.next(void 0));
779
- const sub = combineLatest3([addresses$, chainId$]).pipe(
780
- map3(
781
- ([addresses, chainId]) => addresses.map((addr, i) => getAccount(addr, i, chainId))
782
- )
783
- ).subscribe(subscriber);
784
- return () => {
785
- wallet.provider.removeListener(
786
- "accountsChanged",
787
- handleAccountsChanged
788
- );
789
- wallet.provider.removeListener("chainChanged", handleChainChanged);
790
- wallet.provider.removeListener("disconnect", handleDisconnect);
791
- sub.unsubscribe();
792
- };
793
- }).pipe(shareReplay3({ refCount: true, bufferSize: 1 }))
794
- );
795
- };
796
- var wrapWalletConnectProvider = (provider, sessionTopic, caipNetworkId) => {
797
- return new Proxy(provider, {
798
- get(target, prop, receiver) {
799
- if (prop !== "request") return Reflect.get(target, prop, receiver);
800
- return (args) => {
801
- if (args && typeof args === "object" && args.method) {
802
- if (!args.topic) args.topic = sessionTopic;
803
- if (!args.chainId) args.chainId = caipNetworkId;
804
- }
805
- return target.request(args);
806
- };
807
- }
808
- });
809
- };
810
- var getAppKitAccounts$ = (wallet) => {
811
- const account = wallet.appKit.getAccount("eip155");
812
- const provider = wallet.appKit.getProvider("eip155");
813
- if (!wallet.isConnected || !wallet.appKit || !account?.allAccounts.length || !provider?.session)
814
- return of2([]);
815
- return getCachedObservable$(
816
- "accounts:appKit",
817
- () => new Observable3((subscriber) => {
818
- const caipNetworkId$ = new ReplaySubject(1);
819
- const handleChainChanged = (chainId) => {
820
- const caipNetworkId = toCaipNetworkId(chainId);
821
- if (caipNetworkId) {
822
- caipNetworkId$.next(caipNetworkId);
823
- }
824
- };
825
- provider.on("chainChanged", handleChainChanged);
826
- provider.request({ method: "eth_chainId" }).then(handleChainChanged);
827
- const sub = caipNetworkId$.pipe(
828
- distinctUntilChanged2(),
829
- map3((caipNetworkId) => {
830
- const chainId = normalizeEvmChainId(caipNetworkId);
831
- const transport = custom(
832
- wrapWalletConnectProvider(
833
- provider,
834
- // biome-ignore lint/style/noNonNullAssertion: legacy
835
- provider.session.topic,
836
- caipNetworkId
837
- )
838
- );
839
- return { transport, chainId };
840
- }),
841
- map3(
842
- ({ transport, chainId }) => account.allAccounts.map((acc, i) => {
843
- const client = createWalletClient({
844
- account: acc.address,
845
- transport
846
- });
847
- return {
848
- id: getWalletAccountId(wallet.id, acc.address),
849
- platform: "ethereum",
850
- walletName: wallet.name,
851
- walletId: wallet.id,
852
- address: acc.address,
853
- client,
854
- chainId,
855
- isWalletDefault: i === 0
856
- };
857
- })
858
- )
859
- ).subscribe(subscriber);
860
- return () => {
861
- provider.off("chainChanged", handleChainChanged);
862
- sub.unsubscribe();
863
- };
864
- }).pipe(shareReplay3({ refCount: true, bufferSize: 1 }))
865
- );
866
- };
867
- var getEthereumAccounts$ = (ethereumWallets) => new Observable3((subscriber) => {
868
- const sub = ethereumWallets.pipe(
869
- map3((wallets) => wallets.filter((w) => w.isConnected)),
870
- switchMap2((wallets) => {
871
- return wallets.length ? combineLatest3([
872
- ...wallets.filter((w) => w.type === "injected").map(getInjectedWalletAccounts$),
873
- ...wallets.filter((w) => w.type === "appKit").map(getAppKitAccounts$)
874
- // todo appkit
875
- ]) : of2([]);
876
- }),
877
- map3((accounts) => accounts.flat()),
878
- distinctUntilChanged2(isSameAccountsList)
879
- ).subscribe(subscriber);
880
- return () => {
881
- sub.unsubscribe();
882
- };
883
- }).pipe(
884
- // logObservable("ethereumAccounts$", true),
885
- shareReplay3({ refCount: true, bufferSize: 1 })
886
- );
887
- var isSameAccountsList = (a, b) => {
888
- if (a.length !== b.length) return false;
889
- return a.every(
890
- (account, i) => account.id === b[i]?.id && account.chainId === b[i]?.chainId
891
- );
892
- };
893
-
894
- // src/api/polkadot/accounts.ts
895
- import {
896
- getPolkadotSignerFromPjs
897
- } from "polkadot-api/pjs-signer";
898
- import {
899
- combineLatest as combineLatest4,
900
- distinctUntilChanged as distinctUntilChanged3,
901
- map as map4,
902
- Observable as Observable4,
903
- of as of3,
904
- shareReplay as shareReplay4,
905
- switchMap as switchMap3
906
- } from "rxjs";
907
- var getInjectedWalletAccounts$2 = (wallet) => {
908
- if (!wallet.isConnected) return of3([]);
909
- return new Observable4((subscriber) => {
910
- const getAccount = (account) => ({
911
- id: getWalletAccountId(wallet.id, account.address),
912
- ...account,
913
- type: account.type ?? "sr25519",
914
- platform: "polkadot",
915
- walletName: wallet.name,
916
- walletId: wallet.id
917
- });
918
- const extension = wallet.extension;
919
- const unsubscribe = extension.subscribe((accounts) => {
920
- subscriber.next(accounts.map(getAccount));
921
- });
922
- subscriber.next(extension.getAccounts().map(getAccount));
923
- return () => {
924
- return unsubscribe();
925
- };
926
- });
927
- };
928
- var getAppKitPolkadotSigner = (appKit, address) => {
929
- const provider = appKit.getProvider("polkadot");
930
- if (!provider) throw new Error("No provider found");
931
- if (!provider.session) throw new Error("No session found");
932
- return getPolkadotSignerFromPjs(
933
- address,
934
- (transactionPayload) => {
935
- if (!provider.session) throw new Error("No session found");
936
- return provider.client.request({
937
- topic: provider.session.topic,
938
- chainId: `polkadot:${transactionPayload.genesisHash.substring(2, 34)}`,
939
- request: {
940
- method: "polkadot_signTransaction",
941
- params: {
942
- address,
943
- transactionPayload
944
- }
945
- }
946
- });
947
- },
948
- async ({ address: address2, data }) => {
949
- if (!provider.session) throw new Error("No session found");
950
- const networks = appKit.getCaipNetworks("polkadot");
951
- const chainId = networks[0]?.caipNetworkId;
952
- if (!chainId) throw new Error("No chainId found");
953
- return provider.client.request({
954
- topic: provider.session.topic,
955
- chainId,
956
- request: {
957
- method: "polkadot_signMessage",
958
- params: {
959
- address: address2,
960
- message: data
961
- }
962
- }
963
- });
964
- }
965
- );
966
- };
967
- var getAppKitAccounts$2 = (wallet) => {
968
- const account = wallet.appKit.getAccount("polkadot");
969
- const provider = wallet.appKit.getProvider("polkadot");
970
- if (!wallet.isConnected || !wallet.appKit || !account?.allAccounts.length || !provider?.session)
971
- return of3([]);
972
- return of3(
973
- account.allAccounts.map(
974
- (acc) => ({
975
- id: getWalletAccountId(wallet.id, acc.address),
976
- platform: "polkadot",
977
- walletName: wallet.name,
978
- walletId: wallet.id,
979
- address: acc.address,
980
- polkadotSigner: getAppKitPolkadotSigner(wallet.appKit, acc.address),
981
- genesisHash: null,
982
- name: `${wallet.name} Polkadot`,
983
- // WalletConnect (Reown AppKit) doesn't expose account key type;
984
- // default to sr25519, which is the most common Polkadot key type.
985
- type: "sr25519"
986
- })
987
- )
988
- );
989
- };
990
- var getPolkadotAccounts$ = (polkadotWallets$, polkadotAccountTypes) => new Observable4((subscriber) => {
991
- if (polkadotAccountTypes.length === 0) {
992
- console.warn(
993
- "[kheopskit] config.polkadotAccountTypes is empty; all Polkadot accounts will be filtered out."
994
- );
995
- }
996
- const sub = polkadotWallets$.pipe(
997
- map4((wallets) => wallets.filter((w) => w.isConnected)),
998
- switchMap3(
999
- (wallets) => wallets.length ? combineLatest4([
1000
- ...wallets.filter((w) => w.type === "injected").map(getInjectedWalletAccounts$2),
1001
- ...wallets.filter((w) => w.type === "appKit").map(getAppKitAccounts$2)
1002
- ]) : of3([])
1003
- ),
1004
- map4(
1005
- (accounts) => accounts.flat().filter((account) => polkadotAccountTypes.includes(account.type))
1006
- ),
1007
- distinctUntilChanged3(isSameAccountsList2)
1008
- ).subscribe(subscriber);
1009
- return () => {
1010
- sub.unsubscribe();
1011
- };
1012
- }).pipe(shareReplay4({ refCount: true, bufferSize: 1 }));
1013
- var isSameAccountsList2 = (a, b) => {
1014
- if (a.length !== b.length) return false;
1015
- return a.every((account, i) => account.id === b[i]?.id);
1016
- };
1017
-
1018
- // src/api/accounts.ts
343
+ import { combineLatest as combineLatest2, map as map3, Observable as Observable3, of as of2, shareReplay as shareReplay3 } from "rxjs";
1019
344
  var getAccounts$ = (config, wallets) => {
1020
- return new Observable5((subscriber) => {
345
+ return new Observable3((subscriber) => {
1021
346
  const sources = config.platforms.map(
1022
- (platform) => {
1023
- switch (platform) {
1024
- case "polkadot":
1025
- return getPolkadotAccounts$(
1026
- wallets.pipe(
1027
- map5((w) => w.filter((w2) => w2.platform === "polkadot"))
1028
- ),
1029
- config.polkadotAccountTypes
1030
- );
1031
- case "ethereum":
1032
- return getEthereumAccounts$(
1033
- wallets.pipe(
1034
- map5((w) => w.filter((w2) => w2.platform === "ethereum"))
1035
- )
1036
- );
1037
- }
1038
- }
347
+ (plugin) => plugin.getAccounts$(
348
+ wallets.pipe(
349
+ map3(
350
+ (ws) => ws.filter(
351
+ (w) => isWalletConnectWallet(w) || w.platform === plugin.platform
352
+ )
353
+ )
354
+ )
355
+ )
1039
356
  );
1040
- const accounts$ = sources.length ? combineLatest5(sources).pipe(
1041
- map5((accounts) => accounts.flat().sort(sortAccounts))
1042
- ) : of4([]);
357
+ const accounts$ = sources.length ? combineLatest2(sources).pipe(
358
+ map3((accounts) => accounts.flat().sort(sortAccounts))
359
+ ) : of2([]);
1043
360
  const sub = accounts$.subscribe(subscriber);
1044
361
  return () => {
1045
362
  sub.unsubscribe();
1046
363
  };
1047
- }).pipe(shareReplay5({ refCount: true, bufferSize: 1 }));
1048
- };
1049
-
1050
- // src/api/store.ts
1051
- import { uniq } from "lodash-es";
1052
- var DEFAULT_SETTINGS = {};
1053
- var toCompactPolkadotAccountType = (type) => {
1054
- switch (type) {
1055
- case "sr25519":
1056
- return 0;
1057
- case "ed25519":
1058
- return 1;
1059
- case "ecdsa":
1060
- return 2;
1061
- case "ethereum":
1062
- return 3;
1063
- default:
1064
- return null;
1065
- }
1066
- };
1067
- var fromCompactPolkadotAccountType = (type) => {
1068
- switch (type) {
1069
- case 0:
1070
- return "sr25519";
1071
- case 1:
1072
- return "ed25519";
1073
- case 2:
1074
- return "ecdsa";
1075
- case 3:
1076
- return "ethereum";
1077
- default:
1078
- return void 0;
1079
- }
1080
- };
1081
- var createKheopskitStore = (options = {}) => {
1082
- const { ssrCookies, storageKey = DEFAULT_STORAGE_KEY } = options;
1083
- const storage = ssrCookies !== void 0 ? createCompactCookieStorage(ssrCookies) : safeLocalStorage;
1084
- const store2 = createStore(storageKey, DEFAULT_SETTINGS, storage);
1085
- const addEnabledWalletId = (walletId) => {
1086
- parseWalletId(walletId);
1087
- store2.mutate((prev) => ({
1088
- ...prev,
1089
- autoReconnect: uniq((prev.autoReconnect ?? []).concat(walletId))
1090
- }));
1091
- };
1092
- const removeEnabledWalletId = (walletId) => {
1093
- store2.mutate((prev) => ({
1094
- ...prev,
1095
- autoReconnect: uniq(
1096
- (prev.autoReconnect ?? []).filter((id) => id !== walletId)
1097
- )
1098
- }));
1099
- };
1100
- const getCachedState = () => {
1101
- const data = store2.get();
1102
- return {
1103
- wallets: data.cachedWallets ?? [],
1104
- accounts: data.cachedAccounts ?? []
1105
- };
1106
- };
1107
- const setCachedState = (wallets, accounts) => {
1108
- store2.mutate((prev) => ({
1109
- ...prev,
1110
- cachedWallets: wallets,
1111
- cachedAccounts: accounts
1112
- }));
1113
- };
1114
- return {
1115
- observable: store2.observable,
1116
- addEnabledWalletId,
1117
- removeEnabledWalletId,
1118
- getCachedState,
1119
- setCachedState
1120
- };
1121
- };
1122
- var _defaultStore = null;
1123
- var getDefaultStore = () => {
1124
- if (_defaultStore === null) {
1125
- _defaultStore = createKheopskitStore();
1126
- }
1127
- return _defaultStore;
1128
- };
1129
- var store = {
1130
- get observable() {
1131
- return getDefaultStore().observable;
1132
- },
1133
- addEnabledWalletId: (walletId) => getDefaultStore().addEnabledWalletId(walletId),
1134
- removeEnabledWalletId: (walletId) => getDefaultStore().removeEnabledWalletId(walletId),
1135
- getCachedState: () => getDefaultStore().getCachedState(),
1136
- setCachedState: (wallets, accounts) => getDefaultStore().setCachedState(wallets, accounts)
1137
- };
1138
- var isCompactStore = (value) => {
1139
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
1140
- if ("cachedWallets" in value || "cachedAccounts" in value) return false;
1141
- return "v" in value || "w" in value || "a" in value || "r" in value;
1142
- };
1143
- var toCompactStore = (data) => {
1144
- const wallets = data.cachedWallets?.map(
1145
- (wallet) => [
1146
- wallet.id,
1147
- wallet.name,
1148
- wallet.isConnected ? 1 : 0,
1149
- wallet.type === "appKit" ? 1 : 0
1150
- ]
1151
- );
1152
- const accounts = data.cachedAccounts?.map(
1153
- (account) => [
1154
- account.walletId,
1155
- account.address,
1156
- account.name ?? null,
1157
- account.chainId ?? null,
1158
- toCompactPolkadotAccountType(account.polkadotAccountType)
1159
- ]
1160
- );
1161
- return {
1162
- v: 1,
1163
- r: data.autoReconnect,
1164
- w: wallets?.length ? wallets : void 0,
1165
- a: accounts?.length ? accounts : void 0
1166
- };
1167
- };
1168
- var fromCompactStore = (data) => {
1169
- const walletNameMap = /* @__PURE__ */ new Map();
1170
- const wallets = (data.w ?? []).map((item) => {
1171
- const [id, name, isConnected, type] = item;
1172
- walletNameMap.set(id, name);
1173
- const { platform } = parseWalletId(id);
1174
- return {
1175
- id,
1176
- platform,
1177
- type: type === 1 ? "appKit" : "injected",
1178
- name,
1179
- isConnected: isConnected === 1
1180
- };
1181
- });
1182
- const accounts = (data.a ?? []).map((item) => {
1183
- const [walletId, address, name, chainId, polkadotAccountType] = item;
1184
- const { platform } = parseWalletId(walletId);
1185
- return {
1186
- id: getWalletAccountId(walletId, address),
1187
- platform,
1188
- address,
1189
- name: name ?? void 0,
1190
- chainId: chainId ?? void 0,
1191
- polkadotAccountType: platform === "polkadot" ? fromCompactPolkadotAccountType(polkadotAccountType) : void 0,
1192
- walletId,
1193
- walletName: walletNameMap.get(walletId) ?? walletId
1194
- };
1195
- });
1196
- return {
1197
- autoReconnect: data.r,
1198
- cachedWallets: wallets,
1199
- cachedAccounts: accounts
1200
- };
1201
- };
1202
- var decodeStore = (raw, fallback) => {
1203
- try {
1204
- const parsed = JSON.parse(raw);
1205
- if (isCompactStore(parsed)) return fromCompactStore(parsed);
1206
- return parsed;
1207
- } catch {
1208
- return fallback;
1209
- }
1210
- };
1211
- var encodeStore = (data) => JSON.stringify(toCompactStore(data));
1212
- var createCompactCookieStorage = (initialCookies) => {
1213
- const base = cookieStorage(initialCookies);
1214
- return {
1215
- getItem: (key) => {
1216
- const raw = base.getItem(key);
1217
- if (!raw) return null;
1218
- const expanded = decodeStore(raw, DEFAULT_SETTINGS);
1219
- if (typeof document !== "undefined") {
1220
- try {
1221
- const parsed = JSON.parse(raw);
1222
- if (!isCompactStore(parsed)) {
1223
- base.setItem(key, encodeStore(expanded));
1224
- }
1225
- } catch {
1226
- }
1227
- }
1228
- return JSON.stringify(expanded);
1229
- },
1230
- setItem: (key, value) => {
1231
- const expanded = decodeStore(value, DEFAULT_SETTINGS);
1232
- base.setItem(key, encodeStore(expanded));
1233
- },
1234
- removeItem: base.removeItem,
1235
- subscribe: (key, callback) => {
1236
- const unsubscribe = base.subscribe?.(key, (value) => {
1237
- if (!value) {
1238
- callback(null);
1239
- return;
1240
- }
1241
- const expanded = decodeStore(value, DEFAULT_SETTINGS);
1242
- callback(JSON.stringify(expanded));
1243
- });
1244
- return () => {
1245
- unsubscribe?.();
1246
- };
1247
- }
1248
- };
364
+ }).pipe(shareReplay3({ refCount: true, bufferSize: 1 }));
1249
365
  };
1250
366
 
1251
367
  // src/api/wallets.ts
1252
368
  import {
1253
- combineLatest as combineLatest8,
1254
- distinct,
369
+ combineLatest as combineLatest3,
1255
370
  filter as filter2,
1256
- map as map8,
371
+ map as map4,
1257
372
  mergeMap,
1258
- Observable as Observable8,
1259
- of as of5,
1260
- shareReplay as shareReplay8,
373
+ Observable as Observable4,
374
+ of as of3,
375
+ shareReplay as shareReplay4,
1261
376
  take as take2
1262
377
  } from "rxjs";
1263
-
1264
- // src/utils/sortWallets.ts
1265
- var sortWallets = (w1, w2) => {
1266
- if (w1.platform !== w2.platform) {
1267
- return w1.platform === "polkadot" ? -1 : 1;
1268
- }
1269
- if (w1.name.toLowerCase() === "talisman") return -1;
1270
- if (w2.name.toLowerCase() === "talisman") return 1;
1271
- return w1.name.localeCompare(w2.name);
1272
- };
1273
-
1274
- // src/api/ethereum/wallets.ts
1275
- import {
1276
- createStore as createMipdStore
1277
- } from "mipd";
1278
- import {
1279
- BehaviorSubject as BehaviorSubject4,
1280
- combineLatest as combineLatest6,
1281
- distinctUntilChanged as distinctUntilChanged4,
1282
- map as map6,
1283
- Observable as Observable6,
1284
- shareReplay as shareReplay6
1285
- } from "rxjs";
1286
- var providersDetails$ = new Observable6(
1287
- (subscriber) => {
1288
- if (typeof window === "undefined") {
1289
- subscriber.next([]);
1290
- return () => {
1291
- };
1292
- }
1293
- const mipdStore = createMipdStore();
1294
- const unsubscribe = mipdStore.subscribe((providerDetails2) => {
1295
- subscriber.next(providerDetails2);
1296
- });
1297
- const providerDetails = mipdStore.getProviders();
1298
- subscriber.next(providerDetails);
1299
- return () => {
1300
- unsubscribe();
1301
- mipdStore.destroy();
1302
- };
1303
- }
1304
- ).pipe(shareReplay6({ refCount: true, bufferSize: 1 }));
1305
- var createEthereumInjectedWallets$ = (store2) => new Observable6((subscriber) => {
1306
- const enabledWalletIds$ = new BehaviorSubject4(/* @__PURE__ */ new Set());
1307
- const connectWallet = async (walletId, provider) => {
1308
- if (enabledWalletIds$.value.has(walletId))
1309
- throw new Error(`Extension ${walletId} already connected`);
1310
- await provider.request({
1311
- method: "eth_requestAccounts"
1312
- });
1313
- const newSet = new Set(enabledWalletIds$.value);
1314
- newSet.add(walletId);
1315
- enabledWalletIds$.next(newSet);
1316
- store2.addEnabledWalletId(walletId);
1317
- };
1318
- const disconnectWallet = async (walletId) => {
1319
- if (!enabledWalletIds$.value.has(walletId))
1320
- throw new Error(`Extension ${walletId} is not connected`);
1321
- const newSet = new Set(enabledWalletIds$.value);
1322
- newSet.delete(walletId);
1323
- enabledWalletIds$.next(newSet);
1324
- store2.removeEnabledWalletId(walletId);
1325
- };
1326
- const sub = combineLatest6([providersDetails$, enabledWalletIds$]).pipe(
1327
- map6(([providerDetails, enabledWalletIds]) => {
1328
- return providerDetails.map((pd) => {
1329
- const walletId = getWalletId("ethereum", pd.info.rdns);
1330
- const provider = pd.provider;
1331
- return {
1332
- platform: "ethereum",
1333
- type: "injected",
1334
- id: walletId,
1335
- name: pd.info.name,
1336
- icon: pd.info.icon,
1337
- provider,
1338
- isConnected: enabledWalletIds.has(walletId),
1339
- providerId: pd.info.rdns,
1340
- connect: () => connectWallet(walletId, provider),
1341
- disconnect: () => disconnectWallet(walletId)
1342
- };
1343
- });
1344
- }),
1345
- distinctUntilChanged4(walletsEqual)
1346
- ).subscribe(subscriber);
1347
- return () => {
1348
- sub.unsubscribe();
1349
- };
1350
- }).pipe(shareReplay6({ refCount: true, bufferSize: 1 }));
1351
- var getEthereumWallets$ = (config, store2 = store) => {
1352
- return new Observable6((subscriber) => {
1353
- const subscription = combineLatest6([
1354
- createEthereumInjectedWallets$(store2),
1355
- getAppKitWallets$(config)?.pipe(map6((w) => w.ethereum))
1356
- ]).pipe(
1357
- map6(
1358
- ([injectedWallets, appKitWallet]) => appKitWallet ? [...injectedWallets, appKitWallet] : injectedWallets
1359
- )
1360
- ).subscribe(subscriber);
1361
- return () => {
1362
- subscription.unsubscribe();
1363
- };
1364
- }).pipe(shareReplay6({ refCount: true, bufferSize: 1 }));
1365
- };
1366
- var walletsEqual = (a, b) => {
1367
- if (a.length !== b.length) return false;
1368
- return a.every(
1369
- (w, i) => w.id === b[i]?.id && w.isConnected === b[i]?.isConnected && w.name === b[i]?.name
1370
- );
1371
- };
1372
-
1373
- // src/api/polkadot/wallets.ts
1374
- import { isEqual } from "lodash-es";
1375
- import {
1376
- connectInjectedExtension,
1377
- getInjectedExtensions
1378
- } from "polkadot-api/pjs-signer";
1379
- import {
1380
- BehaviorSubject as BehaviorSubject5,
1381
- combineLatest as combineLatest7,
1382
- distinctUntilChanged as distinctUntilChanged5,
1383
- map as map7,
1384
- Observable as Observable7,
1385
- shareReplay as shareReplay7
1386
- } from "rxjs";
1387
- var getInjectedWalletsIds = () => typeof window === "undefined" ? [] : getInjectedExtensions().map((name) => getWalletId("polkadot", name));
1388
- var createWalletIdsPoller$ = () => {
1389
- return new Observable7((subscriber) => {
1390
- subscriber.next(getInjectedWalletsIds());
1391
- const intervals = [100, 200, 300, 500];
1392
- let index = 0;
1393
- const poll = () => {
1394
- subscriber.next(getInjectedWalletsIds());
1395
- if (index < intervals.length) {
1396
- const delay = intervals[index++];
1397
- setTimeout(poll, delay);
1398
- }
1399
- };
1400
- if (intervals.length > 0) {
1401
- setTimeout(poll, intervals[index++] ?? 100);
1402
- }
1403
- return () => {
1404
- };
1405
- }).pipe(
1406
- distinctUntilChanged5(isEqual),
1407
- shareReplay7({ refCount: true, bufferSize: 1 })
1408
- );
1409
- };
1410
- var createPolkadotInjectedWallets$ = (store2) => new Observable7((subscriber) => {
1411
- const enabledExtensions$ = new BehaviorSubject5(/* @__PURE__ */ new Map());
1412
- const connect = async (walletId) => {
1413
- if (enabledExtensions$.value.has(walletId))
1414
- throw new Error(`Extension ${walletId} already connected`);
1415
- const { identifier } = parseWalletId(walletId);
1416
- const extension = await connectInjectedExtension(identifier);
1417
- const newMap = new Map(enabledExtensions$.value);
1418
- newMap.set(walletId, extension);
1419
- enabledExtensions$.next(newMap);
1420
- store2.addEnabledWalletId(walletId);
1421
- };
1422
- const disconnect = (walletId) => {
1423
- if (!enabledExtensions$.value.has(walletId))
1424
- throw new Error(`Extension ${walletId} is not connected`);
1425
- const newMap = new Map(enabledExtensions$.value);
1426
- newMap.delete(walletId);
1427
- enabledExtensions$.next(newMap);
1428
- store2.removeEnabledWalletId(walletId);
1429
- };
1430
- const walletIds$ = createWalletIdsPoller$();
1431
- const subscription = combineLatest7([walletIds$, enabledExtensions$]).pipe(
1432
- map7(([walletIds, enabledExtensions]) => {
1433
- return walletIds.map((id) => {
1434
- const { identifier } = parseWalletId(id);
1435
- const extension = enabledExtensions.get(id);
1436
- const extInfo = POLKADOT_EXTENSIONS[identifier];
1437
- return {
1438
- id,
1439
- type: "injected",
1440
- platform: "polkadot",
1441
- name: extInfo?.name ?? identifier,
1442
- icon: extInfo?.icon ?? "",
1443
- extensionId: identifier,
1444
- extension,
1445
- isConnected: !!extension,
1446
- connect: () => connect(id),
1447
- disconnect: () => disconnect(id)
1448
- };
1449
- });
1450
- }),
1451
- distinctUntilChanged5(walletsEqual2)
1452
- ).subscribe(subscriber);
1453
- return () => {
1454
- subscription.unsubscribe();
1455
- };
1456
- }).pipe(shareReplay7({ refCount: true, bufferSize: 1 }));
1457
- var getPolkadotWallets$ = (config, store2 = store) => {
1458
- return new Observable7((subscriber) => {
1459
- const subscription = combineLatest7([
1460
- createPolkadotInjectedWallets$(store2),
1461
- getAppKitWallets$(config)?.pipe(map7((w) => w.polkadot))
1462
- ]).pipe(
1463
- map7(
1464
- ([injectedWallets, appKitWallet]) => appKitWallet ? [...injectedWallets, appKitWallet] : injectedWallets
1465
- )
1466
- ).subscribe(subscriber);
1467
- return () => {
1468
- subscription.unsubscribe();
1469
- };
1470
- }).pipe(shareReplay7({ refCount: true, bufferSize: 1 }));
1471
- };
1472
- var walletsEqual2 = (a, b) => {
1473
- if (a.length !== b.length) return false;
1474
- return a.every(
1475
- (w, i) => w.id === b[i]?.id && w.isConnected === b[i]?.isConnected && w.name === b[i]?.name
1476
- );
1477
- };
1478
-
1479
- // src/api/wallets.ts
1480
378
  var getWallets$ = (config, store2 = store) => {
1481
379
  const autoReconnectWalletIds$ = store2.observable.pipe(
1482
- map8((s) => s.autoReconnect ?? []),
380
+ map4((s) => s.autoReconnect ?? []),
1483
381
  take2(1),
1484
- shareReplay8({ bufferSize: 1, refCount: true })
382
+ shareReplay4({ bufferSize: 1, refCount: true })
1485
383
  );
1486
- return new Observable8((subscriber) => {
384
+ return new Observable4((subscriber) => {
385
+ const ctx = { config, store: store2 };
1487
386
  const observables = config.platforms.map(
1488
- (platform) => {
1489
- switch (platform) {
1490
- case "polkadot":
1491
- return getPolkadotWallets$(config, store2);
1492
- case "ethereum":
1493
- return getEthereumWallets$(config, store2);
1494
- }
1495
- }
387
+ (plugin) => plugin.getWallets$(ctx)
1496
388
  );
1497
- const wallets$ = observables.length ? combineLatest8(observables).pipe(
1498
- map8((wallets) => wallets.flat().sort(sortWallets))
389
+ const platformWallets$ = observables.length ? combineLatest3(observables).pipe(map4((wallets) => wallets.flat())) : of3([]);
390
+ const wallets$ = combineLatest3([
391
+ platformWallets$,
392
+ getWalletConnectWallet$(config)
393
+ ]).pipe(
394
+ map4(([platformWallets, walletConnect]) => {
395
+ const all = walletConnect ? [...platformWallets, walletConnect] : platformWallets;
396
+ return all.sort(sortWallets);
397
+ })
1499
398
  // Note: No startWith([]) here - the hydration buffer handles initial state
1500
- ) : of5([]);
399
+ );
1501
400
  const reconnectingWallets = /* @__PURE__ */ new Set();
1502
- const subAutoReconnect = combineLatest8([wallets$, autoReconnectWalletIds$]).pipe(
401
+ const reconnectedWallets = /* @__PURE__ */ new Set();
402
+ const MAX_RECONNECT_ATTEMPTS = 3;
403
+ const failedAttempts = /* @__PURE__ */ new Map();
404
+ const subAutoReconnect = combineLatest3([wallets$, autoReconnectWalletIds$]).pipe(
1503
405
  filter2(([, walletIds]) => config.autoReconnect && !!walletIds?.length),
1504
406
  mergeMap(
1505
407
  ([wallets, walletIds]) => wallets.filter((wallet) => walletIds?.includes(wallet.id))
1506
- ),
1507
- distinct((w) => w.id)
408
+ )
1508
409
  ).subscribe(async (wallet) => {
1509
- if (wallet.isConnected || reconnectingWallets.has(wallet.id)) {
410
+ if (wallet.isConnected || reconnectingWallets.has(wallet.id) || reconnectedWallets.has(wallet.id) || (failedAttempts.get(wallet.id) ?? 0) >= MAX_RECONNECT_ATTEMPTS) {
1510
411
  return;
1511
412
  }
1512
413
  reconnectingWallets.add(wallet.id);
1513
414
  try {
1514
415
  await wallet.connect();
416
+ reconnectedWallets.add(wallet.id);
417
+ failedAttempts.delete(wallet.id);
1515
418
  } catch (err) {
419
+ failedAttempts.set(
420
+ wallet.id,
421
+ (failedAttempts.get(wallet.id) ?? 0) + 1
422
+ );
1516
423
  console.error("Failed to reconnect wallet %s", wallet.id, { err });
1517
424
  } finally {
1518
425
  reconnectingWallets.delete(wallet.id);
@@ -1523,11 +430,12 @@ var getWallets$ = (config, store2 = store) => {
1523
430
  subAutoReconnect.unsubscribe();
1524
431
  subWallets.unsubscribe();
1525
432
  };
1526
- }).pipe(shareReplay8({ refCount: true, bufferSize: 1 }));
433
+ }).pipe(shareReplay4({ refCount: true, bufferSize: 1 }));
1527
434
  };
1528
435
 
1529
436
  // src/api/kheopskit.ts
1530
- var getKheopskit$ = (config, ssrCookies, existingStore) => {
437
+ var getKheopskit$ = (config, options = {}) => {
438
+ const { ssrCookies, store: existingStore } = options;
1531
439
  const kc = resolveConfig(config);
1532
440
  const store2 = existingStore ?? createKheopskitStore({ ssrCookies, storageKey: kc.storageKey });
1533
441
  if (kc.debug) console.debug("[kheopskit] config", kc);
@@ -1547,16 +455,14 @@ var getKheopskit$ = (config, ssrCookies, existingStore) => {
1547
455
  }
1548
456
  return wallet;
1549
457
  });
1550
- const cachedAccounts = cachedState.accounts.map(hydrateAccount).filter(
1551
- (account) => account.platform !== "polkadot" || kc.polkadotAccountTypes.includes(account.type)
1552
- );
458
+ const cachedAccounts = cachedState.accounts.filter((cached) => acceptsCachedAccount(cached, kc.platforms)).map(hydrateAccount);
1553
459
  if (kc.debug && cachedWallets.length > 0) {
1554
460
  console.debug("[kheopskit] hydrating from cache:", {
1555
461
  wallets: cachedWallets.length,
1556
462
  accounts: cachedAccounts.length
1557
463
  });
1558
464
  }
1559
- return new Observable9((subscriber) => {
465
+ return new Observable5((subscriber) => {
1560
466
  const liveWallets$ = getWallets$(kc, store2);
1561
467
  const liveAccounts$ = getAccounts$(kc, liveWallets$);
1562
468
  const bufferedWallets$ = createHydrationBuffer(
@@ -1602,11 +508,17 @@ var getKheopskit$ = (config, ssrCookies, existingStore) => {
1602
508
  return [...cachedWalletIds].every((id) => liveWalletIds.has(id));
1603
509
  }
1604
510
  );
1605
- const subscription = combineLatest9({
1606
- wallets: bufferedWallets$,
1607
- accounts: bufferedAccounts$
511
+ const sharedWallets$ = bufferedWallets$.pipe(
512
+ shareReplay5({ bufferSize: 1, refCount: true })
513
+ );
514
+ const sharedAccounts$ = bufferedAccounts$.pipe(
515
+ shareReplay5({ bufferSize: 1, refCount: true })
516
+ );
517
+ const subscription = combineLatest4({
518
+ wallets: sharedWallets$,
519
+ accounts: sharedAccounts$
1608
520
  }).pipe(
1609
- map9(({ wallets, accounts }) => {
521
+ map5(({ wallets, accounts }) => {
1610
522
  if (kc.debug) {
1611
523
  console.debug("[kheopskit] hydration state", {
1612
524
  walletsHydrating: wallets.isHydrating,
@@ -1617,15 +529,15 @@ var getKheopskit$ = (config, ssrCookies, existingStore) => {
1617
529
  }
1618
530
  return {
1619
531
  config: kc,
1620
- wallets: wallets.items,
1621
- accounts: accounts.items,
532
+ wallets: [...wallets.items].sort(sortWallets),
533
+ accounts: [...accounts.items].sort(sortAccounts),
1622
534
  isHydrating: wallets.isHydrating || accounts.isHydrating
1623
535
  };
1624
536
  })
1625
537
  ).subscribe(subscriber);
1626
- const persistSub = combineLatest9({
1627
- wallets: bufferedWallets$,
1628
- accounts: bufferedAccounts$
538
+ const persistSub = combineLatest4({
539
+ wallets: sharedWallets$,
540
+ accounts: sharedAccounts$
1629
541
  }).pipe(
1630
542
  // Wait for hydration to complete
1631
543
  filter3(
@@ -1633,13 +545,16 @@ var getKheopskit$ = (config, ssrCookies, existingStore) => {
1633
545
  ),
1634
546
  // Debounce to avoid excessive writes
1635
547
  debounceTime(1e3),
1636
- // Only persist if state actually changed
1637
- distinctUntilChanged6((prev, curr) => {
1638
- const prevWalletIds = prev.wallets.items.map((w) => w.id);
1639
- const currWalletIds = curr.wallets.items.map((w) => w.id);
1640
- const prevAccountIds = prev.accounts.items.map((a) => a.id);
1641
- const currAccountIds = curr.accounts.items.map((a) => a.id);
1642
- return arraysEqual(prevWalletIds, currWalletIds) && arraysEqual(prevAccountIds, currAccountIds);
548
+ // Only persist if the serialized snapshot would actually change.
549
+ // Compare the persisted fields (not just ids): an Ethereum chain switch
550
+ // keeps the same account id but changes the cached chainId, so an
551
+ // id-only comparator would skip persisting it.
552
+ distinctUntilChanged2((prev, curr) => {
553
+ const prevWalletKeys = prev.wallets.items.map(walletPersistKey);
554
+ const currWalletKeys = curr.wallets.items.map(walletPersistKey);
555
+ const prevAccountKeys = prev.accounts.items.map(accountChangeKey);
556
+ const currAccountKeys = curr.accounts.items.map(accountChangeKey);
557
+ return arraysEqual(prevWalletKeys, currWalletKeys) && arraysEqual(prevAccountKeys, currAccountKeys);
1643
558
  })
1644
559
  ).subscribe(({ wallets, accounts }) => {
1645
560
  const connectedWalletIds = new Set(
@@ -1671,30 +586,53 @@ var getKheopskit$ = (config, ssrCookies, existingStore) => {
1671
586
  persistSub.unsubscribe();
1672
587
  };
1673
588
  }).pipe(
1674
- distinctUntilChanged6(statesEqual),
589
+ distinctUntilChanged2(statesEqual),
1675
590
  throttleTime(16, void 0, { leading: true, trailing: true }),
1676
591
  // ~1 frame at 60fps
1677
592
  logObservable("kheopskit$", { enabled: kc.debug, printValue: true }),
1678
- shareReplay9({ bufferSize: 1, refCount: true })
593
+ shareReplay5({ bufferSize: 1, refCount: true })
594
+ // The runtime objects are the concrete per-plugin wallet/account types;
595
+ // recover the precise KheopskitState<P> the caller's plugins imply.
1679
596
  );
1680
597
  };
1681
598
  var arraysEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
1682
- var statesEqual = (a, b) => a.isHydrating === b.isHydrating && a.wallets.length === b.wallets.length && a.accounts.length === b.accounts.length && a.wallets.every(
1683
- (w, i) => w.id === b.wallets[i]?.id && w.isConnected === b.wallets[i]?.isConnected
1684
- ) && a.accounts.every(
1685
- (acc, i) => acc.id === b.accounts[i]?.id && (acc.platform !== "ethereum" || acc.chainId === b.accounts[i]?.chainId)
1686
- );
599
+ var accountChangeKey = (account) => {
600
+ switch (account.platform) {
601
+ case "ethereum":
602
+ return `${account.id}|${account.chainId ?? ""}`;
603
+ case "polkadot":
604
+ return `${account.id}|${account.type ?? ""}`;
605
+ case "solana":
606
+ return `${account.id}|${(account.chains ?? []).join(",")}`;
607
+ default:
608
+ return account.id;
609
+ }
610
+ };
611
+ var walletPlatforms = (wallet) => isWalletConnectWallet(wallet) ? wallet.platforms.join(",") : "";
612
+ var walletPersistKey = (wallet) => `${wallet.id}|${wallet.isConnected ? 1 : 0}|${wallet.name}`;
613
+ var walletUiKey = (wallet) => `${walletPersistKey(wallet)}|${wallet.icon}|${walletPlatforms(wallet)}`;
614
+ var statesEqual = (a, b) => a.isHydrating === b.isHydrating && a.wallets.length === b.wallets.length && a.accounts.length === b.accounts.length && a.wallets.every((w, i) => {
615
+ const other = b.wallets[i];
616
+ return !!other && walletUiKey(w) === walletUiKey(other);
617
+ }) && a.accounts.every((acc, i) => {
618
+ const other = b.accounts[i];
619
+ return !!other && accountChangeKey(acc) === accountChangeKey(other);
620
+ });
1687
621
  export {
1688
622
  DEFAULT_STORAGE_KEY,
623
+ KheopskitError,
1689
624
  clearAllCachedObservables,
1690
- clearCachedObservable,
1691
625
  createKheopskitStore,
1692
- getCachedIcon,
1693
626
  getDefaultStore,
1694
627
  getKheopskit$,
1695
- getSafeLocalStorage,
1696
- hydrateAccount,
1697
- hydrateWallet,
628
+ getWalletAccountId,
629
+ getWalletId,
630
+ isInjectedWallet,
631
+ isValidAddress,
632
+ isValidWalletId,
633
+ isWalletConnectWallet,
634
+ parseWalletAccountId,
635
+ parseWalletId,
1698
636
  resetAppKitCache,
1699
637
  resolveConfig
1700
638
  };