thirdweb 5.66.0-nightly-880c3453ee8fc0fabbde0afb752a17894cd579a0-20241106000325 → 5.67.0-nightly-734707e28b829262a1b40f7db8c005d2adeaeaf9-20241107000509

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 (71) hide show
  1. package/dist/cjs/exports/react.js +4 -2
  2. package/dist/cjs/exports/react.js.map +1 -1
  3. package/dist/cjs/react/web/ui/SiteEmbed.js +3 -3
  4. package/dist/cjs/react/web/ui/SiteLink.js +64 -0
  5. package/dist/cjs/react/web/ui/SiteLink.js.map +1 -0
  6. package/dist/cjs/react/web/wallets/shared/PassKeyLogin.js +2 -1
  7. package/dist/cjs/react/web/wallets/shared/PassKeyLogin.js.map +1 -1
  8. package/dist/cjs/utils/encoding/to-bytes.js +4 -0
  9. package/dist/cjs/utils/encoding/to-bytes.js.map +1 -1
  10. package/dist/cjs/version.js +1 -1
  11. package/dist/cjs/wallets/in-app/core/actions/generate-wallet.enclave.js +1 -1
  12. package/dist/cjs/wallets/in-app/core/actions/generate-wallet.enclave.js.map +1 -1
  13. package/dist/cjs/wallets/in-app/core/wallet/enclave-wallet.js +2 -2
  14. package/dist/cjs/wallets/in-app/core/wallet/enclave-wallet.js.map +1 -1
  15. package/dist/cjs/wallets/in-app/native/native-connector.js +15 -15
  16. package/dist/cjs/wallets/in-app/native/native-connector.js.map +1 -1
  17. package/dist/cjs/wallets/in-app/web/lib/auth/iframe-auth.js +1 -1
  18. package/dist/cjs/wallets/in-app/web/lib/auth/iframe-auth.js.map +1 -1
  19. package/dist/cjs/wallets/in-app/web/lib/web-connector.js +7 -9
  20. package/dist/cjs/wallets/in-app/web/lib/web-connector.js.map +1 -1
  21. package/dist/esm/exports/react.js +2 -1
  22. package/dist/esm/exports/react.js.map +1 -1
  23. package/dist/esm/react/web/ui/SiteEmbed.js +3 -3
  24. package/dist/esm/react/web/ui/SiteLink.js +61 -0
  25. package/dist/esm/react/web/ui/SiteLink.js.map +1 -0
  26. package/dist/esm/react/web/wallets/shared/PassKeyLogin.js +2 -1
  27. package/dist/esm/react/web/wallets/shared/PassKeyLogin.js.map +1 -1
  28. package/dist/esm/utils/encoding/to-bytes.js +4 -1
  29. package/dist/esm/utils/encoding/to-bytes.js.map +1 -1
  30. package/dist/esm/version.js +1 -1
  31. package/dist/esm/wallets/in-app/core/actions/generate-wallet.enclave.js +1 -1
  32. package/dist/esm/wallets/in-app/core/actions/generate-wallet.enclave.js.map +1 -1
  33. package/dist/esm/wallets/in-app/core/wallet/enclave-wallet.js +2 -2
  34. package/dist/esm/wallets/in-app/core/wallet/enclave-wallet.js.map +1 -1
  35. package/dist/esm/wallets/in-app/native/native-connector.js +15 -15
  36. package/dist/esm/wallets/in-app/native/native-connector.js.map +1 -1
  37. package/dist/esm/wallets/in-app/web/lib/auth/iframe-auth.js +1 -1
  38. package/dist/esm/wallets/in-app/web/lib/auth/iframe-auth.js.map +1 -1
  39. package/dist/esm/wallets/in-app/web/lib/web-connector.js +7 -9
  40. package/dist/esm/wallets/in-app/web/lib/web-connector.js.map +1 -1
  41. package/dist/types/exports/react.d.ts +1 -0
  42. package/dist/types/exports/react.d.ts.map +1 -1
  43. package/dist/types/react/web/ui/SiteEmbed.d.ts +3 -3
  44. package/dist/types/react/web/ui/SiteLink.d.ts +29 -0
  45. package/dist/types/react/web/ui/SiteLink.d.ts.map +1 -0
  46. package/dist/types/utils/encoding/to-bytes.d.ts +9 -0
  47. package/dist/types/utils/encoding/to-bytes.d.ts.map +1 -1
  48. package/dist/types/version.d.ts +1 -1
  49. package/dist/types/wallets/in-app/core/actions/generate-wallet.enclave.d.ts +2 -2
  50. package/dist/types/wallets/in-app/core/actions/generate-wallet.enclave.d.ts.map +1 -1
  51. package/dist/types/wallets/in-app/native/native-connector.d.ts.map +1 -1
  52. package/dist/types/wallets/in-app/web/lib/web-connector.d.ts +2 -1
  53. package/dist/types/wallets/in-app/web/lib/web-connector.d.ts.map +1 -1
  54. package/package.json +5 -5
  55. package/src/exports/react.ts +2 -1
  56. package/src/react/web/ui/SiteEmbed.tsx +3 -3
  57. package/src/react/web/ui/SiteLink.test.tsx +48 -0
  58. package/src/react/web/ui/SiteLink.tsx +86 -0
  59. package/src/react/web/wallets/shared/PassKeyLogin.tsx +2 -1
  60. package/src/utils/encoding/helpers/assert-size.test.ts +47 -0
  61. package/src/utils/encoding/helpers/byte-size.test.ts +36 -0
  62. package/src/utils/encoding/helpers/charcode-to-base-16.test.ts +39 -0
  63. package/src/utils/encoding/helpers/is-hext.test.ts +54 -0
  64. package/src/utils/encoding/to-bytes.test.ts +233 -0
  65. package/src/utils/encoding/to-bytes.ts +7 -1
  66. package/src/version.ts +1 -1
  67. package/src/wallets/in-app/core/actions/generate-wallet.enclave.ts +2 -2
  68. package/src/wallets/in-app/core/wallet/enclave-wallet.ts +2 -2
  69. package/src/wallets/in-app/native/native-connector.ts +18 -19
  70. package/src/wallets/in-app/web/lib/auth/iframe-auth.ts +1 -1
  71. package/src/wallets/in-app/web/lib/web-connector.ts +13 -12
@@ -17,14 +17,14 @@ import { useActiveWallet } from "../../core/hooks/wallets/useActiveWallet.js";
17
17
  *
18
18
  * @param {Object} props - The props to pass to the iframe
19
19
  * @param {String} props.src - The URL of the site to embed
20
- * @param {ThirdwebClient} props.client - The client to use for the embedded site
21
- * @param {Ecosystem} [props.ecosystem] - The ecosystem to use for the embedded site
20
+ * @param {ThirdwebClient} props.client - The current site's thirdweb client
21
+ * @param {Ecosystem} [props.ecosystem] - The ecosystem to use for the wallet connection in the embedded site
22
22
  *
23
23
  * @example
24
24
  * ```tsx
25
25
  * import { SiteEmbed } from "thirdweb/react";
26
26
  *
27
- * <SiteEmbed src="https://thirdweb.com" clientId="thirdweb-client-id" />
27
+ * <SiteEmbed src="https://thirdweb.com" client={thirdwebClient} ecosystem={{ id: "ecosystem.thirdweb" }} />
28
28
  * ```
29
29
  */
30
30
  export function SiteEmbed({
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { render, waitFor } from "../../../../test/src/react-render.js";
3
+ import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
4
+ import { SiteLink } from "./SiteLink.js";
5
+
6
+ describe("SiteLink", () => {
7
+ it("renders anchor with correct href", () => {
8
+ const testUrl = "https://example.com/";
9
+ const { container } = render(
10
+ <SiteLink href={testUrl} client={TEST_CLIENT}>
11
+ Test Link
12
+ </SiteLink>,
13
+ );
14
+
15
+ const anchor = container.querySelector("a");
16
+ expect(anchor).toBeTruthy();
17
+ expect(anchor?.href).toBe(testUrl);
18
+ expect(anchor?.textContent).toBe("Test Link");
19
+ });
20
+
21
+ it("throws error if clientId is not provided", () => {
22
+ const testUrl = "https://example.com/";
23
+ expect(() =>
24
+ render(
25
+ // biome-ignore lint/suspicious/noExplicitAny: testing invalid input
26
+ <SiteLink href={testUrl} client={{} as any}>
27
+ Test Link
28
+ </SiteLink>,
29
+ ),
30
+ ).toThrow("The SiteLink client must have a clientId");
31
+ });
32
+
33
+ it("adds wallet params to url when wallet is connected", async () => {
34
+ const testUrl = "https://example.com/";
35
+ const { container } = render(
36
+ <SiteLink href={testUrl} client={TEST_CLIENT}>
37
+ Test Link
38
+ </SiteLink>,
39
+ {
40
+ setConnectedWallet: true,
41
+ },
42
+ );
43
+
44
+ const anchor = container.querySelector("a");
45
+ expect(anchor).toBeTruthy();
46
+ await waitFor(() => expect(anchor?.href).toContain("walletId="));
47
+ });
48
+ });
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import { useQuery } from "@tanstack/react-query";
3
+ import type { ThirdwebClient } from "../../../client/client.js";
4
+ import { getLastAuthProvider } from "../../../react/core/utils/storage.js";
5
+ import { webLocalStorage } from "../../../utils/storage/webStorage.js";
6
+ import { isEcosystemWallet } from "../../../wallets/ecosystem/is-ecosystem-wallet.js";
7
+ import { ClientScopedStorage } from "../../../wallets/in-app/core/authentication/client-scoped-storage.js";
8
+ import type { Ecosystem } from "../../../wallets/in-app/core/wallet/types.js";
9
+ import { useActiveWallet } from "../../core/hooks/wallets/useActiveWallet.js";
10
+
11
+ /**
12
+ * Creates a link to another thirdweb-supported site with wallet connection parameters.
13
+ *
14
+ * @note The target site must support the connected wallet (ecosystem or in-app).
15
+ *
16
+ * @param {Object} props - The props to pass to the anchor tag
17
+ * @param {String} props.href - The URL of the site to link to
18
+ * @param {ThirdwebClient} props.client - The current site's thirdweb client
19
+ * @param {Ecosystem} [props.ecosystem] - The ecosystem to use for the wallet connection in the target site
20
+ * @param {React.ReactNode} props.children - The content to render inside the link
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * import { SiteLink } from "thirdweb/react";
25
+ *
26
+ * <SiteLink href="https://thirdweb.com" client={thirdwebClient} ecosystem={{ id: "ecosystem.thirdweb" }}>
27
+ * Visit Site
28
+ * </SiteLink>
29
+ * ```
30
+ */
31
+ export function SiteLink({
32
+ href,
33
+ client,
34
+ ecosystem,
35
+ children,
36
+ ...props
37
+ }: {
38
+ href: string;
39
+ client: ThirdwebClient;
40
+ ecosystem?: Ecosystem;
41
+ children: React.ReactNode;
42
+ } & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href">) {
43
+ if (!client.clientId) {
44
+ throw new Error("The SiteLink client must have a clientId");
45
+ }
46
+
47
+ const activeWallet = useActiveWallet();
48
+ const walletId = activeWallet?.id;
49
+
50
+ const {
51
+ data: { authProvider, authCookie } = {},
52
+ } = useQuery({
53
+ queryKey: ["site-link", walletId, href, client.clientId, ecosystem],
54
+ enabled:
55
+ activeWallet && (isEcosystemWallet(activeWallet) || walletId === "inApp"),
56
+ queryFn: async () => {
57
+ const storage = new ClientScopedStorage({
58
+ storage: webLocalStorage,
59
+ clientId: client.clientId,
60
+ ecosystem,
61
+ });
62
+
63
+ const authProvider = await getLastAuthProvider(webLocalStorage);
64
+ const authCookie = await storage.getAuthCookie();
65
+
66
+ return { authProvider, authCookie };
67
+ },
68
+ });
69
+
70
+ const url = new URL(href);
71
+ if (walletId) {
72
+ url.searchParams.set("walletId", walletId);
73
+ }
74
+ if (authProvider) {
75
+ url.searchParams.set("authProvider", authProvider);
76
+ }
77
+ if (authCookie) {
78
+ url.searchParams.set("authCookie", authCookie);
79
+ }
80
+
81
+ return (
82
+ <a href={encodeURI(url.toString())} {...props}>
83
+ {children}
84
+ </a>
85
+ );
86
+ }
@@ -160,7 +160,8 @@ function LoginScreen(props: {
160
160
  await setLastAuthProvider("passkey", webLocalStorage);
161
161
  }
162
162
  done();
163
- } catch {
163
+ } catch (e) {
164
+ console.error("Failed to login with passkey", e);
164
165
  setStatus("error");
165
166
  }
166
167
  }
@@ -0,0 +1,47 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { assertSize } from "./assert-size.js";
3
+
4
+ describe("assertSize", () => {
5
+ it("should not throw an error for hex strings within the specified size", () => {
6
+ expect(() => assertSize("0x1a4", { size: 2 })).not.toThrow();
7
+ expect(() => assertSize("0x1234", { size: 2 })).not.toThrow();
8
+ });
9
+
10
+ it("should throw an error for hex strings exceeding the specified size", () => {
11
+ expect(() => assertSize("0x123456", { size: 2 })).toThrow(
12
+ "Size overflow: 3 > 2",
13
+ );
14
+ expect(() => assertSize("0xabcdef", { size: 2 })).toThrow(
15
+ "Size overflow: 3 > 2",
16
+ );
17
+ });
18
+
19
+ it("should not throw an error for Uint8Array within the specified size", () => {
20
+ expect(() =>
21
+ assertSize(new Uint8Array([1, 2, 3]), { size: 3 }),
22
+ ).not.toThrow();
23
+ expect(() => assertSize(new Uint8Array([]), { size: 0 })).not.toThrow();
24
+ });
25
+
26
+ it("should throw an error for Uint8Array exceeding the specified size", () => {
27
+ expect(() => assertSize(new Uint8Array([1, 2, 3, 4]), { size: 3 })).toThrow(
28
+ "Size overflow: 4 > 3",
29
+ );
30
+ });
31
+
32
+ it("should not throw an error for empty hex strings", () => {
33
+ expect(() => assertSize("0x", { size: 0 })).not.toThrow();
34
+ });
35
+
36
+ it("should handle boundary conditions correctly", () => {
37
+ expect(() => assertSize("0x12", { size: 1 })).not.toThrow();
38
+ expect(() => assertSize("0x12", { size: 0 })).toThrow(
39
+ "Size overflow: 1 > 0",
40
+ );
41
+ });
42
+
43
+ it("should not throw an error for hex strings exactly at the specified size", () => {
44
+ expect(() => assertSize("0x12", { size: 1 })).not.toThrow();
45
+ expect(() => assertSize("0x1234", { size: 2 })).not.toThrow();
46
+ });
47
+ });
@@ -0,0 +1,36 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { byteSize } from "./byte-size.js";
3
+
4
+ describe("byteSize", () => {
5
+ it('should calculate the byte size for a valid hex string with "0x" prefix', () => {
6
+ expect(byteSize("0x1a4")).toBe(2); // "1a4" is 1 byte + 1 nibble = 2 bytes
7
+ expect(byteSize("0x123456")).toBe(3); // "123456" is 3 bytes
8
+ });
9
+
10
+ it("should return 0 for an empty hex string", () => {
11
+ expect(byteSize("0x")).toBe(0);
12
+ });
13
+
14
+ it("should calculate the byte size for a Uint8Array", () => {
15
+ expect(byteSize(new Uint8Array([1, 2, 3]))).toBe(3);
16
+ expect(byteSize(new Uint8Array([]))).toBe(0);
17
+ });
18
+
19
+ it('should handle a single byte hex string with "0x" prefix', () => {
20
+ expect(byteSize("0x1")).toBe(1); // "1" is half a byte, treated as 1 byte
21
+ expect(byteSize("0x12")).toBe(1); // "12" is 1 byte
22
+ });
23
+
24
+ it("should handle longer hex strings", () => {
25
+ expect(byteSize("0x1234567890abcdef")).toBe(8); // "1234567890abcdef" is 8 bytes
26
+ expect(byteSize("0xabcdef")).toBe(3); // "abcdef" is 3 bytes
27
+ });
28
+
29
+ it("should return 0 for non-hex string inputs in Uint8Array form", () => {
30
+ expect(byteSize(new Uint8Array([]))).toBe(0); // Empty Uint8Array
31
+ });
32
+
33
+ it('should handle strings that are not valid hex but start with "0x"', () => {
34
+ expect(byteSize("0xg")).toBe(1); // Not a valid hex string
35
+ });
36
+ });
@@ -0,0 +1,39 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { charCodeToBase16 } from "./charcode-to-base-16.js";
3
+
4
+ describe("charCodeToBase16", () => {
5
+ it("should return correct values for digits (0-9)", () => {
6
+ expect(charCodeToBase16("0".charCodeAt(0))).toBe(0);
7
+ expect(charCodeToBase16("5".charCodeAt(0))).toBe(5);
8
+ expect(charCodeToBase16("9".charCodeAt(0))).toBe(9);
9
+ });
10
+
11
+ it("should return correct values for uppercase letters (A-F)", () => {
12
+ expect(charCodeToBase16("A".charCodeAt(0))).toBe(10);
13
+ expect(charCodeToBase16("C".charCodeAt(0))).toBe(12);
14
+ expect(charCodeToBase16("F".charCodeAt(0))).toBe(15);
15
+ });
16
+
17
+ it("should return correct values for lowercase letters (a-f)", () => {
18
+ expect(charCodeToBase16("a".charCodeAt(0))).toBe(10);
19
+ expect(charCodeToBase16("c".charCodeAt(0))).toBe(12);
20
+ expect(charCodeToBase16("f".charCodeAt(0))).toBe(15);
21
+ });
22
+
23
+ // Test cases for invalid inputs
24
+ it("should return undefined for invalid inputs", () => {
25
+ expect(charCodeToBase16("G".charCodeAt(0))).toBeUndefined();
26
+ expect(charCodeToBase16("z".charCodeAt(0))).toBeUndefined();
27
+ expect(charCodeToBase16(" ".charCodeAt(0))).toBeUndefined();
28
+ expect(charCodeToBase16("!".charCodeAt(0))).toBeUndefined();
29
+ });
30
+
31
+ it("should handle edge cases correctly", () => {
32
+ expect(charCodeToBase16("0".charCodeAt(0) - 1)).toBeUndefined(); // Just below '0'
33
+ expect(charCodeToBase16("9".charCodeAt(0) + 1)).toBeUndefined(); // Just above '9'
34
+ expect(charCodeToBase16("A".charCodeAt(0) - 1)).toBeUndefined(); // Just below 'A'
35
+ expect(charCodeToBase16("F".charCodeAt(0) + 1)).toBeUndefined(); // Just above 'F'
36
+ expect(charCodeToBase16("a".charCodeAt(0) - 1)).toBeUndefined(); // Just below 'a'
37
+ expect(charCodeToBase16("f".charCodeAt(0) + 1)).toBeUndefined(); // Just above 'f'
38
+ });
39
+ });
@@ -0,0 +1,54 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { isHex } from "./is-hex.js";
3
+
4
+ describe("isHex", () => {
5
+ it('should return true for valid hex strings with "0x" prefix in strict mode', () => {
6
+ expect(isHex("0x1a4", { strict: true })).toBe(true);
7
+ expect(isHex("0xABCDEF", { strict: true })).toBe(true);
8
+ });
9
+
10
+ it('should return false for hex strings without "0x" prefix in strict mode', () => {
11
+ expect(isHex("1a4", { strict: true })).toBe(false);
12
+ expect(isHex("abcdef", { strict: true })).toBe(false);
13
+ });
14
+
15
+ it('should return true for valid hex strings with or without "0x" prefix in non-strict mode', () => {
16
+ expect(isHex("0x1a4", { strict: false })).toBe(true);
17
+ expect(isHex("1a4", { strict: false })).toBe(false);
18
+ });
19
+
20
+ it("should return false for invalid hex strings in strict mode", () => {
21
+ expect(isHex("0x1g4", { strict: true })).toBe(false);
22
+ expect(isHex("0xZXY", { strict: true })).toBe(false);
23
+ });
24
+
25
+ it("should return false for invalid hex strings in non-strict mode", () => {
26
+ expect(isHex("0x1g4", { strict: false })).toBe(true);
27
+ expect(isHex("0xZXY", { strict: false })).toBe(true);
28
+ });
29
+
30
+ it("should return false for non-string inputs", () => {
31
+ expect(isHex(123, { strict: true })).toBe(false);
32
+ expect(isHex(null, { strict: true })).toBe(false);
33
+ expect(isHex(undefined, { strict: true })).toBe(false);
34
+ expect(isHex({}, { strict: true })).toBe(false);
35
+ });
36
+
37
+ it("should return false for empty strings", () => {
38
+ expect(isHex("", { strict: true })).toBe(false);
39
+ expect(isHex("", { strict: false })).toBe(false);
40
+ });
41
+
42
+ it("should return true for valid empty hex prefix in non-strict mode", () => {
43
+ expect(isHex("0x", { strict: false })).toBe(true);
44
+ });
45
+
46
+ it("should return true for valid empty hex prefix in strict mode", () => {
47
+ expect(isHex("0x", { strict: true })).toBe(true);
48
+ });
49
+
50
+ it("should use strict mode by default", () => {
51
+ expect(isHex("0x1a4")).toBe(true);
52
+ expect(isHex("1a4")).toBe(false);
53
+ });
54
+ });
@@ -0,0 +1,233 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { numberToHex } from "./hex.js";
3
+ import {
4
+ boolToBytes,
5
+ hexToBytes,
6
+ numberToBytes,
7
+ padBytes,
8
+ stringToBytes,
9
+ toBytes,
10
+ } from "./to-bytes.js";
11
+
12
+ describe("to-bytes.js", () => {
13
+ describe("padBytes", () => {
14
+ it("should pad bytes to the left by default to the specified size", () => {
15
+ const result = padBytes(new Uint8Array([1, 2, 3]), { size: 5 });
16
+ expect(result).toEqual(new Uint8Array([0, 0, 1, 2, 3]));
17
+ });
18
+
19
+ it('should pad bytes to the right if dir is "right"', () => {
20
+ const result = padBytes(new Uint8Array([1, 2, 3]), {
21
+ dir: "right",
22
+ size: 5,
23
+ });
24
+ expect(result).toEqual(new Uint8Array([1, 2, 3, 0, 0]));
25
+ });
26
+
27
+ it("should not pad if the byte array is already the specified size", () => {
28
+ const result = padBytes(new Uint8Array([1, 2, 3, 4, 5]), { size: 5 });
29
+ expect(result).toEqual(new Uint8Array([1, 2, 3, 4, 5]));
30
+ });
31
+
32
+ it("should throw an error if the byte array exceeds the specified size", () => {
33
+ expect(() =>
34
+ padBytes(new Uint8Array([1, 2, 3, 4, 5, 6]), { size: 5 }),
35
+ ).toThrow("Size overflow: 6 > 5");
36
+ });
37
+
38
+ it("should return the same byte array if size is null", () => {
39
+ const bytes = new Uint8Array([1, 2, 3]);
40
+ const result = padBytes(bytes, { size: null });
41
+ expect(result).toEqual(bytes);
42
+ });
43
+
44
+ it("should pad to the default size of 32 if size is not specified", () => {
45
+ const result = padBytes(new Uint8Array([1, 2, 3]));
46
+ expect(result).toStrictEqual(
47
+ new Uint8Array([
48
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49
+ 0, 0, 0, 0, 0, 0, 1, 2, 3,
50
+ ]),
51
+ );
52
+ });
53
+
54
+ it("should handle an empty byte array and pad to the specified size", () => {
55
+ const result = padBytes(new Uint8Array([]), { size: 3 });
56
+ expect(result).toEqual(new Uint8Array([0, 0, 0]));
57
+ });
58
+ });
59
+
60
+ describe("toBytes", () => {
61
+ it("should convert a number to bytes", () => {
62
+ expect(toBytes(123)).toEqual(new Uint8Array([123]));
63
+ });
64
+
65
+ it("should convert a bigint to bytes", () => {
66
+ expect(toBytes(BigInt(123))).toEqual(new Uint8Array([123]));
67
+ });
68
+
69
+ it("should convert a boolean to bytes", () => {
70
+ expect(toBytes(true)).toEqual(new Uint8Array([1]));
71
+ expect(toBytes(false)).toEqual(new Uint8Array([0]));
72
+ });
73
+
74
+ it("should convert a hex string to bytes", () => {
75
+ expect(toBytes("0x1a")).toEqual(new Uint8Array([26])); // 0x1a = 26 in decimal
76
+ expect(toBytes("0xabcd")).toEqual(new Uint8Array([171, 205]));
77
+ });
78
+
79
+ it("should convert a regular string to bytes", () => {
80
+ expect(toBytes("abc")).toEqual(new Uint8Array([97, 98, 99])); // ASCII values for 'a', 'b', 'c'
81
+ });
82
+
83
+ it("should handle empty hex string", () => {
84
+ expect(toBytes("0x")).toEqual(new Uint8Array([]));
85
+ });
86
+
87
+ it("should handle empty string", () => {
88
+ expect(toBytes("")).toEqual(new Uint8Array([]));
89
+ });
90
+ });
91
+
92
+ describe("boolToBytes", () => {
93
+ it("should convert true to a Uint8Array with a value of 1", () => {
94
+ expect(boolToBytes(true)).toEqual(new Uint8Array([1]));
95
+ });
96
+
97
+ it("should convert false to a Uint8Array with a value of 0", () => {
98
+ expect(boolToBytes(false)).toEqual(new Uint8Array([0]));
99
+ });
100
+
101
+ it("should pad the byte array to the specified size with zeros on the left when size is provided", () => {
102
+ expect(boolToBytes(true, { size: 4 })).toEqual(
103
+ new Uint8Array([0, 0, 0, 1]),
104
+ );
105
+ expect(boolToBytes(false, { size: 4 })).toEqual(
106
+ new Uint8Array([0, 0, 0, 0]),
107
+ );
108
+ });
109
+
110
+ it("should throw an error if the specified size is less than the byte size", () => {
111
+ expect(() => boolToBytes(true, { size: 0 })).toThrow(
112
+ "Size overflow: 1 > 0",
113
+ );
114
+ });
115
+
116
+ it("should not pad if no size is provided", () => {
117
+ expect(boolToBytes(true)).toEqual(new Uint8Array([1]));
118
+ expect(boolToBytes(false)).toEqual(new Uint8Array([0]));
119
+ });
120
+
121
+ it("should handle size of 1 correctly", () => {
122
+ expect(boolToBytes(true, { size: 1 })).toEqual(new Uint8Array([1]));
123
+ expect(boolToBytes(false, { size: 1 })).toEqual(new Uint8Array([0]));
124
+ });
125
+ });
126
+
127
+ describe("hexToBytes", () => {
128
+ it("should convert a valid hex string to Uint8Array", () => {
129
+ expect(hexToBytes("0x1a4")).toEqual(new Uint8Array([1, 164]));
130
+ expect(hexToBytes("0xabcdef")).toEqual(new Uint8Array([171, 205, 239]));
131
+ });
132
+
133
+ it("should handle odd-length hex strings by prepending a zero", () => {
134
+ expect(hexToBytes("0xabc")).toEqual(new Uint8Array([10, 188]));
135
+ });
136
+
137
+ it("should throw an error for invalid hex strings", () => {
138
+ expect(() => hexToBytes("0x1g")).toThrow(
139
+ 'Invalid byte sequence ("1g" in "1g").',
140
+ );
141
+ expect(() => hexToBytes("0xzz")).toThrow(
142
+ 'Invalid byte sequence ("zz" in "zz").',
143
+ );
144
+ });
145
+
146
+ it("should pad the hex string to the specified size by adding extra bytes", () => {
147
+ expect(hexToBytes("0x1a", { size: 4 })).toEqual(
148
+ new Uint8Array([26, 0, 0, 0]),
149
+ );
150
+ });
151
+
152
+ it("should throw an error if the hex string exceeds the specified size", () => {
153
+ expect(() => hexToBytes("0x123456", { size: 2 })).toThrow(
154
+ "Size overflow",
155
+ );
156
+ });
157
+
158
+ it("should correctly convert hex strings with even lengths without additional padding", () => {
159
+ expect(hexToBytes("0x1234")).toEqual(new Uint8Array([18, 52]));
160
+ });
161
+ });
162
+
163
+ describe("numberToBytes", () => {
164
+ it("should convert a number to a Uint8Array", () => {
165
+ const result = numberToBytes(420);
166
+ expect(result).toEqual(new Uint8Array([1, 164]));
167
+ });
168
+
169
+ it("should convert a bigint to a Uint8Array", () => {
170
+ const result = numberToBytes(BigInt(420));
171
+ expect(result).toEqual(new Uint8Array([1, 164]));
172
+ });
173
+
174
+ it("should handle zero correctly", () => {
175
+ const result = numberToBytes(0);
176
+ expect(result).toEqual(new Uint8Array([0]));
177
+ });
178
+
179
+ it("should handle large numbers correctly", () => {
180
+ const largeNumber = BigInt("12345678901234567890");
181
+ const result = numberToBytes(largeNumber);
182
+ expect(result).toEqual(hexToBytes(numberToHex(largeNumber)));
183
+ });
184
+
185
+ it("should apply options correctly when converting numbers", () => {
186
+ const opts = { size: 4 };
187
+ const result = numberToBytes(420, opts);
188
+ expect(result).toEqual(hexToBytes(numberToHex(420, opts)));
189
+ });
190
+ });
191
+
192
+ describe("stringToBytes", () => {
193
+ it("should convert a string to a Uint8Array of bytes", () => {
194
+ const result = stringToBytes("Hello, world!");
195
+ expect(result).toEqual(
196
+ new Uint8Array([
197
+ 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33,
198
+ ]),
199
+ );
200
+ });
201
+
202
+ it("should handle an empty string", () => {
203
+ const result = stringToBytes("");
204
+ expect(result).toEqual(new Uint8Array([]));
205
+ });
206
+
207
+ it("should pad the byte array to the specified size with zeros on the right", () => {
208
+ const result = stringToBytes("Hi", { size: 5 });
209
+ expect(result).toEqual(new Uint8Array([72, 105, 0, 0, 0]));
210
+ });
211
+
212
+ it("should throw an error if the byte array exceeds the specified size", () => {
213
+ expect(() => stringToBytes("Hello", { size: 3 })).toThrow(
214
+ "Size overflow: 5 > 3",
215
+ );
216
+ });
217
+
218
+ it("should not pad if no size is provided", () => {
219
+ const result = stringToBytes("Test");
220
+ expect(result).toEqual(new Uint8Array([84, 101, 115, 116]));
221
+ });
222
+
223
+ it("should handle unicode characters correctly", () => {
224
+ const result = stringToBytes("こんにちは");
225
+ expect(result).toEqual(
226
+ new Uint8Array([
227
+ 227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129,
228
+ 175,
229
+ ]),
230
+ );
231
+ });
232
+ });
233
+ });
@@ -9,7 +9,13 @@ type PadOptions = {
9
9
  size?: number | null;
10
10
  };
11
11
 
12
- function padBytes(bytes: Uint8Array, { dir, size = 32 }: PadOptions = {}) {
12
+ /**
13
+ * @internal Exported for test
14
+ */
15
+ export function padBytes(
16
+ bytes: Uint8Array,
17
+ { dir, size = 32 }: PadOptions = {},
18
+ ) {
13
19
  if (size === null) {
14
20
  return bytes;
15
21
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "5.66.0-nightly-880c3453ee8fc0fabbde0afb752a17894cd579a0-20241106000325";
1
+ export const version = "5.67.0-nightly-734707e28b829262a1b40f7db8c005d2adeaeaf9-20241107000509";
@@ -9,13 +9,13 @@ import type { Ecosystem } from "../wallet/types.js";
9
9
  * @internal
10
10
  */
11
11
  export async function generateWallet({
12
- authToken,
13
12
  client,
14
13
  ecosystem,
14
+ authToken,
15
15
  }: {
16
16
  client: ThirdwebClient;
17
- ecosystem: Ecosystem;
18
17
  authToken: string;
18
+ ecosystem?: Ecosystem;
19
19
  }) {
20
20
  const clientFetch = getClientFetch(client, ecosystem);
21
21
  const response = await clientFetch(
@@ -139,8 +139,8 @@ export class EnclaveWallet implements IWebWallet {
139
139
  chain: getCachedChain(tx.chainId),
140
140
  });
141
141
  const transaction: Record<string, Hex | number | undefined> = {
142
- to: (tx.to as Hex) ?? undefined,
143
- data: tx.data ? toHex(tx.data) : undefined,
142
+ to: tx.to ? getAddress(tx.to) : undefined,
143
+ data: tx.data,
144
144
  value: tx.value ? toHex(tx.value) : undefined,
145
145
  gas: tx.gas ? toHex(tx.gas + tx.gas / BigInt(10)) : undefined, // Add a 10% buffer to gas
146
146
  nonce: tx.nonce
@@ -80,27 +80,26 @@ export class InAppNativeConnector implements InAppConnector {
80
80
  }
81
81
  let wallet = user.wallets[0];
82
82
 
83
- // TODO (enclaves): Migration to enclave wallet for in-app wallets as well
84
- if (
85
- authResult &&
86
- this.storage.ecosystem &&
87
- wallet &&
88
- wallet.type === "sharded"
89
- ) {
90
- const { migrateToEnclaveWallet } = await import(
91
- "./helpers/wallet/migration.js"
92
- );
93
- wallet = await migrateToEnclaveWallet({
94
- client: this.client,
95
- storage: this.storage,
96
- storedToken: authResult.storedToken,
97
- encryptionKey,
98
- });
83
+ if (authResult && wallet && wallet.type === "sharded") {
84
+ try {
85
+ const { migrateToEnclaveWallet } = await import(
86
+ "./helpers/wallet/migration.js"
87
+ );
88
+ wallet = await migrateToEnclaveWallet({
89
+ client: this.client,
90
+ storage: this.storage,
91
+ storedToken: authResult.storedToken,
92
+ encryptionKey,
93
+ });
94
+ } catch {
95
+ console.warn(
96
+ "Failed to migrate from sharded to enclave wallet, continuing with sharded wallet",
97
+ );
98
+ }
99
99
  }
100
100
 
101
- if (authResult && this.ecosystem && !wallet) {
102
- // new ecosystem user, generate enclave wallet
103
- // TODO (enclaves): same flow for in-app wallets
101
+ if (authResult && !wallet) {
102
+ // new user, generate enclave wallet
104
103
  const { generateWallet } = await import(
105
104
  "../core/actions/generate-wallet.enclave.js"
106
105
  );