@tomo-inc/wallet-connect-protocol 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,349 +1,780 @@
1
- import { WalletConnectClient, isSessionExpired, extractAddressFromAccount, extractChainIdFromAccount, extractChainIdNumber, createSiweConfigFromSession, SiweAuth } from './chunk-32KOSJUW.js';
2
- export { APTOS_CHAINS, APTOS_NAMESPACE, AuthMethod, COSMOS_NAMESPACE, ChainType, EIP155_NAMESPACE, EVM_CHAINS, NEAR_NAMESPACE, POLKADOT_NAMESPACE, POPULAR_WALLET_IDS, SOLANA_CHAINS, SOLANA_NAMESPACE, SiweAuth, WalletConnectClient, copyToClipboard, createMultiChainNamespaces, createSiweConfigFromSession, createSiweMessage, extractAddressFromAccount, extractChainIdFromAccount, extractChainIdNumber, formatAddress, formatError, formatTimestamp, generateDeepLink, generateNonce, getAllWallets, getBrowserWallets, getChainName, getChainType, getDesktopWallets, getMobileWallets, getRecommendedWallets, getSessionTimeRemaining, getWalletById, getWalletConnectWallets, getWalletsByChain, isMobile, isSessionExpired, isValidChainId, isValidWalletConnectUri, parseChainId, parseSiweMessage, parseWalletConnectUri, searchWallets, verifySiweSignature } from './chunk-32KOSJUW.js';
3
- import { createContext, useState, useCallback, useEffect, useContext } from 'react';
4
- import { jsx } from 'react/jsx-runtime';
1
+ import SignClient from '@walletconnect/sign-client';
2
+ import QRCode from 'qrcode';
5
3
 
6
- var WalletConnectContext = createContext(void 0);
7
- function WalletConnectProvider({ config, children, autoInit = true }) {
8
- const [client, setClient] = useState(null);
9
- const [initialized, setInitialized] = useState(false);
10
- const [connecting, setConnecting] = useState(false);
11
- const [uri, setUri] = useState(null);
12
- const [sessions, setSessions] = useState([]);
13
- const refreshSessions = useCallback(() => {
14
- if (client) {
15
- const activeSessions = client.getActiveSessions();
16
- setSessions(activeSessions);
17
- }
18
- }, [client]);
19
- const initialize = useCallback(async () => {
20
- if (initialized) {
4
+ // src/client.ts
5
+ var WalletConnectClient = class {
6
+ signClient = null;
7
+ config;
8
+ eventHandlers = /* @__PURE__ */ new Map();
9
+ initialized = false;
10
+ constructor(config) {
11
+ this.config = config;
12
+ }
13
+ /**
14
+ * initialize WalletConnect client
15
+ */
16
+ async initialize() {
17
+ if (this.initialized) {
21
18
  return;
22
19
  }
23
20
  try {
24
- const newClient = new WalletConnectClient(config);
25
- newClient.on("display_uri", ({ uri: uri2 }) => {
26
- setUri(uri2);
21
+ this.signClient = await SignClient.init({
22
+ projectId: this.config.projectId,
23
+ metadata: this.config.metadata,
24
+ relayUrl: this.config.relayUrl
27
25
  });
28
- const handleSessionUpdate = () => {
29
- const activeSessions2 = newClient.getActiveSessions();
30
- setSessions(activeSessions2);
26
+ this.setupEventListeners();
27
+ this.initialized = true;
28
+ } catch (error) {
29
+ throw error;
30
+ }
31
+ }
32
+ /**
33
+ * set event listeners
34
+ */
35
+ setupEventListeners() {
36
+ if (!this.signClient) return;
37
+ this.signClient.on("session_proposal", (proposal) => {
38
+ this.emit("session_proposal", proposal);
39
+ });
40
+ this.signClient.on("session_request", (request) => {
41
+ this.emit("session_request", request);
42
+ });
43
+ this.signClient.on("session_delete", (data) => {
44
+ this.emit("session_delete", data);
45
+ });
46
+ this.signClient.on("session_update", (data) => {
47
+ this.emit("session_update", data);
48
+ });
49
+ }
50
+ /**
51
+ * create pairing connection and generate URI
52
+ * @param params connection parameters
53
+ * @returns WalletConnect URI
54
+ */
55
+ async connect(params) {
56
+ if (!this.signClient) {
57
+ throw new Error("WalletConnect client not initialized. Call initialize() first.");
58
+ }
59
+ try {
60
+ const defaultNamespaces = {
61
+ eip155: {
62
+ methods: [
63
+ "eth_sendTransaction",
64
+ "eth_signTransaction",
65
+ "eth_sign",
66
+ "personal_sign",
67
+ "eth_signTypedData",
68
+ "eth_signTypedData_v4"
69
+ ],
70
+ chains: ["eip155:1"],
71
+ // Ethereum Mainnet
72
+ events: ["chainChanged", "accountsChanged"]
73
+ }
74
+ };
75
+ const defaultOptionalNamespaces = {
76
+ eip155: {
77
+ methods: [
78
+ "eth_sendTransaction",
79
+ "eth_signTransaction",
80
+ "eth_sign",
81
+ "personal_sign",
82
+ "eth_signTypedData",
83
+ "eth_signTypedData_v4"
84
+ ],
85
+ chains: [
86
+ "eip155:137",
87
+ // Polygon Mainnet
88
+ "eip155:56",
89
+ // BSC Mainnet
90
+ "eip155:42161",
91
+ // Arbitrum Mainnet
92
+ "eip155:10",
93
+ // Optimism Mainnet
94
+ "eip155:43114"
95
+ // Avalanche Mainnet
96
+ ],
97
+ events: ["chainChanged", "accountsChanged"]
98
+ },
99
+ solana: {
100
+ methods: ["solana_signTransaction", "solana_signMessage"],
101
+ chains: ["solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ"],
102
+ events: ["accountsChanged"]
103
+ }
104
+ };
105
+ const { uri, approval } = await this.signClient.connect({
106
+ requiredNamespaces: params?.requiredNamespaces || defaultNamespaces,
107
+ optionalNamespaces: params?.optionalNamespaces || defaultOptionalNamespaces
108
+ });
109
+ if (!uri) {
110
+ throw new Error("Failed to generate WalletConnect URI");
111
+ }
112
+ this.emit("display_uri", { uri });
113
+ approval().then((session) => {
114
+ this.emit("session_update", session);
115
+ }).catch((error) => {
116
+ });
117
+ return uri;
118
+ } catch (error) {
119
+ throw error;
120
+ }
121
+ }
122
+ /**
123
+ * generate QR code (Base64 format)
124
+ * @param uri WalletConnect URI
125
+ * @param options QR code options
126
+ * @returns Base64 formatted QR code image
127
+ */
128
+ async generateQRCode(uri, options) {
129
+ try {
130
+ const qrOptions = {
131
+ width: options?.width || 300,
132
+ margin: options?.margin || 4,
133
+ errorCorrectionLevel: options?.errorCorrectionLevel || "M",
134
+ color: {
135
+ dark: options?.color?.dark || "#000000",
136
+ light: options?.color?.light || "#ffffff"
137
+ }
138
+ };
139
+ const qrCodeDataUrl = await QRCode.toDataURL(uri, qrOptions);
140
+ return qrCodeDataUrl;
141
+ } catch (error) {
142
+ throw error;
143
+ }
144
+ }
145
+ /**
146
+ * generate QR code (Canvas format)
147
+ * @param canvas Canvas element
148
+ * @param uri WalletConnect URI
149
+ * @param options QR code options
150
+ */
151
+ async generateQRCodeToCanvas(canvas, uri, options) {
152
+ try {
153
+ const qrOptions = {
154
+ width: options?.width || 300,
155
+ margin: options?.margin || 4,
156
+ errorCorrectionLevel: options?.errorCorrectionLevel || "M",
157
+ color: {
158
+ dark: options?.color?.dark || "#000000",
159
+ light: options?.color?.light || "#ffffff"
160
+ }
31
161
  };
32
- newClient.on("session_proposal", handleSessionUpdate);
33
- newClient.on("session_update", handleSessionUpdate);
34
- newClient.on("session_delete", handleSessionUpdate);
35
- await newClient.initialize();
36
- setClient(newClient);
37
- setInitialized(true);
38
- const activeSessions = newClient.getActiveSessions();
39
- setSessions(activeSessions);
162
+ await QRCode.toCanvas(canvas, uri, qrOptions);
40
163
  } catch (error) {
41
164
  throw error;
42
165
  }
43
- }, [config, initialized]);
44
- const connect = useCallback(async () => {
45
- if (!client) {
166
+ }
167
+ /**
168
+ * get all active sessions
169
+ * @returns session information array
170
+ */
171
+ getActiveSessions() {
172
+ if (!this.signClient) {
173
+ return [];
174
+ }
175
+ const sessions = this.signClient.session.getAll();
176
+ return sessions.map((session) => ({
177
+ topic: session.topic,
178
+ peer: session.peer,
179
+ namespaces: session.namespaces,
180
+ expiry: session.expiry
181
+ }));
182
+ }
183
+ /**
184
+ * disconnect specified session
185
+ * @param topic session topic/ID
186
+ */
187
+ async disconnectSession(topic) {
188
+ if (!this.signClient) {
46
189
  throw new Error("WalletConnect client not initialized");
47
190
  }
48
- setConnecting(true);
49
191
  try {
50
- const connectionUri = await client.connect();
51
- setUri(connectionUri);
52
- return connectionUri;
192
+ await this.signClient.disconnect({
193
+ topic,
194
+ reason: {
195
+ code: 6e3,
196
+ message: "User disconnected"
197
+ }
198
+ });
53
199
  } catch (error) {
54
200
  throw error;
55
- } finally {
56
- setConnecting(false);
57
201
  }
58
- }, [client]);
59
- const generateQRCode = useCallback(
60
- async (uri2, options) => {
61
- if (!client) {
62
- throw new Error("WalletConnect client not initialized");
63
- }
64
- return client.generateQRCode(uri2, options);
65
- },
66
- [client]
67
- );
68
- const disconnect = useCallback(
69
- async (topic) => {
70
- if (!client) {
71
- throw new Error("WalletConnect client not initialized");
72
- }
73
- await client.disconnectSession(topic);
74
- refreshSessions();
75
- },
76
- [client]
77
- );
78
- useEffect(() => {
79
- if (!client || !initialized) return;
80
- const interval = setInterval(() => {
81
- refreshSessions();
82
- }, 2e3);
83
- return () => clearInterval(interval);
84
- }, [client, initialized, refreshSessions]);
85
- useEffect(() => {
86
- if (autoInit && !initialized) {
87
- initialize().catch(console.error);
202
+ }
203
+ /**
204
+ * listen to events
205
+ * @param event event name
206
+ * @param handler event handler
207
+ */
208
+ on(event, handler) {
209
+ if (!this.eventHandlers.has(event)) {
210
+ this.eventHandlers.set(event, /* @__PURE__ */ new Set());
88
211
  }
89
- }, [autoInit, initialized, initialize]);
90
- useEffect(() => {
91
- return () => {
92
- if (client) {
93
- client.destroy().catch(console.error);
94
- }
212
+ this.eventHandlers.get(event)?.add(handler);
213
+ }
214
+ /**
215
+ * remove event listener
216
+ * @param event event name
217
+ * @param handler event handler
218
+ */
219
+ off(event, handler) {
220
+ this.eventHandlers.get(event)?.delete(handler);
221
+ }
222
+ /**
223
+ * trigger event
224
+ * @param event event name
225
+ * @param data event data
226
+ */
227
+ emit(event, data) {
228
+ const handlers = this.eventHandlers.get(event);
229
+ if (handlers) {
230
+ handlers.forEach((handler) => {
231
+ try {
232
+ handler(data);
233
+ } catch (error) {
234
+ }
235
+ });
236
+ }
237
+ }
238
+ /**
239
+ * send JSON-RPC request to wallet
240
+ * @param params request parameters
241
+ * @returns request result
242
+ */
243
+ async sendRequest(params) {
244
+ if (!this.signClient) {
245
+ throw new Error("WalletConnect client not initialized");
246
+ }
247
+ try {
248
+ const result = await this.signClient.request({
249
+ topic: params.topic,
250
+ chainId: params.chainId,
251
+ request: params.request
252
+ });
253
+ return result;
254
+ } catch (error) {
255
+ throw error;
256
+ }
257
+ }
258
+ /**
259
+ * destroy client
260
+ */
261
+ async destroy() {
262
+ if (this.signClient) {
263
+ this.eventHandlers.clear();
264
+ this.signClient = null;
265
+ this.initialized = false;
266
+ }
267
+ }
268
+ /**
269
+ * get if client is initialized
270
+ */
271
+ isInitialized() {
272
+ return this.initialized;
273
+ }
274
+ /**
275
+ * get configuration information
276
+ */
277
+ getConfig() {
278
+ return { ...this.config };
279
+ }
280
+ };
281
+
282
+ // src/utils.ts
283
+ function isValidWalletConnectUri(uri) {
284
+ return uri.startsWith("wc:") || uri.startsWith("wc://");
285
+ }
286
+ function parseWalletConnectUri(uri) {
287
+ try {
288
+ const cleanUri = uri.replace(/^wc:\/?\/?/, "");
289
+ const [topicVersion, paramsString] = cleanUri.split("?");
290
+ const [topic, version] = topicVersion.split("@");
291
+ const params = new URLSearchParams(paramsString);
292
+ return {
293
+ topic,
294
+ version,
295
+ symKey: params.get("symKey") || void 0,
296
+ relay: params.get("relay-protocol") ? {
297
+ protocol: params.get("relay-protocol"),
298
+ data: params.get("relay-data") || void 0
299
+ } : void 0
95
300
  };
96
- }, [client]);
97
- const value = {
98
- client,
99
- initialized,
100
- connecting,
101
- uri,
102
- sessions,
103
- initialize,
104
- connect,
105
- generateQRCode,
106
- disconnect,
107
- refreshSessions
108
- };
109
- return /* @__PURE__ */ jsx(WalletConnectContext.Provider, { value, children });
301
+ } catch {
302
+ return null;
303
+ }
110
304
  }
111
- function useWalletConnect() {
112
- const context = useContext(WalletConnectContext);
113
- if (!context) {
114
- throw new Error("useWalletConnect must be used within WalletConnectProvider");
305
+ function formatAddress(address, startLength = 6, endLength = 4) {
306
+ if (!address || address.length < startLength + endLength) {
307
+ return address;
115
308
  }
116
- return context;
309
+ return `${address.slice(0, startLength)}...${address.slice(-endLength)}`;
117
310
  }
118
- function useQRCode(uri, options) {
119
- const { generateQRCode } = useWalletConnect();
120
- const [qrCode, setQrCode] = useState(null);
121
- const [loading, setLoading] = useState(false);
122
- const [error, setError] = useState(null);
123
- const generate = useCallback(
124
- async (targetUri) => {
125
- const uriToUse = targetUri || uri;
126
- if (!uriToUse) {
127
- setError(new Error("No URI provided"));
128
- return;
129
- }
130
- setLoading(true);
131
- setError(null);
132
- try {
133
- const qr = await generateQRCode(uriToUse, options);
134
- setQrCode(qr);
135
- } catch (err) {
136
- setError(err);
137
- setQrCode(null);
138
- } finally {
139
- setLoading(false);
140
- }
141
- },
142
- [uri, options, generateQRCode]
143
- );
144
- useEffect(() => {
145
- if (uri) {
146
- generate(uri);
311
+ function extractAddressFromAccount(account) {
312
+ const parts = account.split(":");
313
+ return parts.length > 1 ? parts[parts.length - 1] : account;
314
+ }
315
+ function extractChainIdFromAccount(account) {
316
+ const parts = account.split(":");
317
+ return parts.length > 2 ? `${parts[0]}:${parts[1]}` : "";
318
+ }
319
+ function isSessionExpired(expiry) {
320
+ return Date.now() / 1e3 > expiry;
321
+ }
322
+ function getSessionTimeRemaining(expiry) {
323
+ const remaining = expiry - Date.now() / 1e3;
324
+ return Math.max(0, remaining);
325
+ }
326
+ function formatTimestamp(timestamp) {
327
+ const date = new Date(timestamp * 1e3);
328
+ return date.toLocaleString();
329
+ }
330
+ function isMobile() {
331
+ if (typeof window === "undefined") return false;
332
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
333
+ }
334
+ function generateDeepLink(uri, walletName) {
335
+ const encodedUri = encodeURIComponent(uri);
336
+ if (walletName) {
337
+ switch (walletName.toLowerCase()) {
338
+ case "metamask":
339
+ return `https://metamask.app.link/wc?uri=${encodedUri}`;
340
+ case "trust":
341
+ return `https://link.trustwallet.com/wc?uri=${encodedUri}`;
342
+ case "rainbow":
343
+ return `https://rnbwapp.com/wc?uri=${encodedUri}`;
344
+ default:
345
+ return `wc://wc?uri=${encodedUri}`;
147
346
  }
148
- }, [uri, generate]);
149
- return {
150
- qrCode,
151
- loading,
152
- error,
153
- generate
154
- };
347
+ }
348
+ return `wc://wc?uri=${encodedUri}`;
155
349
  }
156
- function useSession(topic) {
157
- const { sessions, disconnect, refreshSessions, client } = useWalletConnect();
158
- const [currentSession, setCurrentSession] = useState(null);
159
- useEffect(() => {
160
- if (topic) {
161
- const session = sessions.find((s) => s.topic === topic);
162
- setCurrentSession(session || null);
350
+ async function copyToClipboard(text) {
351
+ try {
352
+ if (navigator.clipboard) {
353
+ await navigator.clipboard.writeText(text);
354
+ return true;
163
355
  } else {
164
- setCurrentSession(sessions[0] || null);
356
+ const textarea = document.createElement("textarea");
357
+ textarea.value = text;
358
+ textarea.style.position = "fixed";
359
+ textarea.style.opacity = "0";
360
+ document.body.appendChild(textarea);
361
+ textarea.select();
362
+ const success = document.execCommand("copy");
363
+ document.body.removeChild(textarea);
364
+ return success;
165
365
  }
166
- }, [topic, sessions]);
167
- const disconnectSession = useCallback(
168
- async (sessionTopic) => {
169
- const topicToDisconnect = sessionTopic || topic || currentSession?.topic;
170
- if (!topicToDisconnect) {
171
- throw new Error("No session to disconnect");
172
- }
173
- await disconnect(topicToDisconnect);
174
- },
175
- [topic, currentSession, disconnect]
176
- );
177
- const checkExpired = useCallback((session) => {
178
- return isSessionExpired(session.expiry);
179
- }, []);
180
- const getAccounts = useCallback(
181
- (session) => {
182
- const targetSession = session || currentSession;
183
- if (!targetSession) return [];
184
- const allAccounts = [];
185
- Object.values(targetSession.namespaces).forEach((namespace) => {
186
- if (namespace.accounts) {
187
- allAccounts.push(...namespace.accounts);
188
- }
189
- });
190
- return allAccounts;
191
- },
192
- [currentSession]
193
- );
194
- const getChains = useCallback(
195
- (session) => {
196
- const targetSession = session || currentSession;
197
- if (!targetSession) return [];
198
- const allChains = [];
199
- Object.values(targetSession.namespaces).forEach((namespace) => {
200
- if (namespace.chains) {
201
- allChains.push(...namespace.chains);
202
- }
203
- });
204
- return allChains;
205
- },
206
- [currentSession]
207
- );
208
- return {
209
- session: currentSession,
210
- allSessions: sessions,
211
- disconnect: disconnectSession,
212
- refresh: refreshSessions,
213
- isExpired: currentSession ? checkExpired(currentSession) : false,
214
- getAccounts,
215
- getChains,
216
- hasSession: !!currentSession
217
- };
366
+ } catch {
367
+ return false;
368
+ }
218
369
  }
219
- function useConnect(options) {
220
- const { connect, generateQRCode, connecting } = useWalletConnect();
221
- const [uri, setUri] = useState(null);
222
- const [qrCode, setQrCode] = useState(null);
223
- const [error, setError] = useState(null);
224
- const handleConnect = useCallback(async () => {
225
- setError(null);
226
- try {
227
- const connectionUri = await connect();
228
- setUri(connectionUri);
229
- if (options?.onConnect) {
230
- options.onConnect(connectionUri);
231
- }
232
- if (options?.autoGenerateQRCode !== false) {
233
- const qr = await generateQRCode(connectionUri, options?.qrCodeOptions);
234
- setQrCode(qr);
370
+ function formatError(error) {
371
+ if (typeof error === "string") return error;
372
+ if (error?.message) return error.message;
373
+ if (error?.error?.message) return error.error.message;
374
+ return "Unknown error occurred";
375
+ }
376
+ function isValidChainId(chainId) {
377
+ return /^[a-z]+:\d+$/.test(chainId);
378
+ }
379
+ function parseChainId(chainId) {
380
+ if (!isValidChainId(chainId)) return null;
381
+ const [namespace, reference] = chainId.split(":");
382
+ return { namespace, reference };
383
+ }
384
+
385
+ // src/chains.ts
386
+ var EIP155_NAMESPACE = {
387
+ chains: ["eip155:1"],
388
+ // Ethereum Mainnet
389
+ methods: [
390
+ "eth_sendTransaction",
391
+ "eth_signTransaction",
392
+ "eth_sign",
393
+ "personal_sign",
394
+ "eth_signTypedData",
395
+ "eth_signTypedData_v4",
396
+ "wallet_switchEthereumChain",
397
+ "wallet_addEthereumChain"
398
+ ],
399
+ events: ["chainChanged", "accountsChanged"]
400
+ };
401
+ var SOLANA_NAMESPACE = {
402
+ chains: ["solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ"],
403
+ // Solana Mainnet
404
+ methods: ["solana_signTransaction", "solana_signMessage", "solana_signAndSendTransaction"],
405
+ events: ["accountsChanged", "chainChanged"]
406
+ };
407
+ var APTOS_NAMESPACE = {
408
+ chains: ["aptos:1"],
409
+ // Aptos Mainnet
410
+ methods: ["aptos_signTransaction", "aptos_signMessage", "aptos_signAndSubmitTransaction"],
411
+ events: ["accountChanged", "networkChanged"]
412
+ };
413
+ var COSMOS_NAMESPACE = {
414
+ chains: ["cosmos:cosmoshub-4"],
415
+ // Cosmos Hub
416
+ methods: ["cosmos_signDirect", "cosmos_signAmino", "cosmos_getAccounts"],
417
+ events: ["chainChanged", "accountsChanged"]
418
+ };
419
+ var POLKADOT_NAMESPACE = {
420
+ chains: ["polkadot:91b171bb158e2d3848fa23a9f1c25182"],
421
+ // Polkadot Mainnet
422
+ methods: ["polkadot_signTransaction", "polkadot_signMessage"],
423
+ events: ["accountsChanged"]
424
+ };
425
+ var NEAR_NAMESPACE = {
426
+ chains: ["near:mainnet"],
427
+ methods: ["near_signTransaction", "near_signMessage"],
428
+ events: ["accountsChanged"]
429
+ };
430
+ var EVM_CHAINS = {
431
+ // Ethereum
432
+ ETHEREUM_MAINNET: "eip155:1",
433
+ ETHEREUM_GOERLI: "eip155:5",
434
+ ETHEREUM_SEPOLIA: "eip155:11155111",
435
+ // Layer 2 (L2)
436
+ POLYGON: "eip155:137",
437
+ POLYGON_MUMBAI: "eip155:80001",
438
+ ARBITRUM: "eip155:42161",
439
+ ARBITRUM_GOERLI: "eip155:421613",
440
+ OPTIMISM: "eip155:10",
441
+ OPTIMISM_GOERLI: "eip155:420",
442
+ // other EVM chains
443
+ BSC: "eip155:56",
444
+ BSC_TESTNET: "eip155:97",
445
+ AVALANCHE: "eip155:43114",
446
+ AVALANCHE_FUJI: "eip155:43113",
447
+ FANTOM: "eip155:250",
448
+ CRONOS: "eip155:25",
449
+ GNOSIS: "eip155:100",
450
+ BASE: "eip155:8453",
451
+ ZKSYNC: "eip155:324",
452
+ LINEA: "eip155:59144",
453
+ SCROLL: "eip155:534352"
454
+ };
455
+ var SOLANA_CHAINS = {
456
+ MAINNET: "solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ",
457
+ DEVNET: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
458
+ TESTNET: "solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K"
459
+ };
460
+ var APTOS_CHAINS = {
461
+ MAINNET: "aptos:1",
462
+ TESTNET: "aptos:2",
463
+ DEVNET: "aptos:3"
464
+ };
465
+ function createMultiChainNamespaces(chains) {
466
+ const namespaces = {};
467
+ const evmChains = chains.filter((chain) => chain.startsWith("eip155:"));
468
+ if (evmChains.length > 0) {
469
+ namespaces.eip155 = {
470
+ ...EIP155_NAMESPACE,
471
+ chains: evmChains
472
+ };
473
+ }
474
+ const solanaChains = chains.filter((chain) => chain.startsWith("solana:"));
475
+ if (solanaChains.length > 0) {
476
+ namespaces.solana = {
477
+ ...SOLANA_NAMESPACE,
478
+ chains: solanaChains
479
+ };
480
+ }
481
+ const aptosChains = chains.filter((chain) => chain.startsWith("aptos:"));
482
+ if (aptosChains.length > 0) {
483
+ namespaces.aptos = {
484
+ ...APTOS_NAMESPACE,
485
+ chains: aptosChains
486
+ };
487
+ }
488
+ const cosmosChains = chains.filter((chain) => chain.startsWith("cosmos:"));
489
+ if (cosmosChains.length > 0) {
490
+ namespaces.cosmos = {
491
+ ...COSMOS_NAMESPACE,
492
+ chains: cosmosChains
493
+ };
494
+ }
495
+ return namespaces;
496
+ }
497
+
498
+ // src/siwe.ts
499
+ async function getChecksumAddress(address) {
500
+ try {
501
+ const ethers = await import('ethers');
502
+ return ethers.getAddress(address);
503
+ } catch {
504
+ return address;
505
+ }
506
+ }
507
+ async function createSiweMessage(config, address) {
508
+ const siweModule = await import('siwe');
509
+ const SiweMessage = siweModule.SiweMessage || siweModule.default?.SiweMessage;
510
+ const checksumAddress = await getChecksumAddress(address);
511
+ const siweMessage = new SiweMessage({
512
+ domain: config.domain,
513
+ address: checksumAddress,
514
+ statement: config.statement || "Sign in with Ethereum to the app.",
515
+ uri: config.uri,
516
+ version: config.version || "1",
517
+ chainId: config.chainId,
518
+ nonce: config.nonce || generateNonce(),
519
+ issuedAt: config.issuedAt || (/* @__PURE__ */ new Date()).toISOString(),
520
+ expirationTime: config.expirationTime,
521
+ notBefore: config.notBefore,
522
+ requestId: config.requestId,
523
+ resources: config.resources
524
+ });
525
+ return siweMessage.prepareMessage();
526
+ }
527
+ async function parseSiweMessage(message) {
528
+ const siweModule = await import('siwe');
529
+ const SiweMessage = siweModule.SiweMessage || siweModule.default?.SiweMessage;
530
+ return new SiweMessage(message);
531
+ }
532
+ async function verifySiweSignature(params) {
533
+ try {
534
+ const siweModule = await import('siwe');
535
+ const SiweMessage = siweModule.SiweMessage || siweModule.default?.SiweMessage;
536
+ const siweMessage = new SiweMessage(params.message);
537
+ const result = await siweMessage.verify(
538
+ {
539
+ signature: params.signature,
540
+ nonce: params.nonce,
541
+ domain: params.domain,
542
+ time: params.time
543
+ },
544
+ {
545
+ suppressExceptions: true
546
+ // Suppress exceptions to get error details
235
547
  }
236
- return connectionUri;
237
- } catch (err) {
238
- const error2 = err;
239
- setError(error2);
240
- options?.onError?.(error2);
241
- throw error2;
548
+ );
549
+ if (result.success) {
550
+ return {
551
+ success: true,
552
+ data: result.data
553
+ };
554
+ } else {
555
+ return {
556
+ success: false,
557
+ error: result.error?.type || "Verification failed"
558
+ };
242
559
  }
243
- }, [connect, generateQRCode, options]);
244
- const reset = useCallback(() => {
245
- setUri(null);
246
- setQrCode(null);
247
- setError(null);
248
- }, []);
560
+ } catch (error) {
561
+ return {
562
+ success: false,
563
+ error: error.type || error.message || "Unknown verification error"
564
+ };
565
+ }
566
+ }
567
+ function generateNonce(length = 16) {
568
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
569
+ let nonce = "";
570
+ const randomValues = new Uint8Array(length);
571
+ if (typeof window !== "undefined" && window.crypto) {
572
+ window.crypto.getRandomValues(randomValues);
573
+ } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
574
+ globalThis.crypto.getRandomValues(randomValues);
575
+ } else {
576
+ for (let i = 0; i < length; i++) {
577
+ randomValues[i] = Math.floor(Math.random() * 256);
578
+ }
579
+ }
580
+ for (let i = 0; i < length; i++) {
581
+ nonce += chars[randomValues[i] % chars.length];
582
+ }
583
+ return nonce;
584
+ }
585
+ function createSiweConfigFromSession(params) {
249
586
  return {
250
- connect: handleConnect,
251
- uri,
252
- qrCode,
253
- connecting,
254
- error,
255
- reset
587
+ domain: params.domain,
588
+ uri: params.uri,
589
+ chainId: params.chainId,
590
+ statement: params.statement || "Sign in with Ethereum to authenticate your wallet.",
591
+ version: "1",
592
+ nonce: generateNonce(),
593
+ issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
594
+ expirationTime: new Date(Date.now() + 5 * 60 * 1e3).toISOString(),
595
+ // 5 minutes
596
+ resources: params.resources
256
597
  };
257
598
  }
258
- function useSiwe(config) {
259
- const { client } = useWalletConnect();
260
- const [isAuthenticating, setIsAuthenticating] = useState(false);
261
- const [authResult, setAuthResult] = useState(null);
262
- const signIn = useCallback(
263
- async (sessionTopic) => {
264
- if (!client) {
265
- throw new Error("WalletConnect client not initialized");
266
- }
267
- const sessions = client.getActiveSessions();
268
- if (sessions.length === 0) {
269
- throw new Error("No active sessions. Connect wallet first.");
270
- }
271
- setIsAuthenticating(true);
272
- setAuthResult(null);
273
- try {
274
- const session = sessionTopic ? sessions.find((s) => s.topic === sessionTopic) : sessions[0];
275
- if (!session) {
276
- throw new Error("Session not found");
277
- }
278
- const accounts = Object.values(session.namespaces).flatMap((ns) => ns.accounts || []);
279
- const primaryAccount = accounts[0];
280
- if (!primaryAccount) {
281
- throw new Error("No accounts found in session");
282
- }
283
- const address = extractAddressFromAccount(primaryAccount);
284
- const chainIdStr = extractChainIdFromAccount(primaryAccount);
285
- const chainId = extractChainIdNumber(primaryAccount);
286
- const siweConfig = createSiweConfigFromSession({
287
- domain: config?.domain || window.location.host,
288
- uri: config?.uri || window.location.origin,
289
- chainId,
290
- statement: config?.statement,
291
- resources: config?.resources
292
- });
293
- const siweAuth = new SiweAuth(siweConfig);
294
- const message = await siweAuth.createMessage(address);
295
- if (!client.signClient) {
296
- throw new Error("SignClient not initialized");
297
- }
298
- const signature = await client.signClient.request({
299
- topic: session.topic,
300
- chainId: chainIdStr,
301
- request: {
302
- method: "personal_sign",
303
- params: [message, address]
304
- }
305
- });
306
- const verifyResult = await siweAuth.verify(message, signature);
307
- if (verifyResult.success) {
308
- setAuthResult({
309
- success: true,
310
- address,
311
- message,
312
- signature
313
- });
314
- return {
315
- success: true,
316
- address,
317
- message,
318
- signature,
319
- siweMessage: verifyResult.data
320
- };
321
- } else {
322
- throw new Error(verifyResult.error || "Signature verification failed");
323
- }
324
- } catch (error) {
325
- const errorMsg = error.message || "Authentication failed";
326
- setAuthResult({
327
- success: false,
328
- error: errorMsg
329
- });
330
- throw error;
331
- } finally {
332
- setIsAuthenticating(false);
599
+ var SiweAuth = class {
600
+ config;
601
+ constructor(config) {
602
+ this.config = {
603
+ ...config,
604
+ nonce: generateNonce(),
605
+ issuedAt: (/* @__PURE__ */ new Date()).toISOString()
606
+ };
607
+ }
608
+ /**
609
+ * Create the message to sign
610
+ */
611
+ async createMessage(address) {
612
+ return createSiweMessage(this.config, address);
613
+ }
614
+ /**
615
+ * Verify the signature
616
+ */
617
+ async verify(message, signature) {
618
+ return verifySiweSignature({
619
+ message,
620
+ signature,
621
+ nonce: this.config.nonce,
622
+ domain: this.config.domain
623
+ });
624
+ }
625
+ /**
626
+ * Get the nonce
627
+ */
628
+ getNonce() {
629
+ return this.config.nonce || "";
630
+ }
631
+ /**
632
+ * Refresh nonce (for new sign-in attempts)
633
+ */
634
+ refreshNonce() {
635
+ this.config.nonce = generateNonce();
636
+ this.config.issuedAt = (/* @__PURE__ */ new Date()).toISOString();
637
+ }
638
+ };
639
+
640
+ // src/wallets.ts
641
+ var EXPLORER_API_URL = "https://explorer-api.walletconnect.com";
642
+ async function getWalletConnectWallets(options = {}) {
643
+ const { projectId, entries = 100, page = 1, search, chains, include, exclude, recommendedIds } = options;
644
+ const params = new URLSearchParams();
645
+ if (projectId) {
646
+ params.append("projectId", projectId);
647
+ }
648
+ params.append("entries", entries.toString());
649
+ params.append("page", page.toString());
650
+ if (search) {
651
+ params.append("search", search);
652
+ }
653
+ if (chains) {
654
+ params.append("chains", chains);
655
+ }
656
+ if (include) {
657
+ params.append("include", include);
658
+ }
659
+ if (exclude) {
660
+ params.append("exclude", exclude);
661
+ }
662
+ if (recommendedIds) {
663
+ params.append("recommendedIds", recommendedIds);
664
+ }
665
+ const url = `${EXPLORER_API_URL}/v3/wallets?${params.toString()}`;
666
+ try {
667
+ const response = await fetch(url);
668
+ if (!response.ok) {
669
+ throw new Error(`Failed to fetch wallets: ${response.statusText}`);
670
+ }
671
+ const data = await response.json();
672
+ return data;
673
+ } catch (error) {
674
+ throw error;
675
+ }
676
+ }
677
+ async function getAllWallets(options = {}) {
678
+ const allWallets = [];
679
+ let page = 1;
680
+ let hasMore = true;
681
+ while (hasMore) {
682
+ const response = await getWalletConnectWallets({
683
+ ...options,
684
+ page,
685
+ entries: 100
686
+ });
687
+ allWallets.push(...response.data);
688
+ hasMore = response.data.length === 100;
689
+ page++;
690
+ }
691
+ return allWallets;
692
+ }
693
+ async function getWalletById(walletId, projectId) {
694
+ const params = new URLSearchParams();
695
+ if (projectId) {
696
+ params.append("projectId", projectId);
697
+ }
698
+ const url = `${EXPLORER_API_URL}/v3/wallets/${walletId}?${params.toString()}`;
699
+ try {
700
+ const response = await fetch(url);
701
+ if (!response.ok) {
702
+ if (response.status === 404) {
703
+ return null;
333
704
  }
334
- },
335
- [client, config]
705
+ throw new Error(`Failed to fetch wallet: ${response.statusText}`);
706
+ }
707
+ return await response.json();
708
+ } catch (error) {
709
+ return null;
710
+ }
711
+ }
712
+ async function searchWallets(query, options = {}) {
713
+ const response = await getWalletConnectWallets({
714
+ ...options,
715
+ search: query
716
+ });
717
+ return response.data;
718
+ }
719
+ async function getWalletsByChain(chainId, options = {}) {
720
+ const response = await getWalletConnectWallets({
721
+ ...options,
722
+ chains: chainId
723
+ });
724
+ return response.data;
725
+ }
726
+ async function getRecommendedWallets(walletIds, options = {}) {
727
+ const response = await getWalletConnectWallets({
728
+ ...options,
729
+ recommendedIds: walletIds.join(",")
730
+ });
731
+ return response.data;
732
+ }
733
+ async function getMobileWallets(options = {}) {
734
+ const response = await getWalletConnectWallets(options);
735
+ return response.data.filter((wallet) => wallet.mobile || wallet.app?.ios || wallet.app?.android);
736
+ }
737
+ async function getDesktopWallets(options = {}) {
738
+ const response = await getWalletConnectWallets(options);
739
+ return response.data.filter(
740
+ (wallet) => wallet.desktop || wallet.app?.mac || wallet.app?.windows || wallet.app?.linux
741
+ );
742
+ }
743
+ async function getBrowserWallets(options = {}) {
744
+ const response = await getWalletConnectWallets(options);
745
+ return response.data.filter(
746
+ (wallet) => wallet.app?.chrome || wallet.app?.firefox || wallet.app?.safari || wallet.app?.edge
336
747
  );
337
- const signOut = useCallback(() => {
338
- setAuthResult(null);
339
- }, []);
340
- return {
341
- signIn,
342
- signOut,
343
- isAuthenticating,
344
- authResult,
345
- isAuthenticated: authResult?.success || false
346
- };
347
748
  }
749
+ var POPULAR_WALLET_IDS = {
750
+ METAMASK: "c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96",
751
+ TRUST: "4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0",
752
+ RAINBOW: "1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369",
753
+ COINBASE: "fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa",
754
+ SAFE: "225affb176778569276e484e1b92637ad061b01e13a048b35a9d280c3b58970f",
755
+ ARGENT: "bc949c5d968ae81310268bf9193f9c9fb7bb4e1283e1284af8f2bd4992535fd6",
756
+ ZERION: "ecc4036f814562b41a5268adc86270fba1365471402006302e70169465b7ac18",
757
+ IMTOKEN: "ef333840daf915aafdc4a004525502d6d49d77bd9c65e0642dbaefb3c2893bef",
758
+ OKX: "971e689d0a5be527bac79629b4ee9b925e82208e5168b733496a09c0faed0709",
759
+ PHANTOM: "a797aa35c0fadbfc1a53e7f675162ed5226968b44a19ee3d24385c64d1d3c393",
760
+ TOKENPOCKET: "20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66",
761
+ BITGET: "7674bb4e353bf52886768a3ddc2a4562ce2f4191c80831291218ebd90f5f5e26"
762
+ };
763
+
764
+ // src/types.ts
765
+ var ChainType = /* @__PURE__ */ ((ChainType2) => {
766
+ ChainType2["EIP155"] = "eip155";
767
+ ChainType2["SOLANA"] = "solana";
768
+ ChainType2["APTOS"] = "aptos";
769
+ ChainType2["COSMOS"] = "cosmos";
770
+ ChainType2["POLKADOT"] = "polkadot";
771
+ ChainType2["NEAR"] = "near";
772
+ return ChainType2;
773
+ })(ChainType || {});
774
+ var AuthMethod = /* @__PURE__ */ ((AuthMethod2) => {
775
+ AuthMethod2["STANDARD"] = "standard";
776
+ AuthMethod2["SIWE"] = "siwe";
777
+ return AuthMethod2;
778
+ })(AuthMethod || {});
348
779
 
349
- export { WalletConnectProvider, useConnect, useQRCode, useSession, useSiwe, useWalletConnect };
780
+ export { APTOS_CHAINS, APTOS_NAMESPACE, AuthMethod, COSMOS_NAMESPACE, ChainType, EIP155_NAMESPACE, EVM_CHAINS, NEAR_NAMESPACE, POLKADOT_NAMESPACE, POPULAR_WALLET_IDS, SOLANA_CHAINS, SOLANA_NAMESPACE, SiweAuth, WalletConnectClient, copyToClipboard, createMultiChainNamespaces, createSiweConfigFromSession, createSiweMessage, extractAddressFromAccount, extractChainIdFromAccount, formatAddress, formatError, formatTimestamp, generateDeepLink, getAllWallets, getBrowserWallets, getDesktopWallets, getMobileWallets, getRecommendedWallets, getSessionTimeRemaining, getWalletById, getWalletConnectWallets, getWalletsByChain, isMobile, isSessionExpired, isValidChainId, isValidWalletConnectUri, parseChainId, parseSiweMessage, parseWalletConnectUri, searchWallets, verifySiweSignature };