@kheopskit/core 5.3.0 → 6.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +432 -0
  2. package/MIGRATING_TO_V6.md +840 -0
  3. package/README.md +629 -12
  4. package/dist/ethereum.d.mts +12 -6
  5. package/dist/ethereum.d.ts +12 -6
  6. package/dist/ethereum.js +13 -10
  7. package/dist/ethereum.js.map +1 -1
  8. package/dist/ethereum.mjs +7 -4
  9. package/dist/ethereum.mjs.map +1 -1
  10. package/dist/{iconCache-pP2ES4pJ.mjs → iconCache-C-U3IEbP.mjs} +21 -40
  11. package/dist/iconCache-C-U3IEbP.mjs.map +1 -0
  12. package/dist/{iconCache-DUtkJlaX.js → iconCache-FR4iy6go.js} +21 -40
  13. package/dist/iconCache-FR4iy6go.js.map +1 -0
  14. package/dist/index.d.mts +17 -63
  15. package/dist/index.d.ts +17 -63
  16. package/dist/index.js +387 -373
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +384 -369
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/injectedWallets-48L-AL1I.mjs +173 -0
  21. package/dist/injectedWallets-48L-AL1I.mjs.map +1 -0
  22. package/dist/injectedWallets-Dy8YGKL-.js +178 -0
  23. package/dist/injectedWallets-Dy8YGKL-.js.map +1 -0
  24. package/dist/internal.d.mts +3 -27
  25. package/dist/internal.d.ts +3 -27
  26. package/dist/internal.js +2 -2
  27. package/dist/internal.mjs +2 -2
  28. package/dist/pageLoad-BZ7o8p5R.mjs +24 -0
  29. package/dist/pageLoad-BZ7o8p5R.mjs.map +1 -0
  30. package/dist/pageLoad-D1wLeuFG.js +28 -0
  31. package/dist/pageLoad-D1wLeuFG.js.map +1 -0
  32. package/dist/platformAccounts-BjIeRcFN.js +321 -0
  33. package/dist/platformAccounts-BjIeRcFN.js.map +1 -0
  34. package/dist/platformAccounts-yyRUrnel.mjs +256 -0
  35. package/dist/platformAccounts-yyRUrnel.mjs.map +1 -0
  36. package/dist/polkadot.d.mts +127 -11
  37. package/dist/polkadot.d.ts +127 -11
  38. package/dist/polkadot.js +187 -106
  39. package/dist/polkadot.js.map +1 -1
  40. package/dist/polkadot.mjs +180 -99
  41. package/dist/polkadot.mjs.map +1 -1
  42. package/dist/solana.d.mts +11 -5
  43. package/dist/solana.d.ts +11 -5
  44. package/dist/solana.js +18 -15
  45. package/dist/solana.js.map +1 -1
  46. package/dist/solana.mjs +7 -4
  47. package/dist/solana.mjs.map +1 -1
  48. package/dist/storage-D3AwNgqc.d.mts +27 -0
  49. package/dist/storage-D3AwNgqc.d.ts +27 -0
  50. package/dist/testing.d.mts +71 -0
  51. package/dist/testing.d.ts +71 -0
  52. package/dist/testing.js +136 -0
  53. package/dist/testing.js.map +1 -0
  54. package/dist/testing.mjs +131 -0
  55. package/dist/testing.mjs.map +1 -0
  56. package/dist/{types-DKU-SNio.js → types-BWHvNFlN.js} +149 -2
  57. package/dist/types-BWHvNFlN.js.map +1 -0
  58. package/dist/types-Yor672md.mjs +215 -0
  59. package/dist/types-Yor672md.mjs.map +1 -0
  60. package/dist/types-lkMXVJNG.d.mts +685 -0
  61. package/dist/types-lkMXVJNG.d.ts +685 -0
  62. package/dist/walletconnect.d.mts +41 -0
  63. package/dist/walletconnect.d.ts +41 -0
  64. package/dist/walletconnect.js +219 -0
  65. package/dist/walletconnect.js.map +1 -0
  66. package/dist/walletconnect.mjs +216 -0
  67. package/dist/walletconnect.mjs.map +1 -0
  68. package/package.json +30 -6
  69. package/dist/errors-BLFP1dQI.mjs +0 -181
  70. package/dist/errors-BLFP1dQI.mjs.map +0 -1
  71. package/dist/errors-DYWVPHrR.js +0 -222
  72. package/dist/errors-DYWVPHrR.js.map +0 -1
  73. package/dist/iconCache-DUtkJlaX.js.map +0 -1
  74. package/dist/iconCache-pP2ES4pJ.mjs.map +0 -1
  75. package/dist/injectedWallets-BqR-_aAy.js +0 -148
  76. package/dist/injectedWallets-BqR-_aAy.js.map +0 -1
  77. package/dist/injectedWallets-Uz4hPuoW.mjs +0 -119
  78. package/dist/injectedWallets-Uz4hPuoW.mjs.map +0 -1
  79. package/dist/types-AxUDtkR-.d.mts +0 -338
  80. package/dist/types-AxUDtkR-.d.ts +0 -338
  81. package/dist/types-DKU-SNio.js.map +0 -1
  82. package/dist/types-jnifAAA0.mjs +0 -104
  83. package/dist/types-jnifAAA0.mjs.map +0 -1
@@ -0,0 +1,321 @@
1
+ const require_types = require("./types-BWHvNFlN.js");
2
+ let _noble_hashes_sha3_js = require("@noble/hashes/sha3.js");
3
+ let _scure_base = require("@scure/base");
4
+ let _noble_hashes_blake2_js = require("@noble/hashes/blake2.js");
5
+ let rxjs = require("rxjs");
6
+ //#region src/utils/isEthereumAddress.ts
7
+ const HEX_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
8
+ const encoder = new TextEncoder();
9
+ /**
10
+ * Verifies the EIP-55 mixed-case checksum of an Ethereum address.
11
+ * Dependency-free (keccak via @noble/hashes) so core stays decoupled from viem.
12
+ */
13
+ const isChecksumValid = (address) => {
14
+ const hex = address.slice(2);
15
+ const hash = (0, _noble_hashes_sha3_js.keccak_256)(encoder.encode(hex.toLowerCase()));
16
+ for (let i = 0; i < 40; i++) {
17
+ const char = hex.charAt(i);
18
+ if (!(char >= "a" && char <= "f" || char >= "A" && char <= "F")) continue;
19
+ const byte = hash[i >> 1] ?? 0;
20
+ const nibble = i % 2 === 0 ? byte >> 4 : byte & 15;
21
+ if (char <= "F" !== nibble >= 8) return false;
22
+ }
23
+ return true;
24
+ };
25
+ /**
26
+ * Returns true if `address` is a valid Ethereum address.
27
+ *
28
+ * Mirrors viem's `isAddress` (strict): the shape must be `0x` + 40 hex, and a
29
+ * mixed-case address must pass the EIP-55 checksum. All-lowercase addresses are
30
+ * accepted as non-checksummed.
31
+ */
32
+ const isEthereumAddress = (address) => {
33
+ if (!HEX_ADDRESS.test(address)) return false;
34
+ if (address === address.toLowerCase()) return true;
35
+ return isChecksumValid(address);
36
+ };
37
+ //#endregion
38
+ //#region src/utils/isSolanaAddress.ts
39
+ /**
40
+ * Returns true if the value is a valid Solana address: a base58-encoded
41
+ * 32-byte ed25519 public key.
42
+ *
43
+ * Solana addresses carry no checksum, so this is a pure base58 + length check.
44
+ * Dependency-free (base58 via @scure/base) so core stays decoupled from
45
+ * @solana/kit.
46
+ */
47
+ const isSolanaAddress = (address) => {
48
+ if (!address) return false;
49
+ try {
50
+ return _scure_base.base58.decode(address).length === 32;
51
+ } catch {
52
+ return false;
53
+ }
54
+ };
55
+ //#endregion
56
+ //#region src/utils/isSs58Address.ts
57
+ const SS58PRE = new Uint8Array([
58
+ 83,
59
+ 83,
60
+ 53,
61
+ 56,
62
+ 80,
63
+ 82,
64
+ 69
65
+ ]);
66
+ /**
67
+ * Returns true if `address` is a valid SS58-encoded 32-byte account id (the
68
+ * only form Substrate wallets inject), verifying the blake2b-512 checksum.
69
+ *
70
+ * Dependency-free (base58 via @scure/base, blake2b via @noble/hashes) so core
71
+ * stays decoupled from polkadot-api.
72
+ */
73
+ const isSs58Address = (address) => {
74
+ if (!address) return false;
75
+ let decoded;
76
+ try {
77
+ decoded = _scure_base.base58.decode(address);
78
+ } catch {
79
+ return false;
80
+ }
81
+ const firstByte = decoded[0];
82
+ if (firstByte === void 0 || firstByte & 128) return false;
83
+ const prefixLength = firstByte & 64 ? 2 : 1;
84
+ if (decoded.length !== prefixLength + 32 + 2) return false;
85
+ const body = decoded.subarray(0, decoded.length - 2);
86
+ const preimage = new Uint8Array(SS58PRE.length + body.length);
87
+ preimage.set(SS58PRE);
88
+ preimage.set(body, SS58PRE.length);
89
+ const hash = (0, _noble_hashes_blake2_js.blake2b)(preimage, { dkLen: 64 });
90
+ return decoded[decoded.length - 2] === hash[0] && decoded[decoded.length - 1] === hash[1];
91
+ };
92
+ //#endregion
93
+ //#region src/utils/isValidAddress.ts
94
+ const isValidAddress = (address) => {
95
+ if (address.startsWith("0x")) return isEthereumAddress(address);
96
+ return isSs58Address(address) || isSolanaAddress(address);
97
+ };
98
+ //#endregion
99
+ //#region src/utils/WalletAccountId.ts
100
+ const getWalletAccountId = (walletId, address) => {
101
+ if (!walletId) throw new Error("Missing walletId");
102
+ if (!isValidAddress(address)) throw new Error("Invalid address");
103
+ return `${walletId}::${address}`;
104
+ };
105
+ const parseWalletAccountId = (accountId) => {
106
+ if (!accountId) throw new Error("Invalid walletAccountId");
107
+ const [walletId, address] = accountId.split("::");
108
+ if (!walletId) throw new Error("Missing walletId");
109
+ if (!address || !isValidAddress(address)) throw new Error("Invalid address");
110
+ return {
111
+ walletId,
112
+ address
113
+ };
114
+ };
115
+ //#endregion
116
+ //#region src/api/platformAccounts.ts
117
+ const isPlatformAccounts$ = (accounts$) => "frames$" in accounts$;
118
+ /** A plugin not built on `createPlatformAccounts$` reports no answered wallet. */
119
+ const framesOf = (accounts$) => isPlatformAccounts$(accounts$) ? accounts$.frames$ : accounts$.pipe((0, rxjs.map)((accounts) => ({
120
+ accounts,
121
+ answered: []
122
+ })));
123
+ const idsEqual = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
124
+ const sessionKey = (wallet) => `${wallet.id}|${wallet.platforms.join(",")}`;
125
+ const connectionKey = (wallet) => require_types.isWalletConnectWallet(wallet) ? sessionKey(wallet) : wallet.id;
126
+ /** Shared engine behind every platform's `getAccounts$`. */
127
+ const createPlatformAccounts$ = ({ wallets$, getInjectedAccounts$, getWalletConnectAccounts$, mapAccounts, accountChangeKey = (account) => account.id }) => {
128
+ const nameAndChangeKey = (account) => `${account.name ?? ""}|${accountChangeKey(account)}`;
129
+ const accountsListEqual = (a, b) => a.length === b.length && a.every((account, i) => {
130
+ const other = b[i];
131
+ return !!other && nameAndChangeKey(account) === nameAndChangeKey(other);
132
+ });
133
+ const accountsOf = (wallet) => require_types.isWalletConnectWallet(wallet) ? getWalletConnectAccounts$(wallet) : getInjectedAccounts$(wallet);
134
+ const frames$ = new rxjs.Observable((subscriber) => {
135
+ const connections = /* @__PURE__ */ new Map();
136
+ let connectedIds = [];
137
+ let walletsCompleted = false;
138
+ let emitted = false;
139
+ const awaitingFirstAnswers = () => !emitted && [...connections.values()].some((connection) => !connection.answered);
140
+ const accountsListed = () => connectedIds.flatMap((id) => connections.get(id)?.accounts ?? []);
141
+ const walletsAnswered = () => connectedIds.filter((id) => connections.get(id)?.answered);
142
+ const emit = () => {
143
+ if (awaitingFirstAnswers()) return;
144
+ emitted = true;
145
+ subscriber.next({
146
+ accounts: accountsListed(),
147
+ answered: walletsAnswered()
148
+ });
149
+ };
150
+ const completeIfDone = () => {
151
+ if (walletsCompleted && [...connections.values()].every((connection) => connection.completed)) subscriber.complete();
152
+ };
153
+ const reconcile = (wallets) => {
154
+ const connected = wallets.filter((wallet) => wallet.isConnected && !wallet.isPlaceholder);
155
+ const keys = new Map(connected.map((w) => [w.id, connectionKey(w)]));
156
+ for (const [id, connection] of connections) {
157
+ if (keys.get(id) === connection.key) continue;
158
+ connection.subscription.unsubscribe();
159
+ connections.delete(id);
160
+ }
161
+ connectedIds = connected.map((wallet) => wallet.id);
162
+ const opened = connected.filter((wallet) => !connections.has(wallet.id)).map((wallet) => {
163
+ const connection = {
164
+ key: connectionKey(wallet),
165
+ accounts: [],
166
+ answered: false,
167
+ completed: false,
168
+ subscription: new rxjs.Subscription()
169
+ };
170
+ connections.set(wallet.id, connection);
171
+ return {
172
+ wallet,
173
+ connection
174
+ };
175
+ });
176
+ for (const { wallet, connection } of opened) connection.subscription.add(accountsOf(wallet).subscribe({
177
+ next: (accounts) => {
178
+ connection.accounts = accounts;
179
+ connection.answered = true;
180
+ emit();
181
+ },
182
+ error: (error) => subscriber.error(error),
183
+ complete: () => {
184
+ connection.completed = true;
185
+ completeIfDone();
186
+ }
187
+ }));
188
+ emit();
189
+ };
190
+ const sub = wallets$.subscribe({
191
+ next: reconcile,
192
+ error: (error) => subscriber.error(error),
193
+ complete: () => {
194
+ walletsCompleted = true;
195
+ completeIfDone();
196
+ }
197
+ });
198
+ return () => {
199
+ sub.unsubscribe();
200
+ for (const connection of connections.values()) connection.subscription.unsubscribe();
201
+ };
202
+ }).pipe((0, rxjs.map)((frame) => mapAccounts ? {
203
+ ...frame,
204
+ accounts: mapAccounts(frame.accounts)
205
+ } : frame), (0, rxjs.distinctUntilChanged)((a, b) => accountsListEqual(a.accounts, b.accounts) && idsEqual(a.answered, b.answered)), (0, rxjs.shareReplay)({
206
+ refCount: true,
207
+ bufferSize: 1
208
+ }));
209
+ const accounts$ = frames$.pipe((0, rxjs.map)((frame) => frame.accounts), (0, rxjs.distinctUntilChanged)(accountsListEqual), (0, rxjs.shareReplay)({
210
+ refCount: true,
211
+ bufferSize: 1
212
+ }));
213
+ return Object.assign(accounts$, { frames$ });
214
+ };
215
+ /**
216
+ * CAIP-10 account strings ("<namespace>:<chainRef>:<address>") the live
217
+ * WalletConnect session carries for a namespace.
218
+ */
219
+ const getSessionCaip10s = (session, namespace) => Object.values(session.namespaces).flatMap((ns) => ns.accounts ?? []).filter((account) => account.startsWith(`${namespace}:`));
220
+ /**
221
+ * Unique addresses from CAIP-10 account strings (one entry per chain, so the
222
+ * same address repeats — dedupe).
223
+ */
224
+ const getCaip10Addresses = (caip10s) => [...new Set(caip10s.map((account) => account.split(":")[2]).filter((address) => !!address))];
225
+ /**
226
+ * Shared shape of the Polkadot/Solana WalletConnect account streams: no-op
227
+ * unless the session carries the platform's namespace, then a cached
228
+ * observable that rebuilds the account list from the session on
229
+ * `session_update` / `accountsChanged`.
230
+ *
231
+ * AppKit's `getAccount(namespace).allAccounts` is always empty for namespaces
232
+ * without a native AppKit adapter — the WalletConnect session is the source of
233
+ * truth, hence the session-driven rebuild.
234
+ */
235
+ const getWalletConnectSessionAccounts$ = (options) => {
236
+ const { wallet, platform, namespace, cacheKey, buildAccounts } = options;
237
+ const provider = wallet.appKit.getProvider(namespace);
238
+ if (!wallet.platforms.includes(platform) || !provider?.session) return (0, rxjs.of)([]);
239
+ return require_types.getCachedObservable$(cacheKey, () => new rxjs.Observable((subscriber) => {
240
+ subscriber.next(buildAccounts(provider));
241
+ const reemit = () => subscriber.next(buildAccounts(provider));
242
+ provider.on("session_update", reemit);
243
+ provider.on("accountsChanged", reemit);
244
+ return () => {
245
+ provider.off("session_update", reemit);
246
+ provider.off("accountsChanged", reemit);
247
+ };
248
+ }).pipe((0, rxjs.shareReplay)({
249
+ refCount: true,
250
+ bufferSize: 1
251
+ })));
252
+ };
253
+ //#endregion
254
+ Object.defineProperty(exports, "createPlatformAccounts$", {
255
+ enumerable: true,
256
+ get: function() {
257
+ return createPlatformAccounts$;
258
+ }
259
+ });
260
+ Object.defineProperty(exports, "framesOf", {
261
+ enumerable: true,
262
+ get: function() {
263
+ return framesOf;
264
+ }
265
+ });
266
+ Object.defineProperty(exports, "getCaip10Addresses", {
267
+ enumerable: true,
268
+ get: function() {
269
+ return getCaip10Addresses;
270
+ }
271
+ });
272
+ Object.defineProperty(exports, "getSessionCaip10s", {
273
+ enumerable: true,
274
+ get: function() {
275
+ return getSessionCaip10s;
276
+ }
277
+ });
278
+ Object.defineProperty(exports, "getWalletAccountId", {
279
+ enumerable: true,
280
+ get: function() {
281
+ return getWalletAccountId;
282
+ }
283
+ });
284
+ Object.defineProperty(exports, "getWalletConnectSessionAccounts$", {
285
+ enumerable: true,
286
+ get: function() {
287
+ return getWalletConnectSessionAccounts$;
288
+ }
289
+ });
290
+ Object.defineProperty(exports, "isEthereumAddress", {
291
+ enumerable: true,
292
+ get: function() {
293
+ return isEthereumAddress;
294
+ }
295
+ });
296
+ Object.defineProperty(exports, "isSolanaAddress", {
297
+ enumerable: true,
298
+ get: function() {
299
+ return isSolanaAddress;
300
+ }
301
+ });
302
+ Object.defineProperty(exports, "isSs58Address", {
303
+ enumerable: true,
304
+ get: function() {
305
+ return isSs58Address;
306
+ }
307
+ });
308
+ Object.defineProperty(exports, "isValidAddress", {
309
+ enumerable: true,
310
+ get: function() {
311
+ return isValidAddress;
312
+ }
313
+ });
314
+ Object.defineProperty(exports, "parseWalletAccountId", {
315
+ enumerable: true,
316
+ get: function() {
317
+ return parseWalletAccountId;
318
+ }
319
+ });
320
+
321
+ //# sourceMappingURL=platformAccounts-BjIeRcFN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platformAccounts-BjIeRcFN.js","names":["keccak_256","base58","base58","blake2b","map","isWalletConnectWallet","Observable","Subscription","distinctUntilChanged","shareReplay","of","getCachedObservable$"],"sources":["../src/utils/isEthereumAddress.ts","../src/utils/isSolanaAddress.ts","../src/utils/isSs58Address.ts","../src/utils/isValidAddress.ts","../src/utils/WalletAccountId.ts","../src/api/platformAccounts.ts"],"sourcesContent":["import { keccak_256 } from \"@noble/hashes/sha3.js\";\n\nconst HEX_ADDRESS = /^0x[0-9a-fA-F]{40}$/;\nconst encoder = new TextEncoder();\n\n/**\n * Verifies the EIP-55 mixed-case checksum of an Ethereum address.\n * Dependency-free (keccak via @noble/hashes) so core stays decoupled from viem.\n */\nconst isChecksumValid = (address: string): boolean => {\n\tconst hex = address.slice(2);\n\tconst hash = keccak_256(encoder.encode(hex.toLowerCase()));\n\tfor (let i = 0; i < 40; i++) {\n\t\tconst char = hex.charAt(i);\n\t\tconst isLetter =\n\t\t\t(char >= \"a\" && char <= \"f\") || (char >= \"A\" && char <= \"F\");\n\t\tif (!isLetter) continue;\n\t\tconst byte = hash[i >> 1] ?? 0;\n\t\tconst nibble = i % 2 === 0 ? byte >> 4 : byte & 0x0f;\n\t\tconst isUpper = char <= \"F\";\n\t\tif (isUpper !== nibble >= 8) return false;\n\t}\n\treturn true;\n};\n\n/**\n * Returns true if `address` is a valid Ethereum address.\n *\n * Mirrors viem's `isAddress` (strict): the shape must be `0x` + 40 hex, and a\n * mixed-case address must pass the EIP-55 checksum. All-lowercase addresses are\n * accepted as non-checksummed.\n */\nexport const isEthereumAddress = (address: string): boolean => {\n\tif (!HEX_ADDRESS.test(address)) return false;\n\tif (address === address.toLowerCase()) return true;\n\treturn isChecksumValid(address);\n};\n","import { base58 } from \"@scure/base\";\n\n/**\n * Returns true if the value is a valid Solana address: a base58-encoded\n * 32-byte ed25519 public key.\n *\n * Solana addresses carry no checksum, so this is a pure base58 + length check.\n * Dependency-free (base58 via @scure/base) so core stays decoupled from\n * @solana/kit.\n */\nexport const isSolanaAddress = (address: string): boolean => {\n\tif (!address) return false;\n\ttry {\n\t\treturn base58.decode(address).length === 32;\n\t} catch {\n\t\treturn false;\n\t}\n};\n","import { blake2b } from \"@noble/hashes/blake2.js\";\nimport { base58 } from \"@scure/base\";\n\n// The \"SS58PRE\" prefix used in the SS58 checksum preimage.\nconst SS58PRE = new Uint8Array([0x53, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45]);\n\n/**\n * Returns true if `address` is a valid SS58-encoded 32-byte account id (the\n * only form Substrate wallets inject), verifying the blake2b-512 checksum.\n *\n * Dependency-free (base58 via @scure/base, blake2b via @noble/hashes) so core\n * stays decoupled from polkadot-api.\n */\nexport const isSs58Address = (address: string): boolean => {\n\tif (!address) return false;\n\n\tlet decoded: Uint8Array;\n\ttry {\n\t\tdecoded = base58.decode(address);\n\t} catch {\n\t\treturn false;\n\t}\n\n\t// First byte encodes the network prefix; the high bit is reserved/invalid.\n\tconst firstByte = decoded[0];\n\tif (firstByte === undefined || firstByte & 0b1000_0000) return false;\n\t// The 0b0100_0000 bit marks a 2-byte prefix.\n\tconst prefixLength = firstByte & 0b0100_0000 ? 2 : 1;\n\n\t// AccountId32 layout: prefix + 32-byte pubkey + 2-byte checksum.\n\tif (decoded.length !== prefixLength + 32 + 2) return false;\n\n\tconst body = decoded.subarray(0, decoded.length - 2);\n\tconst preimage = new Uint8Array(SS58PRE.length + body.length);\n\tpreimage.set(SS58PRE);\n\tpreimage.set(body, SS58PRE.length);\n\tconst hash = blake2b(preimage, { dkLen: 64 });\n\n\treturn (\n\t\tdecoded[decoded.length - 2] === hash[0] &&\n\t\tdecoded[decoded.length - 1] === hash[1]\n\t);\n};\n","import { isEthereumAddress } from \"./isEthereumAddress\";\nimport { isSolanaAddress } from \"./isSolanaAddress\";\nimport { isSs58Address } from \"./isSs58Address\";\n\nexport const isValidAddress = (address: string): boolean => {\n\tif (address.startsWith(\"0x\")) return isEthereumAddress(address);\n\t// SS58 (checksummed) and Solana (base58, no checksum) are disjoint: a\n\t// 32-byte Solana pubkey fails SS58 decoding, and an SS58 address decodes to\n\t// more than 32 bytes so it fails the Solana length check.\n\treturn isSs58Address(address) || isSolanaAddress(address);\n};\n","import { isValidAddress } from \"./isValidAddress\";\n\nexport type WalletAccountId = string;\n\nexport const getWalletAccountId = (\n\twalletId: string,\n\taddress: string,\n): WalletAccountId => {\n\tif (!walletId) throw new Error(\"Missing walletId\");\n\tif (!isValidAddress(address)) throw new Error(\"Invalid address\");\n\treturn `${walletId}::${address}`;\n};\n\nexport const parseWalletAccountId = (accountId: string) => {\n\tif (!accountId) throw new Error(\"Invalid walletAccountId\");\n\tconst [walletId, address] = accountId.split(\"::\");\n\tif (!walletId) throw new Error(\"Missing walletId\");\n\tif (!address || !isValidAddress(address)) throw new Error(\"Invalid address\");\n\treturn { walletId, address };\n};\n","import {\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tSubscription,\n\tshareReplay,\n} from \"rxjs\";\nimport { getCachedObservable$ } from \"../utils/getCachedObservable\";\nimport type { WalletId } from \"../utils/WalletId\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tWalletConnectProvider,\n\tWalletConnectWallet,\n\tWalletPlatform,\n} from \"./types\";\nimport { isWalletConnectWallet } from \"./types\";\n\nexport type LiveWalletConnectWallet = Exclude<\n\tWalletConnectWallet,\n\t{ isPlaceholder: true }\n>;\n\nexport type PlatformAccountsOptions<\n\tTWallet extends BaseWallet,\n\tTAccount extends BaseWalletAccount,\n> = {\n\t/** This platform's wallets plus the shared WalletConnect connector. */\n\twallets$: Observable<(TWallet | WalletConnectWallet)[]>;\n\t/** Account stream for one connected injected wallet. */\n\tgetInjectedAccounts$: (wallet: TWallet) => Observable<TAccount[]>;\n\t/** Account stream for the WalletConnect connector. */\n\tgetWalletConnectAccounts$: (\n\t\twallet: LiveWalletConnectWallet,\n\t) => Observable<TAccount[]>;\n\t/** Optional post-flatten transform (e.g. Polkadot's `accountTypes` filter). */\n\tmapAccounts?: (accounts: TAccount[]) => TAccount[];\n\t/**\n\t * Signature of the account fields that should trigger a re-emission.\n\t * Defaults to the account id; platforms add mutable fields (Ethereum\n\t * `chainId`, Solana `chains`).\n\t */\n\taccountChangeKey?: (account: TAccount) => string;\n};\n\n/** The account list plus the connected wallets whose stream has answered, an empty list included. */\nexport type PlatformAccountsFrame<TAccount> = {\n\taccounts: TAccount[];\n\tanswered: WalletId[];\n};\n\nexport type PlatformAccounts$<TAccount> = Observable<TAccount[]> & {\n\tframes$: Observable<PlatformAccountsFrame<TAccount>>;\n};\n\nconst isPlatformAccounts$ = <TAccount extends BaseWalletAccount>(\n\taccounts$: Observable<TAccount[]>,\n): accounts$ is PlatformAccounts$<TAccount> => \"frames$\" in accounts$;\n\n/** A plugin not built on `createPlatformAccounts$` reports no answered wallet. */\nexport const framesOf = <TAccount extends BaseWalletAccount>(\n\taccounts$: Observable<TAccount[]>,\n): Observable<PlatformAccountsFrame<TAccount>> =>\n\tisPlatformAccounts$(accounts$)\n\t\t? accounts$.frames$\n\t\t: accounts$.pipe(map((accounts) => ({ accounts, answered: [] })));\n\nconst idsEqual = (a: WalletId[], b: WalletId[]) =>\n\ta.length === b.length && a.every((id, i) => id === b[i]);\n\ntype WalletConnection<TAccount> = {\n\tkey: string;\n\taccounts: TAccount[];\n\tanswered: boolean;\n\tcompleted: boolean;\n\tsubscription: Subscription;\n};\n\nconst sessionKey = (wallet: WalletConnectWallet): string =>\n\t`${wallet.id}|${wallet.platforms.join(\",\")}`;\n\nconst connectionKey = (wallet: BaseWallet | WalletConnectWallet): string =>\n\tisWalletConnectWallet(wallet) ? sessionKey(wallet) : wallet.id;\n\n/** Shared engine behind every platform's `getAccounts$`. */\nexport const createPlatformAccounts$ = <\n\tTWallet extends BaseWallet,\n\tTAccount extends BaseWalletAccount,\n>({\n\twallets$,\n\tgetInjectedAccounts$,\n\tgetWalletConnectAccounts$,\n\tmapAccounts,\n\taccountChangeKey = (account) => account.id,\n}: PlatformAccountsOptions<TWallet, TAccount>): PlatformAccounts$<TAccount> => {\n\ttype Frame = PlatformAccountsFrame<TAccount>;\n\tconst nameAndChangeKey = (account: TAccount) =>\n\t\t`${account.name ?? \"\"}|${accountChangeKey(account)}`;\n\tconst accountsListEqual = (a: TAccount[], b: TAccount[]) =>\n\t\ta.length === b.length &&\n\t\ta.every((account, i) => {\n\t\t\tconst other = b[i];\n\t\t\treturn !!other && nameAndChangeKey(account) === nameAndChangeKey(other);\n\t\t});\n\tconst accountsOf = (wallet: TWallet | LiveWalletConnectWallet) =>\n\t\tisWalletConnectWallet(wallet)\n\t\t\t? getWalletConnectAccounts$(wallet)\n\t\t\t: getInjectedAccounts$(wallet);\n\n\tconst frames$ = new Observable<Frame>((subscriber) => {\n\t\tconst connections = new Map<WalletId, WalletConnection<TAccount>>();\n\t\tlet connectedIds: WalletId[] = [];\n\t\tlet walletsCompleted = false;\n\t\tlet emitted = false;\n\n\t\tconst awaitingFirstAnswers = () =>\n\t\t\t!emitted &&\n\t\t\t[...connections.values()].some((connection) => !connection.answered);\n\n\t\tconst accountsListed = () =>\n\t\t\tconnectedIds.flatMap((id) => connections.get(id)?.accounts ?? []);\n\t\tconst walletsAnswered = () =>\n\t\t\tconnectedIds.filter((id) => connections.get(id)?.answered);\n\n\t\tconst emit = () => {\n\t\t\tif (awaitingFirstAnswers()) return;\n\t\t\temitted = true;\n\t\t\tsubscriber.next({\n\t\t\t\taccounts: accountsListed(),\n\t\t\t\tanswered: walletsAnswered(),\n\t\t\t});\n\t\t};\n\n\t\tconst completeIfDone = () => {\n\t\t\tif (\n\t\t\t\twalletsCompleted &&\n\t\t\t\t[...connections.values()].every((connection) => connection.completed)\n\t\t\t)\n\t\t\t\tsubscriber.complete();\n\t\t};\n\n\t\tconst reconcile = (wallets: (TWallet | WalletConnectWallet)[]) => {\n\t\t\tconst connected = wallets.filter(\n\t\t\t\t(wallet): wallet is TWallet | LiveWalletConnectWallet =>\n\t\t\t\t\twallet.isConnected && !wallet.isPlaceholder,\n\t\t\t);\n\t\t\tconst keys = new Map(\n\t\t\t\tconnected.map((w) => [w.id, connectionKey(w)] as const),\n\t\t\t);\n\t\t\tfor (const [id, connection] of connections) {\n\t\t\t\tif (keys.get(id) === connection.key) continue;\n\t\t\t\tconnection.subscription.unsubscribe();\n\t\t\t\tconnections.delete(id);\n\t\t\t}\n\t\t\tconnectedIds = connected.map((wallet) => wallet.id);\n\t\t\tconst opened = connected\n\t\t\t\t.filter((wallet) => !connections.has(wallet.id))\n\t\t\t\t.map((wallet) => {\n\t\t\t\t\tconst connection: WalletConnection<TAccount> = {\n\t\t\t\t\t\tkey: connectionKey(wallet),\n\t\t\t\t\t\taccounts: [],\n\t\t\t\t\t\tanswered: false,\n\t\t\t\t\t\tcompleted: false,\n\t\t\t\t\t\tsubscription: new Subscription(),\n\t\t\t\t\t};\n\t\t\t\t\tconnections.set(wallet.id, connection);\n\t\t\t\t\treturn { wallet, connection };\n\t\t\t\t});\n\t\t\tfor (const { wallet, connection } of opened) {\n\t\t\t\tconnection.subscription.add(\n\t\t\t\t\taccountsOf(wallet).subscribe({\n\t\t\t\t\t\tnext: (accounts) => {\n\t\t\t\t\t\t\tconnection.accounts = accounts;\n\t\t\t\t\t\t\tconnection.answered = true;\n\t\t\t\t\t\t\temit();\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror: (error) => subscriber.error(error),\n\t\t\t\t\t\tcomplete: () => {\n\t\t\t\t\t\t\tconnection.completed = true;\n\t\t\t\t\t\t\tcompleteIfDone();\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\temit();\n\t\t};\n\n\t\tconst sub = wallets$.subscribe({\n\t\t\tnext: reconcile,\n\t\t\terror: (error) => subscriber.error(error),\n\t\t\tcomplete: () => {\n\t\t\t\twalletsCompleted = true;\n\t\t\t\tcompleteIfDone();\n\t\t\t},\n\t\t});\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t\tfor (const connection of connections.values())\n\t\t\t\tconnection.subscription.unsubscribe();\n\t\t};\n\t}).pipe(\n\t\tmap((frame) =>\n\t\t\tmapAccounts ? { ...frame, accounts: mapAccounts(frame.accounts) } : frame,\n\t\t),\n\t\tdistinctUntilChanged(\n\t\t\t(a, b) =>\n\t\t\t\taccountsListEqual(a.accounts, b.accounts) &&\n\t\t\t\tidsEqual(a.answered, b.answered),\n\t\t),\n\t\tshareReplay({ refCount: true, bufferSize: 1 }),\n\t);\n\tconst accounts$ = frames$.pipe(\n\t\tmap((frame) => frame.accounts),\n\t\tdistinctUntilChanged(accountsListEqual),\n\t\tshareReplay({ refCount: true, bufferSize: 1 }),\n\t);\n\treturn Object.assign(accounts$, { frames$ });\n};\n\n/**\n * CAIP-10 account strings (\"<namespace>:<chainRef>:<address>\") the live\n * WalletConnect session carries for a namespace.\n */\nexport const getSessionCaip10s = (\n\tsession: NonNullable<WalletConnectProvider[\"session\"]>,\n\tnamespace: string,\n): string[] =>\n\tObject.values(session.namespaces)\n\t\t.flatMap((ns) => ns.accounts ?? [])\n\t\t.filter((account) => account.startsWith(`${namespace}:`));\n\n/**\n * Unique addresses from CAIP-10 account strings (one entry per chain, so the\n * same address repeats — dedupe).\n */\nexport const getCaip10Addresses = (caip10s: string[]): string[] => [\n\t...new Set(\n\t\tcaip10s\n\t\t\t.map((account) => account.split(\":\")[2])\n\t\t\t.filter((address): address is string => !!address),\n\t),\n];\n\n/**\n * Shared shape of the Polkadot/Solana WalletConnect account streams: no-op\n * unless the session carries the platform's namespace, then a cached\n * observable that rebuilds the account list from the session on\n * `session_update` / `accountsChanged`.\n *\n * AppKit's `getAccount(namespace).allAccounts` is always empty for namespaces\n * without a native AppKit adapter — the WalletConnect session is the source of\n * truth, hence the session-driven rebuild.\n */\nexport const getWalletConnectSessionAccounts$ = <\n\tTAccount extends BaseWalletAccount,\n>(options: {\n\twallet: LiveWalletConnectWallet;\n\tplatform: WalletPlatform;\n\t/** WalletConnect namespace, e.g. \"polkadot\" | \"solana\" | \"eip155\". */\n\tnamespace: string;\n\t/** Cache key for {@link getCachedObservable$} — must be reconnect-safe. */\n\tcacheKey: string;\n\t/** Build the account list from the live session. */\n\tbuildAccounts: (provider: WalletConnectProvider) => TAccount[];\n}): Observable<TAccount[]> => {\n\tconst { wallet, platform, namespace, cacheKey, buildAccounts } = options;\n\tconst provider = wallet.appKit.getProvider(namespace);\n\n\tif (!wallet.platforms.includes(platform) || !provider?.session) return of([]);\n\n\treturn getCachedObservable$(cacheKey, () =>\n\t\tnew Observable<TAccount[]>((subscriber) => {\n\t\t\tsubscriber.next(buildAccounts(provider));\n\n\t\t\t// Re-derive when the WalletConnect session's accounts change, mirroring\n\t\t\t// the injected paths' change subscriptions.\n\t\t\tconst reemit = () => subscriber.next(buildAccounts(provider));\n\t\t\tprovider.on(\"session_update\", reemit);\n\t\t\tprovider.on(\"accountsChanged\", reemit);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"session_update\", reemit);\n\t\t\t\tprovider.off(\"accountsChanged\", reemit);\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n"],"mappings":"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"}
@@ -0,0 +1,256 @@
1
+ import { _ as getCachedObservable$, n as isWalletConnectWallet } from "./types-Yor672md.mjs";
2
+ import { keccak_256 } from "@noble/hashes/sha3.js";
3
+ import { base58 } from "@scure/base";
4
+ import { blake2b } from "@noble/hashes/blake2.js";
5
+ import { Observable, Subscription, distinctUntilChanged, map, of, shareReplay } from "rxjs";
6
+ //#region src/utils/isEthereumAddress.ts
7
+ const HEX_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
8
+ const encoder = new TextEncoder();
9
+ /**
10
+ * Verifies the EIP-55 mixed-case checksum of an Ethereum address.
11
+ * Dependency-free (keccak via @noble/hashes) so core stays decoupled from viem.
12
+ */
13
+ const isChecksumValid = (address) => {
14
+ const hex = address.slice(2);
15
+ const hash = keccak_256(encoder.encode(hex.toLowerCase()));
16
+ for (let i = 0; i < 40; i++) {
17
+ const char = hex.charAt(i);
18
+ if (!(char >= "a" && char <= "f" || char >= "A" && char <= "F")) continue;
19
+ const byte = hash[i >> 1] ?? 0;
20
+ const nibble = i % 2 === 0 ? byte >> 4 : byte & 15;
21
+ if (char <= "F" !== nibble >= 8) return false;
22
+ }
23
+ return true;
24
+ };
25
+ /**
26
+ * Returns true if `address` is a valid Ethereum address.
27
+ *
28
+ * Mirrors viem's `isAddress` (strict): the shape must be `0x` + 40 hex, and a
29
+ * mixed-case address must pass the EIP-55 checksum. All-lowercase addresses are
30
+ * accepted as non-checksummed.
31
+ */
32
+ const isEthereumAddress = (address) => {
33
+ if (!HEX_ADDRESS.test(address)) return false;
34
+ if (address === address.toLowerCase()) return true;
35
+ return isChecksumValid(address);
36
+ };
37
+ //#endregion
38
+ //#region src/utils/isSolanaAddress.ts
39
+ /**
40
+ * Returns true if the value is a valid Solana address: a base58-encoded
41
+ * 32-byte ed25519 public key.
42
+ *
43
+ * Solana addresses carry no checksum, so this is a pure base58 + length check.
44
+ * Dependency-free (base58 via @scure/base) so core stays decoupled from
45
+ * @solana/kit.
46
+ */
47
+ const isSolanaAddress = (address) => {
48
+ if (!address) return false;
49
+ try {
50
+ return base58.decode(address).length === 32;
51
+ } catch {
52
+ return false;
53
+ }
54
+ };
55
+ //#endregion
56
+ //#region src/utils/isSs58Address.ts
57
+ const SS58PRE = new Uint8Array([
58
+ 83,
59
+ 83,
60
+ 53,
61
+ 56,
62
+ 80,
63
+ 82,
64
+ 69
65
+ ]);
66
+ /**
67
+ * Returns true if `address` is a valid SS58-encoded 32-byte account id (the
68
+ * only form Substrate wallets inject), verifying the blake2b-512 checksum.
69
+ *
70
+ * Dependency-free (base58 via @scure/base, blake2b via @noble/hashes) so core
71
+ * stays decoupled from polkadot-api.
72
+ */
73
+ const isSs58Address = (address) => {
74
+ if (!address) return false;
75
+ let decoded;
76
+ try {
77
+ decoded = base58.decode(address);
78
+ } catch {
79
+ return false;
80
+ }
81
+ const firstByte = decoded[0];
82
+ if (firstByte === void 0 || firstByte & 128) return false;
83
+ const prefixLength = firstByte & 64 ? 2 : 1;
84
+ if (decoded.length !== prefixLength + 32 + 2) return false;
85
+ const body = decoded.subarray(0, decoded.length - 2);
86
+ const preimage = new Uint8Array(SS58PRE.length + body.length);
87
+ preimage.set(SS58PRE);
88
+ preimage.set(body, SS58PRE.length);
89
+ const hash = blake2b(preimage, { dkLen: 64 });
90
+ return decoded[decoded.length - 2] === hash[0] && decoded[decoded.length - 1] === hash[1];
91
+ };
92
+ //#endregion
93
+ //#region src/utils/isValidAddress.ts
94
+ const isValidAddress = (address) => {
95
+ if (address.startsWith("0x")) return isEthereumAddress(address);
96
+ return isSs58Address(address) || isSolanaAddress(address);
97
+ };
98
+ //#endregion
99
+ //#region src/utils/WalletAccountId.ts
100
+ const getWalletAccountId = (walletId, address) => {
101
+ if (!walletId) throw new Error("Missing walletId");
102
+ if (!isValidAddress(address)) throw new Error("Invalid address");
103
+ return `${walletId}::${address}`;
104
+ };
105
+ const parseWalletAccountId = (accountId) => {
106
+ if (!accountId) throw new Error("Invalid walletAccountId");
107
+ const [walletId, address] = accountId.split("::");
108
+ if (!walletId) throw new Error("Missing walletId");
109
+ if (!address || !isValidAddress(address)) throw new Error("Invalid address");
110
+ return {
111
+ walletId,
112
+ address
113
+ };
114
+ };
115
+ //#endregion
116
+ //#region src/api/platformAccounts.ts
117
+ const isPlatformAccounts$ = (accounts$) => "frames$" in accounts$;
118
+ /** A plugin not built on `createPlatformAccounts$` reports no answered wallet. */
119
+ const framesOf = (accounts$) => isPlatformAccounts$(accounts$) ? accounts$.frames$ : accounts$.pipe(map((accounts) => ({
120
+ accounts,
121
+ answered: []
122
+ })));
123
+ const idsEqual = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
124
+ const sessionKey = (wallet) => `${wallet.id}|${wallet.platforms.join(",")}`;
125
+ const connectionKey = (wallet) => isWalletConnectWallet(wallet) ? sessionKey(wallet) : wallet.id;
126
+ /** Shared engine behind every platform's `getAccounts$`. */
127
+ const createPlatformAccounts$ = ({ wallets$, getInjectedAccounts$, getWalletConnectAccounts$, mapAccounts, accountChangeKey = (account) => account.id }) => {
128
+ const nameAndChangeKey = (account) => `${account.name ?? ""}|${accountChangeKey(account)}`;
129
+ const accountsListEqual = (a, b) => a.length === b.length && a.every((account, i) => {
130
+ const other = b[i];
131
+ return !!other && nameAndChangeKey(account) === nameAndChangeKey(other);
132
+ });
133
+ const accountsOf = (wallet) => isWalletConnectWallet(wallet) ? getWalletConnectAccounts$(wallet) : getInjectedAccounts$(wallet);
134
+ const frames$ = new Observable((subscriber) => {
135
+ const connections = /* @__PURE__ */ new Map();
136
+ let connectedIds = [];
137
+ let walletsCompleted = false;
138
+ let emitted = false;
139
+ const awaitingFirstAnswers = () => !emitted && [...connections.values()].some((connection) => !connection.answered);
140
+ const accountsListed = () => connectedIds.flatMap((id) => connections.get(id)?.accounts ?? []);
141
+ const walletsAnswered = () => connectedIds.filter((id) => connections.get(id)?.answered);
142
+ const emit = () => {
143
+ if (awaitingFirstAnswers()) return;
144
+ emitted = true;
145
+ subscriber.next({
146
+ accounts: accountsListed(),
147
+ answered: walletsAnswered()
148
+ });
149
+ };
150
+ const completeIfDone = () => {
151
+ if (walletsCompleted && [...connections.values()].every((connection) => connection.completed)) subscriber.complete();
152
+ };
153
+ const reconcile = (wallets) => {
154
+ const connected = wallets.filter((wallet) => wallet.isConnected && !wallet.isPlaceholder);
155
+ const keys = new Map(connected.map((w) => [w.id, connectionKey(w)]));
156
+ for (const [id, connection] of connections) {
157
+ if (keys.get(id) === connection.key) continue;
158
+ connection.subscription.unsubscribe();
159
+ connections.delete(id);
160
+ }
161
+ connectedIds = connected.map((wallet) => wallet.id);
162
+ const opened = connected.filter((wallet) => !connections.has(wallet.id)).map((wallet) => {
163
+ const connection = {
164
+ key: connectionKey(wallet),
165
+ accounts: [],
166
+ answered: false,
167
+ completed: false,
168
+ subscription: new Subscription()
169
+ };
170
+ connections.set(wallet.id, connection);
171
+ return {
172
+ wallet,
173
+ connection
174
+ };
175
+ });
176
+ for (const { wallet, connection } of opened) connection.subscription.add(accountsOf(wallet).subscribe({
177
+ next: (accounts) => {
178
+ connection.accounts = accounts;
179
+ connection.answered = true;
180
+ emit();
181
+ },
182
+ error: (error) => subscriber.error(error),
183
+ complete: () => {
184
+ connection.completed = true;
185
+ completeIfDone();
186
+ }
187
+ }));
188
+ emit();
189
+ };
190
+ const sub = wallets$.subscribe({
191
+ next: reconcile,
192
+ error: (error) => subscriber.error(error),
193
+ complete: () => {
194
+ walletsCompleted = true;
195
+ completeIfDone();
196
+ }
197
+ });
198
+ return () => {
199
+ sub.unsubscribe();
200
+ for (const connection of connections.values()) connection.subscription.unsubscribe();
201
+ };
202
+ }).pipe(map((frame) => mapAccounts ? {
203
+ ...frame,
204
+ accounts: mapAccounts(frame.accounts)
205
+ } : frame), distinctUntilChanged((a, b) => accountsListEqual(a.accounts, b.accounts) && idsEqual(a.answered, b.answered)), shareReplay({
206
+ refCount: true,
207
+ bufferSize: 1
208
+ }));
209
+ const accounts$ = frames$.pipe(map((frame) => frame.accounts), distinctUntilChanged(accountsListEqual), shareReplay({
210
+ refCount: true,
211
+ bufferSize: 1
212
+ }));
213
+ return Object.assign(accounts$, { frames$ });
214
+ };
215
+ /**
216
+ * CAIP-10 account strings ("<namespace>:<chainRef>:<address>") the live
217
+ * WalletConnect session carries for a namespace.
218
+ */
219
+ const getSessionCaip10s = (session, namespace) => Object.values(session.namespaces).flatMap((ns) => ns.accounts ?? []).filter((account) => account.startsWith(`${namespace}:`));
220
+ /**
221
+ * Unique addresses from CAIP-10 account strings (one entry per chain, so the
222
+ * same address repeats — dedupe).
223
+ */
224
+ const getCaip10Addresses = (caip10s) => [...new Set(caip10s.map((account) => account.split(":")[2]).filter((address) => !!address))];
225
+ /**
226
+ * Shared shape of the Polkadot/Solana WalletConnect account streams: no-op
227
+ * unless the session carries the platform's namespace, then a cached
228
+ * observable that rebuilds the account list from the session on
229
+ * `session_update` / `accountsChanged`.
230
+ *
231
+ * AppKit's `getAccount(namespace).allAccounts` is always empty for namespaces
232
+ * without a native AppKit adapter — the WalletConnect session is the source of
233
+ * truth, hence the session-driven rebuild.
234
+ */
235
+ const getWalletConnectSessionAccounts$ = (options) => {
236
+ const { wallet, platform, namespace, cacheKey, buildAccounts } = options;
237
+ const provider = wallet.appKit.getProvider(namespace);
238
+ if (!wallet.platforms.includes(platform) || !provider?.session) return of([]);
239
+ return getCachedObservable$(cacheKey, () => new Observable((subscriber) => {
240
+ subscriber.next(buildAccounts(provider));
241
+ const reemit = () => subscriber.next(buildAccounts(provider));
242
+ provider.on("session_update", reemit);
243
+ provider.on("accountsChanged", reemit);
244
+ return () => {
245
+ provider.off("session_update", reemit);
246
+ provider.off("accountsChanged", reemit);
247
+ };
248
+ }).pipe(shareReplay({
249
+ refCount: true,
250
+ bufferSize: 1
251
+ })));
252
+ };
253
+ //#endregion
254
+ export { getWalletConnectSessionAccounts$ as a, isValidAddress as c, isEthereumAddress as d, getSessionCaip10s as i, isSs58Address as l, framesOf as n, getWalletAccountId as o, getCaip10Addresses as r, parseWalletAccountId as s, createPlatformAccounts$ as t, isSolanaAddress as u };
255
+
256
+ //# sourceMappingURL=platformAccounts-yyRUrnel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platformAccounts-yyRUrnel.mjs","names":[],"sources":["../src/utils/isEthereumAddress.ts","../src/utils/isSolanaAddress.ts","../src/utils/isSs58Address.ts","../src/utils/isValidAddress.ts","../src/utils/WalletAccountId.ts","../src/api/platformAccounts.ts"],"sourcesContent":["import { keccak_256 } from \"@noble/hashes/sha3.js\";\n\nconst HEX_ADDRESS = /^0x[0-9a-fA-F]{40}$/;\nconst encoder = new TextEncoder();\n\n/**\n * Verifies the EIP-55 mixed-case checksum of an Ethereum address.\n * Dependency-free (keccak via @noble/hashes) so core stays decoupled from viem.\n */\nconst isChecksumValid = (address: string): boolean => {\n\tconst hex = address.slice(2);\n\tconst hash = keccak_256(encoder.encode(hex.toLowerCase()));\n\tfor (let i = 0; i < 40; i++) {\n\t\tconst char = hex.charAt(i);\n\t\tconst isLetter =\n\t\t\t(char >= \"a\" && char <= \"f\") || (char >= \"A\" && char <= \"F\");\n\t\tif (!isLetter) continue;\n\t\tconst byte = hash[i >> 1] ?? 0;\n\t\tconst nibble = i % 2 === 0 ? byte >> 4 : byte & 0x0f;\n\t\tconst isUpper = char <= \"F\";\n\t\tif (isUpper !== nibble >= 8) return false;\n\t}\n\treturn true;\n};\n\n/**\n * Returns true if `address` is a valid Ethereum address.\n *\n * Mirrors viem's `isAddress` (strict): the shape must be `0x` + 40 hex, and a\n * mixed-case address must pass the EIP-55 checksum. All-lowercase addresses are\n * accepted as non-checksummed.\n */\nexport const isEthereumAddress = (address: string): boolean => {\n\tif (!HEX_ADDRESS.test(address)) return false;\n\tif (address === address.toLowerCase()) return true;\n\treturn isChecksumValid(address);\n};\n","import { base58 } from \"@scure/base\";\n\n/**\n * Returns true if the value is a valid Solana address: a base58-encoded\n * 32-byte ed25519 public key.\n *\n * Solana addresses carry no checksum, so this is a pure base58 + length check.\n * Dependency-free (base58 via @scure/base) so core stays decoupled from\n * @solana/kit.\n */\nexport const isSolanaAddress = (address: string): boolean => {\n\tif (!address) return false;\n\ttry {\n\t\treturn base58.decode(address).length === 32;\n\t} catch {\n\t\treturn false;\n\t}\n};\n","import { blake2b } from \"@noble/hashes/blake2.js\";\nimport { base58 } from \"@scure/base\";\n\n// The \"SS58PRE\" prefix used in the SS58 checksum preimage.\nconst SS58PRE = new Uint8Array([0x53, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45]);\n\n/**\n * Returns true if `address` is a valid SS58-encoded 32-byte account id (the\n * only form Substrate wallets inject), verifying the blake2b-512 checksum.\n *\n * Dependency-free (base58 via @scure/base, blake2b via @noble/hashes) so core\n * stays decoupled from polkadot-api.\n */\nexport const isSs58Address = (address: string): boolean => {\n\tif (!address) return false;\n\n\tlet decoded: Uint8Array;\n\ttry {\n\t\tdecoded = base58.decode(address);\n\t} catch {\n\t\treturn false;\n\t}\n\n\t// First byte encodes the network prefix; the high bit is reserved/invalid.\n\tconst firstByte = decoded[0];\n\tif (firstByte === undefined || firstByte & 0b1000_0000) return false;\n\t// The 0b0100_0000 bit marks a 2-byte prefix.\n\tconst prefixLength = firstByte & 0b0100_0000 ? 2 : 1;\n\n\t// AccountId32 layout: prefix + 32-byte pubkey + 2-byte checksum.\n\tif (decoded.length !== prefixLength + 32 + 2) return false;\n\n\tconst body = decoded.subarray(0, decoded.length - 2);\n\tconst preimage = new Uint8Array(SS58PRE.length + body.length);\n\tpreimage.set(SS58PRE);\n\tpreimage.set(body, SS58PRE.length);\n\tconst hash = blake2b(preimage, { dkLen: 64 });\n\n\treturn (\n\t\tdecoded[decoded.length - 2] === hash[0] &&\n\t\tdecoded[decoded.length - 1] === hash[1]\n\t);\n};\n","import { isEthereumAddress } from \"./isEthereumAddress\";\nimport { isSolanaAddress } from \"./isSolanaAddress\";\nimport { isSs58Address } from \"./isSs58Address\";\n\nexport const isValidAddress = (address: string): boolean => {\n\tif (address.startsWith(\"0x\")) return isEthereumAddress(address);\n\t// SS58 (checksummed) and Solana (base58, no checksum) are disjoint: a\n\t// 32-byte Solana pubkey fails SS58 decoding, and an SS58 address decodes to\n\t// more than 32 bytes so it fails the Solana length check.\n\treturn isSs58Address(address) || isSolanaAddress(address);\n};\n","import { isValidAddress } from \"./isValidAddress\";\n\nexport type WalletAccountId = string;\n\nexport const getWalletAccountId = (\n\twalletId: string,\n\taddress: string,\n): WalletAccountId => {\n\tif (!walletId) throw new Error(\"Missing walletId\");\n\tif (!isValidAddress(address)) throw new Error(\"Invalid address\");\n\treturn `${walletId}::${address}`;\n};\n\nexport const parseWalletAccountId = (accountId: string) => {\n\tif (!accountId) throw new Error(\"Invalid walletAccountId\");\n\tconst [walletId, address] = accountId.split(\"::\");\n\tif (!walletId) throw new Error(\"Missing walletId\");\n\tif (!address || !isValidAddress(address)) throw new Error(\"Invalid address\");\n\treturn { walletId, address };\n};\n","import {\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tSubscription,\n\tshareReplay,\n} from \"rxjs\";\nimport { getCachedObservable$ } from \"../utils/getCachedObservable\";\nimport type { WalletId } from \"../utils/WalletId\";\nimport type {\n\tBaseWallet,\n\tBaseWalletAccount,\n\tWalletConnectProvider,\n\tWalletConnectWallet,\n\tWalletPlatform,\n} from \"./types\";\nimport { isWalletConnectWallet } from \"./types\";\n\nexport type LiveWalletConnectWallet = Exclude<\n\tWalletConnectWallet,\n\t{ isPlaceholder: true }\n>;\n\nexport type PlatformAccountsOptions<\n\tTWallet extends BaseWallet,\n\tTAccount extends BaseWalletAccount,\n> = {\n\t/** This platform's wallets plus the shared WalletConnect connector. */\n\twallets$: Observable<(TWallet | WalletConnectWallet)[]>;\n\t/** Account stream for one connected injected wallet. */\n\tgetInjectedAccounts$: (wallet: TWallet) => Observable<TAccount[]>;\n\t/** Account stream for the WalletConnect connector. */\n\tgetWalletConnectAccounts$: (\n\t\twallet: LiveWalletConnectWallet,\n\t) => Observable<TAccount[]>;\n\t/** Optional post-flatten transform (e.g. Polkadot's `accountTypes` filter). */\n\tmapAccounts?: (accounts: TAccount[]) => TAccount[];\n\t/**\n\t * Signature of the account fields that should trigger a re-emission.\n\t * Defaults to the account id; platforms add mutable fields (Ethereum\n\t * `chainId`, Solana `chains`).\n\t */\n\taccountChangeKey?: (account: TAccount) => string;\n};\n\n/** The account list plus the connected wallets whose stream has answered, an empty list included. */\nexport type PlatformAccountsFrame<TAccount> = {\n\taccounts: TAccount[];\n\tanswered: WalletId[];\n};\n\nexport type PlatformAccounts$<TAccount> = Observable<TAccount[]> & {\n\tframes$: Observable<PlatformAccountsFrame<TAccount>>;\n};\n\nconst isPlatformAccounts$ = <TAccount extends BaseWalletAccount>(\n\taccounts$: Observable<TAccount[]>,\n): accounts$ is PlatformAccounts$<TAccount> => \"frames$\" in accounts$;\n\n/** A plugin not built on `createPlatformAccounts$` reports no answered wallet. */\nexport const framesOf = <TAccount extends BaseWalletAccount>(\n\taccounts$: Observable<TAccount[]>,\n): Observable<PlatformAccountsFrame<TAccount>> =>\n\tisPlatformAccounts$(accounts$)\n\t\t? accounts$.frames$\n\t\t: accounts$.pipe(map((accounts) => ({ accounts, answered: [] })));\n\nconst idsEqual = (a: WalletId[], b: WalletId[]) =>\n\ta.length === b.length && a.every((id, i) => id === b[i]);\n\ntype WalletConnection<TAccount> = {\n\tkey: string;\n\taccounts: TAccount[];\n\tanswered: boolean;\n\tcompleted: boolean;\n\tsubscription: Subscription;\n};\n\nconst sessionKey = (wallet: WalletConnectWallet): string =>\n\t`${wallet.id}|${wallet.platforms.join(\",\")}`;\n\nconst connectionKey = (wallet: BaseWallet | WalletConnectWallet): string =>\n\tisWalletConnectWallet(wallet) ? sessionKey(wallet) : wallet.id;\n\n/** Shared engine behind every platform's `getAccounts$`. */\nexport const createPlatformAccounts$ = <\n\tTWallet extends BaseWallet,\n\tTAccount extends BaseWalletAccount,\n>({\n\twallets$,\n\tgetInjectedAccounts$,\n\tgetWalletConnectAccounts$,\n\tmapAccounts,\n\taccountChangeKey = (account) => account.id,\n}: PlatformAccountsOptions<TWallet, TAccount>): PlatformAccounts$<TAccount> => {\n\ttype Frame = PlatformAccountsFrame<TAccount>;\n\tconst nameAndChangeKey = (account: TAccount) =>\n\t\t`${account.name ?? \"\"}|${accountChangeKey(account)}`;\n\tconst accountsListEqual = (a: TAccount[], b: TAccount[]) =>\n\t\ta.length === b.length &&\n\t\ta.every((account, i) => {\n\t\t\tconst other = b[i];\n\t\t\treturn !!other && nameAndChangeKey(account) === nameAndChangeKey(other);\n\t\t});\n\tconst accountsOf = (wallet: TWallet | LiveWalletConnectWallet) =>\n\t\tisWalletConnectWallet(wallet)\n\t\t\t? getWalletConnectAccounts$(wallet)\n\t\t\t: getInjectedAccounts$(wallet);\n\n\tconst frames$ = new Observable<Frame>((subscriber) => {\n\t\tconst connections = new Map<WalletId, WalletConnection<TAccount>>();\n\t\tlet connectedIds: WalletId[] = [];\n\t\tlet walletsCompleted = false;\n\t\tlet emitted = false;\n\n\t\tconst awaitingFirstAnswers = () =>\n\t\t\t!emitted &&\n\t\t\t[...connections.values()].some((connection) => !connection.answered);\n\n\t\tconst accountsListed = () =>\n\t\t\tconnectedIds.flatMap((id) => connections.get(id)?.accounts ?? []);\n\t\tconst walletsAnswered = () =>\n\t\t\tconnectedIds.filter((id) => connections.get(id)?.answered);\n\n\t\tconst emit = () => {\n\t\t\tif (awaitingFirstAnswers()) return;\n\t\t\temitted = true;\n\t\t\tsubscriber.next({\n\t\t\t\taccounts: accountsListed(),\n\t\t\t\tanswered: walletsAnswered(),\n\t\t\t});\n\t\t};\n\n\t\tconst completeIfDone = () => {\n\t\t\tif (\n\t\t\t\twalletsCompleted &&\n\t\t\t\t[...connections.values()].every((connection) => connection.completed)\n\t\t\t)\n\t\t\t\tsubscriber.complete();\n\t\t};\n\n\t\tconst reconcile = (wallets: (TWallet | WalletConnectWallet)[]) => {\n\t\t\tconst connected = wallets.filter(\n\t\t\t\t(wallet): wallet is TWallet | LiveWalletConnectWallet =>\n\t\t\t\t\twallet.isConnected && !wallet.isPlaceholder,\n\t\t\t);\n\t\t\tconst keys = new Map(\n\t\t\t\tconnected.map((w) => [w.id, connectionKey(w)] as const),\n\t\t\t);\n\t\t\tfor (const [id, connection] of connections) {\n\t\t\t\tif (keys.get(id) === connection.key) continue;\n\t\t\t\tconnection.subscription.unsubscribe();\n\t\t\t\tconnections.delete(id);\n\t\t\t}\n\t\t\tconnectedIds = connected.map((wallet) => wallet.id);\n\t\t\tconst opened = connected\n\t\t\t\t.filter((wallet) => !connections.has(wallet.id))\n\t\t\t\t.map((wallet) => {\n\t\t\t\t\tconst connection: WalletConnection<TAccount> = {\n\t\t\t\t\t\tkey: connectionKey(wallet),\n\t\t\t\t\t\taccounts: [],\n\t\t\t\t\t\tanswered: false,\n\t\t\t\t\t\tcompleted: false,\n\t\t\t\t\t\tsubscription: new Subscription(),\n\t\t\t\t\t};\n\t\t\t\t\tconnections.set(wallet.id, connection);\n\t\t\t\t\treturn { wallet, connection };\n\t\t\t\t});\n\t\t\tfor (const { wallet, connection } of opened) {\n\t\t\t\tconnection.subscription.add(\n\t\t\t\t\taccountsOf(wallet).subscribe({\n\t\t\t\t\t\tnext: (accounts) => {\n\t\t\t\t\t\t\tconnection.accounts = accounts;\n\t\t\t\t\t\t\tconnection.answered = true;\n\t\t\t\t\t\t\temit();\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror: (error) => subscriber.error(error),\n\t\t\t\t\t\tcomplete: () => {\n\t\t\t\t\t\t\tconnection.completed = true;\n\t\t\t\t\t\t\tcompleteIfDone();\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\temit();\n\t\t};\n\n\t\tconst sub = wallets$.subscribe({\n\t\t\tnext: reconcile,\n\t\t\terror: (error) => subscriber.error(error),\n\t\t\tcomplete: () => {\n\t\t\t\twalletsCompleted = true;\n\t\t\t\tcompleteIfDone();\n\t\t\t},\n\t\t});\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t\tfor (const connection of connections.values())\n\t\t\t\tconnection.subscription.unsubscribe();\n\t\t};\n\t}).pipe(\n\t\tmap((frame) =>\n\t\t\tmapAccounts ? { ...frame, accounts: mapAccounts(frame.accounts) } : frame,\n\t\t),\n\t\tdistinctUntilChanged(\n\t\t\t(a, b) =>\n\t\t\t\taccountsListEqual(a.accounts, b.accounts) &&\n\t\t\t\tidsEqual(a.answered, b.answered),\n\t\t),\n\t\tshareReplay({ refCount: true, bufferSize: 1 }),\n\t);\n\tconst accounts$ = frames$.pipe(\n\t\tmap((frame) => frame.accounts),\n\t\tdistinctUntilChanged(accountsListEqual),\n\t\tshareReplay({ refCount: true, bufferSize: 1 }),\n\t);\n\treturn Object.assign(accounts$, { frames$ });\n};\n\n/**\n * CAIP-10 account strings (\"<namespace>:<chainRef>:<address>\") the live\n * WalletConnect session carries for a namespace.\n */\nexport const getSessionCaip10s = (\n\tsession: NonNullable<WalletConnectProvider[\"session\"]>,\n\tnamespace: string,\n): string[] =>\n\tObject.values(session.namespaces)\n\t\t.flatMap((ns) => ns.accounts ?? [])\n\t\t.filter((account) => account.startsWith(`${namespace}:`));\n\n/**\n * Unique addresses from CAIP-10 account strings (one entry per chain, so the\n * same address repeats — dedupe).\n */\nexport const getCaip10Addresses = (caip10s: string[]): string[] => [\n\t...new Set(\n\t\tcaip10s\n\t\t\t.map((account) => account.split(\":\")[2])\n\t\t\t.filter((address): address is string => !!address),\n\t),\n];\n\n/**\n * Shared shape of the Polkadot/Solana WalletConnect account streams: no-op\n * unless the session carries the platform's namespace, then a cached\n * observable that rebuilds the account list from the session on\n * `session_update` / `accountsChanged`.\n *\n * AppKit's `getAccount(namespace).allAccounts` is always empty for namespaces\n * without a native AppKit adapter — the WalletConnect session is the source of\n * truth, hence the session-driven rebuild.\n */\nexport const getWalletConnectSessionAccounts$ = <\n\tTAccount extends BaseWalletAccount,\n>(options: {\n\twallet: LiveWalletConnectWallet;\n\tplatform: WalletPlatform;\n\t/** WalletConnect namespace, e.g. \"polkadot\" | \"solana\" | \"eip155\". */\n\tnamespace: string;\n\t/** Cache key for {@link getCachedObservable$} — must be reconnect-safe. */\n\tcacheKey: string;\n\t/** Build the account list from the live session. */\n\tbuildAccounts: (provider: WalletConnectProvider) => TAccount[];\n}): Observable<TAccount[]> => {\n\tconst { wallet, platform, namespace, cacheKey, buildAccounts } = options;\n\tconst provider = wallet.appKit.getProvider(namespace);\n\n\tif (!wallet.platforms.includes(platform) || !provider?.session) return of([]);\n\n\treturn getCachedObservable$(cacheKey, () =>\n\t\tnew Observable<TAccount[]>((subscriber) => {\n\t\t\tsubscriber.next(buildAccounts(provider));\n\n\t\t\t// Re-derive when the WalletConnect session's accounts change, mirroring\n\t\t\t// the injected paths' change subscriptions.\n\t\t\tconst reemit = () => subscriber.next(buildAccounts(provider));\n\t\t\tprovider.on(\"session_update\", reemit);\n\t\t\tprovider.on(\"accountsChanged\", reemit);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"session_update\", reemit);\n\t\t\t\tprovider.off(\"accountsChanged\", reemit);\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n"],"mappings":"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"}