Compare commits

..
Author SHA1 Message Date
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
52f827e8f2 Version Packages (#2586)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-03-29 11:37:16 -07:00
Jonas DanielsandGitHub 6063f40f87 fix(cli): fix execution on windows and when prettier is not installed (#2587) 2024-03-29 18:16:38 +00:00
YashandGitHub 6bd1b82a58 [CLI] Publish and deploy updates for ZKSync (#2584) 2024-03-29 17:12:50 +00:00
Manan TankandGitHub 052892b396 [v5] Fix WC session request (#2585) 2024-03-29 17:09:06 +00:00
53 changed files with 611 additions and 139 deletions
+7
View File
@@ -1,5 +1,12 @@
# @thirdweb-dev/auth
## 4.1.51
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.4.29
## 4.1.50
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "4.1.50",
"version": "4.1.51",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
+11
View File
@@ -1,5 +1,16 @@
# thirdweb
## 0.13.59
### Patch Changes
- [#2584](https://github.com/thirdweb-dev/js/pull/2584) [`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0) Thanks [@kumaryash90](https://github.com/kumaryash90)! - cli changes for zksync publish
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/wallets@2.4.29
- @thirdweb-dev/auth@4.1.51
## 0.13.58
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/cli",
"main": "dist/cli/index.js",
"version": "0.13.58",
"version": "0.13.59",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+1
View File
@@ -377,6 +377,7 @@ const main = async () => {
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.option("--zksync", "Publish with ZKSync settings")
.option(
"--link-lib <library:address...>",
"Specify library names and addresses",
+111 -5
View File
@@ -61,9 +61,7 @@ export async function processProject(
logger.debug("Processing project at path " + projectPath);
const projectType = options.zksync
? "hardhat"
: await detect(projectPath, options);
const projectType = await detect(projectPath, options);
if (projectType === "none") {
if (command === "deploy") {
@@ -106,9 +104,25 @@ export async function processProject(
}
let compiledResult: { contracts: ContractPayload[] };
let zkCompiledResult: { contracts: ContractPayload[] };
const compileLoader = spinner("Compiling project...");
try {
compiledResult = await build(projectPath, projectType, options);
if (options.zksync) {
zkCompiledResult = await build(projectPath, "zk-hardhat", options);
if (
compiledResult.contracts.length !== zkCompiledResult.contracts.length
) {
logger.error(
"Length mismatch: zksolc and solc compiled contracts differ.",
);
process.exit(1);
}
} else {
zkCompiledResult = { contracts: [] };
}
} catch (e) {
compileLoader.fail("Compilation failed");
logger.error(e);
@@ -223,6 +237,23 @@ export async function processProject(
process.exit(1);
}
let zkSelectedContracts: ContractPayload[] = [];
if (options.zksync) {
const fileNames = selectedContracts.map((selected) => selected.fileName);
zkSelectedContracts = zkCompiledResult.contracts.filter((contract) => {
const index = fileNames.indexOf(contract.fileName);
return index !== -1;
});
if (zkSelectedContracts.length !== selectedContracts.length) {
info(
"Selected contract not present in zksolc compiled contracts. Aborting.",
);
process.exit(1);
}
}
if (options.dryRun) {
info("Dry run, skipping deployment");
process.exit(0);
@@ -332,6 +363,81 @@ export async function processProject(
metadataUri: metadataURIs[i],
bytecodeUri: bytecodeURIs[i],
analytics,
compilers: {
solc: [
{
compilerVersion: compiledResult.contracts[0].compilerVersion,
evmVersion: compiledResult.contracts[0].evmVersion,
metadataUri: metadataURIs[i],
bytecodeUri: bytecodeURIs[i],
},
],
},
};
});
}
// upload zk-contracts if present
if (zkSelectedContracts.length > 0) {
for (let i = 0; i < zkSelectedContracts.length; i++) {
const contract = zkSelectedContracts[i];
if (contract.sources) {
// upload sources in batches to avoid getting rate limited (needs to be single uploads)
const batchSize = 3;
for (let j = 0; j < contract.sources.length; j = j + batchSize) {
const batch = contract.sources.slice(j, j + batchSize);
logger.debug(`Uploading Sources:\n${batch.join("\n")}\n`);
await Promise.all(
batch.map(async (c) => {
const file = readFileSync(c, "utf-8");
if (file.includes(soliditySDKPackage)) {
usesSoliditySDK = true;
}
return await storage.upload(file, {
uploadWithoutDirectory: true,
});
}),
);
}
}
}
// Upload build output metadatas (need to be single uploads)
const zkMetadataURIs = await Promise.all(
zkSelectedContracts.map(async (c) => {
logger.debug(`Uploading ${c.name}...`);
return await storage.upload(JSON.parse(JSON.stringify(c.metadata)), {
uploadWithoutDirectory: true,
});
}),
);
// Upload batch all bytecodes
const zkBytecodes = zkSelectedContracts.map((c) => c.bytecode);
const zkBytecodeURIs = await storage.uploadBatch(zkBytecodes);
combinedContents = combinedContents.map((c, i) => {
return {
...c,
compilers: {
zksolc: [
{
compilerVersion: zkCompiledResult.contracts[0].compilerVersion,
evmVersion: zkCompiledResult.contracts[0].evmVersion,
metadataUri: zkMetadataURIs[i],
bytecodeUri: zkBytecodeURIs[i],
},
],
solc: [
{
compilerVersion: compiledResult.contracts[0].compilerVersion,
evmVersion: compiledResult.contracts[0].evmVersion,
metadataUri: metadataURIs[i],
bytecodeUri: bytecodeURIs[i],
},
],
},
};
});
}
@@ -362,8 +468,8 @@ export function getUrl(hashes: string[], command: string) {
if (hashes.length === 1) {
url = new URL(
THIRDWEB_URL +
`/contracts/${command}/` +
encodeURIComponent(hashes[0].replace("ipfs://", "")),
`/contracts/${command}/` +
encodeURIComponent(hashes[0].replace("ipfs://", "")),
);
} else {
url = new URL(THIRDWEB_URL + "/contracts/" + command);
@@ -56,6 +56,8 @@ export class BrownieBuilder extends BaseBuilder {
sources: [], // TODO
fileName: "", // TODO
name: contractName,
compilerVersion: "",
evmVersion: "",
});
break;
}
@@ -5,6 +5,7 @@ import { FoundryBuilder } from "./foundry";
import { HardhatBuilder } from "./hardhat";
import { SolcBuilder } from "./solc";
import { TruffleBuilder } from "./truffle";
import { ZKHardhatBuilder } from "./zkHardhat";
export default async function build(
path: string,
@@ -19,6 +20,10 @@ export default async function build(
builder = new HardhatBuilder();
break;
}
case "zk-hardhat": {
builder = new ZKHardhatBuilder();
break;
}
case "foundry": {
builder = new FoundryBuilder();
break;
@@ -107,6 +107,9 @@ export class FoundryBuilder extends BaseBuilder {
contractInfo.rawMetadata ||
this.sanitizeParsedMetadata(parsedMetadata, contractInfo.abi);
const evmVersion = metadata.settings?.evmVersion || "";
const compilerVersion = metadata.compiler?.version || "";
const sources = Object.keys(parsedMetadata.sources)
.map((path) => {
if (path.startsWith("/") && existsSync(path)) {
@@ -146,6 +149,8 @@ export class FoundryBuilder extends BaseBuilder {
bytecode,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
+10 -29
View File
@@ -36,22 +36,7 @@ export class HardhatBuilder extends BaseBuilder {
logger.debug("successfully extracted hardhat config", actualHardhatConfig);
await execute("npx hardhat clean", options.projectPath);
let ignoreIpfsHash = false;
if (options.zksync) {
const zkNetwork = Object.entries(actualHardhatConfig.networks).find(
(network) => {
return (network[1] as any).zksync;
},
);
ignoreIpfsHash = (zkNetwork?.[1] as any).zksync; // IPFS hash can't be recovered from ZKSync bytecode
await execute(
`npx hardhat compile --network ${zkNetwork?.[0]}`,
options.projectPath,
);
} else {
await execute(`npx hardhat compile`, options.projectPath);
}
await execute(`npx hardhat compile`, options.projectPath);
const solcConfigs = actualHardhatConfig.solidity.compilers;
if (solcConfigs) {
@@ -127,7 +112,7 @@ export class HardhatBuilder extends BaseBuilder {
}
let bytecode = info.evm.bytecode.object;
let deployedBytecode = info.evm.deployedBytecode?.object || bytecode;
let deployedBytecode = info.evm.deployedBytecode.object;
// link external libraries if any
bytecode = linkLibrary(bytecode, libraries);
@@ -135,9 +120,10 @@ export class HardhatBuilder extends BaseBuilder {
const { metadata, abi } = info;
const meta = metadata.solc_metadata
? JSON.parse(metadata.solc_metadata)
: JSON.parse(metadata);
const meta = JSON.parse(metadata);
const evmVersion = meta.settings?.evmVersion || "";
const compilerVersion = meta.compiler?.version || "";
const sources = Object.keys(meta.sources)
.map((path) => {
const directPath = join(options.projectPath, path);
@@ -165,20 +151,15 @@ export class HardhatBuilder extends BaseBuilder {
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (
this.shouldProcessContract(
abi,
deployedBytecode,
contractName,
ignoreIpfsHash,
)
) {
if (this.shouldProcessContract(abi, deployedBytecode, contractName)) {
contracts.push({
metadata: JSON.stringify(meta),
metadata,
bytecode,
name: contractName,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
@@ -116,6 +116,9 @@ export class SolcBuilder extends BaseBuilder {
const parsedMetadata = JSON.parse(metadata);
const abi = parsedMetadata.output.abi;
const evmVersion = parsedMetadata.settings?.evmVersion || "";
const compilerVersion = parsedMetadata.compiler?.version || "";
const target = parsedMetadata.settings.compilationTarget;
if (
Object.keys(target).length === 0 ||
@@ -156,6 +159,8 @@ export class SolcBuilder extends BaseBuilder {
name: contractName,
fileName,
sources: _sources,
compilerVersion,
evmVersion,
});
}
}
@@ -13,10 +13,9 @@ export class TruffleBuilder extends BaseBuilder {
}> {
// get the current config first
// eslint-disable-next-line @typescript-eslint/no-var-requires
const truffleConfig = require(join(
options.projectPath,
"truffle-config.js",
));
const truffleConfig = require(
join(options.projectPath, "truffle-config.js"),
);
const buildPath = join(
options.projectPath,
@@ -42,6 +41,9 @@ export class TruffleBuilder extends BaseBuilder {
const meta = JSON.parse(metadata);
const abi = meta.output.abi;
const evmVersion = meta.settings?.evmVersion || "";
const compilerVersion = meta.compiler?.version || "";
const target = meta.settings.compilationTarget;
if (
Object.keys(target).length === 0 ||
@@ -81,6 +83,8 @@ export class TruffleBuilder extends BaseBuilder {
name: contractName,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
@@ -0,0 +1,171 @@
import { findFiles } from "../../common/file-helper";
import { execute } from "../helpers/exec";
import { logger } from "../helpers/logger";
import { ContractPayload } from "../interfaces/ContractPayload";
import { BaseBuilder } from "./builder-base";
import { existsSync, readFileSync } from "fs";
import { HardhatConfig } from "hardhat/types";
import { join, resolve } from "path";
export class ZKHardhatBuilder extends BaseBuilder {
public async compile(options: any): Promise<{
contracts: ContractPayload[];
}> {
//we get our very own extractor script from the dir that we're in during execution
// this is `./dist/cli` (for all purposes of the CLI)
// then we look up the hardhat config extractor file path from there
const configExtractorScriptPath = resolve(
__dirname,
"../helpers/hardhat-config-extractor.js",
);
//the hardhat extractor **logs out** the runtime config of hardhat, we take that stdout and parse it
const stringifiedConfig = (
await execute(
`npx hardhat run "${configExtractorScriptPath}" --no-compile`,
options.projectPath,
)
).stdout;
//voila the hardhat config
const actualHardhatConfig = JSON.parse(
stringifiedConfig.split("__tw__")[1],
) as HardhatConfig;
logger.debug("successfully extracted hardhat config", actualHardhatConfig);
await execute("npx hardhat clean", options.projectPath);
let ignoreIpfsHash = false;
const zkNetwork = Object.entries(actualHardhatConfig.networks).find(
(network) => {
return (network[1] as any).zksync;
},
);
if (!(zkNetwork?.[1] as any).zksync) {
logger.warn("ZKSync settings not found. Aborting.");
process.exit(1);
}
ignoreIpfsHash = (zkNetwork?.[1] as any).zksync; // IPFS hash can't be recovered from ZKSync bytecode
await execute(
`npx hardhat compile --network ${zkNetwork?.[0]}`,
options.projectPath,
);
const artifactsPath = actualHardhatConfig.paths.artifacts;
const sourcesDir = actualHardhatConfig.paths.sources.replace(
options.projectPath,
"",
);
const contractsPath = join(artifactsPath, sourcesDir);
const contracts: ContractPayload[] = [];
const files: string[] = [];
findFiles(contractsPath, /^.*(?<!dbg)\.json$/, files);
const buildOutputPath = join(artifactsPath, "build-info");
const buildFiles: string[] = [];
findFiles(buildOutputPath, /^.*(?<!dbg)\.json$/, buildFiles);
for (const buildFile of buildFiles) {
const buildJsonFile = readFileSync(buildFile, "utf-8");
const buildJson = JSON.parse(buildJsonFile);
const contractBuildOutputs = buildJson.output.contracts;
for (const [contractPath, contractInfos] of Object.entries(
contractBuildOutputs,
)) {
if (contractPath.includes("@")) {
// skip library contracts
logger.debug("Skipping", contractPath, "(not a source target)");
continue;
}
for (const [contractName, contractInfo] of Object.entries(
contractInfos as any,
)) {
const info = contractInfo as any;
if (
!info.evm ||
!info.evm.bytecode ||
!info.evm.bytecode.object ||
!info.metadata ||
!info.abi
) {
logger.debug("Skipping", contractPath, "(no bytecode or metadata)");
continue;
}
const bytecode = info.evm.bytecode.object;
const deployedBytecode =
info.evm.deployedBytecode?.object || bytecode;
const { metadata, abi } = info;
const meta = metadata.solc_metadata
? JSON.parse(metadata.solc_metadata)
: JSON.parse(metadata);
// Find and add zk_version to solc_metadata settings - needed for verification
// TODO: it's a workaround. remove it (e.g. when ipfs hash issue is resolved)
const zkVersion = metadata.zk_version;
meta.settings["zkVersion"] = zkVersion;
const evmVersion = meta.settings?.evmVersion || "";
const compilerVersion = zkVersion || "";
const sources = Object.keys(meta.sources)
.map((path) => {
const directPath = join(options.projectPath, path);
if (existsSync(directPath)) {
return directPath;
}
const sourcePath = join(options.projectPath, sourcesDir, path);
if (existsSync(sourcePath)) {
return sourcePath;
}
const nodeModulesPath = join(
options.projectPath,
"node_modules",
path,
);
if (existsSync(nodeModulesPath)) {
return nodeModulesPath;
}
return undefined;
})
.filter((path) => path !== undefined) as string[];
const fileNames = Object.keys(
meta?.settings?.compilationTarget || {},
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (
this.shouldProcessContract(
abi,
deployedBytecode,
contractName,
ignoreIpfsHash,
)
) {
contracts.push({
metadata: JSON.stringify(meta),
bytecode,
name: contractName,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
}
}
return {
contracts,
};
}
}
@@ -27,6 +27,17 @@ export default async function detect(
.filter((detector) => detector.matches(path))
.map((detector) => detector.projectType);
if (options.zksync) {
const hardhatProject = possibleProjectTypes.filter(
(projectType) => projectType === "hardhat",
);
if (hardhatProject.length === 0) {
logger.warn("ZKSync compilation requires hardhat plugins. Aborting.");
process.exit(1);
}
}
//if there is no project returned at all then just return unknown}
if (!possibleProjectTypes.length) {
const canCompile = hasContracts(path);
@@ -51,15 +62,28 @@ export default async function detect(
}
//if there is only one possible option just return it
if (possibleProjectTypes.length === 1) {
info(`Detected project type: ${possibleProjectTypes[0]}`);
if (options.zksync) {
info("ZKSync compilation will use hardhat");
} else {
info(`Detected project type: ${possibleProjectTypes[0]}`);
}
return possibleProjectTypes[0];
}
info(
`Detected multiple possible build tools: ${possibleProjectTypes
.map((s) => `"${s}"`)
.join(", ")}`,
);
if (options.zksync) {
info("ZKSync compilation will use hardhat");
info(
`For regular solc compilation, these are the available options: ${possibleProjectTypes
.map((s) => `"${s}"`)
.join(", ")}`,
);
} else {
info(
`Detected multiple possible build tools: ${possibleProjectTypes
.map((s) => `"${s}"`)
.join(", ")}`,
);
}
const question = "How would you like to compile your contracts";
@@ -26,4 +26,8 @@ export interface ContractPayload {
* The source file paths
*/
sources: string[];
compilerVersion: string;
evmVersion: string;
}
@@ -2,6 +2,7 @@ export type ProjectType =
| "brownie"
| "foundry"
| "hardhat"
| "zk-hardhat"
| "truffle"
| "solc"
| "vite"
+9
View File
@@ -1,5 +1,14 @@
# @thirdweb-dev/react-core
## 4.4.27
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/wallets@2.4.29
- @thirdweb-dev/auth@4.1.51
## 4.4.26
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "4.4.26",
"version": "4.4.27",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -1,5 +1,7 @@
# @thirdweb-dev/react-native-compat
## 0.7.24
## 0.7.23
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/react-native-compat",
"description": "Shims for Thirdweb in React Native Projects",
"version": "0.7.23",
"version": "0.7.24",
"author": "thirdweb eng <[email protected]>",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-native-compat",
"license": "Apache-2.0",
@@ -1,5 +1,14 @@
# @thirdweb-dev/react-native
## 0.7.24
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/react-core@4.4.27
- @thirdweb-dev/wallets@2.4.29
## 0.7.23
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.7.23",
"version": "0.7.24",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-native",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+9
View File
@@ -1,5 +1,14 @@
# @thirdweb-dev/react
## 4.4.27
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/react-core@4.4.27
- @thirdweb-dev/wallets@2.4.29
## 4.4.26
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "4.4.26",
"version": "4.4.27",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
Binary file not shown.
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/sdk
## 4.0.53
### Patch Changes
- [#2584](https://github.com/thirdweb-dev/js/pull/2584) [`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0) Thanks [@kumaryash90](https://github.com/kumaryash90)! - cli changes for zksync publish
## 4.0.52
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "4.0.52",
"version": "4.0.53",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/sdk",
"license": "Apache-2.0",
@@ -487,6 +487,7 @@ export class ContractPublisher extends RPCConnectionHandler {
bytecodeUri: predeployMetadata.bytecodeUri,
name: predeployMetadata.name,
analytics: predeployMetadata.analytics,
compilers: predeployMetadata.compilers,
publisher,
});
const fullMetadataUri = await this.storage.upload(fullMetadata);
@@ -112,6 +112,14 @@ export type Abi = z.output<typeof AbiSchema>;
*/
export type AbiInput = z.input<typeof AbiSchema>;
/**
* @internal
*/
export const CompilerTypeInput = /* @__PURE__ */ (() =>
z.union([z.literal("solc"), z.literal("zksolc")]))();
export type CompilerType = z.input<typeof CompilerTypeInput>;
/**
* @internal
*/
@@ -122,6 +130,21 @@ export const PreDeployMetadata = /* @__PURE__ */ (() =>
metadataUri: z.string(),
bytecodeUri: z.string(),
analytics: z.any().optional(),
compilers: z
.record(
CompilerTypeInput,
// z.record(
z.array(
z.object({
compilerVersion: z.string().optional(),
evmVersion: z.string().optional(),
metadataUri: z.string(),
bytecodeUri: z.string(),
}),
),
// ),
)
.optional(),
})
.catchall(z.any()))();
@@ -6,9 +6,9 @@ import { getChainProvider } from "../constants/urls";
import { Abi } from "../schema/contracts/custom";
import { twProxyArtifactZK } from "./temp-artifact/TWProxy";
import { fetchSourceFilesFromMetadata } from "../common/fetchSourceFilesFromMetadata";
import { fetchRawPredeployMetadata } from "../common/feature-detection/fetchRawPredeployMetadata";
import { fetchContractMetadata } from "../common/fetchContractMetadata";
import { checkVerificationStatus } from "../common/verification";
import { ThirdwebSDK } from "../core/sdk";
const RequestStatus = {
OK: "1",
@@ -27,7 +27,8 @@ export async function zkVerify(
explorerAPIUrl: string,
explorerAPIKey: string,
storage: ThirdwebStorage,
contractUri?: string,
metadataUri?: string,
zkVersion?: string,
encodedConstructorArgs?: string,
) {
try {
@@ -43,18 +44,24 @@ export async function zkVerify(
};
compilerMetadata.metadata.sources = twProxyArtifactZK.sources;
} else {
invariant(contractUri, "No contract URI provided");
const rawMeta = await fetchRawPredeployMetadata(contractUri, storage);
const metadataUri = rawMeta.compilers?.zksolc?.metadataUri;
if (!metadataUri || metadataUri.length === 0) {
metadataUri = await fetchFromMultiChainRegistry(
contractAddress,
chainId,
);
}
invariant(metadataUri && metadataUri.length > 0, "No contract URI found");
invariant(metadataUri, "ZkSolc metadata not found");
const parsedMetadata = await fetchContractMetadata(metadataUri, storage);
const zk_version =
parsedMetadata.metadata.settings.zk_version || zkVersion;
invariant(zk_version, "zk version not found");
compilerMetadata = {
name: parsedMetadata.name,
abi: parsedMetadata.abi,
metadata: parsedMetadata.metadata,
zk_version: rawMeta.zk_version,
zk_version,
};
}
@@ -172,13 +179,28 @@ async function zkFetchConstructorParams(
utils.hexDataSlice(transaction.data, 4),
);
return decoded[2];
return decoded[2].startsWith("0x") ? decoded[2] : `0x${decoded[2]}`;
} else {
// TODO: decode for create2 deployments via factory
return "";
return "0x";
}
} else {
// Could not retrieve constructor parameters, using empty parameters as fallback
return "";
return "0x";
}
}
async function fetchFromMultiChainRegistry(
address: string,
chainId: number,
): Promise<string | undefined> {
try {
// random wallet is fine here, we're doing gasless calls
const sdk = new ThirdwebSDK("polygon");
const uri = await sdk.multiChainRegistry.getContractMetadataURI(
chainId,
address,
);
return uri;
} catch (e) {}
}
Binary file not shown.
+7
View File
@@ -1,5 +1,12 @@
# @thirdweb-dev/wallets
## 2.4.29
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
## 2.4.28
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/wallets",
"version": "2.4.28",
"version": "2.4.29",
"main": "dist/thirdweb-dev-wallets.cjs.js",
"module": "dist/thirdweb-dev-wallets.esm.js",
"browser": {
+8
View File
@@ -1,5 +1,13 @@
# thirdweb
## 5.0.2
### Patch Changes
- [#2585](https://github.com/thirdweb-dev/js/pull/2585) [`052892b`](https://github.com/thirdweb-dev/js/commit/052892b39677755b3167da7520d48446a5ce7c59) Thanks [@MananTank](https://github.com/MananTank)! - Fix wallet not opened on WC sessions request event on page reload on mobile
- [#2587](https://github.com/thirdweb-dev/js/pull/2587) [`6063f40`](https://github.com/thirdweb-dev/js/commit/6063f40f87b2a108840cb08e1e9025542931b7e0) Thanks [@jnsdls](https://github.com/jnsdls)! - [CLI] - fix execution on windows and when prettier is not installed
## 5.0.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "thirdweb",
"version": "5.0.1",
"version": "5.0.2",
"repository": {
"type": "git",
"url": "git+https://github.com/thirdweb-dev/js.git#main"
+29 -11
View File
@@ -23,21 +23,39 @@ async function main() {
}
default: {
const isWindows = /^win/.test(process.platform);
let bunAvailable = false;
try {
const res = execSync("bun --version", {
stdio: "ignore",
encoding: "utf-8",
});
if (typeof res === "string" && res.indexOf(".") > -1) {
bunAvailable = true;
// bun has no windows support yet anyways
if (!isWindows) {
try {
const res = execSync("bun --version", {
stdio: "ignore",
encoding: "utf-8",
});
if (typeof res === "string" && res.indexOf(".") > -1) {
bunAvailable = true;
}
} catch {
bunAvailable = false;
}
} catch {
bunAvailable = false;
}
const runner = bunAvailable ? "bunx" : "npx";
let runner = "npx";
switch (true) {
case bunAvailable:
runner = "bun";
break;
case isWindows:
runner = "npx.cmd";
break;
}
const args = command
? ["--yes", "@thirdweb-dev/cli@latest", command, ...rest]
: ["--yes", "@thirdweb-dev/cli@latest", ...rest];
// eslint-disable-next-line better-tree-shaking/no-top-level-side-effects
spawn(runner, ["--yes", "@thirdweb-dev/cli@latest", command, ...rest], {
spawn(runner, args, {
stdio: "inherit",
});
}
@@ -12,12 +12,13 @@ import {
type AbiFunction,
formatAbiItem,
} from "abitype";
import { format } from "prettier";
import { prepareMethod } from "../../../utils/abi/prepare-method.js";
import { mkdir, writeFile } from "node:fs/promises";
import { packageDirectory } from "./utils.js";
import { join } from "node:path";
import { existsSync } from "node:fs";
import type { Options } from "prettier";
const client = createThirdwebClient({ clientId: "test" });
@@ -150,7 +151,7 @@ async function generateFromAbi(abi: Abi | string[]) {
);
}
const prettified = await format(body, {
const prettified = await prettifyCode(body, {
parser: "babel-ts",
});
return prettified;
@@ -330,3 +331,18 @@ function lowercaseFirstLetter(str: string) {
function eventNameToPreparedEventName(name: string) {
return `${lowercaseFirstLetter(name)}Event`;
}
const printedPrettierWarning = false;
async function prettifyCode(code: string, options: Options) {
try {
const { format } = await import("prettier/standalone.js");
return await format(code, options);
} catch (e) {
if (!printedPrettierWarning) {
console.info("Prettier not found, skipping code formatting.");
}
}
return code;
}
@@ -1,22 +0,0 @@
import { isAndroid, isIOS } from "./isMobile.js";
import { openWindow } from "./openWindow.js";
export type PlatformURIs = {
android: string;
ios: string;
other: string;
};
/**
*
* @internal
*/
export function handelWCSessionRequest(uris: PlatformURIs) {
if (isAndroid()) {
openWindow(uris.android);
} else if (isIOS()) {
openWindow(uris.ios);
} else {
openWindow(uris.other);
}
}
@@ -8,7 +8,7 @@ import { StyledDiv } from "../design-system/elements.js";
import { Container } from "./basic.js";
import { Text } from "./text.js";
import type { IconFC } from "../ConnectWallet/icons/types.js";
import { isMobile } from "../../../core/utils/isMobile.js";
import { isMobile } from "../../../../utils/web/isMobile.js";
/**
* @internal
@@ -1,5 +1,4 @@
import { useState } from "react";
import { isMobile } from "../../../core/utils/isMobile.js";
import { QRCode } from "../../ui/components/QRCode.js";
import { Spacer } from "../../ui/components/Spacer.js";
import { Container, ModalHeader } from "../../ui/components/basic.js";
@@ -10,12 +9,13 @@ import { AppleIcon } from "../../ui/ConnectWallet/icons/AppleIcon.js";
import { ChromeIcon } from "../../ui/ConnectWallet/icons/ChromeIcon.js";
import { PlayStoreIcon } from "../../ui/ConnectWallet/icons/PlayStoreIcon.js";
import { Text } from "../../ui/components/text.js";
import { openWindow } from "../../../core/utils/openWindow.js";
import type { InjectedWalletLocale } from "../injected/locale/types.js";
import type { WalletInfo } from "../../../../wallets/wallet-info.js";
import { WalletImage } from "../../ui/components/WalletImage.js";
import type { WalletId } from "../../../../wallets/wallet-types.js";
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
import { isMobile } from "../../../../utils/web/isMobile.js";
import { openWindow } from "../../../../utils/web/openWindow.js";
/**
* @internal
@@ -1,14 +1,13 @@
import { ScanScreen } from "./ScanScreen.js";
import { useState, useRef, useEffect, useCallback } from "react";
import { isAndroid, isIOS, isMobile } from "../../../core/utils/isMobile.js";
import { handelWCSessionRequest } from "../../../core/utils/handleWCSessionRequest.js";
import { ConnectingScreen } from "./ConnectingScreen.js";
import { openWindow } from "../../../core/utils/openWindow.js";
import { useWalletConnectionCtx } from "../../../core/hooks/others/useWalletConnectionCtx.js";
import type { InjectedWalletLocale } from "../injected/locale/types.js";
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
import type { WalletInfo } from "../../../../wallets/wallet-info.js";
import type { WCSupportedWalletIds } from "../../../../wallets/__generated__/wallet-ids.js";
import { isMobile, isAndroid, isIOS } from "../../../../utils/web/isMobile.js";
import { openWindow } from "../../../../utils/web/openWindow.js";
/**
* QR Scan UI for connecting a specific wallet on desktop.
@@ -31,16 +30,6 @@ export const WalletConnectConnection: React.FC<{
const connect = useCallback(() => {
setErrorConnecting(false);
const platformUris = {
ios: walletInfo.mobile.native || "",
android: walletInfo.mobile.universal || "",
other: walletInfo.mobile.universal || "",
};
const onSessionRequestSent = isMobile()
? () => handelWCSessionRequest(platformUris)
: undefined;
wallet
.connect({
chain,
@@ -49,6 +38,12 @@ export const WalletConnectConnection: React.FC<{
projectId: walletConnect?.projectId,
showQrModal: false,
onDisplayUri(uri) {
const platformUris = {
ios: walletInfo.mobile.native || "",
android: walletInfo.mobile.universal || "",
other: walletInfo.mobile.universal || "",
};
setQrCodeUri(uri);
if (isMobile()) {
if (isAndroid()) {
@@ -66,7 +61,6 @@ export const WalletConnectConnection: React.FC<{
}
}
},
onSessionRequestSent,
optionalChains: chains,
},
})
@@ -1,4 +1,4 @@
import { detectOS } from "../../../utils/detect-platform.js";
import { detectOS } from "../detect-platform.js";
/**
* @internal
+14 -3
View File
@@ -6,7 +6,10 @@ import type {
import type { Account, Wallet } from "./interfaces/wallet.js";
import type { Chain } from "../chains/types.js";
import { injectedProvider } from "./injected/mipdStore.js";
import type { InjectedSupportedWalletIds } from "./__generated__/wallet-ids.js";
import type {
InjectedSupportedWalletIds,
WCSupportedWalletIds,
} from "./__generated__/wallet-ids.js";
import { createWalletEmitter } from "./wallet-emitter.js";
import { trackConnect } from "../analytics/track.js";
@@ -131,7 +134,11 @@ export function createWallet<const ID extends WalletId>(
connectedChain,
doDisconnect,
doSwitchChain,
] = await autoConnectWC(options, emitter);
] = await autoConnectWC(
options,
emitter,
wallet.id as WCSupportedWalletIds,
);
// set the states
account = connectedAccount;
chain = connectedChain;
@@ -157,7 +164,11 @@ export function createWallet<const ID extends WalletId>(
connectedChain,
doDisconnect,
doSwitchChain,
] = await connectWC(options, emitter);
] = await connectWC(
options,
emitter,
wallet.id as WCSupportedWalletIds,
);
// set the states
account = connectedAccount;
chain = connectedChain;
@@ -25,6 +25,9 @@ import { getDefaultAppMetadata } from "../utils/defaultDappMetadata.js";
import type { WCSupportedWalletIds } from "../__generated__/wallet-ids.js";
import type { DisconnectFn, SwitchChainFn } from "../types.js";
import type { WalletEmitter } from "../wallet-emitter.js";
import { isAndroid, isIOS, isMobile } from "../../utils/web/isMobile.js";
import { openWindow } from "../../utils/web/openWindow.js";
import { getWalletInfo } from "../__generated__/getWalletInfo.js";
type WCProvider = InstanceType<typeof EthereumProvider>;
@@ -42,8 +45,9 @@ const defaultShowQrModal = true;
export async function connectWC(
options: WCConnectOptions,
emitter: WalletEmitter<WCSupportedWalletIds>,
walletId: WCSupportedWalletIds,
): Promise<ReturnType<typeof onConnect>> {
const provider = await initProvider(options);
const provider = await initProvider(options, walletId);
const wcOptions = options.walletConnect;
const targetChain = options?.chain || ethereum;
@@ -54,22 +58,12 @@ export async function connectWC(
client: options.client,
});
const { onDisplayUri, onSessionRequestSent } = wcOptions || {};
const { onDisplayUri } = wcOptions || {};
if (onDisplayUri || onSessionRequestSent) {
if (onDisplayUri) {
if (onDisplayUri) {
provider.events.addListener("display_uri", onDisplayUri);
}
if (onSessionRequestSent) {
provider.signer.client.on("session_request_sent", onSessionRequestSent);
provider.events.addListener("disconnect", () => {
provider.signer.client.off(
"session_request_sent",
onSessionRequestSent,
);
});
}
}
// If there no active session, or the chain is stale, force connect.
@@ -106,6 +100,7 @@ export async function connectWC(
export async function autoConnectWC(
options: WCAutoConnectOptions,
emitter: WalletEmitter<WCSupportedWalletIds>,
walletId: WCSupportedWalletIds,
): Promise<ReturnType<typeof onConnect>> {
const provider = await initProvider(
options.savedConnectParams
@@ -121,6 +116,7 @@ export async function autoConnectWC(
client: options.client,
walletConnect: {},
},
walletId,
);
const address = provider.accounts[0];
@@ -153,7 +149,11 @@ export async function autoConnectWC(
// Connection utils -----------------------------------------------------------------------------------------------
async function initProvider(options: WCConnectOptions) {
async function initProvider(
options: WCConnectOptions,
walletId: WCSupportedWalletIds,
) {
const walletInfo = await getWalletInfo(walletId);
const wcOptions = options.walletConnect;
const { EthereumProvider, OPTIONAL_EVENTS, OPTIONAL_METHODS } = await import(
"@walletconnect/ethereum-provider"
@@ -192,6 +192,34 @@ async function initProvider(options: WCConnectOptions) {
disableProviderPing: true,
});
function handleSessionRequest() {
if (typeof window === "undefined") {
return;
}
if (!isMobile()) {
return;
}
const preferUniversal =
walletInfo.mobile.universal || walletInfo.mobile.native || "";
const preferNative =
walletInfo.mobile.native || walletInfo.mobile.universal || "";
if (isAndroid()) {
openWindow(preferUniversal);
} else if (isIOS()) {
openWindow(preferNative);
} else {
openWindow(preferUniversal);
}
}
provider.signer.client.on("session_request_sent", handleSessionRequest);
provider.events.addListener("disconnect", () => {
provider.signer.client.off("session_request_sent", handleSessionRequest);
});
provider.events.setMaxListeners(Infinity);
return provider;
@@ -131,11 +131,6 @@ export type WCConnectOptions = {
* ```
*/
onDisplayUri?: (uri: string) => void;
/**
* Callback to be called to listen to the `session_request_sent` event emitted by WalletConnect's `EthereumProvider`.
* This can be used to
*/
onSessionRequestSent?: () => void;
/**
* Your project’s unique identifier that can be obtained at https://cloud.walletconnect.com/
Binary file not shown.
+9
View File
@@ -1,5 +1,14 @@
# @thirdweb-dev/unity-js-bridge
## 0.6.2
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/wallets@2.4.29
- @thirdweb-dev/auth@4.1.51
## 0.6.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/unity-js-bridge",
"version": "0.6.1",
"version": "0.6.2",
"main": "dist/thirdweb-unity-bridge.js",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
"license": "Apache-2.0",