Skip to content

Commit

Permalink
chore: clean up code and dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
jnsdls committed Feb 8, 2024
1 parent 7dc396b commit 7362ad0
Show file tree
Hide file tree
Showing 16 changed files with 112 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function formatCompilerMetadata(metadata: any): PublishedMetadata {
];
return {
name,
abi: metadata.output.abi,
abi: metadata?.output?.abi || [],
metadata,
info,
licenses,
Expand Down
6 changes: 3 additions & 3 deletions packages/thirdweb/src/contract/actions/get-bytecode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ const BYTECODE_CACHE = new WeakMap<ThirdwebContract<Abi>, Promise<Hex>>();
* @returns A Promise that resolves to the bytecode of the contract.
* @example
* ```ts
* import { getByteCode } from "thirdweb/contract";
* const bytecode = await getByteCode(contract);
* import { getBytecode } from "thirdweb/contract";
* const bytecode = await getBytecode(contract);
* ```
*/
export function getByteCode<abi extends Abi>(
export function getBytecode<abi extends Abi>(
contract: ThirdwebContract<abi>,
): Promise<Hex> {
if (BYTECODE_CACHE.has(contract)) {
Expand Down
22 changes: 14 additions & 8 deletions packages/thirdweb/src/contract/actions/resolve-abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { formatAbi, type Abi, parseAbi } from "abitype";
import type { ThirdwebContract } from "../index.js";
import { getChainIdFromChain } from "../../chain/index.js";
import { getClientFetch } from "../../utils/fetch.js";
import { getByteCode } from "./get-bytecode.js";
import { getBytecode } from "./get-bytecode.js";
import { download } from "../../storage/download.js";
import { extractIPFSUri } from "../../utils/bytecode/extractIPFS.js";
import { detectMethodInBytecode } from "../../utils/bytecode/detectExtension.js";
Expand Down Expand Up @@ -106,15 +106,21 @@ export async function resolveAbiFromContractApi(
export async function resolveAbiFromBytecode(
contract: ThirdwebContract<any>,
): Promise<Abi> {
const bytecode = await getByteCode(contract);
const bytecode = await getBytecode(contract);
const ipfsUri = extractIPFSUri(bytecode);
if (!ipfsUri) {
throw new Error("No IPFS URI found in bytecode");
// just early exit if we can't find an IPFS URI
return [];
}

Check warning on line 114 in packages/thirdweb/src/contract/actions/resolve-abi.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/contract/actions/resolve-abi.ts#L112-L114

Added lines #L112 - L114 were not covered by tests
try {
const res = await download({ uri: ipfsUri, client: contract.client });
const json = await res.json();
// ABI is at `json.output.abi`
return json.output.abi;
} catch {
// if we can't resolve the ABI from the IPFS URI, return an empty array
return [];
}

Check warning on line 123 in packages/thirdweb/src/contract/actions/resolve-abi.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/contract/actions/resolve-abi.ts#L121-L123

Added lines #L121 - L123 were not covered by tests
const res = await download({ uri: ipfsUri, client: contract.client });
const json = await res.json();
// ABI is at `json.output.abi`
return json.output.abi;
}

const PLUGINS_ABI = {
Expand Down Expand Up @@ -252,7 +258,7 @@ export async function resolveCompositeAbiFromBytecode(
) {
const [rootAbi, bytecode] = await Promise.all([
resolveAbiFromBytecode(contract),
getByteCode(contract),
getBytecode(contract),
]);

// check if contract is plugin-pattern / dynamic
Expand Down
2 changes: 1 addition & 1 deletion packages/thirdweb/src/contract/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export {

export { formatCompilerMetadata } from "./actions/compiler-metadata.js";

export { getByteCode } from "./actions/get-bytecode.js";
export { getBytecode } from "./actions/get-bytecode.js";

// verification
export {
Expand Down
2 changes: 1 addition & 1 deletion packages/thirdweb/src/contract/verification/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export async function verifyContract(
const encodedArgs = options.encodedConstructorArgs
? options.encodedConstructorArgs
: await fetchConstructorParams({
abi: compilerMetadata.metadata.output.abi,
abi: compilerMetadata?.metadata?.output?.abi || [],
contract: options.contract,
explorerApiUrl: options.explorerApiUrl,
explorerApiKey: options.explorerApiKey,
Expand Down
6 changes: 5 additions & 1 deletion packages/thirdweb/src/storage/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ export async function download(options: DownloadOptions) {
options.requestTimeoutMs,
);

return getClientFetch(options.client)(resolveScheme(options), {
const res = await getClientFetch(options.client)(resolveScheme(options), {
requestTimeoutMs,
});
if (!res.ok) {
throw new Error(`Failed to download file: ${res.statusText}`);
}

Check warning on line 35 in packages/thirdweb/src/storage/download.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/storage/download.ts#L34-L35

Added lines #L34 - L35 were not covered by tests
return res;
}
29 changes: 29 additions & 0 deletions packages/thirdweb/src/utils/any-evm/is-eip155-enforced.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, it, expect } from "vitest";
import { isEIP155Enforced } from "./is-eip155-enforced.js";
import { TEST_CLIENT } from "../../../test/src/test-clients.js";

describe("isEIP155Enforced", () => {
it("should return true if EIP-155 is enforced", async () => {
// Call the isEIP155Enforced function with a chain that enforces EIP-155
const result = await isEIP155Enforced({
// optimism enforce eip155
chain: 10,
client: TEST_CLIENT,
});

// Assert that the result is true
expect(result).toBe(true);
});

it("should return false if EIP-155 is not enforced", async () => {
// Call the isEIP155Enforced function with a chain that does not enforce EIP-155
const result = await isEIP155Enforced({
// ethereum does not enforce eip155
chain: 1,
client: TEST_CLIENT,
});

// Assert that the result is false
expect(result).toBe(false);
});
});
19 changes: 15 additions & 4 deletions packages/thirdweb/src/utils/any-evm/is-eip155-enforced.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import type { Chain } from "../../chain/index.js";
import { getChainIdFromChain, type Chain } from "../../chain/index.js";
import type { ThirdwebClient } from "../../client/client.js";
import { eth_sendRawTransaction } from "../../rpc/index.js";
import { getRpcClient } from "../../rpc/rpc.js";

// it's OK to cache this forever because:
// 1. the results can't change
// 2. the total size can be max <number of chains> * boolean
const EIP_ENFORCED_CACHE = new Map<bigint, boolean>();

type IsEIP155EnforcedOptions = {
chain: Chain;
client: ThirdwebClient;
Expand All @@ -22,6 +27,12 @@ type IsEIP155EnforcedOptions = {
export async function isEIP155Enforced(
options: IsEIP155EnforcedOptions,
): Promise<boolean> {
const chainId = getChainIdFromChain(options.chain);
// cache because the result cannot change
if (EIP_ENFORCED_CACHE.has(chainId)) {
return EIP_ENFORCED_CACHE.get(chainId) as boolean;
}
let result = false;
try {
// TODO: Find a better way to check this.

Expand All @@ -37,11 +48,11 @@ export async function isEIP155Enforced(
const errorJson = JSON.stringify(e).toLowerCase();

if (matchError(errorMsg) || matchError(errorJson)) {
return true;
result = true;
}
return false;
}
return false;
EIP_ENFORCED_CACHE.set(chainId, result);
return result;
}

const ERROR_SUBSTRINGS_COMPOSITE = [
Expand Down
13 changes: 13 additions & 0 deletions packages/thirdweb/src/utils/any-evm/keccack-id.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { describe, bench } from "vitest";
import { keccackId } from "./keccack-id.js";
import { id } from "ethers6";

const input = "Hello, World!";
describe("keccackId", () => {
bench("thirdweb", () => {
keccackId(input);
});
bench("ethers", () => {
id(input);
});
});
12 changes: 12 additions & 0 deletions packages/thirdweb/src/utils/any-evm/keccack-id.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { describe, it, expect } from "vitest";
import { keccackId } from "./keccack-id.js";

describe("keccackId", () => {
it("should return the keccak256 hash of the input", () => {
const input = "Hello, World!";
const result = keccackId(input);
expect(result).toMatchInlineSnapshot(
`"0xacaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f"`,
);
});
});
6 changes: 3 additions & 3 deletions packages/thirdweb/src/utils/any-evm/keccack-id.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { keccak256, toBytes, type Hex } from "viem";
import { keccak256, type Hex, stringToBytes } from "viem";

/**
* Calculates the keccak ID of the given input.
Expand All @@ -10,6 +10,6 @@ import { keccak256, toBytes, type Hex } from "viem";
* const keccakId = keccackId(input);
* ```
*/
export function keccackId(input: string | number | bigint | boolean): Hex {
return keccak256(toBytes(input));
export function keccackId(input: string): Hex {
return keccak256(stringToBytes(input));
}
4 changes: 2 additions & 2 deletions packages/thirdweb/src/utils/bytecode/detectExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AbiFunction } from "abitype";

import { getFunctionSelector } from "../../abi/lib/getFunctionSelector.js";
import { type ThirdwebContract } from "../../contract/contract.js";
import { getByteCode } from "../../contract/actions/get-bytecode.js";
import { getBytecode } from "../../contract/actions/get-bytecode.js";

export type DetectExtensionOptions = {
contract: ThirdwebContract;
Expand All @@ -25,7 +25,7 @@ export type DetectExtensionOptions = {
export async function detectMethod(
options: DetectExtensionOptions,
): Promise<boolean> {
const bytecode = await getByteCode(options.contract);
const bytecode = await getBytecode(options.contract);
return detectMethodInBytecode({ bytecode, method: options.method });
}

Expand Down
6 changes: 3 additions & 3 deletions packages/thirdweb/src/utils/bytecode/extractIPFS.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
import { getByteCode } from "../../contract/index.js";
import { getBytecode } from "../../contract/index.js";
import {
DOODLES_CONTRACT,
USDC_CONTRACT,
Expand All @@ -9,7 +9,7 @@ import { extractIPFSUri } from "./extractIPFS.js";
describe("extractIPFSUri", () => {
it("works if ipfs is there", async () => {
// get some bytecode
const bytecode = await getByteCode(DOODLES_CONTRACT);
const bytecode = await getBytecode(DOODLES_CONTRACT);
// extract IPFS hash
const ipfsHash = extractIPFSUri(bytecode);

Expand All @@ -21,7 +21,7 @@ describe("extractIPFSUri", () => {

it("does not work if ipfs is not there", async () => {
// get some bytecode
const bytecode = await getByteCode(USDC_CONTRACT);
const bytecode = await getBytecode(USDC_CONTRACT);
// extract IPFS hash
const ipfsHash = extractIPFSUri(bytecode);

Expand Down
4 changes: 2 additions & 2 deletions packages/thirdweb/src/utils/bytecode/is-contract-deployed.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ThirdwebContract } from "../../contract/contract.js";
import { getByteCode } from "../../contract/actions/get-bytecode.js";
import { getBytecode } from "../../contract/actions/get-bytecode.js";

/**
* Checks if a contract is deployed by verifying its bytecode.
Expand All @@ -18,5 +18,5 @@ import { getByteCode } from "../../contract/actions/get-bytecode.js";
export async function isContractDeployed(
contract: ThirdwebContract,
): Promise<boolean> {
return (await getByteCode(contract)) !== "0x";
return (await getBytecode(contract)) !== "0x";
}
8 changes: 4 additions & 4 deletions packages/thirdweb/src/utils/bytecode/resolveImplementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ThirdwebContract } from "../../index.js";
import { eth_getStorageAt, getRpcClient } from "../../rpc/index.js";
import { readContractRaw } from "../../transaction/actions/raw/raw-read.js";
import { extractMinimalProxyImplementationAddress } from "./extractMnimalProxyImplementationAddress.js";
import { getByteCode } from "../../contract/actions/get-bytecode.js";
import { getBytecode } from "../../contract/actions/get-bytecode.js";

// TODO: move to const exports
export const AddressZero = "0x0000000000000000000000000000000000000000";
Expand All @@ -22,7 +22,7 @@ export async function resolveImplementation(
contract: ThirdwebContract<any>,
): Promise<{ address: string; bytecode: string }> {
const [bytecode, beacon] = await Promise.all([
getByteCode(contract),
getBytecode(contract),
getBeaconFromStorageSlot(contract),
]);
// check minimal proxy first synchronously
Expand All @@ -31,7 +31,7 @@ export async function resolveImplementation(
if (minimalProxyImplementationAddress) {
return {
address: minimalProxyImplementationAddress,
bytecode: await getByteCode({
bytecode: await getBytecode({
...contract,
address: minimalProxyImplementationAddress,
}),
Expand All @@ -57,7 +57,7 @@ export async function resolveImplementation(
) {
return {
address: implementationAddress,
bytecode: await getByteCode({
bytecode: await getBytecode({
...contract,
address: implementationAddress,
}),
Expand Down
11 changes: 4 additions & 7 deletions packages/thirdweb/src/utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,18 @@ export function getClientFetch(client: ThirdwebClient) {
});
}

let abortController: AbortController | undefined;
const controller = new AbortController();
let abortTimeout: ReturnType<typeof setTimeout> | undefined;
if (requestTimeoutMs) {
abortController = new AbortController();
abortTimeout = setTimeout(abortController.abort, requestTimeoutMs);
abortTimeout = setTimeout(() => controller.abort(), requestTimeoutMs);
}

return fetch(url, {
...restInit,
headers,
signal: abortController?.signal,
signal: controller?.signal,
}).finally(() => {
if (abortTimeout) {
clearTimeout(abortTimeout);
}
clearTimeout(abortTimeout);
});
}
FETCH_CACHE.set(client, fetchWithHeaders);
Expand Down

0 comments on commit 7362ad0

Please sign in to comment.