thirdweb 5.105.20 → 5.105.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/cjs/react/core/hooks/wallets/useConnect.js +10 -1
  2. package/dist/cjs/react/core/hooks/wallets/useConnect.js.map +1 -1
  3. package/dist/cjs/version.js +1 -1
  4. package/dist/cjs/wallets/create-wallet.js +62 -13
  5. package/dist/cjs/wallets/create-wallet.js.map +1 -1
  6. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js +3 -3
  7. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  8. package/dist/cjs/wallets/in-app/web/in-app.js +18 -0
  9. package/dist/cjs/wallets/in-app/web/in-app.js.map +1 -1
  10. package/dist/cjs/wallets/smart/index.js +2 -2
  11. package/dist/cjs/wallets/smart/index.js.map +1 -1
  12. package/dist/cjs/wallets/smart/smart-wallet.js +1 -1
  13. package/dist/cjs/wallets/smart/smart-wallet.js.map +1 -1
  14. package/dist/cjs/wallets/wallet-connect/qr-overlay.js +231 -0
  15. package/dist/cjs/wallets/wallet-connect/qr-overlay.js.map +1 -0
  16. package/dist/esm/react/core/hooks/wallets/useConnect.js +10 -1
  17. package/dist/esm/react/core/hooks/wallets/useConnect.js.map +1 -1
  18. package/dist/esm/version.js +1 -1
  19. package/dist/esm/wallets/create-wallet.js +62 -13
  20. package/dist/esm/wallets/create-wallet.js.map +1 -1
  21. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js +3 -3
  22. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  23. package/dist/esm/wallets/in-app/web/in-app.js +18 -0
  24. package/dist/esm/wallets/in-app/web/in-app.js.map +1 -1
  25. package/dist/esm/wallets/smart/index.js +2 -2
  26. package/dist/esm/wallets/smart/index.js.map +1 -1
  27. package/dist/esm/wallets/smart/smart-wallet.js +1 -1
  28. package/dist/esm/wallets/smart/smart-wallet.js.map +1 -1
  29. package/dist/esm/wallets/wallet-connect/qr-overlay.js +228 -0
  30. package/dist/esm/wallets/wallet-connect/qr-overlay.js.map +1 -0
  31. package/dist/types/react/core/hooks/wallets/useConnect.d.ts +1 -0
  32. package/dist/types/react/core/hooks/wallets/useConnect.d.ts.map +1 -1
  33. package/dist/types/version.d.ts +1 -1
  34. package/dist/types/wallets/create-wallet.d.ts.map +1 -1
  35. package/dist/types/wallets/in-app/web/in-app.d.ts +18 -0
  36. package/dist/types/wallets/in-app/web/in-app.d.ts.map +1 -1
  37. package/dist/types/wallets/wallet-connect/qr-overlay.d.ts +58 -0
  38. package/dist/types/wallets/wallet-connect/qr-overlay.d.ts.map +1 -0
  39. package/dist/types/wallets/wallet-connect/types.d.ts +13 -0
  40. package/dist/types/wallets/wallet-connect/types.d.ts.map +1 -1
  41. package/package.json +3 -1
  42. package/src/react/core/hooks/wallets/useConnect.ts +11 -1
  43. package/src/version.ts +1 -1
  44. package/src/wallets/create-wallet.ts +85 -24
  45. package/src/wallets/in-app/core/wallet/in-app-core.ts +4 -4
  46. package/src/wallets/in-app/web/in-app.ts +18 -0
  47. package/src/wallets/smart/index.ts +2 -2
  48. package/src/wallets/smart/smart-wallet.ts +1 -1
  49. package/src/wallets/wallet-connect/qr-overlay.ts +322 -0
  50. package/src/wallets/wallet-connect/types.ts +13 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Vanilla JavaScript QR Code overlay utility for WalletConnect URIs
3
+ * Works in any browser context without requiring React or other frameworks
4
+ */
5
+ interface QROverlayOptions {
6
+ /**
7
+ * Custom styles to apply to the overlay
8
+ */
9
+ overlayStyles?: Partial<CSSStyleDeclaration>;
10
+ /**
11
+ * Custom styles to apply to the modal container
12
+ */
13
+ modalStyles?: Partial<CSSStyleDeclaration>;
14
+ /**
15
+ * QR code size in pixels
16
+ */
17
+ qrSize?: number;
18
+ /**
19
+ * Show close button
20
+ */
21
+ showCloseButton?: boolean;
22
+ /**
23
+ * Custom close button text
24
+ */
25
+ closeButtonText?: string;
26
+ /**
27
+ * Theme preference
28
+ */
29
+ theme?: "light" | "dark";
30
+ /**
31
+ * Custom container element to append the overlay to
32
+ */
33
+ container?: HTMLElement;
34
+ /**
35
+ * Callback called when user cancels the overlay (closes without connecting)
36
+ */
37
+ onCancel?: () => void;
38
+ }
39
+ export interface QROverlay {
40
+ /**
41
+ * Remove the overlay from the DOM
42
+ */
43
+ destroy: () => void;
44
+ /**
45
+ * Hide the overlay (without removing from DOM)
46
+ */
47
+ hide: () => void;
48
+ /**
49
+ * Show the overlay
50
+ */
51
+ show: () => void;
52
+ }
53
+ /**
54
+ * Creates a QR code overlay for the given WalletConnect URI
55
+ */
56
+ export declare function createQROverlay(uri: string, options?: QROverlayOptions): QROverlay;
57
+ export {};
58
+ //# sourceMappingURL=qr-overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr-overlay.d.ts","sourceRoot":"","sources":["../../../../src/wallets/wallet-connect/qr-overlay.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,UAAU,gBAAgB;IACxB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC7C;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3C;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,gBAAqB,GAC7B,SAAS,CA0OX"}
@@ -151,6 +151,19 @@ export type WCConnectOptions = {
151
151
  * ```
152
152
  */
153
153
  onDisplayUri?: (_uri: string) => void;
154
+ /**
155
+ * Callback that gets called when the user cancels the connection process (e.g., closes the QR modal).
156
+ * This is only called for user-initiated cancellations, not for programmatic cleanup.
157
+ *
158
+ * ```tsx
159
+ * await wallet.connect({
160
+ * onCancel: () => {
161
+ * console.log("User cancelled wallet connection");
162
+ * }
163
+ * })
164
+ * ```
165
+ */
166
+ onCancel?: () => void;
154
167
  }>;
155
168
  };
156
169
  export type WCAutoConnectOptions = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/wallets/wallet-connect/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,KAAK,+BAA+B,GAAG;IACrC,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAC3C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,4BAA4B,CAAC,EAAE,MAAM,EAAE,CAAC;IACxC,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd;;;;;;;;;;;;;;OAcG;IACH,MAAM,EAAE,cAAc,CAAC;IAEvB,aAAa,CAAC,EAAE,QAAQ,CACtB,mBAAmB,GAAG;QACpB;;;;;;;;;;;;;;;;;;;;;;;;;WAyBG;QACH,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC;QACzB;;;;;;;;;;;;;;;;;WAiBG;QACH,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB;;WAEG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB;;;WAGG;QACH,cAAc,CAAC,EAAE,+BAA+B,CAAC;QACjD;;;;;;;;;;;;;WAaG;QACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;KACvC,CACF,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;;;;;;;;;;OAcG;IACH,MAAM,EAAE,cAAc,CAAC;IAEvB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IAExC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/wallets/wallet-connect/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,KAAK,+BAA+B,GAAG;IACrC,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAC3C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,4BAA4B,CAAC,EAAE,MAAM,EAAE,CAAC;IACxC,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd;;;;;;;;;;;;;;OAcG;IACH,MAAM,EAAE,cAAc,CAAC;IAEvB,aAAa,CAAC,EAAE,QAAQ,CACtB,mBAAmB,GAAG;QACpB;;;;;;;;;;;;;;;;;;;;;;;;;WAyBG;QACH,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC;QACzB;;;;;;;;;;;;;;;;;WAiBG;QACH,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB;;WAEG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB;;;WAGG;QACH,cAAc,CAAC,EAAE,+BAA+B,CAAC;QACjD;;;;;;;;;;;;;WAaG;QACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QACtC;;;;;;;;;;;WAWG;QACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;KACvB,CACF,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;;;;;;;;;;OAcG;IACH,MAAM,EAAE,cAAc,CAAC;IAEvB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IAExC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC"}
package/package.json CHANGED
@@ -34,6 +34,7 @@
34
34
  "ora": "8.2.0",
35
35
  "ox": "0.7.0",
36
36
  "prompts": "2.4.2",
37
+ "qrcode": "1.5.3",
37
38
  "toml": "3.0.0",
38
39
  "uqr": "0.1.2",
39
40
  "viem": "2.28.1",
@@ -61,6 +62,7 @@
61
62
  "@testing-library/user-event": "^14.6.1",
62
63
  "@types/cross-spawn": "^6.0.6",
63
64
  "@types/prompts": "2.4.9",
65
+ "@types/qrcode": "1.5.5",
64
66
  "@types/react": "19.1.8",
65
67
  "@viem/anvil": "0.0.10",
66
68
  "@vitejs/plugin-react": "^4.6.0",
@@ -375,7 +377,7 @@
375
377
  }
376
378
  },
377
379
  "typings": "./dist/types/exports/thirdweb.d.ts",
378
- "version": "5.105.20",
380
+ "version": "5.105.21",
379
381
  "scripts": {
380
382
  "bench": "vitest -c ./test/vitest.config.ts bench",
381
383
  "bench:compare": "bun run ./benchmarks/run.ts",
@@ -79,5 +79,15 @@ export function useConnect(options?: ConnectManagerOptions) {
79
79
  [connect, options, setConnectionStatus],
80
80
  );
81
81
 
82
- return { connect: handleConnection, error, isConnecting } as const;
82
+ const cancelConnection = useCallback(() => {
83
+ setIsConnecting(false);
84
+ setConnectionStatus("disconnected");
85
+ }, [setConnectionStatus]);
86
+
87
+ return {
88
+ connect: handleConnection,
89
+ error,
90
+ isConnecting,
91
+ cancelConnection,
92
+ } as const;
83
93
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "5.105.20";
1
+ export const version = "5.105.21";
@@ -17,6 +17,7 @@ import { inAppWallet } from "./in-app/web/in-app.js";
17
17
  import { getInjectedProvider } from "./injected/index.js";
18
18
  import type { Account, Wallet } from "./interfaces/wallet.js";
19
19
  import { smartWallet } from "./smart/smart-wallet.js";
20
+ import type { QROverlay } from "./wallet-connect/qr-overlay.js";
20
21
  import type { WCConnectOptions } from "./wallet-connect/types.js";
21
22
  import { createWalletEmitter } from "./wallet-emitter.js";
22
23
  import type {
@@ -299,30 +300,90 @@ export function createWallet<const ID extends WalletId>(
299
300
  "./wallet-connect/controller.js"
300
301
  );
301
302
 
302
- const [
303
- connectedAccount,
304
- connectedChain,
305
- doDisconnect,
306
- doSwitchChain,
307
- ] = await connectWC(
308
- wcOptions,
309
- emitter,
310
- wallet.id as WCSupportedWalletIds | "walletConnect",
311
- webLocalStorage,
312
- sessionHandler,
313
- );
314
- // set the states
315
- account = connectedAccount;
316
- chain = connectedChain;
317
- handleDisconnect = doDisconnect;
318
- handleSwitchChain = doSwitchChain;
319
- trackConnect({
320
- chainId: chain.id,
321
- client: wcOptions.client,
322
- walletAddress: account.address,
323
- walletType: id,
324
- });
325
- return account;
303
+ let qrOverlay: QROverlay | undefined;
304
+
305
+ try {
306
+ const [
307
+ connectedAccount,
308
+ connectedChain,
309
+ doDisconnect,
310
+ doSwitchChain,
311
+ ] = await connectWC(
312
+ {
313
+ ...wcOptions,
314
+ walletConnect: {
315
+ ...wcOptions.walletConnect,
316
+ onDisplayUri: wcOptions.walletConnect?.showQrModal
317
+ ? async (uri) => {
318
+ // Check if we're in a browser environment
319
+ if (
320
+ typeof window !== "undefined" &&
321
+ typeof document !== "undefined"
322
+ ) {
323
+ try {
324
+ const { createQROverlay } = await import(
325
+ "./wallet-connect/qr-overlay.js"
326
+ );
327
+
328
+ // Clean up any existing overlay
329
+ if (qrOverlay) {
330
+ qrOverlay.destroy();
331
+ }
332
+
333
+ // Create new QR overlay
334
+ qrOverlay = createQROverlay(uri, {
335
+ theme:
336
+ wcOptions.walletConnect?.qrModalOptions
337
+ ?.themeMode ?? "dark",
338
+ qrSize: 280,
339
+ showCloseButton: true,
340
+ onCancel: () => {
341
+ wcOptions.walletConnect?.onCancel?.();
342
+ },
343
+ });
344
+ } catch (error) {
345
+ console.error(
346
+ "Failed to create QR overlay:",
347
+ error,
348
+ );
349
+ }
350
+ }
351
+ }
352
+ : undefined,
353
+ },
354
+ },
355
+ emitter,
356
+ wallet.id as WCSupportedWalletIds | "walletConnect",
357
+ webLocalStorage,
358
+ sessionHandler,
359
+ );
360
+
361
+ // Clean up QR overlay on successful connection
362
+ if (qrOverlay) {
363
+ qrOverlay.destroy();
364
+ qrOverlay = undefined;
365
+ }
366
+
367
+ // set the states
368
+ account = connectedAccount;
369
+ chain = connectedChain;
370
+ handleDisconnect = doDisconnect;
371
+ handleSwitchChain = doSwitchChain;
372
+ trackConnect({
373
+ chainId: chain.id,
374
+ client: wcOptions.client,
375
+ walletAddress: account.address,
376
+ walletType: id,
377
+ });
378
+ return account;
379
+ } catch (error) {
380
+ // Clean up QR overlay on connection error
381
+ if (qrOverlay) {
382
+ qrOverlay.destroy();
383
+ qrOverlay = undefined;
384
+ }
385
+ throw error;
386
+ }
326
387
  }
327
388
 
328
389
  if (id === "walletConnect") {
@@ -57,7 +57,7 @@ export function createInAppWallet(args: {
57
57
  let client: ThirdwebClient | undefined;
58
58
  let authToken: string | null = null;
59
59
 
60
- const resolveSmartAccountOptionsFromEcosystem = async (options: {
60
+ const resolveSmartAccountOptionsFromEcosystem = async (options?: {
61
61
  chain?: Chain;
62
62
  }) => {
63
63
  if (ecosystem) {
@@ -78,7 +78,7 @@ export function createInAppWallet(args: {
78
78
  // default to 4337
79
79
  const { defaultChainId } = ecosystemOptions.smartAccountOptions;
80
80
  const preferredChain =
81
- options.chain ??
81
+ options?.chain ??
82
82
  (defaultChainId ? getCachedChain(defaultChainId) : undefined);
83
83
  if (!preferredChain) {
84
84
  throw new Error(
@@ -108,7 +108,7 @@ export function createInAppWallet(args: {
108
108
  ecosystem,
109
109
  );
110
110
 
111
- await resolveSmartAccountOptionsFromEcosystem(options);
111
+ await resolveSmartAccountOptionsFromEcosystem();
112
112
 
113
113
  const {
114
114
  account: connectedAccount,
@@ -145,7 +145,7 @@ export function createInAppWallet(args: {
145
145
  ecosystem,
146
146
  );
147
147
 
148
- await resolveSmartAccountOptionsFromEcosystem(options);
148
+ await resolveSmartAccountOptionsFromEcosystem();
149
149
 
150
150
  const {
151
151
  account: connectedAccount,
@@ -299,6 +299,24 @@ import type {
299
299
  * });
300
300
  * ```
301
301
  *
302
+ * ### Get the auth token for the wallet
303
+ *
304
+ * You can get the auth token for the wallet by calling `wallet.getAuthToken()`.
305
+ *
306
+ * ```ts
307
+ * import { inAppWallet } from "thirdweb/wallets";
308
+ *
309
+ * const wallet = inAppWallet();
310
+ *
311
+ * await wallet.connect({
312
+ * client,
313
+ * strategy: "google",
314
+ * });
315
+ *
316
+ * const authToken = await wallet.getAuthToken(); // this will return a JWT token that can be used to authenticate the user in the backend
317
+ * console.log(authToken);
318
+ * ```
319
+ *
302
320
  * @returns The created in-app wallet.
303
321
  * @wallet
304
322
  */
@@ -80,7 +80,7 @@ export async function connectSmartAccount(
80
80
  connectionOptions: SmartWalletConnectionOptions,
81
81
  creationOptions: SmartWalletOptions,
82
82
  ): Promise<[Account, Chain]> {
83
- const { personalAccount, client, chain: connectChain } = connectionOptions;
83
+ const { personalAccount, client } = connectionOptions;
84
84
 
85
85
  if (!personalAccount) {
86
86
  throw new Error(
@@ -89,7 +89,7 @@ export async function connectSmartAccount(
89
89
  }
90
90
 
91
91
  const options = creationOptions;
92
- const chain = connectChain ?? options.chain;
92
+ const chain = creationOptions.chain;
93
93
  const sponsorGas =
94
94
  "gasless" in options ? options.gasless : options.sponsorGas;
95
95
  if (await isZkSyncChain(chain)) {
@@ -229,7 +229,7 @@ export function smartWallet(
229
229
  const { connectSmartAccount } = await import("./index.js");
230
230
  const [connectedAccount, connectedChain] = await connectSmartAccount(
231
231
  { ...lastConnectOptions, chain: newChain },
232
- createOptions,
232
+ { ...createOptions, chain: newChain },
233
233
  );
234
234
  // set the states
235
235
  account = connectedAccount;
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Vanilla JavaScript QR Code overlay utility for WalletConnect URIs
3
+ * Works in any browser context without requiring React or other frameworks
4
+ */
5
+
6
+ interface QROverlayOptions {
7
+ /**
8
+ * Custom styles to apply to the overlay
9
+ */
10
+ overlayStyles?: Partial<CSSStyleDeclaration>;
11
+ /**
12
+ * Custom styles to apply to the modal container
13
+ */
14
+ modalStyles?: Partial<CSSStyleDeclaration>;
15
+ /**
16
+ * QR code size in pixels
17
+ */
18
+ qrSize?: number;
19
+ /**
20
+ * Show close button
21
+ */
22
+ showCloseButton?: boolean;
23
+ /**
24
+ * Custom close button text
25
+ */
26
+ closeButtonText?: string;
27
+ /**
28
+ * Theme preference
29
+ */
30
+ theme?: "light" | "dark";
31
+ /**
32
+ * Custom container element to append the overlay to
33
+ */
34
+ container?: HTMLElement;
35
+ /**
36
+ * Callback called when user cancels the overlay (closes without connecting)
37
+ */
38
+ onCancel?: () => void;
39
+ }
40
+
41
+ export interface QROverlay {
42
+ /**
43
+ * Remove the overlay from the DOM
44
+ */
45
+ destroy: () => void;
46
+ /**
47
+ * Hide the overlay (without removing from DOM)
48
+ */
49
+ hide: () => void;
50
+ /**
51
+ * Show the overlay
52
+ */
53
+ show: () => void;
54
+ }
55
+
56
+ /**
57
+ * Creates a QR code overlay for the given WalletConnect URI
58
+ */
59
+ export function createQROverlay(
60
+ uri: string,
61
+ options: QROverlayOptions = {},
62
+ ): QROverlay {
63
+ const {
64
+ qrSize = 280,
65
+ showCloseButton = true,
66
+ closeButtonText = "×",
67
+ theme = "light",
68
+ container = document.body,
69
+ onCancel,
70
+ } = options;
71
+
72
+ // Create overlay backdrop
73
+ const overlay = document.createElement("div");
74
+ overlay.style.cssText = `
75
+ position: fixed;
76
+ inset: 0;
77
+ background-color: ${theme === "dark" ? "rgba(0, 0, 0, 0.8)" : "rgba(0, 0, 0, 0.5)"};
78
+ backdrop-filter: blur(10px);
79
+ z-index: 9999;
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ animation: fadeIn 300ms ease-out;
84
+ `;
85
+
86
+ // Apply custom overlay styles
87
+ if (options.overlayStyles) {
88
+ Object.assign(overlay.style, options.overlayStyles);
89
+ }
90
+
91
+ // Create modal container
92
+ const modal = document.createElement("div");
93
+ modal.style.cssText = `
94
+ background: ${theme === "dark" ? "#1f1f1f" : "#ffffff"};
95
+ border-radius: 16px;
96
+ padding: 24px;
97
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
98
+ max-width: 90vw;
99
+ max-height: 90vh;
100
+ position: relative;
101
+ animation: scaleIn 300ms ease-out;
102
+ `;
103
+
104
+ // Apply custom modal styles
105
+ if (options.modalStyles) {
106
+ Object.assign(modal.style, options.modalStyles);
107
+ }
108
+
109
+ // Create close button
110
+ if (showCloseButton) {
111
+ const closeButton = document.createElement("button");
112
+ closeButton.textContent = closeButtonText;
113
+ closeButton.style.cssText = `
114
+ position: absolute;
115
+ top: 16px;
116
+ right: 16px;
117
+ background: none;
118
+ border: none;
119
+ font-size: 24px;
120
+ cursor: pointer;
121
+ color: ${theme === "dark" ? "#ffffff" : "#000000"};
122
+ width: 32px;
123
+ height: 32px;
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ border-radius: 8px;
128
+ transition: background-color 0.2s;
129
+ `;
130
+
131
+ closeButton.addEventListener("mouseenter", () => {
132
+ closeButton.style.backgroundColor =
133
+ theme === "dark" ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.1)";
134
+ });
135
+
136
+ closeButton.addEventListener("mouseleave", () => {
137
+ closeButton.style.backgroundColor = "transparent";
138
+ });
139
+
140
+ closeButton.addEventListener("click", () => {
141
+ destroyOverlay(true);
142
+ });
143
+
144
+ modal.appendChild(closeButton);
145
+ }
146
+
147
+ // Create QR code container
148
+ const qrContainer = document.createElement("div");
149
+ qrContainer.style.cssText = `
150
+ display: flex;
151
+ flex-direction: column;
152
+ align-items: center;
153
+ gap: 16px;
154
+ `;
155
+
156
+ // Create title
157
+ const title = document.createElement("h3");
158
+ title.textContent = "Scan to Connect";
159
+ title.style.cssText = `
160
+ margin: 0;
161
+ font-size: 18px;
162
+ font-weight: 600;
163
+ color: ${theme === "dark" ? "#ffffff" : "#000000"};
164
+ text-align: center;
165
+ `;
166
+
167
+ // Create QR code canvas
168
+ const qrCanvas = document.createElement("canvas");
169
+ qrCanvas.width = qrSize;
170
+ qrCanvas.height = qrSize;
171
+ qrCanvas.style.cssText = `
172
+ border: 1px solid ${theme === "dark" ? "#333333" : "#e5e5e5"};
173
+ border-radius: 12px;
174
+ `;
175
+
176
+ // Generate QR code
177
+ generateQRCode(uri, qrCanvas, qrSize).catch(console.error);
178
+
179
+ // Create copy button for the URI
180
+ const copyButton = document.createElement("button");
181
+ copyButton.textContent = "Copy URI";
182
+ copyButton.style.cssText = `
183
+ background: ${theme === "dark" ? "#333333" : "#f5f5f5"};
184
+ border: 1px solid ${theme === "dark" ? "#444444" : "#e5e5e5"};
185
+ color: ${theme === "dark" ? "#ffffff" : "#000000"};
186
+ padding: 8px 16px;
187
+ border-radius: 8px;
188
+ cursor: pointer;
189
+ font-size: 14px;
190
+ transition: background-color 0.2s;
191
+ `;
192
+
193
+ copyButton.addEventListener("click", async () => {
194
+ try {
195
+ await navigator.clipboard.writeText(uri);
196
+ const originalText = copyButton.textContent;
197
+ copyButton.textContent = "Copied!";
198
+ setTimeout(() => {
199
+ copyButton.textContent = originalText;
200
+ }, 2000);
201
+ } catch (err) {
202
+ console.error("Failed to copy URI:", err);
203
+ }
204
+ });
205
+
206
+ // Assemble the modal
207
+ qrContainer.appendChild(title);
208
+ qrContainer.appendChild(qrCanvas);
209
+ qrContainer.appendChild(copyButton);
210
+ modal.appendChild(qrContainer);
211
+ overlay.appendChild(modal);
212
+
213
+ // Add CSS animations
214
+ const style = document.createElement("style");
215
+ style.textContent = `
216
+ @keyframes fadeIn {
217
+ from { opacity: 0; }
218
+ to { opacity: 1; }
219
+ }
220
+ @keyframes fadeOut {
221
+ from { opacity: 1; }
222
+ to { opacity: 0; }
223
+ }
224
+ @keyframes scaleIn {
225
+ from { transform: scale(0.9); opacity: 0; }
226
+ to { transform: scale(1); opacity: 1; }
227
+ }
228
+ @keyframes scaleOut {
229
+ from { transform: scale(1); opacity: 1; }
230
+ to { transform: scale(0.9); opacity: 0; }
231
+ }
232
+ `;
233
+ document.head.appendChild(style);
234
+
235
+ // Event handlers
236
+ const handleEscapeKey = (event: KeyboardEvent) => {
237
+ if (event.key === "Escape") {
238
+ destroyOverlay(true);
239
+ }
240
+ };
241
+
242
+ const handleOverlayClick = (event: MouseEvent) => {
243
+ if (event.target === overlay) {
244
+ destroyOverlay(true);
245
+ }
246
+ };
247
+
248
+ // Add event listeners
249
+ document.addEventListener("keydown", handleEscapeKey);
250
+ overlay.addEventListener("click", handleOverlayClick);
251
+
252
+ // Append to container
253
+ container.appendChild(overlay);
254
+
255
+ function destroyOverlay(userInitiated = false) {
256
+ document.removeEventListener("keydown", handleEscapeKey);
257
+ overlay.removeEventListener("click", handleOverlayClick);
258
+
259
+ // Call onCancel callback only if user initiated the close action
260
+ if (userInitiated && onCancel) {
261
+ onCancel();
262
+ }
263
+
264
+ // Animate both overlay and modal out
265
+ overlay.style.animation = "fadeOut 200ms ease-in";
266
+ modal.style.animation = "scaleOut 200ms ease-in";
267
+
268
+ const cleanup = () => {
269
+ if (overlay.parentNode) {
270
+ overlay.parentNode.removeChild(overlay);
271
+ }
272
+ if (style.parentNode) {
273
+ style.parentNode.removeChild(style);
274
+ }
275
+ };
276
+
277
+ overlay.addEventListener("animationend", cleanup, { once: true });
278
+
279
+ // Fallback cleanup in case animation doesn't fire
280
+ setTimeout(cleanup, 250);
281
+ }
282
+
283
+ function hideOverlay() {
284
+ overlay.style.display = "none";
285
+ }
286
+
287
+ function showOverlay() {
288
+ overlay.style.display = "flex";
289
+ }
290
+
291
+ return {
292
+ destroy: () => destroyOverlay(false), // Programmatic cleanup, don't call onCancel
293
+ hide: hideOverlay,
294
+ show: showOverlay,
295
+ };
296
+ }
297
+
298
+ /**
299
+ * QR code generator that tries to use a real QR library if available,
300
+ * otherwise falls back to a placeholder
301
+ */
302
+ async function generateQRCode(
303
+ text: string,
304
+ canvas: HTMLCanvasElement,
305
+ size: number,
306
+ ) {
307
+ const ctx = canvas.getContext("2d");
308
+ if (!ctx) return;
309
+
310
+ // Try to dynamically import a QR code library if available
311
+ // This allows the overlay to work with or without a QR code dependency
312
+ const { toCanvas } = await import("qrcode");
313
+ await toCanvas(canvas, text, {
314
+ width: size,
315
+ margin: 2,
316
+ color: {
317
+ dark: "#000000",
318
+ light: "#ffffff",
319
+ },
320
+ });
321
+ return;
322
+ }