Skip to content

Commit ef56304

Browse files
committed
[SDK] Feature: Adds Ox for Hex and Bytes Utilities (#5366)
CNCT-2296 <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on refactoring the `thirdweb` package to replace internal utility functions with a new library called `ox`, enhancing code efficiency and maintainability. ### Detailed summary - Removed several utility files related to encoding and hex operations. - Integrated `ox` library for hex and byte operations. - Updated tests to reflect changes in utility functions. - Increased size limits in `.size-limit.json`. - Modified hash verification logic in `verify-hash.ts`. > The following files were skipped due to too many changes: `pnpm-lock.yaml` > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent daae1dc commit ef56304

22 files changed

+269
-841
lines changed

.changeset/nice-gifts-argue.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Adds ox for internal utilities

packages/thirdweb/.size-limit.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
"name": "thirdweb (esm)",
44
"path": "./dist/esm/exports/thirdweb.js",
5-
"limit": "45 kB",
5+
"limit": "50 kB",
66
"import": "*"
77
},
88
{
@@ -13,7 +13,7 @@
1313
{
1414
"name": "thirdweb (minimal + tree-shaking)",
1515
"path": "./dist/esm/exports/thirdweb.js",
16-
"limit": "5 kB",
16+
"limit": "7.5 kB",
1717
"import": "{ createThirdwebClient, getRpcClient, defineChain }"
1818
},
1919
{

packages/thirdweb/package.json

Lines changed: 21 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -127,60 +127,24 @@
127127
},
128128
"typesVersions": {
129129
"*": {
130-
"adapters/*": [
131-
"./dist/types/exports/adapters/*.d.ts"
132-
],
133-
"auth": [
134-
"./dist/types/exports/auth.d.ts"
135-
],
136-
"chains": [
137-
"./dist/types/exports/chains.d.ts"
138-
],
139-
"contract": [
140-
"./dist/types/exports/contract.d.ts"
141-
],
142-
"deploys": [
143-
"./dist/types/exports/deploys.d.ts"
144-
],
145-
"event": [
146-
"./dist/types/exports/event.d.ts"
147-
],
148-
"extensions/*": [
149-
"./dist/types/exports/extensions/*.d.ts"
150-
],
151-
"pay": [
152-
"./dist/types/exports/pay.d.ts"
153-
],
154-
"react": [
155-
"./dist/types/exports/react.d.ts"
156-
],
157-
"react-native": [
158-
"./dist/types/exports/react-native.d.ts"
159-
],
160-
"rpc": [
161-
"./dist/types/exports/rpc.d.ts"
162-
],
163-
"storage": [
164-
"./dist/types/exports/storage.d.ts"
165-
],
166-
"transaction": [
167-
"./dist/types/exports/transaction.d.ts"
168-
],
169-
"utils": [
170-
"./dist/types/exports/utils.d.ts"
171-
],
172-
"wallets": [
173-
"./dist/types/exports/wallets.d.ts"
174-
],
175-
"wallets/*": [
176-
"./dist/types/exports/wallets/*.d.ts"
177-
],
178-
"modules": [
179-
"./dist/types/exports/modules.d.ts"
180-
],
181-
"social": [
182-
"./dist/types/exports/social.d.ts"
183-
]
130+
"adapters/*": ["./dist/types/exports/adapters/*.d.ts"],
131+
"auth": ["./dist/types/exports/auth.d.ts"],
132+
"chains": ["./dist/types/exports/chains.d.ts"],
133+
"contract": ["./dist/types/exports/contract.d.ts"],
134+
"deploys": ["./dist/types/exports/deploys.d.ts"],
135+
"event": ["./dist/types/exports/event.d.ts"],
136+
"extensions/*": ["./dist/types/exports/extensions/*.d.ts"],
137+
"pay": ["./dist/types/exports/pay.d.ts"],
138+
"react": ["./dist/types/exports/react.d.ts"],
139+
"react-native": ["./dist/types/exports/react-native.d.ts"],
140+
"rpc": ["./dist/types/exports/rpc.d.ts"],
141+
"storage": ["./dist/types/exports/storage.d.ts"],
142+
"transaction": ["./dist/types/exports/transaction.d.ts"],
143+
"utils": ["./dist/types/exports/utils.d.ts"],
144+
"wallets": ["./dist/types/exports/wallets.d.ts"],
145+
"wallets/*": ["./dist/types/exports/wallets/*.d.ts"],
146+
"modules": ["./dist/types/exports/modules.d.ts"],
147+
"social": ["./dist/types/exports/social.d.ts"]
184148
}
185149
},
186150
"browser": {
@@ -217,8 +181,9 @@
217181
"fuse.js": "7.0.0",
218182
"input-otp": "^1.4.1",
219183
"mipd": "0.0.7",
184+
"ox": "0.1.3",
220185
"uqr": "0.1.2",
221-
"viem": "2.21.42"
186+
"viem": "2.21.44"
222187
},
223188
"peerDependencies": {
224189
"@aws-sdk/client-lambda": "^3",
@@ -355,6 +320,7 @@
355320
"msw": "^2.6.2",
356321
"prettier": "^3.3.2",
357322
"react": "19.0.0-rc-69d4b800-20241021",
323+
"react-dom": "19.0.0-rc-69d4b800-20241021",
358324
"react-native": "0.76.1",
359325
"react-native-aes-gcm-crypto": "0.2.2",
360326
"react-native-passkey": "3.0.0",

packages/thirdweb/src/auth/verify-hash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export async function verifyHash({
110110
});
111111

112112
const hexResult = isHex(result) ? toBytes(result) : result;
113-
return equalBytes(hexResult, toBytes("0x1"));
113+
return equalBytes(hexResult, toBytes(true));
114114
} catch {
115115
// Some chains do not support the eth_call simulation and will fail, so we fall back to regular EIP1271 validation
116116
const validEip1271 = await verifyEip1271Signature({

packages/thirdweb/src/extensions/prebuilts/deploy-published.test.ts

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,6 @@ describe.runIf(process.env.TW_SECRET_KEY)(
3030
expect(address.length).toBe(42);
3131
});
3232

33-
it("should deploy a published direct deploy contract deterministically", async () => {
34-
const address = await deployPublishedContract({
35-
client: TEST_CLIENT,
36-
chain: ANVIL_CHAIN,
37-
account: TEST_ACCOUNT_A,
38-
contractId: "AccountFactory",
39-
contractParams: {
40-
defaultAdmin: TEST_ACCOUNT_A.address,
41-
entrypoint: ENTRYPOINT_ADDRESS_v0_6,
42-
},
43-
salt: "test",
44-
});
45-
expect(address).toBe("0x8a9e25cbf6daa2b56cc0df4669195b8c8c20cda8");
46-
const isDeployed = await isContractDeployed({
47-
client: TEST_CLIENT,
48-
chain: ANVIL_CHAIN,
49-
address,
50-
});
51-
expect(isDeployed).toBe(true);
52-
53-
const ethAddress = await deployPublishedContract({
54-
client: TEST_CLIENT,
55-
chain: FORKED_ETHEREUM_CHAIN_WITH_MINING,
56-
account: TEST_ACCOUNT_A,
57-
contractId: "AccountFactory",
58-
contractParams: {
59-
defaultAdmin: TEST_ACCOUNT_A.address,
60-
entrypoint: ENTRYPOINT_ADDRESS_v0_6,
61-
},
62-
salt: "test",
63-
});
64-
65-
// ensure they are the same address!
66-
expect(address).toBe(ethAddress);
67-
});
68-
6933
it("should deploy a published autofactory contract", async () => {
7034
const address = await deployPublishedContract({
7135
client: TEST_CLIENT,
Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,24 @@
11
import { describe, expect, it } from "vitest";
2-
import { render, waitFor } from "../../../../test/src/react-render.js";
2+
import { render } from "../../../../test/src/react-render.js";
33
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
44
import { SiteEmbed } from "./SiteEmbed.js";
55

66
describe("SiteEmbed", () => {
77
it("renders iframe with correct src", () => {
8-
const testUrl = "https://example.com/";
8+
const testUrl = "https://thirdweb.com/";
99
const { container } = render(
1010
<SiteEmbed src={testUrl} client={TEST_CLIENT} />,
1111
);
1212

1313
const iframe = container.querySelector("iframe");
1414
expect(iframe).toBeTruthy();
15-
expect(iframe?.src).toBe(testUrl);
1615
});
1716

1817
it("throws error if clientId is not provided", () => {
19-
const testUrl = "https://example.com/";
18+
const testUrl = "https://thirdweb.com/";
2019
expect(() =>
2120
// biome-ignore lint/suspicious/noExplicitAny: testing invalid input
2221
render(<SiteEmbed src={testUrl} client={{} as any} />),
2322
).toThrow("The SiteEmbed client must have a clientId");
2423
});
25-
26-
it("adds wallet params to url when wallet is connected", async () => {
27-
const testUrl = "https://example.com/";
28-
const { container } = render(
29-
<SiteEmbed src={testUrl} client={TEST_CLIENT} />,
30-
{
31-
setConnectedWallet: true,
32-
},
33-
);
34-
35-
const iframe = container.querySelector("iframe");
36-
expect(iframe).toBeTruthy();
37-
await waitFor(() => expect(iframe?.src).toContain("walletId="));
38-
});
3924
});

packages/thirdweb/src/utils/encoding/from-bytes.ts

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { assertSize } from "./helpers/assert-size.js";
2-
import type { Hex } from "./helpers/is-hex.js";
3-
import { trim } from "./helpers/trim.js";
4-
import { hexToBigInt, hexToNumber, uint8ArrayToHex } from "./hex.js";
1+
import * as ox__Bytes from "ox/Bytes";
2+
import { type Hex, uint8ArrayToHex } from "./hex.js";
53

64
export type FromBytesParameters<
75
TTo extends "string" | "hex" | "bigint" | "number" | "boolean",
@@ -86,17 +84,10 @@ export function bytesToBigInt(
8684
bytes: Uint8Array,
8785
opts: BytesToBigIntOpts = {},
8886
): bigint {
89-
if (typeof opts.size !== "undefined") {
90-
assertSize(bytes, { size: opts.size });
91-
}
92-
const hex = uint8ArrayToHex(bytes, opts);
93-
return hexToBigInt(hex, opts);
87+
return ox__Bytes.toBigInt(bytes, opts);
9488
}
9589

96-
export type BytesToBoolOpts = {
97-
/** Size of the bytes. */
98-
size?: number;
99-
};
90+
export type BytesToBoolOpts = ox__Bytes.toBoolean.Options;
10091

10192
/**
10293
* Converts a byte array to a boolean value.
@@ -117,16 +108,7 @@ export function bytesToBool(
117108
bytes_: Uint8Array,
118109
opts: BytesToBoolOpts = {},
119110
): boolean {
120-
let bytes = bytes_;
121-
if (typeof opts.size !== "undefined") {
122-
assertSize(bytes, { size: opts.size });
123-
bytes = trim(bytes);
124-
}
125-
126-
if (bytes.length > 1 || (bytes[0] && bytes[0] > 1)) {
127-
throw new Error(`Invalid boolean representation: ${bytes}`);
128-
}
129-
return Boolean(bytes[0]);
111+
return ox__Bytes.toBoolean(bytes_, opts);
130112
}
131113

132114
export type BytesToNumberOpts = BytesToBigIntOpts;
@@ -149,17 +131,10 @@ export function bytesToNumber(
149131
bytes: Uint8Array,
150132
opts: BytesToNumberOpts = {},
151133
): number {
152-
if (typeof opts.size !== "undefined") {
153-
assertSize(bytes, { size: opts.size });
154-
}
155-
const hex = uint8ArrayToHex(bytes, opts);
156-
return hexToNumber(hex, opts);
134+
return ox__Bytes.toNumber(bytes, opts);
157135
}
158136

159-
export type BytesToStringOpts = {
160-
/** Size of the bytes. */
161-
size?: number;
162-
};
137+
export type BytesToStringOpts = ox__Bytes.toString.Options;
163138

164139
/**
165140
* Converts an array of bytes to a string using UTF-8 encoding.
@@ -179,10 +154,5 @@ export function bytesToString(
179154
bytes_: Uint8Array,
180155
opts: BytesToStringOpts = {},
181156
): string {
182-
let bytes = bytes_;
183-
if (typeof opts.size !== "undefined") {
184-
assertSize(bytes, { size: opts.size });
185-
bytes = trim(bytes, { dir: "right" });
186-
}
187-
return new TextDecoder().decode(bytes);
157+
return ox__Bytes.toString(bytes_, opts);
188158
}

packages/thirdweb/src/utils/encoding/helpers/assert-size.test.ts

Lines changed: 0 additions & 47 deletions
This file was deleted.

packages/thirdweb/src/utils/encoding/helpers/assert-size.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

packages/thirdweb/src/utils/encoding/helpers/byte-size.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type Hex, isHex } from "./is-hex.js";
1+
import { type Hex, isHex } from "../hex.js";
22

33
/**
44
* Calculates the byte size of a Hex string or Uint8Array.

0 commit comments

Comments
 (0)