From e3727532533a3e7c9689683102e5b08b2d05c97f Mon Sep 17 00:00:00 2001 From: Afo Date: Sat, 17 Aug 2024 04:08:47 -0700 Subject: [PATCH 1/3] updated contracts prettier, foundry toml, and solhint added javascript files to generate accounts added env example --- .vscode/settings.json | 9 ++ packages/contracts/.editorconfig | 19 +++ packages/contracts/.env.example | 6 + packages/contracts/.gitignore | 45 +++--- packages/contracts/.prettierignore | 20 ++- packages/contracts/.prettierrc.json | 8 +- packages/contracts/.solhint.json | 11 +- packages/contracts/foundry.toml | 38 +++-- packages/contracts/package.json | 15 +- packages/contracts/remappings.txt | 2 +- packages/contracts/script/ListAccount.js | 77 ++++++++++ packages/contracts/script/generateAccount.js | 49 ++++++ packages/contracts/script/generateTsAbis.js | 148 +++++++++++++++++++ pnpm-workspace.yaml | 1 - 14 files changed, 397 insertions(+), 51 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 packages/contracts/.editorconfig create mode 100644 packages/contracts/.env.example create mode 100644 packages/contracts/script/ListAccount.js create mode 100644 packages/contracts/script/generateAccount.js create mode 100644 packages/contracts/script/generateTsAbis.js diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..241108b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "[solidity]": { + "editor.defaultFormatter": "NomicFoundation.hardhat-solidity" + }, + "[toml]": { + "editor.defaultFormatter": "tamasfe.even-better-toml" + }, + "solidity.formatter": "forge" +} diff --git a/packages/contracts/.editorconfig b/packages/contracts/.editorconfig new file mode 100644 index 0000000..746ae31 --- /dev/null +++ b/packages/contracts/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# All files +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.sol] +indent_size = 4 + +[*.tree] +indent_size = 1 diff --git a/packages/contracts/.env.example b/packages/contracts/.env.example new file mode 100644 index 0000000..1751c4a --- /dev/null +++ b/packages/contracts/.env.example @@ -0,0 +1,6 @@ +export API_KEY_ALCHEMY="YOUR_API_KEY_ALCHEMY" +export API_KEY_ARBISCAN="YOUR_API_KEY_ARBISCAN" +export API_KEY_INFURA="YOUR_API_KEY_INFURA" +export PRIVATE_KEY="YOUR_MNEMONIC" +export FOUNDRY_PROFILE="default" +MTYD6JKP478CAYEWAERTS7ANBN5MN43QTP \ No newline at end of file diff --git a/packages/contracts/.gitignore b/packages/contracts/.gitignore index 63973dc..19f25ad 100644 --- a/packages/contracts/.gitignore +++ b/packages/contracts/.gitignore @@ -1,35 +1,24 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -# dependencies - +# directories +cache +coverage node_modules -dist -dev-dist -.DS_Store -DS_Store - -node_modules -/.pnp -.pnp.js - +out -# production - -build - -# local env files - -.env\*.local -.env +# files +*.env +*.log +.DS_Store +.pnp.* +lcov.info +package-lock.json +pnpm-lock.yaml +yarn.lock -# forge -out/ -cache/ -cache_hardhat/ -node_modules/ -bindings/ -artifacts/ +# broadcasts +!broadcast +broadcast/* +broadcast/*/31337/ -# Ignore MUD deploy artifacts -deploys/**/*.json diff --git a/packages/contracts/.prettierignore b/packages/contracts/.prettierignore index 25bb65f..3996d20 100644 --- a/packages/contracts/.prettierignore +++ b/packages/contracts/.prettierignore @@ -1,5 +1,17 @@ -dist -node_modules -contracts/out -contracts/cache +# directories +broadcast cache +coverage +node_modules +out + +# files +*.env +*.log +.DS_Store +.pnp.* +bun.lockb +lcov.info +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/packages/contracts/.prettierrc.json b/packages/contracts/.prettierrc.json index d3be6d2..44c8b9a 100644 --- a/packages/contracts/.prettierrc.json +++ b/packages/contracts/.prettierrc.json @@ -1,5 +1,9 @@ { + "bracketSpacing": true, + "printWidth": 120, + "proseWrap": "always", + "singleQuote": false, "tabWidth": 2, - "useTabs": false, - "trailingComma": "all" + "trailingComma": "all", + "useTabs": false } diff --git a/packages/contracts/.solhint.json b/packages/contracts/.solhint.json index 0ff4bbe..311f3d1 100644 --- a/packages/contracts/.solhint.json +++ b/packages/contracts/.solhint.json @@ -2,10 +2,17 @@ "extends": ["solhint:recommended"], "plugins": [], "rules": { - "compiler-version": ["error", ">=0.8.0"], + "code-complexity": ["error", 8], + "compiler-version": ["error", ">=0.8.25"], + "func-name-mixedcase": "off", + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 120], + "named-parameters-mapping": "warn", + "no-console": "off", + "not-rely-on-time": "off", + "one-contract-per-file": true, "avoid-low-level-calls": "off", "no-inline-assembly": "off", - "func-visibility": ["warn", { "ignoreConstructors": true }], "no-empty-blocks": "off", "no-complex-fallback": "off" } diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml index aa29f55..62a9cb5 100644 --- a/packages/contracts/foundry.toml +++ b/packages/contracts/foundry.toml @@ -1,18 +1,38 @@ [profile.default] -solc = '0.8.21' +solc = "0.8.25" ffi = false -fuzz_runs = 256 +auto_detect_solc = false +block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT +bytecode_hash = "none" +evm_version = "shanghai" +fuzz = { runs = 1_000 } +gas_reports = ["*"] optimizer = true -optimizer_runs = 3000 +optimizer_runs = 10_000 verbosity = 2 +libs = ['lib'] +out = 'out' +script = "script" src = 'src' test = 'test' -out = 'out' -libs = ['lib'] -allow_paths = [ - # pnpm symlinks to the project root's node_modules - "../../node_modules", -] + +[profile.ci] + fuzz = { runs = 10_000 } + verbosity = 4 + +[etherscan] + arbitrum = { key = "${API_KEY_ARBISCAN}" } + +[fmt] + bracket_spacing = true + int_types = "long" + line_length = 120 + multiline_func_header = "all" + number_underscore = "thousands" + quote_style = "double" + tab_width = 4 + wrap_comments = true + extra_output_files = [ "abi", "evm.bytecode" diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 3ed97fb..bbc897b 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -4,6 +4,9 @@ "private": true, "description": "Contracts for Protocol", "scripts": { + "account": "node script/ListAccount.js", + "chain": "anvil --config-out localhost.json", + "compile": "forge compile", "dev": "forge build", "prettier": "prettier --write 'src/**/*.sol'", "solhint": "solhint --config ./.solhint.json 'src/**/*.sol' --fix", @@ -18,11 +21,15 @@ "@ethereum-attestation-service/eas-contracts": "1.7.1" }, "devDependencies": { + "@types/prettier": "2", + "@types/qrcode": "1", + "envfile": "~6.18.0", + "qrcode": "~1.5.3", + "toml": "~3.0.0", "solidity-coverage": "^0.8.12", - "solhint": "^5.0.1", - "ds-test": "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0", - "forge-std": "https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1", + "solhint": "^5.0.3", + "forge-std": "github:foundry-rs/forge-std#v1.8.1", "prettier": "^3.3.3", - "prettier-plugin-solidity": "^1.3.1" + "prettier-plugin-solidity": "^1.4.0" } } diff --git a/packages/contracts/remappings.txt b/packages/contracts/remappings.txt index 32d0ded..40554eb 100644 --- a/packages/contracts/remappings.txt +++ b/packages/contracts/remappings.txt @@ -1,6 +1,6 @@ @openzeppelin/contracts=./node_modules/@openzeppelin/contracts/ @openzeppelin/contracts-upgradeable=./node_modules/@openzeppelin/contracts-upgradeable/ eas-contracts=./node_modules/@ethereum-attestation-service/eas-contracts/contracts/ -forge-std=./node_modules/forge-std/src/ +forge-std/=node_modules/forge-std/src/ ds-test=./node_modules/ds-test/src/ tokenbound=./lib/tokenbound/src/ \ No newline at end of file diff --git a/packages/contracts/script/ListAccount.js b/packages/contracts/script/ListAccount.js new file mode 100644 index 0000000..20493b3 --- /dev/null +++ b/packages/contracts/script/ListAccount.js @@ -0,0 +1,77 @@ +const dotenv = require("dotenv"); +dotenv.config(); +const path = require("path"); +const { ethers, Wallet } = require("ethers"); +const QRCode = require("qrcode"); +const fs = require("fs"); +const toml = require("toml"); + +const ALCHEMY_API_KEY = + process.env.ALCHEMY_API_KEY || "oKxs-03sij-U_N0iOlrSsZFr29-IqbuF"; + +async function getBalanceForEachNetwork(address) { + try { + // Read the foundry.toml file + const foundryTomlPath = path.join(__dirname, "..", "foundry.toml"); + const tomlString = fs.readFileSync(foundryTomlPath, "utf-8"); + + // Parse the tomlString to get the JS object representation + const parsedToml = toml.parse(tomlString); + + // Extract rpc_endpoints from parsedToml + const rpcEndpoints = parsedToml.rpc_endpoints; + + // Replace placeholders in the rpc_endpoints section + function replaceENVAlchemyKey(input) { + return input.replace("${ALCHEMY_API_KEY}", ALCHEMY_API_KEY); + } + + for (const networkName in rpcEndpoints) { + if (networkName === "localhost" || networkName === "default_network") + continue; + + const networkUrl = replaceENVAlchemyKey(rpcEndpoints[networkName]); + + try { + const provider = new ethers.providers.JsonRpcProvider(networkUrl); + const balance = await provider.getBalance(address); + console.log("--", networkName, "-- 📡"); + console.log(" balance:", +ethers.utils.formatEther(balance)); + console.log( + " nonce:", + +(await provider.getTransactionCount(address)) + ); + } catch (e) { + console.log("Can't connect to network", networkName); + console.log(); + } + } + } catch (error) { + console.error("Error reading foundry.toml:", error); + } +} +async function main() { + const privateKey = process.env.DEPLOYER_PRIVATE_KEY; + + if (!privateKey) { + console.log( + "🚫️ You don't have a deployer account. Run `yarn generate` first" + ); + return; + } + + // Get account from private key. + const wallet = new Wallet(privateKey); + const address = wallet.address; + console.log( + await QRCode.toString(address, { type: "terminal", small: true }) + ); + console.log("Public address:", address, "\n"); + + await getBalanceForEachNetwork(address); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/packages/contracts/script/generateAccount.js b/packages/contracts/script/generateAccount.js new file mode 100644 index 0000000..d6b2be3 --- /dev/null +++ b/packages/contracts/script/generateAccount.js @@ -0,0 +1,49 @@ +const ethers = require("ethers"); +const { parse, stringify } = require("envfile"); +const fs = require("fs"); + +const envFilePath = "./.env"; + +/** + * Generate a new random private key and write it to the .env file + * @param existingEnvConfig + */ +const setNewEnvConfig = (existingEnvConfig = {}) => { + console.log("👛 Generating new Wallet"); + const randomWallet = ethers.Wallet.createRandom(); + + const newEnvConfig = { + ...existingEnvConfig, + DEPLOYER_PRIVATE_KEY: randomWallet.privateKey, + }; + + // Store in .env + fs.writeFileSync(envFilePath, stringify(newEnvConfig)); + console.log("📄 Private Key saved to packages/foundry/.env file"); + console.log("🪄 Generated wallet address:", randomWallet.address); +}; + +async function main() { + if (!fs.existsSync(envFilePath)) { + console.log("entered here"); + // No .env file yet. + setNewEnvConfig(); + return; + } + + // .env file exists + const existingEnvConfig = parse(fs.readFileSync(envFilePath).toString()); + if (existingEnvConfig.DEPLOYER_PRIVATE_KEY) { + console.log( + "⚠️ You already have a deployer account. Check the packages/foundry/.env file" + ); + return; + } + + setNewEnvConfig(existingEnvConfig); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/packages/contracts/script/generateTsAbis.js b/packages/contracts/script/generateTsAbis.js new file mode 100644 index 0000000..699c914 --- /dev/null +++ b/packages/contracts/script/generateTsAbis.js @@ -0,0 +1,148 @@ +const fs = require("fs"); +const path = require("path"); +//@ts-expect-error This script runs after `forge deploy` therefore its deterministic that it will present +// const deployments = require("../deployments.json"); +const prettier = require("prettier"); + +const generatedContractComment = ` +/** + * This file is autogenerated by Scaffold-ETH. + * You should not edit it manually or your changes might be overwritten. + */ +`; + +function getDirectories(path) { + return fs.readdirSync(path).filter(function (file) { + return fs.statSync(path + "/" + file).isDirectory(); + }); +} +function getFiles(path) { + return fs.readdirSync(path).filter(function (file) { + return fs.statSync(path + "/" + file).isFile(); + }); +} +function getArtifactOfContract(contractName) { + const current_path_to_artifacts = path.join( + __dirname, + "..", + `out/${contractName}.sol` + ); + const artifactJson = JSON.parse( + fs.readFileSync(`${current_path_to_artifacts}/${contractName}.json`) + ); + + return artifactJson; +} + +function getInheritedFromContracts(artifact) { + let inheritedFromContracts = []; + if (artifact?.ast) { + for (const astNode of artifact.ast.nodes) { + if (astNode.nodeType == "ContractDefinition") { + if (astNode.baseContracts.length > 0) { + inheritedFromContracts = astNode.baseContracts.map( + ({ baseName }) => baseName.name + ); + } + } + } + } + return inheritedFromContracts; +} + +function getInheritedFunctions(mainArtifact) { + const inheritedFromContracts = getInheritedFromContracts(mainArtifact); + const inheritedFunctions = {}; + for (const inheritanceContractName of inheritedFromContracts) { + const { + abi, + ast: { absolutePath }, + } = getArtifactOfContract(inheritanceContractName); + for (const abiEntry of abi) { + if (abiEntry.type == "function") { + inheritedFunctions[abiEntry.name] = absolutePath; + } + } + } + return inheritedFunctions; +} + +function main() { + const current_path_to_broadcast = path.join( + __dirname, + "..", + "broadcast/Deploy.s.sol" + ); + const current_path_to_deployments = path.join(__dirname, "..", "deployments"); + + const chains = getDirectories(current_path_to_broadcast); + const Deploymentchains = getFiles(current_path_to_deployments); + + const deployments = {}; + + Deploymentchains.forEach((chain) => { + if (!chain.endsWith(".json")) return; + chain = chain.slice(0, -5); + var deploymentObject = JSON.parse( + fs.readFileSync(`${current_path_to_deployments}/${chain}.json`) + ); + deployments[chain] = deploymentObject; + }); + + const allGeneratedContracts = {}; + + chains.forEach((chain) => { + allGeneratedContracts[chain] = {}; + const broadCastObject = JSON.parse( + fs.readFileSync(`${current_path_to_broadcast}/${chain}/run-latest.json`) + ); + const transactionsCreate = broadCastObject.transactions.filter( + (transaction) => transaction.transactionType == "CREATE" + ); + transactionsCreate.forEach((transaction) => { + const artifact = getArtifactOfContract(transaction.contractName); + allGeneratedContracts[chain][ + deployments[chain][transaction.contractAddress] || + transaction.contractName + ] = { + address: transaction.contractAddress, + abi: artifact.abi, + inheritedFunctions: getInheritedFunctions(artifact), + }; + }); + }); + + const TARGET_DIR = "../nextjs/contracts/"; + + const fileContent = Object.entries(allGeneratedContracts).reduce( + (content, [chainId, chainConfig]) => { + return `${content}${parseInt(chainId).toFixed(0)}:${JSON.stringify( + chainConfig, + null, + 2 + )},`; + }, + "" + ); + + if (!fs.existsSync(TARGET_DIR)) { + fs.mkdirSync(TARGET_DIR); + } + fs.writeFileSync( + `${TARGET_DIR}deployedContracts.ts`, + prettier.format( + `${generatedContractComment} import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; \n\n + const deployedContracts = {${fileContent}} as const; \n\n export default deployedContracts satisfies GenericContractsDeclaration`, + { + parser: "typescript", + } + ) + ); +} + +try { + main(); +} catch (error) { + console.error(error); + process.exitCode = 1; +} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a108dfa..924b55f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,2 @@ packages: - packages/* - - packages/clients/* From 40341c962fbc71c0f91416ff4944383c1e510bf2 Mon Sep 17 00:00:00 2001 From: Afo Date: Sat, 17 Aug 2024 18:53:43 -0700 Subject: [PATCH 2/3] updates to remapping added openzeppelin node module added pinata keys to env example --- package.json | 8 ++++---- packages/app/.env.example | 5 +++-- packages/contracts/package.json | 4 +++- packages/contracts/remappings.txt | 8 ++++---- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 3caee6c..d3db60b 100644 --- a/package.json +++ b/package.json @@ -28,12 +28,12 @@ "dependencies": { "dotenv": "16.4.5", "ethers": "^6.13.2", - "viem": "^2.19.2" + "viem": "^2.19.6" }, "devDependencies": { - "concurrently": "8.2.1", - "prettier": "^3.0.3", - "typescript": "^5.2.2", + "concurrently": "8.2.2", + "prettier": "^3.3.3", + "typescript": "^5.5.4", "wait-port": "1.1.0" }, "engines": { diff --git a/packages/app/.env.example b/packages/app/.env.example index 6e15834..7257c6f 100644 --- a/packages/app/.env.example +++ b/packages/app/.env.example @@ -2,6 +2,7 @@ VITE_ALCHEMY_API_KEY= VITE_PRIVY_API_KEY= VITE_PIMLICO_API_KEY= +VITE_PINATA_API_KEY= - - +PINATA_API_SECRET= +PINATA_API_JWT= \ No newline at end of file diff --git a/packages/contracts/package.json b/packages/contracts/package.json index bbc897b..d7bbac3 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -18,7 +18,9 @@ "deploy:arbitrum-sepolia": "source .env && FOUNDRY_PROFILE=arbitrum-sepolia forge script script/ArbitrumSepolia.s.sol:ArbitrumScript --private-key $FORGE_PRIVATE_KEY --etherscan-api-key $ETHERSCAN_API_KEY --broadcast" }, "dependencies": { - "@ethereum-attestation-service/eas-contracts": "1.7.1" + "@ethereum-attestation-service/eas-contracts": "1.7.1", + "@openzeppelin/contracts": "4.8.3", + "@openzeppelin/contracts-upgradeable": "4.8.3" }, "devDependencies": { "@types/prettier": "2", diff --git a/packages/contracts/remappings.txt b/packages/contracts/remappings.txt index 40554eb..9fad027 100644 --- a/packages/contracts/remappings.txt +++ b/packages/contracts/remappings.txt @@ -1,6 +1,6 @@ +ds-test=./node_modules/ds-test/src/ +forge-std=./node_modules/forge-std/src/ @openzeppelin/contracts=./node_modules/@openzeppelin/contracts/ @openzeppelin/contracts-upgradeable=./node_modules/@openzeppelin/contracts-upgradeable/ -eas-contracts=./node_modules/@ethereum-attestation-service/eas-contracts/contracts/ -forge-std/=node_modules/forge-std/src/ -ds-test=./node_modules/ds-test/src/ -tokenbound=./lib/tokenbound/src/ \ No newline at end of file +@eas=./node_modules/@ethereum-attestation-service/eas-contracts/contracts/ +@tokenbound=./lib/tokenbound/src/ From 45bc75e927dd3e8432dc038ad51573219f5de456 Mon Sep 17 00:00:00 2001 From: Afo Date: Sat, 17 Aug 2024 18:56:20 -0700 Subject: [PATCH 3/3] some copilot updates for spacing and uneeded strings --- packages/contracts/.env.example | 3 +-- packages/contracts/foundry.toml | 2 +- packages/contracts/script/ListAccount.js | 19 +++++-------------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/packages/contracts/.env.example b/packages/contracts/.env.example index 1751c4a..298ee4a 100644 --- a/packages/contracts/.env.example +++ b/packages/contracts/.env.example @@ -2,5 +2,4 @@ export API_KEY_ALCHEMY="YOUR_API_KEY_ALCHEMY" export API_KEY_ARBISCAN="YOUR_API_KEY_ARBISCAN" export API_KEY_INFURA="YOUR_API_KEY_INFURA" export PRIVATE_KEY="YOUR_MNEMONIC" -export FOUNDRY_PROFILE="default" -MTYD6JKP478CAYEWAERTS7ANBN5MN43QTP \ No newline at end of file +export FOUNDRY_PROFILE="default" \ No newline at end of file diff --git a/packages/contracts/foundry.toml b/packages/contracts/foundry.toml index 62a9cb5..9ae44c3 100644 --- a/packages/contracts/foundry.toml +++ b/packages/contracts/foundry.toml @@ -30,7 +30,7 @@ test = 'test' multiline_func_header = "all" number_underscore = "thousands" quote_style = "double" - tab_width = 4 + tab_width = 2 wrap_comments = true extra_output_files = [ diff --git a/packages/contracts/script/ListAccount.js b/packages/contracts/script/ListAccount.js index 20493b3..8f51217 100644 --- a/packages/contracts/script/ListAccount.js +++ b/packages/contracts/script/ListAccount.js @@ -6,8 +6,7 @@ const QRCode = require("qrcode"); const fs = require("fs"); const toml = require("toml"); -const ALCHEMY_API_KEY = - process.env.ALCHEMY_API_KEY || "oKxs-03sij-U_N0iOlrSsZFr29-IqbuF"; +const ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY || "oKxs-03sij-U_N0iOlrSsZFr29-IqbuF"; async function getBalanceForEachNetwork(address) { try { @@ -27,8 +26,7 @@ async function getBalanceForEachNetwork(address) { } for (const networkName in rpcEndpoints) { - if (networkName === "localhost" || networkName === "default_network") - continue; + if (networkName === "localhost" || networkName === "default_network") continue; const networkUrl = replaceENVAlchemyKey(rpcEndpoints[networkName]); @@ -37,10 +35,7 @@ async function getBalanceForEachNetwork(address) { const balance = await provider.getBalance(address); console.log("--", networkName, "-- 📡"); console.log(" balance:", +ethers.utils.formatEther(balance)); - console.log( - " nonce:", - +(await provider.getTransactionCount(address)) - ); + console.log(" nonce:", +(await provider.getTransactionCount(address))); } catch (e) { console.log("Can't connect to network", networkName); console.log(); @@ -54,18 +49,14 @@ async function main() { const privateKey = process.env.DEPLOYER_PRIVATE_KEY; if (!privateKey) { - console.log( - "🚫️ You don't have a deployer account. Run `yarn generate` first" - ); + console.log("🚫️ You don't have a deployer account. Run `yarn generate` first"); return; } // Get account from private key. const wallet = new Wallet(privateKey); const address = wallet.address; - console.log( - await QRCode.toString(address, { type: "terminal", small: true }) - ); + console.log(await QRCode.toString(address, { type: "terminal", small: true })); console.log("Public address:", address, "\n"); await getBalanceForEachNetwork(address);