decane-connect-kit 0.0.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,2339 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ BUILT_IN_CHAINS: () => BUILT_IN_CHAINS,
34
+ CHAINS: () => CHAINS,
35
+ DecaneError: () => DecaneError,
36
+ DecaneErrorCode: () => DecaneErrorCode,
37
+ DecaneKit: () => DecaneKit,
38
+ WalletSelector: () => WalletSelector,
39
+ createDecane: () => createDecane,
40
+ useChainSwitch: () => useChainSwitch,
41
+ useDecane: () => useDecane,
42
+ useSendTransaction: () => useSendTransaction,
43
+ useSignMessage: () => useSignMessage,
44
+ useSignTypedData: () => useSignTypedData,
45
+ useWalletSelector: () => useWalletSelector
46
+ });
47
+ module.exports = __toCommonJS(index_exports);
48
+
49
+ // src/core/emitter.ts
50
+ function createEmitter() {
51
+ const listeners = /* @__PURE__ */ new Map();
52
+ return {
53
+ on(event, handler) {
54
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
55
+ listeners.get(event).add(handler);
56
+ },
57
+ off(event, handler) {
58
+ listeners.get(event)?.delete(handler);
59
+ },
60
+ emit(event, ...args) {
61
+ listeners.get(event)?.forEach((h) => h(...args));
62
+ }
63
+ };
64
+ }
65
+
66
+ // src/core/registry.ts
67
+ function createRegistry(emitter) {
68
+ const wallets = [];
69
+ function normaliseName(name) {
70
+ return name.toLowerCase().replace(/\s+/g, "").replace(/wallet$/, "");
71
+ }
72
+ function toUnified(incoming) {
73
+ const id = incoming.rdns ?? incoming.uuid ?? normaliseName(incoming.name);
74
+ const account = {
75
+ id,
76
+ name: incoming.name,
77
+ icon: incoming.icon,
78
+ rdns: incoming.rdns,
79
+ chainSupport: [incoming.chain]
80
+ };
81
+ if (incoming.chain === "evm") {
82
+ account.evmProvider = incoming.provider;
83
+ } else {
84
+ account.solanaProvider = incoming.provider;
85
+ }
86
+ return account;
87
+ }
88
+ function mergeInto(existing, incoming) {
89
+ if (!existing.chainSupport.includes(incoming.chain)) {
90
+ existing.chainSupport = [
91
+ ...existing.chainSupport,
92
+ incoming.chain
93
+ ].sort();
94
+ }
95
+ if (incoming.chain === "evm") {
96
+ existing.evmProvider = incoming.provider;
97
+ }
98
+ if (incoming.chain === "solana") {
99
+ existing.solanaProvider = incoming.provider;
100
+ }
101
+ if (!existing.icon && incoming.icon) existing.icon = incoming.icon;
102
+ }
103
+ function registerOrMerge(incoming) {
104
+ if (incoming.rdns) {
105
+ const existing = wallets.find((w) => w.rdns === incoming.rdns);
106
+ if (existing) {
107
+ mergeInto(existing, incoming);
108
+ emitter.emit("walletUpdated", existing);
109
+ return;
110
+ }
111
+ }
112
+ if (!incoming.rdns) {
113
+ const norm = normaliseName(incoming.name);
114
+ const existing = wallets.find(
115
+ (w) => normaliseName(w.name) === norm
116
+ );
117
+ if (existing) {
118
+ mergeInto(existing, incoming);
119
+ emitter.emit("walletUpdated", existing);
120
+ return;
121
+ }
122
+ }
123
+ const account = toUnified(incoming);
124
+ wallets.push(account);
125
+ emitter.emit("walletRegistered", account);
126
+ }
127
+ function unregister(provider) {
128
+ const idx = wallets.findIndex((w) => w.solanaProvider === provider);
129
+ if (idx === -1) return;
130
+ const entry = wallets[idx];
131
+ if (entry.chainSupport.length === 1) {
132
+ wallets.splice(idx, 1);
133
+ emitter.emit("walletUnregistered", entry);
134
+ } else {
135
+ entry.chainSupport = ["evm"];
136
+ entry.solanaProvider = void 0;
137
+ emitter.emit("walletUpdated", entry);
138
+ }
139
+ }
140
+ return {
141
+ registerOrMerge,
142
+ unregister,
143
+ get: {
144
+ all: () => [...wallets],
145
+ evm: () => wallets.filter((w) => w.chainSupport.includes("evm")),
146
+ solana: () => wallets.filter((w) => w.chainSupport.includes("solana")),
147
+ multiChain: () => wallets.filter(
148
+ (w) => w.chainSupport.includes("evm") && w.chainSupport.includes("solana")
149
+ ),
150
+ byId: (id) => wallets.find((w) => w.id === id)
151
+ }
152
+ };
153
+ }
154
+
155
+ // src/errors.ts
156
+ var DecaneError = class extends Error {
157
+ constructor(code, message) {
158
+ super(message);
159
+ this.code = code;
160
+ this.name = "DecaneError";
161
+ }
162
+ };
163
+ var DecaneErrorCode = /* @__PURE__ */ ((DecaneErrorCode2) => {
164
+ DecaneErrorCode2[DecaneErrorCode2["USER_REJECTED"] = 4001] = "USER_REJECTED";
165
+ DecaneErrorCode2[DecaneErrorCode2["UNAUTHORIZED"] = 4100] = "UNAUTHORIZED";
166
+ DecaneErrorCode2[DecaneErrorCode2["NO_ACTIVE_SESSION"] = 5001] = "NO_ACTIVE_SESSION";
167
+ DecaneErrorCode2[DecaneErrorCode2["SCOPE_MISMATCH"] = 5002] = "SCOPE_MISMATCH";
168
+ DecaneErrorCode2[DecaneErrorCode2["SESSION_EXPIRED"] = 5003] = "SESSION_EXPIRED";
169
+ DecaneErrorCode2[DecaneErrorCode2["UNSUPPORTED_CHAIN"] = 5010] = "UNSUPPORTED_CHAIN";
170
+ DecaneErrorCode2[DecaneErrorCode2["CHAIN_NOT_IN_SCOPE"] = 5011] = "CHAIN_NOT_IN_SCOPE";
171
+ DecaneErrorCode2[DecaneErrorCode2["INVALID_CHAIN_CONFIG"] = 5012] = "INVALID_CHAIN_CONFIG";
172
+ DecaneErrorCode2[DecaneErrorCode2["NO_WALLET_CONNECTED"] = 5020] = "NO_WALLET_CONNECTED";
173
+ DecaneErrorCode2[DecaneErrorCode2["WALLET_DISCONNECTED"] = 5021] = "WALLET_DISCONNECTED";
174
+ DecaneErrorCode2[DecaneErrorCode2["PROVIDER_ERROR"] = 5022] = "PROVIDER_ERROR";
175
+ DecaneErrorCode2[DecaneErrorCode2["METHOD_NOT_SUPPORTED"] = 5030] = "METHOD_NOT_SUPPORTED";
176
+ DecaneErrorCode2[DecaneErrorCode2["EVM_ONLY_METHOD"] = 5031] = "EVM_ONLY_METHOD";
177
+ return DecaneErrorCode2;
178
+ })(DecaneErrorCode || {});
179
+
180
+ // src/constants.ts
181
+ var ETH = { name: "Ether", symbol: "ETH", decimals: 18 };
182
+ var SOL = { name: "SOL", symbol: "SOL", decimals: 9 };
183
+ var BUILT_IN_CHAINS = [
184
+ // ── Tier-1 EVM ──────────────────────────────────────────────────────────────
185
+ {
186
+ id: "eip155:1",
187
+ type: "evm",
188
+ name: "Ethereum",
189
+ chainId: 1,
190
+ nativeCurrency: ETH,
191
+ rpcUrl: "https://cloudflare-eth.com",
192
+ blockExplorerUrl: "https://etherscan.io"
193
+ },
194
+ {
195
+ id: "eip155:8453",
196
+ type: "evm",
197
+ name: "Base",
198
+ chainId: 8453,
199
+ nativeCurrency: ETH,
200
+ rpcUrl: "https://mainnet.base.org",
201
+ blockExplorerUrl: "https://basescan.org"
202
+ },
203
+ {
204
+ id: "eip155:42161",
205
+ type: "evm",
206
+ name: "Arbitrum One",
207
+ chainId: 42161,
208
+ nativeCurrency: ETH,
209
+ rpcUrl: "https://arb1.arbitrum.io/rpc",
210
+ blockExplorerUrl: "https://arbiscan.io"
211
+ },
212
+ {
213
+ id: "eip155:10",
214
+ type: "evm",
215
+ name: "Optimism",
216
+ chainId: 10,
217
+ nativeCurrency: ETH,
218
+ rpcUrl: "https://mainnet.optimism.io",
219
+ blockExplorerUrl: "https://optimistic.etherscan.io"
220
+ },
221
+ {
222
+ id: "eip155:56",
223
+ type: "evm",
224
+ name: "BNB Chain",
225
+ chainId: 56,
226
+ nativeCurrency: { name: "BNB", symbol: "BNB", decimals: 18 },
227
+ rpcUrl: "https://bsc-dataseed.binance.org",
228
+ blockExplorerUrl: "https://bscscan.com"
229
+ },
230
+ {
231
+ id: "eip155:137",
232
+ type: "evm",
233
+ name: "Polygon",
234
+ chainId: 137,
235
+ nativeCurrency: { name: "MATIC", symbol: "MATIC", decimals: 18 },
236
+ rpcUrl: "https://polygon-rpc.com",
237
+ blockExplorerUrl: "https://polygonscan.com"
238
+ },
239
+ // ── Extended EVM ecosystem ───────────────────────────────────────────────────
240
+ {
241
+ id: "eip155:2741",
242
+ type: "evm",
243
+ name: "Abstract",
244
+ chainId: 2741,
245
+ nativeCurrency: ETH,
246
+ rpcUrl: "https://api.mainnet.abs.xyz",
247
+ blockExplorerUrl: "https://abscan.org"
248
+ },
249
+ {
250
+ id: "eip155:888888888",
251
+ type: "evm",
252
+ name: "Ancient8",
253
+ chainId: 888888888,
254
+ nativeCurrency: ETH,
255
+ rpcUrl: "https://rpc.ancient8.gg",
256
+ blockExplorerUrl: "https://scan.ancient8.gg"
257
+ },
258
+ {
259
+ id: "eip155:69000",
260
+ type: "evm",
261
+ name: "Animechain",
262
+ chainId: 69e3,
263
+ nativeCurrency: { name: "Anime", symbol: "ANIME", decimals: 18 },
264
+ rpcUrl: "https://rpc.animechain.ai",
265
+ blockExplorerUrl: "https://explorer.animechain.ai"
266
+ },
267
+ {
268
+ id: "eip155:33139",
269
+ type: "evm",
270
+ name: "ApeChain",
271
+ chainId: 33139,
272
+ nativeCurrency: { name: "ApeCoin", symbol: "APE", decimals: 18 },
273
+ rpcUrl: "https://rpc.apechain.com/http",
274
+ blockExplorerUrl: "https://apescan.io"
275
+ },
276
+ {
277
+ id: "eip155:42170",
278
+ type: "evm",
279
+ name: "Arbitrum Nova",
280
+ chainId: 42170,
281
+ nativeCurrency: ETH,
282
+ rpcUrl: "https://nova.arbitrum.io/rpc",
283
+ blockExplorerUrl: "https://nova.arbiscan.io"
284
+ },
285
+ {
286
+ id: "eip155:43114",
287
+ type: "evm",
288
+ name: "Avalanche",
289
+ chainId: 43114,
290
+ nativeCurrency: { name: "Avalanche", symbol: "AVAX", decimals: 18 },
291
+ rpcUrl: "https://api.avax.network/ext/bc/C/rpc",
292
+ blockExplorerUrl: "https://snowtrace.io"
293
+ },
294
+ {
295
+ id: "eip155:8333",
296
+ type: "evm",
297
+ name: "B3",
298
+ chainId: 8333,
299
+ nativeCurrency: ETH,
300
+ rpcUrl: "https://mainnet-rpc.b3.fun/http",
301
+ blockExplorerUrl: "https://explorer.b3.fun"
302
+ },
303
+ {
304
+ id: "eip155:80094",
305
+ type: "evm",
306
+ name: "Berachain",
307
+ chainId: 80094,
308
+ nativeCurrency: { name: "BERA", symbol: "BERA", decimals: 18 },
309
+ rpcUrl: "https://rpc.berachain.com",
310
+ blockExplorerUrl: "https://berascan.com"
311
+ },
312
+ {
313
+ id: "eip155:81457",
314
+ type: "evm",
315
+ name: "Blast",
316
+ chainId: 81457,
317
+ nativeCurrency: ETH,
318
+ rpcUrl: "https://rpc.blast.io",
319
+ blockExplorerUrl: "https://blastscan.io"
320
+ },
321
+ {
322
+ id: "eip155:60808",
323
+ type: "evm",
324
+ name: "BOB",
325
+ chainId: 60808,
326
+ nativeCurrency: ETH,
327
+ rpcUrl: "https://rpc.gobob.xyz",
328
+ blockExplorerUrl: "https://explorer.gobob.xyz"
329
+ },
330
+ {
331
+ id: "eip155:288",
332
+ type: "evm",
333
+ name: "Boba Network",
334
+ chainId: 288,
335
+ nativeCurrency: ETH,
336
+ rpcUrl: "https://mainnet.boba.network",
337
+ blockExplorerUrl: "https://bobascan.com"
338
+ },
339
+ {
340
+ id: "eip155:42220",
341
+ type: "evm",
342
+ name: "Celo",
343
+ chainId: 42220,
344
+ nativeCurrency: { name: "CELO", symbol: "CELO", decimals: 18 },
345
+ rpcUrl: "https://forno.celo.org",
346
+ blockExplorerUrl: "https://celoscan.io"
347
+ },
348
+ {
349
+ id: "eip155:21000000",
350
+ type: "evm",
351
+ name: "Corn",
352
+ chainId: 21e6,
353
+ nativeCurrency: { name: "Bitcorn", symbol: "BTCN", decimals: 18 },
354
+ rpcUrl: "https://mainnet.corn-rpc.com",
355
+ blockExplorerUrl: "https://cornscan.io"
356
+ },
357
+ {
358
+ id: "eip155:25",
359
+ type: "evm",
360
+ name: "Cronos",
361
+ chainId: 25,
362
+ nativeCurrency: { name: "Cronos", symbol: "CRO", decimals: 18 },
363
+ rpcUrl: "https://evm.cronos.org",
364
+ blockExplorerUrl: "https://cronoscan.com"
365
+ },
366
+ {
367
+ id: "eip155:7560",
368
+ type: "evm",
369
+ name: "Cyber",
370
+ chainId: 7560,
371
+ nativeCurrency: ETH,
372
+ rpcUrl: "https://rpc.cyber.co",
373
+ blockExplorerUrl: "https://cyberscan.co"
374
+ },
375
+ {
376
+ id: "eip155:666666666",
377
+ type: "evm",
378
+ name: "Degen",
379
+ chainId: 666666666,
380
+ nativeCurrency: { name: "Degen", symbol: "DEGEN", decimals: 18 },
381
+ rpcUrl: "https://rpc.degen.tips",
382
+ blockExplorerUrl: "https://explorer.degen.tips"
383
+ },
384
+ {
385
+ id: "eip155:747",
386
+ type: "evm",
387
+ name: "Flow EVM",
388
+ chainId: 747,
389
+ nativeCurrency: { name: "Flow", symbol: "FLOW", decimals: 18 },
390
+ rpcUrl: "https://mainnet.evm.nodes.onflow.org",
391
+ blockExplorerUrl: "https://flowdiver.io"
392
+ },
393
+ {
394
+ id: "eip155:100",
395
+ type: "evm",
396
+ name: "Gnosis",
397
+ chainId: 100,
398
+ nativeCurrency: { name: "xDai", symbol: "xDAI", decimals: 18 },
399
+ rpcUrl: "https://rpc.gnosischain.com",
400
+ blockExplorerUrl: "https://gnosisscan.io"
401
+ },
402
+ {
403
+ id: "eip155:49321",
404
+ type: "evm",
405
+ name: "Gunz",
406
+ chainId: 49321,
407
+ nativeCurrency: ETH,
408
+ rpcUrl: "https://rpc.gunz.dev/ext/bc/evm",
409
+ blockExplorerUrl: "https://explorer.gunz.dev"
410
+ },
411
+ {
412
+ id: "eip155:43111",
413
+ type: "evm",
414
+ name: "Hemi",
415
+ chainId: 43111,
416
+ nativeCurrency: ETH,
417
+ rpcUrl: "https://rpc.hemi.network/rpc",
418
+ blockExplorerUrl: "https://explorer.hemi.xyz"
419
+ },
420
+ {
421
+ id: "eip155:999",
422
+ type: "evm",
423
+ name: "HyperEVM",
424
+ chainId: 999,
425
+ nativeCurrency: { name: "HYPE", symbol: "HYPE", decimals: 18 },
426
+ rpcUrl: "https://rpc.hyperliquid.xyz/evm",
427
+ blockExplorerUrl: "https://hyperevm-explorer.hyperliquid.xyz"
428
+ },
429
+ {
430
+ id: "eip155:57073",
431
+ type: "evm",
432
+ name: "Ink",
433
+ chainId: 57073,
434
+ nativeCurrency: ETH,
435
+ rpcUrl: "https://rpc-gel.inkonchain.com",
436
+ blockExplorerUrl: "https://explorer.inkonchain.com"
437
+ },
438
+ {
439
+ id: "eip155:59144",
440
+ type: "evm",
441
+ name: "Linea",
442
+ chainId: 59144,
443
+ nativeCurrency: ETH,
444
+ rpcUrl: "https://rpc.linea.build",
445
+ blockExplorerUrl: "https://lineascan.build"
446
+ },
447
+ {
448
+ id: "eip155:1135",
449
+ type: "evm",
450
+ name: "Lisk",
451
+ chainId: 1135,
452
+ nativeCurrency: ETH,
453
+ rpcUrl: "https://rpc.api.lisk.com",
454
+ blockExplorerUrl: "https://blockscout.lisk.com"
455
+ },
456
+ {
457
+ id: "eip155:169",
458
+ type: "evm",
459
+ name: "Manta Pacific",
460
+ chainId: 169,
461
+ nativeCurrency: ETH,
462
+ rpcUrl: "https://pacific-rpc.manta.network/http",
463
+ blockExplorerUrl: "https://pacific-explorer.manta.network"
464
+ },
465
+ {
466
+ id: "eip155:5000",
467
+ type: "evm",
468
+ name: "Mantle",
469
+ chainId: 5e3,
470
+ nativeCurrency: { name: "MNT", symbol: "MNT", decimals: 18 },
471
+ rpcUrl: "https://rpc.mantle.xyz",
472
+ blockExplorerUrl: "https://explorer.mantle.xyz"
473
+ },
474
+ {
475
+ id: "eip155:6342",
476
+ type: "evm",
477
+ name: "MegaETH",
478
+ chainId: 6342,
479
+ nativeCurrency: ETH,
480
+ rpcUrl: "https://carrot.megaeth.com",
481
+ blockExplorerUrl: "https://megaexplorer.xyz"
482
+ },
483
+ {
484
+ id: "eip155:1088",
485
+ type: "evm",
486
+ name: "Metis",
487
+ chainId: 1088,
488
+ nativeCurrency: { name: "Metis", symbol: "METIS", decimals: 18 },
489
+ rpcUrl: "https://andromeda.metis.io/?owner=1088",
490
+ blockExplorerUrl: "https://andromeda-explorer.metis.io"
491
+ },
492
+ {
493
+ id: "eip155:34443",
494
+ type: "evm",
495
+ name: "Mode",
496
+ chainId: 34443,
497
+ nativeCurrency: ETH,
498
+ rpcUrl: "https://mainnet.mode.network",
499
+ blockExplorerUrl: "https://modescan.io"
500
+ },
501
+ {
502
+ id: "eip155:10143",
503
+ type: "evm",
504
+ name: "Monad",
505
+ chainId: 10143,
506
+ nativeCurrency: { name: "MON", symbol: "MON", decimals: 18 },
507
+ rpcUrl: "https://testnet-rpc.monad.xyz",
508
+ blockExplorerUrl: "https://testnet.monadexplorer.com"
509
+ },
510
+ {
511
+ id: "eip155:2818",
512
+ type: "evm",
513
+ name: "Morph",
514
+ chainId: 2818,
515
+ nativeCurrency: ETH,
516
+ rpcUrl: "https://rpc-quicknode.morphl2.io",
517
+ blockExplorerUrl: "https://explorer.morphl2.io"
518
+ },
519
+ {
520
+ id: "eip155:98866",
521
+ type: "evm",
522
+ name: "Plume",
523
+ chainId: 98866,
524
+ nativeCurrency: { name: "Plume", symbol: "PLUME", decimals: 18 },
525
+ rpcUrl: "https://rpc.plume.org",
526
+ blockExplorerUrl: "https://explorer.plume.org"
527
+ },
528
+ {
529
+ id: "eip155:1380012617",
530
+ type: "evm",
531
+ name: "RARI",
532
+ chainId: 1380012617,
533
+ nativeCurrency: ETH,
534
+ rpcUrl: "https://mainnet.rpc.rarichain.org/ext/bc/C/rpc",
535
+ blockExplorerUrl: "https://mainnet.explorer.rarichain.org"
536
+ },
537
+ {
538
+ id: "eip155:690",
539
+ type: "evm",
540
+ name: "Redstone",
541
+ chainId: 690,
542
+ nativeCurrency: ETH,
543
+ rpcUrl: "https://rpc.redstonechain.com",
544
+ blockExplorerUrl: "https://explorer.redstone.xyz"
545
+ },
546
+ {
547
+ id: "eip155:2020",
548
+ type: "evm",
549
+ name: "Ronin",
550
+ chainId: 2020,
551
+ nativeCurrency: { name: "RON", symbol: "RON", decimals: 18 },
552
+ rpcUrl: "https://api.roninchain.com/rpc",
553
+ blockExplorerUrl: "https://app.roninchain.com"
554
+ },
555
+ {
556
+ id: "eip155:534352",
557
+ type: "evm",
558
+ name: "Scroll",
559
+ chainId: 534352,
560
+ nativeCurrency: ETH,
561
+ rpcUrl: "https://rpc.scroll.io",
562
+ blockExplorerUrl: "https://scrollscan.com"
563
+ },
564
+ {
565
+ id: "eip155:1329",
566
+ type: "evm",
567
+ name: "Sei",
568
+ chainId: 1329,
569
+ nativeCurrency: { name: "Sei", symbol: "SEI", decimals: 18 },
570
+ rpcUrl: "https://evm-rpc.sei-apis.com",
571
+ blockExplorerUrl: "https://seistream.app"
572
+ },
573
+ {
574
+ id: "eip155:360",
575
+ type: "evm",
576
+ name: "Shape",
577
+ chainId: 360,
578
+ nativeCurrency: ETH,
579
+ rpcUrl: "https://mainnet.shape.network",
580
+ blockExplorerUrl: "https://shapescan.xyz"
581
+ },
582
+ {
583
+ id: "eip155:50312",
584
+ type: "evm",
585
+ name: "Somnia",
586
+ chainId: 50312,
587
+ nativeCurrency: { name: "STT", symbol: "STT", decimals: 18 },
588
+ rpcUrl: "https://dream-rpc.somnia.network",
589
+ blockExplorerUrl: "https://shannon-explorer.somnia.network"
590
+ },
591
+ {
592
+ id: "eip155:1868",
593
+ type: "evm",
594
+ name: "Soneium",
595
+ chainId: 1868,
596
+ nativeCurrency: ETH,
597
+ rpcUrl: "https://rpc.soneium.org",
598
+ blockExplorerUrl: "https://soneium.blockscout.com"
599
+ },
600
+ {
601
+ id: "eip155:146",
602
+ type: "evm",
603
+ name: "Sonic",
604
+ chainId: 146,
605
+ nativeCurrency: { name: "Sonic", symbol: "S", decimals: 18 },
606
+ rpcUrl: "https://rpc.soniclabs.com",
607
+ blockExplorerUrl: "https://sonicscan.org"
608
+ },
609
+ {
610
+ id: "eip155:1514",
611
+ type: "evm",
612
+ name: "Story",
613
+ chainId: 1514,
614
+ nativeCurrency: { name: "IP", symbol: "IP", decimals: 18 },
615
+ rpcUrl: "https://mainnet.storyrpc.io",
616
+ blockExplorerUrl: "https://storyscan.xyz"
617
+ },
618
+ {
619
+ id: "eip155:55244",
620
+ type: "evm",
621
+ name: "Superposition",
622
+ chainId: 55244,
623
+ nativeCurrency: ETH,
624
+ rpcUrl: "https://rpc.superposition.so",
625
+ blockExplorerUrl: "https://explorer.superposition.so"
626
+ },
627
+ {
628
+ id: "eip155:5330",
629
+ type: "evm",
630
+ name: "Superseed",
631
+ chainId: 5330,
632
+ nativeCurrency: ETH,
633
+ rpcUrl: "https://mainnet.superseed.xyz",
634
+ blockExplorerUrl: "https://explorer.superseed.xyz"
635
+ },
636
+ {
637
+ id: "eip155:1923",
638
+ type: "evm",
639
+ name: "SwellChain",
640
+ chainId: 1923,
641
+ nativeCurrency: ETH,
642
+ rpcUrl: "https://swell-mainnet.alt.technology",
643
+ blockExplorerUrl: "https://explorer.swellnetwork.io"
644
+ },
645
+ {
646
+ id: "eip155:167000",
647
+ type: "evm",
648
+ name: "Taiko",
649
+ chainId: 167e3,
650
+ nativeCurrency: ETH,
651
+ rpcUrl: "https://rpc.mainnet.taiko.xyz",
652
+ blockExplorerUrl: "https://taikoscan.io"
653
+ },
654
+ {
655
+ id: "eip155:130",
656
+ type: "evm",
657
+ name: "Unichain",
658
+ chainId: 130,
659
+ nativeCurrency: ETH,
660
+ rpcUrl: "https://mainnet.unichain.org",
661
+ blockExplorerUrl: "https://uniscan.xyz"
662
+ },
663
+ {
664
+ id: "eip155:480",
665
+ type: "evm",
666
+ name: "World Chain",
667
+ chainId: 480,
668
+ nativeCurrency: ETH,
669
+ rpcUrl: "https://worldchain-mainnet.g.alchemy.com/public",
670
+ blockExplorerUrl: "https://worldchain-mainnet.explorer.alchemy.com"
671
+ },
672
+ {
673
+ id: "eip155:543210",
674
+ type: "evm",
675
+ name: "ZERO",
676
+ chainId: 543210,
677
+ nativeCurrency: ETH,
678
+ rpcUrl: "https://rpc.zerion.io/v1/zero",
679
+ blockExplorerUrl: "https://explorer.zero.network"
680
+ },
681
+ {
682
+ id: "eip155:48900",
683
+ type: "evm",
684
+ name: "Zircuit",
685
+ chainId: 48900,
686
+ nativeCurrency: ETH,
687
+ rpcUrl: "https://zircuit1-mainnet.p2pify.com",
688
+ blockExplorerUrl: "https://explorer.zircuit.com"
689
+ },
690
+ {
691
+ id: "eip155:324",
692
+ type: "evm",
693
+ name: "zkSync Era",
694
+ chainId: 324,
695
+ nativeCurrency: ETH,
696
+ rpcUrl: "https://mainnet.era.zksync.io",
697
+ blockExplorerUrl: "https://explorer.zksync.io"
698
+ },
699
+ {
700
+ id: "eip155:7777777",
701
+ type: "evm",
702
+ name: "Zora",
703
+ chainId: 7777777,
704
+ nativeCurrency: ETH,
705
+ rpcUrl: "https://rpc.zora.energy",
706
+ blockExplorerUrl: "https://explorer.zora.energy"
707
+ },
708
+ // ── Dev / local ──────────────────────────────────────────────────────────────
709
+ {
710
+ id: "eip155:31337",
711
+ type: "evm",
712
+ name: "Localhost",
713
+ chainId: 31337,
714
+ nativeCurrency: ETH,
715
+ rpcUrl: "http://localhost:8545",
716
+ isCustom: true
717
+ },
718
+ // ── Solana ───────────────────────────────────────────────────────────────────
719
+ {
720
+ id: "solana:mainnet",
721
+ type: "solana",
722
+ name: "Solana",
723
+ nativeCurrency: SOL,
724
+ blockExplorerUrl: "https://solscan.io"
725
+ },
726
+ {
727
+ id: "solana:devnet",
728
+ type: "solana",
729
+ name: "Solana Devnet",
730
+ nativeCurrency: SOL,
731
+ blockExplorerUrl: "https://solscan.io/?cluster=devnet"
732
+ }
733
+ ];
734
+ function getChainType(caip2Id) {
735
+ if (caip2Id.startsWith("eip155:")) return "evm";
736
+ if (caip2Id.startsWith("solana:")) return "solana";
737
+ throw new Error(`Cannot determine chain type from: ${caip2Id}`);
738
+ }
739
+ function toCAIP10(chainId, address) {
740
+ return `${chainId}:${address}`;
741
+ }
742
+ var EVM_METHODS = /* @__PURE__ */ new Set([
743
+ "wallet_sendTransaction",
744
+ "wallet_signMessage",
745
+ "wallet_signTypedData"
746
+ ]);
747
+ var SOLANA_METHODS = /* @__PURE__ */ new Set([
748
+ "wallet_sendTransaction",
749
+ "wallet_signMessage"
750
+ // wallet_signTypedData is EVM-only — never included here
751
+ ]);
752
+ var CHAINS = {
753
+ // Tier-1
754
+ ETHEREUM: "eip155:1",
755
+ BASE: "eip155:8453",
756
+ ARBITRUM: "eip155:42161",
757
+ OPTIMISM: "eip155:10",
758
+ BNB: "eip155:56",
759
+ POLYGON: "eip155:137",
760
+ // Extended EVM
761
+ ABSTRACT: "eip155:2741",
762
+ ANCIENT8: "eip155:888888888",
763
+ ANIMECHAIN: "eip155:69000",
764
+ APE_CHAIN: "eip155:33139",
765
+ ARBITRUM_NOVA: "eip155:42170",
766
+ AVALANCHE: "eip155:43114",
767
+ B3: "eip155:8333",
768
+ BERACHAIN: "eip155:80094",
769
+ BLAST: "eip155:81457",
770
+ BOB: "eip155:60808",
771
+ BOBA: "eip155:288",
772
+ CELO: "eip155:42220",
773
+ CORN: "eip155:21000000",
774
+ CRONOS: "eip155:25",
775
+ CYBER: "eip155:7560",
776
+ DEGEN: "eip155:666666666",
777
+ FLOW_EVM: "eip155:747",
778
+ GNOSIS: "eip155:100",
779
+ GUNZ: "eip155:49321",
780
+ HEMI: "eip155:43111",
781
+ HYPER_EVM: "eip155:999",
782
+ INK: "eip155:57073",
783
+ LINEA: "eip155:59144",
784
+ LISK: "eip155:1135",
785
+ MANTA_PACIFIC: "eip155:169",
786
+ MANTLE: "eip155:5000",
787
+ MEGA_ETH: "eip155:6342",
788
+ METIS: "eip155:1088",
789
+ MODE: "eip155:34443",
790
+ MONAD: "eip155:10143",
791
+ MORPH: "eip155:2818",
792
+ PLUME: "eip155:98866",
793
+ RARI: "eip155:1380012617",
794
+ REDSTONE: "eip155:690",
795
+ RONIN: "eip155:2020",
796
+ SCROLL: "eip155:534352",
797
+ SEI: "eip155:1329",
798
+ SHAPE: "eip155:360",
799
+ SOMNIA: "eip155:50312",
800
+ SONEIUM: "eip155:1868",
801
+ SONIC: "eip155:146",
802
+ STORY: "eip155:1514",
803
+ SUPERPOSITION: "eip155:55244",
804
+ SUPERSEED: "eip155:5330",
805
+ SWELL_CHAIN: "eip155:1923",
806
+ TAIKO: "eip155:167000",
807
+ UNICHAIN: "eip155:130",
808
+ WORLD_CHAIN: "eip155:480",
809
+ ZERO: "eip155:543210",
810
+ ZIRCUIT: "eip155:48900",
811
+ ZKSYNC_ERA: "eip155:324",
812
+ ZORA: "eip155:7777777",
813
+ // Dev
814
+ LOCALHOST: "eip155:31337",
815
+ // Solana
816
+ SOLANA: "solana:mainnet",
817
+ SOLANA_DEVNET: "solana:devnet"
818
+ };
819
+ function validateCustomChain(chain) {
820
+ if (!chain || typeof chain !== "object") return false;
821
+ const c = chain;
822
+ if (typeof c.id !== "string" || !c.id) return false;
823
+ if (c.type !== "evm" && c.type !== "solana") return false;
824
+ if (typeof c.name !== "string" || !c.name) return false;
825
+ if (!c.nativeCurrency || typeof c.nativeCurrency !== "object") return false;
826
+ if (c.type === "evm" && (typeof c.chainId !== "number" || !c.id.startsWith("eip155:")))
827
+ return false;
828
+ if (c.type === "solana" && !c.id.startsWith("solana:")) return false;
829
+ return true;
830
+ }
831
+
832
+ // src/core/session.ts
833
+ var STORAGE_KEY = "decane:session";
834
+ function loadFromStorage() {
835
+ if (typeof localStorage === "undefined") return null;
836
+ try {
837
+ const raw = localStorage.getItem(STORAGE_KEY);
838
+ return raw ? JSON.parse(raw) : null;
839
+ } catch {
840
+ return null;
841
+ }
842
+ }
843
+ function saveToStorage(session) {
844
+ if (typeof localStorage === "undefined") return;
845
+ try {
846
+ if (session) {
847
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(session));
848
+ } else {
849
+ localStorage.removeItem(STORAGE_KEY);
850
+ }
851
+ } catch {
852
+ }
853
+ }
854
+ function createSessionManager() {
855
+ let _session = loadFromStorage();
856
+ return {
857
+ get: () => _session,
858
+ set(s) {
859
+ _session = s;
860
+ saveToStorage(s);
861
+ },
862
+ clear() {
863
+ _session = null;
864
+ saveToStorage(null);
865
+ },
866
+ isChainGranted(chainId) {
867
+ return !!_session?.grantedScopes[chainId];
868
+ },
869
+ isAccountGranted(chainId, address) {
870
+ const scope = _session?.grantedScopes[chainId];
871
+ if (!scope) return false;
872
+ return scope.accounts.includes(toCAIP10(chainId, address));
873
+ },
874
+ assertChainInScope(chainId) {
875
+ if (!this.isChainGranted(chainId)) {
876
+ throw new DecaneError(
877
+ 5011 /* CHAIN_NOT_IN_SCOPE */,
878
+ `Chain ${chainId} is not in the current session scope. Call wallet_requestPermissions first.`
879
+ );
880
+ }
881
+ },
882
+ assertAccountInScope(chainId, address) {
883
+ if (!this.isAccountGranted(chainId, address)) {
884
+ throw new DecaneError(
885
+ 5002 /* SCOPE_MISMATCH */,
886
+ `Account ${address} on chain ${chainId} is not in the current session scope.`
887
+ );
888
+ }
889
+ }
890
+ };
891
+ }
892
+
893
+ // src/core/chainStore.ts
894
+ function createChainStore(initial) {
895
+ const chains = new Map(
896
+ initial.map((c) => [c.id, c])
897
+ );
898
+ return {
899
+ get(id) {
900
+ return chains.get(id);
901
+ },
902
+ getAll() {
903
+ return [...chains.values()];
904
+ },
905
+ add(chain) {
906
+ if (chains.has(chain.id)) {
907
+ throw new DecaneError(
908
+ 5012 /* INVALID_CHAIN_CONFIG */,
909
+ `Chain ${chain.id} is already registered`
910
+ );
911
+ }
912
+ chains.set(chain.id, chain);
913
+ },
914
+ remove(id) {
915
+ const chain = chains.get(id);
916
+ if (!chain) return;
917
+ if (!chain.isCustom) {
918
+ throw new DecaneError(
919
+ 5012 /* INVALID_CHAIN_CONFIG */,
920
+ `Cannot remove built-in chain ${id}`
921
+ );
922
+ }
923
+ chains.delete(id);
924
+ }
925
+ };
926
+ }
927
+
928
+ // src/evm/adapter.ts
929
+ async function eip1193Request(provider, method, payload, account) {
930
+ switch (method) {
931
+ case "wallet_sendTransaction":
932
+ return provider.request({
933
+ method: "eth_sendTransaction",
934
+ params: [{ ...payload, from: account }]
935
+ });
936
+ case "wallet_signMessage":
937
+ return provider.request({
938
+ method: "personal_sign",
939
+ params: [payload, account]
940
+ });
941
+ case "wallet_signTypedData":
942
+ return provider.request({
943
+ method: "eth_signTypedData_v4",
944
+ params: [account, JSON.stringify(payload)]
945
+ });
946
+ default:
947
+ throw new DecaneError(
948
+ 5030 /* METHOD_NOT_SUPPORTED */,
949
+ `EVM adapter: unsupported method ${method}`
950
+ );
951
+ }
952
+ }
953
+ async function getEvmAddress(provider) {
954
+ const accounts = await provider.request({
955
+ method: "eth_requestAccounts"
956
+ });
957
+ if (!accounts?.[0]) {
958
+ throw new DecaneError(
959
+ 4001 /* USER_REJECTED */,
960
+ "No EVM accounts returned"
961
+ );
962
+ }
963
+ return accounts[0];
964
+ }
965
+ async function addEthereumChain(provider, chain) {
966
+ await provider.request({
967
+ method: "wallet_addEthereumChain",
968
+ params: [
969
+ {
970
+ chainId: `0x${chain.chainId.toString(16)}`,
971
+ chainName: chain.name,
972
+ nativeCurrency: chain.nativeCurrency,
973
+ rpcUrls: chain.rpcUrl ? [chain.rpcUrl] : [],
974
+ blockExplorerUrls: chain.blockExplorerUrl ? [chain.blockExplorerUrl] : []
975
+ }
976
+ ]
977
+ });
978
+ }
979
+
980
+ // src/solana/adapter.ts
981
+ var import_base = require("@scure/base");
982
+ function deserializeSolanaTransaction(data) {
983
+ return data;
984
+ }
985
+ async function walletStandardRequest(wallet, method, payload, account) {
986
+ switch (method) {
987
+ case "wallet_sendTransaction": {
988
+ const feature = wallet.features["solana:signAndSendTransaction"];
989
+ if (!feature) {
990
+ throw new DecaneError(
991
+ 5030 /* METHOD_NOT_SUPPORTED */,
992
+ "Wallet does not support solana:signAndSendTransaction"
993
+ );
994
+ }
995
+ const walletAccount = wallet.accounts.find(
996
+ (a) => import_base.base58.encode(a.publicKey) === account
997
+ );
998
+ if (!walletAccount) {
999
+ throw new DecaneError(
1000
+ 5002 /* SCOPE_MISMATCH */,
1001
+ `Account ${account} not found`
1002
+ );
1003
+ }
1004
+ const tx = deserializeSolanaTransaction(payload);
1005
+ const [result] = await feature.signAndSendTransaction({
1006
+ transaction: tx,
1007
+ account: walletAccount
1008
+ });
1009
+ return result.signature;
1010
+ }
1011
+ case "wallet_signMessage": {
1012
+ const feature = wallet.features["solana:signMessage"];
1013
+ if (!feature) {
1014
+ throw new DecaneError(
1015
+ 5030 /* METHOD_NOT_SUPPORTED */,
1016
+ "Wallet does not support solana:signMessage"
1017
+ );
1018
+ }
1019
+ const walletAccount = wallet.accounts.find(
1020
+ (a) => import_base.base58.encode(a.publicKey) === account
1021
+ );
1022
+ if (!walletAccount) {
1023
+ throw new DecaneError(
1024
+ 5002 /* SCOPE_MISMATCH */,
1025
+ `Account ${account} not found`
1026
+ );
1027
+ }
1028
+ const messageBytes = typeof payload === "string" ? new TextEncoder().encode(payload) : payload;
1029
+ const [result] = await feature.signMessage({
1030
+ message: messageBytes,
1031
+ account: walletAccount
1032
+ });
1033
+ return import_base.base58.encode(result.signature);
1034
+ }
1035
+ default:
1036
+ throw new DecaneError(
1037
+ 5030 /* METHOD_NOT_SUPPORTED */,
1038
+ `Solana adapter: unsupported method ${method}`
1039
+ );
1040
+ }
1041
+ }
1042
+ async function getSolanaAddress(wallet) {
1043
+ const connectFeature = wallet.features["standard:connect"];
1044
+ if (!connectFeature) {
1045
+ throw new DecaneError(
1046
+ 5030 /* METHOD_NOT_SUPPORTED */,
1047
+ "Wallet does not support standard:connect"
1048
+ );
1049
+ }
1050
+ const { accounts } = await connectFeature.connect();
1051
+ if (!accounts?.[0]) {
1052
+ throw new DecaneError(
1053
+ 4001 /* USER_REJECTED */,
1054
+ "No Solana accounts returned"
1055
+ );
1056
+ }
1057
+ return import_base.base58.encode(accounts[0].publicKey);
1058
+ }
1059
+
1060
+ // src/core/router.ts
1061
+ function createRouter(opts) {
1062
+ const { registry, session, chainStore } = opts;
1063
+ async function request(args) {
1064
+ switch (args.method) {
1065
+ case "wallet_requestPermissions":
1066
+ return handleRequestPermissions(
1067
+ args.params
1068
+ );
1069
+ case "wallet_revokePermissions":
1070
+ return handleRevokePermissions();
1071
+ case "wallet_getPermissions":
1072
+ return handleGetPermissions();
1073
+ case "wallet_sendTransaction":
1074
+ case "wallet_signMessage":
1075
+ case "wallet_signTypedData":
1076
+ return handleSigning(args.method, args.params);
1077
+ default:
1078
+ throw new DecaneError(
1079
+ 5030 /* METHOD_NOT_SUPPORTED */,
1080
+ `Unknown CAIP-25 method: ${args.method}`
1081
+ );
1082
+ }
1083
+ }
1084
+ async function handleRequestPermissions([
1085
+ req,
1086
+ walletIdHint
1087
+ ]) {
1088
+ const connectedWallet = (walletIdHint ? registry.get.byId(walletIdHint) : void 0) ?? registry.get.all().find((w) => w.id === session.get()?.walletId) ?? registry.get.all()[0];
1089
+ if (!connectedWallet) {
1090
+ throw new DecaneError(
1091
+ 5020 /* NO_WALLET_CONNECTED */,
1092
+ "No wallet connected"
1093
+ );
1094
+ }
1095
+ const allScopes = { ...req.requiredScopes, ...req.optionalScopes };
1096
+ const grantedScopes = {};
1097
+ for (const [chainId, scope] of Object.entries(allScopes)) {
1098
+ const chain = chainStore.get(chainId);
1099
+ if (!chain) {
1100
+ throw new DecaneError(
1101
+ 5010 /* UNSUPPORTED_CHAIN */,
1102
+ `Unknown chain: ${chainId}`
1103
+ );
1104
+ }
1105
+ const chainType = getChainType(chainId);
1106
+ if (chainType === "evm" && !connectedWallet.evmProvider) continue;
1107
+ if (chainType === "solana" && !connectedWallet.solanaProvider) continue;
1108
+ let address;
1109
+ if (chainType === "evm") {
1110
+ address = await getEvmAddress(connectedWallet.evmProvider);
1111
+ if (chain.isCustom) {
1112
+ await addEthereumChain(
1113
+ connectedWallet.evmProvider,
1114
+ chain
1115
+ ).catch(() => {
1116
+ });
1117
+ }
1118
+ } else {
1119
+ address = await getSolanaAddress(connectedWallet.solanaProvider);
1120
+ }
1121
+ const methodSet = chainType === "evm" ? EVM_METHODS : SOLANA_METHODS;
1122
+ const grantedMethods = (scope?.methods ?? []).filter(
1123
+ (m) => methodSet.has(m)
1124
+ );
1125
+ grantedScopes[chainId] = {
1126
+ methods: grantedMethods,
1127
+ accounts: [toCAIP10(chainId, address)],
1128
+ events: scope?.events ?? []
1129
+ };
1130
+ }
1131
+ for (const chainId of Object.keys(req.requiredScopes)) {
1132
+ if (!grantedScopes[chainId]) {
1133
+ throw new DecaneError(
1134
+ 5010 /* UNSUPPORTED_CHAIN */,
1135
+ `Required chain ${chainId} could not be granted`
1136
+ );
1137
+ }
1138
+ }
1139
+ const newSession = {
1140
+ sessionId: crypto.randomUUID(),
1141
+ grantedScopes,
1142
+ walletId: connectedWallet.id,
1143
+ walletType: connectedWallet.chainSupport.length === 2 ? "multi" : connectedWallet.chainSupport[0],
1144
+ createdAt: Date.now()
1145
+ };
1146
+ session.set(newSession);
1147
+ return { sessionId: newSession.sessionId, grantedScopes };
1148
+ }
1149
+ async function handleRevokePermissions() {
1150
+ session.clear();
1151
+ return null;
1152
+ }
1153
+ async function handleGetPermissions() {
1154
+ const s = session.get();
1155
+ if (!s) return null;
1156
+ return { sessionId: s.sessionId, grantedScopes: s.grantedScopes };
1157
+ }
1158
+ function extractSigningContext(method, params) {
1159
+ if (!params || params.length < 3) {
1160
+ throw new DecaneError(
1161
+ 5030 /* METHOD_NOT_SUPPORTED */,
1162
+ `${method} requires [chainId, account, payload] params`
1163
+ );
1164
+ }
1165
+ return {
1166
+ chainId: params[0],
1167
+ account: params[1],
1168
+ payload: params[2]
1169
+ };
1170
+ }
1171
+ async function handleSigning(method, params) {
1172
+ const s = session.get();
1173
+ if (!s) {
1174
+ throw new DecaneError(
1175
+ 5001 /* NO_ACTIVE_SESSION */,
1176
+ "No active session. Call wallet_requestPermissions first."
1177
+ );
1178
+ }
1179
+ const { chainId, account, payload } = extractSigningContext(
1180
+ method,
1181
+ params
1182
+ );
1183
+ const chainType = getChainType(chainId);
1184
+ session.assertChainInScope(chainId);
1185
+ session.assertAccountInScope(chainId, account);
1186
+ if (method === "wallet_signTypedData" && chainType !== "evm") {
1187
+ throw new DecaneError(
1188
+ 5031 /* EVM_ONLY_METHOD */,
1189
+ "wallet_signTypedData is only supported on EVM chains"
1190
+ );
1191
+ }
1192
+ const wallet = registry.get.byId(s.walletId);
1193
+ if (!wallet) {
1194
+ throw new DecaneError(
1195
+ 5020 /* NO_WALLET_CONNECTED */,
1196
+ "Connected wallet not found"
1197
+ );
1198
+ }
1199
+ if (chainType === "evm") {
1200
+ return eip1193Request(
1201
+ wallet.evmProvider,
1202
+ method,
1203
+ payload,
1204
+ account
1205
+ );
1206
+ } else {
1207
+ return walletStandardRequest(
1208
+ wallet.solanaProvider,
1209
+ method,
1210
+ payload,
1211
+ account
1212
+ );
1213
+ }
1214
+ }
1215
+ return { request };
1216
+ }
1217
+
1218
+ // src/provider.ts
1219
+ function createProvider(opts) {
1220
+ const { config, registry, session, chainStore, router, emitter } = opts;
1221
+ let _connectedWallet = null;
1222
+ let _activeChain = config.defaultChain ?? null;
1223
+ function tryRestoreWallet(w) {
1224
+ const s = session.get();
1225
+ if (!s || _connectedWallet) return;
1226
+ if (w.id !== s.walletId) return;
1227
+ _connectedWallet = w;
1228
+ const granted = Object.keys(s.grantedScopes);
1229
+ if (!_activeChain || !granted.includes(_activeChain)) {
1230
+ _activeChain = granted[0] ?? null;
1231
+ }
1232
+ emitter.emit("connect", w);
1233
+ }
1234
+ emitter.on("walletRegistered", (w) => tryRestoreWallet(w));
1235
+ emitter.on("walletUpdated", (w) => {
1236
+ const wallet = w;
1237
+ if (_connectedWallet?.id === wallet.id) {
1238
+ _connectedWallet = wallet;
1239
+ } else {
1240
+ tryRestoreWallet(wallet);
1241
+ }
1242
+ });
1243
+ const provider = {
1244
+ // ── CAIP-25 request gateway ─────────────────────────────────────────────
1245
+ request(args) {
1246
+ return router.request(args);
1247
+ },
1248
+ on(event, handler) {
1249
+ emitter.on(event, handler);
1250
+ },
1251
+ off(event, handler) {
1252
+ emitter.off(event, handler);
1253
+ },
1254
+ // ── Registry views ──────────────────────────────────────────────────────
1255
+ get wallets() {
1256
+ return registry.get.all();
1257
+ },
1258
+ get evmWallets() {
1259
+ return registry.get.evm();
1260
+ },
1261
+ get solanaWallets() {
1262
+ return registry.get.solana();
1263
+ },
1264
+ get multiChainWallets() {
1265
+ return registry.get.multiChain();
1266
+ },
1267
+ // ── Connection ──────────────────────────────────────────────────────────
1268
+ async connect(wallet, preferredChain) {
1269
+ if (session.get()) {
1270
+ session.clear();
1271
+ emitter.emit("disconnect");
1272
+ }
1273
+ _connectedWallet = wallet;
1274
+ const support = wallet.chainSupport;
1275
+ if (support.includes("evm") && preferredChain !== "solana") {
1276
+ _activeChain = config.defaultChain?.startsWith("eip155:") ? config.defaultChain : "eip155:1";
1277
+ } else {
1278
+ _activeChain = "solana:mainnet";
1279
+ }
1280
+ const hasEvm = support.includes("evm") && preferredChain !== "solana";
1281
+ const hasSol = support.includes("solana") && preferredChain !== "evm";
1282
+ const required = {};
1283
+ const optional = {};
1284
+ if (hasEvm) {
1285
+ required[_activeChain ?? "eip155:1"] = {
1286
+ methods: ["wallet_sendTransaction", "wallet_signMessage", "wallet_signTypedData"],
1287
+ accounts: [],
1288
+ events: ["chainChanged", "accountsChanged"]
1289
+ };
1290
+ }
1291
+ if (hasSol) {
1292
+ const solChain = "solana:mainnet";
1293
+ const scope = {
1294
+ methods: ["wallet_sendTransaction", "wallet_signMessage"],
1295
+ accounts: [],
1296
+ events: []
1297
+ };
1298
+ if (hasEvm) {
1299
+ optional[solChain] = scope;
1300
+ } else {
1301
+ required[solChain] = scope;
1302
+ _activeChain = solChain;
1303
+ }
1304
+ }
1305
+ await router.request({
1306
+ method: "wallet_requestPermissions",
1307
+ params: [{ requiredScopes: required, optionalScopes: optional }, wallet.id]
1308
+ });
1309
+ const s = session.get();
1310
+ if (s) {
1311
+ const granted = Object.keys(s.grantedScopes);
1312
+ if (_activeChain && !granted.includes(_activeChain)) {
1313
+ _activeChain = granted[0] ?? null;
1314
+ }
1315
+ }
1316
+ emitter.emit("connect", wallet);
1317
+ },
1318
+ async disconnect() {
1319
+ session.clear();
1320
+ _connectedWallet = null;
1321
+ _activeChain = null;
1322
+ emitter.emit("disconnect");
1323
+ },
1324
+ // ── Custom chain management ─────────────────────────────────────────────
1325
+ addChain(chain) {
1326
+ if (!validateCustomChain(chain)) {
1327
+ throw new DecaneError(
1328
+ 5012 /* INVALID_CHAIN_CONFIG */,
1329
+ "Invalid chain descriptor"
1330
+ );
1331
+ }
1332
+ chainStore.add(chain);
1333
+ if (_connectedWallet?.evmProvider && chain.type === "evm") {
1334
+ addEthereumChain(_connectedWallet.evmProvider, chain).catch(() => {
1335
+ });
1336
+ }
1337
+ emitter.emit("chainAdded", chain);
1338
+ },
1339
+ removeChain(chainId) {
1340
+ chainStore.remove(chainId);
1341
+ const s = session.get();
1342
+ if (s?.grantedScopes[chainId]) {
1343
+ delete s.grantedScopes[chainId];
1344
+ session.set(s);
1345
+ }
1346
+ if (_activeChain === chainId) {
1347
+ const remaining = Object.keys(session.get()?.grantedScopes ?? {});
1348
+ _activeChain = remaining[0] ?? null;
1349
+ }
1350
+ emitter.emit("chainRemoved", chainId);
1351
+ },
1352
+ getChain(chainId) {
1353
+ return chainStore.get(chainId);
1354
+ },
1355
+ get chains() {
1356
+ return chainStore.getAll();
1357
+ },
1358
+ // ── State ───────────────────────────────────────────────────────────────
1359
+ get connectedWallet() {
1360
+ return _connectedWallet;
1361
+ },
1362
+ get activeSession() {
1363
+ return session.get();
1364
+ },
1365
+ get activeChain() {
1366
+ return _activeChain;
1367
+ }
1368
+ };
1369
+ return provider;
1370
+ }
1371
+
1372
+ // src/evm/discovery.ts
1373
+ function startEvmDiscovery(registry) {
1374
+ if (typeof window === "undefined") return;
1375
+ const seenUuids = /* @__PURE__ */ new Set();
1376
+ window.addEventListener(
1377
+ "eip6963:announceProvider",
1378
+ (event) => {
1379
+ const e = event;
1380
+ const { info, provider } = e.detail;
1381
+ if (seenUuids.has(info.uuid)) return;
1382
+ seenUuids.add(info.uuid);
1383
+ registry.registerOrMerge({
1384
+ chain: "evm",
1385
+ name: info.name,
1386
+ icon: info.icon,
1387
+ rdns: info.rdns,
1388
+ uuid: info.uuid,
1389
+ provider
1390
+ });
1391
+ }
1392
+ );
1393
+ window.dispatchEvent(new CustomEvent("eip6963:requestProvider"));
1394
+ setTimeout(
1395
+ () => window.dispatchEvent(new CustomEvent("eip6963:requestProvider")),
1396
+ 100
1397
+ );
1398
+ }
1399
+
1400
+ // src/solana/discovery.ts
1401
+ var import_app = require("@wallet-standard/app");
1402
+ function startSolanaDiscovery(registry) {
1403
+ if (typeof window === "undefined") return;
1404
+ const { get, on } = (0, import_app.getWallets)();
1405
+ function register(wallet) {
1406
+ const required = [
1407
+ "standard:connect",
1408
+ "solana:signTransaction",
1409
+ "solana:signMessage"
1410
+ ];
1411
+ if (!required.every((f) => f in wallet.features)) return;
1412
+ registry.registerOrMerge({
1413
+ chain: "solana",
1414
+ name: wallet.name,
1415
+ icon: wallet.icon,
1416
+ rdns: wallet.rdns ?? void 0,
1417
+ provider: wallet
1418
+ });
1419
+ }
1420
+ get().forEach(register);
1421
+ on(
1422
+ "register",
1423
+ (...wallets) => wallets.forEach(register)
1424
+ );
1425
+ on(
1426
+ "unregister",
1427
+ (...wallets) => wallets.forEach((w) => registry.unregister(w))
1428
+ );
1429
+ }
1430
+
1431
+ // src/factory.ts
1432
+ function createDecane(config = {}) {
1433
+ const emitter = createEmitter();
1434
+ const registry = createRegistry(emitter);
1435
+ const session = createSessionManager();
1436
+ const builtIn = config.supportedChainIds ? BUILT_IN_CHAINS.filter((c) => config.supportedChainIds.includes(c.id)) : BUILT_IN_CHAINS;
1437
+ const chainStore = createChainStore([
1438
+ ...builtIn,
1439
+ ...config.chains ?? []
1440
+ ]);
1441
+ const router = createRouter({ registry, session, chainStore });
1442
+ startEvmDiscovery(registry);
1443
+ startSolanaDiscovery(registry);
1444
+ return createProvider({ config, registry, session, chainStore, router, emitter });
1445
+ }
1446
+
1447
+ // src/ui/WalletSelector.tsx
1448
+ var import_react2 = __toESM(require("react"), 1);
1449
+ var import_react_dom = require("react-dom");
1450
+
1451
+ // src/ui/styles.ts
1452
+ var tokens = {
1453
+ // ── Gold palette ──────────────────────────────────────────────────────────
1454
+ gold: {
1455
+ 50: "#FFFDF0",
1456
+ 100: "#FFF8D6",
1457
+ 200: "#FFEF99",
1458
+ 300: "#FFE04D",
1459
+ 400: "#F5C800",
1460
+ // primary gold — buttons, accents
1461
+ 500: "#D4A800",
1462
+ // darker gold — hover states
1463
+ 600: "#A37F00",
1464
+ // deep gold — borders, active
1465
+ 700: "#7A5E00",
1466
+ 800: "#4D3B00",
1467
+ 900: "#261D00"
1468
+ },
1469
+ // ── Black / dark palette ──────────────────────────────────────────────────
1470
+ black: {
1471
+ 0: "#FFFFFF",
1472
+ 50: "#F9F9F7",
1473
+ 100: "#F0EFEB",
1474
+ 200: "#DDDCDA",
1475
+ 300: "#BDBBB8",
1476
+ 400: "#8A8884",
1477
+ 500: "#5C5A57",
1478
+ 600: "#3D3C39",
1479
+ 700: "#2A2927",
1480
+ 800: "#1A1917",
1481
+ 900: "#0D0D0B",
1482
+ 950: "#070706"
1483
+ },
1484
+ // ── Semantic tokens — light mode ──────────────────────────────────────────
1485
+ light: {
1486
+ bg: "#FFFFFF",
1487
+ bgOverlay: "rgba(0, 0, 0, 0.55)",
1488
+ surface: "#F9F9F7",
1489
+ surfaceHover: "#F0EFEB",
1490
+ border: "#DDDCDA",
1491
+ borderAccent: "#F5C800",
1492
+ text: "#0D0D0B",
1493
+ textSecondary: "#5C5A57",
1494
+ textMuted: "#8A8884",
1495
+ accent: "#F5C800",
1496
+ accentHover: "#D4A800",
1497
+ accentText: "#0D0D0B",
1498
+ badgeEvm: "#1A1917",
1499
+ badgeEvmText: "#F5C800",
1500
+ badgeSolana: "#F5C800",
1501
+ badgeSolanaText: "#0D0D0B",
1502
+ danger: "#CC3300"
1503
+ },
1504
+ // ── Semantic tokens — dark mode ───────────────────────────────────────────
1505
+ dark: {
1506
+ bg: "#0D0D0B",
1507
+ bgOverlay: "rgba(0, 0, 0, 0.75)",
1508
+ surface: "#1A1917",
1509
+ surfaceHover: "#2A2927",
1510
+ border: "#3D3C39",
1511
+ borderAccent: "#F5C800",
1512
+ text: "#F9F9F7",
1513
+ textSecondary: "#BDBBB8",
1514
+ textMuted: "#8A8884",
1515
+ accent: "#F5C800",
1516
+ accentHover: "#FFE04D",
1517
+ accentText: "#0D0D0B",
1518
+ badgeEvm: "#F5C800",
1519
+ badgeEvmText: "#0D0D0B",
1520
+ badgeSolana: "#1A1917",
1521
+ badgeSolanaText: "#F5C800",
1522
+ danger: "#FF5533"
1523
+ }
1524
+ };
1525
+ var FONT_SANS = "'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
1526
+ var FONT_MONO = "'JetBrains Mono', 'Fira Code', ui-monospace, monospace";
1527
+ var CSS_VARS = {
1528
+ light: `
1529
+ --dc-font-sans: ${FONT_SANS};
1530
+ --dc-font-mono: ${FONT_MONO};
1531
+ --dc-bg: ${tokens.light.bg};
1532
+ --dc-bg-overlay: ${tokens.light.bgOverlay};
1533
+ --dc-surface: ${tokens.light.surface};
1534
+ --dc-surface-hover: ${tokens.light.surfaceHover};
1535
+ --dc-border: ${tokens.light.border};
1536
+ --dc-border-accent: ${tokens.light.borderAccent};
1537
+ --dc-text: ${tokens.light.text};
1538
+ --dc-text-secondary: ${tokens.light.textSecondary};
1539
+ --dc-text-muted: ${tokens.light.textMuted};
1540
+ --dc-accent: ${tokens.light.accent};
1541
+ --dc-accent-hover: ${tokens.light.accentHover};
1542
+ --dc-accent-text: ${tokens.light.accentText};
1543
+ --dc-badge-evm: ${tokens.light.badgeEvm};
1544
+ --dc-badge-evm-text: ${tokens.light.badgeEvmText};
1545
+ --dc-badge-sol: ${tokens.light.badgeSolana};
1546
+ --dc-badge-sol-text: ${tokens.light.badgeSolanaText};
1547
+ --dc-danger: ${tokens.light.danger};
1548
+ `,
1549
+ dark: `
1550
+ --dc-font-sans: ${FONT_SANS};
1551
+ --dc-font-mono: ${FONT_MONO};
1552
+ --dc-bg: ${tokens.dark.bg};
1553
+ --dc-bg-overlay: ${tokens.dark.bgOverlay};
1554
+ --dc-surface: ${tokens.dark.surface};
1555
+ --dc-surface-hover: ${tokens.dark.surfaceHover};
1556
+ --dc-border: ${tokens.dark.border};
1557
+ --dc-border-accent: ${tokens.dark.borderAccent};
1558
+ --dc-text: ${tokens.dark.text};
1559
+ --dc-text-secondary: ${tokens.dark.textSecondary};
1560
+ --dc-text-muted: ${tokens.dark.textMuted};
1561
+ --dc-accent: ${tokens.dark.accent};
1562
+ --dc-accent-hover: ${tokens.dark.accentHover};
1563
+ --dc-accent-text: ${tokens.dark.accentText};
1564
+ --dc-badge-evm: ${tokens.dark.badgeEvm};
1565
+ --dc-badge-evm-text: ${tokens.dark.badgeEvmText};
1566
+ --dc-badge-sol: ${tokens.dark.badgeSolana};
1567
+ --dc-badge-sol-text: ${tokens.dark.badgeSolanaText};
1568
+ --dc-danger: ${tokens.dark.danger};
1569
+ `
1570
+ };
1571
+
1572
+ // src/ui/icons.tsx
1573
+ var import_react = __toESM(require("react"), 1);
1574
+ function WalletIcon({ src, name, size = 36 }) {
1575
+ if (src) {
1576
+ return /* @__PURE__ */ import_react.default.createElement(
1577
+ "img",
1578
+ {
1579
+ src,
1580
+ alt: name,
1581
+ width: size,
1582
+ height: size,
1583
+ style: { borderRadius: size * 0.25, objectFit: "cover", flexShrink: 0 }
1584
+ }
1585
+ );
1586
+ }
1587
+ const initial = name.charAt(0).toUpperCase();
1588
+ return /* @__PURE__ */ import_react.default.createElement(
1589
+ "div",
1590
+ {
1591
+ style: {
1592
+ width: size,
1593
+ height: size,
1594
+ borderRadius: size * 0.25,
1595
+ background: "linear-gradient(135deg, var(--dc-surface-hover), var(--dc-surface-active, var(--dc-surface-hover)))",
1596
+ border: "1px solid var(--dc-border)",
1597
+ display: "flex",
1598
+ alignItems: "center",
1599
+ justifyContent: "center",
1600
+ fontSize: size * 0.38,
1601
+ fontWeight: 800,
1602
+ color: "var(--dc-accent)",
1603
+ flexShrink: 0,
1604
+ fontFamily: "var(--dc-font-sans)",
1605
+ letterSpacing: "-0.02em"
1606
+ }
1607
+ },
1608
+ initial
1609
+ );
1610
+ }
1611
+
1612
+ // src/ui/WalletSelector.tsx
1613
+ var FONT_URL = "https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap";
1614
+ function injectTokens(theme) {
1615
+ let resolved;
1616
+ if (theme === "auto") {
1617
+ resolved = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1618
+ } else {
1619
+ resolved = theme;
1620
+ }
1621
+ let styleEl = document.getElementById("decane-tokens");
1622
+ if (!styleEl) {
1623
+ styleEl = document.createElement("style");
1624
+ styleEl.id = "decane-tokens";
1625
+ document.head.appendChild(styleEl);
1626
+ }
1627
+ styleEl.textContent = `:root { ${CSS_VARS[resolved]} }`;
1628
+ }
1629
+ function injectFont() {
1630
+ if (document.getElementById("decane-font")) return;
1631
+ const link = document.createElement("link");
1632
+ link.id = "decane-font";
1633
+ link.rel = "stylesheet";
1634
+ link.href = FONT_URL;
1635
+ document.head.appendChild(link);
1636
+ }
1637
+ var badgeBase = {
1638
+ display: "inline-flex",
1639
+ alignItems: "center",
1640
+ padding: "3px 8px",
1641
+ borderRadius: 20,
1642
+ fontSize: 10,
1643
+ fontWeight: 700,
1644
+ letterSpacing: "0.04em",
1645
+ textTransform: "uppercase"
1646
+ };
1647
+ function ChainBadges({ chainSupport }) {
1648
+ const hasEvm = chainSupport.includes("evm");
1649
+ const hasSol = chainSupport.includes("solana");
1650
+ return /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4 } }, hasEvm && /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"), hasSol && /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM"));
1651
+ }
1652
+ function WalletRow({ wallet, onClick }) {
1653
+ const [hovered, setHovered] = (0, import_react2.useState)(false);
1654
+ const [focused, setFocused] = (0, import_react2.useState)(false);
1655
+ return /* @__PURE__ */ import_react2.default.createElement(
1656
+ "button",
1657
+ {
1658
+ onClick,
1659
+ onMouseEnter: () => setHovered(true),
1660
+ onMouseLeave: () => setHovered(false),
1661
+ onFocus: () => setFocused(true),
1662
+ onBlur: () => setFocused(false),
1663
+ style: {
1664
+ display: "flex",
1665
+ alignItems: "center",
1666
+ gap: 12,
1667
+ width: "100%",
1668
+ padding: "11px 14px",
1669
+ background: hovered ? "var(--dc-surface-hover)" : "transparent",
1670
+ border: focused ? "1px solid var(--dc-border-accent)" : "1px solid transparent",
1671
+ borderRadius: 10,
1672
+ cursor: "pointer",
1673
+ textAlign: "left",
1674
+ transition: "background 0.12s, border-color 0.12s",
1675
+ outline: "none",
1676
+ fontFamily: "inherit"
1677
+ }
1678
+ },
1679
+ /* @__PURE__ */ import_react2.default.createElement(WalletIcon, { src: wallet.icon || void 0, name: wallet.name, size: 38 }),
1680
+ /* @__PURE__ */ import_react2.default.createElement("span", { style: { flex: 1, fontSize: 14, fontWeight: 600, color: "var(--dc-text)", letterSpacing: "-0.01em" } }, wallet.name),
1681
+ /* @__PURE__ */ import_react2.default.createElement(ChainBadges, { chainSupport: wallet.chainSupport }),
1682
+ /* @__PURE__ */ import_react2.default.createElement(
1683
+ "svg",
1684
+ {
1685
+ width: "14",
1686
+ height: "14",
1687
+ viewBox: "0 0 14 14",
1688
+ fill: "none",
1689
+ style: { color: hovered ? "var(--dc-text-secondary)" : "var(--dc-text-muted)", flexShrink: 0, transition: "color 0.12s" }
1690
+ },
1691
+ /* @__PURE__ */ import_react2.default.createElement("path", { d: "M5 2.5L9.5 7L5 11.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1692
+ )
1693
+ );
1694
+ }
1695
+ function FilterTab({ label, active, onClick }) {
1696
+ const [hovered, setHovered] = (0, import_react2.useState)(false);
1697
+ return /* @__PURE__ */ import_react2.default.createElement(
1698
+ "button",
1699
+ {
1700
+ onClick,
1701
+ onMouseEnter: () => setHovered(true),
1702
+ onMouseLeave: () => setHovered(false),
1703
+ style: {
1704
+ flex: 1,
1705
+ padding: "6px 8px",
1706
+ borderRadius: 8,
1707
+ border: active ? "1px solid var(--dc-border-accent)" : "1px solid transparent",
1708
+ background: active ? "rgba(245,200,0,0.1)" : hovered ? "var(--dc-surface-hover)" : "transparent",
1709
+ color: active ? "var(--dc-accent)" : "var(--dc-text-muted)",
1710
+ fontSize: 11,
1711
+ fontWeight: 700,
1712
+ letterSpacing: "0.04em",
1713
+ textTransform: "uppercase",
1714
+ cursor: "pointer",
1715
+ transition: "all 0.12s",
1716
+ fontFamily: "inherit",
1717
+ outline: "none"
1718
+ }
1719
+ },
1720
+ label
1721
+ );
1722
+ }
1723
+ function ChainOption({ label, description, badges, onClick }) {
1724
+ const [hovered, setHovered] = (0, import_react2.useState)(false);
1725
+ return /* @__PURE__ */ import_react2.default.createElement(
1726
+ "button",
1727
+ {
1728
+ onClick,
1729
+ onMouseEnter: () => setHovered(true),
1730
+ onMouseLeave: () => setHovered(false),
1731
+ style: {
1732
+ display: "flex",
1733
+ flexDirection: "column",
1734
+ alignItems: "flex-start",
1735
+ gap: 6,
1736
+ width: "100%",
1737
+ padding: "14px 16px",
1738
+ background: hovered ? "var(--dc-surface-hover)" : "var(--dc-surface)",
1739
+ border: hovered ? "1px solid var(--dc-border-accent)" : "1px solid var(--dc-border)",
1740
+ borderRadius: 12,
1741
+ cursor: "pointer",
1742
+ textAlign: "left",
1743
+ transition: "all 0.12s",
1744
+ fontFamily: "inherit",
1745
+ outline: "none"
1746
+ }
1747
+ },
1748
+ badges,
1749
+ /* @__PURE__ */ import_react2.default.createElement("span", { style: { fontSize: 13, fontWeight: 700, color: "var(--dc-text)" } }, label),
1750
+ /* @__PURE__ */ import_react2.default.createElement("span", { style: { fontSize: 11, color: "var(--dc-text-muted)", lineHeight: 1.4 } }, description)
1751
+ );
1752
+ }
1753
+ function WalletSelector({
1754
+ provider,
1755
+ open,
1756
+ onClose,
1757
+ onConnect,
1758
+ theme = "auto",
1759
+ networks = "all"
1760
+ }) {
1761
+ const [search, setSearch] = (0, import_react2.useState)("");
1762
+ const [filter, setFilter] = (0, import_react2.useState)("all");
1763
+ const [pendingWallet, setPendingWallet] = (0, import_react2.useState)(null);
1764
+ (0, import_react2.useEffect)(() => {
1765
+ if (!open) return;
1766
+ injectFont();
1767
+ injectTokens(theme);
1768
+ if (theme !== "auto") return;
1769
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
1770
+ const handler = () => injectTokens("auto");
1771
+ mq.addEventListener("change", handler);
1772
+ return () => mq.removeEventListener("change", handler);
1773
+ }, [open, theme]);
1774
+ (0, import_react2.useEffect)(() => {
1775
+ if (!open) {
1776
+ setSearch("");
1777
+ setFilter("all");
1778
+ setPendingWallet(null);
1779
+ return;
1780
+ }
1781
+ return () => {
1782
+ document.getElementById("decane-tokens")?.remove();
1783
+ };
1784
+ }, [open]);
1785
+ const handleKey = (0, import_react2.useCallback)(
1786
+ (e) => {
1787
+ if (e.key === "Escape") {
1788
+ if (pendingWallet) {
1789
+ setPendingWallet(null);
1790
+ } else {
1791
+ onClose();
1792
+ }
1793
+ }
1794
+ },
1795
+ [onClose, pendingWallet]
1796
+ );
1797
+ (0, import_react2.useEffect)(() => {
1798
+ if (!open) return;
1799
+ document.addEventListener("keydown", handleKey);
1800
+ return () => document.removeEventListener("keydown", handleKey);
1801
+ }, [open, handleKey]);
1802
+ if (!open) return null;
1803
+ const q = search.toLowerCase();
1804
+ const networkWallets = provider.wallets.filter((w) => {
1805
+ const cs = w.chainSupport;
1806
+ if (networks === "evm") return cs.includes("evm");
1807
+ if (networks === "solana") return cs.includes("solana");
1808
+ return true;
1809
+ });
1810
+ const baseWallets = filter === "evm" ? networkWallets.filter((w) => w.chainSupport.includes("evm")) : filter === "solana" ? networkWallets.filter((w) => w.chainSupport.includes("solana")) : networkWallets;
1811
+ const filtered = q ? baseWallets.filter((w) => w.name.toLowerCase().includes(q)) : baseWallets;
1812
+ function handleWalletClick(wallet) {
1813
+ const cs = wallet.chainSupport;
1814
+ const isMulti = cs.includes("evm") && cs.includes("solana");
1815
+ if (isMulti && networks === "all") {
1816
+ setPendingWallet(wallet);
1817
+ } else {
1818
+ const preference = networks === "evm" ? "evm" : networks === "solana" ? "solana" : void 0;
1819
+ onConnect(wallet, preference);
1820
+ onClose();
1821
+ }
1822
+ }
1823
+ function handleChainChoice(preference) {
1824
+ if (!pendingWallet) return;
1825
+ onConnect(pendingWallet, preference);
1826
+ onClose();
1827
+ }
1828
+ const modal = /* @__PURE__ */ import_react2.default.createElement(
1829
+ "div",
1830
+ {
1831
+ role: "dialog",
1832
+ "aria-modal": "true",
1833
+ "aria-label": "Connect wallet",
1834
+ style: {
1835
+ position: "fixed",
1836
+ inset: 0,
1837
+ zIndex: 9999,
1838
+ display: "flex",
1839
+ alignItems: "center",
1840
+ justifyContent: "center",
1841
+ padding: "16px",
1842
+ fontFamily: "var(--dc-font-sans)"
1843
+ }
1844
+ },
1845
+ /* @__PURE__ */ import_react2.default.createElement(
1846
+ "div",
1847
+ {
1848
+ onClick: () => {
1849
+ if (pendingWallet) {
1850
+ setPendingWallet(null);
1851
+ } else {
1852
+ onClose();
1853
+ }
1854
+ },
1855
+ style: {
1856
+ position: "absolute",
1857
+ inset: 0,
1858
+ background: "var(--dc-bg-overlay)",
1859
+ backdropFilter: "blur(8px)",
1860
+ WebkitBackdropFilter: "blur(8px)"
1861
+ }
1862
+ }
1863
+ ),
1864
+ /* @__PURE__ */ import_react2.default.createElement(
1865
+ "div",
1866
+ {
1867
+ style: {
1868
+ position: "relative",
1869
+ background: "var(--dc-bg)",
1870
+ border: "1px solid var(--dc-border)",
1871
+ borderRadius: 20,
1872
+ width: "100%",
1873
+ maxWidth: 400,
1874
+ maxHeight: "85vh",
1875
+ display: "flex",
1876
+ flexDirection: "column",
1877
+ boxShadow: "0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)",
1878
+ overflow: "hidden"
1879
+ }
1880
+ },
1881
+ /* @__PURE__ */ import_react2.default.createElement(
1882
+ "div",
1883
+ {
1884
+ style: {
1885
+ height: 2,
1886
+ background: "linear-gradient(90deg, transparent, var(--dc-accent) 30%, var(--dc-accent) 70%, transparent)"
1887
+ }
1888
+ }
1889
+ ),
1890
+ pendingWallet ? (
1891
+ /* ── Chain picker step ───────────────────────────────────────── */
1892
+ /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "18px 20px 16px", display: "flex", alignItems: "center", gap: 10 } }, /* @__PURE__ */ import_react2.default.createElement(
1893
+ "button",
1894
+ {
1895
+ onClick: () => setPendingWallet(null),
1896
+ "aria-label": "Back",
1897
+ style: {
1898
+ background: "var(--dc-surface)",
1899
+ border: "1px solid var(--dc-border)",
1900
+ borderRadius: 8,
1901
+ width: 28,
1902
+ height: 28,
1903
+ display: "flex",
1904
+ alignItems: "center",
1905
+ justifyContent: "center",
1906
+ cursor: "pointer",
1907
+ color: "var(--dc-text-muted)",
1908
+ flexShrink: 0,
1909
+ fontFamily: "inherit",
1910
+ padding: 0
1911
+ }
1912
+ },
1913
+ /* @__PURE__ */ import_react2.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" }, /* @__PURE__ */ import_react2.default.createElement("path", { d: "M7.5 2L3 6l4.5 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }))
1914
+ ), /* @__PURE__ */ import_react2.default.createElement("h2", { style: { margin: 0, fontSize: 16, fontWeight: 800, color: "var(--dc-text)", letterSpacing: "-0.02em" } }, "Choose networks"), /* @__PURE__ */ import_react2.default.createElement(
1915
+ "button",
1916
+ {
1917
+ onClick: onClose,
1918
+ "aria-label": "Close",
1919
+ style: {
1920
+ marginLeft: "auto",
1921
+ background: "var(--dc-surface)",
1922
+ border: "1px solid var(--dc-border)",
1923
+ borderRadius: 8,
1924
+ width: 28,
1925
+ height: 28,
1926
+ display: "flex",
1927
+ alignItems: "center",
1928
+ justifyContent: "center",
1929
+ cursor: "pointer",
1930
+ color: "var(--dc-text-muted)",
1931
+ flexShrink: 0,
1932
+ fontFamily: "inherit",
1933
+ padding: 0
1934
+ }
1935
+ },
1936
+ /* @__PURE__ */ import_react2.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" }, /* @__PURE__ */ import_react2.default.createElement("path", { d: "M1.5 1.5L10.5 10.5M10.5 1.5L1.5 10.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }))
1937
+ )), /* @__PURE__ */ import_react2.default.createElement(
1938
+ "div",
1939
+ {
1940
+ style: {
1941
+ margin: "0 20px 16px",
1942
+ padding: "12px 14px",
1943
+ background: "var(--dc-surface)",
1944
+ border: "1px solid var(--dc-border)",
1945
+ borderRadius: 12,
1946
+ display: "flex",
1947
+ alignItems: "center",
1948
+ gap: 12
1949
+ }
1950
+ },
1951
+ /* @__PURE__ */ import_react2.default.createElement(WalletIcon, { src: pendingWallet.icon || void 0, name: pendingWallet.name, size: 36 }),
1952
+ /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("div", { style: { fontSize: 14, fontWeight: 700, color: "var(--dc-text)" } }, pendingWallet.name), /* @__PURE__ */ import_react2.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 2 } }, "Multi-chain wallet detected"))
1953
+ ), /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "0 12px 20px", display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement(
1954
+ ChainOption,
1955
+ {
1956
+ label: "EVM networks",
1957
+ description: "Connect your Ethereum-compatible address only",
1958
+ badges: /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"),
1959
+ onClick: () => handleChainChoice("evm")
1960
+ }
1961
+ ), /* @__PURE__ */ import_react2.default.createElement(
1962
+ ChainOption,
1963
+ {
1964
+ label: "Solana network",
1965
+ description: "Connect your Solana address only",
1966
+ badges: /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM"),
1967
+ onClick: () => handleChainChoice("solana")
1968
+ }
1969
+ ), /* @__PURE__ */ import_react2.default.createElement(
1970
+ ChainOption,
1971
+ {
1972
+ label: "Both networks",
1973
+ description: "Connect EVM and Solana addresses together",
1974
+ badges: /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4 } }, /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-evm)", color: "var(--dc-badge-evm-text)" } }, "EVM"), /* @__PURE__ */ import_react2.default.createElement("span", { style: { ...badgeBase, background: "var(--dc-badge-sol)", color: "var(--dc-badge-sol-text)", border: "1px solid var(--dc-border)" } }, "SVM")),
1975
+ onClick: () => handleChainChoice(void 0)
1976
+ }
1977
+ )))
1978
+ ) : (
1979
+ /* ── Wallet list step ────────────────────────────────────────── */
1980
+ /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "18px 20px 0" } }, /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", marginBottom: 14 } }, /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("h2", { style: { margin: 0, fontSize: 17, fontWeight: 800, color: "var(--dc-text)", letterSpacing: "-0.02em", lineHeight: 1.2 } }, "Connect wallet"), networkWallets.length > 0 && /* @__PURE__ */ import_react2.default.createElement("p", { style: { margin: "3px 0 0", fontSize: 12, color: "var(--dc-text-muted)" } }, networkWallets.length, " wallet", networkWallets.length !== 1 ? "s" : "", " detected")), /* @__PURE__ */ import_react2.default.createElement(
1981
+ "button",
1982
+ {
1983
+ onClick: onClose,
1984
+ "aria-label": "Close",
1985
+ style: {
1986
+ background: "var(--dc-surface)",
1987
+ border: "1px solid var(--dc-border)",
1988
+ cursor: "pointer",
1989
+ padding: 0,
1990
+ width: 28,
1991
+ height: 28,
1992
+ borderRadius: 8,
1993
+ display: "flex",
1994
+ alignItems: "center",
1995
+ justifyContent: "center",
1996
+ color: "var(--dc-text-muted)",
1997
+ flexShrink: 0,
1998
+ transition: "background 0.12s, color 0.12s",
1999
+ fontFamily: "inherit"
2000
+ },
2001
+ onMouseEnter: (e) => {
2002
+ e.currentTarget.style.background = "var(--dc-surface-hover)";
2003
+ e.currentTarget.style.color = "var(--dc-text)";
2004
+ },
2005
+ onMouseLeave: (e) => {
2006
+ e.currentTarget.style.background = "var(--dc-surface)";
2007
+ e.currentTarget.style.color = "var(--dc-text-muted)";
2008
+ }
2009
+ },
2010
+ /* @__PURE__ */ import_react2.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" }, /* @__PURE__ */ import_react2.default.createElement("path", { d: "M1.5 1.5L10.5 10.5M10.5 1.5L1.5 10.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }))
2011
+ )), /* @__PURE__ */ import_react2.default.createElement("div", { style: { position: "relative", marginBottom: 10 } }, /* @__PURE__ */ import_react2.default.createElement(
2012
+ "svg",
2013
+ {
2014
+ width: "14",
2015
+ height: "14",
2016
+ viewBox: "0 0 14 14",
2017
+ fill: "none",
2018
+ style: { position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--dc-text-muted)", pointerEvents: "none" }
2019
+ },
2020
+ /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "6", cy: "6", r: "4", stroke: "currentColor", strokeWidth: "1.4" }),
2021
+ /* @__PURE__ */ import_react2.default.createElement("path", { d: "M9.5 9.5L12 12", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" })
2022
+ ), /* @__PURE__ */ import_react2.default.createElement(
2023
+ "input",
2024
+ {
2025
+ type: "text",
2026
+ placeholder: "Search wallets\u2026",
2027
+ value: search,
2028
+ onChange: (e) => setSearch(e.target.value),
2029
+ style: {
2030
+ width: "100%",
2031
+ background: "var(--dc-surface)",
2032
+ border: "1px solid var(--dc-border)",
2033
+ borderRadius: 10,
2034
+ color: "var(--dc-text)",
2035
+ fontSize: 13,
2036
+ padding: "8px 12px 8px 32px",
2037
+ outline: "none",
2038
+ fontFamily: "var(--dc-font-sans)",
2039
+ transition: "border-color 0.15s",
2040
+ boxSizing: "border-box"
2041
+ },
2042
+ onFocus: (e) => {
2043
+ e.currentTarget.style.borderColor = "var(--dc-border-accent)";
2044
+ },
2045
+ onBlur: (e) => {
2046
+ e.currentTarget.style.borderColor = "var(--dc-border)";
2047
+ }
2048
+ }
2049
+ )), networks === "all" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4, marginBottom: 10 } }, /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "All", active: filter === "all", onClick: () => setFilter("all") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "EVM", active: filter === "evm", onClick: () => setFilter("evm") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Solana", active: filter === "solana", onClick: () => setFilter("solana") }))), /* @__PURE__ */ import_react2.default.createElement("div", { style: { overflowY: "auto", flex: 1, padding: "0 12px 20px" } }, filtered.length > 0 ? /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((w) => /* @__PURE__ */ import_react2.default.createElement(WalletRow, { key: w.id, wallet: w, onClick: () => handleWalletClick(w) }))) : /* @__PURE__ */ import_react2.default.createElement("div", { style: { textAlign: "center", padding: "32px 16px", color: "var(--dc-text-muted)", fontSize: 13 } }, q ? `No wallets matching "${q}"` : "No wallets detected")), /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "10px 20px 14px", borderTop: "1px solid var(--dc-border)", textAlign: "center", fontSize: 11, color: "var(--dc-text-muted)" } }, "Don't see your wallet? Make sure it's installed and unlocked"))
2050
+ )
2051
+ )
2052
+ );
2053
+ return (0, import_react_dom.createPortal)(modal, document.body);
2054
+ }
2055
+
2056
+ // src/ui/context.tsx
2057
+ var import_react3 = __toESM(require("react"), 1);
2058
+ var DecaneContext = (0, import_react3.createContext)(null);
2059
+ function DecaneKit({ config, children }) {
2060
+ const ref = (0, import_react3.useRef)(null);
2061
+ if (!ref.current) {
2062
+ ref.current = createDecane(config);
2063
+ }
2064
+ const [selectorOpen, setSelectorOpen] = (0, import_react3.useState)(false);
2065
+ const [theme, setTheme] = (0, import_react3.useState)(config?.theme ?? "auto");
2066
+ const openSelector = (0, import_react3.useCallback)(() => setSelectorOpen(true), []);
2067
+ const closeSelector = (0, import_react3.useCallback)(() => setSelectorOpen(false), []);
2068
+ const handleConnect = (0, import_react3.useCallback)(
2069
+ (wallet, preference) => {
2070
+ ref.current.connect(wallet, preference).catch(console.error);
2071
+ },
2072
+ []
2073
+ );
2074
+ return /* @__PURE__ */ import_react3.default.createElement(
2075
+ DecaneContext.Provider,
2076
+ {
2077
+ value: { provider: ref.current, selectorOpen, openSelector, closeSelector, theme, setTheme }
2078
+ },
2079
+ children,
2080
+ /* @__PURE__ */ import_react3.default.createElement(
2081
+ WalletSelector,
2082
+ {
2083
+ provider: ref.current,
2084
+ open: selectorOpen,
2085
+ onClose: closeSelector,
2086
+ onConnect: handleConnect,
2087
+ theme,
2088
+ networks: config?.networks ?? "all"
2089
+ }
2090
+ )
2091
+ );
2092
+ }
2093
+ function useDecaneContext() {
2094
+ const ctx = (0, import_react3.useContext)(DecaneContext);
2095
+ if (!ctx) {
2096
+ throw new Error(
2097
+ "Decane hooks must be called inside <DecaneKit>. Wrap your app: <DecaneKit config={...}><App /></DecaneKit>"
2098
+ );
2099
+ }
2100
+ return ctx;
2101
+ }
2102
+
2103
+ // src/ui/hooks.ts
2104
+ var import_react4 = require("react");
2105
+ function useDecane() {
2106
+ const { provider, theme, setTheme } = useDecaneContext();
2107
+ const [, forceUpdate] = (0, import_react4.useState)(0);
2108
+ (0, import_react4.useEffect)(() => {
2109
+ const refresh = () => forceUpdate((n) => n + 1);
2110
+ const events = [
2111
+ "connect",
2112
+ "disconnect",
2113
+ "walletRegistered",
2114
+ "walletUpdated",
2115
+ "walletUnregistered",
2116
+ "chainAdded",
2117
+ "chainRemoved"
2118
+ ];
2119
+ events.forEach((e) => provider.on(e, refresh));
2120
+ return () => events.forEach((e) => provider.off(e, refresh));
2121
+ }, [provider]);
2122
+ return {
2123
+ provider,
2124
+ wallets: provider.wallets,
2125
+ evmWallets: provider.evmWallets,
2126
+ solanaWallets: provider.solanaWallets,
2127
+ multiChainWallets: provider.multiChainWallets,
2128
+ chains: provider.chains,
2129
+ connectedWallet: provider.connectedWallet,
2130
+ activeSession: provider.activeSession,
2131
+ activeChain: provider.activeChain,
2132
+ isConnected: !!provider.connectedWallet,
2133
+ theme,
2134
+ setTheme,
2135
+ connect: (wallet, preference) => provider.connect(wallet, preference),
2136
+ disconnect: () => provider.disconnect(),
2137
+ addChain: (chain) => provider.addChain(chain),
2138
+ removeChain: (chainId) => provider.removeChain(chainId)
2139
+ };
2140
+ }
2141
+ function useWalletSelector() {
2142
+ const { selectorOpen, openSelector, closeSelector } = useDecaneContext();
2143
+ return { isOpen: selectorOpen, open: openSelector, close: closeSelector };
2144
+ }
2145
+ function useChainSwitch() {
2146
+ const { provider } = useDecaneContext();
2147
+ const [, forceUpdate] = (0, import_react4.useState)(0);
2148
+ const [loading, setLoading] = (0, import_react4.useState)(false);
2149
+ const [error, setError] = (0, import_react4.useState)(null);
2150
+ (0, import_react4.useEffect)(() => {
2151
+ const refresh = () => forceUpdate((n) => n + 1);
2152
+ provider.on("connect", refresh);
2153
+ provider.on("disconnect", refresh);
2154
+ return () => {
2155
+ provider.off("connect", refresh);
2156
+ provider.off("disconnect", refresh);
2157
+ };
2158
+ }, [provider]);
2159
+ const switchChain = (0, import_react4.useCallback)(
2160
+ async (chainId) => {
2161
+ setLoading(true);
2162
+ setError(null);
2163
+ try {
2164
+ const existingScope = provider.activeSession?.grantedScopes[chainId];
2165
+ await provider.request({
2166
+ method: "wallet_requestPermissions",
2167
+ params: [
2168
+ {
2169
+ requiredScopes: {
2170
+ [chainId]: existingScope ?? {
2171
+ methods: ["wallet_sendTransaction", "wallet_signMessage"],
2172
+ accounts: [],
2173
+ events: []
2174
+ }
2175
+ },
2176
+ optionalScopes: {}
2177
+ }
2178
+ ]
2179
+ });
2180
+ forceUpdate((n) => n + 1);
2181
+ } catch (err) {
2182
+ const e = err instanceof DecaneError ? err : new DecaneError(5022 /* PROVIDER_ERROR */, String(err));
2183
+ setError(e);
2184
+ throw err;
2185
+ } finally {
2186
+ setLoading(false);
2187
+ }
2188
+ },
2189
+ [provider]
2190
+ );
2191
+ return {
2192
+ switchChain,
2193
+ loading,
2194
+ error,
2195
+ activeChain: provider.activeChain,
2196
+ grantedChains: provider.activeSession ? Object.keys(provider.activeSession.grantedScopes) : []
2197
+ };
2198
+ }
2199
+ function resolveScope(provider, chainId, account) {
2200
+ const chain = chainId ?? provider.activeChain;
2201
+ if (!chain) {
2202
+ throw new DecaneError(
2203
+ 5001 /* NO_ACTIVE_SESSION */,
2204
+ "No active chain \u2014 connect a wallet first."
2205
+ );
2206
+ }
2207
+ const scope = provider.activeSession?.grantedScopes[chain];
2208
+ const resolved = account ?? scope?.accounts[0]?.split(":").pop() ?? "";
2209
+ return { chain, account: resolved };
2210
+ }
2211
+ function useSignMessage() {
2212
+ const { provider } = useDecaneContext();
2213
+ const [signature, setSignature] = (0, import_react4.useState)(null);
2214
+ const [loading, setLoading] = (0, import_react4.useState)(false);
2215
+ const [error, setError] = (0, import_react4.useState)(null);
2216
+ const signMessage = (0, import_react4.useCallback)(
2217
+ async (message, options) => {
2218
+ const { chain, account } = resolveScope(
2219
+ provider,
2220
+ options?.chainId,
2221
+ options?.account
2222
+ );
2223
+ setLoading(true);
2224
+ setError(null);
2225
+ try {
2226
+ const sig = await provider.request({
2227
+ method: "wallet_signMessage",
2228
+ params: [chain, account, message]
2229
+ });
2230
+ setSignature(sig);
2231
+ return sig;
2232
+ } catch (err) {
2233
+ const e = err instanceof DecaneError ? err : new DecaneError(5022 /* PROVIDER_ERROR */, String(err));
2234
+ setError(e);
2235
+ throw err;
2236
+ } finally {
2237
+ setLoading(false);
2238
+ }
2239
+ },
2240
+ [provider]
2241
+ );
2242
+ const reset = (0, import_react4.useCallback)(() => {
2243
+ setSignature(null);
2244
+ setError(null);
2245
+ }, []);
2246
+ return { signMessage, signature, loading, error, reset };
2247
+ }
2248
+ function useSendTransaction() {
2249
+ const { provider } = useDecaneContext();
2250
+ const [txHash, setTxHash] = (0, import_react4.useState)(null);
2251
+ const [loading, setLoading] = (0, import_react4.useState)(false);
2252
+ const [error, setError] = (0, import_react4.useState)(null);
2253
+ const sendTransaction = (0, import_react4.useCallback)(
2254
+ async (tx, options) => {
2255
+ const { chain, account } = resolveScope(
2256
+ provider,
2257
+ options?.chainId,
2258
+ options?.from
2259
+ );
2260
+ const value = tx.value ? tx.value.startsWith("0x") ? tx.value : `0x${parseInt(tx.value, 10).toString(16)}` : "0x0";
2261
+ setLoading(true);
2262
+ setError(null);
2263
+ try {
2264
+ const hash = await provider.request({
2265
+ method: "wallet_sendTransaction",
2266
+ params: [chain, account, { ...tx, value }]
2267
+ });
2268
+ setTxHash(hash);
2269
+ return hash;
2270
+ } catch (err) {
2271
+ const e = err instanceof DecaneError ? err : new DecaneError(5022 /* PROVIDER_ERROR */, String(err));
2272
+ setError(e);
2273
+ throw err;
2274
+ } finally {
2275
+ setLoading(false);
2276
+ }
2277
+ },
2278
+ [provider]
2279
+ );
2280
+ const reset = (0, import_react4.useCallback)(() => {
2281
+ setTxHash(null);
2282
+ setError(null);
2283
+ }, []);
2284
+ return { sendTransaction, txHash, loading, error, reset };
2285
+ }
2286
+ function useSignTypedData() {
2287
+ const { provider } = useDecaneContext();
2288
+ const [signature, setSignature] = (0, import_react4.useState)(null);
2289
+ const [loading, setLoading] = (0, import_react4.useState)(false);
2290
+ const [error, setError] = (0, import_react4.useState)(null);
2291
+ const signTypedData = (0, import_react4.useCallback)(
2292
+ async (typedData, options) => {
2293
+ const { chain, account } = resolveScope(
2294
+ provider,
2295
+ options?.chainId,
2296
+ options?.account
2297
+ );
2298
+ setLoading(true);
2299
+ setError(null);
2300
+ try {
2301
+ const sig = await provider.request({
2302
+ method: "wallet_signTypedData",
2303
+ params: [chain, account, typedData]
2304
+ });
2305
+ setSignature(sig);
2306
+ return sig;
2307
+ } catch (err) {
2308
+ const e = err instanceof DecaneError ? err : new DecaneError(5022 /* PROVIDER_ERROR */, String(err));
2309
+ setError(e);
2310
+ throw err;
2311
+ } finally {
2312
+ setLoading(false);
2313
+ }
2314
+ },
2315
+ [provider]
2316
+ );
2317
+ const reset = (0, import_react4.useCallback)(() => {
2318
+ setSignature(null);
2319
+ setError(null);
2320
+ }, []);
2321
+ return { signTypedData, signature, loading, error, reset };
2322
+ }
2323
+ // Annotate the CommonJS export names for ESM import in node:
2324
+ 0 && (module.exports = {
2325
+ BUILT_IN_CHAINS,
2326
+ CHAINS,
2327
+ DecaneError,
2328
+ DecaneErrorCode,
2329
+ DecaneKit,
2330
+ WalletSelector,
2331
+ createDecane,
2332
+ useChainSwitch,
2333
+ useDecane,
2334
+ useSendTransaction,
2335
+ useSignMessage,
2336
+ useSignTypedData,
2337
+ useWalletSelector
2338
+ });
2339
+ //# sourceMappingURL=index.cjs.map