thirdweb 5.105.19 → 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 (78) hide show
  1. package/dist/cjs/pay/buyWithCrypto/getQuote.js +8 -8
  2. package/dist/cjs/pay/buyWithCrypto/getQuote.js.map +1 -1
  3. package/dist/cjs/pay/buyWithCrypto/getTransfer.js +4 -4
  4. package/dist/cjs/pay/buyWithCrypto/getTransfer.js.map +1 -1
  5. package/dist/cjs/pay/buyWithFiat/getQuote.js +3 -3
  6. package/dist/cjs/pay/buyWithFiat/getQuote.js.map +1 -1
  7. package/dist/cjs/react/core/hooks/usePaymentMethods.js +2 -2
  8. package/dist/cjs/react/core/hooks/usePaymentMethods.js.map +1 -1
  9. package/dist/cjs/react/core/hooks/wallets/useConnect.js +10 -1
  10. package/dist/cjs/react/core/hooks/wallets/useConnect.js.map +1 -1
  11. package/dist/cjs/version.js +1 -1
  12. package/dist/cjs/wallets/create-wallet.js +62 -13
  13. package/dist/cjs/wallets/create-wallet.js.map +1 -1
  14. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js +3 -3
  15. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  16. package/dist/cjs/wallets/in-app/web/in-app.js +18 -0
  17. package/dist/cjs/wallets/in-app/web/in-app.js.map +1 -1
  18. package/dist/cjs/wallets/smart/index.js +2 -2
  19. package/dist/cjs/wallets/smart/index.js.map +1 -1
  20. package/dist/cjs/wallets/smart/lib/signing.js +26 -95
  21. package/dist/cjs/wallets/smart/lib/signing.js.map +1 -1
  22. package/dist/cjs/wallets/smart/smart-wallet.js +1 -1
  23. package/dist/cjs/wallets/smart/smart-wallet.js.map +1 -1
  24. package/dist/cjs/wallets/wallet-connect/qr-overlay.js +231 -0
  25. package/dist/cjs/wallets/wallet-connect/qr-overlay.js.map +1 -0
  26. package/dist/esm/pay/buyWithCrypto/getQuote.js +8 -8
  27. package/dist/esm/pay/buyWithCrypto/getQuote.js.map +1 -1
  28. package/dist/esm/pay/buyWithCrypto/getTransfer.js +4 -4
  29. package/dist/esm/pay/buyWithCrypto/getTransfer.js.map +1 -1
  30. package/dist/esm/pay/buyWithFiat/getQuote.js +3 -3
  31. package/dist/esm/pay/buyWithFiat/getQuote.js.map +1 -1
  32. package/dist/esm/react/core/hooks/usePaymentMethods.js +2 -2
  33. package/dist/esm/react/core/hooks/usePaymentMethods.js.map +1 -1
  34. package/dist/esm/react/core/hooks/wallets/useConnect.js +10 -1
  35. package/dist/esm/react/core/hooks/wallets/useConnect.js.map +1 -1
  36. package/dist/esm/version.js +1 -1
  37. package/dist/esm/wallets/create-wallet.js +62 -13
  38. package/dist/esm/wallets/create-wallet.js.map +1 -1
  39. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js +3 -3
  40. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  41. package/dist/esm/wallets/in-app/web/in-app.js +18 -0
  42. package/dist/esm/wallets/in-app/web/in-app.js.map +1 -1
  43. package/dist/esm/wallets/smart/index.js +2 -2
  44. package/dist/esm/wallets/smart/index.js.map +1 -1
  45. package/dist/esm/wallets/smart/lib/signing.js +27 -96
  46. package/dist/esm/wallets/smart/lib/signing.js.map +1 -1
  47. package/dist/esm/wallets/smart/smart-wallet.js +1 -1
  48. package/dist/esm/wallets/smart/smart-wallet.js.map +1 -1
  49. package/dist/esm/wallets/wallet-connect/qr-overlay.js +228 -0
  50. package/dist/esm/wallets/wallet-connect/qr-overlay.js.map +1 -0
  51. package/dist/types/react/core/hooks/wallets/useConnect.d.ts +1 -0
  52. package/dist/types/react/core/hooks/wallets/useConnect.d.ts.map +1 -1
  53. package/dist/types/version.d.ts +1 -1
  54. package/dist/types/wallets/create-wallet.d.ts.map +1 -1
  55. package/dist/types/wallets/in-app/web/in-app.d.ts +18 -0
  56. package/dist/types/wallets/in-app/web/in-app.d.ts.map +1 -1
  57. package/dist/types/wallets/smart/lib/signing.d.ts +2 -3
  58. package/dist/types/wallets/smart/lib/signing.d.ts.map +1 -1
  59. package/dist/types/wallets/wallet-connect/qr-overlay.d.ts +58 -0
  60. package/dist/types/wallets/wallet-connect/qr-overlay.d.ts.map +1 -0
  61. package/dist/types/wallets/wallet-connect/types.d.ts +13 -0
  62. package/dist/types/wallets/wallet-connect/types.d.ts.map +1 -1
  63. package/package.json +5 -3
  64. package/src/pay/buyWithCrypto/getQuote.ts +8 -8
  65. package/src/pay/buyWithCrypto/getTransfer.ts +4 -4
  66. package/src/pay/buyWithFiat/getQuote.ts +3 -3
  67. package/src/react/core/hooks/usePaymentMethods.ts +2 -2
  68. package/src/react/core/hooks/wallets/useConnect.ts +11 -1
  69. package/src/version.ts +1 -1
  70. package/src/wallets/create-wallet.ts +85 -24
  71. package/src/wallets/in-app/core/wallet/in-app-core.ts +4 -4
  72. package/src/wallets/in-app/web/in-app.ts +18 -0
  73. package/src/wallets/smart/index.ts +2 -2
  74. package/src/wallets/smart/lib/signing.ts +34 -121
  75. package/src/wallets/smart/smart-wallet-integration.test.ts +1 -76
  76. package/src/wallets/smart/smart-wallet.ts +1 -1
  77. package/src/wallets/wallet-connect/qr-overlay.ts +322 -0
  78. package/src/wallets/wallet-connect/types.ts +13 -0
@@ -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
+ }
@@ -157,6 +157,19 @@ export type WCConnectOptions = {
157
157
  * ```
158
158
  */
159
159
  onDisplayUri?: (_uri: string) => void;
160
+ /**
161
+ * Callback that gets called when the user cancels the connection process (e.g., closes the QR modal).
162
+ * This is only called for user-initiated cancellations, not for programmatic cleanup.
163
+ *
164
+ * ```tsx
165
+ * await wallet.connect({
166
+ * onCancel: () => {
167
+ * console.log("User cancelled wallet connection");
168
+ * }
169
+ * })
170
+ * ```
171
+ */
172
+ onCancel?: () => void;
160
173
  }
161
174
  >;
162
175
  };