thirdweb 5.86.1 → 5.86.2

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 (65) hide show
  1. package/dist/cjs/auth/verify-hash.js +24 -0
  2. package/dist/cjs/auth/verify-hash.js.map +1 -1
  3. package/dist/cjs/gas/fee-data.js +1 -0
  4. package/dist/cjs/gas/fee-data.js.map +1 -1
  5. package/dist/cjs/react/web/ui/prebuilt/Wallet/provider.js +0 -1
  6. package/dist/cjs/react/web/ui/prebuilt/Wallet/provider.js.map +1 -1
  7. package/dist/cjs/version.js +1 -1
  8. package/dist/cjs/wallets/in-app/core/authentication/backend.js +2 -1
  9. package/dist/cjs/wallets/in-app/core/authentication/backend.js.map +1 -1
  10. package/dist/cjs/wallets/in-app/web/lib/auth/iframe-auth.js +4 -7
  11. package/dist/cjs/wallets/in-app/web/lib/auth/iframe-auth.js.map +1 -1
  12. package/dist/cjs/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.js +14 -3
  13. package/dist/cjs/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.js.map +1 -1
  14. package/dist/cjs/wallets/in-app/web/utils/iFrameCommunication/InAppWalletIframeCommunicator.js +1 -1
  15. package/dist/cjs/wallets/in-app/web/utils/iFrameCommunication/InAppWalletIframeCommunicator.js.map +1 -1
  16. package/dist/cjs/wallets/smart/index.js +9 -0
  17. package/dist/cjs/wallets/smart/index.js.map +1 -1
  18. package/dist/cjs/wallets/smart/lib/signing.js +1 -1
  19. package/dist/cjs/wallets/wallet-connect/controller.js +4 -2
  20. package/dist/cjs/wallets/wallet-connect/controller.js.map +1 -1
  21. package/dist/esm/auth/verify-hash.js +24 -0
  22. package/dist/esm/auth/verify-hash.js.map +1 -1
  23. package/dist/esm/gas/fee-data.js +1 -0
  24. package/dist/esm/gas/fee-data.js.map +1 -1
  25. package/dist/esm/react/web/ui/prebuilt/Wallet/provider.js +0 -1
  26. package/dist/esm/react/web/ui/prebuilt/Wallet/provider.js.map +1 -1
  27. package/dist/esm/version.js +1 -1
  28. package/dist/esm/wallets/in-app/core/authentication/backend.js +2 -1
  29. package/dist/esm/wallets/in-app/core/authentication/backend.js.map +1 -1
  30. package/dist/esm/wallets/in-app/web/lib/auth/iframe-auth.js +4 -7
  31. package/dist/esm/wallets/in-app/web/lib/auth/iframe-auth.js.map +1 -1
  32. package/dist/esm/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.js +14 -3
  33. package/dist/esm/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.js.map +1 -1
  34. package/dist/esm/wallets/in-app/web/utils/iFrameCommunication/InAppWalletIframeCommunicator.js +1 -1
  35. package/dist/esm/wallets/in-app/web/utils/iFrameCommunication/InAppWalletIframeCommunicator.js.map +1 -1
  36. package/dist/esm/wallets/smart/index.js +9 -0
  37. package/dist/esm/wallets/smart/index.js.map +1 -1
  38. package/dist/esm/wallets/smart/lib/signing.js +1 -1
  39. package/dist/esm/wallets/wallet-connect/controller.js +4 -2
  40. package/dist/esm/wallets/wallet-connect/controller.js.map +1 -1
  41. package/dist/types/auth/verify-hash.d.ts.map +1 -1
  42. package/dist/types/gas/fee-data.d.ts.map +1 -1
  43. package/dist/types/react/web/ui/prebuilt/Wallet/provider.d.ts +0 -1
  44. package/dist/types/react/web/ui/prebuilt/Wallet/provider.d.ts.map +1 -1
  45. package/dist/types/version.d.ts +1 -1
  46. package/dist/types/wallets/in-app/core/authentication/backend.d.ts.map +1 -1
  47. package/dist/types/wallets/in-app/web/lib/auth/iframe-auth.d.ts.map +1 -1
  48. package/dist/types/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.d.ts +1 -1
  49. package/dist/types/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.d.ts.map +1 -1
  50. package/dist/types/wallets/smart/index.d.ts.map +1 -1
  51. package/dist/types/wallets/smart/lib/signing.d.ts +1 -1
  52. package/dist/types/wallets/wallet-connect/controller.d.ts.map +1 -1
  53. package/package.json +2 -2
  54. package/src/auth/verify-hash.ts +29 -0
  55. package/src/gas/fee-data.ts +1 -0
  56. package/src/react/web/ui/prebuilt/Wallet/provider.tsx +0 -1
  57. package/src/version.ts +1 -1
  58. package/src/wallets/in-app/core/authentication/backend.ts +3 -1
  59. package/src/wallets/in-app/web/lib/auth/iframe-auth.ts +4 -8
  60. package/src/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.test.tsx +102 -0
  61. package/src/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.ts +17 -4
  62. package/src/wallets/in-app/web/utils/iFrameCommunication/InAppWalletIframeCommunicator.ts +1 -1
  63. package/src/wallets/smart/index.ts +10 -0
  64. package/src/wallets/smart/lib/signing.ts +1 -1
  65. package/src/wallets/wallet-connect/controller.ts +4 -2
@@ -0,0 +1,102 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { IframeCommunicator } from "./IframeCommunicator.js";
3
+
4
+ describe("IframeCommunicator", () => {
5
+ // biome-ignore lint/suspicious/noExplicitAny: mock
6
+ let mockLocalStorage: any;
7
+ let mockContainer: HTMLElement;
8
+ let mockIframe: HTMLIFrameElement;
9
+
10
+ beforeEach(() => {
11
+ // Mock localStorage
12
+ vi.restoreAllMocks();
13
+
14
+ mockLocalStorage = {
15
+ getAuthCookie: vi.fn().mockResolvedValue("mockAuthCookie"),
16
+ getDeviceShare: vi.fn().mockResolvedValue("mockDeviceShare"),
17
+ getWalletUserId: vi.fn().mockResolvedValue("mockWalletUserId"),
18
+ };
19
+ // Mock DOM elements
20
+ mockContainer = document.createElement("div");
21
+ mockIframe = document.createElement("iframe");
22
+ vi.spyOn(document, "createElement").mockReturnValue(mockIframe);
23
+ vi.spyOn(document, "getElementById").mockReturnValue(null);
24
+ });
25
+
26
+ it("should create an iframe with correct properties", () => {
27
+ new IframeCommunicator({
28
+ link: "https://example.com",
29
+ baseUrl: "https://example.com",
30
+ iframeId: "test-iframe",
31
+ container: mockContainer,
32
+ localStorage: mockLocalStorage,
33
+ clientId: "test-client",
34
+ });
35
+
36
+ expect(document.createElement).toHaveBeenCalledWith("iframe");
37
+ expect(mockIframe.id).toBe("test-iframe");
38
+ expect(mockIframe.src).toBe("https://example.com/");
39
+ expect(mockIframe.style.display).toBe("none");
40
+ });
41
+
42
+ it("should initialize with correct variables", async () => {
43
+ const communicator = new IframeCommunicator({
44
+ link: "https://example.com",
45
+ baseUrl: "https://example.com",
46
+ iframeId: "test-iframe",
47
+ container: mockContainer,
48
+ localStorage: mockLocalStorage,
49
+ clientId: "test-client",
50
+ });
51
+
52
+ // biome-ignore lint/complexity/useLiteralKeys: accessing protected method
53
+ const vars = await communicator["onIframeLoadedInitVariables"]();
54
+
55
+ expect(vars).toEqual({
56
+ authCookie: "mockAuthCookie",
57
+ deviceShareStored: "mockDeviceShare",
58
+ walletUserId: "mockWalletUserId",
59
+ clientId: "test-client",
60
+ partnerId: undefined,
61
+ ecosystemId: undefined,
62
+ });
63
+ });
64
+
65
+ it("should throw error when calling methods without iframe", async () => {
66
+ const temp = global.document;
67
+ // @ts-expect-error - Testing undefined document scenario
68
+ global.document = undefined;
69
+
70
+ const communicator = new IframeCommunicator({
71
+ link: "https://example.com",
72
+ baseUrl: "https://example.com",
73
+ iframeId: "test-iframe",
74
+ localStorage: mockLocalStorage,
75
+ clientId: "test-client",
76
+ });
77
+
78
+ await expect(
79
+ communicator.call({
80
+ procedureName: "test",
81
+ params: {},
82
+ }),
83
+ ).rejects.toThrow("Iframe not found");
84
+ global.document = temp;
85
+ });
86
+
87
+ it("should cleanup on destroy", () => {
88
+ const communicator = new IframeCommunicator({
89
+ link: "https://example.com",
90
+ baseUrl: "https://example.com",
91
+ iframeId: "test-iframe",
92
+ container: mockContainer,
93
+ localStorage: mockLocalStorage,
94
+ clientId: "test-client",
95
+ });
96
+
97
+ communicator.destroy();
98
+
99
+ // biome-ignore lint/complexity/useLiteralKeys: accessing protected field
100
+ expect(communicator["iframe"]).toBeDefined();
101
+ });
102
+ });
@@ -35,7 +35,7 @@ const isIframeLoaded = new Map<string, boolean>();
35
35
  */
36
36
  // biome-ignore lint/suspicious/noExplicitAny: TODO: fix later
37
37
  export class IframeCommunicator<T extends { [key: string]: any }> {
38
- private iframe: HTMLIFrameElement;
38
+ private iframe?: HTMLIFrameElement;
39
39
  private POLLING_INTERVAL_SECONDS = 1.4;
40
40
  private iframeBaseUrl;
41
41
  protected localStorage: ClientScopedStorage;
@@ -49,7 +49,7 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
49
49
  link,
50
50
  baseUrl,
51
51
  iframeId,
52
- container = document.body,
52
+ container,
53
53
  onIframeInitialize,
54
54
  localStorage,
55
55
  clientId,
@@ -60,6 +60,10 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
60
60
  this.ecosystem = ecosystem;
61
61
  this.iframeBaseUrl = baseUrl;
62
62
 
63
+ if (typeof document === "undefined") {
64
+ return;
65
+ }
66
+ container = container ?? document.body;
63
67
  // Creating the IFrame element for communication
64
68
  let iframe = document.getElementById(iframeId) as HTMLIFrameElement | null;
65
69
  const hrefLink = new URL(link);
@@ -164,6 +168,11 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
164
168
  params: T[keyof T];
165
169
  showIframe?: boolean;
166
170
  }) {
171
+ if (!this.iframe) {
172
+ throw new Error(
173
+ "Iframe not found. You are likely calling this from the backend where the DOM is not available.",
174
+ );
175
+ }
167
176
  while (!isIframeLoaded.get(this.iframe.src)) {
168
177
  await sleep(this.POLLING_INTERVAL_SECONDS * 1000);
169
178
  }
@@ -182,7 +191,9 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
182
191
  if (showIframe) {
183
192
  // magic number to let modal fade out before hiding it
184
193
  await sleep(0.1 * 1000);
185
- this.iframe.style.display = "none";
194
+ if (this.iframe) {
195
+ this.iframe.style.display = "none";
196
+ }
186
197
  }
187
198
  if (!data.success) {
188
199
  rej(new Error(data.error));
@@ -213,6 +224,8 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
213
224
  * @internal
214
225
  */
215
226
  destroy() {
216
- isIframeLoaded.delete(this.iframe.src);
227
+ if (this.iframe) {
228
+ isIframeLoaded.delete(this.iframe.src);
229
+ }
217
230
  }
218
231
  }
@@ -32,7 +32,7 @@ export class InAppWalletIframeCommunicator<
32
32
  baseUrl,
33
33
  }).href,
34
34
  baseUrl,
35
- container: document.body,
35
+ container: typeof document === "undefined" ? undefined : document.body,
36
36
  localStorage: new ClientScopedStorage({
37
37
  storage: webLocalStorage,
38
38
  clientId,
@@ -17,6 +17,7 @@ import { readContract } from "../../transaction/read-contract.js";
17
17
  import { getAddress } from "../../utils/address.js";
18
18
  import { isZkSyncChain } from "../../utils/any-evm/zksync/isZkSyncChain.js";
19
19
  import type { Hex } from "../../utils/encoding/hex.js";
20
+ import { resolvePromisedValue } from "../../utils/promise/resolve-promised-value.js";
20
21
  import { parseTypedData } from "../../utils/signatures/helpers/parse-typed-data.js";
21
22
  import { type SignableMessage, maxUint96 } from "../../utils/types.js";
22
23
  import type {
@@ -525,6 +526,15 @@ async function _sendUserOp(args: {
525
526
  userOpHash,
526
527
  });
527
528
 
529
+ trackTransaction({
530
+ client: options.client,
531
+ chainId: options.chain.id,
532
+ transactionHash: receipt.transactionHash,
533
+ walletAddress: options.accountContract.address,
534
+ walletType: "smart",
535
+ contractAddress: await resolvePromisedValue(executeTx.to ?? undefined),
536
+ });
537
+
528
538
  return {
529
539
  client: options.client,
530
540
  chain: options.chain,
@@ -268,7 +268,7 @@ async function checkFor712Factory({
268
268
  }
269
269
 
270
270
  /**
271
- * Deployes a smart account via a dummy transaction.
271
+ * Deployes a smart account via a dummy transaction. If the account is already deployed, this will do nothing.
272
272
  *
273
273
  * @param args - Arguments for the deployment.
274
274
  * @param args.smartAccount - The smart account to deploy.
@@ -93,12 +93,14 @@ export async function connectWC(
93
93
  let { onDisplayUri } = wcOptions || {};
94
94
 
95
95
  // use default sessionHandler unless onDisplayUri is explicitly provided
96
- if (!onDisplayUri && sessionHandler && walletId !== "walletConnect") {
96
+ if (!onDisplayUri && sessionHandler) {
97
97
  const walletInfo = await getWalletInfo(walletId);
98
98
  const deeplinkHandler = (uri: string) => {
99
99
  const appUrl = walletInfo.mobile.native || walletInfo.mobile.universal;
100
100
  if (!appUrl) {
101
- throw new Error("No app url found for wallet connect to redirect to.");
101
+ // generic wc uri
102
+ sessionHandler(uri);
103
+ return;
102
104
  }
103
105
  const fullUrl = formatWalletConnectUrl(appUrl, uri).redirect;
104
106
  sessionHandler(fullUrl);