@enclave-hq/wallet-sdk 1.2.3 → 1.2.5

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.
@@ -1,10 +1,580 @@
1
- import React, { createContext, useState, useCallback, useEffect, useContext } from 'react';
2
- import EventEmitter from 'eventemitter3';
3
1
  import { ChainType as ChainType$1 } from '@enclave-hq/chain-utils';
4
- import { createWalletClient, http, createPublicClient, custom, isAddress, getAddress } from 'viem';
2
+ import React2, { createContext, useState, useCallback, useEffect, useContext, useRef } from 'react';
3
+ import EventEmitter from 'eventemitter3';
4
+ import { encodeFunctionData, createWalletClient, custom, createPublicClient, http, isAddress, getAddress } from 'viem';
5
5
  import { privateKeyToAccount } from 'viem/accounts';
6
+ import EthereumProvider from '@walletconnect/ethereum-provider';
7
+ import { WalletConnectChainID, WalletConnectWallet } from '@tronweb3/walletconnect-tron';
8
+ import QRCode from 'qrcode';
6
9
 
7
- // src/react/WalletContext.tsx
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __esm = (fn, res) => function __init() {
15
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
16
+ };
17
+ var __export = (target, all) => {
18
+ for (var name in all)
19
+ __defProp(target, name, { get: all[name], enumerable: true });
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (let key of __getOwnPropNames(from))
24
+ if (!__hasOwnProp.call(to, key) && key !== except)
25
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
26
+ }
27
+ return to;
28
+ };
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var ChainType;
31
+ var init_types = __esm({
32
+ "src/core/types.ts"() {
33
+ ChainType = ChainType$1;
34
+ }
35
+ });
36
+
37
+ // src/adapters/deep-link/providers/tokenpocket.ts
38
+ var tokenpocket_exports = {};
39
+ __export(tokenpocket_exports, {
40
+ TokenPocketDeepLinkProvider: () => TokenPocketDeepLinkProvider
41
+ });
42
+ var TokenPocketDeepLinkProvider;
43
+ var init_tokenpocket = __esm({
44
+ "src/adapters/deep-link/providers/tokenpocket.ts"() {
45
+ init_types();
46
+ TokenPocketDeepLinkProvider = class {
47
+ constructor(options) {
48
+ this.name = "TokenPocket";
49
+ this.icon = "https://tokenpocket.pro/icon.png";
50
+ this.supportedChainTypes = [ChainType.EVM, ChainType.TRON];
51
+ this.callbackUrl = options?.callbackUrl;
52
+ this.callbackSchema = options?.callbackSchema;
53
+ }
54
+ async isAvailable() {
55
+ if (typeof window === "undefined") {
56
+ return false;
57
+ }
58
+ const isTelegramMiniApp = !!(window.Telegram && window.Telegram.WebApp);
59
+ if (isTelegramMiniApp) {
60
+ return true;
61
+ }
62
+ const isMobile = /Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
63
+ navigator.userAgent
64
+ );
65
+ return isMobile;
66
+ }
67
+ /**
68
+ * Generate unique actionId
69
+ */
70
+ generateActionId() {
71
+ return `web-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
72
+ }
73
+ /**
74
+ * Get callback configuration
75
+ */
76
+ getCallbackConfig() {
77
+ if (this.callbackSchema) {
78
+ return { callbackSchema: this.callbackSchema };
79
+ }
80
+ if (this.callbackUrl) {
81
+ return { callbackUrl: this.callbackUrl };
82
+ }
83
+ if (typeof window !== "undefined" && window.location) {
84
+ return {
85
+ callbackSchema: `${window.location.protocol}//${window.location.host}${window.location.pathname}`
86
+ };
87
+ }
88
+ return {};
89
+ }
90
+ /**
91
+ * Get blockchain configuration based on chain type
92
+ */
93
+ getBlockchainConfig(chainId, chainType) {
94
+ if (chainType === ChainType.TRON) {
95
+ return {
96
+ chainId: String(chainId),
97
+ network: "tron"
98
+ };
99
+ } else if (chainType === ChainType.EVM) {
100
+ return {
101
+ chainId: String(chainId),
102
+ network: "ethereum"
103
+ };
104
+ }
105
+ throw new Error(`Unsupported chain type: ${chainType}`);
106
+ }
107
+ buildSignMessageLink(params) {
108
+ const actionId = this.generateActionId();
109
+ const callback = this.getCallbackConfig();
110
+ const blockchain = this.getBlockchainConfig(params.chainId, params.chainType);
111
+ const param = {
112
+ action: "sign",
113
+ actionId,
114
+ message: params.message,
115
+ hash: false,
116
+ signType: params.chainType === ChainType.TRON ? "ethPersonalSign" : "ethPersonalSign",
117
+ memo: `${params.chainType} message signature`,
118
+ blockchains: [blockchain],
119
+ dappName: "Enclave Wallet SDK",
120
+ dappIcon: "https://walletconnect.com/walletconnect-logo.svg",
121
+ protocol: "TokenPocket",
122
+ version: "1.1.8",
123
+ expired: 0,
124
+ ...callback
125
+ };
126
+ const encodedParam = encodeURIComponent(JSON.stringify(param));
127
+ const url = `tpoutside://pull.activity?param=${encodedParam}`;
128
+ return {
129
+ url,
130
+ actionId,
131
+ ...callback
132
+ };
133
+ }
134
+ buildSignTransactionLink(params) {
135
+ const actionId = this.generateActionId();
136
+ const callback = this.getCallbackConfig();
137
+ const blockchain = this.getBlockchainConfig(params.chainId, params.chainType);
138
+ let transactionData;
139
+ if (typeof params.transaction === "string") {
140
+ transactionData = params.transaction;
141
+ } else {
142
+ transactionData = JSON.stringify(params.transaction);
143
+ }
144
+ const param = {
145
+ action: "pushTransaction",
146
+ actionId,
147
+ txData: transactionData,
148
+ blockchains: [blockchain],
149
+ dappName: "Enclave Wallet SDK",
150
+ dappIcon: "https://walletconnect.com/walletconnect-logo.svg",
151
+ protocol: "TokenPocket",
152
+ version: "1.1.8",
153
+ expired: 0,
154
+ ...callback
155
+ };
156
+ const encodedParam = encodeURIComponent(JSON.stringify(param));
157
+ const url = `tpoutside://pull.activity?param=${encodedParam}`;
158
+ return {
159
+ url,
160
+ actionId,
161
+ ...callback
162
+ };
163
+ }
164
+ buildConnectLink(params) {
165
+ const actionId = this.generateActionId();
166
+ const blockchain = this.getBlockchainConfig(params.chainId, params.chainType);
167
+ const param = {
168
+ action: "login",
169
+ actionId,
170
+ blockchains: [blockchain],
171
+ dappName: "Enclave Wallet SDK",
172
+ dappIcon: "https://walletconnect.com/walletconnect-logo.svg",
173
+ protocol: "TokenPocket",
174
+ version: "1.0",
175
+ expired: 1602
176
+ // 30 minutes
177
+ };
178
+ const encodedParam = encodeURIComponent(JSON.stringify(param));
179
+ const url = `tpoutside://pull.activity?param=${encodedParam}`;
180
+ return {
181
+ url,
182
+ actionId
183
+ };
184
+ }
185
+ parseCallbackResult(urlParams) {
186
+ const actionId = urlParams.get("actionId");
187
+ const resultParam = urlParams.get("result");
188
+ const error = urlParams.get("error");
189
+ let result = null;
190
+ if (resultParam) {
191
+ try {
192
+ result = JSON.parse(decodeURIComponent(resultParam));
193
+ } catch (e) {
194
+ result = resultParam;
195
+ }
196
+ }
197
+ return {
198
+ actionId,
199
+ result,
200
+ error
201
+ };
202
+ }
203
+ getDefaultCallbackSchema() {
204
+ if (typeof window !== "undefined" && window.location) {
205
+ return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
206
+ }
207
+ return "";
208
+ }
209
+ };
210
+ }
211
+ });
212
+
213
+ // src/adapters/deep-link/providers/tronlink.ts
214
+ var tronlink_exports = {};
215
+ __export(tronlink_exports, {
216
+ TronLinkDeepLinkProvider: () => TronLinkDeepLinkProvider
217
+ });
218
+ var TronLinkDeepLinkProvider;
219
+ var init_tronlink = __esm({
220
+ "src/adapters/deep-link/providers/tronlink.ts"() {
221
+ init_types();
222
+ TronLinkDeepLinkProvider = class {
223
+ constructor() {
224
+ this.name = "TronLink";
225
+ this.icon = "https://www.tronlink.org/static/logoIcon.svg";
226
+ this.supportedChainTypes = [ChainType.TRON];
227
+ }
228
+ async isAvailable() {
229
+ if (typeof window === "undefined") {
230
+ return false;
231
+ }
232
+ const isTelegramMiniApp = !!(window.Telegram && window.Telegram.WebApp);
233
+ if (isTelegramMiniApp) {
234
+ return true;
235
+ }
236
+ const isMobile = /Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
237
+ navigator.userAgent
238
+ );
239
+ return isMobile;
240
+ }
241
+ buildSignMessageLink(params) {
242
+ if (params.chainType !== ChainType.TRON) {
243
+ throw new Error("TronLink only supports TRON chain");
244
+ }
245
+ const encodedMessage = encodeURIComponent(params.message);
246
+ const url = `tronlink://signMessage?message=${encodedMessage}`;
247
+ const actionId = `tronlink-${Date.now()}`;
248
+ return {
249
+ url,
250
+ actionId
251
+ };
252
+ }
253
+ buildSignTransactionLink(params) {
254
+ if (params.chainType !== ChainType.TRON) {
255
+ throw new Error("TronLink only supports TRON chain");
256
+ }
257
+ const transactionData = typeof params.transaction === "string" ? params.transaction : JSON.stringify(params.transaction);
258
+ const encodedData = encodeURIComponent(transactionData);
259
+ const url = `tronlink://signTransaction?transaction=${encodedData}`;
260
+ const actionId = `tronlink-${Date.now()}`;
261
+ return {
262
+ url,
263
+ actionId
264
+ };
265
+ }
266
+ buildConnectLink(params) {
267
+ if (params.chainType !== ChainType.TRON) {
268
+ throw new Error("TronLink only supports TRON chain");
269
+ }
270
+ const url = `tronlink://open?action=connect&network=tron`;
271
+ return {
272
+ url
273
+ };
274
+ }
275
+ parseCallbackResult(_urlParams) {
276
+ return {
277
+ actionId: null,
278
+ result: null,
279
+ error: null
280
+ };
281
+ }
282
+ };
283
+ }
284
+ });
285
+
286
+ // src/adapters/deep-link/providers/imtoken.ts
287
+ var imtoken_exports = {};
288
+ __export(imtoken_exports, {
289
+ ImTokenDeepLinkProvider: () => ImTokenDeepLinkProvider
290
+ });
291
+ var ImTokenDeepLinkProvider;
292
+ var init_imtoken = __esm({
293
+ "src/adapters/deep-link/providers/imtoken.ts"() {
294
+ init_types();
295
+ ImTokenDeepLinkProvider = class {
296
+ constructor(options) {
297
+ this.name = "ImToken";
298
+ this.icon = "https://token.im/static/img/logo.png";
299
+ this.supportedChainTypes = [ChainType.EVM, ChainType.TRON];
300
+ this.callbackUrl = options?.callbackUrl;
301
+ this.callbackSchema = options?.callbackSchema;
302
+ }
303
+ async isAvailable() {
304
+ if (typeof window === "undefined") {
305
+ return false;
306
+ }
307
+ const isTelegramMiniApp = !!(window.Telegram && window.Telegram.WebApp);
308
+ if (isTelegramMiniApp) {
309
+ return true;
310
+ }
311
+ const isMobile = /Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
312
+ navigator.userAgent
313
+ );
314
+ return isMobile;
315
+ }
316
+ /**
317
+ * Generate unique actionId
318
+ */
319
+ generateActionId() {
320
+ return `imtoken-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
321
+ }
322
+ /**
323
+ * Get callback configuration
324
+ */
325
+ getCallbackConfig() {
326
+ if (this.callbackSchema) {
327
+ return { callbackSchema: this.callbackSchema };
328
+ }
329
+ if (this.callbackUrl) {
330
+ return { callbackUrl: this.callbackUrl };
331
+ }
332
+ if (typeof window !== "undefined" && window.location) {
333
+ return {
334
+ callbackSchema: `${window.location.protocol}//${window.location.host}${window.location.pathname}`
335
+ };
336
+ }
337
+ return {};
338
+ }
339
+ buildSignMessageLink(params) {
340
+ const actionId = this.generateActionId();
341
+ const callback = this.getCallbackConfig();
342
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=signMessage&message=${encodeURIComponent(params.message)}&chainId=${params.chainId}`;
343
+ const encodedDappUrl = encodeURIComponent(dappUrl);
344
+ const url = `imtokenv2://navigate/DappView?url=${encodedDappUrl}`;
345
+ return {
346
+ url,
347
+ actionId,
348
+ ...callback
349
+ };
350
+ }
351
+ buildSignTransactionLink(params) {
352
+ const actionId = this.generateActionId();
353
+ const callback = this.getCallbackConfig();
354
+ const transactionData = typeof params.transaction === "string" ? params.transaction : JSON.stringify(params.transaction);
355
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=signTransaction&transaction=${encodeURIComponent(transactionData)}&chainId=${params.chainId}`;
356
+ const encodedDappUrl = encodeURIComponent(dappUrl);
357
+ const url = `imtokenv2://navigate/DappView?url=${encodedDappUrl}`;
358
+ return {
359
+ url,
360
+ actionId,
361
+ ...callback
362
+ };
363
+ }
364
+ buildConnectLink(params) {
365
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=connect&chainId=${params.chainId}`;
366
+ const encodedDappUrl = encodeURIComponent(dappUrl);
367
+ const url = `imtokenv2://navigate/DappView?url=${encodedDappUrl}`;
368
+ return {
369
+ url
370
+ };
371
+ }
372
+ parseCallbackResult(urlParams) {
373
+ const actionId = urlParams.get("actionId");
374
+ const resultParam = urlParams.get("result");
375
+ const error = urlParams.get("error");
376
+ let result = null;
377
+ if (resultParam) {
378
+ try {
379
+ result = JSON.parse(decodeURIComponent(resultParam));
380
+ } catch (e) {
381
+ result = resultParam;
382
+ }
383
+ }
384
+ return {
385
+ actionId,
386
+ result,
387
+ error
388
+ };
389
+ }
390
+ getDefaultCallbackSchema() {
391
+ if (typeof window !== "undefined" && window.location) {
392
+ return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
393
+ }
394
+ return "";
395
+ }
396
+ };
397
+ }
398
+ });
399
+
400
+ // src/adapters/deep-link/providers/metamask.ts
401
+ var metamask_exports = {};
402
+ __export(metamask_exports, {
403
+ MetaMaskDeepLinkProvider: () => MetaMaskDeepLinkProvider
404
+ });
405
+ var MetaMaskDeepLinkProvider;
406
+ var init_metamask = __esm({
407
+ "src/adapters/deep-link/providers/metamask.ts"() {
408
+ init_types();
409
+ MetaMaskDeepLinkProvider = class {
410
+ constructor() {
411
+ this.name = "MetaMask";
412
+ this.icon = "https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Fox.svg";
413
+ this.supportedChainTypes = [ChainType.EVM];
414
+ }
415
+ async isAvailable() {
416
+ if (typeof window === "undefined") {
417
+ return false;
418
+ }
419
+ const isTelegramMiniApp = !!(window.Telegram && window.Telegram.WebApp);
420
+ if (isTelegramMiniApp) {
421
+ return true;
422
+ }
423
+ const isMobile = /Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
424
+ navigator.userAgent
425
+ );
426
+ return isMobile;
427
+ }
428
+ buildSignMessageLink(params) {
429
+ if (params.chainType !== ChainType.EVM) {
430
+ throw new Error("MetaMask only supports EVM chains");
431
+ }
432
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=signMessage&message=${encodeURIComponent(params.message)}&chainId=${params.chainId}`;
433
+ const encodedDappUrl = encodeURIComponent(dappUrl);
434
+ const url = `https://link.metamask.io/dapp/${encodedDappUrl}`;
435
+ const actionId = `metamask-${Date.now()}`;
436
+ return {
437
+ url,
438
+ actionId
439
+ };
440
+ }
441
+ buildSignTransactionLink(params) {
442
+ if (params.chainType !== ChainType.EVM) {
443
+ throw new Error("MetaMask only supports EVM chains");
444
+ }
445
+ const transactionData = typeof params.transaction === "string" ? params.transaction : JSON.stringify(params.transaction);
446
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=signTransaction&transaction=${encodeURIComponent(transactionData)}&chainId=${params.chainId}`;
447
+ const encodedDappUrl = encodeURIComponent(dappUrl);
448
+ const url = `https://link.metamask.io/dapp/${encodedDappUrl}`;
449
+ const actionId = `metamask-${Date.now()}`;
450
+ return {
451
+ url,
452
+ actionId
453
+ };
454
+ }
455
+ buildConnectLink(params) {
456
+ if (params.chainType !== ChainType.EVM) {
457
+ throw new Error("MetaMask only supports EVM chains");
458
+ }
459
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=connect&chainId=${params.chainId}`;
460
+ const encodedDappUrl = encodeURIComponent(dappUrl);
461
+ const url = `https://link.metamask.io/dapp/${encodedDappUrl}`;
462
+ return {
463
+ url
464
+ };
465
+ }
466
+ parseCallbackResult(urlParams) {
467
+ const actionId = urlParams.get("actionId");
468
+ const resultParam = urlParams.get("result");
469
+ const error = urlParams.get("error");
470
+ let result = null;
471
+ if (resultParam) {
472
+ try {
473
+ result = JSON.parse(decodeURIComponent(resultParam));
474
+ } catch (e) {
475
+ result = resultParam;
476
+ }
477
+ }
478
+ return {
479
+ actionId,
480
+ result,
481
+ error
482
+ };
483
+ }
484
+ getDefaultCallbackSchema() {
485
+ if (typeof window !== "undefined" && window.location) {
486
+ return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
487
+ }
488
+ return "";
489
+ }
490
+ };
491
+ }
492
+ });
493
+
494
+ // src/adapters/deep-link/providers/okx.ts
495
+ var okx_exports = {};
496
+ __export(okx_exports, {
497
+ OKXDeepLinkProvider: () => OKXDeepLinkProvider
498
+ });
499
+ var OKXDeepLinkProvider;
500
+ var init_okx = __esm({
501
+ "src/adapters/deep-link/providers/okx.ts"() {
502
+ init_types();
503
+ OKXDeepLinkProvider = class {
504
+ constructor() {
505
+ this.name = "OKX";
506
+ this.icon = "https://www.okx.com/favicon.ico";
507
+ this.supportedChainTypes = [ChainType.EVM, ChainType.TRON];
508
+ }
509
+ async isAvailable() {
510
+ if (typeof window === "undefined") {
511
+ return false;
512
+ }
513
+ const isTelegramMiniApp = !!(window.Telegram && window.Telegram.WebApp);
514
+ if (isTelegramMiniApp) {
515
+ return true;
516
+ }
517
+ const isMobile = /Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
518
+ navigator.userAgent
519
+ );
520
+ return isMobile;
521
+ }
522
+ buildSignMessageLink(params) {
523
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=signMessage&message=${encodeURIComponent(params.message)}&chainId=${params.chainId}`;
524
+ const encodedDappUrl = encodeURIComponent(dappUrl);
525
+ const url = `okx://wallet/dapp/url?dappUrl=${encodedDappUrl}`;
526
+ const actionId = `okx-${Date.now()}`;
527
+ return {
528
+ url,
529
+ actionId
530
+ };
531
+ }
532
+ buildSignTransactionLink(params) {
533
+ const transactionData = typeof params.transaction === "string" ? params.transaction : JSON.stringify(params.transaction);
534
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=signTransaction&transaction=${encodeURIComponent(transactionData)}&chainId=${params.chainId}`;
535
+ const encodedDappUrl = encodeURIComponent(dappUrl);
536
+ const url = `okx://wallet/dapp/url?dappUrl=${encodedDappUrl}`;
537
+ const actionId = `okx-${Date.now()}`;
538
+ return {
539
+ url,
540
+ actionId
541
+ };
542
+ }
543
+ buildConnectLink(params) {
544
+ const dappUrl = `${window.location.origin}${window.location.pathname}?action=connect&chainId=${params.chainId}`;
545
+ const encodedDappUrl = encodeURIComponent(dappUrl);
546
+ const url = `okx://wallet/dapp/url?dappUrl=${encodedDappUrl}`;
547
+ return {
548
+ url
549
+ };
550
+ }
551
+ parseCallbackResult(urlParams) {
552
+ const actionId = urlParams.get("actionId");
553
+ const resultParam = urlParams.get("result");
554
+ const error = urlParams.get("error");
555
+ let result = null;
556
+ if (resultParam) {
557
+ try {
558
+ result = JSON.parse(decodeURIComponent(resultParam));
559
+ } catch (e) {
560
+ result = resultParam;
561
+ }
562
+ }
563
+ return {
564
+ actionId,
565
+ result,
566
+ error
567
+ };
568
+ }
569
+ getDefaultCallbackSchema() {
570
+ if (typeof window !== "undefined" && window.location) {
571
+ return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
572
+ }
573
+ return "";
574
+ }
575
+ };
576
+ }
577
+ });
8
578
  var TypedEventEmitter = class {
9
579
  constructor() {
10
580
  this.emitter = new EventEmitter();
@@ -33,7 +603,12 @@ var TypedEventEmitter = class {
33
603
  return this;
34
604
  }
35
605
  };
36
- var ChainType = ChainType$1;
606
+
607
+ // src/core/adapter-registry.ts
608
+ init_types();
609
+
610
+ // src/adapters/base/wallet-adapter.ts
611
+ init_types();
37
612
 
38
613
  // src/core/errors.ts
39
614
  var WalletSDKError = class _WalletSDKError extends Error {
@@ -104,6 +679,18 @@ var MethodNotSupportedError = class extends WalletSDKError {
104
679
  this.name = "MethodNotSupportedError";
105
680
  }
106
681
  };
682
+ var ConfigurationError = class extends WalletSDKError {
683
+ constructor(message, details) {
684
+ super(message, "CONFIGURATION_ERROR", details);
685
+ this.name = "ConfigurationError";
686
+ }
687
+ };
688
+ var NetworkError = class extends WalletSDKError {
689
+ constructor(message, details) {
690
+ super(message, "NETWORK_ERROR", details);
691
+ this.name = "NetworkError";
692
+ }
693
+ };
107
694
 
108
695
  // src/adapters/base/wallet-adapter.ts
109
696
  var WalletAdapter = class extends EventEmitter {
@@ -113,6 +700,13 @@ var WalletAdapter = class extends EventEmitter {
113
700
  this.state = "disconnected" /* DISCONNECTED */;
114
701
  this.currentAccount = null;
115
702
  }
703
+ /**
704
+ * Check if the wallet is currently connected
705
+ * @returns true if the wallet is connected (state is CONNECTED and has an account)
706
+ */
707
+ isConnected() {
708
+ return this.state === "connected" /* CONNECTED */ && this.currentAccount !== null;
709
+ }
116
710
  /**
117
711
  * Get the signer's address (implements ISigner interface)
118
712
  * Returns the native address of the current account
@@ -182,6 +776,7 @@ var WalletAdapter = class extends EventEmitter {
182
776
  };
183
777
 
184
778
  // src/adapters/base/browser-wallet-adapter.ts
779
+ init_types();
185
780
  var BrowserWalletAdapter = class extends WalletAdapter {
186
781
  /**
187
782
  * 检查钱包是否可用
@@ -215,6 +810,9 @@ var BrowserWalletAdapter = class extends WalletAdapter {
215
810
  }
216
811
  };
217
812
 
813
+ // src/adapters/evm/metamask.ts
814
+ init_types();
815
+
218
816
  // src/utils/address/universal-address.ts
219
817
  function createUniversalAddress(chainId, address) {
220
818
  return `${chainId}:${address}`;
@@ -239,7 +837,12 @@ var CHAIN_INFO = {
239
837
  symbol: "ETH",
240
838
  decimals: 18
241
839
  },
242
- rpcUrls: ["https://eth.llamarpc.com"],
840
+ // 使用支持浏览器 CORS 的公共 RPC,避免 dapp 域名被跨域拦截(如 eth.llamarpc.com 无 CORS 头)
841
+ rpcUrls: [
842
+ "https://cloudflare-eth.com",
843
+ "https://rpc.ankr.com/eth",
844
+ "https://eth.llamarpc.com"
845
+ ],
243
846
  blockExplorerUrls: ["https://etherscan.io"]
244
847
  },
245
848
  // EVM Testnets
@@ -459,6 +1062,7 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
459
1062
  */
460
1063
  async connect(chainId) {
461
1064
  await this.ensureAvailable();
1065
+ const targetChainId = Array.isArray(chainId) ? chainId[0] : chainId;
462
1066
  try {
463
1067
  this.setState("connecting" /* CONNECTING */);
464
1068
  const provider = this.getBrowserProvider();
@@ -472,10 +1076,10 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
472
1076
  method: "eth_chainId"
473
1077
  });
474
1078
  const parsedChainId = parseInt(currentChainId, 16);
475
- if (chainId && chainId !== parsedChainId) {
476
- await this.switchChain(chainId);
1079
+ if (targetChainId && targetChainId !== parsedChainId) {
1080
+ await this.switchChain(targetChainId);
477
1081
  }
478
- const finalChainId = chainId || parsedChainId;
1082
+ const finalChainId = targetChainId || parsedChainId;
479
1083
  const viemChain = this.getViemChain(finalChainId);
480
1084
  this.walletClient = createWalletClient({
481
1085
  account: accounts[0],
@@ -637,6 +1241,56 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
637
1241
  }]
638
1242
  });
639
1243
  }
1244
+ /**
1245
+ * 请求切换账户
1246
+ * 弹出 MetaMask 账户选择界面,让用户选择或切换到目标地址
1247
+ * @param targetAddress 目标地址(可选),如果提供,会在切换后验证是否匹配
1248
+ * @returns 切换后的账户信息
1249
+ */
1250
+ async requestSwitchAccount(targetAddress) {
1251
+ const provider = this.getBrowserProvider();
1252
+ if (!provider) {
1253
+ throw new Error("MetaMask provider not available");
1254
+ }
1255
+ try {
1256
+ await provider.request({
1257
+ method: "wallet_requestPermissions",
1258
+ params: [{ eth_accounts: {} }]
1259
+ });
1260
+ const accounts = await provider.request({
1261
+ method: "eth_accounts"
1262
+ });
1263
+ if (!accounts || accounts.length === 0) {
1264
+ throw new ConnectionRejectedError(this.type);
1265
+ }
1266
+ const address = formatEVMAddress(accounts[0]);
1267
+ if (targetAddress && address.toLowerCase() !== targetAddress.toLowerCase()) {
1268
+ throw new Error(`\u8BF7\u5728 MetaMask \u4E2D\u9009\u62E9\u5730\u5740 ${targetAddress.slice(0, 6)}...${targetAddress.slice(-4)}\uFF0C\u5F53\u524D\u9009\u62E9\u7684\u662F ${address.slice(0, 6)}...${address.slice(-4)}`);
1269
+ }
1270
+ const chainId = this.currentAccount?.chainId || 1;
1271
+ const account = {
1272
+ universalAddress: createUniversalAddress(chainId, address),
1273
+ nativeAddress: address,
1274
+ chainId,
1275
+ chainType: ChainType.EVM,
1276
+ isActive: true
1277
+ };
1278
+ this.setAccount(account);
1279
+ this.emitAccountChanged(account);
1280
+ const viemChain = this.getViemChain(chainId);
1281
+ this.walletClient = createWalletClient({
1282
+ account: address,
1283
+ chain: viemChain,
1284
+ transport: custom(provider)
1285
+ });
1286
+ return account;
1287
+ } catch (error) {
1288
+ if (error.code === 4001) {
1289
+ throw new ConnectionRejectedError(this.type);
1290
+ }
1291
+ throw error;
1292
+ }
1293
+ }
640
1294
  /**
641
1295
  * 读取合约
642
1296
  */
@@ -861,6 +1515,47 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
861
1515
  };
862
1516
 
863
1517
  // src/adapters/tron/tronlink.ts
1518
+ init_types();
1519
+ var TronApiRateLimiter = class {
1520
+ constructor(minIntervalMs = 600) {
1521
+ this.lastCallTime = 0;
1522
+ this.minInterval = minIntervalMs;
1523
+ }
1524
+ /**
1525
+ * 等待直到可以进行下一次 API 调用
1526
+ */
1527
+ async waitForNextCall() {
1528
+ const now = Date.now();
1529
+ const timeSinceLastCall = now - this.lastCallTime;
1530
+ if (timeSinceLastCall < this.minInterval) {
1531
+ const waitTime = this.minInterval - timeSinceLastCall;
1532
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
1533
+ }
1534
+ this.lastCallTime = Date.now();
1535
+ }
1536
+ };
1537
+ var tronApiRateLimiter = new TronApiRateLimiter(600);
1538
+ async function retryWithBackoff(fn, maxRetries = 3, initialDelay = 500) {
1539
+ let lastError;
1540
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
1541
+ try {
1542
+ return await fn();
1543
+ } catch (error) {
1544
+ lastError = error;
1545
+ const errorMsg = error?.message || String(error);
1546
+ const errorLower = errorMsg.toLowerCase();
1547
+ const isRateLimitError = error?.response?.status === 429 || error?.status === 429 || errorLower.includes("429") || errorLower.includes("rate limit") || errorLower.includes("too many requests") || error?.code === "ERR_BAD_REQUEST" && error?.response?.status === 429;
1548
+ if (isRateLimitError && attempt < maxRetries - 1) {
1549
+ const delay = initialDelay * Math.pow(2, attempt);
1550
+ console.warn(`[TronLink] \u9047\u5230\u901F\u7387\u9650\u5236 (429)\uFF0C\u7B49\u5F85 ${delay}ms \u540E\u91CD\u8BD5 (${attempt + 1}/${maxRetries})...`);
1551
+ await new Promise((resolve) => setTimeout(resolve, delay));
1552
+ continue;
1553
+ }
1554
+ throw error;
1555
+ }
1556
+ }
1557
+ throw lastError;
1558
+ }
864
1559
  var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
865
1560
  constructor() {
866
1561
  super(...arguments);
@@ -908,6 +1603,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
908
1603
  */
909
1604
  async connect(chainId) {
910
1605
  await this.ensureAvailable();
1606
+ const targetChainId = Array.isArray(chainId) ? chainId[0] : chainId;
911
1607
  try {
912
1608
  this.setState("connecting" /* CONNECTING */);
913
1609
  const w = window;
@@ -962,7 +1658,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
962
1658
  if (!address) {
963
1659
  throw new Error("Failed to get Tron address. Please make sure your wallet is unlocked and try again.");
964
1660
  }
965
- const tronChainId = chainId || _TronLinkAdapter.TRON_MAINNET_CHAIN_ID;
1661
+ const tronChainId = targetChainId || _TronLinkAdapter.TRON_MAINNET_CHAIN_ID;
966
1662
  const account = {
967
1663
  universalAddress: createUniversalAddress(tronChainId, address),
968
1664
  nativeAddress: address,
@@ -1037,10 +1733,12 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
1037
1733
  /**
1038
1734
  * 读取合约
1039
1735
  * 参考 webserver 的实现,使用 TronWeb 合约实例的标准 call() 方法
1736
+ * 带 TronGrid 限流 + 429 重试
1040
1737
  */
1041
1738
  async readContract(params) {
1042
1739
  this.ensureConnected();
1043
- try {
1740
+ await tronApiRateLimiter.waitForNextCall();
1741
+ const doRead = async () => {
1044
1742
  const tronWeb = this.getTronWeb();
1045
1743
  if (!this.currentAccount) {
1046
1744
  throw new Error("No account connected");
@@ -1055,19 +1753,17 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
1055
1753
  return result;
1056
1754
  } catch (method1Error) {
1057
1755
  console.warn("\u26A0\uFE0F [\u65B9\u6CD51] TronWeb\u6807\u51C6\u65B9\u6CD5\u5931\u8D25\uFF0C\u5C1D\u8BD5\u65B9\u6CD52:", method1Error.message);
1058
- try {
1059
- const contract2 = await tronWeb.contract().at(params.address);
1060
- const method2 = contract2[params.functionName];
1061
- if (!method2 || typeof method2 !== "function") {
1062
- throw new Error(`Function ${params.functionName} not found in contract`);
1063
- }
1064
- const result = await method2(...params.args || []).call();
1065
- return result;
1066
- } catch (method2Error) {
1067
- console.error("\u26A0\uFE0F [\u65B9\u6CD52] \u4E5F\u5931\u8D25:", method2Error.message);
1068
- throw method1Error;
1756
+ const contract2 = await tronWeb.contract().at(params.address);
1757
+ const method2 = contract2[params.functionName];
1758
+ if (!method2 || typeof method2 !== "function") {
1759
+ throw new Error(`Function ${params.functionName} not found in contract`);
1069
1760
  }
1761
+ const result = await method2(...params.args || []).call();
1762
+ return result;
1070
1763
  }
1764
+ };
1765
+ try {
1766
+ return await retryWithBackoff(doRead, 3, 800);
1071
1767
  } catch (error) {
1072
1768
  console.error("Read contract error:", error);
1073
1769
  throw new Error(`Failed to read contract: ${error.message || "Unknown error"}`);
@@ -1078,6 +1774,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
1078
1774
  */
1079
1775
  async writeContract(params) {
1080
1776
  this.ensureConnected();
1777
+ await tronApiRateLimiter.waitForNextCall();
1081
1778
  try {
1082
1779
  const tronWeb = this.getTronWeb();
1083
1780
  console.log("[TronLink] writeContract params:", {
@@ -1103,29 +1800,171 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
1103
1800
  }
1104
1801
  console.log("[TronLink] Function ABI:", functionAbi);
1105
1802
  console.log("[TronLink] Calling with args:", params.args);
1803
+ const TRON_FEE_LIMIT = 1e8;
1106
1804
  const options = {
1107
- feeLimit: params.gas || 1e8,
1108
- // 默认 100 TRX 的能量限制
1805
+ feeLimit: TRON_FEE_LIMIT,
1806
+ // 固定为 100 TRX 的能量限制
1109
1807
  callValue: params.value || 0
1110
1808
  // 发送的 TRX 数量(单位:SUN)
1111
1809
  };
1112
- const parameter = functionAbi.inputs.map((input, index) => ({
1113
- type: input.type,
1114
- value: params.args[index]
1115
- }));
1116
- console.log("[TronLink] Transaction options:", options);
1117
- console.log("[TronLink] Parameters:", parameter);
1118
- const functionSelector = params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")";
1119
- console.log("[TronLink] Function selector:", functionSelector);
1120
- console.log("[TronLink] Transaction options:", options);
1121
- console.log("[TronLink] Parameters:", parameter);
1122
- const tx = await tronWeb.transactionBuilder.triggerSmartContract(
1123
- params.address,
1124
- functionSelector,
1125
- options,
1126
- parameter,
1127
- this.currentAccount.nativeAddress
1128
- );
1810
+ const hasTupleArray = functionAbi.inputs.some((input) => input.type === "tuple[]");
1811
+ console.log("[TronLink] \u68C0\u67E5 tuple[] \u7C7B\u578B:", {
1812
+ hasTupleArray,
1813
+ inputs: functionAbi.inputs.map((i) => ({ name: i.name, type: i.type }))
1814
+ });
1815
+ let tx;
1816
+ if (hasTupleArray) {
1817
+ console.log("[TronLink] \u68C0\u6D4B\u5230 tuple[] \u53C2\u6570\uFF0C\u4F7F\u7528\u624B\u52A8\u7F16\u7801\u65B9\u5F0F");
1818
+ const processedArgs = params.args.map((argValue, index) => {
1819
+ const input = functionAbi.inputs[index];
1820
+ if (input.type === "address" && typeof argValue === "string") {
1821
+ if (argValue.startsWith("T") && argValue.length === 34) {
1822
+ const hexAddress = tronWeb.address.toHex(argValue);
1823
+ return hexAddress.startsWith("0x") ? hexAddress : `0x${hexAddress}`;
1824
+ }
1825
+ return argValue.startsWith("0x") ? argValue : `0x${argValue}`;
1826
+ }
1827
+ if (input.type === "tuple[]" && Array.isArray(argValue)) {
1828
+ return argValue.map((tupleItem) => {
1829
+ if (input.components && Array.isArray(input.components)) {
1830
+ const processedTuple = {};
1831
+ input.components.forEach((component) => {
1832
+ let value = tupleItem[component.name];
1833
+ if (component.type === "address" && typeof value === "string") {
1834
+ if (value.startsWith("T") && value.length === 34) {
1835
+ const hexAddress = tronWeb.address.toHex(value);
1836
+ value = hexAddress.startsWith("0x") ? hexAddress : `0x${hexAddress}`;
1837
+ } else if (!value.startsWith("0x")) {
1838
+ value = `0x${value}`;
1839
+ }
1840
+ }
1841
+ processedTuple[component.name] = value;
1842
+ });
1843
+ return processedTuple;
1844
+ }
1845
+ return tupleItem;
1846
+ });
1847
+ }
1848
+ if (input.type === "tuple" && typeof argValue === "object" && !Array.isArray(argValue)) {
1849
+ if (input.components && Array.isArray(input.components)) {
1850
+ const processedTuple = {};
1851
+ input.components.forEach((component) => {
1852
+ let value = argValue[component.name];
1853
+ if (component.type === "address" && typeof value === "string") {
1854
+ if (value.startsWith("T") && value.length === 34) {
1855
+ const hexAddress = tronWeb.address.toHex(value);
1856
+ value = hexAddress.startsWith("0x") ? hexAddress : `0x${hexAddress}`;
1857
+ } else if (!value.startsWith("0x")) {
1858
+ value = `0x${value}`;
1859
+ }
1860
+ }
1861
+ processedTuple[component.name] = value;
1862
+ });
1863
+ return processedTuple;
1864
+ }
1865
+ }
1866
+ return argValue;
1867
+ });
1868
+ console.log("[TronLink] \u5904\u7406\u540E\u7684\u53C2\u6570\uFF08\u7528\u4E8E viem \u7F16\u7801\uFF09:", processedArgs);
1869
+ const encodedData = encodeFunctionData({
1870
+ abi: [functionAbi],
1871
+ functionName: params.functionName,
1872
+ args: processedArgs
1873
+ });
1874
+ console.log("[TronLink] \u7F16\u7801\u540E\u7684\u6570\u636E:", encodedData);
1875
+ const functionSelector = encodedData.slice(0, 10);
1876
+ const parameterData = encodedData.slice(10);
1877
+ console.log("[TronLink] \u51FD\u6570\u9009\u62E9\u5668:", functionSelector);
1878
+ console.log("[TronLink] \u53C2\u6570\u6570\u636E:", parameterData);
1879
+ const functionSignature = params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")";
1880
+ const parameterHexClean = parameterData.startsWith("0x") ? parameterData.slice(2) : parameterData;
1881
+ console.log("[TronLink] \u4F7F\u7528 TronWeb triggerSmartContract (rawParameter)...", {
1882
+ contractAddress: params.address,
1883
+ functionSelector: functionSignature,
1884
+ encodedDataLength: parameterHexClean.length
1885
+ });
1886
+ tx = await retryWithBackoff(
1887
+ () => tronWeb.transactionBuilder.triggerSmartContract(
1888
+ params.address,
1889
+ // Base58 格式的合约地址
1890
+ functionSignature,
1891
+ // 函数签名(用于识别函数)
1892
+ {
1893
+ feeLimit: options.feeLimit,
1894
+ callValue: options.callValue,
1895
+ rawParameter: parameterHexClean
1896
+ // 使用 rawParameter 直接提供编码后的数据
1897
+ },
1898
+ [],
1899
+ // parameter 留空(因为使用 rawParameter)
1900
+ this.currentAccount.nativeAddress
1901
+ // Base58 格式的发送地址
1902
+ ),
1903
+ 3,
1904
+ // 最多重试 3 次
1905
+ 500
1906
+ // 初始延迟 500ms
1907
+ );
1908
+ console.log("[TronLink] \u4F7F\u7528 TronWeb API \u6784\u5EFA\u7684\u4EA4\u6613:", tx);
1909
+ } else {
1910
+ const parameter = functionAbi.inputs.map((input, index) => {
1911
+ const argValue = params.args[index];
1912
+ if (input.type === "tuple" && typeof argValue === "object" && !Array.isArray(argValue)) {
1913
+ if (input.components && Array.isArray(input.components)) {
1914
+ return {
1915
+ type: input.type,
1916
+ value: input.components.map((component) => ({
1917
+ type: component.type,
1918
+ value: argValue[component.name]
1919
+ }))
1920
+ };
1921
+ }
1922
+ }
1923
+ if (input.type === "address" && typeof argValue === "string") {
1924
+ if (argValue.startsWith("T") && argValue.length === 34) {
1925
+ return {
1926
+ type: input.type,
1927
+ value: argValue
1928
+ };
1929
+ }
1930
+ try {
1931
+ const base58Address = tronWeb.address.fromHex(argValue.startsWith("0x") ? argValue : `0x${argValue}`);
1932
+ return {
1933
+ type: input.type,
1934
+ value: base58Address
1935
+ };
1936
+ } catch (e) {
1937
+ return {
1938
+ type: input.type,
1939
+ value: argValue
1940
+ };
1941
+ }
1942
+ }
1943
+ return {
1944
+ type: input.type,
1945
+ value: argValue
1946
+ };
1947
+ });
1948
+ console.log("[TronLink] Transaction options:", options);
1949
+ console.log("[TronLink] Parameters:", parameter);
1950
+ const functionSelector = params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")";
1951
+ console.log("[TronLink] Function selector:", functionSelector);
1952
+ console.log("[TronLink] Transaction options:", options);
1953
+ console.log("[TronLink] Parameters:", parameter);
1954
+ tx = await retryWithBackoff(
1955
+ () => tronWeb.transactionBuilder.triggerSmartContract(
1956
+ params.address,
1957
+ functionSelector,
1958
+ options,
1959
+ parameter,
1960
+ this.currentAccount.nativeAddress
1961
+ ),
1962
+ 3,
1963
+ // 最多重试 3 次
1964
+ 500
1965
+ // 初始延迟 500ms
1966
+ );
1967
+ }
1129
1968
  console.log("[TronLink] Transaction built:", tx);
1130
1969
  if (!tx || !tx.transaction) {
1131
1970
  throw new Error("Failed to build transaction");
@@ -1165,6 +2004,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
1165
2004
  const maxAttempts = 60;
1166
2005
  while (attempts < maxAttempts) {
1167
2006
  try {
2007
+ await tronApiRateLimiter.waitForNextCall();
1168
2008
  const txInfo = await tronWeb.trx.getTransactionInfo(txHash);
1169
2009
  if (txInfo && txInfo.id) {
1170
2010
  const receipt = {
@@ -1292,6 +2132,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
1292
2132
  // Tron 主网链 ID
1293
2133
  _TronLinkAdapter.TRON_MAINNET_CHAIN_ID = 195;
1294
2134
  var TronLinkAdapter = _TronLinkAdapter;
2135
+ init_types();
1295
2136
  var EVMPrivateKeyAdapter = class extends WalletAdapter {
1296
2137
  constructor() {
1297
2138
  super(...arguments);
@@ -1305,27 +2146,28 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
1305
2146
  /**
1306
2147
  * 连接(导入私钥)
1307
2148
  */
1308
- async connect(chainId = 1) {
2149
+ async connect(chainId) {
1309
2150
  if (!this.privateKey) {
1310
2151
  throw new Error("Private key not set. Call setPrivateKey() first.");
1311
2152
  }
1312
2153
  try {
1313
2154
  this.setState("connecting" /* CONNECTING */);
1314
2155
  const account = privateKeyToAccount(this.privateKey);
2156
+ const targetChainId = Array.isArray(chainId) ? chainId[0] : chainId || 1;
1315
2157
  this.walletClient = createWalletClient({
1316
2158
  account,
1317
- chain: this.getViemChain(chainId),
2159
+ chain: this.getViemChain(targetChainId),
1318
2160
  transport: http()
1319
2161
  });
1320
2162
  this.publicClient = createPublicClient({
1321
- chain: this.getViemChain(chainId),
2163
+ chain: this.getViemChain(targetChainId),
1322
2164
  transport: http()
1323
2165
  });
1324
2166
  const address = formatEVMAddress(account.address);
1325
2167
  const accountInfo = {
1326
- universalAddress: createUniversalAddress(chainId, address),
2168
+ universalAddress: createUniversalAddress(targetChainId, address),
1327
2169
  nativeAddress: address,
1328
- chainId,
2170
+ chainId: targetChainId,
1329
2171
  chainType: ChainType.EVM,
1330
2172
  isActive: true
1331
2173
  };
@@ -1537,38 +2379,2094 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
1537
2379
  };
1538
2380
  }
1539
2381
  };
1540
-
1541
- // src/core/adapter-registry.ts
1542
- var AdapterRegistry = class {
1543
- constructor() {
1544
- this.adapters = /* @__PURE__ */ new Map();
1545
- this.registerDefaultAdapters();
1546
- }
1547
- /**
1548
- * Register default adapters
1549
- */
1550
- registerDefaultAdapters() {
1551
- this.register("metamask" /* METAMASK */, () => new MetaMaskAdapter());
1552
- this.register("private-key" /* PRIVATE_KEY */, () => new EVMPrivateKeyAdapter());
1553
- this.register("tronlink" /* TRONLINK */, () => new TronLinkAdapter());
1554
- }
1555
- /**
1556
- * Register adapter
1557
- */
1558
- register(type, factory) {
1559
- this.adapters.set(type, factory);
1560
- }
1561
- /**
1562
- * Get adapter
1563
- */
1564
- getAdapter(type) {
1565
- const factory = this.adapters.get(type);
1566
- if (!factory) {
1567
- return null;
1568
- }
1569
- return factory();
1570
- }
1571
- /**
2382
+ init_types();
2383
+ var _WalletConnectAdapter = class _WalletConnectAdapter extends WalletAdapter {
2384
+ constructor(projectId) {
2385
+ super();
2386
+ this.type = "walletconnect" /* WALLETCONNECT */;
2387
+ this.chainType = ChainType.EVM;
2388
+ this.name = "WalletConnect";
2389
+ this.icon = "https://avatars.githubusercontent.com/u/37784886";
2390
+ this.provider = null;
2391
+ this.walletClient = null;
2392
+ this.publicClient = null;
2393
+ this.supportedChains = [];
2394
+ /**
2395
+ * Handle accounts changed
2396
+ */
2397
+ this.handleAccountsChanged = (accounts) => {
2398
+ if (accounts.length === 0) {
2399
+ this.setState("disconnected" /* DISCONNECTED */);
2400
+ this.setAccount(null);
2401
+ this.emitAccountChanged(null);
2402
+ } else {
2403
+ const address = formatEVMAddress(accounts[0]);
2404
+ const account = {
2405
+ universalAddress: createUniversalAddress(this.currentAccount.chainId, address),
2406
+ nativeAddress: address,
2407
+ chainId: this.currentAccount.chainId,
2408
+ chainType: ChainType.EVM,
2409
+ isActive: true
2410
+ };
2411
+ this.setAccount(account);
2412
+ this.emitAccountChanged(account);
2413
+ }
2414
+ };
2415
+ /**
2416
+ * Handle chain changed
2417
+ */
2418
+ this.handleChainChanged = (chainIdHex) => {
2419
+ const chainId = parseInt(chainIdHex, 16);
2420
+ if (this.currentAccount) {
2421
+ const account = {
2422
+ ...this.currentAccount,
2423
+ chainId,
2424
+ universalAddress: createUniversalAddress(chainId, this.currentAccount.nativeAddress)
2425
+ };
2426
+ this.setAccount(account);
2427
+ this.emitChainChanged(chainId);
2428
+ const viemChain = this.getViemChain(chainId);
2429
+ const chainInfo = getChainInfo(chainId);
2430
+ const primaryRpcUrl = chainInfo?.rpcUrls[0];
2431
+ if (this.provider) {
2432
+ this.walletClient = createWalletClient({
2433
+ account: this.currentAccount.nativeAddress,
2434
+ chain: viemChain,
2435
+ transport: custom(this.provider)
2436
+ });
2437
+ this.publicClient = createPublicClient({
2438
+ chain: viemChain,
2439
+ transport: primaryRpcUrl ? http(primaryRpcUrl) : custom(this.provider)
2440
+ });
2441
+ }
2442
+ }
2443
+ };
2444
+ /**
2445
+ * Handle disconnect
2446
+ */
2447
+ this.handleDisconnect = () => {
2448
+ this.setState("disconnected" /* DISCONNECTED */);
2449
+ this.setAccount(null);
2450
+ if (_WalletConnectAdapter.providerInstance === this.provider) {
2451
+ _WalletConnectAdapter.providerInstance = null;
2452
+ _WalletConnectAdapter.providerProjectId = null;
2453
+ }
2454
+ this.provider = null;
2455
+ this.walletClient = null;
2456
+ this.publicClient = null;
2457
+ this.emitDisconnected();
2458
+ };
2459
+ if (!projectId) {
2460
+ throw new ConfigurationError("WalletConnect projectId is required");
2461
+ }
2462
+ this.projectId = projectId;
2463
+ }
2464
+ /**
2465
+ * Check if WalletConnect is available
2466
+ * WalletConnect is always available (it's a web-based connection)
2467
+ * Also works in Telegram Mini Apps
2468
+ */
2469
+ async isAvailable() {
2470
+ return typeof window !== "undefined";
2471
+ }
2472
+ /**
2473
+ * Check if running in Telegram environment (Mini App or Web)
2474
+ * Both Telegram Mini App (in client) and Telegram Web (web.telegram.org)
2475
+ * provide window.Telegram.WebApp API, so they are treated the same way.
2476
+ *
2477
+ * Reference: https://docs.reown.com/appkit/integrations/telegram-mini-apps
2478
+ */
2479
+ isTelegramMiniApp() {
2480
+ if (typeof window === "undefined") return false;
2481
+ const tg = window.Telegram?.WebApp;
2482
+ if (!tg) return false;
2483
+ const platform = tg.platform || "unknown";
2484
+ console.log("[WalletConnect] Telegram environment detected:", {
2485
+ platform,
2486
+ version: tg.version,
2487
+ isMiniApp: platform !== "web",
2488
+ // Mini App if not web platform
2489
+ isWeb: platform === "web"
2490
+ // Telegram Web if web platform
2491
+ });
2492
+ return true;
2493
+ }
2494
+ /**
2495
+ * Get Telegram WebApp instance if available
2496
+ */
2497
+ getTelegramWebApp() {
2498
+ if (typeof window === "undefined") return null;
2499
+ return window.Telegram?.WebApp || null;
2500
+ }
2501
+ /**
2502
+ * Close Telegram deep link popup (wc:// links)
2503
+ * In Telegram Mini Apps, WalletConnect may open a wc:// deep link popup
2504
+ * that doesn't automatically close after the operation completes.
2505
+ * This method attempts to close it by:
2506
+ * 1. Trying to close any open windows/popups
2507
+ * 2. Using Telegram WebApp API if available
2508
+ * 3. Navigating back or closing the popup
2509
+ */
2510
+ closeTelegramDeepLinkPopup() {
2511
+ if (!this.isTelegramMiniApp()) {
2512
+ return;
2513
+ }
2514
+ try {
2515
+ const tg = this.getTelegramWebApp();
2516
+ if (!tg) {
2517
+ return;
2518
+ }
2519
+ if (typeof window !== "undefined") {
2520
+ window.focus();
2521
+ if (tg.BackButton && tg.BackButton.isVisible) {
2522
+ console.log("[WalletConnect] Closing Telegram deep link popup via BackButton");
2523
+ }
2524
+ setTimeout(() => {
2525
+ if (document.hasFocus()) {
2526
+ console.log("[WalletConnect] Main window has focus, popup likely closed");
2527
+ } else {
2528
+ window.focus();
2529
+ console.log("[WalletConnect] Attempted to focus main window to close popup");
2530
+ }
2531
+ }, 500);
2532
+ const handleVisibilityChange = () => {
2533
+ if (document.visibilityState === "visible") {
2534
+ console.log("[WalletConnect] Page became visible, popup may have closed");
2535
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
2536
+ }
2537
+ };
2538
+ document.addEventListener("visibilitychange", handleVisibilityChange);
2539
+ setTimeout(() => {
2540
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
2541
+ }, 2e3);
2542
+ }
2543
+ } catch (error) {
2544
+ console.warn("[WalletConnect] Error closing Telegram deep link popup:", error);
2545
+ }
2546
+ }
2547
+ /**
2548
+ * Connect wallet
2549
+ *
2550
+ * @param chainId - Single chain ID or array of chain IDs to request
2551
+ * If array is provided, wallet will be requested to connect to multiple chains
2552
+ * When multiple chains are requested, the wallet can switch between them
2553
+ * Default: 1 (Ethereum Mainnet)
2554
+ *
2555
+ * @example
2556
+ * // Single chain
2557
+ * await adapter.connect(1) // Ethereum only
2558
+ *
2559
+ * @example
2560
+ * // Multiple chains
2561
+ * await adapter.connect([1, 56, 137]) // Ethereum, BSC, Polygon
2562
+ */
2563
+ async connect(chainId) {
2564
+ if (typeof window === "undefined") {
2565
+ throw new Error("WalletConnect requires a browser environment");
2566
+ }
2567
+ if (_WalletConnectAdapter.providerInstance && _WalletConnectAdapter.providerProjectId === this.projectId) {
2568
+ const existingProvider = _WalletConnectAdapter.providerInstance;
2569
+ if (existingProvider.accounts && existingProvider.accounts.length > 0) {
2570
+ this.provider = existingProvider;
2571
+ let targetChains;
2572
+ if (Array.isArray(chainId)) {
2573
+ targetChains = chainId.length > 0 ? chainId : [1];
2574
+ } else if (chainId) {
2575
+ targetChains = [chainId];
2576
+ } else {
2577
+ targetChains = [1];
2578
+ }
2579
+ const existingChains = this.supportedChains || [];
2580
+ const mergedChains = [.../* @__PURE__ */ new Set([...existingChains, ...targetChains])];
2581
+ this.supportedChains = mergedChains;
2582
+ const currentChainId = existingProvider.chainId || targetChains[0];
2583
+ const address = formatEVMAddress(existingProvider.accounts[0]);
2584
+ const account = {
2585
+ universalAddress: createUniversalAddress(currentChainId, address),
2586
+ nativeAddress: address,
2587
+ chainId: currentChainId,
2588
+ chainType: ChainType.EVM,
2589
+ isActive: true
2590
+ };
2591
+ this.setState("connected" /* CONNECTED */);
2592
+ this.setAccount(account);
2593
+ if (!this.walletClient) {
2594
+ const viemChain = this.getViemChain(currentChainId);
2595
+ this.walletClient = createWalletClient({
2596
+ account: existingProvider.accounts[0],
2597
+ chain: viemChain,
2598
+ transport: custom(existingProvider)
2599
+ });
2600
+ const chainInfo = getChainInfo(currentChainId);
2601
+ const primaryRpcUrl = chainInfo?.rpcUrls[0];
2602
+ this.publicClient = createPublicClient({
2603
+ chain: viemChain,
2604
+ transport: primaryRpcUrl ? http(primaryRpcUrl) : custom(existingProvider)
2605
+ });
2606
+ this.setupEventListeners();
2607
+ }
2608
+ console.log("[WalletConnect] Reusing existing provider session");
2609
+ return account;
2610
+ }
2611
+ }
2612
+ if (this.state === "connected" /* CONNECTED */ && this.currentAccount && this.provider) {
2613
+ if (this.provider.accounts && this.provider.accounts.length > 0) {
2614
+ let targetChains;
2615
+ if (Array.isArray(chainId)) {
2616
+ targetChains = chainId.length > 0 ? chainId : [1];
2617
+ } else if (chainId) {
2618
+ targetChains = [chainId];
2619
+ } else {
2620
+ targetChains = [1];
2621
+ }
2622
+ const existingChains = this.supportedChains || [];
2623
+ const mergedChains = [.../* @__PURE__ */ new Set([...existingChains, ...targetChains])];
2624
+ this.supportedChains = mergedChains;
2625
+ console.log("[WalletConnect] Already connected, reusing existing connection");
2626
+ return this.currentAccount;
2627
+ } else {
2628
+ this.setState("disconnected" /* DISCONNECTED */);
2629
+ this.setAccount(null);
2630
+ this.provider = null;
2631
+ }
2632
+ }
2633
+ try {
2634
+ this.setState("connecting" /* CONNECTING */);
2635
+ let targetChains;
2636
+ if (Array.isArray(chainId)) {
2637
+ targetChains = chainId.length > 0 ? chainId : [1];
2638
+ } else if (chainId) {
2639
+ targetChains = [chainId];
2640
+ } else {
2641
+ targetChains = [1];
2642
+ }
2643
+ this.supportedChains = targetChains;
2644
+ const primaryChain = targetChains[0];
2645
+ const optionalChains = targetChains.slice(1);
2646
+ const isTelegram = this.isTelegramMiniApp();
2647
+ const telegramWebApp = this.getTelegramWebApp();
2648
+ let appUrl = "";
2649
+ if (typeof window !== "undefined") {
2650
+ try {
2651
+ if (window.location && window.location.origin) {
2652
+ appUrl = window.location.origin;
2653
+ } else if (window.location && window.location.href) {
2654
+ const url = new URL(window.location.href);
2655
+ appUrl = url.origin;
2656
+ }
2657
+ } catch (error) {
2658
+ console.warn("[WalletConnect] Failed to get origin from window.location:", error);
2659
+ }
2660
+ if (!appUrl) {
2661
+ appUrl = "https://enclave.network";
2662
+ }
2663
+ } else {
2664
+ appUrl = "https://enclave.network";
2665
+ }
2666
+ if (!appUrl || !appUrl.startsWith("http://") && !appUrl.startsWith("https://")) {
2667
+ appUrl = "https://enclave.network";
2668
+ }
2669
+ const icons = [
2670
+ "https://walletconnect.com/walletconnect-logo.svg",
2671
+ "https://avatars.githubusercontent.com/u/37784886"
2672
+ // WalletConnect GitHub avatar
2673
+ ];
2674
+ const initOptions = {
2675
+ projectId: this.projectId,
2676
+ chains: [primaryChain],
2677
+ // Primary chain (required)
2678
+ showQrModal: true,
2679
+ // QR modal works in Telegram Mini Apps
2680
+ metadata: {
2681
+ name: "Enclave Wallet SDK",
2682
+ description: "Multi-chain wallet adapter for Enclave",
2683
+ url: appUrl,
2684
+ icons
2685
+ }
2686
+ };
2687
+ if (isTelegram && telegramWebApp) {
2688
+ const platform = telegramWebApp.platform || "unknown";
2689
+ const isMiniApp = platform !== "web";
2690
+ console.log("[WalletConnect] Detected Telegram environment:", {
2691
+ platform,
2692
+ isMiniApp,
2693
+ isWeb: platform === "web"
2694
+ });
2695
+ if (telegramWebApp.isExpanded === false) {
2696
+ telegramWebApp.expand();
2697
+ }
2698
+ }
2699
+ if (optionalChains.length > 0) {
2700
+ initOptions.optionalChains = optionalChains;
2701
+ } else {
2702
+ initOptions.optionalChains = [primaryChain];
2703
+ }
2704
+ const hasExistingProvider = _WalletConnectAdapter.providerInstance && _WalletConnectAdapter.providerProjectId === this.projectId;
2705
+ const needsReinit = hasExistingProvider && _WalletConnectAdapter.providerChains !== null && JSON.stringify(_WalletConnectAdapter.providerChains.sort()) !== JSON.stringify(targetChains.sort());
2706
+ if (needsReinit) {
2707
+ console.log("[WalletConnect] Provider initialized with different chains, reinitializing...", {
2708
+ existing: _WalletConnectAdapter.providerChains,
2709
+ requested: targetChains
2710
+ });
2711
+ const existingProvider = _WalletConnectAdapter.providerInstance;
2712
+ if (existingProvider) {
2713
+ try {
2714
+ if (existingProvider.accounts && existingProvider.accounts.length > 0) {
2715
+ await existingProvider.disconnect();
2716
+ }
2717
+ } catch (error) {
2718
+ console.warn("[WalletConnect] Error disconnecting existing provider:", error);
2719
+ }
2720
+ }
2721
+ _WalletConnectAdapter.providerInstance = null;
2722
+ _WalletConnectAdapter.providerChains = null;
2723
+ }
2724
+ if (_WalletConnectAdapter.providerInstance && _WalletConnectAdapter.providerProjectId === this.projectId) {
2725
+ this.provider = _WalletConnectAdapter.providerInstance;
2726
+ console.log("[WalletConnect] Reusing existing provider instance");
2727
+ if (this.provider.accounts && this.provider.accounts.length > 0) {
2728
+ console.log("[WalletConnect] Provider already has accounts, skipping enable()");
2729
+ } else {
2730
+ const hasSession = this.provider.session !== void 0 && this.provider.session !== null;
2731
+ console.log("[WalletConnect] Provider has no accounts, calling enable() to show QR modal");
2732
+ console.log("[WalletConnect] Provider state:", {
2733
+ accounts: this.provider.accounts,
2734
+ chainId: this.provider.chainId,
2735
+ hasSession,
2736
+ sessionTopic: this.provider.session?.topic
2737
+ });
2738
+ if (hasSession && (!this.provider.accounts || this.provider.accounts.length === 0)) {
2739
+ console.log("[WalletConnect] Found stale session, disconnecting before reconnecting...");
2740
+ try {
2741
+ await this.provider.disconnect();
2742
+ await new Promise((resolve) => setTimeout(resolve, 100));
2743
+ } catch (disconnectError) {
2744
+ console.warn("[WalletConnect] Error disconnecting stale session:", disconnectError);
2745
+ }
2746
+ }
2747
+ try {
2748
+ console.log("[WalletConnect] Calling enable()...");
2749
+ const enableResult = await this.provider.enable();
2750
+ console.log("[WalletConnect] enable() completed, result:", enableResult);
2751
+ console.log("[WalletConnect] Provider state after enable():", {
2752
+ accounts: this.provider.accounts,
2753
+ chainId: this.provider.chainId,
2754
+ session: this.provider.session ? {
2755
+ topic: this.provider.session.topic,
2756
+ namespaces: this.provider.session.namespaces ? Object.keys(this.provider.session.namespaces) : "none"
2757
+ } : "none"
2758
+ });
2759
+ } catch (error) {
2760
+ console.error("[WalletConnect] enable() error:", error);
2761
+ if (error.code === 4001 || error.message?.includes("rejected") || error.message?.includes("User rejected")) {
2762
+ throw new ConnectionRejectedError(this.type);
2763
+ }
2764
+ throw error;
2765
+ }
2766
+ }
2767
+ } else if (_WalletConnectAdapter.providerInstance && _WalletConnectAdapter.providerProjectId === this.projectId) {
2768
+ this.provider = _WalletConnectAdapter.providerInstance;
2769
+ console.log("[WalletConnect] Reusing existing provider instance (not connected)");
2770
+ if (this.provider.accounts && this.provider.accounts.length > 0) {
2771
+ console.log("[WalletConnect] Provider already has accounts after init, skipping enable()");
2772
+ } else {
2773
+ const hasSession = this.provider.session !== void 0 && this.provider.session !== null;
2774
+ console.log("[WalletConnect] Provider has no accounts, calling enable() to show QR modal");
2775
+ console.log("[WalletConnect] Provider state:", {
2776
+ accounts: this.provider.accounts,
2777
+ chainId: this.provider.chainId,
2778
+ hasSession,
2779
+ sessionTopic: this.provider.session?.topic
2780
+ });
2781
+ if (hasSession && (!this.provider.accounts || this.provider.accounts.length === 0)) {
2782
+ console.log("[WalletConnect] Found stale session after init, disconnecting before reconnecting...");
2783
+ try {
2784
+ await this.provider.disconnect();
2785
+ await new Promise((resolve) => setTimeout(resolve, 100));
2786
+ } catch (disconnectError) {
2787
+ console.warn("[WalletConnect] Error disconnecting stale session:", disconnectError);
2788
+ }
2789
+ }
2790
+ try {
2791
+ await this.provider.enable();
2792
+ } catch (error) {
2793
+ console.error("[WalletConnect] enable() error:", error);
2794
+ if (error.code === 4001 || error.message?.includes("rejected") || error.message?.includes("User rejected")) {
2795
+ throw new ConnectionRejectedError(this.type);
2796
+ }
2797
+ throw error;
2798
+ }
2799
+ }
2800
+ } else if (_WalletConnectAdapter.isInitializing && _WalletConnectAdapter.initPromise) {
2801
+ console.log("[WalletConnect] Waiting for ongoing initialization...");
2802
+ this.provider = await _WalletConnectAdapter.initPromise;
2803
+ _WalletConnectAdapter.providerInstance = this.provider;
2804
+ _WalletConnectAdapter.providerProjectId = this.projectId;
2805
+ _WalletConnectAdapter.providerChains = targetChains;
2806
+ if (this.provider.accounts && this.provider.accounts.length > 0) {
2807
+ console.log("[WalletConnect] Provider already has accounts after init, skipping enable()");
2808
+ } else {
2809
+ try {
2810
+ await this.provider.enable();
2811
+ } catch (error) {
2812
+ if (error.code === 4001 || error.message?.includes("rejected") || error.message?.includes("User rejected")) {
2813
+ throw new ConnectionRejectedError(this.type);
2814
+ }
2815
+ throw error;
2816
+ }
2817
+ }
2818
+ } else {
2819
+ console.log("[WalletConnect] Initializing new provider with chains:", {
2820
+ primary: primaryChain,
2821
+ optional: optionalChains,
2822
+ all: targetChains
2823
+ });
2824
+ _WalletConnectAdapter.isInitializing = true;
2825
+ _WalletConnectAdapter.initPromise = EthereumProvider.init(initOptions);
2826
+ try {
2827
+ this.provider = await _WalletConnectAdapter.initPromise;
2828
+ _WalletConnectAdapter.providerInstance = this.provider;
2829
+ _WalletConnectAdapter.providerProjectId = this.projectId;
2830
+ _WalletConnectAdapter.providerChains = targetChains;
2831
+ if (this.provider.accounts && this.provider.accounts.length > 0) {
2832
+ console.log("[WalletConnect] Provider has restored session, skipping enable()");
2833
+ } else {
2834
+ const hasSession = this.provider.session !== void 0 && this.provider.session !== null;
2835
+ console.log("[WalletConnect] New provider initialized, calling enable() to show QR modal");
2836
+ console.log("[WalletConnect] Provider state:", {
2837
+ accounts: this.provider.accounts,
2838
+ chainId: this.provider.chainId,
2839
+ hasSession,
2840
+ sessionTopic: this.provider.session?.topic
2841
+ });
2842
+ if (hasSession && (!this.provider.accounts || this.provider.accounts.length === 0)) {
2843
+ console.log("[WalletConnect] Found stale session after init, disconnecting before reconnecting...");
2844
+ try {
2845
+ await this.provider.disconnect();
2846
+ await new Promise((resolve) => setTimeout(resolve, 100));
2847
+ } catch (disconnectError) {
2848
+ console.warn("[WalletConnect] Error disconnecting stale session:", disconnectError);
2849
+ }
2850
+ }
2851
+ try {
2852
+ await this.provider.enable();
2853
+ } catch (error) {
2854
+ console.error("[WalletConnect] enable() error:", error);
2855
+ if (error.code === 4001 || error.message?.includes("rejected") || error.message?.includes("User rejected")) {
2856
+ throw new ConnectionRejectedError(this.type);
2857
+ }
2858
+ throw error;
2859
+ }
2860
+ }
2861
+ } finally {
2862
+ _WalletConnectAdapter.isInitializing = false;
2863
+ _WalletConnectAdapter.initPromise = null;
2864
+ }
2865
+ }
2866
+ let accounts = this.provider.accounts;
2867
+ if (!accounts || accounts.length === 0) {
2868
+ console.log("[WalletConnect] provider.accounts is empty, checking session.namespaces.eip155.accounts...");
2869
+ const session = this.provider.session;
2870
+ if (session && session.namespaces?.eip155?.accounts) {
2871
+ const sessionAccounts = session.namespaces.eip155.accounts.map((acc) => {
2872
+ const parts = acc.split(":");
2873
+ if (parts.length >= 3 && parts[0] === "eip155") {
2874
+ return parts[2];
2875
+ }
2876
+ return null;
2877
+ }).filter((addr) => addr !== null && addr.startsWith("0x"));
2878
+ if (sessionAccounts.length > 0) {
2879
+ const uniqueAccounts = [...new Set(sessionAccounts)];
2880
+ console.log("[WalletConnect] Found accounts in session.namespaces.eip155.accounts:", {
2881
+ raw: session.namespaces.eip155.accounts,
2882
+ extracted: uniqueAccounts,
2883
+ chains: session.namespaces.eip155.chains
2884
+ });
2885
+ accounts = uniqueAccounts;
2886
+ }
2887
+ }
2888
+ }
2889
+ if (!accounts || accounts.length === 0) {
2890
+ console.log("[WalletConnect] Accounts not available, waiting for provider.accounts to populate...");
2891
+ const maxWaitTime = 3e3;
2892
+ const checkInterval = 100;
2893
+ const maxChecks = maxWaitTime / checkInterval;
2894
+ for (let i = 0; i < maxChecks; i++) {
2895
+ await new Promise((resolve) => setTimeout(resolve, checkInterval));
2896
+ accounts = this.provider.accounts;
2897
+ if (accounts && accounts.length > 0) {
2898
+ console.log(`[WalletConnect] Accounts available after ${(i + 1) * checkInterval}ms`);
2899
+ break;
2900
+ }
2901
+ }
2902
+ }
2903
+ if (!accounts || accounts.length === 0) {
2904
+ const session = this.provider.session;
2905
+ const providerState = {
2906
+ providerAccounts: this.provider.accounts,
2907
+ providerChainId: this.provider.chainId,
2908
+ session: session ? {
2909
+ exists: true,
2910
+ topic: session.topic,
2911
+ namespaces: session.namespaces ? Object.keys(session.namespaces) : "none",
2912
+ eip155Namespace: session.namespaces?.eip155 ? {
2913
+ accounts: session.namespaces.eip155.accounts,
2914
+ // CAIP-10 format
2915
+ chains: session.namespaces.eip155.chains,
2916
+ // CAIP-2 format
2917
+ methods: session.namespaces.eip155.methods,
2918
+ events: session.namespaces.eip155.events
2919
+ } : "none",
2920
+ // Log full session structure for debugging
2921
+ fullSession: JSON.stringify(session, null, 2)
2922
+ } : "none",
2923
+ // Check if provider has any other properties that might contain accounts
2924
+ providerKeys: Object.keys(this.provider)
2925
+ };
2926
+ console.error("[WalletConnect] No accounts available after enable() and wait", providerState);
2927
+ console.error("[WalletConnect] Full provider object:", this.provider);
2928
+ console.error("[WalletConnect] Full session object:", session);
2929
+ console.error("[WalletConnect] Session namespaces structure:", session?.namespaces);
2930
+ throw new Error("WalletConnect connection established but no accounts available. Please check session.namespaces.eip155.accounts in the console logs above.");
2931
+ }
2932
+ const currentChainId = this.provider.chainId || targetChains[0];
2933
+ const viemChain = this.getViemChain(currentChainId);
2934
+ this.walletClient = createWalletClient({
2935
+ account: accounts[0],
2936
+ chain: viemChain,
2937
+ transport: custom(this.provider)
2938
+ });
2939
+ const chainInfo = getChainInfo(currentChainId);
2940
+ const primaryRpcUrl = chainInfo?.rpcUrls[0];
2941
+ this.publicClient = createPublicClient({
2942
+ chain: viemChain,
2943
+ transport: primaryRpcUrl ? http(primaryRpcUrl) : custom(this.provider)
2944
+ });
2945
+ const address = formatEVMAddress(accounts[0]);
2946
+ const account = {
2947
+ universalAddress: createUniversalAddress(currentChainId, address),
2948
+ nativeAddress: address,
2949
+ chainId: currentChainId,
2950
+ chainType: ChainType.EVM,
2951
+ isActive: true
2952
+ };
2953
+ this.setState("connected" /* CONNECTED */);
2954
+ this.setAccount(account);
2955
+ this.setupEventListeners();
2956
+ return account;
2957
+ } catch (error) {
2958
+ this.setState("error" /* ERROR */);
2959
+ this.setAccount(null);
2960
+ const origin = typeof window !== "undefined" && window.location ? window.location.origin : "";
2961
+ const errorCode = error?.code;
2962
+ const errorMessage = error?.message || String(error);
2963
+ const isOriginNotAllowed = errorCode === 3e3 || /origin not allowed/i.test(errorMessage) || /Unauthorized:\s*origin not allowed/i.test(errorMessage);
2964
+ const session = this.provider?.session;
2965
+ const providerState = this.provider ? {
2966
+ accounts: this.provider.accounts,
2967
+ chainId: this.provider.chainId,
2968
+ session: session ? {
2969
+ exists: true,
2970
+ topic: session.topic,
2971
+ namespaces: session.namespaces ? Object.keys(session.namespaces) : "none",
2972
+ eip155Namespace: session.namespaces?.eip155 ? {
2973
+ accounts: session.namespaces.eip155.accounts,
2974
+ chains: session.namespaces.eip155.chains,
2975
+ methods: session.namespaces.eip155.methods,
2976
+ events: session.namespaces.eip155.events
2977
+ } : "none"
2978
+ } : "none",
2979
+ providerKeys: Object.keys(this.provider)
2980
+ } : "no provider";
2981
+ console.error("[WalletConnect] Connection error:", {
2982
+ error,
2983
+ code: error.code,
2984
+ message: error.message,
2985
+ stack: error.stack,
2986
+ providerState
2987
+ });
2988
+ if (this.provider) {
2989
+ console.error("[WalletConnect] Full provider object:", this.provider);
2990
+ console.error("[WalletConnect] Full session object:", session);
2991
+ }
2992
+ if (error.code === 4001 || error.message && (error.message.includes("User rejected") || error.message.includes("rejected by user") || error.message.includes("User cancelled"))) {
2993
+ throw new ConnectionRejectedError(this.type);
2994
+ }
2995
+ if (isOriginNotAllowed) {
2996
+ throw new ConfigurationError(
2997
+ `WalletConnect relayer rejected this origin (code 3000: Unauthorized: origin not allowed).
2998
+
2999
+ Fix:
3000
+ 1) Open WalletConnect Cloud \u2192 your project (${this.projectId})
3001
+ 2) Add this site origin to the allowlist:
3002
+ - ${origin || "(unknown origin)"}
3003
+
3004
+ Common dev origins to allow:
3005
+ - http://localhost:5173
3006
+ - http://192.168.0.221:5173 (your LAN dev URL)
3007
+ - https://wallet-test.enclave-hq.com (your Cloudflare Tunnel/custom domain)
3008
+
3009
+ Original error: ${errorMessage}`
3010
+ );
3011
+ }
3012
+ throw error;
3013
+ }
3014
+ }
3015
+ /**
3016
+ * Disconnect wallet
3017
+ */
3018
+ async disconnect() {
3019
+ if (this.provider) {
3020
+ try {
3021
+ await this.provider.disconnect();
3022
+ } catch (error) {
3023
+ console.warn("[WalletConnect] Error during disconnect:", error);
3024
+ }
3025
+ if (_WalletConnectAdapter.providerInstance === this.provider) {
3026
+ _WalletConnectAdapter.providerInstance = null;
3027
+ _WalletConnectAdapter.providerProjectId = null;
3028
+ _WalletConnectAdapter.providerChains = null;
3029
+ }
3030
+ this.provider = null;
3031
+ }
3032
+ this.removeEventListeners();
3033
+ this.walletClient = null;
3034
+ this.publicClient = null;
3035
+ this.setState("disconnected" /* DISCONNECTED */);
3036
+ this.setAccount(null);
3037
+ this.emitDisconnected();
3038
+ }
3039
+ /**
3040
+ * Sign message
3041
+ */
3042
+ async signMessage(message) {
3043
+ this.ensureConnected();
3044
+ try {
3045
+ if (!this.provider) {
3046
+ throw new Error("Provider not initialized");
3047
+ }
3048
+ const signature = await this.provider.request({
3049
+ method: "personal_sign",
3050
+ params: [message, this.currentAccount.nativeAddress]
3051
+ });
3052
+ this.closeTelegramDeepLinkPopup();
3053
+ return signature;
3054
+ } catch (error) {
3055
+ if (error.code === 4001 || error.message?.includes("rejected")) {
3056
+ throw new SignatureRejectedError();
3057
+ }
3058
+ throw error;
3059
+ }
3060
+ }
3061
+ /**
3062
+ * Sign TypedData (EIP-712)
3063
+ */
3064
+ async signTypedData(typedData) {
3065
+ this.ensureConnected();
3066
+ try {
3067
+ if (!this.provider) {
3068
+ throw new Error("Provider not initialized");
3069
+ }
3070
+ const signature = await this.provider.request({
3071
+ method: "eth_signTypedData_v4",
3072
+ params: [this.currentAccount.nativeAddress, JSON.stringify(typedData)]
3073
+ });
3074
+ this.closeTelegramDeepLinkPopup();
3075
+ return signature;
3076
+ } catch (error) {
3077
+ if (error.code === 4001 || error.message?.includes("rejected")) {
3078
+ throw new SignatureRejectedError();
3079
+ }
3080
+ throw error;
3081
+ }
3082
+ }
3083
+ /**
3084
+ * Sign transaction
3085
+ */
3086
+ async signTransaction(transaction) {
3087
+ this.ensureConnected();
3088
+ try {
3089
+ if (!this.provider) {
3090
+ throw new Error("Provider not initialized");
3091
+ }
3092
+ const tx = {
3093
+ from: this.currentAccount.nativeAddress,
3094
+ to: transaction.to,
3095
+ value: transaction.value ? `0x${BigInt(transaction.value).toString(16)}` : void 0,
3096
+ data: transaction.data || "0x",
3097
+ gas: transaction.gas ? `0x${BigInt(transaction.gas).toString(16)}` : void 0,
3098
+ gasPrice: transaction.gasPrice && transaction.gasPrice !== "auto" ? `0x${BigInt(transaction.gasPrice).toString(16)}` : void 0,
3099
+ maxFeePerGas: transaction.maxFeePerGas ? `0x${BigInt(transaction.maxFeePerGas).toString(16)}` : void 0,
3100
+ maxPriorityFeePerGas: transaction.maxPriorityFeePerGas ? `0x${BigInt(transaction.maxPriorityFeePerGas).toString(16)}` : void 0,
3101
+ nonce: transaction.nonce !== void 0 ? `0x${transaction.nonce.toString(16)}` : void 0,
3102
+ chainId: transaction.chainId || this.currentAccount.chainId
3103
+ };
3104
+ const signature = await this.provider.request({
3105
+ method: "eth_signTransaction",
3106
+ params: [tx]
3107
+ });
3108
+ this.closeTelegramDeepLinkPopup();
3109
+ return signature;
3110
+ } catch (error) {
3111
+ if (error.code === 4001 || error.message?.includes("rejected")) {
3112
+ throw new SignatureRejectedError("Transaction signature was rejected by user");
3113
+ }
3114
+ throw error;
3115
+ }
3116
+ }
3117
+ /**
3118
+ * Get supported chains from current connection
3119
+ * Returns the chains that were requested during connection
3120
+ */
3121
+ getSupportedChains() {
3122
+ return [...this.supportedChains];
3123
+ }
3124
+ /**
3125
+ * Switch chain
3126
+ *
3127
+ * Note: WalletConnect v2 with mobile wallets may not support chain switching reliably.
3128
+ * Some wallets may ignore the switch request or fail silently.
3129
+ * It's recommended to include all needed chains in the initial connection.
3130
+ *
3131
+ * Reference: https://specs.walletconnect.com/2.0/specs/clients/sign/namespaces
3132
+ */
3133
+ async switchChain(chainId) {
3134
+ if (!this.provider) {
3135
+ throw new Error("Provider not initialized");
3136
+ }
3137
+ const session = this.provider.session;
3138
+ const supportedChains = session?.namespaces?.eip155?.chains || [];
3139
+ const targetChainCAIP = `eip155:${chainId}`;
3140
+ const isChainApproved = supportedChains.includes(targetChainCAIP);
3141
+ if (!isChainApproved) {
3142
+ console.warn(`[WalletConnect] Chain ${chainId} (${targetChainCAIP}) not in session approved chains:`, supportedChains);
3143
+ console.warn("[WalletConnect] Chain switching may fail. Consider including all chains in initial connection.");
3144
+ }
3145
+ try {
3146
+ console.log(`[WalletConnect] Attempting to switch to chain ${chainId} (${targetChainCAIP})`);
3147
+ const result = await this.provider.request({
3148
+ method: "wallet_switchEthereumChain",
3149
+ params: [{ chainId: `0x${chainId.toString(16)}` }]
3150
+ });
3151
+ if (result !== null && result !== void 0) {
3152
+ console.warn("[WalletConnect] wallet_switchEthereumChain returned non-null result:", result);
3153
+ }
3154
+ await new Promise((resolve) => setTimeout(resolve, 500));
3155
+ const currentChainId = this.provider.chainId;
3156
+ if (currentChainId !== chainId) {
3157
+ console.warn(`[WalletConnect] Chain switch may have failed. Expected ${chainId}, got ${currentChainId}`);
3158
+ console.warn("[WalletConnect] Some mobile wallets may not support chain switching via WalletConnect.");
3159
+ console.warn("[WalletConnect] User may need to manually switch chains in the wallet app.");
3160
+ }
3161
+ if (this.currentAccount) {
3162
+ const updatedAccount = {
3163
+ ...this.currentAccount,
3164
+ chainId,
3165
+ universalAddress: createUniversalAddress(chainId, this.currentAccount.nativeAddress)
3166
+ };
3167
+ this.setAccount(updatedAccount);
3168
+ this.emitChainChanged(chainId);
3169
+ const viemChain = this.getViemChain(chainId);
3170
+ const chainInfo = getChainInfo(chainId);
3171
+ const primaryRpcUrl = chainInfo?.rpcUrls[0];
3172
+ this.walletClient = createWalletClient({
3173
+ account: this.currentAccount.nativeAddress,
3174
+ chain: viemChain,
3175
+ transport: custom(this.provider)
3176
+ });
3177
+ this.publicClient = createPublicClient({
3178
+ chain: viemChain,
3179
+ transport: primaryRpcUrl ? http(primaryRpcUrl) : custom(this.provider)
3180
+ });
3181
+ }
3182
+ } catch (error) {
3183
+ console.error("[WalletConnect] Chain switch error:", {
3184
+ chainId,
3185
+ errorCode: error.code,
3186
+ errorMessage: error.message,
3187
+ supportedChains
3188
+ });
3189
+ if (error.code === 4902) {
3190
+ console.log(`[WalletConnect] Chain ${chainId} not found in wallet, attempting to add...`);
3191
+ const chainInfo = getChainInfo(chainId);
3192
+ if (chainInfo) {
3193
+ try {
3194
+ await this.addChain({
3195
+ chainId: chainInfo.id,
3196
+ chainName: chainInfo.name,
3197
+ nativeCurrency: chainInfo.nativeCurrency,
3198
+ rpcUrls: chainInfo.rpcUrls,
3199
+ blockExplorerUrls: chainInfo.blockExplorerUrls
3200
+ });
3201
+ console.log(`[WalletConnect] Chain added, attempting to switch again...`);
3202
+ await this.switchChain(chainId);
3203
+ } catch (addError) {
3204
+ console.error("[WalletConnect] Failed to add chain:", addError);
3205
+ throw new Error(`Failed to add chain ${chainId}: ${addError.message}`);
3206
+ }
3207
+ } else {
3208
+ throw new Error(`Chain ${chainId} not supported`);
3209
+ }
3210
+ } else if (error.code === 4001) {
3211
+ throw new Error("User rejected chain switch");
3212
+ } else if (error.code === 4100) {
3213
+ throw new Error("Wallet does not support wallet_switchEthereumChain. Please switch chains manually in your wallet app.");
3214
+ } else {
3215
+ console.warn("[WalletConnect] Chain switch may not be supported by this wallet. User may need to switch manually.");
3216
+ throw error;
3217
+ }
3218
+ }
3219
+ }
3220
+ /**
3221
+ * Add chain
3222
+ */
3223
+ async addChain(chainConfig) {
3224
+ if (!this.provider) {
3225
+ throw new Error("Provider not initialized");
3226
+ }
3227
+ await this.provider.request({
3228
+ method: "wallet_addEthereumChain",
3229
+ params: [{
3230
+ chainId: `0x${chainConfig.chainId.toString(16)}`,
3231
+ chainName: chainConfig.chainName,
3232
+ nativeCurrency: chainConfig.nativeCurrency,
3233
+ rpcUrls: chainConfig.rpcUrls,
3234
+ blockExplorerUrls: chainConfig.blockExplorerUrls
3235
+ }]
3236
+ });
3237
+ }
3238
+ /**
3239
+ * Read contract
3240
+ */
3241
+ async readContract(params) {
3242
+ if (!this.publicClient) {
3243
+ throw new Error("Public client not initialized");
3244
+ }
3245
+ const result = await this.publicClient.readContract({
3246
+ address: params.address,
3247
+ abi: params.abi,
3248
+ functionName: params.functionName,
3249
+ ...params.args ? { args: params.args } : {}
3250
+ });
3251
+ return result;
3252
+ }
3253
+ /**
3254
+ * Write contract
3255
+ */
3256
+ async writeContract(params) {
3257
+ this.ensureConnected();
3258
+ if (!this.walletClient) {
3259
+ throw new Error("Wallet client not initialized");
3260
+ }
3261
+ try {
3262
+ const txOptions = {
3263
+ address: params.address,
3264
+ abi: params.abi,
3265
+ functionName: params.functionName,
3266
+ ...params.args ? { args: params.args } : {},
3267
+ value: params.value ? BigInt(params.value) : void 0,
3268
+ gas: params.gas ? BigInt(params.gas) : void 0
3269
+ };
3270
+ if (params.maxFeePerGas || params.maxPriorityFeePerGas) {
3271
+ if (params.maxFeePerGas) {
3272
+ txOptions.maxFeePerGas = BigInt(params.maxFeePerGas);
3273
+ }
3274
+ if (params.maxPriorityFeePerGas) {
3275
+ txOptions.maxPriorityFeePerGas = BigInt(params.maxPriorityFeePerGas);
3276
+ }
3277
+ } else if (params.gasPrice && params.gasPrice !== "auto") {
3278
+ txOptions.gasPrice = BigInt(params.gasPrice);
3279
+ } else {
3280
+ if (this.publicClient) {
3281
+ try {
3282
+ const feesPerGas = await this.publicClient.estimateFeesPerGas().catch(() => null);
3283
+ if (feesPerGas) {
3284
+ const minPriorityFeeWei = BigInt(1e8);
3285
+ const maxPriorityFeePerGas = feesPerGas.maxPriorityFeePerGas > minPriorityFeeWei ? feesPerGas.maxPriorityFeePerGas : minPriorityFeeWei;
3286
+ const adjustedMaxFeePerGas = feesPerGas.maxFeePerGas > maxPriorityFeePerGas ? feesPerGas.maxFeePerGas : maxPriorityFeePerGas + BigInt(1e9);
3287
+ txOptions.maxFeePerGas = adjustedMaxFeePerGas;
3288
+ txOptions.maxPriorityFeePerGas = maxPriorityFeePerGas;
3289
+ } else {
3290
+ const gasPrice = await this.publicClient.getGasPrice();
3291
+ txOptions.gasPrice = gasPrice;
3292
+ }
3293
+ } catch (err) {
3294
+ }
3295
+ }
3296
+ }
3297
+ const txHash = await this.walletClient.writeContract(txOptions);
3298
+ this.closeTelegramDeepLinkPopup();
3299
+ return txHash;
3300
+ } catch (error) {
3301
+ if (error.code === 4001 || error.message?.includes("rejected")) {
3302
+ throw new SignatureRejectedError("Transaction was rejected by user");
3303
+ }
3304
+ throw error;
3305
+ }
3306
+ }
3307
+ /**
3308
+ * Estimate gas
3309
+ */
3310
+ async estimateGas(params) {
3311
+ if (!this.publicClient) {
3312
+ throw new Error("Public client not initialized");
3313
+ }
3314
+ const gas = await this.publicClient.estimateContractGas({
3315
+ address: params.address,
3316
+ abi: params.abi,
3317
+ functionName: params.functionName,
3318
+ ...params.args ? { args: params.args } : {},
3319
+ value: params.value ? BigInt(params.value) : void 0,
3320
+ account: this.currentAccount.nativeAddress
3321
+ });
3322
+ return gas;
3323
+ }
3324
+ /**
3325
+ * Wait for transaction
3326
+ */
3327
+ async waitForTransaction(txHash, confirmations = 1) {
3328
+ if (!this.publicClient) {
3329
+ throw new Error("Public client not initialized");
3330
+ }
3331
+ const receipt = await this.publicClient.waitForTransactionReceipt({
3332
+ hash: txHash,
3333
+ confirmations
3334
+ });
3335
+ if (receipt.status === "reverted") {
3336
+ throw new TransactionFailedError(txHash, "Transaction reverted");
3337
+ }
3338
+ return {
3339
+ transactionHash: receipt.transactionHash,
3340
+ blockNumber: Number(receipt.blockNumber),
3341
+ blockHash: receipt.blockHash,
3342
+ from: receipt.from,
3343
+ to: receipt.to || void 0,
3344
+ status: receipt.status === "success" ? "success" : "failed",
3345
+ gasUsed: receipt.gasUsed.toString(),
3346
+ effectiveGasPrice: receipt.effectiveGasPrice?.toString(),
3347
+ logs: receipt.logs
3348
+ };
3349
+ }
3350
+ /**
3351
+ * Get provider
3352
+ */
3353
+ getProvider() {
3354
+ return this.provider;
3355
+ }
3356
+ /**
3357
+ * Get signer
3358
+ */
3359
+ getSigner() {
3360
+ return this.walletClient;
3361
+ }
3362
+ /**
3363
+ * Setup event listeners
3364
+ */
3365
+ setupEventListeners() {
3366
+ if (!this.provider) return;
3367
+ this.provider.on("accountsChanged", this.handleAccountsChanged);
3368
+ this.provider.on("chainChanged", this.handleChainChanged);
3369
+ this.provider.on("disconnect", this.handleDisconnect);
3370
+ }
3371
+ /**
3372
+ * Remove event listeners
3373
+ */
3374
+ removeEventListeners() {
3375
+ if (!this.provider) return;
3376
+ this.provider.removeListener("accountsChanged", this.handleAccountsChanged);
3377
+ this.provider.removeListener("chainChanged", this.handleChainChanged);
3378
+ this.provider.removeListener("disconnect", this.handleDisconnect);
3379
+ }
3380
+ /**
3381
+ * Get viem chain config
3382
+ */
3383
+ getViemChain(chainId) {
3384
+ const chainInfo = getChainInfo(chainId);
3385
+ if (chainInfo) {
3386
+ return {
3387
+ id: chainId,
3388
+ name: chainInfo.name,
3389
+ network: chainInfo.name.toLowerCase().replace(/\s+/g, "-"),
3390
+ nativeCurrency: chainInfo.nativeCurrency,
3391
+ rpcUrls: {
3392
+ default: { http: chainInfo.rpcUrls },
3393
+ public: { http: chainInfo.rpcUrls }
3394
+ },
3395
+ blockExplorers: chainInfo.blockExplorerUrls ? {
3396
+ default: { name: "Explorer", url: chainInfo.blockExplorerUrls[0] }
3397
+ } : void 0
3398
+ };
3399
+ }
3400
+ return {
3401
+ id: chainId,
3402
+ name: `Chain ${chainId}`,
3403
+ network: `chain-${chainId}`,
3404
+ nativeCurrency: {
3405
+ name: "ETH",
3406
+ symbol: "ETH",
3407
+ decimals: 18
3408
+ },
3409
+ rpcUrls: {
3410
+ default: { http: [] },
3411
+ public: { http: [] }
3412
+ }
3413
+ };
3414
+ }
3415
+ };
3416
+ // Store supported chains from connection
3417
+ // Static provider instance to avoid multiple initializations
3418
+ _WalletConnectAdapter.providerInstance = null;
3419
+ _WalletConnectAdapter.providerProjectId = null;
3420
+ _WalletConnectAdapter.providerChains = null;
3421
+ // Store the chains used during initialization
3422
+ _WalletConnectAdapter.isInitializing = false;
3423
+ _WalletConnectAdapter.initPromise = null;
3424
+ var WalletConnectAdapter = _WalletConnectAdapter;
3425
+
3426
+ // src/adapters/tron/wallet-connect.ts
3427
+ var wallet_connect_exports = {};
3428
+ __export(wallet_connect_exports, {
3429
+ WalletConnectTronAdapter: () => WalletConnectTronAdapter
3430
+ });
3431
+ init_types();
3432
+ var _WalletConnectTronAdapter = class _WalletConnectTronAdapter extends WalletAdapter {
3433
+ constructor(projectId) {
3434
+ super();
3435
+ this.type = "walletconnect-tron" /* WALLETCONNECT_TRON */;
3436
+ this.chainType = ChainType.TRON;
3437
+ this.name = "WalletConnect (Tron)";
3438
+ this.icon = "https://avatars.githubusercontent.com/u/37784886";
3439
+ this.wallet = null;
3440
+ this.currentAddress = null;
3441
+ if (!projectId) {
3442
+ throw new ConfigurationError("WalletConnect projectId is required");
3443
+ }
3444
+ this.projectId = projectId;
3445
+ }
3446
+ /**
3447
+ * Check if WalletConnect is available
3448
+ */
3449
+ async isAvailable() {
3450
+ return typeof window !== "undefined";
3451
+ }
3452
+ /**
3453
+ * Check if running in Telegram environment (Mini App or Web)
3454
+ * Both Telegram Mini App (in client) and Telegram Web (web.telegram.org)
3455
+ * provide window.Telegram.WebApp API, so they are treated the same way.
3456
+ */
3457
+ isTelegramMiniApp() {
3458
+ if (typeof window === "undefined") return false;
3459
+ const tg = window.Telegram?.WebApp;
3460
+ if (!tg) return false;
3461
+ const platform = tg.platform || "unknown";
3462
+ console.log("[WalletConnect Tron] Telegram environment detected:", {
3463
+ platform,
3464
+ version: tg.version,
3465
+ isMiniApp: platform !== "web",
3466
+ // Mini App if not web platform
3467
+ isWeb: platform === "web"
3468
+ // Telegram Web if web platform
3469
+ });
3470
+ return true;
3471
+ }
3472
+ /**
3473
+ * Restore session from existing wallet (for storage restoration)
3474
+ */
3475
+ async restoreSession(chainId) {
3476
+ if (typeof window === "undefined") {
3477
+ return null;
3478
+ }
3479
+ try {
3480
+ const targetChainId = Array.isArray(chainId) ? chainId[0] || _WalletConnectTronAdapter.TRON_MAINNET_CHAIN_ID : chainId || _WalletConnectTronAdapter.TRON_MAINNET_CHAIN_ID;
3481
+ if (!_WalletConnectTronAdapter.walletInstance || _WalletConnectTronAdapter.walletProjectId !== this.projectId) {
3482
+ this.initializeWallet(targetChainId);
3483
+ }
3484
+ this.wallet = _WalletConnectTronAdapter.walletInstance;
3485
+ if (!this.wallet) {
3486
+ return null;
3487
+ }
3488
+ const status = await this.wallet.checkConnectStatus();
3489
+ if (status && status.address) {
3490
+ this.currentAddress = status.address;
3491
+ const account = {
3492
+ universalAddress: createUniversalAddress(targetChainId, status.address),
3493
+ nativeAddress: status.address,
3494
+ chainId: targetChainId,
3495
+ chainType: ChainType.TRON,
3496
+ isActive: true
3497
+ };
3498
+ this.setState("connected" /* CONNECTED */);
3499
+ this.setAccount(account);
3500
+ this.setupEventListeners();
3501
+ return account;
3502
+ }
3503
+ return null;
3504
+ } catch (error) {
3505
+ console.debug("[WalletConnect Tron] Restore session failed:", error);
3506
+ return null;
3507
+ }
3508
+ }
3509
+ /**
3510
+ * Initialize WalletConnect wallet instance
3511
+ * @param chainId - Optional chain ID to determine network (default: Mainnet)
3512
+ */
3513
+ initializeWallet(chainId) {
3514
+ if (_WalletConnectTronAdapter.walletInstance && _WalletConnectTronAdapter.walletProjectId === this.projectId) {
3515
+ return;
3516
+ }
3517
+ let appUrl = "";
3518
+ if (typeof window !== "undefined") {
3519
+ try {
3520
+ if (window.location && window.location.origin) {
3521
+ appUrl = window.location.origin;
3522
+ } else if (window.location && window.location.href) {
3523
+ const url = new URL(window.location.href);
3524
+ appUrl = url.origin;
3525
+ }
3526
+ } catch (error) {
3527
+ console.warn("[WalletConnect Tron] Failed to get origin from window.location:", error);
3528
+ }
3529
+ if (appUrl && (appUrl.includes("serveo.net") || appUrl.includes("loca.lt") || appUrl.includes("ngrok.io") || appUrl.includes("ngrok-free.app") || appUrl.includes("cloudflared.io"))) {
3530
+ console.log("[WalletConnect Tron] Detected tunnel service URL:", appUrl);
3531
+ console.log("[WalletConnect Tron] \u26A0\uFE0F Make sure this URL is added to WalletConnect Cloud project allowlist");
3532
+ }
3533
+ if (!appUrl) {
3534
+ const tg = window.Telegram?.WebApp;
3535
+ if (tg && tg.initDataUnsafe?.start_param) {
3536
+ appUrl = "https://enclave.network";
3537
+ } else {
3538
+ appUrl = "https://enclave.network";
3539
+ }
3540
+ }
3541
+ } else {
3542
+ appUrl = "https://enclave.network";
3543
+ }
3544
+ if (!appUrl || !appUrl.startsWith("http://") && !appUrl.startsWith("https://")) {
3545
+ appUrl = "https://enclave.network";
3546
+ }
3547
+ const icons = [
3548
+ "https://walletconnect.com/walletconnect-logo.svg",
3549
+ "https://avatars.githubusercontent.com/u/37784886"
3550
+ // WalletConnect GitHub avatar
3551
+ ];
3552
+ let network = WalletConnectChainID.Mainnet;
3553
+ if (chainId !== void 0) {
3554
+ if (chainId === 195 || chainId === _WalletConnectTronAdapter.TRON_MAINNET_CHAIN_ID) {
3555
+ network = WalletConnectChainID.Mainnet;
3556
+ } else if (chainId === 201910292) {
3557
+ network = WalletConnectChainID.Shasta;
3558
+ } else if (chainId === 2494104990) {
3559
+ network = WalletConnectChainID.Nile;
3560
+ }
3561
+ }
3562
+ const metadataInfo = {
3563
+ name: "Enclave Wallet SDK",
3564
+ description: "Multi-chain wallet adapter for Enclave",
3565
+ url: appUrl,
3566
+ icons,
3567
+ network,
3568
+ chainId,
3569
+ isTelegram: this.isTelegramMiniApp(),
3570
+ projectId: this.projectId,
3571
+ urlValid: appUrl && (appUrl.startsWith("http://") || appUrl.startsWith("https://")),
3572
+ iconsValid: icons && icons.length > 0 && icons.every((icon) => icon && icon.startsWith("http")),
3573
+ currentLocation: typeof window !== "undefined" ? window.location.href : "N/A",
3574
+ telegramPlatform: typeof window !== "undefined" && window.Telegram?.WebApp?.platform || "N/A"
3575
+ };
3576
+ console.log("[WalletConnect Tron] Initializing with metadata:", metadataInfo);
3577
+ if (!metadataInfo.urlValid) {
3578
+ console.warn("[WalletConnect Tron] \u26A0\uFE0F Invalid URL in metadata:", appUrl);
3579
+ }
3580
+ if (!metadataInfo.iconsValid) {
3581
+ console.warn("[WalletConnect Tron] \u26A0\uFE0F Invalid icons in metadata:", icons);
3582
+ }
3583
+ console.log("[WalletConnect Tron] Initializing wallet...", {
3584
+ network,
3585
+ chainId,
3586
+ note: "If no wallets are in WalletConnect Explorer for TRON, QR code will be displayed for scanning"
3587
+ });
3588
+ _WalletConnectTronAdapter.walletInstance = new WalletConnectWallet({
3589
+ network,
3590
+ options: {
3591
+ projectId: this.projectId,
3592
+ metadata: {
3593
+ name: "Enclave Wallet SDK",
3594
+ description: "Multi-chain wallet adapter for Enclave",
3595
+ url: appUrl,
3596
+ icons
3597
+ }
3598
+ },
3599
+ // Theme configuration
3600
+ themeMode: "light",
3601
+ themeVariables: {
3602
+ "--w3m-z-index": 1e4
3603
+ // Ensure modal appears above Telegram UI
3604
+ },
3605
+ // Web3Modal configuration for recommended wallets
3606
+ // According to official docs: https://developers.tron.network/docs/walletconnect-tron
3607
+ // Note: If no wallets are registered in WalletConnect Explorer for TRON,
3608
+ // explorerRecommendedWalletIds will have no effect, and QR code will be shown instead.
3609
+ // @ts-ignore - web3ModalConfig is supported but may not be in TypeScript types
3610
+ web3ModalConfig: {
3611
+ themeMode: "light",
3612
+ themeVariables: {
3613
+ "--w3m-z-index": 1e4
3614
+ },
3615
+ /**
3616
+ * Recommended Wallets are fetched from WalletConnect explore api:
3617
+ * https://walletconnect.com/explorer?type=wallet&version=2
3618
+ *
3619
+ * IMPORTANT: If wallets are not registered in Explorer for TRON, this list will be ignored.
3620
+ * The AppKit will show a QR code instead, which users can scan with any WalletConnect-compatible wallet.
3621
+ *
3622
+ * Wallet IDs (for reference, may not work if not in Explorer):
3623
+ * - TokenPocket: 20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66
3624
+ * - TronLink: 1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369
3625
+ */
3626
+ explorerRecommendedWalletIds: [
3627
+ // These IDs are kept for when wallets register in WalletConnect Explorer
3628
+ // Currently, if no TRON wallets are in Explorer, QR code will be shown
3629
+ "20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66",
3630
+ // TokenPocket
3631
+ "1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369",
3632
+ // TronLink
3633
+ "4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0"
3634
+ // TokenPocket (backup)
3635
+ ]
3636
+ }
3637
+ });
3638
+ _WalletConnectTronAdapter.walletProjectId = this.projectId;
3639
+ }
3640
+ /**
3641
+ * Connect wallet
3642
+ */
3643
+ async connect(chainId) {
3644
+ if (typeof window === "undefined") {
3645
+ throw new Error("WalletConnect requires a browser environment");
3646
+ }
3647
+ const currentState = this.state;
3648
+ if (currentState === "connecting" /* CONNECTING */) {
3649
+ console.warn("[WalletConnect Tron] Connection already in progress, waiting...");
3650
+ let attempts = 0;
3651
+ while (this.state === "connecting" /* CONNECTING */ && attempts < 50) {
3652
+ await new Promise((resolve) => setTimeout(resolve, 100));
3653
+ attempts++;
3654
+ }
3655
+ if (this.state === "connected" /* CONNECTED */ && this.currentAccount) {
3656
+ return this.currentAccount;
3657
+ }
3658
+ if (this.state === "connecting" /* CONNECTING */) {
3659
+ throw new Error("Connection timeout - previous connection attempt is still pending");
3660
+ }
3661
+ }
3662
+ if (this.state === "connected" /* CONNECTED */ && this.currentAccount) {
3663
+ return this.currentAccount;
3664
+ }
3665
+ try {
3666
+ this.setState("connecting" /* CONNECTING */);
3667
+ const targetChainId = Array.isArray(chainId) ? chainId[0] || _WalletConnectTronAdapter.TRON_MAINNET_CHAIN_ID : chainId || _WalletConnectTronAdapter.TRON_MAINNET_CHAIN_ID;
3668
+ if (!_WalletConnectTronAdapter.walletInstance || _WalletConnectTronAdapter.walletProjectId !== this.projectId) {
3669
+ this.initializeWallet(targetChainId);
3670
+ }
3671
+ this.wallet = _WalletConnectTronAdapter.walletInstance;
3672
+ if (!this.wallet) {
3673
+ throw new Error("Failed to initialize WalletConnect wallet");
3674
+ }
3675
+ let network = WalletConnectChainID.Mainnet;
3676
+ if (targetChainId === 195) {
3677
+ network = WalletConnectChainID.Mainnet;
3678
+ } else if (targetChainId === 201910292) {
3679
+ network = WalletConnectChainID.Shasta;
3680
+ } else if (targetChainId === 2494104990) {
3681
+ network = WalletConnectChainID.Nile;
3682
+ }
3683
+ let address;
3684
+ try {
3685
+ console.log("[WalletConnect Tron] Attempting to connect...", {
3686
+ network,
3687
+ chainId: targetChainId,
3688
+ isTelegram: this.isTelegramMiniApp(),
3689
+ projectId: this.projectId
3690
+ });
3691
+ const result = await this.wallet.connect();
3692
+ address = result.address;
3693
+ if (!address) {
3694
+ throw new ConnectionRejectedError(this.type);
3695
+ }
3696
+ console.log("[WalletConnect Tron] Connection successful:", {
3697
+ address,
3698
+ network,
3699
+ chainId: targetChainId,
3700
+ isTelegram: this.isTelegramMiniApp()
3701
+ });
3702
+ } catch (error) {
3703
+ const errorMessage = error.message || String(error);
3704
+ const errorCode = error.code || error.error?.code;
3705
+ const origin = typeof window !== "undefined" && window.location ? window.location.origin : "";
3706
+ let detailedError = errorMessage;
3707
+ if (error.error) {
3708
+ if (typeof error.error === "string") {
3709
+ detailedError = error.error;
3710
+ } else if (error.error.message) {
3711
+ detailedError = error.error.message;
3712
+ } else if (error.error.data) {
3713
+ detailedError = JSON.stringify(error.error.data);
3714
+ }
3715
+ }
3716
+ const isNoWalletFound = errorMessage.includes("\u6CA1\u6709\u627E\u5230\u652F\u6301\u7684\u94B1\u5305") || errorMessage.includes("No matching wallet") || errorMessage.includes("No wallet found") || errorMessage.includes("\u627E\u4E0D\u5230\u94B1\u5305") || errorMessage.includes("not found") || errorMessage.includes("no matching");
3717
+ const isTimeout = errorMessage.includes("timeout") || errorMessage.includes("\u8D85\u65F6") || errorCode === "TIMEOUT";
3718
+ const isRejected = errorMessage.includes("rejected") || errorMessage.includes("\u62D2\u7EDD") || errorCode === 4001;
3719
+ const isOriginNotAllowed = errorCode === 3e3 || /origin not allowed/i.test(errorMessage) || /Unauthorized:\s*origin not allowed/i.test(errorMessage);
3720
+ const currentMetadata = this.wallet ? {
3721
+ // Try to get metadata from wallet instance if available
3722
+ projectId: this.projectId,
3723
+ network
3724
+ } : null;
3725
+ const errorDetails = {
3726
+ error: errorMessage,
3727
+ detailedError,
3728
+ code: errorCode,
3729
+ isTelegram: this.isTelegramMiniApp(),
3730
+ network,
3731
+ chainId: targetChainId,
3732
+ projectId: this.projectId,
3733
+ metadata: currentMetadata,
3734
+ // Get URL from window.location if available
3735
+ currentUrl: typeof window !== "undefined" ? window.location.href : "N/A",
3736
+ telegramPlatform: typeof window !== "undefined" && window.Telegram?.WebApp?.platform || "N/A",
3737
+ errorType: isNoWalletFound ? "NO_WALLET_FOUND" : isTimeout ? "TIMEOUT" : isRejected ? "REJECTED" : "UNKNOWN"
3738
+ };
3739
+ console.error("[WalletConnect Tron] Connection error - Full details:", errorDetails);
3740
+ console.error("[WalletConnect Tron] Error object:", error);
3741
+ console.error("[WalletConnect Tron] Error stack:", error.stack);
3742
+ if (isNoWalletFound) {
3743
+ const noWalletErrorDetails = [
3744
+ `
3745
+ === WalletConnect Tron: No Matching Wallet Found ===`,
3746
+ `Error: ${errorMessage}`,
3747
+ `Detailed: ${detailedError}`,
3748
+ `Code: ${errorCode || "N/A"}`,
3749
+ ``,
3750
+ `Environment:`,
3751
+ ` - Telegram Mini App: ${this.isTelegramMiniApp() ? "Yes" : "No"}`,
3752
+ ` - Platform: ${errorDetails.telegramPlatform}`,
3753
+ ` - Current URL: ${errorDetails.currentUrl}`,
3754
+ ``,
3755
+ `Configuration:`,
3756
+ ` - Project ID: ${this.projectId ? "Set" : "Missing"}`,
3757
+ ` - Network: ${network}`,
3758
+ ` - Chain ID: ${targetChainId}`,
3759
+ ` - Metadata URL: ${typeof window !== "undefined" ? window.location.origin : "N/A"}`,
3760
+ ``,
3761
+ `Possible Causes:`,
3762
+ ` 1. No WalletConnect-compatible wallet (TokenPocket, etc.) installed on device`,
3763
+ ` 2. Wallet app not opened or not responding to deep link (wc://)`,
3764
+ ` 3. Deep link handling issue in Telegram Mini App environment`,
3765
+ ` 4. WalletConnect session timeout (user took too long to approve)`,
3766
+ ` 5. Network connectivity issue preventing WalletConnect relay connection`,
3767
+ ``,
3768
+ `Solutions:`,
3769
+ ` 1. Ensure TokenPocket or other WalletConnect-compatible wallet is installed`,
3770
+ ` 2. Try opening the wallet app manually before connecting`,
3771
+ ` 3. In Telegram Mini App, ensure the deep link popup is not blocked`,
3772
+ ` 4. Try connecting again (may need to wait a few seconds)`,
3773
+ ` 5. Check network connection and WalletConnect relay server accessibility`,
3774
+ ``,
3775
+ `For more details, see the error object logged above.`,
3776
+ `===========================================
3777
+ `
3778
+ ].join("\n");
3779
+ console.error(noWalletErrorDetails);
3780
+ throw new ConnectionRejectedError(
3781
+ `WalletConnect Tron: \u6CA1\u6709\u627E\u5230\u652F\u6301\u7684\u94B1\u5305 (No matching wallet found)
3782
+
3783
+ \u53EF\u80FD\u7684\u539F\u56E0\uFF1A
3784
+ 1. \u8BBE\u5907\u4E0A\u672A\u5B89\u88C5\u652F\u6301 WalletConnect \u7684\u94B1\u5305\uFF08\u5982 TokenPocket\uFF09
3785
+ 2. \u94B1\u5305\u5E94\u7528\u672A\u6253\u5F00\u6216\u672A\u54CD\u5E94 deep link (wc://)
3786
+ 3. \u5728 Telegram Mini App \u4E2D\uFF0Cdeep link \u5904\u7406\u53EF\u80FD\u6709\u95EE\u9898
3787
+ 4. \u8FDE\u63A5\u8D85\u65F6\uFF08\u7528\u6237\u672A\u53CA\u65F6\u6279\u51C6\uFF09
3788
+ 5. \u7F51\u7EDC\u8FDE\u63A5\u95EE\u9898
3789
+
3790
+ \u89E3\u51B3\u65B9\u6848\uFF1A
3791
+ 1. \u786E\u4FDD\u5DF2\u5B89\u88C5 TokenPocket \u6216\u5176\u4ED6\u652F\u6301 WalletConnect \u7684\u94B1\u5305
3792
+ 2. \u5C1D\u8BD5\u624B\u52A8\u6253\u5F00\u94B1\u5305\u5E94\u7528\u540E\u518D\u8FDE\u63A5
3793
+ 3. \u5728 Telegram Mini App \u4E2D\uFF0C\u786E\u4FDD deep link \u5F39\u7A97\u672A\u88AB\u963B\u6B62
3794
+ 4. \u7A0D\u7B49\u51E0\u79D2\u540E\u91CD\u8BD5\u8FDE\u63A5
3795
+ 5. \u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u548C WalletConnect \u4E2D\u7EE7\u670D\u52A1\u5668\u53EF\u8BBF\u95EE\u6027
3796
+
3797
+ \u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u65E5\u5FD7\u3002`
3798
+ );
3799
+ }
3800
+ if (errorMessage.includes("Invalid") || errorMessage.includes("Configuration") || errorMessage.includes("App Config") || errorMessage.includes("Invalid App")) {
3801
+ const configErrorDetails = [
3802
+ `
3803
+ === WalletConnect Tron Configuration Error ===`,
3804
+ `Error: ${errorMessage}`,
3805
+ `Detailed: ${detailedError}`,
3806
+ `Code: ${errorCode || "N/A"}`,
3807
+ `
3808
+ Environment:`,
3809
+ ` - Telegram Mini App: ${this.isTelegramMiniApp() ? "Yes" : "No"}`,
3810
+ ` - Platform: ${errorDetails.telegramPlatform}`,
3811
+ ` - Current URL: ${errorDetails.currentUrl}`,
3812
+ `
3813
+ Configuration:`,
3814
+ ` - Project ID: ${this.projectId ? "Set" : "Missing"}`,
3815
+ ` - Network: ${network}`,
3816
+ ` - Chain ID: ${targetChainId}`,
3817
+ `
3818
+ Possible Causes:`,
3819
+ ` 1. Deep link (wc://) handling issue in Telegram Mini App`,
3820
+ ` 2. Invalid metadata configuration (URL or icons not accessible)`,
3821
+ ` 3. Network/chainId mismatch`,
3822
+ ` 4. WalletConnect project ID not configured correctly`,
3823
+ ` 5. Domain not added to WalletConnect Cloud allowlist`,
3824
+ `
3825
+ Please check:`,
3826
+ ` - WalletConnect Project ID is valid and active`,
3827
+ ` - Domain is added to WalletConnect Cloud allowlist (for serveo.net, etc.)`,
3828
+ ` - Metadata URL is accessible: Check console for metadata logs`,
3829
+ ` - Icons are accessible: Check console for icon URLs`,
3830
+ ` - Network matches chainId: Expected ${network} for chainId ${targetChainId}`,
3831
+ `
3832
+ For more details, see the error object logged above.`,
3833
+ `===========================================
3834
+ `
3835
+ ].join("\n");
3836
+ console.error(configErrorDetails);
3837
+ throw new ConfigurationError(
3838
+ `WalletConnect Tron connection failed: ${errorMessage}
3839
+
3840
+ Configuration Details:
3841
+ - Telegram Mini App: ${this.isTelegramMiniApp() ? "Yes" : "No"}
3842
+ - Platform: ${errorDetails.telegramPlatform}
3843
+ - Origin: ${origin || "(unknown)"}
3844
+ - Project ID: ${this.projectId ? "Set" : "Missing"}
3845
+ - Network: ${network}
3846
+ - Chain ID: ${targetChainId}
3847
+
3848
+ This "Invalid App Configuration" error may be caused by:
3849
+ 1. Deep link (wc://) handling issue in Telegram Mini App
3850
+ 2. Invalid metadata configuration (URL or icons)
3851
+ 3. Network/chainId mismatch
3852
+ 4. Domain not added to WalletConnect Cloud allowlist
3853
+
3854
+ Please check the console for detailed error information.`
3855
+ );
3856
+ }
3857
+ if (isOriginNotAllowed) {
3858
+ throw new ConfigurationError(
3859
+ `WalletConnect Tron relayer rejected this origin (code 3000: Unauthorized: origin not allowed).
3860
+
3861
+ Fix:
3862
+ 1) Open WalletConnect Cloud \u2192 your project (${this.projectId})
3863
+ 2) Add this site origin to the allowlist:
3864
+ - ${origin || "(unknown origin)"}
3865
+
3866
+ Common dev origins to allow:
3867
+ - http://localhost:5173
3868
+ - http://192.168.0.221:5173 (your LAN dev URL)
3869
+ - https://wallet-test.enclave-hq.com (your Cloudflare Tunnel/custom domain)
3870
+
3871
+ Original error: ${errorMessage}`
3872
+ );
3873
+ }
3874
+ if (isTimeout) {
3875
+ throw new ConnectionRejectedError(
3876
+ `WalletConnect Tron connection timeout. Please try again and ensure your wallet app is open and ready.`
3877
+ );
3878
+ }
3879
+ if (isRejected) {
3880
+ throw new ConnectionRejectedError(this.type);
3881
+ }
3882
+ throw error;
3883
+ }
3884
+ this.currentAddress = address;
3885
+ const account = {
3886
+ universalAddress: createUniversalAddress(targetChainId, address),
3887
+ nativeAddress: address,
3888
+ chainId: targetChainId,
3889
+ chainType: ChainType.TRON,
3890
+ isActive: true
3891
+ };
3892
+ this.setState("connected" /* CONNECTED */);
3893
+ this.setAccount(account);
3894
+ this.setupEventListeners();
3895
+ return account;
3896
+ } catch (error) {
3897
+ this.setState("error" /* ERROR */);
3898
+ this.setAccount(null);
3899
+ this.currentAddress = null;
3900
+ if (error.message?.includes("rejected") || error.code === 4001) {
3901
+ throw new ConnectionRejectedError(this.type);
3902
+ }
3903
+ throw error;
3904
+ }
3905
+ }
3906
+ /**
3907
+ * Disconnect wallet
3908
+ */
3909
+ async disconnect() {
3910
+ this.removeEventListeners();
3911
+ if (this.wallet) {
3912
+ try {
3913
+ await this.wallet.disconnect();
3914
+ } catch (error) {
3915
+ console.warn("[WalletConnect Tron] Error during disconnect:", error);
3916
+ }
3917
+ }
3918
+ this.wallet = null;
3919
+ this.currentAddress = null;
3920
+ this.setState("disconnected" /* DISCONNECTED */);
3921
+ this.setAccount(null);
3922
+ this.emitDisconnected();
3923
+ }
3924
+ /**
3925
+ * Sign message
3926
+ */
3927
+ async signMessage(message) {
3928
+ this.ensureConnected();
3929
+ try {
3930
+ if (!this.wallet) {
3931
+ throw new Error("Wallet not initialized");
3932
+ }
3933
+ const signature = await this.wallet.signMessage(message);
3934
+ if (typeof signature === "string") {
3935
+ return signature;
3936
+ } else if (signature && typeof signature === "object") {
3937
+ if ("signature" in signature) {
3938
+ return signature.signature;
3939
+ } else if ("result" in signature) {
3940
+ return signature.result;
3941
+ } else {
3942
+ return JSON.stringify(signature);
3943
+ }
3944
+ }
3945
+ throw new Error("Invalid signature format returned from wallet");
3946
+ } catch (error) {
3947
+ console.error("[WalletConnect Tron] Sign message error:", error);
3948
+ let errorMessage = "Unknown error";
3949
+ if (typeof error === "string") {
3950
+ errorMessage = error;
3951
+ } else if (error?.message) {
3952
+ errorMessage = error.message;
3953
+ } else if (error?.error?.message) {
3954
+ errorMessage = error.error.message;
3955
+ } else {
3956
+ try {
3957
+ errorMessage = JSON.stringify(error);
3958
+ } catch {
3959
+ errorMessage = String(error);
3960
+ }
3961
+ }
3962
+ if (errorMessage?.includes("rejected") || errorMessage?.includes("declined") || errorMessage?.includes("User rejected") || error?.code === 4001 || error?.code === "USER_REJECTED" || error?.error?.code === 4001) {
3963
+ throw new SignatureRejectedError();
3964
+ }
3965
+ if (errorMessage?.includes("not supported") || errorMessage?.includes("method not found") || errorMessage?.includes("Method not found") || error?.code === -32601 || error?.error?.code === -32601) {
3966
+ throw new Error("tron_signMessage is not supported by the connected wallet. Please use a wallet that supports WalletConnect Tron signing, or use TronLink extension for browser-based signing.");
3967
+ }
3968
+ throw new Error(`WalletConnect Tron sign message failed: ${errorMessage}`);
3969
+ }
3970
+ }
3971
+ /**
3972
+ * Sign transaction
3973
+ *
3974
+ * @param transaction - Tron transaction object
3975
+ * Can be created using TronWeb (if available) or any TRON transaction builder
3976
+ * Format: { raw_data: {...}, raw_data_hex: "...", txID: "..." }
3977
+ * @returns Signed transaction object or signature
3978
+ */
3979
+ async signTransaction(transaction) {
3980
+ this.ensureConnected();
3981
+ try {
3982
+ if (!this.wallet) {
3983
+ throw new Error("Wallet not initialized");
3984
+ }
3985
+ if (!transaction) {
3986
+ throw new Error("Transaction object is required");
3987
+ }
3988
+ console.log("[WalletConnect Tron] Signing transaction:", {
3989
+ hasRawData: !!transaction.raw_data,
3990
+ hasRawDataHex: !!transaction.raw_data_hex,
3991
+ hasTxID: !!transaction.txID
3992
+ });
3993
+ const result = await this.wallet.signTransaction(transaction);
3994
+ if (typeof result === "string") {
3995
+ return result;
3996
+ } else if (result && typeof result === "object") {
3997
+ if ("txID" in result && typeof result.txID === "string") {
3998
+ return result.txID;
3999
+ } else if ("txid" in result && typeof result.txid === "string") {
4000
+ return result.txid;
4001
+ } else if ("signature" in result) {
4002
+ return JSON.stringify(result);
4003
+ } else {
4004
+ return JSON.stringify(result);
4005
+ }
4006
+ }
4007
+ throw new Error("Invalid signature format returned from wallet");
4008
+ } catch (error) {
4009
+ console.error("[WalletConnect Tron] Sign transaction error:", error);
4010
+ let errorMessage = "Unknown error";
4011
+ if (typeof error === "string") {
4012
+ errorMessage = error;
4013
+ } else if (error?.message) {
4014
+ errorMessage = error.message;
4015
+ } else if (error?.error?.message) {
4016
+ errorMessage = error.error.message;
4017
+ } else if (error?.data?.message) {
4018
+ errorMessage = error.data.message;
4019
+ } else {
4020
+ try {
4021
+ errorMessage = JSON.stringify(error);
4022
+ } catch {
4023
+ errorMessage = String(error);
4024
+ }
4025
+ }
4026
+ if (errorMessage?.includes("rejected") || errorMessage?.includes("declined") || errorMessage?.includes("User rejected") || error?.code === 4001 || error?.code === "USER_REJECTED" || error?.error?.code === 4001) {
4027
+ throw new SignatureRejectedError("Transaction signature was rejected by user");
4028
+ }
4029
+ if (errorMessage?.includes("not supported") || errorMessage?.includes("method not found") || errorMessage?.includes("Method not found") || errorMessage?.includes("Not support") || error?.code === -32601 || error?.error?.code === -32601) {
4030
+ throw new Error("tron_signTransaction is not supported by the connected wallet. Please use a wallet that supports WalletConnect Tron signing, or use TronLink extension for browser-based signing.");
4031
+ }
4032
+ throw new Error(`WalletConnect Tron sign transaction failed: ${errorMessage}`);
4033
+ }
4034
+ }
4035
+ /**
4036
+ * Read contract (not supported by WalletConnect)
4037
+ */
4038
+ async readContract(_params) {
4039
+ this.ensureConnected();
4040
+ throw new Error("WalletConnect Tron does not support direct contract reading. Please use direct Tron RPC calls or a wallet extension (like TronLink) for read operations.");
4041
+ }
4042
+ /**
4043
+ * Write contract (not yet implemented)
4044
+ */
4045
+ async writeContract(_params) {
4046
+ throw new Error("Contract write not yet implemented for WalletConnect Tron");
4047
+ }
4048
+ /**
4049
+ * Estimate gas (not yet implemented)
4050
+ */
4051
+ async estimateGas(_params) {
4052
+ throw new Error("Gas estimation not yet implemented for WalletConnect Tron");
4053
+ }
4054
+ /**
4055
+ * Wait for transaction (not yet implemented)
4056
+ */
4057
+ async waitForTransaction(_txHash, _confirmations) {
4058
+ throw new Error("Transaction waiting not yet implemented for WalletConnect Tron");
4059
+ }
4060
+ /**
4061
+ * Setup event listeners
4062
+ */
4063
+ setupEventListeners() {
4064
+ if (!this.wallet) {
4065
+ return;
4066
+ }
4067
+ this.wallet.on("accountsChanged", (accounts) => {
4068
+ if (accounts && accounts.length > 0 && accounts[0] !== this.currentAddress) {
4069
+ const newAddress = accounts[0];
4070
+ this.currentAddress = newAddress;
4071
+ if (this.currentAccount) {
4072
+ const newAccount = {
4073
+ ...this.currentAccount,
4074
+ nativeAddress: newAddress,
4075
+ universalAddress: createUniversalAddress(this.currentAccount.chainId, newAddress)
4076
+ };
4077
+ this.setAccount(newAccount);
4078
+ this.emit("accountChanged", newAccount);
4079
+ }
4080
+ } else if (!accounts || accounts.length === 0) {
4081
+ this.disconnect();
4082
+ }
4083
+ });
4084
+ this.wallet.on("disconnect", () => {
4085
+ this.disconnect();
4086
+ });
4087
+ }
4088
+ /**
4089
+ * Remove event listeners
4090
+ */
4091
+ removeEventListeners() {
4092
+ if (!this.wallet) {
4093
+ return;
4094
+ }
4095
+ this.wallet.removeAllListeners("accountsChanged");
4096
+ this.wallet.removeAllListeners("disconnect");
4097
+ }
4098
+ /**
4099
+ * Get provider (returns wallet instance)
4100
+ */
4101
+ getProvider() {
4102
+ return this.wallet;
4103
+ }
4104
+ /**
4105
+ * Clear static wallet instance (for complete cleanup)
4106
+ */
4107
+ static clearWalletInstance() {
4108
+ if (_WalletConnectTronAdapter.walletInstance) {
4109
+ _WalletConnectTronAdapter.walletInstance.disconnect().catch(() => {
4110
+ });
4111
+ _WalletConnectTronAdapter.walletInstance = null;
4112
+ _WalletConnectTronAdapter.walletProjectId = null;
4113
+ }
4114
+ }
4115
+ };
4116
+ // Tron 主网链 ID
4117
+ _WalletConnectTronAdapter.TRON_MAINNET_CHAIN_ID = 195;
4118
+ // Static wallet instance to avoid multiple initializations
4119
+ _WalletConnectTronAdapter.walletInstance = null;
4120
+ _WalletConnectTronAdapter.walletProjectId = null;
4121
+ var WalletConnectTronAdapter = _WalletConnectTronAdapter;
4122
+
4123
+ // src/internal/walletconnect-tron-loader.esm.ts
4124
+ function loadWalletConnectTronModule() {
4125
+ return wallet_connect_exports;
4126
+ }
4127
+
4128
+ // src/adapters/deep-link/adapter.ts
4129
+ init_types();
4130
+ var _DeepLinkAdapter = class _DeepLinkAdapter extends WalletAdapter {
4131
+ constructor(config) {
4132
+ super();
4133
+ this.currentChainId = null;
4134
+ this.currentChainType = null;
4135
+ this.provider = this.createProvider(config);
4136
+ this.name = `${this.provider.name} (Deep Link)`;
4137
+ this.icon = this.provider.icon;
4138
+ if (this.provider.supportedChainTypes.includes(ChainType.EVM)) {
4139
+ this.chainType = ChainType.EVM;
4140
+ this.type = "deep-link-evm" /* DEEP_LINK_EVM */;
4141
+ } else if (this.provider.supportedChainTypes.includes(ChainType.TRON)) {
4142
+ this.chainType = ChainType.TRON;
4143
+ this.type = "deep-link-tron" /* DEEP_LINK_TRON */;
4144
+ } else {
4145
+ this.chainType = ChainType.EVM;
4146
+ this.type = "deep-link-evm" /* DEEP_LINK_EVM */;
4147
+ }
4148
+ if (typeof window !== "undefined") {
4149
+ this.setupCallbackHandler();
4150
+ }
4151
+ }
4152
+ /**
4153
+ * Create provider instance based on type
4154
+ */
4155
+ createProvider(config) {
4156
+ switch (config.providerType) {
4157
+ case "tokenpocket" /* TOKENPOCKET */: {
4158
+ const { TokenPocketDeepLinkProvider: TokenPocketDeepLinkProvider2 } = (init_tokenpocket(), __toCommonJS(tokenpocket_exports));
4159
+ return new TokenPocketDeepLinkProvider2({
4160
+ callbackUrl: config.callbackUrl,
4161
+ callbackSchema: config.callbackSchema
4162
+ });
4163
+ }
4164
+ case "tronlink" /* TRONLINK */: {
4165
+ const { TronLinkDeepLinkProvider: TronLinkDeepLinkProvider2 } = (init_tronlink(), __toCommonJS(tronlink_exports));
4166
+ return new TronLinkDeepLinkProvider2();
4167
+ }
4168
+ case "imtoken" /* IMTOKEN */: {
4169
+ const { ImTokenDeepLinkProvider: ImTokenDeepLinkProvider2 } = (init_imtoken(), __toCommonJS(imtoken_exports));
4170
+ return new ImTokenDeepLinkProvider2({
4171
+ callbackUrl: config.callbackUrl,
4172
+ callbackSchema: config.callbackSchema
4173
+ });
4174
+ }
4175
+ case "metamask" /* METAMASK */: {
4176
+ const { MetaMaskDeepLinkProvider: MetaMaskDeepLinkProvider2 } = (init_metamask(), __toCommonJS(metamask_exports));
4177
+ return new MetaMaskDeepLinkProvider2();
4178
+ }
4179
+ case "okx" /* OKX */: {
4180
+ const { OKXDeepLinkProvider: OKXDeepLinkProvider2 } = (init_okx(), __toCommonJS(okx_exports));
4181
+ return new OKXDeepLinkProvider2();
4182
+ }
4183
+ default:
4184
+ throw new Error(`Unsupported deep link provider type: ${config.providerType}`);
4185
+ }
4186
+ }
4187
+ /**
4188
+ * Setup callback handler for deep link results
4189
+ */
4190
+ setupCallbackHandler() {
4191
+ if (typeof window === "undefined") {
4192
+ return;
4193
+ }
4194
+ const handleUrlChange = () => {
4195
+ const urlParams = new URLSearchParams(window.location.search);
4196
+ const result = this.provider.parseCallbackResult(urlParams);
4197
+ if (result.actionId && _DeepLinkAdapter.pendingActions.has(result.actionId)) {
4198
+ const callback = _DeepLinkAdapter.pendingActions.get(result.actionId);
4199
+ if (result.error) {
4200
+ callback.reject(new Error(result.error));
4201
+ } else if (result.result) {
4202
+ callback.resolve(result.result);
4203
+ }
4204
+ _DeepLinkAdapter.pendingActions.delete(result.actionId);
4205
+ }
4206
+ };
4207
+ window.addEventListener("popstate", handleUrlChange);
4208
+ window.addEventListener("hashchange", handleUrlChange);
4209
+ handleUrlChange();
4210
+ }
4211
+ /**
4212
+ * Check if deep link is available
4213
+ */
4214
+ async isAvailable() {
4215
+ return this.provider.isAvailable();
4216
+ }
4217
+ /**
4218
+ * Connect to wallet via deep link
4219
+ *
4220
+ * Note: Deep links typically don't support persistent connections
4221
+ * This method may throw ConnectionRejectedError as deep links are
4222
+ * primarily used for signing operations, not connection
4223
+ */
4224
+ async connect(chainId) {
4225
+ const targetChainId = Array.isArray(chainId) ? chainId[0] : chainId || 1;
4226
+ let chainType;
4227
+ if (targetChainId === 195) {
4228
+ chainType = ChainType.TRON;
4229
+ } else {
4230
+ chainType = ChainType.EVM;
4231
+ }
4232
+ if (!this.provider.supportedChainTypes.includes(chainType)) {
4233
+ throw new Error(
4234
+ `Provider ${this.provider.name} does not support chain type ${chainType}`
4235
+ );
4236
+ }
4237
+ if (this.provider.buildConnectLink) {
4238
+ const linkInfo = this.provider.buildConnectLink({
4239
+ chainId: targetChainId,
4240
+ chainType
4241
+ });
4242
+ if (linkInfo.actionId) {
4243
+ return new Promise((resolve, reject) => {
4244
+ _DeepLinkAdapter.pendingActions.set(linkInfo.actionId, {
4245
+ resolve: (result) => {
4246
+ const address = result?.address || result?.account || result;
4247
+ if (!address || typeof address !== "string") {
4248
+ reject(new ConnectionRejectedError("Invalid connection result: no address found"));
4249
+ return;
4250
+ }
4251
+ const account = {
4252
+ universalAddress: createUniversalAddress(targetChainId, address),
4253
+ nativeAddress: address,
4254
+ chainId: targetChainId,
4255
+ chainType,
4256
+ isActive: true
4257
+ };
4258
+ this.setState("connected" /* CONNECTED */);
4259
+ this.setAccount(account);
4260
+ this.emit("connected", account);
4261
+ resolve(account);
4262
+ },
4263
+ reject: (error) => {
4264
+ this.setState("disconnected" /* DISCONNECTED */);
4265
+ reject(error);
4266
+ }
4267
+ });
4268
+ window.location.href = linkInfo.url;
4269
+ setTimeout(() => {
4270
+ if (_DeepLinkAdapter.pendingActions.has(linkInfo.actionId)) {
4271
+ _DeepLinkAdapter.pendingActions.delete(linkInfo.actionId);
4272
+ this.setState("disconnected" /* DISCONNECTED */);
4273
+ reject(new ConnectionRejectedError("Deep link connection timeout"));
4274
+ }
4275
+ }, 3e4);
4276
+ });
4277
+ } else {
4278
+ window.location.href = linkInfo.url;
4279
+ throw new ConnectionRejectedError(
4280
+ "Deep link connection initiated. Please complete the connection in your wallet app."
4281
+ );
4282
+ }
4283
+ } else {
4284
+ throw new ConnectionRejectedError(
4285
+ `Deep link connection is not supported by ${this.provider.name}. Deep links are primarily used for signing operations.`
4286
+ );
4287
+ }
4288
+ }
4289
+ /**
4290
+ * Disconnect from wallet
4291
+ */
4292
+ async disconnect() {
4293
+ this.setState("disconnected" /* DISCONNECTED */);
4294
+ this.setAccount(null);
4295
+ this.currentChainId = null;
4296
+ this.currentChainType = null;
4297
+ this.emitDisconnected();
4298
+ }
4299
+ /**
4300
+ * Sign a message
4301
+ */
4302
+ async signMessage(message) {
4303
+ this.ensureConnected();
4304
+ if (!this.currentChainId || !this.currentChainType) {
4305
+ throw new WalletNotConnectedError(this.type);
4306
+ }
4307
+ const linkInfo = this.provider.buildSignMessageLink({
4308
+ message,
4309
+ chainId: this.currentChainId,
4310
+ chainType: this.currentChainType
4311
+ });
4312
+ if (linkInfo.callbackSchema || linkInfo.callbackUrl) {
4313
+ return new Promise((resolve, reject) => {
4314
+ _DeepLinkAdapter.pendingActions.set(linkInfo.actionId, { resolve, reject });
4315
+ window.location.href = linkInfo.url;
4316
+ setTimeout(() => {
4317
+ if (_DeepLinkAdapter.pendingActions.has(linkInfo.actionId)) {
4318
+ _DeepLinkAdapter.pendingActions.delete(linkInfo.actionId);
4319
+ reject(new SignatureRejectedError("Message signature timeout"));
4320
+ }
4321
+ }, 3e4);
4322
+ });
4323
+ } else {
4324
+ window.location.href = linkInfo.url;
4325
+ throw new SignatureRejectedError(
4326
+ "Deep link signature initiated. Please complete the signature in your wallet app."
4327
+ );
4328
+ }
4329
+ }
4330
+ /**
4331
+ * Sign a transaction
4332
+ */
4333
+ async signTransaction(transaction) {
4334
+ this.ensureConnected();
4335
+ if (!this.currentChainId || !this.currentChainType) {
4336
+ throw new WalletNotConnectedError(this.type);
4337
+ }
4338
+ const linkInfo = this.provider.buildSignTransactionLink({
4339
+ transaction,
4340
+ chainId: this.currentChainId,
4341
+ chainType: this.currentChainType
4342
+ });
4343
+ if (linkInfo.callbackSchema || linkInfo.callbackUrl) {
4344
+ return new Promise((resolve, reject) => {
4345
+ _DeepLinkAdapter.pendingActions.set(linkInfo.actionId, { resolve, reject });
4346
+ window.location.href = linkInfo.url;
4347
+ setTimeout(() => {
4348
+ if (_DeepLinkAdapter.pendingActions.has(linkInfo.actionId)) {
4349
+ _DeepLinkAdapter.pendingActions.delete(linkInfo.actionId);
4350
+ reject(new SignatureRejectedError("Transaction signature timeout"));
4351
+ }
4352
+ }, 3e4);
4353
+ });
4354
+ } else {
4355
+ window.location.href = linkInfo.url;
4356
+ throw new SignatureRejectedError(
4357
+ "Deep link transaction signature initiated. Please complete the signature in your wallet app."
4358
+ );
4359
+ }
4360
+ }
4361
+ /**
4362
+ * Get provider (not applicable for deep links)
4363
+ */
4364
+ getProvider() {
4365
+ return null;
4366
+ }
4367
+ /**
4368
+ * Static method to handle callback from wallet apps
4369
+ * This can be called from anywhere in the application
4370
+ */
4371
+ static handleCallback() {
4372
+ if (typeof window === "undefined") {
4373
+ return;
4374
+ }
4375
+ const urlParams = new URLSearchParams(window.location.search);
4376
+ const actionId = urlParams.get("actionId");
4377
+ if (actionId && _DeepLinkAdapter.pendingActions.has(actionId)) {
4378
+ const callback = _DeepLinkAdapter.pendingActions.get(actionId);
4379
+ const result = urlParams.get("result");
4380
+ const error = urlParams.get("error");
4381
+ if (error) {
4382
+ callback.reject(new Error(error));
4383
+ } else if (result) {
4384
+ try {
4385
+ const parsedResult = JSON.parse(decodeURIComponent(result));
4386
+ callback.resolve(parsedResult);
4387
+ } catch (e) {
4388
+ callback.resolve(result);
4389
+ }
4390
+ }
4391
+ _DeepLinkAdapter.pendingActions.delete(actionId);
4392
+ }
4393
+ }
4394
+ /**
4395
+ * Set current account (called after successful connection)
4396
+ */
4397
+ setAccount(account) {
4398
+ this.currentAccount = account;
4399
+ if (account) {
4400
+ this.currentChainId = account.chainId;
4401
+ this.currentChainType = account.chainType;
4402
+ }
4403
+ }
4404
+ /**
4405
+ * Emit disconnected event
4406
+ */
4407
+ emitDisconnected() {
4408
+ this.emit("disconnected");
4409
+ }
4410
+ };
4411
+ // Static map to store pending actions across all instances
4412
+ // Key: actionId, Value: { resolve, reject }
4413
+ _DeepLinkAdapter.pendingActions = /* @__PURE__ */ new Map();
4414
+ var DeepLinkAdapter = _DeepLinkAdapter;
4415
+
4416
+ // src/core/adapter-registry.ts
4417
+ var AdapterRegistry = class {
4418
+ constructor(config = {}) {
4419
+ this.adapters = /* @__PURE__ */ new Map();
4420
+ this.config = config;
4421
+ this.registerDefaultAdapters();
4422
+ }
4423
+ /**
4424
+ * Register default adapters
4425
+ */
4426
+ registerDefaultAdapters() {
4427
+ this.register("metamask" /* METAMASK */, () => new MetaMaskAdapter());
4428
+ this.register("private-key" /* PRIVATE_KEY */, () => new EVMPrivateKeyAdapter());
4429
+ if (this.config.walletConnectProjectId) {
4430
+ this.register(
4431
+ "walletconnect" /* WALLETCONNECT */,
4432
+ () => new WalletConnectAdapter(this.config.walletConnectProjectId)
4433
+ );
4434
+ this.register("walletconnect-tron" /* WALLETCONNECT_TRON */, () => {
4435
+ const { WalletConnectTronAdapter: WalletConnectTronAdapter2 } = loadWalletConnectTronModule();
4436
+ return new WalletConnectTronAdapter2(this.config.walletConnectProjectId);
4437
+ });
4438
+ }
4439
+ this.register("tronlink" /* TRONLINK */, () => new TronLinkAdapter());
4440
+ this.register(
4441
+ "deep-link-evm" /* DEEP_LINK_EVM */,
4442
+ () => new DeepLinkAdapter({
4443
+ providerType: "tokenpocket" /* TOKENPOCKET */
4444
+ })
4445
+ );
4446
+ this.register(
4447
+ "deep-link-tron" /* DEEP_LINK_TRON */,
4448
+ () => new DeepLinkAdapter({
4449
+ providerType: "tokenpocket" /* TOKENPOCKET */
4450
+ })
4451
+ );
4452
+ }
4453
+ /**
4454
+ * Register adapter
4455
+ */
4456
+ register(type, factory) {
4457
+ this.adapters.set(type, factory);
4458
+ }
4459
+ /**
4460
+ * Get adapter
4461
+ */
4462
+ getAdapter(type) {
4463
+ const factory = this.adapters.get(type);
4464
+ if (!factory) {
4465
+ return null;
4466
+ }
4467
+ return factory();
4468
+ }
4469
+ /**
1572
4470
  * Check if adapter is registered
1573
4471
  */
1574
4472
  has(type) {
@@ -1595,6 +4493,190 @@ var AdapterRegistry = class {
1595
4493
  }
1596
4494
  };
1597
4495
 
4496
+ // src/core/wallet-manager.ts
4497
+ init_types();
4498
+ var QRCodeSigner = class {
4499
+ constructor(config) {
4500
+ this.pollTimer = null;
4501
+ this.timeoutTimer = null;
4502
+ this.status = "waiting" /* WAITING */;
4503
+ this.qrCodeDataUrl = null;
4504
+ this.result = null;
4505
+ this.config = {
4506
+ requestId: config.requestId,
4507
+ requestUrl: config.requestUrl,
4508
+ pollUrl: config.pollUrl || "",
4509
+ pollInterval: config.pollInterval || 2e3,
4510
+ timeout: config.timeout || 3e5,
4511
+ // 5 minutes
4512
+ pollFn: config.pollFn
4513
+ };
4514
+ }
4515
+ /**
4516
+ * 生成二维码图片(Data URL)
4517
+ */
4518
+ async generateQRCode(options) {
4519
+ if (this.qrCodeDataUrl) {
4520
+ return this.qrCodeDataUrl;
4521
+ }
4522
+ try {
4523
+ const qrCodeOptions = {
4524
+ width: options?.width || 300,
4525
+ margin: options?.margin || 2,
4526
+ color: {
4527
+ dark: options?.color?.dark || "#000000",
4528
+ light: options?.color?.light || "#FFFFFF"
4529
+ }
4530
+ };
4531
+ this.qrCodeDataUrl = await QRCode.toDataURL(this.config.requestUrl, qrCodeOptions);
4532
+ return this.qrCodeDataUrl;
4533
+ } catch (error) {
4534
+ throw new Error(`Failed to generate QR code: ${error instanceof Error ? error.message : String(error)}`);
4535
+ }
4536
+ }
4537
+ /**
4538
+ * 开始轮询签名结果
4539
+ */
4540
+ async startPolling(onStatusChange, onResult) {
4541
+ if (this.status === "success" /* SUCCESS */ && this.result?.signature) {
4542
+ return this.result.signature;
4543
+ }
4544
+ if (this.status === "cancelled" /* CANCELLED */ || this.status === "timeout" /* TIMEOUT */) {
4545
+ throw new SignatureRejectedError("Signature request was cancelled or timed out");
4546
+ }
4547
+ this.timeoutTimer = setTimeout(() => {
4548
+ this.stopPolling();
4549
+ this.status = "timeout" /* TIMEOUT */;
4550
+ onStatusChange?.(this.status);
4551
+ throw new SignatureRejectedError("Signature request timed out");
4552
+ }, this.config.timeout);
4553
+ return new Promise((resolve, reject) => {
4554
+ const poll = async () => {
4555
+ try {
4556
+ let result = null;
4557
+ if (this.config.pollFn) {
4558
+ result = await this.config.pollFn(this.config.requestId);
4559
+ } else if (this.config.pollUrl) {
4560
+ result = await this.defaultPoll(this.config.requestId);
4561
+ } else {
4562
+ return;
4563
+ }
4564
+ if (result?.completed) {
4565
+ this.stopPolling();
4566
+ this.result = result;
4567
+ if (result.signature) {
4568
+ this.status = "success" /* SUCCESS */;
4569
+ onStatusChange?.(this.status);
4570
+ onResult?.(result);
4571
+ resolve(result.signature);
4572
+ } else if (result.error) {
4573
+ this.status = "failed" /* FAILED */;
4574
+ onStatusChange?.(this.status);
4575
+ reject(new SignatureRejectedError(result.error));
4576
+ }
4577
+ } else if (result) {
4578
+ if (this.status === "waiting" /* WAITING */) {
4579
+ this.status = "pending" /* PENDING */;
4580
+ onStatusChange?.(this.status);
4581
+ }
4582
+ this.pollTimer = setTimeout(poll, this.config.pollInterval);
4583
+ } else {
4584
+ this.pollTimer = setTimeout(poll, this.config.pollInterval);
4585
+ }
4586
+ } catch (error) {
4587
+ this.stopPolling();
4588
+ this.status = "failed" /* FAILED */;
4589
+ onStatusChange?.(this.status);
4590
+ reject(error);
4591
+ }
4592
+ };
4593
+ poll();
4594
+ });
4595
+ }
4596
+ /**
4597
+ * 默认 HTTP 轮询函数
4598
+ */
4599
+ async defaultPoll(requestId) {
4600
+ if (!this.config.pollUrl) {
4601
+ return null;
4602
+ }
4603
+ try {
4604
+ const url = `${this.config.pollUrl}?requestId=${encodeURIComponent(requestId)}`;
4605
+ const response = await fetch(url, {
4606
+ method: "GET",
4607
+ headers: {
4608
+ "Content-Type": "application/json"
4609
+ }
4610
+ });
4611
+ if (!response.ok) {
4612
+ if (response.status === 404) {
4613
+ return null;
4614
+ }
4615
+ throw new NetworkError(`Poll request failed: ${response.statusText}`);
4616
+ }
4617
+ const data = await response.json();
4618
+ return {
4619
+ completed: data.completed === true,
4620
+ signature: data.signature,
4621
+ error: data.error,
4622
+ signer: data.signer
4623
+ };
4624
+ } catch (error) {
4625
+ if (error instanceof NetworkError) {
4626
+ throw error;
4627
+ }
4628
+ return null;
4629
+ }
4630
+ }
4631
+ /**
4632
+ * 停止轮询
4633
+ */
4634
+ stopPolling() {
4635
+ if (this.pollTimer) {
4636
+ clearTimeout(this.pollTimer);
4637
+ this.pollTimer = null;
4638
+ }
4639
+ if (this.timeoutTimer) {
4640
+ clearTimeout(this.timeoutTimer);
4641
+ this.timeoutTimer = null;
4642
+ }
4643
+ }
4644
+ /**
4645
+ * 取消签名请求
4646
+ */
4647
+ cancel() {
4648
+ this.stopPolling();
4649
+ this.status = "cancelled" /* CANCELLED */;
4650
+ }
4651
+ /**
4652
+ * 获取当前状态
4653
+ */
4654
+ getStatus() {
4655
+ return this.status;
4656
+ }
4657
+ /**
4658
+ * 获取二维码 URL
4659
+ */
4660
+ getQRCodeUrl() {
4661
+ return this.config.requestUrl;
4662
+ }
4663
+ /**
4664
+ * 获取结果
4665
+ */
4666
+ getResult() {
4667
+ return this.result;
4668
+ }
4669
+ /**
4670
+ * 清理资源
4671
+ */
4672
+ cleanup() {
4673
+ this.stopPolling();
4674
+ this.qrCodeDataUrl = null;
4675
+ this.result = null;
4676
+ this.status = "waiting" /* WAITING */;
4677
+ }
4678
+ };
4679
+
1598
4680
  // src/core/wallet-manager.ts
1599
4681
  var WalletManager = class extends TypedEventEmitter {
1600
4682
  constructor(config = {}) {
@@ -1610,9 +4692,15 @@ var WalletManager = class extends TypedEventEmitter {
1610
4692
  defaultTronChainId: config.defaultTronChainId ?? 195,
1611
4693
  walletConnectProjectId: config.walletConnectProjectId ?? ""
1612
4694
  };
1613
- this.registry = new AdapterRegistry();
4695
+ this.registry = new AdapterRegistry(this.config);
1614
4696
  }
1615
4697
  // ===== Connection Management =====
4698
+ /**
4699
+ * Check if adapter is registered for a wallet type
4700
+ */
4701
+ hasAdapter(type) {
4702
+ return this.registry.has(type);
4703
+ }
1616
4704
  /**
1617
4705
  * Connect primary wallet
1618
4706
  */
@@ -1679,7 +4767,7 @@ var WalletManager = class extends TypedEventEmitter {
1679
4767
  this.connectedWallets.delete(chainType);
1680
4768
  this.primaryWallet = null;
1681
4769
  if (this.config.enableStorage) {
1682
- this.saveToStorage();
4770
+ this.clearStorage();
1683
4771
  }
1684
4772
  this.emit("disconnected");
1685
4773
  }
@@ -1768,6 +4856,35 @@ var WalletManager = class extends TypedEventEmitter {
1768
4856
  }
1769
4857
  return adapter.signMessage(message);
1770
4858
  }
4859
+ /**
4860
+ * Create QR code signer for message signing
4861
+ *
4862
+ * This method creates a QR code signer that can be used to display a QR code
4863
+ * for users to scan with their wallet app to sign a message.
4864
+ *
4865
+ * @param message - Message to sign
4866
+ * @param config - QR code signer configuration
4867
+ * @returns QRCodeSigner instance
4868
+ *
4869
+ * @example
4870
+ * ```typescript
4871
+ * const signer = walletManager.createQRCodeSigner('Hello World', {
4872
+ * requestId: 'sign-123',
4873
+ * requestUrl: 'https://example.com/sign?requestId=sign-123&message=Hello%20World',
4874
+ * pollUrl: 'https://api.example.com/sign/status',
4875
+ * })
4876
+ *
4877
+ * const qrCodeUrl = await signer.generateQRCode()
4878
+ * const signature = await signer.startPolling()
4879
+ * ```
4880
+ */
4881
+ createQRCodeSigner(message, config) {
4882
+ return new QRCodeSigner({
4883
+ ...config,
4884
+ // Encode message in request URL if not already encoded
4885
+ requestUrl: config.requestUrl.includes(encodeURIComponent(message)) ? config.requestUrl : `${config.requestUrl}${config.requestUrl.includes("?") ? "&" : "?"}message=${encodeURIComponent(message)}`
4886
+ });
4887
+ }
1771
4888
  /**
1772
4889
  * Sign TypedData (EVM only)
1773
4890
  */
@@ -1832,6 +4949,41 @@ var WalletManager = class extends TypedEventEmitter {
1832
4949
  throw error;
1833
4950
  }
1834
4951
  }
4952
+ /**
4953
+ * Request account switch (opens wallet account selector)
4954
+ * @param targetAddress Optional target address to verify after switching
4955
+ * @returns The new account after switching
4956
+ */
4957
+ async requestSwitchAccount(targetAddress) {
4958
+ if (!this.primaryWallet) {
4959
+ throw new WalletNotConnectedError();
4960
+ }
4961
+ if (!this.primaryWallet.requestSwitchAccount) {
4962
+ throw new Error(`Account switching not supported by ${this.primaryWallet.type}`);
4963
+ }
4964
+ const account = await this.primaryWallet.requestSwitchAccount(targetAddress);
4965
+ if (this.config.enableStorage) {
4966
+ this.saveToStorage();
4967
+ }
4968
+ return account;
4969
+ }
4970
+ /**
4971
+ * Ensure the current account matches the target address
4972
+ * If not matching, request account switch
4973
+ * @param targetAddress The address that should be active
4974
+ * @returns The account (either existing or after switch)
4975
+ */
4976
+ async ensureAccount(targetAddress) {
4977
+ const currentAccount = this.getPrimaryAccount();
4978
+ if (!currentAccount) {
4979
+ throw new WalletNotConnectedError();
4980
+ }
4981
+ if (currentAccount.nativeAddress.toLowerCase() === targetAddress.toLowerCase()) {
4982
+ return currentAccount;
4983
+ }
4984
+ console.log(`[WalletManager] Current account ${currentAccount.nativeAddress} doesn't match target ${targetAddress}, requesting switch...`);
4985
+ return this.requestSwitchAccount(targetAddress);
4986
+ }
1835
4987
  // ===== Contract Calls =====
1836
4988
  /**
1837
4989
  * Read contract
@@ -2078,6 +5230,29 @@ var WalletManager = class extends TypedEventEmitter {
2078
5230
  console.debug("Silent TronLink connection failed:", silentError);
2079
5231
  }
2080
5232
  }
5233
+ if (data.primaryWalletType === "walletconnect-tron" /* WALLETCONNECT_TRON */) {
5234
+ try {
5235
+ const wcAdapter = adapter;
5236
+ if (typeof wcAdapter.restoreSession === "function") {
5237
+ console.debug("[WalletManager] Attempting to restore WalletConnect Tron session...");
5238
+ const account2 = await wcAdapter.restoreSession(data.primaryChainId);
5239
+ if (account2) {
5240
+ console.debug("[WalletManager] WalletConnect Tron session restored successfully");
5241
+ this.setPrimaryWallet(adapter);
5242
+ this.connectedWallets.set(adapter.chainType, adapter);
5243
+ this.setupAdapterListeners(adapter, true);
5244
+ this.emit("accountChanged", account2);
5245
+ return account2;
5246
+ } else {
5247
+ console.debug("[WalletManager] No valid WalletConnect Tron session found");
5248
+ return null;
5249
+ }
5250
+ }
5251
+ } catch (restoreError) {
5252
+ console.debug("[WalletManager] WalletConnect Tron restore failed:", restoreError);
5253
+ return null;
5254
+ }
5255
+ }
2081
5256
  const account = await adapter.connect(data.primaryChainId);
2082
5257
  this.setPrimaryWallet(adapter);
2083
5258
  this.connectedWallets.set(adapter.chainType, adapter);
@@ -2226,7 +5401,7 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
2226
5401
  signMessage,
2227
5402
  signTransaction
2228
5403
  };
2229
- return /* @__PURE__ */ React.createElement(WalletContext.Provider, { value }, children);
5404
+ return /* @__PURE__ */ React2.createElement(WalletContext.Provider, { value }, children);
2230
5405
  }
2231
5406
  function useWallet() {
2232
5407
  const context = useContext(WalletContext);
@@ -2357,7 +5532,375 @@ function useSignTransaction() {
2357
5532
  error
2358
5533
  };
2359
5534
  }
5535
+ function useQRCodeSigner(config) {
5536
+ const [qrCodeDataUrl, setQrCodeDataUrl] = useState(null);
5537
+ const [status, setStatus] = useState("waiting" /* WAITING */);
5538
+ const [result, setResult] = useState(null);
5539
+ const [isPolling, setIsPolling] = useState(false);
5540
+ const [error, setError] = useState(null);
5541
+ const signerRef = useRef(null);
5542
+ useEffect(() => {
5543
+ signerRef.current = new QRCodeSigner(config);
5544
+ return () => {
5545
+ signerRef.current?.cleanup();
5546
+ };
5547
+ }, [config.requestId, config.requestUrl, config.pollUrl]);
5548
+ const generateQRCode = useCallback(async () => {
5549
+ if (!signerRef.current) return;
5550
+ try {
5551
+ const dataUrl = await signerRef.current.generateQRCode();
5552
+ setQrCodeDataUrl(dataUrl);
5553
+ } catch (err) {
5554
+ const error2 = err instanceof Error ? err : new Error(String(err));
5555
+ setError(error2);
5556
+ }
5557
+ }, []);
5558
+ const startSign = useCallback(async () => {
5559
+ if (!signerRef.current) {
5560
+ throw new Error("QRCodeSigner not initialized");
5561
+ }
5562
+ setError(null);
5563
+ setStatus("waiting" /* WAITING */);
5564
+ setIsPolling(true);
5565
+ try {
5566
+ await generateQRCode();
5567
+ const signature = await signerRef.current.startPolling(
5568
+ (newStatus) => {
5569
+ setStatus(newStatus);
5570
+ },
5571
+ (signResult) => {
5572
+ setResult(signResult);
5573
+ }
5574
+ );
5575
+ setIsPolling(false);
5576
+ return signature;
5577
+ } catch (err) {
5578
+ setIsPolling(false);
5579
+ const error2 = err instanceof Error ? err : new SignatureRejectedError(err instanceof Error ? err.message : String(err));
5580
+ setError(error2);
5581
+ throw error2;
5582
+ }
5583
+ }, [generateQRCode]);
5584
+ const stopPolling = useCallback(() => {
5585
+ signerRef.current?.stopPolling();
5586
+ setIsPolling(false);
5587
+ }, []);
5588
+ const cancel = useCallback(() => {
5589
+ signerRef.current?.cancel();
5590
+ setStatus("cancelled" /* CANCELLED */);
5591
+ setIsPolling(false);
5592
+ }, []);
5593
+ return {
5594
+ qrCodeDataUrl,
5595
+ status,
5596
+ result,
5597
+ isPolling,
5598
+ startSign,
5599
+ stopPolling,
5600
+ cancel,
5601
+ error
5602
+ };
5603
+ }
5604
+ function QRCodeModal({
5605
+ isOpen,
5606
+ onClose,
5607
+ qrCodeDataUrl,
5608
+ status,
5609
+ error,
5610
+ title = "\u626B\u7801\u7B7E\u540D",
5611
+ description
5612
+ }) {
5613
+ useEffect(() => {
5614
+ if (isOpen) {
5615
+ document.body.style.overflow = "hidden";
5616
+ } else {
5617
+ document.body.style.overflow = "";
5618
+ }
5619
+ return () => {
5620
+ document.body.style.overflow = "";
5621
+ };
5622
+ }, [isOpen]);
5623
+ if (!isOpen) {
5624
+ return null;
5625
+ }
5626
+ const getStatusText = () => {
5627
+ switch (status) {
5628
+ case "waiting" /* WAITING */:
5629
+ return "\u8BF7\u4F7F\u7528\u94B1\u5305\u626B\u63CF\u4E8C\u7EF4\u7801";
5630
+ case "pending" /* PENDING */:
5631
+ return "\u5DF2\u626B\u63CF\uFF0C\u8BF7\u5728\u94B1\u5305\u4E2D\u786E\u8BA4\u7B7E\u540D";
5632
+ case "success" /* SUCCESS */:
5633
+ return "\u7B7E\u540D\u6210\u529F";
5634
+ case "failed" /* FAILED */:
5635
+ return "\u7B7E\u540D\u5931\u8D25";
5636
+ case "timeout" /* TIMEOUT */:
5637
+ return "\u7B7E\u540D\u8D85\u65F6";
5638
+ case "cancelled" /* CANCELLED */:
5639
+ return "\u5DF2\u53D6\u6D88";
5640
+ default:
5641
+ return "\u7B49\u5F85\u626B\u63CF";
5642
+ }
5643
+ };
5644
+ const getStatusColor = () => {
5645
+ switch (status) {
5646
+ case "waiting" /* WAITING */:
5647
+ case "pending" /* PENDING */:
5648
+ return "#3b82f6";
5649
+ // blue
5650
+ case "success" /* SUCCESS */:
5651
+ return "#10b981";
5652
+ // green
5653
+ case "failed" /* FAILED */:
5654
+ case "timeout" /* TIMEOUT */:
5655
+ case "cancelled" /* CANCELLED */:
5656
+ return "#ef4444";
5657
+ // red
5658
+ default:
5659
+ return "#6b7280";
5660
+ }
5661
+ };
5662
+ return /* @__PURE__ */ React2.createElement(
5663
+ "div",
5664
+ {
5665
+ style: {
5666
+ position: "fixed",
5667
+ top: 0,
5668
+ left: 0,
5669
+ right: 0,
5670
+ bottom: 0,
5671
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
5672
+ display: "flex",
5673
+ alignItems: "center",
5674
+ justifyContent: "center",
5675
+ zIndex: 1e4,
5676
+ padding: "20px"
5677
+ },
5678
+ onClick: (e) => {
5679
+ if (e.target === e.currentTarget) {
5680
+ onClose();
5681
+ }
5682
+ }
5683
+ },
5684
+ /* @__PURE__ */ React2.createElement(
5685
+ "div",
5686
+ {
5687
+ style: {
5688
+ backgroundColor: "#ffffff",
5689
+ borderRadius: "12px",
5690
+ padding: "24px",
5691
+ maxWidth: "400px",
5692
+ width: "100%",
5693
+ boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)"
5694
+ }
5695
+ },
5696
+ /* @__PURE__ */ React2.createElement(
5697
+ "div",
5698
+ {
5699
+ style: {
5700
+ display: "flex",
5701
+ justifyContent: "space-between",
5702
+ alignItems: "center",
5703
+ marginBottom: "20px"
5704
+ }
5705
+ },
5706
+ /* @__PURE__ */ React2.createElement(
5707
+ "h2",
5708
+ {
5709
+ style: {
5710
+ margin: 0,
5711
+ fontSize: "20px",
5712
+ fontWeight: 600,
5713
+ color: "#111827"
5714
+ }
5715
+ },
5716
+ title
5717
+ ),
5718
+ /* @__PURE__ */ React2.createElement(
5719
+ "button",
5720
+ {
5721
+ onClick: onClose,
5722
+ style: {
5723
+ background: "none",
5724
+ border: "none",
5725
+ fontSize: "24px",
5726
+ cursor: "pointer",
5727
+ color: "#6b7280",
5728
+ padding: 0,
5729
+ width: "24px",
5730
+ height: "24px",
5731
+ display: "flex",
5732
+ alignItems: "center",
5733
+ justifyContent: "center"
5734
+ }
5735
+ },
5736
+ "\xD7"
5737
+ )
5738
+ ),
5739
+ description && /* @__PURE__ */ React2.createElement(
5740
+ "p",
5741
+ {
5742
+ style: {
5743
+ margin: "0 0 20px 0",
5744
+ fontSize: "14px",
5745
+ color: "#6b7280"
5746
+ }
5747
+ },
5748
+ description
5749
+ ),
5750
+ /* @__PURE__ */ React2.createElement(
5751
+ "div",
5752
+ {
5753
+ style: {
5754
+ display: "flex",
5755
+ justifyContent: "center",
5756
+ marginBottom: "20px"
5757
+ }
5758
+ },
5759
+ qrCodeDataUrl ? /* @__PURE__ */ React2.createElement(
5760
+ "img",
5761
+ {
5762
+ src: qrCodeDataUrl,
5763
+ alt: "QR Code",
5764
+ style: {
5765
+ width: "100%",
5766
+ maxWidth: "300px",
5767
+ height: "auto",
5768
+ border: "1px solid #e5e7eb",
5769
+ borderRadius: "8px"
5770
+ }
5771
+ }
5772
+ ) : /* @__PURE__ */ React2.createElement(
5773
+ "div",
5774
+ {
5775
+ style: {
5776
+ width: "300px",
5777
+ height: "300px",
5778
+ backgroundColor: "#f3f4f6",
5779
+ display: "flex",
5780
+ alignItems: "center",
5781
+ justifyContent: "center",
5782
+ borderRadius: "8px",
5783
+ color: "#6b7280"
5784
+ }
5785
+ },
5786
+ "\u751F\u6210\u4E8C\u7EF4\u7801\u4E2D..."
5787
+ )
5788
+ ),
5789
+ /* @__PURE__ */ React2.createElement(
5790
+ "div",
5791
+ {
5792
+ style: {
5793
+ textAlign: "center",
5794
+ marginBottom: "20px"
5795
+ }
5796
+ },
5797
+ /* @__PURE__ */ React2.createElement(
5798
+ "div",
5799
+ {
5800
+ style: {
5801
+ display: "inline-flex",
5802
+ alignItems: "center",
5803
+ gap: "8px",
5804
+ padding: "8px 16px",
5805
+ borderRadius: "6px",
5806
+ backgroundColor: `${getStatusColor()}15`,
5807
+ color: getStatusColor(),
5808
+ fontSize: "14px",
5809
+ fontWeight: 500
5810
+ }
5811
+ },
5812
+ status === "waiting" /* WAITING */ && /* @__PURE__ */ React2.createElement(
5813
+ "div",
5814
+ {
5815
+ style: {
5816
+ width: "8px",
5817
+ height: "8px",
5818
+ borderRadius: "50%",
5819
+ backgroundColor: getStatusColor(),
5820
+ animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite"
5821
+ }
5822
+ }
5823
+ ),
5824
+ status === "pending" /* PENDING */ && /* @__PURE__ */ React2.createElement(
5825
+ "div",
5826
+ {
5827
+ style: {
5828
+ width: "8px",
5829
+ height: "8px",
5830
+ borderRadius: "50%",
5831
+ backgroundColor: getStatusColor()
5832
+ }
5833
+ }
5834
+ ),
5835
+ status === "success" /* SUCCESS */ && "\u2713",
5836
+ status === "failed" /* FAILED */ && "\u2715",
5837
+ getStatusText()
5838
+ )
5839
+ ),
5840
+ error && /* @__PURE__ */ React2.createElement(
5841
+ "div",
5842
+ {
5843
+ style: {
5844
+ padding: "12px",
5845
+ backgroundColor: "#fef2f2",
5846
+ border: "1px solid #fecaca",
5847
+ borderRadius: "6px",
5848
+ marginBottom: "20px"
5849
+ }
5850
+ },
5851
+ /* @__PURE__ */ React2.createElement(
5852
+ "p",
5853
+ {
5854
+ style: {
5855
+ margin: 0,
5856
+ fontSize: "14px",
5857
+ color: "#dc2626"
5858
+ }
5859
+ },
5860
+ error.message
5861
+ )
5862
+ ),
5863
+ /* @__PURE__ */ React2.createElement(
5864
+ "div",
5865
+ {
5866
+ style: {
5867
+ display: "flex",
5868
+ gap: "12px"
5869
+ }
5870
+ },
5871
+ /* @__PURE__ */ React2.createElement(
5872
+ "button",
5873
+ {
5874
+ onClick: onClose,
5875
+ style: {
5876
+ flex: 1,
5877
+ padding: "10px 20px",
5878
+ border: "1px solid #d1d5db",
5879
+ borderRadius: "6px",
5880
+ backgroundColor: "#ffffff",
5881
+ color: "#374151",
5882
+ fontSize: "14px",
5883
+ fontWeight: 500,
5884
+ cursor: "pointer"
5885
+ }
5886
+ },
5887
+ status === "success" /* SUCCESS */ ? "\u5173\u95ED" : "\u53D6\u6D88"
5888
+ )
5889
+ )
5890
+ ),
5891
+ /* @__PURE__ */ React2.createElement("style", null, `
5892
+ @keyframes pulse {
5893
+ 0%, 100% {
5894
+ opacity: 1;
5895
+ }
5896
+ 50% {
5897
+ opacity: 0.5;
5898
+ }
5899
+ }
5900
+ `)
5901
+ );
5902
+ }
2360
5903
 
2361
- export { WalletProvider, useAccount, useConnect, useDisconnect, useSignMessage, useSignTransaction, useWallet };
5904
+ export { QRCodeModal, WalletProvider, useAccount, useConnect, useDisconnect, useQRCodeSigner, useSignMessage, useSignTransaction, useWallet };
2362
5905
  //# sourceMappingURL=index.mjs.map
2363
5906
  //# sourceMappingURL=index.mjs.map