@kheopskit/core 5.3.0 → 6.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +426 -0
- package/MIGRATING_TO_V6.md +837 -0
- package/README.md +628 -12
- package/dist/ethereum.d.mts +12 -6
- package/dist/ethereum.d.ts +12 -6
- package/dist/ethereum.js +13 -10
- package/dist/ethereum.js.map +1 -1
- package/dist/ethereum.mjs +7 -4
- package/dist/ethereum.mjs.map +1 -1
- package/dist/{iconCache-pP2ES4pJ.mjs → iconCache-C-U3IEbP.mjs} +21 -40
- package/dist/iconCache-C-U3IEbP.mjs.map +1 -0
- package/dist/{iconCache-DUtkJlaX.js → iconCache-FR4iy6go.js} +21 -40
- package/dist/iconCache-FR4iy6go.js.map +1 -0
- package/dist/index.d.mts +17 -63
- package/dist/index.d.ts +17 -63
- package/dist/index.js +387 -373
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +384 -369
- package/dist/index.mjs.map +1 -1
- package/dist/injectedWallets-48L-AL1I.mjs +173 -0
- package/dist/injectedWallets-48L-AL1I.mjs.map +1 -0
- package/dist/injectedWallets-Dy8YGKL-.js +178 -0
- package/dist/injectedWallets-Dy8YGKL-.js.map +1 -0
- package/dist/internal.d.mts +3 -27
- package/dist/internal.d.ts +3 -27
- package/dist/internal.js +2 -2
- package/dist/internal.mjs +2 -2
- package/dist/pageLoad-BZ7o8p5R.mjs +24 -0
- package/dist/pageLoad-BZ7o8p5R.mjs.map +1 -0
- package/dist/pageLoad-D1wLeuFG.js +28 -0
- package/dist/pageLoad-D1wLeuFG.js.map +1 -0
- package/dist/platformAccounts-BjIeRcFN.js +321 -0
- package/dist/platformAccounts-BjIeRcFN.js.map +1 -0
- package/dist/platformAccounts-yyRUrnel.mjs +256 -0
- package/dist/platformAccounts-yyRUrnel.mjs.map +1 -0
- package/dist/polkadot.d.mts +127 -11
- package/dist/polkadot.d.ts +127 -11
- package/dist/polkadot.js +170 -106
- package/dist/polkadot.js.map +1 -1
- package/dist/polkadot.mjs +163 -99
- package/dist/polkadot.mjs.map +1 -1
- package/dist/solana.d.mts +11 -5
- package/dist/solana.d.ts +11 -5
- package/dist/solana.js +18 -15
- package/dist/solana.js.map +1 -1
- package/dist/solana.mjs +7 -4
- package/dist/solana.mjs.map +1 -1
- package/dist/storage-D3AwNgqc.d.mts +27 -0
- package/dist/storage-D3AwNgqc.d.ts +27 -0
- package/dist/testing.d.mts +71 -0
- package/dist/testing.d.ts +71 -0
- package/dist/testing.js +136 -0
- package/dist/testing.js.map +1 -0
- package/dist/testing.mjs +131 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/{types-DKU-SNio.js → types-BWHvNFlN.js} +149 -2
- package/dist/types-BWHvNFlN.js.map +1 -0
- package/dist/types-Dkyt9bf4.d.mts +683 -0
- package/dist/types-Dkyt9bf4.d.ts +683 -0
- package/dist/types-Yor672md.mjs +215 -0
- package/dist/types-Yor672md.mjs.map +1 -0
- package/dist/walletconnect.d.mts +41 -0
- package/dist/walletconnect.d.ts +41 -0
- package/dist/walletconnect.js +219 -0
- package/dist/walletconnect.js.map +1 -0
- package/dist/walletconnect.mjs +216 -0
- package/dist/walletconnect.mjs.map +1 -0
- package/package.json +30 -6
- package/dist/errors-BLFP1dQI.mjs +0 -181
- package/dist/errors-BLFP1dQI.mjs.map +0 -1
- package/dist/errors-DYWVPHrR.js +0 -222
- package/dist/errors-DYWVPHrR.js.map +0 -1
- package/dist/iconCache-DUtkJlaX.js.map +0 -1
- package/dist/iconCache-pP2ES4pJ.mjs.map +0 -1
- package/dist/injectedWallets-BqR-_aAy.js +0 -148
- package/dist/injectedWallets-BqR-_aAy.js.map +0 -1
- package/dist/injectedWallets-Uz4hPuoW.mjs +0 -119
- package/dist/injectedWallets-Uz4hPuoW.mjs.map +0 -1
- package/dist/types-AxUDtkR-.d.mts +0 -338
- package/dist/types-AxUDtkR-.d.ts +0 -338
- package/dist/types-DKU-SNio.js.map +0 -1
- package/dist/types-jnifAAA0.mjs +0 -104
- package/dist/types-jnifAAA0.mjs.map +0 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
//#region src/utils/getCachedObservable.ts
|
|
2
|
+
const CACHE_SYMBOL = Symbol.for("kheopskit.observableCache");
|
|
3
|
+
const getCache = () => {
|
|
4
|
+
const g = globalThis;
|
|
5
|
+
let cache = g[CACHE_SYMBOL];
|
|
6
|
+
if (!cache) {
|
|
7
|
+
cache = /* @__PURE__ */ new Map();
|
|
8
|
+
g[CACHE_SYMBOL] = cache;
|
|
9
|
+
}
|
|
10
|
+
return cache;
|
|
11
|
+
};
|
|
12
|
+
const getCachedObservable$ = (key, create) => {
|
|
13
|
+
const cache = getCache();
|
|
14
|
+
if (!cache.has(key)) cache.set(key, create());
|
|
15
|
+
return cache.get(key);
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Clears an observable from the cache.
|
|
19
|
+
* Use when a wallet disconnects or configuration changes.
|
|
20
|
+
*/
|
|
21
|
+
const clearCachedObservable = (key) => {
|
|
22
|
+
getCache().delete(key);
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Clears all cached observables whose key starts with `prefix`.
|
|
26
|
+
*
|
|
27
|
+
* Used to drop a wallet's account observables when it disconnects, so a later
|
|
28
|
+
* reconnect rebuilds them against the current wallet handle instead of a stale
|
|
29
|
+
* closure — and to keep the cache from growing unbounded across connect cycles.
|
|
30
|
+
*/
|
|
31
|
+
const clearCachedObservablesByPrefix = (prefix) => {
|
|
32
|
+
const cache = getCache();
|
|
33
|
+
for (const key of cache.keys()) if (key.startsWith(prefix)) cache.delete(key);
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Clears all cached observables.
|
|
37
|
+
* Use when resetting the entire kheopskit state.
|
|
38
|
+
*/
|
|
39
|
+
const clearAllCachedObservables = () => {
|
|
40
|
+
getCache().clear();
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/utils/isWalletPlatform.ts
|
|
44
|
+
const isWalletPlatform = (platform) => typeof platform === "string" && [
|
|
45
|
+
"polkadot",
|
|
46
|
+
"ethereum",
|
|
47
|
+
"solana"
|
|
48
|
+
].includes(platform);
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/utils/WalletId.ts
|
|
51
|
+
/**
|
|
52
|
+
* Stable id of the single WalletConnect connector. It is platform-less: one WC
|
|
53
|
+
* session spans whichever namespaces the wallet approves, so it isn't tied to a
|
|
54
|
+
* platform (unlike injected wallet ids, which are `<platform>:<identifier>`).
|
|
55
|
+
*/
|
|
56
|
+
const WALLET_CONNECT_WALLET_ID = "walletconnect";
|
|
57
|
+
const getWalletId = (platform, identifier) => {
|
|
58
|
+
if (!isWalletPlatform(platform)) throw new Error("Invalid platform");
|
|
59
|
+
if (!identifier) throw new Error("Invalid name");
|
|
60
|
+
return `${platform}:${identifier}`;
|
|
61
|
+
};
|
|
62
|
+
const parseWalletId = (walletId) => {
|
|
63
|
+
if (!walletId) throw new Error("Invalid walletId");
|
|
64
|
+
const [platform, identifier] = walletId.split(":");
|
|
65
|
+
if (!isWalletPlatform(platform)) throw new Error("Invalid platform");
|
|
66
|
+
if (!identifier) throw new Error("Invalid address");
|
|
67
|
+
return {
|
|
68
|
+
platform,
|
|
69
|
+
identifier
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Non-throwing variant of {@link parseWalletId}. Use when validating untrusted
|
|
74
|
+
* input (e.g. cached state persisted by an older version) before parsing.
|
|
75
|
+
*/
|
|
76
|
+
const isValidWalletId = (walletId) => {
|
|
77
|
+
if (typeof walletId !== "string" || !walletId) return false;
|
|
78
|
+
if (walletId === "walletconnect") return true;
|
|
79
|
+
const [platform, identifier] = walletId.split(":");
|
|
80
|
+
return isWalletPlatform(platform) && !!identifier;
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/typeof.js
|
|
84
|
+
function _typeof(o) {
|
|
85
|
+
"@babel/helpers - typeof";
|
|
86
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
87
|
+
return typeof o;
|
|
88
|
+
} : function(o) {
|
|
89
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
90
|
+
}, _typeof(o);
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPrimitive.js
|
|
94
|
+
function toPrimitive(t, r) {
|
|
95
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
96
|
+
var e = t[Symbol.toPrimitive];
|
|
97
|
+
if (void 0 !== e) {
|
|
98
|
+
var i = e.call(t, r || "default");
|
|
99
|
+
if ("object" != _typeof(i)) return i;
|
|
100
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
101
|
+
}
|
|
102
|
+
return ("string" === r ? String : Number)(t);
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPropertyKey.js
|
|
106
|
+
function toPropertyKey(t) {
|
|
107
|
+
var i = toPrimitive(t, "string");
|
|
108
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/defineProperty.js
|
|
112
|
+
function _defineProperty(e, r, t) {
|
|
113
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
114
|
+
value: t,
|
|
115
|
+
enumerable: !0,
|
|
116
|
+
configurable: !0,
|
|
117
|
+
writable: !0
|
|
118
|
+
}) : e[r] = t, e;
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/api/errors.ts
|
|
122
|
+
/**
|
|
123
|
+
* Error thrown by kheopskit wallet/account operations. Carries a stable
|
|
124
|
+
* {@link KheopskitErrorCode} and, when relevant, the offending wallet id.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* try {
|
|
129
|
+
* await wallet.connect();
|
|
130
|
+
* } catch (error) {
|
|
131
|
+
* if (error instanceof KheopskitError && error.code === "USER_REJECTED") {
|
|
132
|
+
* // the user closed or refused the wallet prompt
|
|
133
|
+
* } else throw error;
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
var KheopskitError = class extends Error {
|
|
138
|
+
constructor(code, message, options) {
|
|
139
|
+
super(`[kheopskit] ${message}`, { cause: options?.cause });
|
|
140
|
+
_defineProperty(this, "code", void 0);
|
|
141
|
+
_defineProperty(this, "walletId", void 0);
|
|
142
|
+
this.name = "KheopskitError";
|
|
143
|
+
this.code = code;
|
|
144
|
+
this.walletId = options?.walletId;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const abortedError = (walletId, operation) => new KheopskitError("ABORTED", `${operation} of wallet ${walletId} was aborted`, { walletId });
|
|
148
|
+
const walletPendingError = (walletId) => new KheopskitError("WALLET_PENDING", `wallet ${walletId} was not discovered before hydration ended`, { walletId });
|
|
149
|
+
const toConnectError = (error, walletId, isUserRejection) => {
|
|
150
|
+
if (error instanceof KheopskitError) return error;
|
|
151
|
+
return isUserRejection(error) ? new KheopskitError("USER_REJECTED", `the user rejected the connect request of wallet ${walletId}`, {
|
|
152
|
+
walletId,
|
|
153
|
+
cause: error
|
|
154
|
+
}) : new KheopskitError("CONNECT_FAILED", `wallet ${walletId} failed to connect`, {
|
|
155
|
+
walletId,
|
|
156
|
+
cause: error
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
const EIP1193_USER_REJECTED_REQUEST = 4001;
|
|
160
|
+
const isEip1193UserRejection = (error) => typeof error === "object" && error !== null && error.code === EIP1193_USER_REJECTED_REQUEST;
|
|
161
|
+
/**
|
|
162
|
+
* How Polkadot extensions and Wallet Standard wallets reject a refused connect
|
|
163
|
+
* prompt. They send a plain `Error`, so the message is the only signal.
|
|
164
|
+
* `evidence` records whether the row was observed live or inferred from the
|
|
165
|
+
* wallet's source or documentation.
|
|
166
|
+
*/
|
|
167
|
+
const REFUSAL_MESSAGES = [
|
|
168
|
+
{
|
|
169
|
+
pattern: /^Site .+ has not been authorised for Talisman yet$/,
|
|
170
|
+
wallet: "Talisman 3.11.0, Reject button or prompt window closed",
|
|
171
|
+
evidence: "live"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
pattern: /^Connection request was (rejected|cancelled) by the user\.$/,
|
|
175
|
+
wallet: "polkadot-js extension (extension-base 0.64 State.ts)",
|
|
176
|
+
evidence: "inferred"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
pattern: /^(Rejected|Cancelled)$/,
|
|
180
|
+
wallet: "SubWallet (Extension.ts)",
|
|
181
|
+
evidence: "inferred"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
pattern: /^User rejected the request\.$/,
|
|
185
|
+
wallet: "Phantom (Wallet Standard)",
|
|
186
|
+
evidence: "inferred"
|
|
187
|
+
}
|
|
188
|
+
];
|
|
189
|
+
const isRefusalMessage = (error) => {
|
|
190
|
+
const message = error?.message;
|
|
191
|
+
return typeof message === "string" && REFUSAL_MESSAGES.some((row) => row.pattern.test(message));
|
|
192
|
+
};
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/api/types.ts
|
|
195
|
+
/** Narrows a wallet to the platform-less {@link WalletConnectWallet}. */
|
|
196
|
+
const isWalletConnectWallet = (wallet) => wallet.type === "walletconnect";
|
|
197
|
+
/**
|
|
198
|
+
* Narrows a wallet to an injected (browser-extension / Wallet Standard) wallet,
|
|
199
|
+
* the complement of {@link isWalletConnectWallet}. `state.wallets` is
|
|
200
|
+
* `(InjectedWallet | WalletConnectWallet)[]`, so use this to recover the
|
|
201
|
+
* injected-only fields when iterating: `platform`, `sourceId`, and the SDK
|
|
202
|
+
* handle (`provider` on Ethereum, `extension` on Polkadot, `wallet` on Solana).
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```ts
|
|
206
|
+
* for (const wallet of wallets.filter(isInjectedWallet)) {
|
|
207
|
+
* console.log(wallet.platform, wallet.sourceId); // typed, no WC widening
|
|
208
|
+
* }
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
const isInjectedWallet = (wallet) => wallet.type === "injected";
|
|
212
|
+
//#endregion
|
|
213
|
+
export { getCachedObservable$ as _, isEip1193UserRejection as a, walletPendingError as c, isValidWalletId as d, parseWalletId as f, clearCachedObservablesByPrefix as g, clearCachedObservable as h, abortedError as i, WALLET_CONNECT_WALLET_ID as l, clearAllCachedObservables as m, isWalletConnectWallet as n, isRefusalMessage as o, isWalletPlatform as p, KheopskitError as r, toConnectError as s, isInjectedWallet as t, getWalletId as u };
|
|
214
|
+
|
|
215
|
+
//# sourceMappingURL=types-Yor672md.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-Yor672md.mjs","names":[],"sources":["../src/utils/getCachedObservable.ts","../src/utils/isWalletPlatform.ts","../src/utils/WalletId.ts","../src/api/errors.ts","../src/api/types.ts"],"sourcesContent":["import type { Observable } from \"rxjs\";\n\n// Anchored on globalThis so the cache stays a single instance even if the\n// module is duplicated across bundle chunks (e.g. CJS subpath entries).\nconst CACHE_SYMBOL = Symbol.for(\"kheopskit.observableCache\");\n\nconst getCache = (): Map<string, Observable<unknown>> => {\n\tconst g = globalThis as unknown as Record<\n\t\tsymbol,\n\t\tMap<string, Observable<unknown>> | undefined\n\t>;\n\tlet cache = g[CACHE_SYMBOL];\n\tif (!cache) {\n\t\tcache = new Map();\n\t\tg[CACHE_SYMBOL] = cache;\n\t}\n\treturn cache;\n};\n\nexport const getCachedObservable$ = <T, Obs = Observable<T>>(\n\tkey: string,\n\tcreate: () => Obs,\n): Obs => {\n\tconst cache = getCache();\n\tif (!cache.has(key)) cache.set(key, create() as Observable<unknown>);\n\n\treturn cache.get(key) as Obs;\n};\n\n/**\n * Clears an observable from the cache.\n * Use when a wallet disconnects or configuration changes.\n */\nexport const clearCachedObservable = (key: string): void => {\n\tgetCache().delete(key);\n};\n\n/**\n * Clears all cached observables whose key starts with `prefix`.\n *\n * Used to drop a wallet's account observables when it disconnects, so a later\n * reconnect rebuilds them against the current wallet handle instead of a stale\n * closure — and to keep the cache from growing unbounded across connect cycles.\n */\nexport const clearCachedObservablesByPrefix = (prefix: string): void => {\n\tconst cache = getCache();\n\tfor (const key of cache.keys()) {\n\t\tif (key.startsWith(prefix)) cache.delete(key);\n\t}\n};\n\n/**\n * Clears all cached observables.\n * Use when resetting the entire kheopskit state.\n */\nexport const clearAllCachedObservables = (): void => {\n\tgetCache().clear();\n};\n","import type { WalletPlatform } from \"../api/types\";\n\nexport const isWalletPlatform = (\n\tplatform: unknown,\n): platform is WalletPlatform =>\n\ttypeof platform === \"string\" &&\n\t[\"polkadot\", \"ethereum\", \"solana\"].includes(platform as WalletPlatform);\n","import type { WalletPlatform } from \"../api/types\";\nimport { isWalletPlatform } from \"./isWalletPlatform\";\n\nexport type WalletId = string;\n\n/**\n * Stable id of the single WalletConnect connector. It is platform-less: one WC\n * session spans whichever namespaces the wallet approves, so it isn't tied to a\n * platform (unlike injected wallet ids, which are `<platform>:<identifier>`).\n */\nexport const WALLET_CONNECT_WALLET_ID: WalletId = \"walletconnect\";\n\nexport const getWalletId = (\n\tplatform: WalletPlatform,\n\tidentifier: string,\n): WalletId => {\n\tif (!isWalletPlatform(platform)) throw new Error(\"Invalid platform\");\n\tif (!identifier) throw new Error(\"Invalid name\");\n\treturn `${platform}:${identifier}`;\n};\n\nexport const parseWalletId = (walletId: string) => {\n\tif (!walletId) throw new Error(\"Invalid walletId\");\n\tconst [platform, identifier] = walletId.split(\":\");\n\tif (!isWalletPlatform(platform)) throw new Error(\"Invalid platform\");\n\tif (!identifier) throw new Error(\"Invalid address\");\n\treturn { platform, identifier };\n};\n\n/**\n * Non-throwing variant of {@link parseWalletId}. Use when validating untrusted\n * input (e.g. cached state persisted by an older version) before parsing.\n */\nexport const isValidWalletId = (walletId: unknown): walletId is WalletId => {\n\tif (typeof walletId !== \"string\" || !walletId) return false;\n\tif (walletId === WALLET_CONNECT_WALLET_ID) return true;\n\tconst [platform, identifier] = walletId.split(\":\");\n\treturn isWalletPlatform(platform) && !!identifier;\n};\n","import type { WalletId } from \"../utils/WalletId\";\n\n/**\n * Stable error codes thrown by kheopskit. Catch a {@link KheopskitError} and\n * branch on `error.code` instead of matching message strings.\n */\nexport type KheopskitErrorCode =\n\t/**\n\t * This `connect()` or `disconnect()` call was abandoned. For `connect()`:\n\t * its `signal` fired before the platform answered, `disconnect()` was\n\t * called while it pended, its wallet disappeared, or the last `kheopskit$`\n\t * subscriber unsubscribed.\n\t * For either call on an injected wallet: the wallet object came from a\n\t * subscription that had already ended, in which case the call rejects\n\t * without asking the platform and without changing the remembered list. A\n\t * placeholder's `connect()` rejects the same way, its `disconnect()`\n\t * resolves, and the WalletConnect connector still calls AppKit.\n\t */\n\t| \"ABORTED\"\n\t/** The user refused the wallet's connect prompt. `cause` holds the platform error. */\n\t| \"USER_REJECTED\"\n\t/** The wallet's connect call failed for another reason. `cause` holds the platform error. */\n\t| \"CONNECT_FAILED\"\n\t/**\n\t * `connect()` was called on a placeholder wallet restored from the cache:\n\t * on `kheopskit$`, hydration ended without kheopskit discovering that\n\t * wallet; on `getHydratedSnapshot` and the React provider's initial\n\t * snapshot, always.\n\t */\n\t| \"WALLET_PENDING\"\n\t/** The wallet does not advertise a capability kheopskit needs to proceed. */\n\t| \"FEATURE_NOT_SUPPORTED\"\n\t/** No active WalletConnect session for the requested operation. */\n\t| \"NO_SESSION\"\n\t/** No provider available for the requested namespace. */\n\t| \"NO_PROVIDER\"\n\t/** The installed polkadot-api version exposes neither `getTxCreatorFromPjs` (v3) nor `getPolkadotSignerFromPjs` (v2). */\n\t| \"UNSUPPORTED_VERSION\"\n\t/** The requested chain cannot be used for this operation (e.g. a Solana cluster with no CAIP-2 id over WalletConnect). */\n\t| \"UNSUPPORTED_CHAIN\"\n\t/** `getKheopskit$` received a config value it cannot use. The message names the fix. */\n\t| \"INVALID_CONFIG\";\n\n/**\n * Error thrown by kheopskit wallet/account operations. Carries a stable\n * {@link KheopskitErrorCode} and, when relevant, the offending wallet id.\n *\n * @example\n * ```ts\n * try {\n * await wallet.connect();\n * } catch (error) {\n * if (error instanceof KheopskitError && error.code === \"USER_REJECTED\") {\n * // the user closed or refused the wallet prompt\n * } else throw error;\n * }\n * ```\n */\nexport class KheopskitError extends Error {\n\treadonly code: KheopskitErrorCode;\n\t/** The wallet id this error relates to, when applicable. */\n\treadonly walletId?: WalletId;\n\n\tconstructor(\n\t\tcode: KheopskitErrorCode,\n\t\tmessage: string,\n\t\toptions?: { walletId?: WalletId; cause?: unknown },\n\t) {\n\t\tsuper(`[kheopskit] ${message}`, { cause: options?.cause });\n\t\tthis.name = \"KheopskitError\";\n\t\tthis.code = code;\n\t\tthis.walletId = options?.walletId;\n\t}\n}\n\nexport const abortedError = (\n\twalletId: WalletId,\n\toperation: \"connect\" | \"disconnect\",\n): KheopskitError =>\n\tnew KheopskitError(\n\t\t\"ABORTED\",\n\t\t`${operation} of wallet ${walletId} was aborted`,\n\t\t{ walletId },\n\t);\n\nexport const walletPendingError = (walletId: WalletId): KheopskitError =>\n\tnew KheopskitError(\n\t\t\"WALLET_PENDING\",\n\t\t`wallet ${walletId} was not discovered before hydration ended`,\n\t\t{ walletId },\n\t);\n\nexport const toConnectError = (\n\terror: unknown,\n\twalletId: WalletId,\n\tisUserRejection: (error: unknown) => boolean,\n): KheopskitError => {\n\tif (error instanceof KheopskitError) return error;\n\treturn isUserRejection(error)\n\t\t? new KheopskitError(\n\t\t\t\t\"USER_REJECTED\",\n\t\t\t\t`the user rejected the connect request of wallet ${walletId}`,\n\t\t\t\t{ walletId, cause: error },\n\t\t\t)\n\t\t: new KheopskitError(\n\t\t\t\t\"CONNECT_FAILED\",\n\t\t\t\t`wallet ${walletId} failed to connect`,\n\t\t\t\t{ walletId, cause: error },\n\t\t\t);\n};\n\nconst EIP1193_USER_REJECTED_REQUEST = 4001;\n\nexport const isEip1193UserRejection = (error: unknown): boolean =>\n\ttypeof error === \"object\" &&\n\terror !== null &&\n\t(error as { code?: unknown }).code === EIP1193_USER_REJECTED_REQUEST;\n\ntype RefusalMessage = {\n\tpattern: RegExp;\n\twallet: string;\n\tevidence: \"live\" | \"inferred\";\n};\n\n/**\n * How Polkadot extensions and Wallet Standard wallets reject a refused connect\n * prompt. They send a plain `Error`, so the message is the only signal.\n * `evidence` records whether the row was observed live or inferred from the\n * wallet's source or documentation.\n */\nconst REFUSAL_MESSAGES: readonly RefusalMessage[] = [\n\t{\n\t\tpattern: /^Site .+ has not been authorised for Talisman yet$/,\n\t\twallet: \"Talisman 3.11.0, Reject button or prompt window closed\",\n\t\tevidence: \"live\",\n\t},\n\t{\n\t\tpattern: /^Connection request was (rejected|cancelled) by the user\\.$/,\n\t\twallet: \"polkadot-js extension (extension-base 0.64 State.ts)\",\n\t\tevidence: \"inferred\",\n\t},\n\t{\n\t\tpattern: /^(Rejected|Cancelled)$/,\n\t\twallet: \"SubWallet (Extension.ts)\",\n\t\tevidence: \"inferred\",\n\t},\n\t{\n\t\tpattern: /^User rejected the request\\.$/,\n\t\twallet: \"Phantom (Wallet Standard)\",\n\t\tevidence: \"inferred\",\n\t},\n];\n\nexport const isRefusalMessage = (error: unknown): boolean => {\n\tconst message = (error as { message?: unknown } | null | undefined)?.message;\n\treturn (\n\t\ttypeof message === \"string\" &&\n\t\tREFUSAL_MESSAGES.some((row) => row.pattern.test(message))\n\t);\n};\n","import type { Observable } from \"rxjs\";\nimport type { WalletAccountId } from \"../utils\";\nimport type { WalletId } from \"../utils/WalletId\";\nimport type { KheopskitError } from \"./errors\";\n\nexport type WalletPlatform = \"polkadot\" | \"ethereum\" | \"solana\";\n\n/**\n * Minimal structural view of a WalletConnect `UniversalProvider`, the subset\n * kheopskit reads. Declared locally so core never depends on\n * `@walletconnect/universal-provider`. The concrete instance comes from\n * `@reown/appkit` at runtime.\n */\nexport type WalletConnectProvider = {\n\tsession?: {\n\t\ttopic: string;\n\t\tnamespaces: Record<string, { accounts?: string[] }>;\n\t};\n\tclient: {\n\t\trequest<T = unknown>(args: {\n\t\t\ttopic: string;\n\t\t\tchainId: string;\n\t\t\trequest: { method: string; params: unknown };\n\t\t}): Promise<T>;\n\t};\n\trequest(args: { method: string; params?: unknown }): Promise<unknown>;\n\ton(event: string, listener: (...args: unknown[]) => void): void;\n\toff(event: string, listener: (...args: unknown[]) => void): void;\n};\n\n/**\n * Minimal structural view of the Reown AppKit instance, the subset kheopskit's\n * account factories use. Exposed as the `appKit` escape hatch on AppKit wallets;\n * cast it to `@reown/appkit`'s `AppKit` type for the full API. Declared locally\n * so core never depends on `@reown/appkit`'s types (it's an optional peer).\n */\nexport type AppKitInstance = {\n\tgetProvider<T = WalletConnectProvider>(namespace: string): T | undefined;\n\tgetAccount(\n\t\tnamespace: string,\n\t): { allAccounts: { address: string }[] } | undefined;\n\tgetCaipNetworks(namespace: string): { caipNetworkId?: string }[];\n};\n\nexport type WalletType = \"injected\" | \"walletconnect\";\n\n/**\n * Where a wallet stands with the dapp. `connecting` covers a `connect()` call\n * in flight and an auto-reconnect in flight alike.\n */\nexport type WalletStatus = \"disconnected\" | \"connecting\" | \"connected\";\n\nexport type PolkadotAccountType = \"sr25519\" | \"ed25519\" | \"ecdsa\" | \"ethereum\";\n\n/** Options accepted by {@link BaseWallet.connect}. */\nexport type ConnectOptions = {\n\t/**\n\t * Ends this caller's wait for the platform's answer: its promise rejects\n\t * with a `KheopskitError` of code `ABORTED`. An abort after the platform\n\t * has granted the connect changes nothing, and a Polkadot extension counts\n\t * as granted only once its account list has been read. Other callers\n\t * sharing the attempt keep waiting. Once no caller waits any more,\n\t * kheopskit drops a handle the platform hands back afterwards without\n\t * revoking the platform's grant, and the wallet is neither connected nor\n\t * remembered. The\n\t * extension's own prompt may stay open: nothing can withdraw it from the\n\t * page. Kheopskit sets no timeout of its own, because an extension prompt\n\t * pends only while the user has not answered it; pass\n\t * `AbortSignal.timeout(ms)` to cap the wait.\n\t */\n\tsignal?: AbortSignal;\n};\n\n/**\n * SDK-free fields common to every wallet, regardless of platform. Platform\n * packages (`@kheopskit/core/<platform>`) extend this with SDK-typed fields\n * (the injected provider/extension/standard-wallet handle).\n */\nexport type BaseWallet = {\n\t/** `<platform>:<identifier>`, e.g. `polkadot:talisman`. Stable across reloads. */\n\tid: WalletId;\n\t/** The platform whose registry listed the wallet. */\n\tplatform: WalletPlatform;\n\t/**\n\t * `\"injected\"`, for a browser extension or Wallet Standard wallet. The\n\t * WalletConnect connector is the separate {@link WalletConnectWallet}.\n\t */\n\ttype: WalletType;\n\t/** Display name, e.g. `Talisman`. */\n\tname: string;\n\t/** Icon URL or data URI. `\"\"` when the wallet exposes none. */\n\ticon: string;\n\t/**\n\t * `true` for a wallet restored from the cache that kheopskit has not\n\t * discovered yet: its SDK handle and `sourceId` are absent and it is never\n\t * connected. On `kheopskit$` its `connect()` waits for the live wallet and\n\t * connects that one, rejecting with `WALLET_PENDING` if hydration ends first\n\t * and `ABORTED` if its `signal` fires or the subscription ends. On\n\t * `getHydratedSnapshot` it rejects with `WALLET_PENDING`. Its `disconnect()`\n\t * resolves at once. Set on every wallet of `kheopskit$` and of the hydrated\n\t * snapshot; plugins leave it unset.\n\t */\n\tisPlaceholder?: boolean;\n\t/**\n\t * `connecting` while a `connect()` call or an auto-reconnect waits for the\n\t * platform, `connected` once the platform granted it, `disconnected`\n\t * otherwise. On a reload, a remembered wallet kheopskit will reconnect is\n\t * `connecting` from the first frame when the cache recorded it connected,\n\t * which the cache does 1 s after the state settles.\n\t */\n\tstatus: WalletStatus;\n\t/**\n\t * The last `connect()` or auto-reconnect that the platform refused or\n\t * failed (`USER_REJECTED` or `CONNECT_FAILED`, or `FEATURE_NOT_SUPPORTED`\n\t * for a Wallet Standard wallet without `standard:connect`). Cleared when\n\t * the next attempt starts. An aborted attempt sets nothing.\n\t */\n\terror?: KheopskitError;\n\t/** `status === \"connected\"`. */\n\tisConnected: boolean;\n\t/**\n\t * Connects the wallet.\n\t *\n\t * - **Shared in flight.** Concurrent calls on one wallet share a single\n\t * platform attempt and the platform is asked once. Each call gets its own\n\t * promise: aborting a caller's `signal` rejects only that caller with code\n\t * `ABORTED`. The attempt itself is abandoned only when every caller that\n\t * passed a signal has aborted and no caller without one joined, when\n\t * `disconnect()` is called, or when the last `kheopskit$` subscriber\n\t * unsubscribes; those reject every remaining caller with `ABORTED`.\n\t * - **Idempotent.** On a connected wallet it resolves at once without\n\t * touching the platform, unless a `disconnect()` still waits for the\n\t * platform. It then waits for that disconnect to settle and connects\n\t * again if the wallet ended up disconnected.\n\t * - **Abortable.** See {@link ConnectOptions.signal}. There is no default\n\t * timeout.\n\t * - **Settles with the state.** It resolves only after `kheopskit$` has\n\t * emitted a state in which this wallet has `isConnected: true`, so the\n\t * consumer-visible state already reflects the connect. On platforms that\n\t * list accounts asynchronously (Ethereum `eth_accounts`), the accounts may\n\t * arrive in a later emission. No emission shows a disconnected wallet\n\t * still listing live accounts, or a connected wallet listing the accounts\n\t * of a previous connection. During hydration a wallet's cached\n\t * placeholder accounts stay listed whatever its status. Another wallet's\n\t * pending `eth_accounts` request never delays them. A `disconnect()` that\n\t * completes while it waits for that state rejects it with `ABORTED`. If\n\t * the platform's disconnect is still pending or refuses, it resolves once\n\t * the state shows the wallet connected (today only Solana has a platform\n\t * disconnect). A `connect()`\n\t * whose wallet disappears before the platform grants it (an extension\n\t * removed, a Wallet Standard wallet unregistered) rejects `ABORTED`;\n\t * granted first, it resolves and the wallet stays remembered. Once the last `kheopskit$`\n\t * subscriber has unsubscribed, a call on a wallet object from that\n\t * subscription rejects with `ABORTED` without asking the platform,\n\t * placeholders included.\n\t * - **Typed rejections.** A platform rejection is wrapped in a\n\t * `KheopskitError` carrying the original error as `cause` and the\n\t * `walletId`: `USER_REJECTED` when the user refused the prompt,\n\t * `CONNECT_FAILED` otherwise. A Wallet Standard wallet without\n\t * `standard:connect` rejects with `FEATURE_NOT_SUPPORTED`.\n\t */\n\tconnect: (options?: ConnectOptions) => Promise<void>;\n\t/**\n\t * Disconnects the wallet.\n\t *\n\t * On a disconnected wallet it resolves at once. While a `connect()` waits\n\t * for the platform to grant it, it aborts that connect (its promise rejects\n\t * with `ABORTED`) and never waits for the extension prompt. Otherwise it\n\t * first waits for the platform's disconnect and rejects if that fails, so\n\t * callers can surface or retry. It then resolves once `kheopskit$` has\n\t * emitted a state in which this wallet has `isConnected: false`, or once a\n\t * later `connect()`, the wallet leaving the list or the end of the\n\t * subscription makes that emission impossible. Once the last `kheopskit$`\n\t * subscriber has unsubscribed, a call on a wallet object from that\n\t * subscription rejects with `ABORTED` without asking the platform and\n\t * without changing the remembered list, except on a placeholder, whose\n\t * `disconnect()` resolves. A `disconnect()` started before that point\n\t * settles once the platform has answered: the wallet was\n\t * forgotten when it was called, and nothing else is written once the\n\t * subscription has ended.\n\t */\n\tdisconnect: () => Promise<void>;\n};\n\n/**\n * SDK-free fields common to every account, regardless of platform. Platform\n * packages extend this with their SDK-typed signer/client.\n */\nexport type BaseWalletAccount = {\n\t/** `<walletId>::<address>`, e.g. `polkadot:talisman::5Grw…`. */\n\tid: WalletAccountId;\n\t/**\n\t * `true` for an account restored from the cache that the live wallet has\n\t * not listed yet: its signing surface is absent. Set on every account of\n\t * `kheopskit$` and of the hydrated snapshot; plugins leave it unset.\n\t */\n\tisPlaceholder?: boolean;\n\t/** The platform of the wallet that lists the account. */\n\tplatform: WalletPlatform;\n\t/** Base58 (Solana), SS58 (Polkadot) or 0x-hex (Ethereum) address. */\n\taddress: string;\n\t/** Friendly account name, when the wallet exposes one (e.g. Polkadot). */\n\tname?: string;\n\t/** `name` of the wallet that lists the account. */\n\twalletName: string;\n\t/** `id` of the wallet that lists the account. */\n\twalletId: WalletId;\n};\n\ntype LiveWalletConnectWallet = {\n\t/** See {@link BaseWallet.isPlaceholder}. */\n\tisPlaceholder?: false;\n\t/** `\"walletconnect\"`, the one connector shared by every platform. */\n\tid: WalletId;\n\t/** Narrow with {@link isWalletConnectWallet}. */\n\ttype: \"walletconnect\";\n\t/**\n\t * Platforms (namespaces) the live session currently carries. Empty until\n\t * connected; populated with whatever the wallet approved (e.g. just\n\t * `[\"ethereum\"]`, or `[\"polkadot\", \"ethereum\"]`).\n\t */\n\tplatforms: WalletPlatform[];\n\t/**\n\t * Raw Reown AppKit instance, exposed as an escape hatch for advanced use\n\t * (custom modal control, reading providers directly). Most consumers should\n\t * use `connect`/`disconnect` and the derived accounts instead.\n\t */\n\tappKit: AppKitInstance;\n\t/** The name AppKit reports for the paired wallet, `\"WalletConnect\"` when it reports none. */\n\tname: string;\n\t/** The icon AppKit reports for the paired wallet, the WalletConnect logo when it reports none. */\n\ticon: string;\n\t/**\n\t * `connecting` while `connect()` opens the modal, `connected` while a\n\t * session is live, `disconnected` otherwise. On a reload with a cached\n\t * session it is `connecting` until AppKit restores the session or hydration\n\t * ends.\n\t */\n\tstatus: WalletStatus;\n\t/** The last `connect()` whose modal failed to open. Cleared by the next call. */\n\terror?: KheopskitError;\n\t/** `status === \"connected\"`. */\n\tisConnected: boolean;\n\t/**\n\t * Opens the WalletConnect modal and resolves once it is open; `isConnected`\n\t * follows when the user approves a session. Unlike injected wallets, this\n\t * promise does not wait for the state to show the connector connected, and\n\t * `signal` is accepted for signature compatibility only.\n\t */\n\tconnect: (options?: ConnectOptions) => Promise<void>;\n\t/** Ends the live session when there is one; resolves at once otherwise. */\n\tdisconnect: () => Promise<void>;\n};\n\n/**\n * The single WalletConnect connector, shared across every platform.\n *\n * Unlike injected wallets, it is **not tied to a platform**: one WalletConnect\n * session spans whichever namespaces the remote wallet approves in a single\n * pairing (a namespace can't be added to a live session afterwards). So there is\n * exactly one of these in `wallets`, discriminated by `type: \"walletconnect\"`.\n * Its accounts appear in `accounts`, each carrying its own `platform`.\n *\n * A placeholder (see {@link BaseWallet.isPlaceholder}) has no `appKit`.\n */\nexport type WalletConnectWallet =\n\t| LiveWalletConnectWallet\n\t| PlaceholderWallet<LiveWalletConnectWallet, \"appKit\">;\n\n/**\n * The cached stand-in for a live item `T`: `isPlaceholder: true`, and the\n * fields `K`, which only the live item carries, absent. Platform account and\n * wallet types are `T | Placeholder<T, K>`, so narrow on `isPlaceholder`\n * before reading a field of `K`.\n */\nexport type Placeholder<T, K extends keyof T> = Omit<T, K | \"isPlaceholder\"> & {\n\t/** Restored from the cache and not yet replaced by the live item. */\n\tisPlaceholder: true;\n} & { [P in K]?: undefined };\n\n/** A {@link Placeholder} wallet, which is never connected. */\nexport type PlaceholderWallet<\n\tT extends { isConnected: boolean },\n\tK extends keyof T,\n> = Omit<Placeholder<T, K>, \"isConnected\"> & { isConnected: false };\n\n/** Narrows a wallet to the platform-less {@link WalletConnectWallet}. */\nexport const isWalletConnectWallet = (\n\twallet: BaseWallet | WalletConnectWallet,\n): wallet is WalletConnectWallet => wallet.type === \"walletconnect\";\n\n/**\n * Narrows a wallet to an injected (browser-extension / Wallet Standard) wallet,\n * the complement of {@link isWalletConnectWallet}. `state.wallets` is\n * `(InjectedWallet | WalletConnectWallet)[]`, so use this to recover the\n * injected-only fields when iterating: `platform`, `sourceId`, and the SDK\n * handle (`provider` on Ethereum, `extension` on Polkadot, `wallet` on Solana).\n *\n * @example\n * ```ts\n * for (const wallet of wallets.filter(isInjectedWallet)) {\n * console.log(wallet.platform, wallet.sourceId); // typed, no WC widening\n * }\n * ```\n */\nexport const isInjectedWallet = <W extends BaseWallet | WalletConnectWallet>(\n\twallet: W,\n): wallet is Exclude<W, WalletConnectWallet> => wallet.type === \"injected\";\n\n/**\n * Dapp metadata shown in the WalletConnect modal. Mirrors WalletConnect's\n * `Metadata`, declared locally so core doesn't depend on\n * `@walletconnect/universal-provider`.\n */\nexport type WalletConnectMetadata = {\n\tname: string;\n\tdescription: string;\n\turl: string;\n\ticons: string[];\n};\n\n/**\n * The WalletConnect connector for `config.walletConnect`. Create it with\n * `walletConnect()` from `@kheopskit/core/walletconnect`; that entry is the only\n * one that loads Reown AppKit.\n */\nexport type WalletConnectPlugin = {\n\treadonly type: \"walletconnect\";\n\treadonly metadata: WalletConnectMetadata;\n\tgetWallet$(ctx: PlatformContext): Observable<WalletConnectWallet | null>;\n};\n\n/**\n * Context passed to a platform plugin's `getWallets$`. Carries the shared store\n * and the resolved core config (for WalletConnect / debug).\n */\nexport type PlatformContext = {\n\tstore: KheopskitStore;\n\tconfig: KheopskitConfig;\n};\n\n/**\n * A platform plugin. Created by the per-platform factories exported from\n * `@kheopskit/core/polkadot`, `/ethereum`, `/solana`. Core iterates plugins\n * generically and never imports a platform SDK itself.\n *\n * @typeParam TPlatform - the platform discriminant\n * @typeParam TWallet - the platform's wallet type (extends {@link BaseWallet})\n * @typeParam TAccount - the platform's account type (extends {@link BaseWalletAccount})\n */\nexport type KheopskitPlatform<\n\tTPlatform extends WalletPlatform = WalletPlatform,\n\tTWallet extends BaseWallet = BaseWallet,\n\tTAccount extends BaseWalletAccount = BaseWalletAccount,\n> = {\n\treadonly platform: TPlatform;\n\t// Declared as methods (not arrow properties) so parameters are checked\n\t// bivariantly — this lets a specific `KheopskitPlatform<\"polkadot\", …>` be\n\t// assigned to the base `KheopskitPlatform` despite the contravariant\n\t// `wallets$` parameter.\n\tgetWallets$(ctx: PlatformContext): Observable<TWallet[]>;\n\t// Receives this platform's (injected) wallets plus the shared, platform-less\n\t// WalletConnect connector — the plugin derives its injected accounts and, if\n\t// the WC session carries its namespace, its WalletConnect accounts.\n\tgetAccounts$(\n\t\twallets$: Observable<(TWallet | WalletConnectWallet)[]>,\n\t): Observable<TAccount[]>;\n\t/**\n\t * Optional hydration filter. Cached accounts for which this returns false are\n\t * dropped during SSR hydration (Polkadot uses it to honour `accountTypes`).\n\t */\n\tacceptsCachedAccount?(cached: CachedAccount): boolean;\n};\n\ntype ElementOf<T> = T extends readonly (infer E)[] ? E : never;\n\n/** The account type produced by a plugin (inferred from its `getAccounts$`). */\nexport type AccountOf<T> = T extends {\n\tgetAccounts$: (wallets$: never) => Observable<infer R>;\n}\n\t? ElementOf<R>\n\t: never;\n\n/** The wallet type produced by a plugin (inferred from its `getWallets$`). */\nexport type WalletOf<T> = T extends {\n\tgetWallets$: (ctx: never) => Observable<infer R>;\n}\n\t? ElementOf<R>\n\t: never;\n\nexport type KheopskitConfig<\n\tP extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n> = {\n\t/**\n\t * Which remembered injected wallets kheopskit reconnects after a reload.\n\t *\n\t * A wallet is remembered on every successful `connect()` and forgotten on\n\t * `disconnect()`, whatever this option says; the list is the store's\n\t * `remembered`. `true` reconnects every remembered injected wallet, `false`\n\t * none, and a function is asked for each cached connected injected wallet\n\t * on the first frame, then for each remembered one with its live object\n\t * before the attempt. The function must be synchronous and pure. It runs on\n\t * the server and on the client for the same input and both must agree, or\n\t * the markup diverges. It receives the {@link BaseWallet} fields only, so\n\t * key on `id`.\n\t *\n\t * The WalletConnect row is not governed by this option: AppKit restores its\n\t * own session on load, and the row hydrates `connecting` while it does.\n\t *\n\t * A reconnect opens no connect prompt while the site stays authorised in\n\t * the extension. When the authorisation was revoked the extension prompts\n\t * once; a refusal forgets the wallet, so the next load stays silent. A manual\n\t * `connect()` or `disconnect()` on a remembered wallet ends its automatic\n\t * reconnect for the session. A `disconnect()` while the automatic reconnect\n\t * still waits for the extension aborts it without forgetting the wallet, so\n\t * the next load reconnects it.\n\t * Automatic reconnect also ends when the wallet disappears mid-attempt; the\n\t * wallet stays remembered for the next load.\n\t *\n\t * A cached connected wallet this accepts shows `status: \"connecting\"` from\n\t * the first frame until its attempt settles. A wallet this rejects shows\n\t * `disconnected` from the first frame, without its cached accounts, so\n\t * nothing flashes from connected to disconnected.\n\t *\n\t * @default true\n\t */\n\tautoReconnect: boolean | ((wallet: BaseWallet) => boolean);\n\t/**\n\t * Platform plugins to enable, e.g. `[polkadot(), solana({ chain })]`.\n\t * Import factories from `@kheopskit/core/<platform>`.\n\t */\n\tplatforms: P;\n\t/** Create with `walletConnect()` from `@kheopskit/core/walletconnect`. */\n\twalletConnect?: WalletConnectPlugin;\n\t/**\n\t * Dapp name sent to Polkadot injected extensions on connect. Some\n\t * extensions (e.g. polkadot.js) warn about a suspicious origin when it's\n\t * empty.\n\t *\n\t * @default walletConnect.metadata.name, then window.location.hostname\n\t */\n\tappName?: string;\n\t/**\n\t * Logs the resolved config, every state emission and the hydration and\n\t * persistence steps with `console.debug`.\n\t *\n\t * @default false\n\t */\n\tdebug: boolean;\n\t/**\n\t * Custom storage key for persisting wallet connection state.\n\t * Useful when running multiple kheopskit instances on the same domain\n\t * to prevent state conflicts between different dapps.\n\t *\n\t * @default \"kheopskit\"\n\t */\n\tstorageKey: string;\n\t/**\n\t * Minimum time in milliseconds the cached placeholders are shown after a\n\t * reload, so the wallet list does not flash while extensions inject and\n\t * remembered wallets reconnect. Hydration goes on past it until the rule\n\t * documented on {@link KheopskitConfig.hydrationTimeout} ends it, and that\n\t * timeout wins over a longer grace period. The old cap of six times this\n\t * value is gone, so an app that raises it sets `hydrationTimeout` as well.\n\t *\n\t * `0` disables placeholders: `isHydrating` is `false` from the first\n\t * emission.\n\t *\n\t * @default 500\n\t */\n\thydrationGracePeriod: number;\n\t/**\n\t * Upper bound in milliseconds on {@link KheopskitState.isHydrating}.\n\t *\n\t * `isHydrating` turns `false` once `hydrationGracePeriod` has elapsed,\n\t * discovery has ended ({@link KheopskitState.isDiscovering} is `false`),\n\t * and every wallet that hydrated as `connecting` has settled. A wallet has\n\t * settled when it is absent from the discovered wallets, connected once its\n\t * account list has been read (an empty list counts) or connected with no\n\t * cached accounts, disconnected with `error` set, or disconnected and not\n\t * remembered when hydration began. At `hydrationTimeout` hydration ends\n\t * whatever is pending, and a wallet whose reconnect is still pending stays\n\t * `connecting`.\n\t *\n\t * - Discovery ends only after the page fires `load`, so a page with a cache\n\t * hydrates until `load` or `hydrationTimeout`, whichever comes first,\n\t * even when no wallet reconnects.\n\t * - A wallet that reconnects without sharing any account with the site\n\t * settles as soon as it answers; its cached accounts leave the list when\n\t * hydration ends.\n\t * - A failed reconnect ends that wallet's wait, even when the reconnect\n\t * policy still permits a retry. A retry runs only when the wallet list next\n\t * changes (a wallet discovered or removed, or any wallet's status, error\n\t * or name changing), which may never happen, so waiting for it would\n\t * hold most failed reconnects until `hydrationTimeout`. A retry that\n\t * does run shows on the live wallet's `status`, not as a placeholder.\n\t * - A remembered wallet the user disconnects during or right after its\n\t * reconnect holds hydration, and shows its cached accounts, until\n\t * `hydrationTimeout`.\n\t * - A prompt the extension opens for a revoked site holds hydration until\n\t * the user answers or `hydrationTimeout` elapses.\n\t *\n\t * @default 3000\n\t */\n\thydrationTimeout: number;\n};\n\n/**\n * The current kheopskit state.\n *\n * @remarks\n * While {@link KheopskitState.isHydrating} is `true`, `wallets` and `accounts`\n * may contain placeholders restored from the cache, flagged\n * `isPlaceholder: true`. Each platform type is a union on that flag: a\n * placeholder lacks the SDK handles (`account.txCreator` or `polkadotSigner`\n * on Polkadot, `account.client` on Ethereum, `account.signer` / `getSigner` on\n * Solana, `wallet.extension` / `provider` / `wallet` and `sourceId`). Reading\n * one without narrowing yields a possibly-`undefined` value, so the compiler\n * rejects using it as present until you narrow:\n *\n * ```ts\n * if (account.isPlaceholder) return;\n * account.txCreator; // TxCreator\n * ```\n *\n * A placeholder wallet's `connect()` waits for the live wallet and connects\n * it, rejecting with `WALLET_PENDING` if hydration ends first. No item is a\n * placeholder once `isHydrating` is `false`.\n *\n * The plain, serializable platform data that is persisted in the cache IS\n * restored on the placeholders (Ethereum `chainId`, Polkadot key `type`), so it\n * renders immediately on reload without flashing. Solana `chains` is not\n * cached: a placeholder account's is empty.\n */\nexport type KheopskitState<\n\tP extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[],\n> = {\n\t/**\n\t * Every discovered wallet, connected or not, then the WalletConnect\n\t * connector once AppKit has loaded, when `config.walletConnect` is set.\n\t * While `isHydrating` is `true`, also the cached placeholders. Sorted by\n\t * platform (Polkadot, Ethereum, Solana, WalletConnect), then Talisman\n\t * first, then by name.\n\t */\n\twallets: (WalletOf<P[number]> | WalletConnectWallet)[];\n\t/**\n\t * The accounts of every connected wallet. While `isHydrating` is `true`,\n\t * also the cached placeholders of every wallet that has no live account\n\t * yet. Grouped by platform, then by wallet (Talisman first, then by wallet\n\t * name); inside a wallet, in the order the wallet lists them.\n\t */\n\taccounts: AccountOf<P[number]>[];\n\t/** The resolved config, with every default filled in. */\n\tconfig: KheopskitConfig<P>;\n\t/**\n\t * Whether the state is still being hydrated from cache.\n\t *\n\t * During hydration, cached wallets/accounts may be displayed before the\n\t * actual wallet extensions have injected. See the type-level remarks: those\n\t * are flagged `isPlaceholder: true` and carry no SDK handle.\n\t */\n\tisHydrating: boolean;\n\t/**\n\t * Whether wallet discovery may still be incomplete.\n\t *\n\t * `true` when the subscription started before `document.readyState` was\n\t * `\"complete\"`. It turns `false` in the first emission after `window` fired\n\t * `load` and the Polkadot registry (`window.injectedWeb3`) was read again,\n\t * so that emission already lists every extension injected by `load`. When the\n\t * subscription starts after `load`, it is `false` from the first emission.\n\t * Always `true` on the server.\n\t *\n\t * This rests on wallets injecting `injectedWeb3` before `load`. It says\n\t * nothing about wallets that inject after `load`. Ethereum (EIP-6963) and\n\t * Solana (Wallet Standard) registries are event-driven and need no re-read.\n\t */\n\tisDiscovering: boolean;\n};\n\n/** Shape of the persisted store data (localStorage, or cookies in compact form). */\nexport type KheopskitStoreData = {\n\t/** Wallets the user connected and has not disconnected */\n\tremembered?: WalletId[];\n\t/** Cached wallet state for SSR hydration to prevent UI flash */\n\tcachedWallets?: CachedWallet[];\n\t/** Cached account state for SSR hydration to prevent UI flash */\n\tcachedAccounts?: CachedAccount[];\n};\n\n/**\n * The persisted settings store shared between core and framework bindings.\n * Declared structurally here (implemented by `createKheopskitStore`) so modules\n * can depend on the interface without importing the implementation.\n */\nexport type KheopskitStore = {\n\tobservable: Observable<KheopskitStoreData>;\n\trememberWallet: (walletId: WalletId) => void;\n\tforgetWallet: (walletId: WalletId) => void;\n\tgetCachedState: () => { wallets: CachedWallet[]; accounts: CachedAccount[] };\n\tsetCachedState: (wallets: CachedWallet[], accounts: CachedAccount[]) => void;\n\t/** Stops cross-tab storage sync and completes `observable`. */\n\tdestroy: () => void;\n};\n\n/**\n * Serializable wallet data for SSR hydration cache.\n * Contains only the data needed to render wallet UI without flash.\n * Note: icon is NOT stored to save cookie space - it's looked up at hydration time.\n */\nexport type CachedWallet = {\n\tid: WalletId;\n\t/** Absent for the platform-less WalletConnect connector. */\n\tplatform?: WalletPlatform;\n\ttype: WalletType;\n\tname: string;\n\tisConnected: boolean;\n};\n\n/**\n * Serializable account data for SSR hydration cache.\n * Contains only the data needed to render account UI without flash.\n */\nexport type CachedAccount = {\n\tid: string;\n\tplatform: WalletPlatform;\n\taddress: string;\n\tname?: string;\n\t/** Cached chain ID for Ethereum accounts. */\n\tchainId?: number;\n\t/** Cached key type for Polkadot accounts. */\n\tpolkadotAccountType?: PolkadotAccountType;\n\twalletId: WalletId;\n\twalletName: string;\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { E as isWalletConnectWallet, _ as WalletConnectMetadata, b as WalletConnectWallet, v as WalletConnectPlugin } from "./types-Dkyt9bf4.mjs";
|
|
2
|
+
//#region src/api/walletconnect/plugin.d.ts
|
|
3
|
+
type WalletConnectOptions = {
|
|
4
|
+
projectId: string;
|
|
5
|
+
metadata: WalletConnectMetadata;
|
|
6
|
+
/**
|
|
7
|
+
* Networks AppKit should enable. Pass `AppKitNetwork[]` from
|
|
8
|
+
* `@reown/appkit/networks` (see
|
|
9
|
+
* https://docs.reown.com/advanced/multichain/polkadot/dapp-integration-guide#walletconnect-code%2Fcomponent-setup).
|
|
10
|
+
* Loosely typed (`unknown`) so the declarations don't depend on
|
|
11
|
+
* `@reown/appkit`'s types; the value is forwarded to AppKit as-is.
|
|
12
|
+
*/
|
|
13
|
+
networks: [unknown, ...unknown[]];
|
|
14
|
+
themeMode?: "light" | "dark";
|
|
15
|
+
themeVariables?: Record<string, string | number>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Clears the cached AppKit observable.
|
|
19
|
+
* Use when configuration changes or for testing purposes.
|
|
20
|
+
* Note: This does NOT destroy the appKit instance created by Reown.
|
|
21
|
+
*/
|
|
22
|
+
export declare const resetAppKitCache: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* The WalletConnect plugin for `config.walletConnect`. Importing this entry is
|
|
25
|
+
* what brings Reown AppKit into a dapp's bundle; a dapp that never imports it
|
|
26
|
+
* ships none of it.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { walletConnect } from "@kheopskit/core/walletconnect";
|
|
31
|
+
*
|
|
32
|
+
* getKheopskit$({
|
|
33
|
+
* platforms: [polkadot()],
|
|
34
|
+
* walletConnect: walletConnect({ projectId, metadata, networks }),
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare const walletConnect: (options: WalletConnectOptions) => WalletConnectPlugin;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { type WalletConnectMetadata, type WalletConnectOptions, type WalletConnectPlugin, type WalletConnectWallet, isWalletConnectWallet };
|
|
41
|
+
//# sourceMappingURL=walletconnect.d.mts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { E as isWalletConnectWallet, _ as WalletConnectMetadata, b as WalletConnectWallet, v as WalletConnectPlugin } from "./types-Dkyt9bf4.js";
|
|
2
|
+
//#region src/api/walletconnect/plugin.d.ts
|
|
3
|
+
type WalletConnectOptions = {
|
|
4
|
+
projectId: string;
|
|
5
|
+
metadata: WalletConnectMetadata;
|
|
6
|
+
/**
|
|
7
|
+
* Networks AppKit should enable. Pass `AppKitNetwork[]` from
|
|
8
|
+
* `@reown/appkit/networks` (see
|
|
9
|
+
* https://docs.reown.com/advanced/multichain/polkadot/dapp-integration-guide#walletconnect-code%2Fcomponent-setup).
|
|
10
|
+
* Loosely typed (`unknown`) so the declarations don't depend on
|
|
11
|
+
* `@reown/appkit`'s types; the value is forwarded to AppKit as-is.
|
|
12
|
+
*/
|
|
13
|
+
networks: [unknown, ...unknown[]];
|
|
14
|
+
themeMode?: "light" | "dark";
|
|
15
|
+
themeVariables?: Record<string, string | number>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Clears the cached AppKit observable.
|
|
19
|
+
* Use when configuration changes or for testing purposes.
|
|
20
|
+
* Note: This does NOT destroy the appKit instance created by Reown.
|
|
21
|
+
*/
|
|
22
|
+
export declare const resetAppKitCache: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* The WalletConnect plugin for `config.walletConnect`. Importing this entry is
|
|
25
|
+
* what brings Reown AppKit into a dapp's bundle; a dapp that never imports it
|
|
26
|
+
* ships none of it.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { walletConnect } from "@kheopskit/core/walletconnect";
|
|
31
|
+
*
|
|
32
|
+
* getKheopskit$({
|
|
33
|
+
* platforms: [polkadot()],
|
|
34
|
+
* walletConnect: walletConnect({ projectId, metadata, networks }),
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare const walletConnect: (options: WalletConnectOptions) => WalletConnectPlugin;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { type WalletConnectMetadata, type WalletConnectOptions, type WalletConnectPlugin, type WalletConnectWallet, isWalletConnectWallet };
|
|
41
|
+
//# sourceMappingURL=walletconnect.d.ts.map
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_types = require("./types-BWHvNFlN.js");
|
|
3
|
+
let rxjs = require("rxjs");
|
|
4
|
+
//#region src/api/walletconnect/plugin.ts
|
|
5
|
+
/**
|
|
6
|
+
* Dynamically import @reown/appkit/core to avoid loading browser-only code
|
|
7
|
+
* during SSR or in edge runtimes like Cloudflare Workers.
|
|
8
|
+
* The AppKit library uses Lit for web components which requires document.
|
|
9
|
+
*/
|
|
10
|
+
const loadAppKit = async () => {
|
|
11
|
+
try {
|
|
12
|
+
const { createAppKit } = await import("@reown/appkit/core");
|
|
13
|
+
return createAppKit;
|
|
14
|
+
} catch (cause) {
|
|
15
|
+
console.error("[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.", cause);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const WALLET_CONNECT_ICON = "data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjQwMCIgdmlld0JveD0iMCAwIDQwMCA0MDAiIHdpZHRoPSI0MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxjbGlwUGF0aCBpZD0iYSI+PHBhdGggZD0ibTAgMGg0MDB2NDAwaC00MDB6Ii8+PC9jbGlwUGF0aD48ZyBjbGlwLXBhdGg9InVybCgjYSkiPjxjaXJjbGUgY3g9IjIwMCIgY3k9IjIwMCIgZmlsbD0iIzMzOTZmZiIgcj0iMTk5LjUiIHN0cm9rZT0iIzY2YjFmZiIvPjxwYXRoIGQ9Im0xMjIuNTE5IDE0OC45NjVjNDIuNzkxLTQxLjcyOSAxMTIuMTcxLTQxLjcyOSAxNTQuOTYyIDBsNS4xNSA1LjAyMmMyLjE0IDIuMDg2IDIuMTQgNS40NjkgMCA3LjU1NWwtMTcuNjE3IDE3LjE4Yy0xLjA3IDEuMDQzLTIuODA0IDEuMDQzLTMuODc0IDBsLTcuMDg3LTYuOTExYy0yOS44NTMtMjkuMTExLTc4LjI1My0yOS4xMTEtMTA4LjEwNiAwbC03LjU5IDcuNDAxYy0xLjA3IDEuMDQzLTIuODA0IDEuMDQzLTMuODc0IDBsLTE3LjYxNy0xNy4xOGMtMi4xNC0yLjA4Ni0yLjE0LTUuNDY5IDAtNy41NTV6bTE5MS4zOTcgMzUuNTI5IDE1LjY3OSAxNS4yOWMyLjE0IDIuMDg2IDIuMTQgNS40NjkgMCA3LjU1NWwtNzAuNyA2OC45NDRjLTIuMTM5IDIuMDg3LTUuNjA4IDIuMDg3LTcuNzQ4IDBsLTUwLjE3OC00OC45MzFjLS41MzUtLjUyMi0xLjQwMi0uNTIyLTEuOTM3IDBsLTUwLjE3OCA0OC45MzFjLTIuMTM5IDIuMDg3LTUuNjA4IDIuMDg3LTcuNzQ4IDBsLTcwLjcwMTUtNjguOTQ1Yy0yLjEzOTYtMi4wODYtMi4xMzk2LTUuNDY5IDAtNy41NTVsMTUuNjc5NS0xNS4yOWMyLjEzOTYtMi4wODYgNS42MDg1LTIuMDg2IDcuNzQ4MSAwbDUwLjE3ODkgNDguOTMyYy41MzUuNTIyIDEuNDAyLjUyMiAxLjkzNyAwbDUwLjE3Ny00OC45MzJjMi4xMzktMi4wODcgNS42MDgtMi4wODcgNy43NDggMGw1MC4xNzkgNDguOTMyYy41MzUuNTIyIDEuNDAyLjUyMiAxLjkzNyAwbDUwLjE3OS00OC45MzFjMi4xMzktMi4wODcgNS42MDgtMi4wODcgNy43NDggMHoiIGZpbGw9IiNmZmYiLz48L2c+PC9zdmc+";
|
|
20
|
+
const APPKIT_SYMBOL = Symbol.for("kheopskit.cachedAppKit");
|
|
21
|
+
const APPKIT_PROJECT_ID_SYMBOL = Symbol.for("kheopskit.cachedAppKitProjectId");
|
|
22
|
+
const getCachedAppKit = () => globalThis[APPKIT_SYMBOL];
|
|
23
|
+
const getCachedAppKitProjectId = () => globalThis[APPKIT_PROJECT_ID_SYMBOL];
|
|
24
|
+
const setCachedAppKit = (value, projectId) => {
|
|
25
|
+
globalThis[APPKIT_SYMBOL] = value;
|
|
26
|
+
globalThis[APPKIT_PROJECT_ID_SYMBOL] = projectId;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Clears the cached AppKit observable.
|
|
30
|
+
* Use when configuration changes or for testing purposes.
|
|
31
|
+
* Note: This does NOT destroy the appKit instance created by Reown.
|
|
32
|
+
*/
|
|
33
|
+
const resetAppKitCache = () => {
|
|
34
|
+
setCachedAppKit(void 0);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Keys are `accounts:<walletId>:...`; the trailing colon scopes the prefix to
|
|
38
|
+
* this wallet and avoids matching a sibling whose id is a string prefix.
|
|
39
|
+
*/
|
|
40
|
+
const dropAccountsCache = (platform) => {
|
|
41
|
+
require_types.clearCachedObservablesByPrefix(`accounts:${require_types.WALLET_CONNECT_WALLET_ID}:${platform}:`);
|
|
42
|
+
};
|
|
43
|
+
const namespaceOf = {
|
|
44
|
+
polkadot: "polkadot",
|
|
45
|
+
ethereum: "eip155",
|
|
46
|
+
solana: "solana"
|
|
47
|
+
};
|
|
48
|
+
const allPlatforms = [
|
|
49
|
+
"polkadot",
|
|
50
|
+
"ethereum",
|
|
51
|
+
"solana"
|
|
52
|
+
];
|
|
53
|
+
const createConnector$ = (appKit) => {
|
|
54
|
+
const appKitInstance = appKit;
|
|
55
|
+
const status$ = new rxjs.BehaviorSubject({
|
|
56
|
+
isPolkadotConnected: false,
|
|
57
|
+
isEthereumConnected: false,
|
|
58
|
+
isSolanaConnected: false,
|
|
59
|
+
opening: false,
|
|
60
|
+
error: void 0
|
|
61
|
+
});
|
|
62
|
+
const syncProviders = (providers) => {
|
|
63
|
+
status$.next({
|
|
64
|
+
...status$.value,
|
|
65
|
+
isPolkadotConnected: !!providers.polkadot,
|
|
66
|
+
isEthereumConnected: !!providers.eip155,
|
|
67
|
+
isSolanaConnected: !!providers.solana
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const openModal = async () => {
|
|
71
|
+
status$.next({
|
|
72
|
+
...status$.value,
|
|
73
|
+
opening: true,
|
|
74
|
+
error: void 0
|
|
75
|
+
});
|
|
76
|
+
try {
|
|
77
|
+
await appKit.open();
|
|
78
|
+
} catch (cause) {
|
|
79
|
+
const error = require_types.toConnectError(cause, require_types.WALLET_CONNECT_WALLET_ID, () => false);
|
|
80
|
+
status$.next({
|
|
81
|
+
...status$.value,
|
|
82
|
+
opening: false,
|
|
83
|
+
error
|
|
84
|
+
});
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
status$.next({
|
|
88
|
+
...status$.value,
|
|
89
|
+
opening: false
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const enabledPlatforms = allPlatforms.filter((p) => appKit.chainNamespaces.includes(namespaceOf[p]));
|
|
93
|
+
let prevConnected = {
|
|
94
|
+
polkadot: false,
|
|
95
|
+
ethereum: false,
|
|
96
|
+
solana: false
|
|
97
|
+
};
|
|
98
|
+
const wallet$ = status$.pipe((0, rxjs.map)((s) => ({
|
|
99
|
+
polkadot: s.isPolkadotConnected,
|
|
100
|
+
ethereum: s.isEthereumConnected,
|
|
101
|
+
solana: s.isSolanaConnected,
|
|
102
|
+
opening: s.opening,
|
|
103
|
+
error: s.error
|
|
104
|
+
})), (0, rxjs.distinctUntilChanged)((a, b) => a.polkadot === b.polkadot && a.ethereum === b.ethereum && a.solana === b.solana && a.opening === b.opening && a.error === b.error), (0, rxjs.tap)((connected) => {
|
|
105
|
+
for (const platform of allPlatforms) if (prevConnected[platform] && !connected[platform]) dropAccountsCache(platform);
|
|
106
|
+
prevConnected = connected;
|
|
107
|
+
}), (0, rxjs.map)(({ opening, error, ...connected }) => {
|
|
108
|
+
const platforms = enabledPlatforms.filter((p) => connected[p]);
|
|
109
|
+
const isConnected = platforms.length > 0;
|
|
110
|
+
const walletInfo = appKit.getWalletInfo();
|
|
111
|
+
return {
|
|
112
|
+
id: require_types.WALLET_CONNECT_WALLET_ID,
|
|
113
|
+
type: "walletconnect",
|
|
114
|
+
platforms,
|
|
115
|
+
appKit: appKitInstance,
|
|
116
|
+
name: walletInfo?.name ?? "WalletConnect",
|
|
117
|
+
icon: walletInfo?.icon ?? WALLET_CONNECT_ICON,
|
|
118
|
+
connect: async () => {
|
|
119
|
+
if (!isConnected) await openModal();
|
|
120
|
+
},
|
|
121
|
+
disconnect: async () => {
|
|
122
|
+
if (isConnected) await appKit.disconnect();
|
|
123
|
+
},
|
|
124
|
+
status: isConnected ? "connected" : opening ? "connecting" : "disconnected",
|
|
125
|
+
error,
|
|
126
|
+
isConnected
|
|
127
|
+
};
|
|
128
|
+
}));
|
|
129
|
+
return new rxjs.Observable((subscriber) => {
|
|
130
|
+
for (const platform of allPlatforms) dropAccountsCache(platform);
|
|
131
|
+
syncProviders({
|
|
132
|
+
polkadot: appKit.getProvider("polkadot"),
|
|
133
|
+
eip155: appKit.getProvider("eip155"),
|
|
134
|
+
solana: appKit.getProvider("solana")
|
|
135
|
+
});
|
|
136
|
+
const unsubProviders = appKit.subscribeProviders(syncProviders);
|
|
137
|
+
const sub = wallet$.subscribe(subscriber);
|
|
138
|
+
return () => {
|
|
139
|
+
sub.unsubscribe();
|
|
140
|
+
unsubProviders();
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* @remarks
|
|
146
|
+
* The AppKit instance is a process-wide singleton: a second instance would
|
|
147
|
+
* share AppKit's module-level controller state with the first, so it is
|
|
148
|
+
* created once. The **first** call with a `walletConnect` config wins;
|
|
149
|
+
* later calls with a *different* `walletConnect` config reuse that first
|
|
150
|
+
* instance. Call {@link resetAppKitCache} before re-initialising if the
|
|
151
|
+
* WalletConnect config must change.
|
|
152
|
+
*
|
|
153
|
+
* One WalletConnect session is shared across every namespace, and a namespace
|
|
154
|
+
* can only be established during the initial pairing — it can't be added to a
|
|
155
|
+
* live session afterwards. So this exposes ONE connector (not one per platform):
|
|
156
|
+
* `connect()` opens the modal; the wallet approves whichever namespaces it
|
|
157
|
+
* supports in that single pairing, and `platforms` reflects what the live
|
|
158
|
+
* session carries. Per-namespace accounts are derived by each platform plugin.
|
|
159
|
+
*/
|
|
160
|
+
const getWalletConnectWallet$ = (walletConnect, debug) => {
|
|
161
|
+
if (typeof window === "undefined") return (0, rxjs.of)(null);
|
|
162
|
+
const cachedProjectId = getCachedAppKitProjectId();
|
|
163
|
+
if (cachedProjectId !== void 0 && cachedProjectId !== walletConnect.projectId) console.warn("[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.", cachedProjectId, walletConnect.projectId);
|
|
164
|
+
let cachedAppKit = getCachedAppKit();
|
|
165
|
+
if (!cachedAppKit) {
|
|
166
|
+
cachedAppKit = (0, rxjs.from)(loadAppKit()).pipe((0, rxjs.map)((createAppKit) => createAppKit ? createConnector$(createAppKit({
|
|
167
|
+
projectId: walletConnect.projectId,
|
|
168
|
+
metadata: walletConnect.metadata,
|
|
169
|
+
networks: walletConnect.networks,
|
|
170
|
+
themeMode: walletConnect.themeMode,
|
|
171
|
+
themeVariables: walletConnect.themeVariables,
|
|
172
|
+
universalProviderConfigOverride: { methods: {
|
|
173
|
+
polkadot: ["polkadot_signTransaction", "polkadot_signMessage"],
|
|
174
|
+
solana: [
|
|
175
|
+
"solana_signTransaction",
|
|
176
|
+
"solana_signMessage",
|
|
177
|
+
"solana_signAndSendTransaction"
|
|
178
|
+
]
|
|
179
|
+
} },
|
|
180
|
+
allWallets: "HIDE",
|
|
181
|
+
debug,
|
|
182
|
+
allowUnsupportedChain: true
|
|
183
|
+
})) : null), (0, rxjs.shareReplay)({
|
|
184
|
+
refCount: false,
|
|
185
|
+
bufferSize: 1
|
|
186
|
+
})).pipe((0, rxjs.switchMap)((wallet$) => wallet$ ?? (0, rxjs.of)(null)), (0, rxjs.shareReplay)({
|
|
187
|
+
refCount: true,
|
|
188
|
+
bufferSize: 1
|
|
189
|
+
}));
|
|
190
|
+
setCachedAppKit(cachedAppKit, walletConnect.projectId);
|
|
191
|
+
}
|
|
192
|
+
return cachedAppKit;
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* The WalletConnect plugin for `config.walletConnect`. Importing this entry is
|
|
196
|
+
* what brings Reown AppKit into a dapp's bundle; a dapp that never imports it
|
|
197
|
+
* ships none of it.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* import { walletConnect } from "@kheopskit/core/walletconnect";
|
|
202
|
+
*
|
|
203
|
+
* getKheopskit$({
|
|
204
|
+
* platforms: [polkadot()],
|
|
205
|
+
* walletConnect: walletConnect({ projectId, metadata, networks }),
|
|
206
|
+
* });
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
const walletConnect = (options) => ({
|
|
210
|
+
type: "walletconnect",
|
|
211
|
+
metadata: options.metadata,
|
|
212
|
+
getWallet$: ({ config }) => getWalletConnectWallet$(options, config.debug)
|
|
213
|
+
});
|
|
214
|
+
//#endregion
|
|
215
|
+
exports.isWalletConnectWallet = require_types.isWalletConnectWallet;
|
|
216
|
+
exports.resetAppKitCache = resetAppKitCache;
|
|
217
|
+
exports.walletConnect = walletConnect;
|
|
218
|
+
|
|
219
|
+
//# sourceMappingURL=walletconnect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walletconnect.js","names":["WALLET_CONNECT_WALLET_ID","BehaviorSubject","toConnectError","map","distinctUntilChanged","tap","Observable","of","from","shareReplay","switchMap"],"sources":["../src/api/walletconnect/plugin.ts"],"sourcesContent":["import type { AppKit } from \"@reown/appkit/core\";\nimport {\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 KheopskitError, toConnectError } from \"../errors\";\nimport type {\n\tAppKitInstance,\n\tWalletConnectMetadata,\n\tWalletConnectPlugin,\n\tWalletConnectWallet,\n\tWalletPlatform,\n} from \"../types\";\n\nexport type WalletConnectOptions = {\n\tprojectId: string;\n\tmetadata: WalletConnectMetadata;\n\t/**\n\t * Networks AppKit should enable. Pass `AppKitNetwork[]` from\n\t * `@reown/appkit/networks` (see\n\t * https://docs.reown.com/advanced/multichain/polkadot/dapp-integration-guide#walletconnect-code%2Fcomponent-setup).\n\t * Loosely typed (`unknown`) so the declarations don't depend on\n\t * `@reown/appkit`'s types; the value is forwarded to AppKit as-is.\n\t */\n\tnetworks: [unknown, ...unknown[]];\n\tthemeMode?: \"light\" | \"dark\";\n\tthemeVariables?: Record<string, string | number>;\n};\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 * 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\nconst namespaceOf: Record<WalletPlatform, string> = {\n\tpolkadot: \"polkadot\",\n\tethereum: \"eip155\",\n\tsolana: \"solana\",\n};\nconst allPlatforms: WalletPlatform[] = [\"polkadot\", \"ethereum\", \"solana\"];\n\nconst createConnector$ = (appKit: AppKit): Observable<WalletConnectWallet> => {\n\t// Exposed on the wallet as the (decoupled) AppKitInstance escape hatch.\n\tconst appKitInstance = appKit as unknown as AppKitInstance;\n\n\tconst status$ = new BehaviorSubject<{\n\t\tisPolkadotConnected: boolean;\n\t\tisEthereumConnected: boolean;\n\t\tisSolanaConnected: boolean;\n\t\topening: boolean;\n\t\terror: KheopskitError | undefined;\n\t}>({\n\t\tisPolkadotConnected: false,\n\t\tisEthereumConnected: false,\n\t\tisSolanaConnected: false,\n\t\topening: false,\n\t\terror: undefined,\n\t});\n\n\tconst syncProviders = (providers: Partial<Record<string, unknown>>) => {\n\t\tstatus$.next({\n\t\t\t...status$.value,\n\t\t\tisPolkadotConnected: !!providers.polkadot,\n\t\t\tisEthereumConnected: !!providers.eip155,\n\t\t\tisSolanaConnected: !!providers.solana,\n\t\t});\n\t};\n\n\tconst openModal = async () => {\n\t\tstatus$.next({ ...status$.value, opening: true, error: undefined });\n\t\ttry {\n\t\t\tawait appKit.open();\n\t\t} catch (cause) {\n\t\t\tconst error = toConnectError(\n\t\t\t\tcause,\n\t\t\t\tWALLET_CONNECT_WALLET_ID,\n\t\t\t\t() => false,\n\t\t\t);\n\t\t\tstatus$.next({ ...status$.value, opening: false, error });\n\t\t\tthrow error;\n\t\t}\n\t\tstatus$.next({ ...status$.value, opening: false });\n\t};\n\n\tconst enabledPlatforms = allPlatforms.filter((p) =>\n\t\t(appKit.chainNamespaces as string[]).includes(namespaceOf[p]),\n\t);\n\n\tlet prevConnected = {\n\t\tpolkadot: false,\n\t\tethereum: false,\n\t\tsolana: false,\n\t};\n\n\tconst wallet$ = status$.pipe(\n\t\tmap((s) => ({\n\t\t\tpolkadot: s.isPolkadotConnected,\n\t\t\tethereum: s.isEthereumConnected,\n\t\t\tsolana: s.isSolanaConnected,\n\t\t\topening: s.opening,\n\t\t\terror: s.error,\n\t\t})),\n\t\tdistinctUntilChanged(\n\t\t\t(a, b) =>\n\t\t\t\ta.polkadot === b.polkadot &&\n\t\t\t\ta.ethereum === b.ethereum &&\n\t\t\t\ta.solana === b.solana &&\n\t\t\t\ta.opening === b.opening &&\n\t\t\t\ta.error === b.error,\n\t\t),\n\t\ttap((connected) => {\n\t\t\t// Drop caches for namespaces that just went disconnected.\n\t\t\tfor (const platform of allPlatforms)\n\t\t\t\tif (prevConnected[platform] && !connected[platform])\n\t\t\t\t\tdropAccountsCache(platform);\n\t\t\tprevConnected = connected;\n\t\t}),\n\t\tmap(({ opening, error, ...connected }): WalletConnectWallet => {\n\t\t\tconst platforms = enabledPlatforms.filter((p) => connected[p]);\n\t\t\tconst isConnected = platforms.length > 0;\n\t\t\tconst walletInfo = appKit.getWalletInfo();\n\t\t\treturn {\n\t\t\t\tid: WALLET_CONNECT_WALLET_ID,\n\t\t\t\ttype: \"walletconnect\",\n\t\t\t\tplatforms,\n\t\t\t\tappKit: appKitInstance,\n\t\t\t\tname: walletInfo?.name ?? \"WalletConnect\",\n\t\t\t\ticon: walletInfo?.icon ?? WALLET_CONNECT_ICON,\n\t\t\t\t// One shared session: connecting opens the modal; the wallet\n\t\t\t\t// approves namespaces in that single pairing. Disconnect is\n\t\t\t\t// session-wide; re-pair to change the approved set.\n\t\t\t\tconnect: async () => {\n\t\t\t\t\tif (!isConnected) await openModal();\n\t\t\t\t},\n\t\t\t\tdisconnect: async () => {\n\t\t\t\t\tif (isConnected) await appKit.disconnect();\n\t\t\t\t},\n\t\t\t\tstatus: isConnected\n\t\t\t\t\t? \"connected\"\n\t\t\t\t\t: opening\n\t\t\t\t\t\t? \"connecting\"\n\t\t\t\t\t\t: \"disconnected\",\n\t\t\t\terror,\n\t\t\t\tisConnected,\n\t\t\t};\n\t\t}),\n\t);\n\n\treturn new Observable<WalletConnectWallet>((subscriber) => {\n\t\tfor (const platform of allPlatforms) dropAccountsCache(platform);\n\t\t// AppKit's subscribeProviders only reports later changes, so read the\n\t\t// state that may have changed while nobody observed.\n\t\tsyncProviders({\n\t\t\tpolkadot: appKit.getProvider(\"polkadot\"),\n\t\t\teip155: appKit.getProvider(\"eip155\"),\n\t\t\tsolana: appKit.getProvider(\"solana\"),\n\t\t});\n\t\tconst unsubProviders = appKit.subscribeProviders(syncProviders);\n\t\tconst sub = wallet$.subscribe(subscriber);\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t\tunsubProviders();\n\t\t};\n\t});\n};\n\n/**\n * @remarks\n * The AppKit instance is a process-wide singleton: a second instance would\n * share AppKit's module-level controller state with the first, so it is\n * created once. 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 */\nconst getWalletConnectWallet$ = (\n\twalletConnect: WalletConnectOptions,\n\tdebug: boolean,\n): Observable<WalletConnectWallet | null> => {\n\t// SSR guard - don't try to load AppKit on the server\n\tif (typeof window === \"undefined\") return of(null);\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\tconst connectorOnce$ = from(loadAppKit()).pipe(\n\t\t\tmap((createAppKit) =>\n\t\t\t\t// @reown/appkit missing (optional peer dep) — degrade gracefully.\n\t\t\t\tcreateAppKit\n\t\t\t\t\t? createConnector$(\n\t\t\t\t\t\t\tcreateAppKit({\n\t\t\t\t\t\t\t\tprojectId: walletConnect.projectId,\n\t\t\t\t\t\t\t\tmetadata: walletConnect.metadata,\n\t\t\t\t\t\t\t\tnetworks: walletConnect.networks as never,\n\t\t\t\t\t\t\t\tthemeMode: walletConnect.themeMode,\n\t\t\t\t\t\t\t\tthemeVariables: walletConnect.themeVariables as never,\n\t\t\t\t\t\t\t\tuniversalProviderConfigOverride: {\n\t\t\t\t\t\t\t\t\tmethods: {\n\t\t\t\t\t\t\t\t\t\tpolkadot: [\n\t\t\t\t\t\t\t\t\t\t\t\"polkadot_signTransaction\",\n\t\t\t\t\t\t\t\t\t\t\t\"polkadot_signMessage\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\tsolana: [\n\t\t\t\t\t\t\t\t\t\t\t\"solana_signTransaction\",\n\t\t\t\t\t\t\t\t\t\t\t\"solana_signMessage\",\n\t\t\t\t\t\t\t\t\t\t\t\"solana_signAndSendTransaction\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tallWallets: \"HIDE\",\n\t\t\t\t\t\t\t\tdebug,\n\t\t\t\t\t\t\t\tallowUnsupportedChain: true,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t: null,\n\t\t\t),\n\t\t\tshareReplay({ refCount: false, bufferSize: 1 }),\n\t\t);\n\t\tcachedAppKit = connectorOnce$.pipe(\n\t\t\tswitchMap((wallet$) => wallet$ ?? of(null)),\n\t\t\tshareReplay({ refCount: true, bufferSize: 1 }),\n\t\t);\n\t\tsetCachedAppKit(cachedAppKit, walletConnect.projectId);\n\t}\n\n\treturn cachedAppKit;\n};\n\n/**\n * The WalletConnect plugin for `config.walletConnect`. Importing this entry is\n * what brings Reown AppKit into a dapp's bundle; a dapp that never imports it\n * ships none of it.\n *\n * @example\n * ```ts\n * import { walletConnect } from \"@kheopskit/core/walletconnect\";\n *\n * getKheopskit$({\n * platforms: [polkadot()],\n * walletConnect: walletConnect({ projectId, metadata, networks }),\n * });\n * ```\n */\nexport const walletConnect = (\n\toptions: WalletConnectOptions,\n): WalletConnectPlugin => ({\n\ttype: \"walletconnect\",\n\tmetadata: options.metadata,\n\tgetWallet$: ({ config }) => getWalletConnectWallet$(options, config.debug),\n});\n"],"mappings":"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"}
|