From ecb2e16b110650dd465963e31da55e32dad4adfb Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 12:30:11 +0200 Subject: [PATCH 01/46] base setup and simple send spec --- .circleci/config.yml | 19 ++ lavamoat/browserify/beta/policy.json | 18 +- lavamoat/browserify/flask/policy.json | 18 +- lavamoat/browserify/main/policy.json | 18 +- lavamoat/browserify/mmi/policy.json | 18 +- package.json | 2 + test/e2e/helpers.js | 23 ++ test/e2e/seeder/anvil-clients.ts | 49 +++++ test/e2e/seeder/anvil.ts | 126 +++++++++++ .../e2e/tests/transaction/simple-send.spec.ts | 6 +- yarn.lock | 206 +++++++++++++++++- 11 files changed, 463 insertions(+), 40 deletions(-) create mode 100644 test/e2e/seeder/anvil-clients.ts create mode 100644 test/e2e/seeder/anvil.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index 095650aae02d..11d6d7ec007f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -202,44 +202,55 @@ workflows: requires: - prep-build-test-webpack - get-changed-files-with-git-diff + - prep-test-deps - test-e2e-chrome: requires: - prep-build-test - get-changed-files-with-git-diff + - prep-test-deps - test-e2e-firefox: requires: - prep-build-test-mv2 - get-changed-files-with-git-diff + - prep-test-deps - test-e2e-chrome-rpc: requires: - prep-build-test - get-changed-files-with-git-diff + - prep-test-deps - test-api-specs: requires: - prep-build-test + - prep-test-deps - test-e2e-chrome-multiple-providers: requires: - prep-build-test - get-changed-files-with-git-diff + - prep-test-deps - test-e2e-chrome-flask: requires: - prep-build-test-flask - get-changed-files-with-git-diff + - prep-test-deps - test-e2e-firefox-flask: <<: *develop_master_rc_only requires: - prep-build-test-flask-mv2 + - prep-test-deps - test-e2e-chrome-mmi: requires: - prep-build-test-mmi - get-changed-files-with-git-diff + - prep-test-deps - test-e2e-mmi-playwright - OPTIONAL: requires: - prep-build-test-mmi-playwright + - prep-test-deps - test-e2e-chrome-rpc-mmi: requires: - prep-build-test-mmi - get-changed-files-with-git-diff + - prep-test-deps - test-e2e-chrome-vault-decryption: filters: branches: @@ -248,6 +259,7 @@ workflows: - /^Version-v(\d+)[.](\d+)[.](\d+)/ requires: - prep-build + - prep-test-deps - test-storybook: requires: - prep-deps @@ -491,6 +503,13 @@ jobs: - node_modules - build-artifacts + prep-test-deps: + executor: node-browsers-medium + steps: + - run: + name: Install Foundry package for Anvil Testing Dependency + command: curl -L https://foundry.paradigm.xyz | bash + # This job is used for the e2e quality gate. # It must be run before any job which uses the run-all.js script. # The job is skipped in develop, master or RC branches. diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index b27b95f111a4..665623c5abc7 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -174,16 +174,9 @@ "crypto": true }, "packages": { - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true - } - }, - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": { - "packages": { - "@metamask/message-signing-snap>@noble/curves": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "@noble/hashes": true, + "viem>@scure/bip32": true } }, "@ethersproject/abi": { @@ -5520,6 +5513,13 @@ "msCrypto": true } }, + "viem>@scure/bip32": { + "packages": { + "@metamask/message-signing-snap>@noble/curves": true, + "@metamask/utils>@scure/base": true, + "@noble/hashes": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index b27b95f111a4..665623c5abc7 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -174,16 +174,9 @@ "crypto": true }, "packages": { - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true - } - }, - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": { - "packages": { - "@metamask/message-signing-snap>@noble/curves": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "@noble/hashes": true, + "viem>@scure/bip32": true } }, "@ethersproject/abi": { @@ -5520,6 +5513,13 @@ "msCrypto": true } }, + "viem>@scure/bip32": { + "packages": { + "@metamask/message-signing-snap>@noble/curves": true, + "@metamask/utils>@scure/base": true, + "@noble/hashes": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index b27b95f111a4..665623c5abc7 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -174,16 +174,9 @@ "crypto": true }, "packages": { - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true - } - }, - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": { - "packages": { - "@metamask/message-signing-snap>@noble/curves": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "@noble/hashes": true, + "viem>@scure/bip32": true } }, "@ethersproject/abi": { @@ -5520,6 +5513,13 @@ "msCrypto": true } }, + "viem>@scure/bip32": { + "packages": { + "@metamask/message-signing-snap>@noble/curves": true, + "@metamask/utils>@scure/base": true, + "@noble/hashes": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 56b9dc57a34a..ecda3ca6bd19 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -174,16 +174,9 @@ "crypto": true }, "packages": { - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true - } - }, - "@ethereumjs/tx>ethereum-cryptography>@scure/bip32": { - "packages": { - "@metamask/message-signing-snap>@noble/curves": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "@noble/hashes": true, + "viem>@scure/bip32": true } }, "@ethersproject/abi": { @@ -5588,6 +5581,13 @@ "msCrypto": true } }, + "viem>@scure/bip32": { + "packages": { + "@metamask/message-signing-snap>@noble/curves": true, + "@metamask/utils>@scure/base": true, + "@noble/hashes": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/package.json b/package.json index 34a022f2d8d6..722eafb1d2a4 100644 --- a/package.json +++ b/package.json @@ -544,6 +544,7 @@ "@types/yargs-parser": "^21.0.3", "@typescript-eslint/eslint-plugin": "^7.10.0", "@typescript-eslint/parser": "^7.10.0", + "@viem/anvil": "^0.0.10", "@welldone-software/why-did-you-render": "^8.0.3", "@whitespace/storybook-addon-html": "^5.1.6", "addons-linter": "^6.28.0", @@ -668,6 +669,7 @@ "tsx": "^4.7.1", "ttest": "^2.1.1", "typescript": "~5.4.5", + "viem": "^2.21.8", "vinyl": "^2.2.1", "vinyl-buffer": "^1.0.1", "vinyl-source-stream": "^2.0.0", diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 15fc5eff1ade..518c087725eb 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -9,6 +9,7 @@ const createStaticServer = require('../../development/create-static-server'); const { tEn } = require('../lib/i18n-helpers'); const { setupMocking } = require('./mock-e2e'); const { Ganache } = require('./seeder/ganache'); +const { LocalNetwork } = require('./seeder/anvil'); const FixtureServer = require('./fixture-server'); const PhishingWarningPageServer = require('./phishing-warning-page-server'); const { buildWebDriver } = require('./webdriver'); @@ -59,6 +60,8 @@ const convertETHToHexGwei = (eth) => convertToHexValue(eth * 10 ** 18); */ async function withFixtures(options, testSuite) { const { + anvil, + anvilOptions, dapp, fixtures, ganacheOptions, @@ -85,6 +88,12 @@ async function withFixtures(options, testSuite) { if (!disableGanache) { ganacheServer = new Ganache(); } + + let anvilServer; + if (anvil) { + anvilServer = new LocalNetwork(); + } + const bundlerServer = new Bundler(); const https = await mockttp.generateCACertificate(); const mockServer = mockttp.getLocal({ https, cors: true }); @@ -104,6 +113,11 @@ async function withFixtures(options, testSuite) { if (!disableGanache) { await ganacheServer.start(ganacheOptions); } + + if (anvil) { + await anvilServer.start(anvilOptions); + } + let contractRegistry; if (smartContract && !disableGanache) { @@ -305,6 +319,10 @@ async function withFixtures(options, testSuite) { await ganacheServer.quit(); } + if (anvil) { + await anvilServer.quit(); + } + if (ganacheOptions?.concurrent) { secondaryGanacheServer.forEach(async (server) => { await server.quit(); @@ -784,6 +802,10 @@ const defaultGanacheOptions = { ], }; +const defaultAnvilOptions = { + balance: 25, +}; + const defaultGanacheOptionsForType2Transactions = { ...defaultGanacheOptions, // EVM version that supports type 2 transactions (EIP1559) @@ -1269,6 +1291,7 @@ module.exports = { connectToDapp, multipleGanacheOptions, defaultGanacheOptions, + defaultAnvilOptions, defaultGanacheOptionsForType2Transactions, multipleGanacheOptionsForType2Transactions, sendTransaction, diff --git a/test/e2e/seeder/anvil-clients.ts b/test/e2e/seeder/anvil-clients.ts new file mode 100644 index 000000000000..d1691d844e2d --- /dev/null +++ b/test/e2e/seeder/anvil-clients.ts @@ -0,0 +1,49 @@ +import { + createPublicClient, + createTestClient, + createWalletClient, + http, +} from 'viem'; + +const anvil = { + id: 1337, + name: 'Localhost', + nativeCurrency: { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + rpcUrls: { + default: { + http: ['http://127.0.0.1:8545'], + webSocket: ['ws://127.0.0.1:8545'], + }, + }, +}; + +type Instance = { + host: string; + port: number; +}; + +function createAnvilClients(instance: Instance) { + const publicClient = createPublicClient({ + chain: anvil, + transport: http(`http://${instance.host}:${instance.port}`), + }); + + const testClient = createTestClient({ + chain: anvil, + mode: 'anvil', + transport: http(`http://${instance.host}:${instance.port}`), + }); + + const walletClient = createWalletClient({ + chain: anvil, + transport: http(`http://${instance.host}:${instance.port}`), + }); + + return { publicClient, testClient, walletClient }; +} + +export { createAnvilClients }; diff --git a/test/e2e/seeder/anvil.ts b/test/e2e/seeder/anvil.ts new file mode 100644 index 000000000000..ed9c01a7de1c --- /dev/null +++ b/test/e2e/seeder/anvil.ts @@ -0,0 +1,126 @@ +import { createAnvil, Anvil } from '@viem/anvil'; +import { createAnvilClients } from './anvil-clients'; + +type Hardfork = + | 'Frontier' + | 'Homestead' + | 'Dao' + | 'Tangerine' + | 'SpuriousDragon' + | 'Byzantium' + | 'Constantinople' + | 'Petersburg' + | 'Istanbul' + | 'Muirglacier' + | 'Berlin' + | 'London' + | 'ArrowGlacier' + | 'GrayGlacier' + | 'Paris' + | 'Shanghai' + | 'Latest'; + +const defaultOptions = { + host: '127.0.0.1', + port: 8545, + blockTime: 2, + chainId: 1337, + mnemonic: + 'spread raise short crane omit tent fringe mandate neglect detail suspect cradle', + hardfork: 'Muirglacier' as Hardfork, + gasLimit: 30000000, + gasPrice: 2000000000, +}; + +export class LocalNetwork { + #server: Anvil | undefined; + + async start(opts = defaultOptions): Promise { + const options = { ...defaultOptions, ...opts }; + + this.#server = createAnvil(options); + + await this.#server.start(); + } + + getProvider() { + if (!this.#server) { + throw new Error('Server not running yet'); + } + + const { walletClient, publicClient, testClient } = createAnvilClients( + this.#server, + ); + + return { walletClient, publicClient, testClient }; + } + + async getAccounts(): Promise { + const provider = this.getProvider(); + + const { walletClient } = provider; + const accounts = await walletClient.getAddresses(); + return accounts; + } + + async getBalance(address: `0x${string}` | null = null): Promise { + const provider = this.getProvider(); + + if (!provider) { + console.log('No provider found'); + return 0; + } + const { publicClient } = provider; + + const accountToUse = address || (await this.getAccounts())?.[0]; + + if (!accountToUse) { + console.log('No accounts found'); + return 0; + } + + const balanceInt = await publicClient.getBalance({ + address: accountToUse as `0x${string}`, + }); + const balanceFormatted = Number(balanceInt) / 10 ** 18; + + return balanceFormatted; + } + + async getFiatBalance(): Promise { + const balance = await this.getBalance(); + const currencyConversionRate = 1700.0; + const fiatBalance = (balance * currencyConversionRate).toFixed(2); + + return Number(fiatBalance); + } + + async setAccountBalance( + address: `0x${string}`, + balance: string, + ): Promise { + const provider = this.getProvider(); + const { testClient } = provider; + + if (!provider) { + throw new Error('No provider found'); + } + + const balanceInWei = BigInt(balance); + await testClient.setBalance({ + address, + value: balanceInWei, + }); + } + + async quit(): Promise { + if (!this.#server) { + throw new Error('Server not running yet'); + } + try { + await this.#server.stop(); + } catch (e) { + console.log('Caught error while closing Anvil network:', e); + } + } +} diff --git a/test/e2e/tests/transaction/simple-send.spec.ts b/test/e2e/tests/transaction/simple-send.spec.ts index 25a9497d6bb3..accd8d5767cc 100644 --- a/test/e2e/tests/transaction/simple-send.spec.ts +++ b/test/e2e/tests/transaction/simple-send.spec.ts @@ -1,6 +1,6 @@ import { Suite } from 'mocha'; import { Driver } from '../../webdriver/driver'; -import { withFixtures, defaultGanacheOptions } from '../../helpers'; +import { withFixtures, defaultAnvilOptions } from '../../helpers'; import FixtureBuilder from '../../fixture-builder'; import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow'; import { sendTransaction } from '../../page-objects/flows/send-transaction.flow'; @@ -11,7 +11,9 @@ describe('Simple send eth', function (this: Suite) { await withFixtures( { fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, + disableGanache: true, + anvil: true, + anvilOptions: defaultAnvilOptions, title: this.test?.fullTitle(), }, async ({ driver }: { driver: Driver }) => { diff --git a/yarn.lock b/yarn.lock index ea8a91ae8270..b8e20bb503cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -50,6 +50,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:1.10.0": + version: 1.10.0 + resolution: "@adraffy/ens-normalize@npm:1.10.0" + checksum: 10/5cdb5d2a9c9f8c0a71a7bb830967da0069cae1f1235cd41ae11147e4000f368f6958386e622cd4d52bf45c1ed3f8275056b387cba28902b83354e40ff323ecde + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" @@ -6654,6 +6661,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:1.4.0": + version: 1.4.0 + resolution: "@noble/curves@npm:1.4.0" + dependencies: + "@noble/hashes": "npm:1.4.0" + checksum: 10/b21b30a36ff02bfcc0f5e6163d245cdbaf7f640511fff97ccf83fc207ee79cfd91584b4d97977374de04cb118a55eb63a7964c82596a64162bbc42bc685ae6d9 + languageName: node + linkType: hard + "@noble/curves@npm:1.4.2, @noble/curves@npm:^1.2.0, @noble/curves@npm:^1.4.0, @noble/curves@npm:^1.4.2, @noble/curves@npm:~1.4.0": version: 1.4.2 resolution: "@noble/curves@npm:1.4.2" @@ -6691,6 +6707,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:~1.5.0": + version: 1.5.0 + resolution: "@noble/hashes@npm:1.5.0" + checksum: 10/da7fc7af52af7afcf59810a7eea6155075464ff462ffda2572dc6d57d53e2669b1ea2ec774e814f6273f1697e567f28d36823776c9bf7068cba2a2855140f26e + languageName: node + linkType: hard + "@noble/secp256k1@npm:1.6.3, @noble/secp256k1@npm:~1.6.0": version: 1.6.3 resolution: "@noble/secp256k1@npm:1.6.3" @@ -7815,6 +7838,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:~1.1.8": + version: 1.1.8 + resolution: "@scure/base@npm:1.1.8" + checksum: 10/5b764c0e98610bc4993479965db718457d91b68d3c6f1339e3cc74e53fc6b0ae0428d1d64d29a0de0cee9d966034674d4464fdbd2d1dbef27013927b2fe05c45 + languageName: node + linkType: hard + "@scure/bip32@npm:1.1.0": version: 1.1.0 resolution: "@scure/bip32@npm:1.1.0" @@ -7857,6 +7887,16 @@ __metadata: languageName: node linkType: hard +"@scure/bip39@npm:1.4.0": + version: 1.4.0 + resolution: "@scure/bip39@npm:1.4.0" + dependencies: + "@noble/hashes": "npm:~1.5.0" + "@scure/base": "npm:~1.1.8" + checksum: 10/f86e0e79768c95bc684ed6de92892b1a6f228db0f8fab836f091c0ec0f6d1e291b8c4391cfbeaa9ea83f41045613535b1940cd10e7d780a5b73db163b1e7f151 + languageName: node + linkType: hard + "@segment/loosely-validate-event@npm:^2.0.0": version: 2.0.0 resolution: "@segment/loosely-validate-event@npm:2.0.0" @@ -11441,6 +11481,18 @@ __metadata: languageName: node linkType: hard +"@viem/anvil@npm:^0.0.10": + version: 0.0.10 + resolution: "@viem/anvil@npm:0.0.10" + dependencies: + execa: "npm:^7.1.1" + get-port: "npm:^6.1.2" + http-proxy: "npm:^1.18.1" + ws: "npm:^8.13.0" + checksum: 10/8e688b9b2a7f4f90b5b7d9669bc73b20b37f05cd09646bce0fd934e582ac067bf8006c23f49d7dc0af4aa4261d863fe52730372afc0e377931da78deb1eb68bf + languageName: node + linkType: hard + "@vue/compiler-core@npm:3.1.4": version: 3.1.4 resolution: "@vue/compiler-core@npm:3.1.4" @@ -11814,6 +11866,21 @@ __metadata: languageName: node linkType: hard +"abitype@npm:1.0.5": + version: 1.0.5 + resolution: "abitype@npm:1.0.5" + peerDependencies: + typescript: ">=5.0.4" + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + checksum: 10/1acd0d9687945dd78442b71bd84ff3b9dceae27d15f0d8b14b16554a0c8c9518eeb971ff8e94d507f4d9f05a8a8b91eb8fafd735eaecebac37d5c5a4aac06d8e + languageName: node + linkType: hard + "abort-controller@npm:3.0.0": version: 3.0.0 resolution: "abort-controller@npm:3.0.0" @@ -18704,6 +18771,23 @@ __metadata: languageName: node linkType: hard +"execa@npm:^7.1.1": + version: 7.2.0 + resolution: "execa@npm:7.2.0" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^6.0.1" + human-signals: "npm:^4.3.0" + is-stream: "npm:^3.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^5.1.0" + onetime: "npm:^6.0.0" + signal-exit: "npm:^3.0.7" + strip-final-newline: "npm:^3.0.0" + checksum: 10/473feff60f9d4dbe799225948de48b5158c1723021d19c4b982afe37bcd111ae84e1b4c9dfe967fae5101b0894b1a62e4dd564a286dfa3e46d7b0cfdbf7fe62b + languageName: node + linkType: hard + "execall@npm:^2.0.0": version: 2.0.0 resolution: "execall@npm:2.0.0" @@ -20134,6 +20218,13 @@ __metadata: languageName: node linkType: hard +"get-port@npm:^6.1.2": + version: 6.1.2 + resolution: "get-port@npm:6.1.2" + checksum: 10/e3c3d591492a11393455ef220f24c812a28f7da56ec3e4a2512d931a1f196d42850b50ac6138349a44622eda6dc3c0ccd8495cd91376d968e2d9e6f6f849e0a9 + languageName: node + linkType: hard + "get-stdin@npm:^8.0.0": version: 8.0.0 resolution: "get-stdin@npm:8.0.0" @@ -20157,7 +20248,7 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^6.0.0": +"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": version: 6.0.1 resolution: "get-stream@npm:6.0.1" checksum: 10/781266d29725f35c59f1d214aedc92b0ae855800a980800e2923b3fbc4e56b3cb6e462c42e09a1cf1a00c64e056a78fa407cbe06c7c92b7e5cd49b4b85c2a497 @@ -21683,6 +21774,13 @@ __metadata: languageName: node linkType: hard +"human-signals@npm:^4.3.0": + version: 4.3.1 + resolution: "human-signals@npm:4.3.1" + checksum: 10/fa59894c358fe9f2b5549be2fb083661d5e1dff618d3ac70a49ca73495a72e873fbf6c0878561478e521e17d498292746ee391791db95ffe5747bfb5aef8765b + languageName: node + linkType: hard + "human-standard-token-abi@npm:^2.0.0": version: 2.0.0 resolution: "human-standard-token-abi@npm:2.0.0" @@ -22768,6 +22866,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: 10/172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 + languageName: node + linkType: hard + "is-string@npm:^1.0.5, is-string@npm:^1.0.7": version: 1.0.7 resolution: "is-string@npm:1.0.7" @@ -22995,6 +23100,15 @@ __metadata: languageName: node linkType: hard +"isows@npm:1.0.4": + version: 1.0.4 + resolution: "isows@npm:1.0.4" + peerDependencies: + ws: "*" + checksum: 10/a3ee62e3d6216abb3adeeb2a551fe2e7835eac87b05a6ecc3e7739259bf5f8e83290501f49e26137390c8093f207fc3378d4a7653aab76ad7bbab4b2dba9c5b9 + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.0.0-alpha.1, istanbul-lib-coverage@npm:^3.2.0": version: 3.2.0 resolution: "istanbul-lib-coverage@npm:3.2.0" @@ -26122,6 +26236,7 @@ __metadata: "@types/yargs-parser": "npm:^21.0.3" "@typescript-eslint/eslint-plugin": "npm:^7.10.0" "@typescript-eslint/parser": "npm:^7.10.0" + "@viem/anvil": "npm:^0.0.10" "@welldone-software/why-did-you-render": "npm:^8.0.3" "@whitespace/storybook-addon-html": "npm:^5.1.6" "@zxing/browser": "npm:^0.1.4" @@ -26317,6 +26432,7 @@ __metadata: typescript: "npm:~5.4.5" unicode-confusables: "npm:^0.1.1" uuid: "npm:^8.3.2" + viem: "npm:^2.21.8" vinyl: "npm:^2.2.1" vinyl-buffer: "npm:^1.0.1" vinyl-source-stream: "npm:^2.0.0" @@ -26816,6 +26932,13 @@ __metadata: languageName: node linkType: hard +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: 10/995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 + languageName: node + linkType: hard + "mimic-response@npm:^1.0.0": version: 1.0.1 resolution: "mimic-response@npm:1.0.1" @@ -27833,6 +27956,15 @@ __metadata: languageName: node linkType: hard +"npm-run-path@npm:^5.1.0": + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" + dependencies: + path-key: "npm:^4.0.0" + checksum: 10/ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 + languageName: node + linkType: hard + "nth-check@npm:^2.0.1": version: 2.0.1 resolution: "nth-check@npm:2.0.1" @@ -28149,6 +28281,15 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: "npm:^4.0.0" + checksum: 10/0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 + languageName: node + linkType: hard + "only@npm:~0.0.2": version: 0.0.2 resolution: "only@npm:0.0.2" @@ -28769,6 +28910,13 @@ __metadata: languageName: node linkType: hard +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 10/8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 + languageName: node + linkType: hard + "path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -33817,6 +33965,13 @@ __metadata: languageName: node linkType: hard +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: 10/23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 + languageName: node + linkType: hard + "strip-hex-prefix@npm:1.0.0": version: 1.0.0 resolution: "strip-hex-prefix@npm:1.0.0" @@ -36149,6 +36304,28 @@ __metadata: languageName: node linkType: hard +"viem@npm:^2.21.8": + version: 2.21.8 + resolution: "viem@npm:2.21.8" + dependencies: + "@adraffy/ens-normalize": "npm:1.10.0" + "@noble/curves": "npm:1.4.0" + "@noble/hashes": "npm:1.4.0" + "@scure/bip32": "npm:1.4.0" + "@scure/bip39": "npm:1.4.0" + abitype: "npm:1.0.5" + isows: "npm:1.0.4" + webauthn-p256: "npm:0.0.5" + ws: "npm:8.17.1" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/158976108ed04de22cd01e2897b9fe4961c0f07c04eb8f3ab87f2f73aabc59e56cf83b49979508c90c45634cb1806dd2144428c9e27c19b674461211b8fa2959 + languageName: node + linkType: hard + "vinyl-buffer@npm:^1.0.1": version: 1.0.1 resolution: "vinyl-buffer@npm:1.0.1" @@ -36470,6 +36647,16 @@ __metadata: languageName: node linkType: hard +"webauthn-p256@npm:0.0.5": + version: 0.0.5 + resolution: "webauthn-p256@npm:0.0.5" + dependencies: + "@noble/curves": "npm:^1.4.0" + "@noble/hashes": "npm:^1.4.0" + checksum: 10/6bf5d1857dfb99ecb3b318af06eddea874c10135e6ebb9f046270f5cbb162933bc6caf77aedb033e14c09971dda544a5fb367ac545e4ec8001b309ba517555cf + languageName: node + linkType: hard + "webextension-polyfill@npm:>=0.10.0 <1.0, webextension-polyfill@npm:^0.10.0": version: 0.10.0 resolution: "webextension-polyfill@npm:0.10.0" @@ -36984,7 +37171,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": +"ws@npm:*, ws@npm:8.17.1, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": version: 8.17.1 resolution: "ws@npm:8.17.1" peerDependencies: @@ -37023,6 +37210,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.13.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + languageName: node + linkType: hard + "xdg-basedir@npm:^3.0.0": version: 3.0.0 resolution: "xdg-basedir@npm:3.0.0" From 3945591002bac3da7b281f035e42ced134ef9b7f Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 12:34:42 +0200 Subject: [PATCH 02/46] config tweak --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 11d6d7ec007f..0f6152179810 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -372,6 +372,8 @@ workflows: value: << pipeline.git.branch >> jobs: - prep-deps + - prep-test-deps: + - prep-deps - get-changed-files-with-git-diff: requires: - prep-deps From 104372ef41c1936f5c2bfd27eb668294874c292c Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 12:35:39 +0200 Subject: [PATCH 03/46] add require --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0f6152179810..cda5fcd79ad9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -373,7 +373,8 @@ workflows: jobs: - prep-deps - prep-test-deps: - - prep-deps + requires: + - prep-deps - get-changed-files-with-git-diff: requires: - prep-deps From 39dcb0e38d9e88a54f2e4c28068c9e4cc29a84a4 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 13:47:11 +0200 Subject: [PATCH 04/46] fix identation --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cda5fcd79ad9..f9b1e95600ab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -373,8 +373,8 @@ workflows: jobs: - prep-deps - prep-test-deps: - requires: - - prep-deps + requires: + - prep-deps - get-changed-files-with-git-diff: requires: - prep-deps From 1c0b0ed6a600e355cfb2f20fa00211510d2db9c6 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 13:53:08 +0200 Subject: [PATCH 05/46] fix --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f9b1e95600ab..2dce78be3702 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -116,6 +116,9 @@ workflows: - prep-deps - check-pr-tag - prep-deps + - prep-test-deps: + requires: + - prep-deps - get-changed-files-with-git-diff: filters: branches: @@ -372,9 +375,6 @@ workflows: value: << pipeline.git.branch >> jobs: - prep-deps - - prep-test-deps: - requires: - - prep-deps - get-changed-files-with-git-diff: requires: - prep-deps From 04eec2b76b2d08f49f03b294f17576f27e65c946 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 14:15:22 +0200 Subject: [PATCH 06/46] add installation steps --- .circleci/config.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2dce78be3702..ab5f7d02bbf5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -511,7 +511,21 @@ jobs: steps: - run: name: Install Foundry package for Anvil Testing Dependency - command: curl -L https://foundry.paradigm.xyz | bash + command: | + #!/bin/bash + set -e + set -u + set -o pipefail + + # Install Foundry + curl -L https://foundry.paradigm.xyz | bash + + # Add Foundry to PATH + echo 'export PATH=${HOME}/.foundry/bin:$PATH' >> ~/.bashrc + source ~/.bashrc + + # Verify Foundry Installation + foundryup --version # This job is used for the e2e quality gate. # It must be run before any job which uses the run-all.js script. From 9576c519f88f34729984ee8c664ec71ca801f1a7 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 15:05:16 +0200 Subject: [PATCH 07/46] add to path --- .circleci/config.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ab5f7d02bbf5..5766aa9678f6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -517,15 +517,12 @@ jobs: set -u set -o pipefail - # Install Foundry - curl -L https://foundry.paradigm.xyz | bash - # Add Foundry to PATH - echo 'export PATH=${HOME}/.foundry/bin:$PATH' >> ~/.bashrc - source ~/.bashrc + echo "export PATH=${HOME}/.foundry/bin:${PATH}" >> $BASH_ENV + source $BASH_ENV - # Verify Foundry Installation - foundryup --version + # Install Foundry + foundryup # This job is used for the e2e quality gate. # It must be run before any job which uses the run-all.js script. From aae945a110f0f0d26ca0b947229faf059fd073e0 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 15:16:59 +0200 Subject: [PATCH 08/46] fix? --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5766aa9678f6..096f1a68eb8a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -517,6 +517,9 @@ jobs: set -u set -o pipefail + # Using Foundryup Installer + curl -L https://foundry.paradigm.xyz | bash || true + # Add Foundry to PATH echo "export PATH=${HOME}/.foundry/bin:${PATH}" >> $BASH_ENV source $BASH_ENV From 7d988ac35b54c0a1304148fea698855fe478e931 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 15:46:59 +0200 Subject: [PATCH 09/46] dedupe --- .circleci/config.yml | 58 +++++++++++++++++--------------------------- yarn.lock | 57 +++++++++++++++++++------------------------ 2 files changed, 47 insertions(+), 68 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 096f1a68eb8a..82813eb335cf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -99,6 +99,27 @@ aliases: circleci step halt fi +commands: + foundry-install: + steps: + - run: + name: Install Foundry package for Anvil Testing Dependency + command: | + #!/bin/bash + set -e + set -u + set -o pipefail + + # Using Foundryup Installer + curl -L https://foundry.paradigm.xyz | bash || true + + # Add Foundry to PATH + echo "export PATH=${HOME}/.foundry/bin:${PATH}" >> $BASH_ENV + source $BASH_ENV + + # Install Foundry + foundryup + workflows: test_and_release: when: @@ -116,9 +137,6 @@ workflows: - prep-deps - check-pr-tag - prep-deps - - prep-test-deps: - requires: - - prep-deps - get-changed-files-with-git-diff: filters: branches: @@ -205,55 +223,44 @@ workflows: requires: - prep-build-test-webpack - get-changed-files-with-git-diff - - prep-test-deps - test-e2e-chrome: requires: - prep-build-test - get-changed-files-with-git-diff - - prep-test-deps - test-e2e-firefox: requires: - prep-build-test-mv2 - get-changed-files-with-git-diff - - prep-test-deps - test-e2e-chrome-rpc: requires: - prep-build-test - get-changed-files-with-git-diff - - prep-test-deps - test-api-specs: requires: - prep-build-test - - prep-test-deps - test-e2e-chrome-multiple-providers: requires: - prep-build-test - get-changed-files-with-git-diff - - prep-test-deps - test-e2e-chrome-flask: requires: - prep-build-test-flask - get-changed-files-with-git-diff - - prep-test-deps - test-e2e-firefox-flask: <<: *develop_master_rc_only requires: - prep-build-test-flask-mv2 - - prep-test-deps - test-e2e-chrome-mmi: requires: - prep-build-test-mmi - get-changed-files-with-git-diff - - prep-test-deps - test-e2e-mmi-playwright - OPTIONAL: requires: - prep-build-test-mmi-playwright - - prep-test-deps - test-e2e-chrome-rpc-mmi: requires: - prep-build-test-mmi - get-changed-files-with-git-diff - - prep-test-deps - test-e2e-chrome-vault-decryption: filters: branches: @@ -262,7 +269,6 @@ workflows: - /^Version-v(\d+)[.](\d+)[.](\d+)/ requires: - prep-build - - prep-test-deps - test-storybook: requires: - prep-deps @@ -506,27 +512,6 @@ jobs: - node_modules - build-artifacts - prep-test-deps: - executor: node-browsers-medium - steps: - - run: - name: Install Foundry package for Anvil Testing Dependency - command: | - #!/bin/bash - set -e - set -u - set -o pipefail - - # Using Foundryup Installer - curl -L https://foundry.paradigm.xyz | bash || true - - # Add Foundry to PATH - echo "export PATH=${HOME}/.foundry/bin:${PATH}" >> $BASH_ENV - source $BASH_ENV - - # Install Foundry - foundryup - # This job is used for the e2e quality gate. # It must be run before any job which uses the run-all.js script. # The job is skipped in develop, master or RC branches. @@ -1121,6 +1106,7 @@ jobs: - run: name: Move test build to dist command: mv ./dist-test-webpack ./dist + - foundry-install - run: name: test:e2e:chrome:webpack command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:chrome:webpack diff --git a/yarn.lock b/yarn.lock index b8e20bb503cb..466d21fb84d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6686,13 +6686,20 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.4.0, @noble/hashes@npm:^1.1.2, @noble/hashes@npm:^1.2.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.3.2, @noble/hashes@npm:^1.3.3, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:~1.4.0": +"@noble/hashes@npm:1.4.0, @noble/hashes@npm:~1.4.0": version: 1.4.0 resolution: "@noble/hashes@npm:1.4.0" checksum: 10/e156e65794c473794c52fa9d06baf1eb20903d0d96719530f523cc4450f6c721a957c544796e6efd0197b2296e7cd70efeb312f861465e17940a3e3c7e0febc6 languageName: node linkType: hard +"@noble/hashes@npm:^1.1.2, @noble/hashes@npm:^1.2.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.3.2, @noble/hashes@npm:^1.3.3, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:~1.5.0": + version: 1.5.0 + resolution: "@noble/hashes@npm:1.5.0" + checksum: 10/da7fc7af52af7afcf59810a7eea6155075464ff462ffda2572dc6d57d53e2669b1ea2ec774e814f6273f1697e567f28d36823776c9bf7068cba2a2855140f26e + languageName: node + linkType: hard + "@noble/hashes@npm:~1.1.1": version: 1.1.3 resolution: "@noble/hashes@npm:1.1.3" @@ -6707,13 +6714,6 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:~1.5.0": - version: 1.5.0 - resolution: "@noble/hashes@npm:1.5.0" - checksum: 10/da7fc7af52af7afcf59810a7eea6155075464ff462ffda2572dc6d57d53e2669b1ea2ec774e814f6273f1697e567f28d36823776c9bf7068cba2a2855140f26e - languageName: node - linkType: hard - "@noble/secp256k1@npm:1.6.3, @noble/secp256k1@npm:~1.6.0": version: 1.6.3 resolution: "@noble/secp256k1@npm:1.6.3" @@ -7831,14 +7831,7 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.0.0, @scure/base@npm:^1.1.1, @scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6": - version: 1.1.7 - resolution: "@scure/base@npm:1.1.7" - checksum: 10/fc50ffaab36cb46ff9fa4dc5052a06089ab6a6707f63d596bb34aaaec76173c9a564ac312a0b981b5e7a5349d60097b8878673c75d6cbfc4da7012b63a82099b - languageName: node - linkType: hard - -"@scure/base@npm:~1.1.8": +"@scure/base@npm:^1.0.0, @scure/base@npm:^1.1.1, @scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6, @scure/base@npm:~1.1.8": version: 1.1.8 resolution: "@scure/base@npm:1.1.8" checksum: 10/5b764c0e98610bc4993479965db718457d91b68d3c6f1339e3cc74e53fc6b0ae0428d1d64d29a0de0cee9d966034674d4464fdbd2d1dbef27013927b2fe05c45 @@ -37171,7 +37164,22 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:8.17.1, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": +"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.13.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + languageName: node + linkType: hard + +"ws@npm:8.17.1": version: 8.17.1 resolution: "ws@npm:8.17.1" peerDependencies: @@ -37210,21 +37218,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.13.0": - version: 8.18.0 - resolution: "ws@npm:8.18.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 - languageName: node - linkType: hard - "xdg-basedir@npm:^3.0.0": version: 3.0.0 resolution: "xdg-basedir@npm:3.0.0" From 4b2dcb1882011a92879e17aabeefeae5ac8c2308 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 16:06:16 +0200 Subject: [PATCH 10/46] lavamoat auto --- lavamoat/browserify/beta/policy.json | 24 +++++++++++++++++++++--- lavamoat/browserify/flask/policy.json | 24 +++++++++++++++++++++--- lavamoat/browserify/main/policy.json | 24 +++++++++++++++++++++--- lavamoat/browserify/mmi/policy.json | 24 +++++++++++++++++++++--- 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 665623c5abc7..274546889151 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -174,11 +174,17 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true, "viem>@scure/bip32": true } }, + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, "@ethersproject/abi": { "globals": { "console.log": true @@ -1660,7 +1666,13 @@ "TextEncoder": true }, "packages": { - "@noble/hashes": true + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": true + } + }, + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "@metamask/name-controller": { @@ -5517,7 +5529,13 @@ "packages": { "@metamask/message-signing-snap>@noble/curves": true, "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "viem>@scure/bip32>@noble/hashes": true + } + }, + "viem>@scure/bip32>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "web3": { diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 665623c5abc7..274546889151 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -174,11 +174,17 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true, "viem>@scure/bip32": true } }, + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, "@ethersproject/abi": { "globals": { "console.log": true @@ -1660,7 +1666,13 @@ "TextEncoder": true }, "packages": { - "@noble/hashes": true + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": true + } + }, + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "@metamask/name-controller": { @@ -5517,7 +5529,13 @@ "packages": { "@metamask/message-signing-snap>@noble/curves": true, "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "viem>@scure/bip32>@noble/hashes": true + } + }, + "viem>@scure/bip32>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "web3": { diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 665623c5abc7..274546889151 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -174,11 +174,17 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true, "viem>@scure/bip32": true } }, + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, "@ethersproject/abi": { "globals": { "console.log": true @@ -1660,7 +1666,13 @@ "TextEncoder": true }, "packages": { - "@noble/hashes": true + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": true + } + }, + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "@metamask/name-controller": { @@ -5517,7 +5529,13 @@ "packages": { "@metamask/message-signing-snap>@noble/curves": true, "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "viem>@scure/bip32>@noble/hashes": true + } + }, + "viem>@scure/bip32>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "web3": { diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index ecda3ca6bd19..71a0ca86b1cb 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -174,11 +174,17 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true, "@metamask/message-signing-snap>@noble/curves": true, - "@noble/hashes": true, "viem>@scure/bip32": true } }, + "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, "@ethersproject/abi": { "globals": { "console.log": true @@ -1752,7 +1758,13 @@ "TextEncoder": true }, "packages": { - "@noble/hashes": true + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": true + } + }, + "@metamask/message-signing-snap>@noble/curves>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "@metamask/name-controller": { @@ -5585,7 +5597,13 @@ "packages": { "@metamask/message-signing-snap>@noble/curves": true, "@metamask/utils>@scure/base": true, - "@noble/hashes": true + "viem>@scure/bip32>@noble/hashes": true + } + }, + "viem>@scure/bip32>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, "web3": { From 38b4b807b862b3d467c06cb358f4742eaf928b8a Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 18 Sep 2024 16:30:38 +0200 Subject: [PATCH 11/46] run foundry install in all test jobs --- .circleci/config.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 82813eb335cf..4a5818e2e8f5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1130,6 +1130,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test ./builds + - foundry-install - gh/install - run: name: test:api-specs @@ -1162,6 +1163,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test ./builds + - foundry-install - run: name: test:e2e:chrome command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:chrome @@ -1186,6 +1188,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test ./builds + - foundry-install - run: name: test:e2e:chrome:rpc command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:chrome:rpc @@ -1210,6 +1213,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test ./builds + - foundry-install - run: name: test:e2e:chrome:multi-provider command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:chrome:multi-provider @@ -1233,6 +1237,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test-mmi ./builds + - foundry-install - run: name: test:e2e:chrome:rpc command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:chrome:rpc --build-type=mmi @@ -1250,6 +1255,7 @@ jobs: - run: sudo corepack enable - attach_workspace: at: . + - foundry-install - run: name: test:e2e:single command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:single test/e2e/vault-decryption-chrome.spec.js --browser chrome @@ -1274,6 +1280,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test-flask-mv2 ./builds + - foundry-install - run: name: test:e2e:firefox:flask command: ENABLE_MV3=false .circleci/scripts/test-run-e2e.sh yarn test:e2e:firefox:flask @@ -1298,6 +1305,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test-flask ./builds + - foundry-install - run: name: test:e2e:chrome:flask command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:chrome:flask @@ -1322,6 +1330,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test-mmi ./builds + - foundry-install - run: name: test:e2e:chrome:mmi command: .circleci/scripts/test-run-e2e.sh yarn test:e2e:chrome:mmi --build-type=mmi @@ -1344,6 +1353,7 @@ jobs: - run: name: Move test build to dist command: mv ./dist-test-mmi-playwright ./dist + - foundry-install - run: name: Install chromium command: yarn playwright install chromium @@ -1384,6 +1394,7 @@ jobs: - run: name: Install chromium command: yarn playwright install chromium + - foundry-install - run: name: test:e2e:chrome:swap command: | @@ -1417,6 +1428,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test-mv2 ./builds + - foundry-install - run: name: test:e2e:firefox command: ENABLE_MV3=false .circleci/scripts/test-run-e2e.sh yarn test:e2e:firefox From 189fdc57058026c6301bcd51dd17b8ef73558163 Mon Sep 17 00:00:00 2001 From: seaona Date: Fri, 20 Sep 2024 11:53:34 +0200 Subject: [PATCH 12/46] anvil seeder setup --- .../snap-account-contract-interaction.spec.ts | 2 +- test/e2e/helpers.js | 86 +++++----- test/e2e/seeder/anvil-seeder.js | 149 ++++++++++++++++++ test/e2e/seeder/anvil.ts | 19 ++- ...gistry.js => contract-address-registry.js} | 6 +- test/e2e/seeder/ganache-seeder.js | 6 +- .../alerts/queued-confirmations.spec.ts | 6 +- .../contract-interaction-redesign.spec.ts | 4 +- .../increase-token-allowance-redesign.spec.ts | 4 +- .../confirmations/transactions/shared.ts | 8 +- test/e2e/tests/transaction/send-eth.spec.js | 22 +-- .../transaction/send-hex-address.spec.js | 23 ++- .../e2e/tests/transaction/simple-send.spec.ts | 5 +- 13 files changed, 240 insertions(+), 100 deletions(-) create mode 100644 test/e2e/seeder/anvil-seeder.js rename test/e2e/seeder/{ganache-contract-address-registry.js => contract-address-registry.js} (80%) diff --git a/test/e2e/accounts/snap-account-contract-interaction.spec.ts b/test/e2e/accounts/snap-account-contract-interaction.spec.ts index 4588d014802c..fb58be2550bf 100644 --- a/test/e2e/accounts/snap-account-contract-interaction.spec.ts +++ b/test/e2e/accounts/snap-account-contract-interaction.spec.ts @@ -1,4 +1,4 @@ -import GanacheContractAddressRegistry from '../seeder/ganache-contract-address-registry'; +import GanacheContractAddressRegistry from '../seeder/contract-address-registry'; import { scrollAndConfirmAndAssertConfirm } from '../tests/confirmations/helpers'; import { createDepositTransaction, diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 518c087725eb..69830db6ec0e 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -8,12 +8,13 @@ const { difference } = require('lodash'); const createStaticServer = require('../../development/create-static-server'); const { tEn } = require('../lib/i18n-helpers'); const { setupMocking } = require('./mock-e2e'); +const { Anvil } = require('./seeder/anvil'); const { Ganache } = require('./seeder/ganache'); -const { LocalNetwork } = require('./seeder/anvil'); const FixtureServer = require('./fixture-server'); const PhishingWarningPageServer = require('./phishing-warning-page-server'); const { buildWebDriver } = require('./webdriver'); const { PAGES } = require('./webdriver/driver'); +const AnvilSeeder = require('./seeder/anvil-seeder'); const GanacheSeeder = require('./seeder/ganache-seeder'); const { Bundler } = require('./bundler'); const { SMART_CONTRACTS } = require('./seeder/smart-contracts'); @@ -60,11 +61,10 @@ const convertETHToHexGwei = (eth) => convertToHexValue(eth * 10 ** 18); */ async function withFixtures(options, testSuite) { const { - anvil, - anvilOptions, dapp, fixtures, ganacheOptions, + networkOptions, smartContract, driverOptions, dappOptions, @@ -85,13 +85,13 @@ async function withFixtures(options, testSuite) { const fixtureServer = new FixtureServer(); let ganacheServer; - if (!disableGanache) { - ganacheServer = new Ganache(); - } + let localNetworkServer; - let anvilServer; - if (anvil) { - anvilServer = new LocalNetwork(); + // Temporary logic for network management until we remove ganache from all specs + if (networkOptions || (!ganacheOptions && !disableGanache)) { + localNetworkServer = new Anvil(); + } else if (!disableGanache) { + ganacheServer = new Ganache(); } const bundlerServer = new Bundler(); @@ -110,26 +110,40 @@ async function withFixtures(options, testSuite) { let driver; let failed = false; try { - if (!disableGanache) { + if (ganacheServer) { await ganacheServer.start(ganacheOptions); } - if (anvil) { - await anvilServer.start(anvilOptions); + if (localNetworkServer) { + await localNetworkServer.start(networkOptions || {}); } let contractRegistry; - if (smartContract && !disableGanache) { - const ganacheSeeder = new GanacheSeeder(ganacheServer.getProvider()); - const contracts = - smartContract instanceof Array ? smartContract : [smartContract]; - await Promise.all( - contracts.map((contract) => - ganacheSeeder.deploySmartContract(contract), - ), - ); - contractRegistry = ganacheSeeder.getContractRegistry(); + if (smartContract) { + if (ganacheServer) { + const ganacheSeeder = new GanacheSeeder(ganacheServer.getProvider()); + const contracts = + smartContract instanceof Array ? smartContract : [smartContract]; + await Promise.all( + contracts.map((contract) => + ganacheSeeder.deploySmartContract(contract), + ), + ); + contractRegistry = ganacheSeeder.getContractRegistry(); + } else if (localNetworkServer) { + const localNetworkSeeder = new AnvilSeeder( + localNetworkServer.getProvider(), + ); + const contracts = + smartContract instanceof Array ? smartContract : [smartContract]; + await Promise.all( + contracts.map((contract) => + localNetworkSeeder.deploySmartContract(contract), + ), + ); + contractRegistry = localNetworkSeeder.getContractRegistry(); + } } if (ganacheOptions?.concurrent) { @@ -229,13 +243,14 @@ async function withFixtures(options, testSuite) { console.log(`\nExecuting testcase: '${title}'\n`); await testSuite({ - driver: driverProxy ?? driver, + bundlerServer, contractRegistry, + driver: driverProxy ?? driver, ganacheServer, - secondaryGanacheServer, + localNetworkServer, mockedEndpoint, - bundlerServer, mockServer, + secondaryGanacheServer, }); const errorsAndExceptions = driver.summarizeErrorsAndExceptions(); @@ -319,8 +334,8 @@ async function withFixtures(options, testSuite) { await ganacheServer.quit(); } - if (anvil) { - await anvilServer.quit(); + if (localNetworkServer) { + await localNetworkServer.quit(); } if (ganacheOptions?.concurrent) { @@ -802,10 +817,6 @@ const defaultGanacheOptions = { ], }; -const defaultAnvilOptions = { - balance: 25, -}; - const defaultGanacheOptionsForType2Transactions = { ...defaultGanacheOptions, // EVM version that supports type 2 transactions (EIP1559) @@ -946,17 +957,17 @@ const TEST_SEED_PHRASE_TWO = * or after a transaction is made. * * @param {WebDriver} driver - The WebDriver instance. - * @param {Ganache} [ganacheServer] - The Ganache server instance (optional). + * @param {Ganache} [localNetworkServer] - The local server instance (optional). * @param {string} [address] - The address to check the balance for (optional). */ const locateAccountBalanceDOM = async ( driver, - ganacheServer, + localNetworkServer, address = null, ) => { const balanceSelector = '[data-testid="eth-overview__primary-currency"]'; - if (ganacheServer) { - const balance = await ganacheServer.getBalance(address); + if (localNetworkServer) { + const balance = await localNetworkServer.getBalance(address); await driver.waitForSelector({ css: balanceSelector, text: `${balance} ETH`, @@ -997,10 +1008,10 @@ async function unlockWallet( } } -const logInWithBalanceValidation = async (driver, ganacheServer) => { +const logInWithBalanceValidation = async (driver, localNetworkServer) => { await unlockWallet(driver); // Wait for balance to load - await locateAccountBalanceDOM(driver, ganacheServer); + await locateAccountBalanceDOM(driver, localNetworkServer); }; function roundToXDecimalPlaces(number, decimalPlaces) { @@ -1291,7 +1302,6 @@ module.exports = { connectToDapp, multipleGanacheOptions, defaultGanacheOptions, - defaultAnvilOptions, defaultGanacheOptionsForType2Transactions, multipleGanacheOptionsForType2Transactions, sendTransaction, diff --git a/test/e2e/seeder/anvil-seeder.js b/test/e2e/seeder/anvil-seeder.js new file mode 100644 index 000000000000..aef20326c566 --- /dev/null +++ b/test/e2e/seeder/anvil-seeder.js @@ -0,0 +1,149 @@ +const { DEFAULT_FIXTURE_ACCOUNT, ENTRYPOINT } = require('../constants'); +const ContractAddressRegistry = require('./contract-address-registry'); +const { contractConfiguration, SMART_CONTRACTS } = require('./smart-contracts'); + +/* + * Local network seeder is used to seed initial smart contract or set initial blockchain state. + */ +class AnvilSeeder { + constructor(provider) { + this.smartContractRegistry = new ContractAddressRegistry(); + this.provider = provider; + } + + /** + * Deploy initial smart contracts that can be used later within the e2e tests. + * + * @param contractName + */ + + async deploySmartContract(contractName) { + const { publicClient, testClient, walletClient } = this.provider; + const fromAddress = (await walletClient.getAddresses())[0]; + + const contractConfig = contractConfiguration[contractName]; + const deployArgs = this.getDeployArgs(contractName, contractConfig); + + const hash = await walletClient.deployContract({ + abi: contractConfig.abi, + account: fromAddress, + args: deployArgs, + bytecode: contractConfig.bytecode, + gasPrice: 2000000000, + }); + + await testClient.mine({ + blocks: 1, + }); + + const receipt = await publicClient.getTransactionReceipt({ hash }); + + console.log('Deployed smart contract', { + contractName, + contractAddress: receipt.contractAddress, + }); + + if (contractName === SMART_CONTRACTS.NFTS) { + const transaction = await walletClient.sendTransaction({ + from: fromAddress, + data: contractConfig.abi.encodeFunctionData('mintNFTs', [1]), + to: receipt.contractAddress, + }); + await publicClient.getTransactionReceipt({ hash: transaction.hash }); + } + + if (contractName === SMART_CONTRACTS.ERC1155) { + const transaction = await walletClient.sendTransaction({ + from: fromAddress, + data: contractConfig.abi.encodeFunctionData('mintBatch', [ + fromAddress, + [1, 2, 3], + [1, 1, 100000000000000], + '0x', + ]), + to: receipt.contractAddress, + }); + await publicClient.getTransactionReceipt({ hash: transaction.hash }); + } + + this.storeSmartContractAddress(contractName, receipt.contractAddress); + } + + async transfer(to, value) { + const { publicClient, walletClient } = this.provider; + const fromAddress = (await walletClient.getAddresses())[0]; + + const transaction = await walletClient.sendTransaction({ + from: fromAddress, + value, + to, + }); + + await publicClient.getTransactionReceipt({ hash: transaction.hash }); + + console.log('Completed transfer', { to, value }); + } + + async paymasterDeposit(amount) { + const paymasterAddress = this.smartContractRegistry.getContractAddress( + SMART_CONTRACTS.VERIFYING_PAYMASTER, + ); + + const { publicClient, walletClient } = this.provider; + const fromAddress = (await walletClient.getAddresses())[0]; + + const transaction = await walletClient.sendTransaction({ + from: fromAddress, + data: contractConfiguration[ + SMART_CONTRACTS.VERIFYING_PAYMASTER + ].abi.encodeFunctionData('deposit', []), + to: paymasterAddress, + value: amount, + }); + + await publicClient.getTransactionReceipt({ hash: transaction.hash }); + + console.log('Completed paymaster deposit', { amount }); + } + + /** + * Store deployed smart contract address within the environment variables + * to make it available everywhere. + * + * @param contractName + * @param contractAddress + */ + storeSmartContractAddress(contractName, contractAddress) { + this.smartContractRegistry.storeNewContractAddress( + contractName, + contractAddress, + ); + } + + /** + * Return an instance of the currently used smart contract registry. + * + * @returns ContractAddressRegistry + */ + getContractRegistry() { + return this.smartContractRegistry; + } + + getDeployArgs(contractName, contractConfig) { + if (contractName === SMART_CONTRACTS.HST) { + return [ + contractConfig.initialAmount, + contractConfig.tokenName, + contractConfig.decimalUnits, + contractConfig.tokenSymbol, + ]; + } else if (contractName === SMART_CONTRACTS.SIMPLE_ACCOUNT_FACTORY) { + return [ENTRYPOINT]; + } else if (contractName === SMART_CONTRACTS.VERIFYING_PAYMASTER) { + return [ENTRYPOINT, DEFAULT_FIXTURE_ACCOUNT]; + } + return []; + } +} + +module.exports = AnvilSeeder; diff --git a/test/e2e/seeder/anvil.ts b/test/e2e/seeder/anvil.ts index ed9c01a7de1c..56f136efd0aa 100644 --- a/test/e2e/seeder/anvil.ts +++ b/test/e2e/seeder/anvil.ts @@ -1,4 +1,4 @@ -import { createAnvil, Anvil } from '@viem/anvil'; +import { createAnvil, Anvil as AnvilType } from '@viem/anvil'; import { createAnvilClients } from './anvil-clients'; type Hardfork = @@ -21,25 +21,25 @@ type Hardfork = | 'Latest'; const defaultOptions = { - host: '127.0.0.1', - port: 8545, + balance: 25, blockTime: 2, chainId: 1337, - mnemonic: - 'spread raise short crane omit tent fringe mandate neglect detail suspect cradle', - hardfork: 'Muirglacier' as Hardfork, gasLimit: 30000000, gasPrice: 2000000000, + hardfork: 'Muirglacier' as Hardfork, + host: '127.0.0.1', + mnemonic: + 'spread raise short crane omit tent fringe mandate neglect detail suspect cradle', + port: 8545, }; -export class LocalNetwork { - #server: Anvil | undefined; +export class Anvil { + #server: AnvilType | undefined; async start(opts = defaultOptions): Promise { const options = { ...defaultOptions, ...opts }; this.#server = createAnvil(options); - await this.#server.start(); } @@ -47,7 +47,6 @@ export class LocalNetwork { if (!this.#server) { throw new Error('Server not running yet'); } - const { walletClient, publicClient, testClient } = createAnvilClients( this.#server, ); diff --git a/test/e2e/seeder/ganache-contract-address-registry.js b/test/e2e/seeder/contract-address-registry.js similarity index 80% rename from test/e2e/seeder/ganache-contract-address-registry.js rename to test/e2e/seeder/contract-address-registry.js index bfad708d3c90..b437d6b47f86 100644 --- a/test/e2e/seeder/ganache-contract-address-registry.js +++ b/test/e2e/seeder/contract-address-registry.js @@ -1,8 +1,8 @@ /* * Use this class to store pre-deployed smart contract addresses of the contracts deployed to - * a local blockchain instance ran by Ganache. + * a local blockchain instance. */ -class GanacheContractAddressRegistry { +class ContractAddressRegistry { #addresses = {}; /** @@ -25,4 +25,4 @@ class GanacheContractAddressRegistry { } } -module.exports = GanacheContractAddressRegistry; +module.exports = ContractAddressRegistry; diff --git a/test/e2e/seeder/ganache-seeder.js b/test/e2e/seeder/ganache-seeder.js index 821d3b4a62ff..ebec4d5a8dcd 100644 --- a/test/e2e/seeder/ganache-seeder.js +++ b/test/e2e/seeder/ganache-seeder.js @@ -3,14 +3,14 @@ const { ContractFactory, Contract } = require('@ethersproject/contracts'); const { ENTRYPOINT, GANACHE_ACCOUNT } = require('../constants'); const { SMART_CONTRACTS, contractConfiguration } = require('./smart-contracts'); -const GanacheContractAddressRegistry = require('./ganache-contract-address-registry'); +const ContractAddressRegistry = require('./contract-address-registry'); /* * Ganache seeder is used to seed initial smart contract or set initial blockchain state. */ class GanacheSeeder { constructor(ganacheProvider) { - this.smartContractRegistry = new GanacheContractAddressRegistry(); + this.smartContractRegistry = new ContractAddressRegistry(); this.ganacheProvider = ganacheProvider; } @@ -125,7 +125,7 @@ class GanacheSeeder { /** * Return an instance of the currently used smart contract registry. * - * @returns GanacheContractAddressRegistry + * @returns ContractAddressRegistry */ getContractRegistry() { return this.smartContractRegistry; diff --git a/test/e2e/tests/confirmations/alerts/queued-confirmations.spec.ts b/test/e2e/tests/confirmations/alerts/queued-confirmations.spec.ts index 6fd44e6f7af1..8ecd7e908a30 100644 --- a/test/e2e/tests/confirmations/alerts/queued-confirmations.spec.ts +++ b/test/e2e/tests/confirmations/alerts/queued-confirmations.spec.ts @@ -10,7 +10,7 @@ import { openDAppWithContract, TestSuiteArguments, } from '../transactions/shared'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; const FixtureBuilder = require('../../../fixture-builder'); const { @@ -168,7 +168,7 @@ describe('Queued Confirmations', function () { await openDAppWithContract(driver, contractRegistry, smartContract); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(smartContract); await connectToDappTwoAndSwitchBackToOne(driver, contractAddress); @@ -317,7 +317,7 @@ describe('Queued Confirmations', function () { await openDAppWithContract(driver, contractRegistry, smartContract); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(smartContract); await connectToDappTwoAndSwitchBackToOne(driver, contractAddress); diff --git a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts index 3d28afff5790..bb178f459ab9 100644 --- a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ import { openDapp, unlockWallet } from '../../../helpers'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { assertAdvancedGasDetails, confirmDepositTransaction, @@ -105,7 +105,7 @@ describe('Confirmation Redesign Contract Interaction Component', function () { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(smartContract); await openDapp(driver, contractAddress); diff --git a/test/e2e/tests/confirmations/transactions/increase-token-allowance-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/increase-token-allowance-redesign.spec.ts index 2571a69107b3..7728cdee8383 100644 --- a/test/e2e/tests/confirmations/transactions/increase-token-allowance-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/increase-token-allowance-redesign.spec.ts @@ -8,7 +8,7 @@ import { withFixtures, } from '../../../helpers'; import { Mockttp } from '../../../mock-e2e'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { SMART_CONTRACTS } from '../../../seeder/smart-contracts'; import { Driver } from '../../../webdriver/driver'; import { scrollAndConfirmAndAssertConfirm } from '../helpers'; @@ -142,7 +142,7 @@ async function mocked4BytesIncreaseAllowance(mockServer: Mockttp) { async function createAndAssertIncreaseAllowanceSubmission( driver: Driver, newSpendingCap: string, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await openDAppWithContract(driver, contractRegistry, SMART_CONTRACTS.HST); diff --git a/test/e2e/tests/confirmations/transactions/shared.ts b/test/e2e/tests/confirmations/transactions/shared.ts index 62ceb318aa48..f984417fae94 100644 --- a/test/e2e/tests/confirmations/transactions/shared.ts +++ b/test/e2e/tests/confirmations/transactions/shared.ts @@ -2,7 +2,7 @@ import { MockedEndpoint } from 'mockttp'; import { veryLargeDelayMs } from '../../../helpers'; import { Ganache } from '../../../seeder/ganache'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; const { @@ -15,17 +15,17 @@ const { scrollAndConfirmAndAssertConfirm } = require('../helpers'); export type TestSuiteArguments = { driver: Driver; ganacheServer?: Ganache; - contractRegistry?: GanacheContractAddressRegistry; + contractRegistry?: ContractAddressRegistry; mockedEndpoint?: MockedEndpoint | MockedEndpoint[]; }; export async function openDAppWithContract( driver: Driver, - contractRegistry: GanacheContractAddressRegistry | undefined, + contractRegistry: ContractAddressRegistry | undefined, smartContract: string, ) { const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(smartContract); await logInWithBalanceValidation(driver); diff --git a/test/e2e/tests/transaction/send-eth.spec.js b/test/e2e/tests/transaction/send-eth.spec.js index 5c49bba0cf4e..c6dcd10dc30d 100644 --- a/test/e2e/tests/transaction/send-eth.spec.js +++ b/test/e2e/tests/transaction/send-eth.spec.js @@ -8,7 +8,6 @@ const { unlockWallet, editGasFeeForm, WINDOW_TITLES, - defaultGanacheOptions, } = require('../../helpers'); const FixtureBuilder = require('../../fixture-builder'); @@ -18,11 +17,10 @@ describe('Send ETH', function () { await withFixtures( { fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), }, - async ({ driver, ganacheServer }) => { - await logInWithBalanceValidation(driver, ganacheServer); + async ({ driver, networkServer }) => { + await logInWithBalanceValidation(driver, networkServer); await openActionMenuAndStartSendFlow(driver); @@ -99,8 +97,6 @@ describe('Send ETH', function () { await withFixtures( { fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, - defaultGanacheOptions, title: this.test.fullTitle(), }, async ({ driver }) => { @@ -154,18 +150,17 @@ describe('Send ETH', function () { await withFixtures( { fixtures: new FixtureBuilder().build(), - ganacheOptions: { - ...defaultGanacheOptions, + networkOptions: { hardfork: 'london', }, smartContract, title: this.test.fullTitle(), }, - async ({ driver, contractRegistry, ganacheServer }) => { + async ({ driver, contractRegistry, networkServer }) => { const contractAddress = await contractRegistry.getContractAddress( smartContract, ); - await logInWithBalanceValidation(driver, ganacheServer); + await logInWithBalanceValidation(driver, networkServer); // Wait for balance to load await driver.delay(500); @@ -210,7 +205,6 @@ describe('Send ETH', function () { await withFixtures( { fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), }, async ({ driver }) => { @@ -247,8 +241,6 @@ describe('Send ETH', function () { fixtures: new FixtureBuilder() .withPermissionControllerConnectedToTestDapp() .build(), - ganacheOptions: defaultGanacheOptions, - defaultGanacheOptions, title: this.test.fullTitle(), }, async ({ driver }) => { @@ -321,8 +313,7 @@ describe('Send ETH', function () { fixtures: new FixtureBuilder() .withPermissionControllerConnectedToTestDapp() .build(), - ganacheOptions: { - ...defaultGanacheOptions, + networkOptions: { hardfork: 'london', }, title: this.test.fullTitle(), @@ -427,7 +418,6 @@ describe('Send ETH', function () { }) .withPreferencesControllerPetnamesDisabled() .build(), - ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), }, async ({ driver }) => { diff --git a/test/e2e/tests/transaction/send-hex-address.spec.js b/test/e2e/tests/transaction/send-hex-address.spec.js index 6adb6b5f9f6c..73b89c158521 100644 --- a/test/e2e/tests/transaction/send-hex-address.spec.js +++ b/test/e2e/tests/transaction/send-hex-address.spec.js @@ -1,5 +1,4 @@ const { - defaultGanacheOptions, withFixtures, logInWithBalanceValidation, openActionMenuAndStartSendFlow, @@ -17,11 +16,10 @@ describe('Send ETH to a 40 character hexadecimal address', function () { fixtures: new FixtureBuilder() .withPreferencesControllerPetnamesDisabled() .build(), - ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), }, - async ({ driver, ganacheServer }) => { - await logInWithBalanceValidation(driver, ganacheServer); + async ({ driver, networkServer }) => { + await logInWithBalanceValidation(driver, networkServer); // Send ETH await openActionMenuAndStartSendFlow(driver); @@ -62,11 +60,10 @@ describe('Send ETH to a 40 character hexadecimal address', function () { fixtures: new FixtureBuilder() .withPreferencesControllerPetnamesDisabled() .build(), - ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), }, - async ({ driver, ganacheServer }) => { - await logInWithBalanceValidation(driver, ganacheServer); + async ({ driver, networkServer }) => { + await logInWithBalanceValidation(driver, networkServer); // Send ETH await openActionMenuAndStartSendFlow(driver); @@ -113,17 +110,16 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { .withPreferencesControllerPetnamesDisabled() .withTokensControllerERC20() .build(), - ganacheOptions: defaultGanacheOptions, smartContract, title: this.test.fullTitle(), }, - async ({ driver, ganacheServer }) => { - await logInWithBalanceValidation(driver, ganacheServer); - + async ({ driver, networkServer }) => { + await logInWithBalanceValidation(driver, networkServer); // Send TST await driver.clickElement( '[data-testid="account-overview__asset-tab"]', ); + await driver.clickElement( '[data-testid="multichain-token-list-button"]', ); @@ -175,12 +171,11 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { .withPreferencesControllerPetnamesDisabled() .withTokensControllerERC20() .build(), - ganacheOptions: defaultGanacheOptions, smartContract, title: this.test.fullTitle(), }, - async ({ driver, ganacheServer }) => { - await logInWithBalanceValidation(driver, ganacheServer); + async ({ driver, networkServer }) => { + await logInWithBalanceValidation(driver, networkServer); // Send TST await driver.clickElement( '[data-testid="account-overview__asset-tab"]', diff --git a/test/e2e/tests/transaction/simple-send.spec.ts b/test/e2e/tests/transaction/simple-send.spec.ts index accd8d5767cc..f10d8209e83c 100644 --- a/test/e2e/tests/transaction/simple-send.spec.ts +++ b/test/e2e/tests/transaction/simple-send.spec.ts @@ -1,6 +1,6 @@ import { Suite } from 'mocha'; import { Driver } from '../../webdriver/driver'; -import { withFixtures, defaultAnvilOptions } from '../../helpers'; +import { withFixtures } from '../../helpers'; import FixtureBuilder from '../../fixture-builder'; import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow'; import { sendTransaction } from '../../page-objects/flows/send-transaction.flow'; @@ -11,9 +11,6 @@ describe('Simple send eth', function (this: Suite) { await withFixtures( { fixtures: new FixtureBuilder().build(), - disableGanache: true, - anvil: true, - anvilOptions: defaultAnvilOptions, title: this.test?.fullTitle(), }, async ({ driver }: { driver: Driver }) => { From b9a66c13f2a6f032b1d078fe6e26a4dd9c3964f2 Mon Sep 17 00:00:00 2001 From: seaona Date: Fri, 20 Sep 2024 11:55:07 +0200 Subject: [PATCH 13/46] rename --- test/e2e/accounts/snap-account-contract-interaction.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/accounts/snap-account-contract-interaction.spec.ts b/test/e2e/accounts/snap-account-contract-interaction.spec.ts index fb58be2550bf..51809060628a 100644 --- a/test/e2e/accounts/snap-account-contract-interaction.spec.ts +++ b/test/e2e/accounts/snap-account-contract-interaction.spec.ts @@ -1,4 +1,4 @@ -import GanacheContractAddressRegistry from '../seeder/contract-address-registry'; +import ContractAddressRegistry from '../seeder/contract-address-registry'; import { scrollAndConfirmAndAssertConfirm } from '../tests/confirmations/helpers'; import { createDepositTransaction, @@ -48,7 +48,7 @@ describe('Snap Account Contract interaction', function () { // Open DApp with contract const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(smartContract); await openDapp(driver, contractAddress); From a1263709bcf6c4f758f5975c376153659c4ddb66 Mon Sep 17 00:00:00 2001 From: seaona Date: Fri, 20 Sep 2024 12:30:08 +0200 Subject: [PATCH 14/46] fix benchmark --- test/e2e/benchmark.js | 1 + yarn.lock | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index 738d766f8555..e982a0a10b9e 100755 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -22,6 +22,7 @@ async function measurePage(pageName) { await withFixtures( { fixtures: new FixtureBuilder().build(), + ganacheOptions: {}, disableServerMochaToBackground: true, }, async ({ driver }) => { diff --git a/yarn.lock b/yarn.lock index 556902f50481..fa5e85d5d4d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -50,6 +50,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:1.10.0": + version: 1.10.0 + resolution: "@adraffy/ens-normalize@npm:1.10.0" + checksum: 10/5cdb5d2a9c9f8c0a71a7bb830967da0069cae1f1235cd41ae11147e4000f368f6958386e622cd4d52bf45c1ed3f8275056b387cba28902b83354e40ff323ecde + languageName: node + linkType: hard + "@adraffy/ens-normalize@npm:1.10.1": version: 1.10.1 resolution: "@adraffy/ens-normalize@npm:1.10.1" @@ -6690,7 +6697,7 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.4.0, @noble/hashes@npm:^1.1.2, @noble/hashes@npm:^1.2.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.3.2, @noble/hashes@npm:^1.3.3, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:~1.4.0": +"@noble/hashes@npm:1.4.0, @noble/hashes@npm:~1.4.0": version: 1.4.0 resolution: "@noble/hashes@npm:1.4.0" checksum: 10/e156e65794c473794c52fa9d06baf1eb20903d0d96719530f523cc4450f6c721a957c544796e6efd0197b2296e7cd70efeb312f861465e17940a3e3c7e0febc6 @@ -37320,6 +37327,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.13.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + languageName: node + linkType: hard + "xdg-basedir@npm:^3.0.0": version: 3.0.0 resolution: "xdg-basedir@npm:3.0.0" From eeac3a8377915f9f96f4f410ee7554c896fcdb2a Mon Sep 17 00:00:00 2001 From: seaona Date: Fri, 20 Sep 2024 12:36:06 +0200 Subject: [PATCH 15/46] yarn dedupe --- yarn.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/yarn.lock b/yarn.lock index fa5e85d5d4d4..9caad408663c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -37288,7 +37288,22 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:8.17.1, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": +"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.13.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + languageName: node + linkType: hard + +"ws@npm:8.17.1": version: 8.17.1 resolution: "ws@npm:8.17.1" peerDependencies: @@ -37327,21 +37342,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.13.0": - version: 8.18.0 - resolution: "ws@npm:8.18.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 - languageName: node - linkType: hard - "xdg-basedir@npm:^3.0.0": version: 3.0.0 resolution: "xdg-basedir@npm:3.0.0" From b5d5315c85e34dba699c658c16ea7a8cc381812b Mon Sep 17 00:00:00 2001 From: seaona Date: Fri, 20 Sep 2024 12:56:31 +0200 Subject: [PATCH 16/46] fix lint --- .circleci/config.yml | 1 + test/e2e/benchmark.js | 1 - .../transactions/contract-interaction-redesign.spec.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4a5818e2e8f5..1d474424b98a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1452,6 +1452,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test ./builds + - foundry-install - run: name: Run page load benchmark command: yarn benchmark:chrome --out test-artifacts/chrome/benchmark/pageload.json --retries 2 diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index e982a0a10b9e..738d766f8555 100755 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -22,7 +22,6 @@ async function measurePage(pageName) { await withFixtures( { fixtures: new FixtureBuilder().build(), - ganacheOptions: {}, disableServerMochaToBackground: true, }, async ({ driver }) => { diff --git a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts index b58520866285..4baa5919136c 100644 --- a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts @@ -2,7 +2,7 @@ import { Mockttp } from 'mockttp'; import { openDapp, unlockWallet } from '../../../helpers'; import { createDappTransaction } from '../../../page-objects/flows/transaction'; -import ContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; import { MockedEndpoint } from '../../../mock-e2e'; import { From a33e7ae5506de91b9483b4e858d9cd01718a31ba Mon Sep 17 00:00:00 2001 From: seaona Date: Fri, 20 Sep 2024 13:51:51 +0200 Subject: [PATCH 17/46] fix remaining tests --- .circleci/config.yml | 2 +- test/e2e/benchmark.js | 8 +++++++- test/e2e/tests/metrics/dapp-viewed.spec.js | 1 + test/e2e/tests/settings/ipfs-toggle.spec.js | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1d474424b98a..a0f663083e89 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1452,7 +1452,6 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test ./builds - - foundry-install - run: name: Run page load benchmark command: yarn benchmark:chrome --out test-artifacts/chrome/benchmark/pageload.json --retries 2 @@ -1501,6 +1500,7 @@ jobs: - run: name: Move test zips to builds command: mv ./builds-test ./builds + - foundry-install - run: name: Run page load benchmark command: | diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index 738d766f8555..ada527ba6d44 100755 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -10,7 +10,12 @@ const { isWritable, getFirstParentDirectoryThatExists, } = require('../helpers/file'); -const { withFixtures, tinyDelayMs, unlockWallet } = require('./helpers'); +const { + defaultGanacheOptions, + tinyDelayMs, + unlockWallet, + withFixtures, +} = require('./helpers'); const { PAGES } = require('./webdriver/driver'); const FixtureBuilder = require('./fixture-builder'); @@ -22,6 +27,7 @@ async function measurePage(pageName) { await withFixtures( { fixtures: new FixtureBuilder().build(), + ganacheOptions: defaultGanacheOptions, disableServerMochaToBackground: true, }, async ({ driver }) => { diff --git a/test/e2e/tests/metrics/dapp-viewed.spec.js b/test/e2e/tests/metrics/dapp-viewed.spec.js index b9b4b08ca73e..34bf6702180b 100644 --- a/test/e2e/tests/metrics/dapp-viewed.spec.js +++ b/test/e2e/tests/metrics/dapp-viewed.spec.js @@ -79,6 +79,7 @@ describe('Dapp viewed Event @no-mmi', function () { participateInMetaMetrics: true, }) .build(), + ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), testSpecificMock: mockSegment, }, diff --git a/test/e2e/tests/settings/ipfs-toggle.spec.js b/test/e2e/tests/settings/ipfs-toggle.spec.js index 045c51496853..3f295b2fe4ae 100644 --- a/test/e2e/tests/settings/ipfs-toggle.spec.js +++ b/test/e2e/tests/settings/ipfs-toggle.spec.js @@ -14,7 +14,7 @@ describe('Settings', function () { { dapp: true, fixtures: new FixtureBuilder().withNftControllerERC1155().build(), - defaultGanacheOptions, + ganacheOptions: defaultGanacheOptions, smartContract, title: this.test.fullTitle(), }, From a78f5aea371dde4f020309432d506f146e2868ee Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Fri, 8 Nov 2024 17:18:09 -0500 Subject: [PATCH 18/46] wip --- foundryup.ts | 279 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 +- types/unzipper.d.ts | 17 +++ yarn.lock | 84 ++++++++++++- 4 files changed, 379 insertions(+), 7 deletions(-) create mode 100644 foundryup.ts create mode 100644 types/unzipper.d.ts diff --git a/foundryup.ts b/foundryup.ts new file mode 100644 index 000000000000..2155cfcf3b99 --- /dev/null +++ b/foundryup.ts @@ -0,0 +1,279 @@ +#!/usr/bin/env node + +import yargs from 'yargs/yargs'; +import { mkdir } from 'node:fs/promises'; +import { createWriteStream } from 'node:fs'; +import { join } from 'node:path'; +import { argv, arch as osArch, platform as osPlatform } from 'node:process'; +import { execSync } from 'node:child_process'; +import { extract as extractTar } from 'tar'; +import { Open as Unzip, Source } from 'unzipper'; +import { request as httpRequest } from 'node:https'; +import { Agent as HttpsAgent, request as httpsRequest } from 'node:https'; +import { toOrange } from './development/webpack/utils/helpers'; +import { Stream } from 'node:stream'; +import { Agent as HttpAgent, type IncomingMessage } from 'node:http'; + +type BinFormat = 'zip' | 'tar.gz'; + +const BASE_DIR = join(__dirname, 'node_modules', '.bin'); +const FOUNDRY_BIN_DIR = BASE_DIR || join(BASE_DIR, '.foundry', 'bin'); + +const BINS = ['anvil', 'forge', 'cast', 'chisel'] as const; +const { + repo, + version: { version, tag }, + arch, + platform, + binaries, +} = yargs() + // Ensure unrecognized commands/options are reported as errors. + .strict() + // disable yargs's version, as it doesn't make sense here + .version(false) + // use the scriptName in `--help` output + .scriptName('yarn foundryup') + // wrap output at a maximum of 120 characters or `process.stdout.columns` + .wrap(Math.min(120, process.stdout.columns)) + // enable the `--config` command, which allows the user to specify a custom + // config file containing webpack options + .config() + .parserConfiguration({ + 'strip-aliased': true, + 'strip-dashed': true, + }) + // enable ENV parsing, which allows the user to specify fondryup options via + // environment variables prefixed with `FOUNDRYUP_` + .env('FOUNDRYUP') + .updateStrings({ + 'Options:': toOrange('Options:'), + 'Examples:': toOrange('Examples:'), + }) + .option('binaries', { + alias: 'b', + type: 'string', + array: true, + multiple: true, + description: 'Specify the binaries to install', + default: ['anvil'] as (typeof BINS)[number][], + choices: BINS, + }) + .option('repo', { + alias: 'r', + type: 'string', + description: 'Specify the repository', + default: 'foundry-rs/foundry', + }) + .option('version', { + alias: 'v', + type: 'string', + description: 'Specify the version', + default: 'nightly', + coerce: (version) => { + if (/^nightly/.test(version)) { + return { version: 'nightly', tag: version }; + } else if (/^\d/.test(version)) { + return { version: `v${version}`, tag: version }; + } else { + return { version: version, tag: version }; + } + }, + }) + .option('arch', { + description: 'Specify the architecture (amd64 or arm64)', + default: osArch, + choices: ['amd64', 'arm64'] as const, + coerce: (ARCHITECTURE: NodeJS.Architecture) => { + if (ARCHITECTURE === 'arm') { + return 'arm64'; + } else { + return 'amd64'; + } + }, + }) + .option('platform', { + type: 'string', + description: 'Specify the platform (win32, linux, or darwin)', + default: osPlatform, + choices: ['win32', 'linux', 'darwin'] as const, + }) + .parseSync(argv.slice(2)); + +// Print the banner +banner(); + +(async function main() { + say(`installing foundry (version ${version}, tag ${tag})`); + + const ext: BinFormat = platform === 'win32' ? 'zip' : 'tar.gz'; + const RELEASE_URL = `https://github.com/${repo}/releases/download/${tag}/`; + const BIN_ARCHIVE_URL = `${RELEASE_URL}foundry_${version}_${platform}_${arch}.${ext}`; + + say(`downloading ${binaries.join(', ')}`); + await downloadAndExtract(ext, new URL(BIN_ARCHIVE_URL), FOUNDRY_BIN_DIR); + + for (const bin of binaries) { + const binPath = join(FOUNDRY_BIN_DIR, bin); + say(`installed - ${getVersion(binPath)}`); + } + + say('done!'); +})(); + +// Helper Functions +function say(message: string) { + console.log(`foundryup: ${message}`); +} + +function banner() { + console.log(` +.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx + + ╔═╗ ╔═╗ ╦ ╦ ╔╗╔ ╔╦╗ ╦═╗ ╦ ╦ Portable and modular toolkit + ╠╣ ║ ║ ║ ║ ║║║ ║║ ╠╦╝ ╚╦╝ for Ethereum Application Development + ╚ ╚═╝ ╚═╝ ╝╚╝ ═╩╝ ╩╚═ ╩ written in Rust. + +.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx + +Repo : https://github.com/foundry-rs/ +Book : https://book.getfoundry.sh/ +Chat : https://t.me/foundry_rs/ +Support : https://t.me/foundry_support/ +Contribute : https://github.com/orgs/foundry-rs/projects/2/ + +.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx +`); +} + +async function _download( + url: URL, + options: { + method?: 'GET' | 'HEAD'; + headers?: Record; + agent?: HttpAgent; + } = {}, + redirects: number = 0, +): Promise { + const MAX_REDIRECTS = 5; + const request = url.protocol === 'https:' ? httpsRequest : httpRequest; + return new Promise((resolve, reject) => { + request(url, options, (res) => { + const { statusCode, statusMessage, headers } = res; + // Handle redirects + if ( + statusCode && + statusCode >= 300 && + statusCode < 400 && + headers.location + ) { + if (redirects >= MAX_REDIRECTS) { + reject(new Error('Too many redirects')); + res.resume(); // Consume response data to free up memory + return; + } + // Resolve relative redirects + const redirectUrl = new URL(headers.location, url); + res.resume(); // Consume response data to free up memory + + // Follow the redirect + _download(redirectUrl, options, redirects + 1) + .then(resolve) + .catch(reject); + return; + } + + // Check for HTTP errors + if (!statusCode || statusCode < 200 || statusCode >= 300) { + reject( + new Error( + `Request Failed. Status Code: ${statusCode} - ${statusMessage}`, + ), + ); + res.resume(); // Consume response data to free up memory + return; + } + + // Resolve with response stream + resolve(res); + }) + .on('error', (e: Error) => { + reject(e); + }) + .end(); + }); +} + +async function download( + url: URL, + options?: { + method?: 'GET' | 'HEAD'; + headers?: Record; + agent?: HttpAgent; + }, +): Promise { + return _download(url, options); +} + +async function downloadAndExtract(format: BinFormat, url: URL, cwd: string) { + await mkdir(cwd, { recursive: true }); + + return await new Promise(async (resolve, reject) => { + if (format === 'zip') { + const agent = new (url.protocol === 'http' ? HttpAgent : HttpsAgent)({ + keepAlive: true, + }); + const source: Source = { + stream: function (offset: number, length: number) { + const stream = new Stream.PassThrough(); + const options = { + agent, + headers: { + range: 'bytes=' + offset + '-' + (length ? offset + length : ''), + }, + }; + download(url, options).then( + (response) => response.pipe(stream), + (error: Error) => stream.emit('error', error), + ); + return stream; + }, + size: async function () { + const response = await download(url, { agent, method: 'HEAD' }); + response.resume(); // Consume response data to free up memory + const contentLength = response.headers['content-length']; + return contentLength ? parseInt(contentLength, 10) : 0; + }, + }; + const { files } = await Unzip.custom(source); + for await (const file of files) { + if (file.type !== 'File') continue; + // remove `.exe` from the path to get the binary name + const path = file.path.slice(0, -4) as (typeof BINS)[number]; + // ignore files that are not in the list of binaries + if (!binaries.includes(path)) continue; + // write the binary to the destination + + file + .stream() + .pipe(createWriteStream(join(cwd, file.path))) + .on('error', reject) + .on('finish', resolve); + } + } else { + const stream = (await download(url)).pipe(extractTar({ cwd }, binaries)); + stream.on('finish', resolve); + stream.on('error', reject); + } + }); +} + +function getVersion(binPath: string): string { + try { + const result = execSync(`${binPath} --version`, { + encoding: 'utf8', + }).trim(); + return result; + } catch { + return 'unknown version'; + } +} diff --git a/package.json b/package.json index 6c9811cb3ed6..39500fe8782e 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "webpack": "tsx ./development/webpack/launch.ts", "webpack:clearcache": "rimraf node_modules/.cache/webpack", - "postinstall": "yarn webpack:clearcache", + "postinstall": "yarn webpack:clearcache && tsx foundryup", "env:e2e": "SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' yarn", "start": "yarn build:dev dev --apply-lavamoat=false --snow=false", "start:with-state": "node ./app/scripts/start-with-wallet-state.mjs", @@ -44,6 +44,7 @@ "forwarder": "node ./development/static-server.js ./node_modules/@metamask/forwarder/dist/ --port 9010", "dapp-forwarder": "concurrently -k -n forwarder,dapp -p '[{time}][{name}]' 'yarn forwarder' 'yarn dapp'", "test:unit": "jest", + "anvil": "npx anvil", "test:unit:watch": "jest --watch", "test:unit:coverage": "jest --coverage", "test:unit:webpack": "tsx --test development/webpack/test/*.test.ts", @@ -537,6 +538,7 @@ "@types/serve-handler": "^6.1.4", "@types/sinon": "^10.0.13", "@types/sprintf-js": "^1", + "@types/unzipper": "^0", "@types/w3c-web-hid": "^1.0.3", "@types/watchify": "^3.11.1", "@types/webextension-polyfill": "^0.10.4", @@ -664,6 +666,7 @@ "style-loader": "^0.21.0", "stylelint": "^13.6.1", "superstruct": "^1.0.3", + "tar": "^7.4.3", "terser": "^5.7.0", "terser-webpack-plugin": "^5.3.10", "through2": "^4.0.2", @@ -671,6 +674,7 @@ "tsx": "^4.7.1", "ttest": "^2.1.1", "typescript": "~5.4.5", + "unzipper": "^0.12.3", "vinyl": "^2.2.1", "vinyl-buffer": "^1.0.1", "vinyl-source-stream": "^2.0.0", diff --git a/types/unzipper.d.ts b/types/unzipper.d.ts new file mode 100644 index 000000000000..fd665df66c73 --- /dev/null +++ b/types/unzipper.d.ts @@ -0,0 +1,17 @@ +import 'unzipper'; + +declare module 'unzipper' { + type Source = { + stream: (offset: number, length: number) => NodeJS.ReadableStream; + size: () => Promise; + }; + type Options = { + tailSize?: number; + }; + namespace Open { + function custom( + source: Source, + options?: Options, + ): Promise; + } +} diff --git a/yarn.lock b/yarn.lock index d40270b12e9c..a3c351e13c14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3677,6 +3677,15 @@ __metadata: languageName: node linkType: hard +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10/4412e9e6713c89c1e66d80bb0bb5a2a93192f10477623a27d08f228ba0316bb880affabc5bfe7f838f58a34d26c2c190da726e576cdfc18c49a72e89adabdcf5 + languageName: node + linkType: hard + "@istanbuljs/load-nyc-config@npm:^1.0.0": version: 1.0.0 resolution: "@istanbuljs/load-nyc-config@npm:1.0.0" @@ -11413,6 +11422,15 @@ __metadata: languageName: node linkType: hard +"@types/unzipper@npm:^0": + version: 0.10.10 + resolution: "@types/unzipper@npm:0.10.10" + dependencies: + "@types/node": "npm:*" + checksum: 10/4ba5f6c4c5a892f5f5ce7724a4c3f2ea772a29043e296a28b725162ffff8fb25d2d0995c5536705e13bfbde7765d085f0da5408b25946457d050ac4b75aaefee + languageName: node + linkType: hard + "@types/uuid@npm:^10.0.0": version: 10.0.0 resolution: "@types/uuid@npm:10.0.0" @@ -13937,7 +13955,7 @@ __metadata: languageName: node linkType: hard -"bluebird@npm:^3.7.2": +"bluebird@npm:^3.7.2, bluebird@npm:~3.7.2": version: 3.7.2 resolution: "bluebird@npm:3.7.2" checksum: 10/007c7bad22c5d799c8dd49c85b47d012a1fe3045be57447721e6afbd1d5be43237af1db62e26cb9b0d9ba812d2e4ca3bac82f6d7e016b6b88de06ee25ceb96e7 @@ -15058,6 +15076,13 @@ __metadata: languageName: node linkType: hard +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10/b63cb1f73d171d140a2ed8154ee6566c8ab775d3196b0e03a2a94b5f6a0ce7777ee5685ca56849403c8d17bd457a6540672f9a60696a6137c7a409097495b82c + languageName: node + linkType: hard + "chrome-trace-event@npm:^1.0.2": version: 1.0.2 resolution: "chrome-trace-event@npm:1.0.2" @@ -17555,7 +17580,7 @@ __metadata: languageName: node linkType: hard -"duplexer2@npm:^0.1.2, duplexer2@npm:~0.1.0, duplexer2@npm:~0.1.2": +"duplexer2@npm:^0.1.2, duplexer2@npm:~0.1.0, duplexer2@npm:~0.1.2, duplexer2@npm:~0.1.4": version: 0.1.4 resolution: "duplexer2@npm:0.1.4" dependencies: @@ -20381,7 +20406,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.1.0": +"fs-extra@npm:^11.1.0, fs-extra@npm:^11.2.0": version: 11.2.0 resolution: "fs-extra@npm:11.2.0" dependencies: @@ -21227,7 +21252,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.0.0, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.0.0, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 @@ -26849,6 +26874,7 @@ __metadata: "@types/serve-handler": "npm:^6.1.4" "@types/sinon": "npm:^10.0.13" "@types/sprintf-js": "npm:^1" + "@types/unzipper": "npm:^0" "@types/w3c-web-hid": "npm:^1.0.3" "@types/watchify": "npm:^3.11.1" "@types/webextension-polyfill": "npm:^0.10.4" @@ -27045,6 +27071,7 @@ __metadata: style-loader: "npm:^0.21.0" stylelint: "npm:^13.6.1" superstruct: "npm:^1.0.3" + tar: "npm:^7.4.3" terser: "npm:^5.7.0" terser-webpack-plugin: "npm:^5.3.10" through2: "npm:^4.0.2" @@ -27054,6 +27081,7 @@ __metadata: ttest: "npm:^2.1.1" typescript: "npm:~5.4.5" unicode-confusables: "npm:^0.1.1" + unzipper: "npm:^0.12.3" uri-js: "npm:^4.4.1" uuid: "npm:^8.3.2" vinyl: "npm:^2.2.1" @@ -27724,7 +27752,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 resolution: "minipass@npm:7.1.2" checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950 @@ -27741,6 +27769,16 @@ __metadata: languageName: node linkType: hard +"minizlib@npm:^3.0.1": + version: 3.0.1 + resolution: "minizlib@npm:3.0.1" + dependencies: + minipass: "npm:^7.0.4" + rimraf: "npm:^5.0.5" + checksum: 10/622cb85f51e5c206a080a62d20db0d7b4066f308cb6ce82a9644da112367c3416ae7062017e631eb7ac8588191cfa4a9a279b8651c399265202b298e98c4acef + languageName: node + linkType: hard + "mitt@npm:^3.0.1": version: 3.0.1 resolution: "mitt@npm:3.0.1" @@ -27795,7 +27833,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^3.0.0": +"mkdirp@npm:^3.0.0, mkdirp@npm:^3.0.1": version: 3.0.1 resolution: "mkdirp@npm:3.0.1" bin: @@ -35217,6 +35255,20 @@ __metadata: languageName: node linkType: hard +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10/12a2a4fc6dee23e07cc47f1aeb3a14a1afd3f16397e1350036a8f4cdfee8dcac7ef5978337a4e7b2ac2c27a9a6d46388fc2088ea7c80cb6878c814b1425f8ecf + languageName: node + linkType: hard + "telejson@npm:^7.2.0": version: 7.2.0 resolution: "telejson@npm:7.2.0" @@ -36612,6 +36664,19 @@ __metadata: languageName: node linkType: hard +"unzipper@npm:^0.12.3": + version: 0.12.3 + resolution: "unzipper@npm:0.12.3" + dependencies: + bluebird: "npm:~3.7.2" + duplexer2: "npm:~0.1.4" + fs-extra: "npm:^11.2.0" + graceful-fs: "npm:^4.2.2" + node-int64: "npm:^0.4.0" + checksum: 10/b210c421308e1913e01b54faad4ae79e758c674311892414a0697acacba9f82fa0051b677faa77e62fab422eef928c858f2d5cda9ddb47a2f3db95b0e9b36359 + languageName: node + linkType: hard + "upath@npm:2.0.1": version: 2.0.1 resolution: "upath@npm:2.0.1" @@ -38226,6 +38291,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10/1884d272d485845ad04759a255c71775db0fac56308764b4c77ea56a20d56679fad340213054c8c9c9c26fcfd4c4b2a90df993b7e0aaf3cdb73c618d1d1a802a + languageName: node + linkType: hard + "yaml@npm:^1.10.0, yaml@npm:^1.10.2, yaml@npm:^1.7.2": version: 1.10.2 resolution: "yaml@npm:1.10.2" From 226235c701440359a8b4ed937b99fa97ff210d71 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Fri, 8 Nov 2024 17:20:51 -0500 Subject: [PATCH 19/46] coerce default arch --- foundryup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundryup.ts b/foundryup.ts index 2155cfcf3b99..c836c8480ec0 100644 --- a/foundryup.ts +++ b/foundryup.ts @@ -81,7 +81,7 @@ const { }) .option('arch', { description: 'Specify the architecture (amd64 or arm64)', - default: osArch, + default: osArch === 'arm' ? 'arm64' : 'amd64', choices: ['amd64', 'arm64'] as const, coerce: (ARCHITECTURE: NodeJS.Architecture) => { if (ARCHITECTURE === 'arm') { From fd4d10a5e4d55315e87a0f22566520b4eff80e1b Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Fri, 8 Nov 2024 18:27:38 -0500 Subject: [PATCH 20/46] lavamoat --- lavamoat/build-system/policy.json | 84 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index 2d6b7ce3ad14..ca8c1bbdea8e 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -1554,45 +1554,6 @@ "browserify>deps-sort>through2>readable-stream>safe-buffer": true } }, - "browserify>duplexer2": { - "packages": { - "browserify>duplexer2>readable-stream": true - } - }, - "browserify>duplexer2>readable-stream": { - "builtin": { - "events.EventEmitter": true, - "stream": true, - "util": true - }, - "globals": { - "process.browser": true, - "process.env.READABLE_STREAM": true, - "process.stderr": true, - "process.stdout": true, - "process.version.slice": true, - "setImmediate": true - }, - "packages": { - "browserify>duplexer2>readable-stream>isarray": true, - "browserify>duplexer2>readable-stream>safe-buffer": true, - "browserify>duplexer2>readable-stream>string_decoder": true, - "pumpify>inherits": true, - "readable-stream-2>core-util-is": true, - "readable-stream-2>process-nextick-args": true, - "readable-stream>util-deprecate": true - } - }, - "browserify>duplexer2>readable-stream>safe-buffer": { - "builtin": { - "buffer": true - } - }, - "browserify>duplexer2>readable-stream>string_decoder": { - "packages": { - "browserify>duplexer2>readable-stream>safe-buffer": true - } - }, "browserify>has": { "packages": { "browserify>has>function-bind": true @@ -1697,7 +1658,6 @@ "browserify>browser-resolve": true, "browserify>cached-path-relative": true, "browserify>concat-stream": true, - "browserify>duplexer2": true, "browserify>module-deps>detective": true, "browserify>module-deps>readable-stream": true, "browserify>module-deps>stream-combiner2": true, @@ -1706,6 +1666,7 @@ "depcheck>resolve": true, "loose-envify": true, "pumpify>inherits": true, + "unzipper>duplexer2": true, "watchify>defined": true, "watchify>xtend": true } @@ -1752,8 +1713,8 @@ }, "browserify>module-deps>stream-combiner2": { "packages": { - "browserify>duplexer2": true, - "browserify>module-deps>stream-combiner2>readable-stream": true + "browserify>module-deps>stream-combiner2>readable-stream": true, + "unzipper>duplexer2": true } }, "browserify>module-deps>stream-combiner2>readable-stream": { @@ -8814,6 +8775,45 @@ "terser>source-map-support": true } }, + "unzipper>duplexer2": { + "packages": { + "unzipper>duplexer2>readable-stream": true + } + }, + "unzipper>duplexer2>readable-stream": { + "builtin": { + "events.EventEmitter": true, + "stream": true, + "util": true + }, + "globals": { + "process.browser": true, + "process.env.READABLE_STREAM": true, + "process.stderr": true, + "process.stdout": true, + "process.version.slice": true, + "setImmediate": true + }, + "packages": { + "pumpify>inherits": true, + "readable-stream-2>core-util-is": true, + "readable-stream-2>process-nextick-args": true, + "readable-stream>util-deprecate": true, + "unzipper>duplexer2>readable-stream>isarray": true, + "unzipper>duplexer2>readable-stream>safe-buffer": true, + "unzipper>duplexer2>readable-stream>string_decoder": true + } + }, + "unzipper>duplexer2>readable-stream>safe-buffer": { + "builtin": { + "buffer": true + } + }, + "unzipper>duplexer2>readable-stream>string_decoder": { + "packages": { + "unzipper>duplexer2>readable-stream>safe-buffer": true + } + }, "uri-js": { "globals": { "define": true From 5de492a0cc7a7ca0f9866602c29d4ba9aa32e664 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Fri, 8 Nov 2024 21:06:05 -0500 Subject: [PATCH 21/46] lint --- foundryup.ts | 80 ++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/foundryup.ts b/foundryup.ts index c836c8480ec0..30a8ce9e3c6b 100644 --- a/foundryup.ts +++ b/foundryup.ts @@ -1,18 +1,21 @@ #!/usr/bin/env node -import yargs from 'yargs/yargs'; -import { mkdir } from 'node:fs/promises'; +import { execSync } from 'node:child_process'; import { createWriteStream } from 'node:fs'; +import { mkdir } from 'node:fs/promises'; +import { Agent as HttpAgent, type IncomingMessage } from 'node:http'; +import { + Agent as HttpsAgent, + request as httpRequest, + request as httpsRequest, +} from 'node:https'; import { join } from 'node:path'; import { argv, arch as osArch, platform as osPlatform } from 'node:process'; -import { execSync } from 'node:child_process'; +import { Stream } from 'node:stream'; import { extract as extractTar } from 'tar'; -import { Open as Unzip, Source } from 'unzipper'; -import { request as httpRequest } from 'node:https'; -import { Agent as HttpsAgent, request as httpsRequest } from 'node:https'; +import { Source, Open as Unzip } from 'unzipper'; +import yargs from 'yargs/yargs'; import { toOrange } from './development/webpack/utils/helpers'; -import { Stream } from 'node:stream'; -import { Agent as HttpAgent, type IncomingMessage } from 'node:http'; type BinFormat = 'zip' | 'tar.gz'; @@ -69,31 +72,26 @@ const { type: 'string', description: 'Specify the version', default: 'nightly', - coerce: (version) => { - if (/^nightly/.test(version)) { - return { version: 'nightly', tag: version }; - } else if (/^\d/.test(version)) { - return { version: `v${version}`, tag: version }; - } else { - return { version: version, tag: version }; + coerce: (rawVersion) => { + if (/^nightly/u.test(rawVersion)) { + return { version: 'nightly', tag: rawVersion }; + } else if (/^\d/u.test(rawVersion)) { + return { version: `v${rawVersion}`, tag: rawVersion }; } + return { version: rawVersion, tag: rawVersion }; }, }) .option('arch', { - description: 'Specify the architecture (amd64 or arm64)', + description: 'Specify the architecture', default: osArch === 'arm' ? 'arm64' : 'amd64', choices: ['amd64', 'arm64'] as const, - coerce: (ARCHITECTURE: NodeJS.Architecture) => { - if (ARCHITECTURE === 'arm') { - return 'arm64'; - } else { - return 'amd64'; - } + coerce: (rawArch: NodeJS.Architecture) => { + return rawArch === 'arm' ? 'arm64' : 'amd64'; }, }) .option('platform', { type: 'string', - description: 'Specify the platform (win32, linux, or darwin)', + description: 'Specify the platform', default: osPlatform, choices: ['win32', 'linux', 'darwin'] as const, }) @@ -217,27 +215,28 @@ async function download( async function downloadAndExtract(format: BinFormat, url: URL, cwd: string) { await mkdir(cwd, { recursive: true }); + // eslint-disable-next-line no-async-promise-executor return await new Promise(async (resolve, reject) => { if (format === 'zip') { const agent = new (url.protocol === 'http' ? HttpAgent : HttpsAgent)({ keepAlive: true, }); const source: Source = { - stream: function (offset: number, length: number) { - const stream = new Stream.PassThrough(); + stream(offset: number, length: number) { + const passThrough = new Stream.PassThrough(); const options = { agent, headers: { - range: 'bytes=' + offset + '-' + (length ? offset + length : ''), + range: `bytes=${offset}-${length ? offset + length : ''}`, }, }; download(url, options).then( - (response) => response.pipe(stream), - (error: Error) => stream.emit('error', error), + (response) => response.pipe(passThrough), + (error: Error) => passThrough.emit('error', error), ); - return stream; + return passThrough; }, - size: async function () { + async size() { const response = await download(url, { agent, method: 'HEAD' }); response.resume(); // Consume response data to free up memory const contentLength = response.headers['content-length']; @@ -246,23 +245,24 @@ async function downloadAndExtract(format: BinFormat, url: URL, cwd: string) { }; const { files } = await Unzip.custom(source); for await (const file of files) { - if (file.type !== 'File') continue; + if (file.type !== 'File') { + continue; + } // remove `.exe` from the path to get the binary name const path = file.path.slice(0, -4) as (typeof BINS)[number]; // ignore files that are not in the list of binaries - if (!binaries.includes(path)) continue; + if (!binaries.includes(path)) { + continue; + } // write the binary to the destination - - file - .stream() - .pipe(createWriteStream(join(cwd, file.path))) - .on('error', reject) - .on('finish', resolve); + const dest = join(cwd, file.path); + const stream = file.stream().pipe(createWriteStream(dest)); + stream.on('finish', resolve).on('error', reject); } } else { + // write the binaries to the destination const stream = (await download(url)).pipe(extractTar({ cwd }, binaries)); - stream.on('finish', resolve); - stream.on('error', reject); + stream.on('finish', resolve).on('error', reject); } }); } From a55f7009dd56cb18e047999b22068ad8fafe4cb6 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:13:20 -0500 Subject: [PATCH 22/46] some polish --- foundryup.ts | 279 ------------------------- package.json | 2 +- test/helpers/foundry/foundryup.mts | 58 ++++++ test/helpers/foundry/helpers.mts | 319 +++++++++++++++++++++++++++++ test/helpers/foundry/tsconfig.json | 8 + yarn.lock | 18 ++ 6 files changed, 404 insertions(+), 280 deletions(-) delete mode 100644 foundryup.ts create mode 100755 test/helpers/foundry/foundryup.mts create mode 100644 test/helpers/foundry/helpers.mts create mode 100644 test/helpers/foundry/tsconfig.json diff --git a/foundryup.ts b/foundryup.ts deleted file mode 100644 index 30a8ce9e3c6b..000000000000 --- a/foundryup.ts +++ /dev/null @@ -1,279 +0,0 @@ -#!/usr/bin/env node - -import { execSync } from 'node:child_process'; -import { createWriteStream } from 'node:fs'; -import { mkdir } from 'node:fs/promises'; -import { Agent as HttpAgent, type IncomingMessage } from 'node:http'; -import { - Agent as HttpsAgent, - request as httpRequest, - request as httpsRequest, -} from 'node:https'; -import { join } from 'node:path'; -import { argv, arch as osArch, platform as osPlatform } from 'node:process'; -import { Stream } from 'node:stream'; -import { extract as extractTar } from 'tar'; -import { Source, Open as Unzip } from 'unzipper'; -import yargs from 'yargs/yargs'; -import { toOrange } from './development/webpack/utils/helpers'; - -type BinFormat = 'zip' | 'tar.gz'; - -const BASE_DIR = join(__dirname, 'node_modules', '.bin'); -const FOUNDRY_BIN_DIR = BASE_DIR || join(BASE_DIR, '.foundry', 'bin'); - -const BINS = ['anvil', 'forge', 'cast', 'chisel'] as const; -const { - repo, - version: { version, tag }, - arch, - platform, - binaries, -} = yargs() - // Ensure unrecognized commands/options are reported as errors. - .strict() - // disable yargs's version, as it doesn't make sense here - .version(false) - // use the scriptName in `--help` output - .scriptName('yarn foundryup') - // wrap output at a maximum of 120 characters or `process.stdout.columns` - .wrap(Math.min(120, process.stdout.columns)) - // enable the `--config` command, which allows the user to specify a custom - // config file containing webpack options - .config() - .parserConfiguration({ - 'strip-aliased': true, - 'strip-dashed': true, - }) - // enable ENV parsing, which allows the user to specify fondryup options via - // environment variables prefixed with `FOUNDRYUP_` - .env('FOUNDRYUP') - .updateStrings({ - 'Options:': toOrange('Options:'), - 'Examples:': toOrange('Examples:'), - }) - .option('binaries', { - alias: 'b', - type: 'string', - array: true, - multiple: true, - description: 'Specify the binaries to install', - default: ['anvil'] as (typeof BINS)[number][], - choices: BINS, - }) - .option('repo', { - alias: 'r', - type: 'string', - description: 'Specify the repository', - default: 'foundry-rs/foundry', - }) - .option('version', { - alias: 'v', - type: 'string', - description: 'Specify the version', - default: 'nightly', - coerce: (rawVersion) => { - if (/^nightly/u.test(rawVersion)) { - return { version: 'nightly', tag: rawVersion }; - } else if (/^\d/u.test(rawVersion)) { - return { version: `v${rawVersion}`, tag: rawVersion }; - } - return { version: rawVersion, tag: rawVersion }; - }, - }) - .option('arch', { - description: 'Specify the architecture', - default: osArch === 'arm' ? 'arm64' : 'amd64', - choices: ['amd64', 'arm64'] as const, - coerce: (rawArch: NodeJS.Architecture) => { - return rawArch === 'arm' ? 'arm64' : 'amd64'; - }, - }) - .option('platform', { - type: 'string', - description: 'Specify the platform', - default: osPlatform, - choices: ['win32', 'linux', 'darwin'] as const, - }) - .parseSync(argv.slice(2)); - -// Print the banner -banner(); - -(async function main() { - say(`installing foundry (version ${version}, tag ${tag})`); - - const ext: BinFormat = platform === 'win32' ? 'zip' : 'tar.gz'; - const RELEASE_URL = `https://github.com/${repo}/releases/download/${tag}/`; - const BIN_ARCHIVE_URL = `${RELEASE_URL}foundry_${version}_${platform}_${arch}.${ext}`; - - say(`downloading ${binaries.join(', ')}`); - await downloadAndExtract(ext, new URL(BIN_ARCHIVE_URL), FOUNDRY_BIN_DIR); - - for (const bin of binaries) { - const binPath = join(FOUNDRY_BIN_DIR, bin); - say(`installed - ${getVersion(binPath)}`); - } - - say('done!'); -})(); - -// Helper Functions -function say(message: string) { - console.log(`foundryup: ${message}`); -} - -function banner() { - console.log(` -.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx - - ╔═╗ ╔═╗ ╦ ╦ ╔╗╔ ╔╦╗ ╦═╗ ╦ ╦ Portable and modular toolkit - ╠╣ ║ ║ ║ ║ ║║║ ║║ ╠╦╝ ╚╦╝ for Ethereum Application Development - ╚ ╚═╝ ╚═╝ ╝╚╝ ═╩╝ ╩╚═ ╩ written in Rust. - -.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx - -Repo : https://github.com/foundry-rs/ -Book : https://book.getfoundry.sh/ -Chat : https://t.me/foundry_rs/ -Support : https://t.me/foundry_support/ -Contribute : https://github.com/orgs/foundry-rs/projects/2/ - -.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx -`); -} - -async function _download( - url: URL, - options: { - method?: 'GET' | 'HEAD'; - headers?: Record; - agent?: HttpAgent; - } = {}, - redirects: number = 0, -): Promise { - const MAX_REDIRECTS = 5; - const request = url.protocol === 'https:' ? httpsRequest : httpRequest; - return new Promise((resolve, reject) => { - request(url, options, (res) => { - const { statusCode, statusMessage, headers } = res; - // Handle redirects - if ( - statusCode && - statusCode >= 300 && - statusCode < 400 && - headers.location - ) { - if (redirects >= MAX_REDIRECTS) { - reject(new Error('Too many redirects')); - res.resume(); // Consume response data to free up memory - return; - } - // Resolve relative redirects - const redirectUrl = new URL(headers.location, url); - res.resume(); // Consume response data to free up memory - - // Follow the redirect - _download(redirectUrl, options, redirects + 1) - .then(resolve) - .catch(reject); - return; - } - - // Check for HTTP errors - if (!statusCode || statusCode < 200 || statusCode >= 300) { - reject( - new Error( - `Request Failed. Status Code: ${statusCode} - ${statusMessage}`, - ), - ); - res.resume(); // Consume response data to free up memory - return; - } - - // Resolve with response stream - resolve(res); - }) - .on('error', (e: Error) => { - reject(e); - }) - .end(); - }); -} - -async function download( - url: URL, - options?: { - method?: 'GET' | 'HEAD'; - headers?: Record; - agent?: HttpAgent; - }, -): Promise { - return _download(url, options); -} - -async function downloadAndExtract(format: BinFormat, url: URL, cwd: string) { - await mkdir(cwd, { recursive: true }); - - // eslint-disable-next-line no-async-promise-executor - return await new Promise(async (resolve, reject) => { - if (format === 'zip') { - const agent = new (url.protocol === 'http' ? HttpAgent : HttpsAgent)({ - keepAlive: true, - }); - const source: Source = { - stream(offset: number, length: number) { - const passThrough = new Stream.PassThrough(); - const options = { - agent, - headers: { - range: `bytes=${offset}-${length ? offset + length : ''}`, - }, - }; - download(url, options).then( - (response) => response.pipe(passThrough), - (error: Error) => passThrough.emit('error', error), - ); - return passThrough; - }, - async size() { - const response = await download(url, { agent, method: 'HEAD' }); - response.resume(); // Consume response data to free up memory - const contentLength = response.headers['content-length']; - return contentLength ? parseInt(contentLength, 10) : 0; - }, - }; - const { files } = await Unzip.custom(source); - for await (const file of files) { - if (file.type !== 'File') { - continue; - } - // remove `.exe` from the path to get the binary name - const path = file.path.slice(0, -4) as (typeof BINS)[number]; - // ignore files that are not in the list of binaries - if (!binaries.includes(path)) { - continue; - } - // write the binary to the destination - const dest = join(cwd, file.path); - const stream = file.stream().pipe(createWriteStream(dest)); - stream.on('finish', resolve).on('error', reject); - } - } else { - // write the binaries to the destination - const stream = (await download(url)).pipe(extractTar({ cwd }, binaries)); - stream.on('finish', resolve).on('error', reject); - } - }); -} - -function getVersion(binPath: string): string { - try { - const result = execSync(`${binPath} --version`, { - encoding: 'utf8', - }).trim(); - return result; - } catch { - return 'unknown version'; - } -} diff --git a/package.json b/package.json index 39500fe8782e..9ed25a2d4b72 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "webpack": "tsx ./development/webpack/launch.ts", "webpack:clearcache": "rimraf node_modules/.cache/webpack", - "postinstall": "yarn webpack:clearcache && tsx foundryup", + "postinstall": "yarn webpack:clearcache && tsx --tsconfig ./test/helpers/foundry/tsconfig.json ./test/helpers/foundry/foundryup.mts", "env:e2e": "SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' yarn", "start": "yarn build:dev dev --apply-lavamoat=false --snow=false", "start:with-state": "node ./app/scripts/start-with-wallet-state.mjs", diff --git a/test/helpers/foundry/foundryup.mts b/test/helpers/foundry/foundryup.mts new file mode 100755 index 000000000000..53621d62a3f1 --- /dev/null +++ b/test/helpers/foundry/foundryup.mts @@ -0,0 +1,58 @@ +#!/usr/bin/env -S node --require "./node_modules/tsx/dist/preflight.cjs" --import "./node_modules/tsx/dist/loader.mjs" + +import { join } from 'node:path'; +import { homedir } from 'node:os'; +import { + BinFormat, + Platform, + extractFrom, + getVersion, + printBanner, + say, + parseArgs, +} from './helpers.mts'; +import { existsSync, mkdirSync, symlinkSync, unlinkSync } from 'node:fs'; + +const { + repo, + version: { version, tag }, + arch, + platform, + binaries, +} = parseArgs(); + +printBanner(); + +say(`installing foundry (version ${version}, tag ${tag})`); + +const ext = platform === Platform.Windows ? BinFormat.Zip : BinFormat.Tar; +const RELEASE_URL = `https://github.com/${repo}/releases/download/${tag}/`; +const BIN_ARCHIVE_URL = `${RELEASE_URL}foundry_${version}_${platform}_${arch}.${ext}`; +const BIN_DIR = join(process.cwd(), 'node_modules', '.bin'); + +say(`downloading ${binaries.join(', ')}`); +const url = new URL(BIN_ARCHIVE_URL); +const cacheDir = join(homedir(), '.cache', 'metamask-extension'); +const cacheKey = Buffer.from( + `${BIN_ARCHIVE_URL}-${binaries.join('_')}`, +).toString('base64url'); +const cachePath = join(cacheDir, cacheKey); +if (!existsSync(cachePath)) { + mkdirSync(cachePath, { recursive: true }); + await extractFrom(url, binaries, cachePath); +} + +for (const file of binaries) { + const path = join(BIN_DIR, file); + try { + // remove existing symlink + unlinkSync(path); + } catch {} + const target = join(cachePath, file); + // create new symlink + symlinkSync(target, path); + // check that it works and log the version + say(`installed - ${getVersion(target)}`); +} + +say('done!'); diff --git a/test/helpers/foundry/helpers.mts b/test/helpers/foundry/helpers.mts new file mode 100644 index 000000000000..1a593844ca78 --- /dev/null +++ b/test/helpers/foundry/helpers.mts @@ -0,0 +1,319 @@ +import { ok } from 'node:assert'; +import { execSync } from 'node:child_process'; +import { createWriteStream } from 'node:fs'; +import { + Agent as HttpAgent, + request as httpRequest, + type IncomingMessage, +} from 'node:http'; +import { Agent as HttpsAgent, request as httpsRequest } from 'node:https'; +import { join, basename, extname } from 'node:path'; +import { + argv, + arch as osArch, + platform as osPlatform, + stdout, +} from 'node:process'; +import { Stream } from 'node:stream'; +import { pipeline } from 'node:stream/promises'; +import { extract as extractTar } from 'tar'; +import { Source, Open as Unzip } from 'unzipper'; +import { alias } from 'yargs'; +import yargs from 'yargs/yargs'; + +export enum BinFormat { + Zip = 'zip', + Tar = 'tar.gz', +} + +export enum Platform { + Windows = 'win32', + Linux = 'linux', + Mac = 'darwin', +} + +export enum Binary { + Anvil = 'anvil', + Forge = 'forge', + Cast = 'cast', + Chisel = 'chisel', +} + +type Options = ReturnType; +type OptionsKeys = keyof Options; + +export function parseArgs(args: string[] = argv.slice(2)) { + const { $0, _, ...parsed } = yargs() + // Ensure unrecognized commands/options are reported as errors. + .strict() + // disable yargs's version, as it doesn't make sense here + .version(false) + // use the scriptName in `--help` output + .scriptName('yarn foundryup') + // wrap output at a maximum of 120 characters or `process.stdout.columns` + .wrap(Math.min(120, stdout.columns)) + // enable the `--config` command, which allows the user to specify a custom + // config file containing webpack options + .config() + .parserConfiguration({ + 'strip-aliased': true, + 'strip-dashed': true, + }) + // enable ENV parsing, which allows the user to specify foundryup options + // via environment variables prefixed with `FOUNDRYUP_` + .env('FOUNDRYUP') + .options(getOptions()) + .parseSync(args); + return parsed as { [key in OptionsKeys]: (typeof parsed)[key] }; +} + +function getOptions() { + return { + binaries: { + alias: 'b', + type: 'array' as const, + multiple: true, + description: 'Specify the binaries to install', + default: [Binary.Anvil], + choices: Object.values(Binary) as Binary[], + }, + repo: { + alias: 'r', + description: 'Specify the repository', + default: 'foundry-rs/foundry', + }, + version: { + alias: 'v', + description: 'Specify the version', + default: 'nightly', + coerce: ( + rawVersion: string, + ): { version: 'nightly' | `v${string}`; tag: string } => { + if (/^nightly/u.test(rawVersion)) { + return { version: 'nightly', tag: rawVersion }; + // we don't validate the version here, we just trust the user + } else if (/^\d/u.test(rawVersion)) { + return { version: `v${rawVersion}`, tag: rawVersion }; + } + throw new Error('Invalid version'); + }, + }, + arch: { + alias: 'a', + description: 'Specify the architecture', + // foundry only handles `amd64` and `arm64` architectures + default: + osArch === 'arm' || osArch === 'arm64' + ? ('arm64' as const) + : ('amd64' as const), + choices: ['amd64', 'arm64'] as const, + }, + platform: { + alias: 'p', + description: 'Specify the platform', + // if `osPlatform` is not a supported Platform yargs will throw an error + default: osPlatform as Platform, + choices: Object.values(Platform) as Platform[], + }, + }; +} + +export function printBanner() { + console.log(` +.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx + + ╔═╗ ╔═╗ ╦ ╦ ╔╗╔ ╔╦╗ ╦═╗ ╦ ╦ Portable and modular toolkit + ╠╣ ║ ║ ║ ║ ║║║ ║║ ╠╦╝ ╚╦╝ for Ethereum Application Development + ╚ ╚═╝ ╚═╝ ╝╚╝ ═╩╝ ╩╚═ ╩ written in Rust. + +.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx + +Repo : https://github.com/foundry-rs/ +Book : https://book.getfoundry.sh/ +Chat : https://t.me/foundry_rs/ +Support : https://t.me/foundry_support/ +Contribute : https://github.com/orgs/foundry-rs/projects/2/ + +.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx +`); +} + +/** + * Log a message to the console. + * + * @param message The message to log + */ +export function say(message: string) { + console.log(`[foundryup] ${message}`); +} + +/** + * Extracts the binaries from the given URL and writes them to the destination. + * + * @param url The URL of the archive to extract the binaries from + * @param binaries The list of binaries to extract + * @param dir The destination directory + * @returns The list of binaries extracted + */ +export async function extractFrom(url: URL, binaries: string[], dir: string) { + const extract = url.pathname.toLowerCase().endsWith(BinFormat.Tar) + ? extractFromTar + : extractFromZip; + return extract(url, binaries, dir); +} + +/** + * Extracts the binaries from a tar archive. + * + * @param url The URL of the archive to extract the binaries from + * @param binaries The list of binaries to extract + * @param dir The destination directory + * @returns The list of binaries extracted + */ +async function extractFromTar(url: URL, binaries: string[], dir: string) { + const dl = startDownload(url); + await pipeline(dl, extractTar({ cwd: dir }, binaries)); +} + +/** + * Extracts the binaries from a zip archive. + * + * @param url The URL of the archive to extract the binaries from + * @param binaries The list of binaries to extract + * @param dir The destination directory + * @returns The list of binaries extracted + */ +async function extractFromZip(url: URL, binaries: string[], dir: string) { + const agent = new (url.protocol === 'http:' ? HttpAgent : HttpsAgent)({ + keepAlive: true, + }); + const source: Source = { + async size() { + const download = startDownload(url, { agent, method: 'HEAD' }); + const response = await download.response(); + const contentLength = response.headers['content-length']; + return contentLength ? parseInt(contentLength, 10) : 0; + }, + stream(offset: number, bytes: number) { + const options = { + agent, + headers: { + range: `bytes=${offset}-${bytes ? offset + bytes : ''}`, + }, + }; + return startDownload(url, options); + }, + }; + + const { files } = await Unzip.custom(source); + const filtered = files.filter(({ path }) => + binaries.includes(basename(path, extname(path))), + ); + ok(filtered.length === binaries.length, 'Failed to extract all binaries'); + return await Promise.all( + filtered.map(async ({ stream, path }) => { + await pipeline(stream(), createWriteStream(join(dir, path))); + }), + ); +} + +type DownloadOptions = { + method?: 'GET' | 'HEAD'; + headers?: Record; + agent?: HttpsAgent | HttpAgent; + maxRedirects?: number; +}; + +/** + * Starts a download from the given URL. + * + * @param url The URL to download from + * @param options The download options + * @param redirects The number of redirects that have occurred + * @returns A stream of the download + */ +function startDownload( + url: URL, + options: DownloadOptions = {}, + redirects: number = 0, +): DownloadStream { + const MAX_REDIRECTS = options.maxRedirects ?? 5; + const request = url.protocol === 'http:' ? httpRequest : httpsRequest; + const stream = new DownloadStream(); + request(url, options, async (response) => { + stream.once('close', () => { + response.destroy(); + }); + + const { statusCode, statusMessage, headers } = response; + // handle redirects + if ( + statusCode && + statusCode >= 300 && + statusCode < 400 && + headers.location + ) { + if (redirects >= MAX_REDIRECTS) { + stream.emit('error', new Error('Too many redirects')); + response.destroy(); + } else { + // note: we don't emit a response until we're done redirecting, because + // handlers only expect it to be emitted once. + await pipeline( + startDownload(new URL(headers.location, url), options, redirects + 1) + // remit the response event to the stream + .once('response', stream.emit.bind(stream, 'response')), + stream, + ).catch(stream.emit.bind(stream, 'error')); + response.destroy(); + } + } + // check for HTTP errors + else if (!statusCode || statusCode < 200 || statusCode >= 300) { + stream.emit( + 'error', + new Error( + `Request to ${url} failed. Status Code: ${statusCode} - ${statusMessage}`, + ), + ); + response.destroy(); + } else { + // resolve with response stream + stream.emit('response', response); + + response.once('error', stream.emit.bind(stream, 'error')); + await pipeline(response, stream).catch(stream.emit.bind(stream, 'error')); + } + }) + .once('error', stream.emit.bind(stream, 'error')) + .end(); + return stream; +} + +export class DownloadStream extends Stream.PassThrough { + async response(): Promise { + return new Promise((resolve, reject) => { + this.once('response', resolve); + this.once('error', reject); + }); + } +} + +/** + * Get the version of the binary at the given path. + * + * @param binPath + * @returns The `--version` reported by the binary + * @throws If the binary fails to report its version + */ +export function getVersion(binPath: string): Buffer { + try { + return execSync(`${binPath} --version`).subarray(0, -1); // ignore newline + } catch (error: unknown) { + const msg = `Failed to get version for ${binPath}`; + if (error instanceof Error) { + throw new Error(`${msg}: ${error.message}`); + } + throw new Error(msg); + } +} diff --git a/test/helpers/foundry/tsconfig.json b/test/helpers/foundry/tsconfig.json new file mode 100644 index 000000000000..6af8922ce66e --- /dev/null +++ b/test/helpers/foundry/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "module": "ESNext", + "target": "ESNext", + "moduleResolution": "Node" + }, + "extends": "../../../tsconfig.json" +} diff --git a/yarn.lock b/yarn.lock index a3c351e13c14..67f1698df13b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11537,6 +11537,13 @@ __metadata: languageName: node linkType: hard +"@types/wtfnode@npm:^0": + version: 0.7.3 + resolution: "@types/wtfnode@npm:0.7.3" + checksum: 10/73d7b2faf57c7337c9541c8e194f2ca380b8ea848144d14f1c7534dd5c3f1b7117c8b113bd9e9de7ff099ad56a03c4e70fdb066294503c37fe88fd11fc2de157 + languageName: node + linkType: hard + "@types/yargs-parser@npm:*, @types/yargs-parser@npm:^21.0.3": version: 21.0.3 resolution: "@types/yargs-parser@npm:21.0.3" @@ -26879,6 +26886,7 @@ __metadata: "@types/watchify": "npm:^3.11.1" "@types/webextension-polyfill": "npm:^0.10.4" "@types/ws": "npm:^8.5.10" + "@types/wtfnode": "npm:^0" "@types/yargs": "npm:^17.0.32" "@types/yargs-parser": "npm:^21.0.3" "@typescript-eslint/eslint-plugin": "npm:^7.10.0" @@ -27096,6 +27104,7 @@ __metadata: webpack-cli: "npm:^5.1.4" webpack-dev-server: "npm:^5.0.3" ws: "npm:^8.17.1" + wtfnode: "npm:^0.9.3" yaml: "npm:^2.4.1" yargs: "npm:^17.7.2" yargs-parser: "npm:^21.1.1" @@ -38186,6 +38195,15 @@ __metadata: languageName: node linkType: hard +"wtfnode@npm:^0.9.3": + version: 0.9.3 + resolution: "wtfnode@npm:0.9.3" + bin: + wtfnode: proxy.js + checksum: 10/986252f94ebb8c977773f3529a0031842b2403fdc5dc776aed0e995641b750bcddcf7b4862f6ba02a8888518ab324854c8a8907a1c622ae95506db51722d04a7 + languageName: node + linkType: hard + "xdg-basedir@npm:^3.0.0": version: 3.0.0 resolution: "xdg-basedir@npm:3.0.0" From 8d55035292551a21bd4a1c2322ab9abb0eaec872 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:51:07 -0500 Subject: [PATCH 23/46] fix --- test/helpers/foundry/helpers.mts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/helpers/foundry/helpers.mts b/test/helpers/foundry/helpers.mts index 1a593844ca78..c2ee85106e6c 100644 --- a/test/helpers/foundry/helpers.mts +++ b/test/helpers/foundry/helpers.mts @@ -18,7 +18,6 @@ import { Stream } from 'node:stream'; import { pipeline } from 'node:stream/promises'; import { extract as extractTar } from 'tar'; import { Source, Open as Unzip } from 'unzipper'; -import { alias } from 'yargs'; import yargs from 'yargs/yargs'; export enum BinFormat { From 628af1aa2e4924cfb97096bf7a317119de29b9a1 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:39:51 -0500 Subject: [PATCH 24/46] polish --- .vscode/package.json-schema.json | 4 ++ package.json | 5 ++- test/helpers/foundry/foundryup.mts | 68 ++++++++++++++++++++---------- test/helpers/foundry/helpers.mts | 54 +++++++++++++++++++++--- 4 files changed, 100 insertions(+), 31 deletions(-) diff --git a/.vscode/package.json-schema.json b/.vscode/package.json-schema.json index 458329d0741c..5ac21e3d5d1d 100644 --- a/.vscode/package.json-schema.json +++ b/.vscode/package.json-schema.json @@ -18,6 +18,10 @@ "type": "string", "description": "Deletes webpack's build cache. Useful to force a rebuild (webpack not detecting changes, node_modules have changed, etc)." }, + "foundryup": { + "type": "string", + "description": "Installs foundry's Anvil. Run `yarn foundryup --help` for advanced usage." + }, "postinstall": { "type": "string", "description": "Runs automatically after running `yarn` (`yarn install`) in order to prime the webpack dev build." diff --git a/package.json b/package.json index 9ed25a2d4b72..6ea588080e73 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "scripts": { "webpack": "tsx ./development/webpack/launch.ts", "webpack:clearcache": "rimraf node_modules/.cache/webpack", - "postinstall": "yarn webpack:clearcache && tsx --tsconfig ./test/helpers/foundry/tsconfig.json ./test/helpers/foundry/foundryup.mts", + "foundryup": "tsx --tsconfig ./test/helpers/foundry/tsconfig.json ./test/helpers/foundry/foundryup.mts", + "postinstall": "yarn webpack:clearcache", "env:e2e": "SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' yarn", "start": "yarn build:dev dev --apply-lavamoat=false --snow=false", "start:with-state": "node ./app/scripts/start-with-wallet-state.mjs", @@ -691,7 +692,7 @@ "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 20", + "node": ">= 20.17", "yarn": "^4.4.1" }, "lavamoat": { diff --git a/test/helpers/foundry/foundryup.mts b/test/helpers/foundry/foundryup.mts index 53621d62a3f1..cef939a5eea3 100755 --- a/test/helpers/foundry/foundryup.mts +++ b/test/helpers/foundry/foundryup.mts @@ -1,6 +1,6 @@ #!/usr/bin/env -S node --require "./node_modules/tsx/dist/preflight.cjs" --import "./node_modules/tsx/dist/loader.mjs" -import { join } from 'node:path'; +import { join, relative } from 'node:path'; import { homedir } from 'node:os'; import { BinFormat, @@ -10,8 +10,12 @@ import { printBanner, say, parseArgs, + isCodedError, + noop, } from './helpers.mts'; -import { existsSync, mkdirSync, symlinkSync, unlinkSync } from 'node:fs'; +import { Dir } from 'node:fs'; +import { opendir, symlink, unlink, copyFile } from 'node:fs/promises'; +import { createHash } from 'node:crypto'; const { repo, @@ -23,35 +27,53 @@ const { printBanner(); -say(`installing foundry (version ${version}, tag ${tag})`); +say( + `installing foundry (version ${version}, tag ${tag}) for ${platform} ${arch}`, +); const ext = platform === Platform.Windows ? BinFormat.Zip : BinFormat.Tar; -const RELEASE_URL = `https://github.com/${repo}/releases/download/${tag}/`; -const BIN_ARCHIVE_URL = `${RELEASE_URL}foundry_${version}_${platform}_${arch}.${ext}`; +const BIN_ARCHIVE_URL = `https://github.com/${repo}/releases/download/${tag}/foundry_${version}_${platform}_${arch}.${ext}`; const BIN_DIR = join(process.cwd(), 'node_modules', '.bin'); +const CACHE_DIR = join(homedir(), '.cache', 'metamask-extension'); say(`downloading ${binaries.join(', ')}`); const url = new URL(BIN_ARCHIVE_URL); -const cacheDir = join(homedir(), '.cache', 'metamask-extension'); -const cacheKey = Buffer.from( - `${BIN_ARCHIVE_URL}-${binaries.join('_')}`, -).toString('base64url'); -const cachePath = join(cacheDir, cacheKey); -if (!existsSync(cachePath)) { - mkdirSync(cachePath, { recursive: true }); - await extractFrom(url, binaries, cachePath); -} +const cacheKey = createHash('sha256') + .update(`${BIN_ARCHIVE_URL}-${binaries.join('_')}`) + .digest('hex'); +const cachePath = join(CACHE_DIR, cacheKey); -for (const file of binaries) { - const path = join(BIN_DIR, file); +// check the cache, if the cache dir exists we assume the correct files do, too +let downloadedBinaries: Dir; +try { + downloadedBinaries = await opendir(cachePath); +} catch (e: unknown) { + if ((e as NodeJS.ErrnoException).code === 'ENOENT') { + // directory doesn't exist, download and extract + await extractFrom(url, binaries, cachePath); + downloadedBinaries = await opendir(cachePath); + } else { + throw e; + } +} +for await (const file of downloadedBinaries) { + if (!file.isFile()) continue; + const target = join(file.parentPath, file.name); + const path = join(BIN_DIR, relative(cachePath, target)); + // clean up any existing files or symlinks + await unlink(path).catch(noop); try { - // remove existing symlink - unlinkSync(path); - } catch {} - const target = join(cachePath, file); - // create new symlink - symlinkSync(target, path); - // check that it works and log the version + // create new symlink + await symlink(target, path); + } catch (e) { + if (!(isCodedError(e) && ['EPERM', 'EXDEV'].includes(e.code))) { + throw e; + } + // symlinking can fail if its a cross-device/filesystem link, or for + // permissions reasons, so we'll just copy the file instead + await copyFile(target, path); + } + // check that it works by logging the version say(`installed - ${getVersion(target)}`); } diff --git a/test/helpers/foundry/helpers.mts b/test/helpers/foundry/helpers.mts index c2ee85106e6c..8d5406a79a2c 100644 --- a/test/helpers/foundry/helpers.mts +++ b/test/helpers/foundry/helpers.mts @@ -1,13 +1,14 @@ import { ok } from 'node:assert'; import { execSync } from 'node:child_process'; import { createWriteStream } from 'node:fs'; +import { rename, mkdir, rm } from 'node:fs/promises'; import { Agent as HttpAgent, request as httpRequest, type IncomingMessage, } from 'node:http'; import { Agent as HttpsAgent, request as httpsRequest } from 'node:https'; -import { join, basename, extname } from 'node:path'; +import { join, basename, extname, relative } from 'node:path'; import { argv, arch as osArch, @@ -20,6 +21,8 @@ import { extract as extractTar } from 'tar'; import { Source, Open as Unzip } from 'unzipper'; import yargs from 'yargs/yargs'; +export function noop() {} + export enum BinFormat { Zip = 'zip', Tar = 'tar.gz', @@ -158,7 +161,31 @@ export async function extractFrom(url: URL, binaries: string[], dir: string) { const extract = url.pathname.toLowerCase().endsWith(BinFormat.Tar) ? extractFromTar : extractFromZip; - return extract(url, binaries, dir); + // write all files to a temporary directory first, then rename to the final + // destination to avoid accidental partial extraction. We don't use + // `os.tmpdir` for this because `rename` will fail if the directories are on + // different file systems. + const tempDir = dir + '.downloading'; + const rmOpts = { recursive: true, maxRetries: 3, force: true }; + try { + // clean up any previous in-progress downloads + await rm(tempDir, rmOpts); + // make the temporary directory to extract the binaries to + await mkdir(tempDir, { recursive: true }); + const downloads = await extract(url, binaries, tempDir); + ok(downloads.length === binaries.length, 'Failed to extract all binaries'); + + // everything has been extracted; move the files to their final destination + await rename(tempDir, dir); + // return the list of extracted binaries + return downloads.map((file) => join(dir, relative(tempDir, file))); + } catch (e) { + // if things fail for any reason try to clean up a bit. it is very important + // to not leave `dir` behind, as its existence is a signal that the binaries + // are installed. + await Promise.all([rm(tempDir, rmOpts), rm(dir, rmOpts)]).catch(noop); + throw e; + } } /** @@ -170,8 +197,14 @@ export async function extractFrom(url: URL, binaries: string[], dir: string) { * @returns The list of binaries extracted */ async function extractFromTar(url: URL, binaries: string[], dir: string) { - const dl = startDownload(url); - await pipeline(dl, extractTar({ cwd: dir }, binaries)); + const downloads: string[] = []; + await pipeline( + startDownload(url), + extractTar({ cwd: dir }, binaries).on('entry', ({ absolute }) => + downloads.push(absolute), + ), + ); + return downloads; } /** @@ -208,10 +241,11 @@ async function extractFromZip(url: URL, binaries: string[], dir: string) { const filtered = files.filter(({ path }) => binaries.includes(basename(path, extname(path))), ); - ok(filtered.length === binaries.length, 'Failed to extract all binaries'); return await Promise.all( filtered.map(async ({ stream, path }) => { - await pipeline(stream(), createWriteStream(join(dir, path))); + const dest = join(dir, path); + await pipeline(stream(), createWriteStream(dest)); + return dest; }), ); } @@ -316,3 +350,11 @@ export function getVersion(binPath: string): Buffer { throw new Error(msg); } } + +export function isCodedError( + error: unknown, +): error is Error & { code: string } { + return ( + error instanceof Error && 'code' in error && typeof error.code === 'string' + ); +} From 15cb1a17317112375fbbe59d359404ded67d78a3 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:11:18 -0500 Subject: [PATCH 25/46] add `cache clean` command --- test/helpers/foundry/foundryup.mts | 15 ++++++++++++--- test/helpers/foundry/helpers.mts | 28 +++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/test/helpers/foundry/foundryup.mts b/test/helpers/foundry/foundryup.mts index cef939a5eea3..718827645a4f 100755 --- a/test/helpers/foundry/foundryup.mts +++ b/test/helpers/foundry/foundryup.mts @@ -14,16 +14,26 @@ import { noop, } from './helpers.mts'; import { Dir } from 'node:fs'; -import { opendir, symlink, unlink, copyFile } from 'node:fs/promises'; +import { opendir, symlink, unlink, copyFile, rm } from 'node:fs/promises'; import { createHash } from 'node:crypto'; +const parsedArgs = parseArgs(); + +const CACHE_DIR = join(homedir(), '.cache', 'metamask-extension'); + +if (parsedArgs.command === 'cache clean') { + await rm(CACHE_DIR, { recursive: true, force: true }); + say('done!'); + process.exit(0); +} + const { repo, version: { version, tag }, arch, platform, binaries, -} = parseArgs(); +} = parsedArgs.options; printBanner(); @@ -34,7 +44,6 @@ say( const ext = platform === Platform.Windows ? BinFormat.Zip : BinFormat.Tar; const BIN_ARCHIVE_URL = `https://github.com/${repo}/releases/download/${tag}/foundry_${version}_${platform}_${arch}.${ext}`; const BIN_DIR = join(process.cwd(), 'node_modules', '.bin'); -const CACHE_DIR = join(homedir(), '.cache', 'metamask-extension'); say(`downloading ${binaries.join(', ')}`); const url = new URL(BIN_ARCHIVE_URL); diff --git a/test/helpers/foundry/helpers.mts b/test/helpers/foundry/helpers.mts index 8d5406a79a2c..e9e390d206fd 100644 --- a/test/helpers/foundry/helpers.mts +++ b/test/helpers/foundry/helpers.mts @@ -19,6 +19,7 @@ import { Stream } from 'node:stream'; import { pipeline } from 'node:stream/promises'; import { extract as extractTar } from 'tar'; import { Source, Open as Unzip } from 'unzipper'; +import { Argv, InferredOptionTypes } from 'yargs'; import yargs from 'yargs/yargs'; export function noop() {} @@ -43,6 +44,9 @@ export enum Binary { type Options = ReturnType; type OptionsKeys = keyof Options; +type ParsedOptions = { + [key in OptionsKeys]: InferredOptionTypes[key]; +}; export function parseArgs(args: string[] = argv.slice(2)) { const { $0, _, ...parsed } = yargs() @@ -54,9 +58,6 @@ export function parseArgs(args: string[] = argv.slice(2)) { .scriptName('yarn foundryup') // wrap output at a maximum of 120 characters or `process.stdout.columns` .wrap(Math.min(120, stdout.columns)) - // enable the `--config` command, which allows the user to specify a custom - // config file containing webpack options - .config() .parserConfiguration({ 'strip-aliased': true, 'strip-dashed': true, @@ -64,9 +65,26 @@ export function parseArgs(args: string[] = argv.slice(2)) { // enable ENV parsing, which allows the user to specify foundryup options // via environment variables prefixed with `FOUNDRYUP_` .env('FOUNDRYUP') - .options(getOptions()) + .command(['$0', 'install'], 'Install foundry binaries', getOptions()) + .command('cache', '', (yargs) => { + yargs.command('clean', 'Remove the shared cache files').demandCommand(); + }) .parseSync(args); - return parsed as { [key in OptionsKeys]: (typeof parsed)[key] }; + + const command = _.join(' '); + switch (command) { + case 'cache clean': + return { + command, + } as const; + case '': + case 'install': + return { + command: 'install', + options: parsed as ParsedOptions, + } as const; + } + throw new Error(`Unknown command: '${command}'`); } function getOptions() { From d9c2f36284d2cde7c3df8002872a027dc2f2a09a Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:22:15 -0500 Subject: [PATCH 26/46] fix yarn lock --- yarn.lock | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/yarn.lock b/yarn.lock index 67f1698df13b..a3c351e13c14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11537,13 +11537,6 @@ __metadata: languageName: node linkType: hard -"@types/wtfnode@npm:^0": - version: 0.7.3 - resolution: "@types/wtfnode@npm:0.7.3" - checksum: 10/73d7b2faf57c7337c9541c8e194f2ca380b8ea848144d14f1c7534dd5c3f1b7117c8b113bd9e9de7ff099ad56a03c4e70fdb066294503c37fe88fd11fc2de157 - languageName: node - linkType: hard - "@types/yargs-parser@npm:*, @types/yargs-parser@npm:^21.0.3": version: 21.0.3 resolution: "@types/yargs-parser@npm:21.0.3" @@ -26886,7 +26879,6 @@ __metadata: "@types/watchify": "npm:^3.11.1" "@types/webextension-polyfill": "npm:^0.10.4" "@types/ws": "npm:^8.5.10" - "@types/wtfnode": "npm:^0" "@types/yargs": "npm:^17.0.32" "@types/yargs-parser": "npm:^21.0.3" "@typescript-eslint/eslint-plugin": "npm:^7.10.0" @@ -27104,7 +27096,6 @@ __metadata: webpack-cli: "npm:^5.1.4" webpack-dev-server: "npm:^5.0.3" ws: "npm:^8.17.1" - wtfnode: "npm:^0.9.3" yaml: "npm:^2.4.1" yargs: "npm:^17.7.2" yargs-parser: "npm:^21.1.1" @@ -38195,15 +38186,6 @@ __metadata: languageName: node linkType: hard -"wtfnode@npm:^0.9.3": - version: 0.9.3 - resolution: "wtfnode@npm:0.9.3" - bin: - wtfnode: proxy.js - checksum: 10/986252f94ebb8c977773f3529a0031842b2403fdc5dc776aed0e995641b750bcddcf7b4862f6ba02a8888518ab324854c8a8907a1c622ae95506db51722d04a7 - languageName: node - linkType: hard - "xdg-basedir@npm:^3.0.0": version: 3.0.0 resolution: "xdg-basedir@npm:3.0.0" From d211f1d6adbfdeeb81351a25bb5f242fbffa03fc Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:30:34 -0500 Subject: [PATCH 27/46] more polish --- .circleci/config.yml | 2 +- test/helpers/foundry/foundryup.mts | 24 +++++++++-------- test/helpers/foundry/helpers.mts | 43 +++++++++++++++++++----------- 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 03cb5091da4e..36eaf28b0462 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ executors: NODE_OPTIONS: --max_old_space_size=3072 node-linux-medium: machine: - image: ubuntu-2404:current + image: ubuntu-2404:2024.08.1 resource_class: medium #// linux medium: 2 CPUs, 7.5 GB RAM, 10 credits/min environment: NODE_OPTIONS: --max_old_space_size=6144 diff --git a/test/helpers/foundry/foundryup.mts b/test/helpers/foundry/foundryup.mts index 718827645a4f..62629d620c91 100755 --- a/test/helpers/foundry/foundryup.mts +++ b/test/helpers/foundry/foundryup.mts @@ -2,6 +2,10 @@ import { join, relative } from 'node:path'; import { homedir } from 'node:os'; +import { Dir } from 'node:fs'; +import { opendir, symlink, unlink, copyFile, rm } from 'node:fs/promises'; +import { createHash } from 'node:crypto'; +import { exit, cwd } from 'node:process'; import { BinFormat, Platform, @@ -13,9 +17,6 @@ import { isCodedError, noop, } from './helpers.mts'; -import { Dir } from 'node:fs'; -import { opendir, symlink, unlink, copyFile, rm } from 'node:fs/promises'; -import { createHash } from 'node:crypto'; const parsedArgs = parseArgs(); @@ -24,7 +25,7 @@ const CACHE_DIR = join(homedir(), '.cache', 'metamask-extension'); if (parsedArgs.command === 'cache clean') { await rm(CACHE_DIR, { recursive: true, force: true }); say('done!'); - process.exit(0); + exit(0); } const { @@ -36,28 +37,29 @@ const { } = parsedArgs.options; printBanner(); - -say( - `installing foundry (version ${version}, tag ${tag}) for ${platform} ${arch}`, -); +const bins = binaries.join(', '); +say(`fetching ${bins} ${version} for ${platform} ${arch}`); const ext = platform === Platform.Windows ? BinFormat.Zip : BinFormat.Tar; const BIN_ARCHIVE_URL = `https://github.com/${repo}/releases/download/${tag}/foundry_${version}_${platform}_${arch}.${ext}`; -const BIN_DIR = join(process.cwd(), 'node_modules', '.bin'); +const BIN_DIR = join(cwd(), 'node_modules', '.bin'); -say(`downloading ${binaries.join(', ')}`); const url = new URL(BIN_ARCHIVE_URL); const cacheKey = createHash('sha256') - .update(`${BIN_ARCHIVE_URL}-${binaries.join('_')}`) + .update(`${BIN_ARCHIVE_URL}-${bins}`) .digest('hex'); const cachePath = join(CACHE_DIR, cacheKey); // check the cache, if the cache dir exists we assume the correct files do, too let downloadedBinaries: Dir; try { + say(`checking cache`); downloadedBinaries = await opendir(cachePath); + say(`found binaries in cache`); } catch (e: unknown) { + say(`binaries not in cache`); if ((e as NodeJS.ErrnoException).code === 'ENOENT') { + say(`installing from ${url.toString()}`); // directory doesn't exist, download and extract await extractFrom(url, binaries, cachePath); downloadedBinaries = await opendir(cachePath); diff --git a/test/helpers/foundry/helpers.mts b/test/helpers/foundry/helpers.mts index e9e390d206fd..5b2355761de0 100644 --- a/test/helpers/foundry/helpers.mts +++ b/test/helpers/foundry/helpers.mts @@ -9,17 +9,13 @@ import { } from 'node:http'; import { Agent as HttpsAgent, request as httpsRequest } from 'node:https'; import { join, basename, extname, relative } from 'node:path'; -import { - argv, - arch as osArch, - platform as osPlatform, - stdout, -} from 'node:process'; +import { argv, stdout } from 'node:process'; +import { arch, platform } from 'node:os'; import { Stream } from 'node:stream'; import { pipeline } from 'node:stream/promises'; import { extract as extractTar } from 'tar'; import { Source, Open as Unzip } from 'unzipper'; -import { Argv, InferredOptionTypes } from 'yargs'; +import { InferredOptionTypes } from 'yargs'; import yargs from 'yargs/yargs'; export function noop() {} @@ -56,7 +52,7 @@ export function parseArgs(args: string[] = argv.slice(2)) { .version(false) // use the scriptName in `--help` output .scriptName('yarn foundryup') - // wrap output at a maximum of 120 characters or `process.stdout.columns` + // wrap output at a maximum of 120 characters or `stdout.columns` .wrap(Math.min(120, stdout.columns)) .parserConfiguration({ 'strip-aliased': true, @@ -111,7 +107,7 @@ function getOptions() { ): { version: 'nightly' | `v${string}`; tag: string } => { if (/^nightly/u.test(rawVersion)) { return { version: 'nightly', tag: rawVersion }; - // we don't validate the version here, we just trust the user + // we don't validate the version much, we just trust the user } else if (/^\d/u.test(rawVersion)) { return { version: `v${rawVersion}`, tag: rawVersion }; } @@ -121,23 +117,40 @@ function getOptions() { arch: { alias: 'a', description: 'Specify the architecture', - // foundry only handles `amd64` and `arm64` architectures - default: - osArch === 'arm' || osArch === 'arm64' - ? ('arm64' as const) - : ('amd64' as const), + default: getSystemArch(), choices: ['amd64', 'arm64'] as const, }, platform: { alias: 'p', description: 'Specify the platform', // if `osPlatform` is not a supported Platform yargs will throw an error - default: osPlatform as Platform, + default: platform() as Platform, choices: Object.values(Platform) as Platform[], }, }; } +function getSystemArch(): 'amd64' | 'arm64' { + const architecture = arch(); + if (architecture.startsWith('arm')) { + // if `arm*`, use `arm64` + return 'arm64'; + } else if (architecture === 'x64') { + // if `x64`, it _might_ be amd64 running via Rosetta on Apple Silicon + // (arm64). we can check this by running `sysctl.proc_translated` and + // checking the output; `1` === `arm64`. This can happen if the user is + // running an amd64 version of Node on Apple Silicon. We want to use the + // binaries native to the system for better performance. + try { + if (execSync('sysctl -n sysctl.proc_translated 2>/dev/null')[0] === 1) { + return 'arm64'; + } + } catch {} // if `sysctl` check fails, assume native `amd64` + } + + return 'amd64'; // Default for all other architectures +} + export function printBanner() { console.log(` .xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx.xOx From f82825cec398f60fe50f48ee8770e5dbdc529215 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:38:54 -0500 Subject: [PATCH 28/46] align node versions in CI and local --- .circleci/config.yml | 6 +++--- .nvmrc | 2 +- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 36eaf28b0462..7fb1e01f174b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,13 +3,13 @@ version: 2.1 executors: node-browsers-small: docker: - - image: cimg/node:20.17-browsers + - image: cimg/node:20.16.0-browsers resource_class: small environment: NODE_OPTIONS: --max_old_space_size=2048 node-browsers-medium: docker: - - image: cimg/node:20.17-browsers + - image: cimg/node:20.16.0-browsers resource_class: medium environment: NODE_OPTIONS: --max_old_space_size=3072 @@ -21,7 +21,7 @@ executors: NODE_OPTIONS: --max_old_space_size=6144 node-browsers-medium-plus: docker: - - image: cimg/node:20.17-browsers + - image: cimg/node:20.16.0-browsers resource_class: medium+ environment: NODE_OPTIONS: --max_old_space_size=4096 diff --git a/.nvmrc b/.nvmrc index 8cfab175cf90..80a9956e1e50 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20.17 +v20.16.0 diff --git a/package.json b/package.json index 6ea588080e73..6c1f17cb4bda 100644 --- a/package.json +++ b/package.json @@ -692,7 +692,7 @@ "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 20.17", + "node": ">= 20.16.0", "yarn": "^4.4.1" }, "lavamoat": { From d926ecd93b52ba7aeee42c98c2b9d2890d03547c Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:05:00 -0500 Subject: [PATCH 29/46] align again, lavamoat doesn't support 20.16 --- .circleci/config.yml | 8 ++++---- .nvmrc | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7fb1e01f174b..fc839ce176a6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,25 +3,25 @@ version: 2.1 executors: node-browsers-small: docker: - - image: cimg/node:20.16.0-browsers + - image: cimg/node:20.12.0-browsers resource_class: small environment: NODE_OPTIONS: --max_old_space_size=2048 node-browsers-medium: docker: - - image: cimg/node:20.16.0-browsers + - image: cimg/node:20.12.0-browsers resource_class: medium environment: NODE_OPTIONS: --max_old_space_size=3072 node-linux-medium: machine: - image: ubuntu-2404:2024.08.1 + image: ubuntu-2404:2024.05.1 resource_class: medium #// linux medium: 2 CPUs, 7.5 GB RAM, 10 credits/min environment: NODE_OPTIONS: --max_old_space_size=6144 node-browsers-medium-plus: docker: - - image: cimg/node:20.16.0-browsers + - image: cimg/node:20.12.0-browsers resource_class: medium+ environment: NODE_OPTIONS: --max_old_space_size=4096 diff --git a/.nvmrc b/.nvmrc index 80a9956e1e50..9ff19494c8f1 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20.16.0 +v20.12.0 diff --git a/package.json b/package.json index 6c1f17cb4bda..a1d9154c5287 100644 --- a/package.json +++ b/package.json @@ -692,7 +692,7 @@ "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 20.16.0", + "node": ">= 20.12.0", "yarn": "^4.4.1" }, "lavamoat": { From d080ea77fa707658a0466bec5b0e71970a59d5d3 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:58:03 -0500 Subject: [PATCH 30/46] lavamoat doesn't work with some node versions --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1d9154c5287..e75a19cded98 100644 --- a/package.json +++ b/package.json @@ -692,7 +692,7 @@ "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 20.12.0", + "node": ">20.12.0 <20.15.0 || >=20.17.0", "yarn": "^4.4.1" }, "lavamoat": { From 7b8f51bb2069d55ab73b6fd6391be39fe3f36ed0 Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 19 Nov 2024 11:31:11 +0100 Subject: [PATCH 31/46] rebase --- .depcheckrc.yml | 4 ++- lavamoat/browserify/beta/policy.json | 11 +++++++ lavamoat/browserify/flask/policy.json | 11 +++++++ lavamoat/browserify/main/policy.json | 11 +++++++ lavamoat/browserify/mmi/policy.json | 11 +++++++ lavamoat/build-system/policy.json | 20 +++++++++-- .../snap-account-contract-interaction.spec.ts | 6 ++-- yarn.lock | 33 +++++++++++-------- 8 files changed, 88 insertions(+), 19 deletions(-) diff --git a/.depcheckrc.yml b/.depcheckrc.yml index bafacc56c918..5260be984692 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -70,7 +70,6 @@ ignores: - 'crypto-browserify' # polyfill - 'process' # polyfill - 'stream-http' # polyfill - - 'rimraf' # misc: install helper - 'json-schema-to-ts' # misc: typescript helper - 'https-browserify' # polyfill - 'path-browserify' # polyfill @@ -80,6 +79,9 @@ ignores: - '@babel/plugin-transform-logical-assignment-operators' # trezor - 'ts-mixer' + - '@testing-library/dom' + - 'mini-css-extract-plugin' + - 'webpack-cli' # files depcheck should not parse ignorePatterns: diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 668cba784486..16b2fb1b4436 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -5841,6 +5841,17 @@ "crypto": true } }, + "wait-on>rxjs": { + "globals": { + "cancelAnimationFrame": true, + "clearInterval": true, + "clearTimeout": true, + "performance": true, + "requestAnimationFrame": true, + "setInterval.apply": true, + "setTimeout.apply": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 668cba784486..16b2fb1b4436 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -5841,6 +5841,17 @@ "crypto": true } }, + "wait-on>rxjs": { + "globals": { + "cancelAnimationFrame": true, + "clearInterval": true, + "clearTimeout": true, + "performance": true, + "requestAnimationFrame": true, + "setInterval.apply": true, + "setTimeout.apply": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 668cba784486..16b2fb1b4436 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -5841,6 +5841,17 @@ "crypto": true } }, + "wait-on>rxjs": { + "globals": { + "cancelAnimationFrame": true, + "clearInterval": true, + "clearTimeout": true, + "performance": true, + "requestAnimationFrame": true, + "setInterval.apply": true, + "setTimeout.apply": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 09ddb5ce65a3..82e5d46cafac 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -5909,6 +5909,17 @@ "crypto": true } }, + "wait-on>rxjs": { + "globals": { + "cancelAnimationFrame": true, + "clearInterval": true, + "clearTimeout": true, + "performance": true, + "requestAnimationFrame": true, + "setInterval.apply": true, + "setTimeout.apply": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index 1cadff4100d7..718ff4ba5b62 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -3004,7 +3004,7 @@ "eslint-plugin-prettier": true, "eslint-plugin-react": true, "eslint-plugin-react-hooks": true, - "eslint>ajv": true, + "eslint>@eslint/eslintrc>ajv": true, "eslint>globals": true, "eslint>ignore": true, "eslint>minimatch": true, @@ -3012,6 +3012,17 @@ "nock>debug": true } }, + "eslint>@eslint/eslintrc>ajv": { + "globals": { + "console": true + }, + "packages": { + "@metamask/snaps-utils>fast-json-stable-stringify": true, + "eslint>@eslint/eslintrc>ajv>json-schema-traverse": true, + "eslint>fast-deep-equal": true, + "uri-js": true + } + }, "eslint>@eslint/eslintrc>import-fresh": { "builtin": { "path.dirname": true @@ -8466,12 +8477,17 @@ "process.stdout.write": true }, "packages": { - "eslint>ajv": true, "lodash": true, + "stylelint>table>ajv": true, "stylelint>table>slice-ansi": true, "stylelint>table>string-width": true } }, + "stylelint>table>ajv": { + "packages": { + "eslint>fast-deep-equal": true + } + }, "stylelint>table>slice-ansi": { "packages": { "stylelint>table>slice-ansi>ansi-styles": true, diff --git a/test/e2e/tests/account/snap-account-contract-interaction.spec.ts b/test/e2e/tests/account/snap-account-contract-interaction.spec.ts index e4753f5ff05b..b5cfd4d2707c 100644 --- a/test/e2e/tests/account/snap-account-contract-interaction.spec.ts +++ b/test/e2e/tests/account/snap-account-contract-interaction.spec.ts @@ -2,7 +2,7 @@ import { Suite } from 'mocha'; import { Driver } from '../../webdriver/driver'; import FixtureBuilder from '../../fixture-builder'; import { Ganache } from '../../seeder/ganache'; -import GanacheContractAddressRegistry from '../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../seeder/contract-address-registry'; import { multipleGanacheOptionsForType2Transactions, PRIVATE_KEY_TWO, @@ -42,7 +42,7 @@ describe('Snap Account Contract interaction @no-mmi', function (this: Suite) { ganacheServer, }: { driver: Driver; - contractRegistry: GanacheContractAddressRegistry; + contractRegistry: ContractAddressRegistry; ganacheServer?: Ganache; }) => { await loginWithBalanceValidation(driver, ganacheServer); @@ -62,7 +62,7 @@ describe('Snap Account Contract interaction @no-mmi', function (this: Suite) { // Open Dapp with contract const testDapp = new TestDapp(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(smartContract); await testDapp.openTestDappPage({ contractAddress }); await testDapp.check_pageIsLoaded(); diff --git a/yarn.lock b/yarn.lock index ece1c037e759..6edaa3116974 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6887,13 +6887,6 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:~1.1.1": - version: 1.1.3 - resolution: "@noble/hashes@npm:1.1.3" - checksum: 10/42e9883649abd85e6a65cfa528e72b2a81ebb601b44db1d71b6ba927cede0627d7d8c649df159a7f84a949dfe17fe268d4b664c5a36c7e0b2a3d4198bc19f5e4 - languageName: node - linkType: hard - "@noble/hashes@npm:~1.3.2": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" @@ -8018,10 +8011,10 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.0.0, @scure/base@npm:^1.1.1, @scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6, @scure/base@npm:~1.1.8": - version: 1.1.8 - resolution: "@scure/base@npm:1.1.8" - checksum: 10/5b764c0e98610bc4993479965db718457d91b68d3c6f1339e3cc74e53fc6b0ae0428d1d64d29a0de0cee9d966034674d4464fdbd2d1dbef27013927b2fe05c45 +"@remix-run/router@npm:1.19.2": + version: 1.19.2 + resolution: "@remix-run/router@npm:1.19.2" + checksum: 10/31b62b66ea68bd62018189047de7b262700113438f62407df019f81a9856a08a705b2b77454be9293518e2f5f3bbf3f8b858ac19f48cb7d89f8ab56b7b630c19 languageName: node linkType: hard @@ -8032,6 +8025,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:~1.1.8": + version: 1.1.8 + resolution: "@scure/base@npm:1.1.8" + checksum: 10/5b764c0e98610bc4993479965db718457d91b68d3c6f1339e3cc74e53fc6b0ae0428d1d64d29a0de0cee9d966034674d4464fdbd2d1dbef27013927b2fe05c45 + languageName: node + linkType: hard + "@scure/bip32@npm:1.4.0": version: 1.4.0 resolution: "@scure/bip32@npm:1.4.0" @@ -27691,7 +27691,7 @@ __metadata: languageName: node linkType: hard -"mimic-response@npm:^1.0.0": +"mimic-response@npm:^1.0.0, mimic-response@npm:^1.0.1": version: 1.0.1 resolution: "mimic-response@npm:1.0.1" checksum: 10/034c78753b0e622bc03c983663b1cdf66d03861050e0c8606563d149bc2b02d63f62ce4d32be4ab50d0553ae0ffe647fc34d1f5281184c6e1e8cf4d85e8d9823 @@ -37671,6 +37671,13 @@ __metadata: languageName: node linkType: hard +"webextension-polyfill@npm:^0.12.0": + version: 0.12.0 + resolution: "webextension-polyfill@npm:0.12.0" + checksum: 10/77e648b958b573ef075e75a0c180e2bbd74dee17b3145e86d21fcbb168c4999e4a311654fe634b8178997bee9b35ea5808d8d3d3e5ff2ad138f197f4f0ea75d9 + languageName: node + linkType: hard + "webextension-polyfill@npm:^0.8.0": version: 0.8.0 resolution: "webextension-polyfill@npm:0.8.0" @@ -38236,7 +38243,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.13.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": +"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.13.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.18.0, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": version: 8.18.0 resolution: "ws@npm:8.18.0" peerDependencies: From c06eb883925c6f25847c03d058d6846fa35cac56 Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 19 Nov 2024 12:18:44 +0100 Subject: [PATCH 32/46] some job fixes --- .../e2e/tests/transaction/simple-send.spec.ts | 6 ++--- yarn.lock | 25 +++++++------------ 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/test/e2e/tests/transaction/simple-send.spec.ts b/test/e2e/tests/transaction/simple-send.spec.ts index 8277caf4e6e8..369db1bd724b 100644 --- a/test/e2e/tests/transaction/simple-send.spec.ts +++ b/test/e2e/tests/transaction/simple-send.spec.ts @@ -2,7 +2,7 @@ import { Suite } from 'mocha'; import { Driver } from '../../webdriver/driver'; import { withFixtures } from '../../helpers'; import FixtureBuilder from '../../fixture-builder'; -import { loginWithBalanceValidation, loginWithoutBalanceValidation } from '../../page-objects/flows/login.flow'; +import { loginWithoutBalanceValidation } from '../../page-objects/flows/login.flow'; import { sendTransactionToAddress } from '../../page-objects/flows/send-transaction.flow'; import HomePage from '../../page-objects/pages/homepage'; @@ -13,9 +13,7 @@ describe('Simple send eth', function (this: Suite) { fixtures: new FixtureBuilder().build(), title: this.test?.fullTitle(), }, - async ({ - driver, - }: { driver: Driver }) => { + async ({ driver }: { driver: Driver }) => { await loginWithoutBalanceValidation(driver); await sendTransactionToAddress({ driver, diff --git a/yarn.lock b/yarn.lock index 6edaa3116974..90630aad47b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8018,20 +8018,13 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.0.0, @scure/base@npm:^1.1.1, @scure/base@npm:^1.1.3, @scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6": +"@scure/base@npm:^1.0.0, @scure/base@npm:^1.1.1, @scure/base@npm:^1.1.3, @scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6, @scure/base@npm:~1.1.8": version: 1.1.9 resolution: "@scure/base@npm:1.1.9" checksum: 10/f0ab7f687bbcdee2a01377fe3cd808bf63977999672751295b6a92625d5322f4754a96d40f6bd579bc367aad48ecf8a4e6d0390e70296e6ded1076f52adb16bb languageName: node linkType: hard -"@scure/base@npm:~1.1.8": - version: 1.1.8 - resolution: "@scure/base@npm:1.1.8" - checksum: 10/5b764c0e98610bc4993479965db718457d91b68d3c6f1339e3cc74e53fc6b0ae0428d1d64d29a0de0cee9d966034674d4464fdbd2d1dbef27013927b2fe05c45 - languageName: node - linkType: hard - "@scure/bip32@npm:1.4.0": version: 1.4.0 resolution: "@scure/bip32@npm:1.4.0" @@ -37664,20 +37657,20 @@ __metadata: languageName: node linkType: hard -"webextension-polyfill@npm:>=0.10.0 <1.0, webextension-polyfill@npm:^0.10.0": - version: 0.10.0 - resolution: "webextension-polyfill@npm:0.10.0" - checksum: 10/51ff30ebed4b1aa802b7f0347f05021b2fe492078bb1a597223d43995fcee96e2da8f914a2f6e36f988c1877ed5ab36ca7077f2f3ab828955151a59e4c01bf7e - languageName: node - linkType: hard - -"webextension-polyfill@npm:^0.12.0": +"webextension-polyfill@npm:>=0.10.0 <1.0, webextension-polyfill@npm:^0.12.0": version: 0.12.0 resolution: "webextension-polyfill@npm:0.12.0" checksum: 10/77e648b958b573ef075e75a0c180e2bbd74dee17b3145e86d21fcbb168c4999e4a311654fe634b8178997bee9b35ea5808d8d3d3e5ff2ad138f197f4f0ea75d9 languageName: node linkType: hard +"webextension-polyfill@npm:^0.10.0": + version: 0.10.0 + resolution: "webextension-polyfill@npm:0.10.0" + checksum: 10/51ff30ebed4b1aa802b7f0347f05021b2fe492078bb1a597223d43995fcee96e2da8f914a2f6e36f988c1877ed5ab36ca7077f2f3ab828955151a59e4c01bf7e + languageName: node + linkType: hard + "webextension-polyfill@npm:^0.8.0": version: 0.8.0 resolution: "webextension-polyfill@npm:0.8.0" From 79da9f62a14d12b3f149d32fec6810a5942657c1 Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 19 Nov 2024 13:58:31 +0100 Subject: [PATCH 33/46] more rebase fixes --- lavamoat/build-system/policy.json | 20 ++----------------- test/e2e/json-rpc/eth_call.spec.ts | 4 ++-- ...55-revoke-set-approval-for-all-redesign.ts | 6 +++--- ...1155-set-approval-for-all-redesign.spec.ts | 6 +++--- .../erc20-token-send-redesign.spec.ts | 10 +++++----- ...21-revoke-set-approval-for-all-redesign.ts | 6 +++--- ...c721-set-approval-for-all-redesign.spec.ts | 6 +++--- .../nft-token-send-redesign.spec.ts | 14 ++++++------- 8 files changed, 28 insertions(+), 44 deletions(-) diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index 718ff4ba5b62..1cadff4100d7 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -3004,7 +3004,7 @@ "eslint-plugin-prettier": true, "eslint-plugin-react": true, "eslint-plugin-react-hooks": true, - "eslint>@eslint/eslintrc>ajv": true, + "eslint>ajv": true, "eslint>globals": true, "eslint>ignore": true, "eslint>minimatch": true, @@ -3012,17 +3012,6 @@ "nock>debug": true } }, - "eslint>@eslint/eslintrc>ajv": { - "globals": { - "console": true - }, - "packages": { - "@metamask/snaps-utils>fast-json-stable-stringify": true, - "eslint>@eslint/eslintrc>ajv>json-schema-traverse": true, - "eslint>fast-deep-equal": true, - "uri-js": true - } - }, "eslint>@eslint/eslintrc>import-fresh": { "builtin": { "path.dirname": true @@ -8477,17 +8466,12 @@ "process.stdout.write": true }, "packages": { + "eslint>ajv": true, "lodash": true, - "stylelint>table>ajv": true, "stylelint>table>slice-ansi": true, "stylelint>table>string-width": true } }, - "stylelint>table>ajv": { - "packages": { - "eslint>fast-deep-equal": true - } - }, "stylelint>table>slice-ansi": { "packages": { "stylelint>table>slice-ansi>ansi-styles": true, diff --git a/test/e2e/json-rpc/eth_call.spec.ts b/test/e2e/json-rpc/eth_call.spec.ts index 7ff1dd7489ff..fedc08ea645b 100644 --- a/test/e2e/json-rpc/eth_call.spec.ts +++ b/test/e2e/json-rpc/eth_call.spec.ts @@ -4,7 +4,7 @@ import { defaultGanacheOptions, withFixtures } from '../helpers'; import { Driver } from '../webdriver/driver'; import FixtureBuilder from '../fixture-builder'; import { Ganache } from '../seeder/ganache'; -import GanacheContractAddressRegistry from '../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../seeder/contract-address-registry'; import { SMART_CONTRACTS } from '../seeder/smart-contracts'; import { loginWithBalanceValidation } from '../page-objects/flows/login.flow'; @@ -28,7 +28,7 @@ describe('eth_call', function () { }: { driver: Driver; ganacheServer?: Ganache; - contractRegistry: GanacheContractAddressRegistry; + contractRegistry: ContractAddressRegistry; }) => { const contract = contractRegistry.getContractAddress(smartContract); await loginWithBalanceValidation(driver, ganacheServer); diff --git a/test/e2e/tests/confirmations/transactions/erc1155-revoke-set-approval-for-all-redesign.ts b/test/e2e/tests/confirmations/transactions/erc1155-revoke-set-approval-for-all-redesign.ts index 1f9d05cd26a8..33a7760a050d 100644 --- a/test/e2e/tests/confirmations/transactions/erc1155-revoke-set-approval-for-all-redesign.ts +++ b/test/e2e/tests/confirmations/transactions/erc1155-revoke-set-approval-for-all-redesign.ts @@ -5,7 +5,7 @@ import { unlockWallet, WINDOW_TITLES } from '../../../helpers'; import { Mockttp } from '../../../mock-e2e'; import SetApprovalForAllTransactionConfirmation from '../../../page-objects/pages/confirmations/redesign/set-approval-for-all-transaction-confirmation'; import TestDapp from '../../../page-objects/pages/test-dapp'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; import { withRedesignConfirmationFixtures } from '../helpers'; import { mocked4BytesSetApprovalForAll } from './erc721-revoke-set-approval-for-all-redesign'; @@ -47,12 +47,12 @@ async function mocks(server: Mockttp) { async function createTransactionAndAssertDetails( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.NFTS); const testDapp = new TestDapp(driver); diff --git a/test/e2e/tests/confirmations/transactions/erc1155-set-approval-for-all-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/erc1155-set-approval-for-all-redesign.spec.ts index c9c9fdbd5eda..da9da0a59873 100644 --- a/test/e2e/tests/confirmations/transactions/erc1155-set-approval-for-all-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/erc1155-set-approval-for-all-redesign.spec.ts @@ -4,7 +4,7 @@ import { DAPP_URL, unlockWallet, WINDOW_TITLES } from '../../../helpers'; import { Mockttp } from '../../../mock-e2e'; import SetApprovalForAllTransactionConfirmation from '../../../page-objects/pages/confirmations/redesign/set-approval-for-all-transaction-confirmation'; import TestDapp from '../../../page-objects/pages/test-dapp'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; import { withRedesignConfirmationFixtures } from '../helpers'; import { TestSuiteArguments } from './shared'; @@ -75,12 +75,12 @@ export async function mocked4BytesSetApprovalForAll(mockServer: Mockttp) { async function createTransactionAssertDetailsAndConfirm( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.NFTS); const testDapp = new TestDapp(driver); diff --git a/test/e2e/tests/confirmations/transactions/erc20-token-send-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/erc20-token-send-redesign.spec.ts index 9cd1d3837729..f5293161172f 100644 --- a/test/e2e/tests/confirmations/transactions/erc20-token-send-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/erc20-token-send-redesign.spec.ts @@ -12,7 +12,7 @@ import TokenTransferTransactionConfirmation from '../../../page-objects/pages/co import HomePage from '../../../page-objects/pages/homepage'; import SendTokenPage from '../../../page-objects/pages/send/send-token-page'; import TestDapp from '../../../page-objects/pages/test-dapp'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; import { withRedesignConfirmationFixtures } from '../helpers'; import { TestSuiteArguments } from './shared'; @@ -115,12 +115,12 @@ export async function mockedSourcifyTokenSend(mockServer: Mockttp) { async function createWalletInitiatedTransactionAndAssertDetails( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.HST); const testDapp = new TestDapp(driver); @@ -160,12 +160,12 @@ async function createWalletInitiatedTransactionAndAssertDetails( async function createDAppInitiatedTransactionAndAssertDetails( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.HST); const testDapp = new TestDapp(driver); diff --git a/test/e2e/tests/confirmations/transactions/erc721-revoke-set-approval-for-all-redesign.ts b/test/e2e/tests/confirmations/transactions/erc721-revoke-set-approval-for-all-redesign.ts index b0f1291a47d9..95768c35de3f 100644 --- a/test/e2e/tests/confirmations/transactions/erc721-revoke-set-approval-for-all-redesign.ts +++ b/test/e2e/tests/confirmations/transactions/erc721-revoke-set-approval-for-all-redesign.ts @@ -5,7 +5,7 @@ import { unlockWallet, WINDOW_TITLES } from '../../../helpers'; import { Mockttp } from '../../../mock-e2e'; import SetApprovalForAllTransactionConfirmation from '../../../page-objects/pages/confirmations/redesign/set-approval-for-all-transaction-confirmation'; import TestDapp from '../../../page-objects/pages/test-dapp'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; import { withRedesignConfirmationFixtures } from '../helpers'; import { TestSuiteArguments } from './shared'; @@ -70,12 +70,12 @@ export async function mocked4BytesSetApprovalForAll(mockServer: Mockttp) { async function createTransactionAndAssertDetails( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.NFTS); const testDapp = new TestDapp(driver); diff --git a/test/e2e/tests/confirmations/transactions/erc721-set-approval-for-all-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/erc721-set-approval-for-all-redesign.spec.ts index 9e481ee9c75f..ba3c877973e5 100644 --- a/test/e2e/tests/confirmations/transactions/erc721-set-approval-for-all-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/erc721-set-approval-for-all-redesign.spec.ts @@ -4,7 +4,7 @@ import { DAPP_URL, unlockWallet, WINDOW_TITLES } from '../../../helpers'; import { Mockttp } from '../../../mock-e2e'; import SetApprovalForAllTransactionConfirmation from '../../../page-objects/pages/confirmations/redesign/set-approval-for-all-transaction-confirmation'; import TestDapp from '../../../page-objects/pages/test-dapp'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; import { withRedesignConfirmationFixtures } from '../helpers'; import { TestSuiteArguments } from './shared'; @@ -75,12 +75,12 @@ export async function mocked4BytesSetApprovalForAll(mockServer: Mockttp) { async function createTransactionAssertDetailsAndConfirm( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.NFTS); const testDapp = new TestDapp(driver); diff --git a/test/e2e/tests/confirmations/transactions/nft-token-send-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/nft-token-send-redesign.spec.ts index b7902717a787..8d319b62c482 100644 --- a/test/e2e/tests/confirmations/transactions/nft-token-send-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/nft-token-send-redesign.spec.ts @@ -14,7 +14,7 @@ import HomePage from '../../../page-objects/pages/homepage'; import NFTDetailsPage from '../../../page-objects/pages/nft-details-page'; import SendTokenPage from '../../../page-objects/pages/send/send-token-page'; import TestDapp from '../../../page-objects/pages/test-dapp'; -import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import ContractAddressRegistry from '../../../seeder/contract-address-registry'; import { Driver } from '../../../webdriver/driver'; import { withRedesignConfirmationFixtures } from '../helpers'; import { TestSuiteArguments } from './shared'; @@ -184,12 +184,12 @@ export async function mockedERC11554BytesNFTTokenSend(mockServer: Mockttp) { async function createERC721WalletInitiatedTransactionAndAssertDetails( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.NFTS); const testDapp = new TestDapp(driver); @@ -231,12 +231,12 @@ async function createERC721WalletInitiatedTransactionAndAssertDetails( async function createERC721DAppInitiatedTransactionAndAssertDetails( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.NFTS); const testDapp = new TestDapp(driver); @@ -266,12 +266,12 @@ async function createERC721DAppInitiatedTransactionAndAssertDetails( async function createERC1155WalletInitiatedTransactionAndAssertDetails( driver: Driver, - contractRegistry?: GanacheContractAddressRegistry, + contractRegistry?: ContractAddressRegistry, ) { await unlockWallet(driver); const contractAddress = await ( - contractRegistry as GanacheContractAddressRegistry + contractRegistry as ContractAddressRegistry ).getContractAddress(SMART_CONTRACTS.ERC1155); const testDapp = new TestDapp(driver); From aa5e8b8e81149328c2e8d7c6bc3634ee26f037e7 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 20 Nov 2024 11:00:53 +0100 Subject: [PATCH 34/46] fix --- test/e2e/helpers.js | 6 +++--- test/e2e/tests/transaction/send-eth.spec.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 01c96cf9b598..4619bc7cd775 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -64,7 +64,7 @@ async function withFixtures(options, testSuite) { dapp, fixtures, ganacheOptions, - networkOptions, + anvilOptions, smartContract, driverOptions, dappOptions, @@ -89,7 +89,7 @@ async function withFixtures(options, testSuite) { let localNetworkServer; // Temporary logic for network management until we remove ganache from all specs - if (networkOptions || (!ganacheOptions && !disableGanache)) { + if (anvilOptions) { localNetworkServer = new Anvil(); } else if (!disableGanache) { ganacheServer = new Ganache(); @@ -116,7 +116,7 @@ async function withFixtures(options, testSuite) { } if (localNetworkServer) { - await localNetworkServer.start(networkOptions || {}); + await localNetworkServer.start(anvilOptions || {}); } let contractRegistry; diff --git a/test/e2e/tests/transaction/send-eth.spec.js b/test/e2e/tests/transaction/send-eth.spec.js index f10a6751c262..079be849d90d 100644 --- a/test/e2e/tests/transaction/send-eth.spec.js +++ b/test/e2e/tests/transaction/send-eth.spec.js @@ -150,7 +150,7 @@ describe('Send ETH', function () { await withFixtures( { fixtures: new FixtureBuilder().build(), - networkOptions: { + anvilOptions: { hardfork: 'london', }, smartContract, @@ -315,7 +315,7 @@ describe('Send ETH', function () { fixtures: new FixtureBuilder() .withPermissionControllerConnectedToTestDapp() .build(), - networkOptions: { + anvilOptions: { hardfork: 'london', }, title: this.test.fullTitle(), From e63cd7fcbe707e44cfc5c611c0a93fa06a90dfcf Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 20 Nov 2024 11:11:50 +0100 Subject: [PATCH 35/46] useAnvil --- test/e2e/benchmark.js | 8 +---- test/e2e/helpers.js | 34 +++++++++---------- test/e2e/tests/settings/ipfs-toggle.spec.js | 2 +- test/e2e/tests/transaction/send-eth.spec.js | 15 +++++--- .../transaction/send-hex-address.spec.js | 20 ++++++----- .../e2e/tests/transaction/simple-send.spec.ts | 1 + 6 files changed, 42 insertions(+), 38 deletions(-) diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index 659cb0bad8b5..1f24a960d9eb 100755 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -10,12 +10,7 @@ const { isWritable, getFirstParentDirectoryThatExists, } = require('../helpers/file'); -const { - defaultGanacheOptions, - tinyDelayMs, - unlockWallet, - withFixtures, -} = require('./helpers'); +const { withFixtures, tinyDelayMs, unlockWallet } = require('./helpers'); const { PAGES } = require('./webdriver/driver'); const FixtureBuilder = require('./fixture-builder'); @@ -37,7 +32,6 @@ async function measurePage(pageName) { await withFixtures( { fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, disableServerMochaToBackground: true, }, async ({ driver }) => { diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 4619bc7cd775..e4c335cfc5b3 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -65,6 +65,7 @@ async function withFixtures(options, testSuite) { fixtures, ganacheOptions, anvilOptions, + useAnvil, smartContract, driverOptions, dappOptions, @@ -86,15 +87,14 @@ async function withFixtures(options, testSuite) { const fixtureServer = new FixtureServer(); let ganacheServer; - let localNetworkServer; + let anvilServer; // Temporary logic for network management until we remove ganache from all specs - if (anvilOptions) { - localNetworkServer = new Anvil(); + if (anvilOptions || useAnvil) { + anvilServer = new Anvil(); } else if (!disableGanache) { ganacheServer = new Ganache(); } - const bundlerServer = new Bundler(); const https = await mockttp.generateCACertificate(); const mockServer = mockttp.getLocal({ https, cors: true }); @@ -115,8 +115,8 @@ async function withFixtures(options, testSuite) { await ganacheServer.start(ganacheOptions); } - if (localNetworkServer) { - await localNetworkServer.start(anvilOptions || {}); + if (anvilServer) { + await anvilServer.start(anvilOptions || {}); } let contractRegistry; @@ -132,9 +132,9 @@ async function withFixtures(options, testSuite) { ), ); contractRegistry = ganacheSeeder.getContractRegistry(); - } else if (localNetworkServer) { + } else if (anvilServer) { const localNetworkSeeder = new AnvilSeeder( - localNetworkServer.getProvider(), + anvilServer.getProvider(), ); const contracts = smartContract instanceof Array ? smartContract : [smartContract]; @@ -251,7 +251,7 @@ async function withFixtures(options, testSuite) { contractRegistry, driver: driverProxy ?? driver, ganacheServer, - localNetworkServer, + anvilServer, mockedEndpoint, mockServer, secondaryGanacheServer, @@ -338,8 +338,8 @@ async function withFixtures(options, testSuite) { await ganacheServer.quit(); } - if (localNetworkServer) { - await localNetworkServer.quit(); + if (anvilServer) { + await anvilServer.quit(); } if (ganacheOptions?.concurrent) { @@ -772,17 +772,17 @@ const TEST_SEED_PHRASE_TWO = * or after a transaction is made. * * @param {WebDriver} driver - The WebDriver instance. - * @param {Ganache} [localNetworkServer] - The local server instance (optional). + * @param {Ganache} [anvilServer] - The local server instance (optional). * @param {string} [address] - The address to check the balance for (optional). */ const locateAccountBalanceDOM = async ( driver, - localNetworkServer, + anvilServer, address = null, ) => { const balanceSelector = '[data-testid="eth-overview__primary-currency"]'; - if (localNetworkServer) { - const balance = await localNetworkServer.getBalance(address); + if (anvilServer) { + const balance = await anvilServer.getBalance(address); await driver.waitForSelector({ css: balanceSelector, text: `${balance} ETH`, @@ -823,10 +823,10 @@ async function unlockWallet( } } -const logInWithBalanceValidation = async (driver, localNetworkServer) => { +const logInWithBalanceValidation = async (driver, anvilServer) => { await unlockWallet(driver); // Wait for balance to load - await locateAccountBalanceDOM(driver, localNetworkServer); + await locateAccountBalanceDOM(driver, anvilServer); }; function roundToXDecimalPlaces(number, decimalPlaces) { diff --git a/test/e2e/tests/settings/ipfs-toggle.spec.js b/test/e2e/tests/settings/ipfs-toggle.spec.js index 94dc93a6d5e9..cd078b587d54 100644 --- a/test/e2e/tests/settings/ipfs-toggle.spec.js +++ b/test/e2e/tests/settings/ipfs-toggle.spec.js @@ -15,7 +15,7 @@ describe('Settings', function () { { dapp: true, fixtures: new FixtureBuilder().withNftControllerERC1155().build(), - ganacheOptions: defaultGanacheOptions, + defaultGanacheOptions, smartContract, title: this.test.fullTitle(), }, diff --git a/test/e2e/tests/transaction/send-eth.spec.js b/test/e2e/tests/transaction/send-eth.spec.js index 079be849d90d..f96e4dffe102 100644 --- a/test/e2e/tests/transaction/send-eth.spec.js +++ b/test/e2e/tests/transaction/send-eth.spec.js @@ -18,9 +18,10 @@ describe('Send ETH', function () { { fixtures: new FixtureBuilder().build(), title: this.test.fullTitle(), + useAnvil: true, }, - async ({ driver, networkServer }) => { - await logInWithBalanceValidation(driver, networkServer); + async ({ driver, anvilServer }) => { + await logInWithBalanceValidation(driver, anvilServer); await openActionMenuAndStartSendFlow(driver); @@ -98,6 +99,7 @@ describe('Send ETH', function () { { fixtures: new FixtureBuilder().build(), title: this.test.fullTitle(), + useAnvil: true, }, async ({ driver }) => { await unlockWallet(driver); @@ -156,11 +158,11 @@ describe('Send ETH', function () { smartContract, title: this.test.fullTitle(), }, - async ({ driver, contractRegistry, networkServer }) => { + async ({ driver, contractRegistry, anvilServer }) => { const contractAddress = await contractRegistry.getContractAddress( smartContract, ); - await logInWithBalanceValidation(driver, networkServer); + await logInWithBalanceValidation(driver, anvilServer); // Wait for balance to load await driver.delay(500); @@ -208,6 +210,7 @@ describe('Send ETH', function () { { fixtures: new FixtureBuilder().build(), title: this.test.fullTitle(), + useAnvil: true, }, async ({ driver }) => { await unlockWallet(driver); @@ -244,6 +247,7 @@ describe('Send ETH', function () { .withPermissionControllerConnectedToTestDapp() .build(), title: this.test.fullTitle(), + useAnvil: true, }, async ({ driver }) => { await unlockWallet(driver); @@ -315,7 +319,7 @@ describe('Send ETH', function () { fixtures: new FixtureBuilder() .withPermissionControllerConnectedToTestDapp() .build(), - anvilOptions: { + anvilOptions: { hardfork: 'london', }, title: this.test.fullTitle(), @@ -421,6 +425,7 @@ describe('Send ETH', function () { .withPreferencesControllerPetnamesDisabled() .build(), title: this.test.fullTitle(), + useAnvil: true, }, async ({ driver }) => { await unlockWallet(driver); diff --git a/test/e2e/tests/transaction/send-hex-address.spec.js b/test/e2e/tests/transaction/send-hex-address.spec.js index 91c12215f310..28980d007173 100644 --- a/test/e2e/tests/transaction/send-hex-address.spec.js +++ b/test/e2e/tests/transaction/send-hex-address.spec.js @@ -17,9 +17,10 @@ describe('Send ETH to a 40 character hexadecimal address', function () { .withPreferencesControllerPetnamesDisabled() .build(), title: this.test.fullTitle(), + useAnvil: true, }, - async ({ driver, networkServer }) => { - await logInWithBalanceValidation(driver, networkServer); + async ({ driver, anvilServer }) => { + await logInWithBalanceValidation(driver, anvilServer); // Send ETH await openActionMenuAndStartSendFlow(driver); @@ -61,9 +62,10 @@ describe('Send ETH to a 40 character hexadecimal address', function () { .withPreferencesControllerPetnamesDisabled() .build(), title: this.test.fullTitle(), + useAnvil: true, }, - async ({ driver, networkServer }) => { - await logInWithBalanceValidation(driver, networkServer); + async ({ driver, anvilServer }) => { + await logInWithBalanceValidation(driver, anvilServer); // Send ETH await openActionMenuAndStartSendFlow(driver); @@ -112,9 +114,10 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { .build(), smartContract, title: this.test.fullTitle(), + useAnvil: true, }, - async ({ driver, networkServer }) => { - await logInWithBalanceValidation(driver, networkServer); + async ({ driver, anvilServer }) => { + await logInWithBalanceValidation(driver, anvilServer); // Send TST await driver.clickElement( '[data-testid="account-overview__asset-tab"]', @@ -173,9 +176,10 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { .build(), smartContract, title: this.test.fullTitle(), + useAnvil: true, }, - async ({ driver, networkServer }) => { - await logInWithBalanceValidation(driver, networkServer); + async ({ driver, anvilServer }) => { + await logInWithBalanceValidation(driver, anvilServer); // Send TST await driver.clickElement( '[data-testid="account-overview__asset-tab"]', diff --git a/test/e2e/tests/transaction/simple-send.spec.ts b/test/e2e/tests/transaction/simple-send.spec.ts index 369db1bd724b..45d45d0359e8 100644 --- a/test/e2e/tests/transaction/simple-send.spec.ts +++ b/test/e2e/tests/transaction/simple-send.spec.ts @@ -12,6 +12,7 @@ describe('Simple send eth', function (this: Suite) { { fixtures: new FixtureBuilder().build(), title: this.test?.fullTitle(), + useAnvil: true, }, async ({ driver }: { driver: Driver }) => { await loginWithoutBalanceValidation(driver); From 617d5321d3fd564d1263a4e8a737a46e24231ccd Mon Sep 17 00:00:00 2001 From: seaona Date: Mon, 25 Nov 2024 08:54:15 +0100 Subject: [PATCH 36/46] update balance vvalidation function --- test/e2e/helpers.js | 20 +++++++++---------- test/e2e/page-objects/flows/login.flow.ts | 11 ++++++---- test/e2e/page-objects/pages/homepage.ts | 11 ++++++---- test/e2e/tests/account/add-account.spec.ts | 6 +++--- test/e2e/tests/metrics/dapp-viewed.spec.js | 1 - test/e2e/tests/network/multi-rpc.spec.ts | 2 +- test/e2e/tests/network/switch-network.spec.ts | 8 ++++---- test/e2e/tests/onboarding/onboarding.spec.ts | 2 +- test/e2e/tests/tokens/nft/import-nft.spec.ts | 2 +- .../e2e/tests/transaction/simple-send.spec.ts | 13 +++++++++--- 10 files changed, 43 insertions(+), 33 deletions(-) diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index b36aed4c37d2..b10d5ba779cc 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -132,17 +132,15 @@ async function withFixtures(options, testSuite) { ); contractRegistry = ganacheSeeder.getContractRegistry(); } else if (anvilServer) { - const localNetworkSeeder = new AnvilSeeder( - anvilServer.getProvider(), - ); + const anvilSeeder = new AnvilSeeder(anvilServer.getProvider()); const contracts = smartContract instanceof Array ? smartContract : [smartContract]; await Promise.all( contracts.map((contract) => - localNetworkSeeder.deploySmartContract(contract), + anvilSeeder.deploySmartContract(contract), ), ); - contractRegistry = localNetworkSeeder.getContractRegistry(); + contractRegistry = anvilSeeder.getContractRegistry(); } } @@ -671,17 +669,17 @@ const TEST_SEED_PHRASE_TWO = * or after a transaction is made. * * @param {WebDriver} driver - The WebDriver instance. - * @param {Ganache} [anvilServer] - The local server instance (optional). + * @param {Ganache | Anvil} [localBlockchainServer] - The local server instance (optional). * @param {string} [address] - The address to check the balance for (optional). */ const locateAccountBalanceDOM = async ( driver, - anvilServer, + localBlockchainServer, address = null, ) => { const balanceSelector = '[data-testid="eth-overview__primary-currency"]'; - if (anvilServer) { - const balance = await anvilServer.getBalance(address); + if (localBlockchainServer) { + const balance = await localBlockchainServer.getBalance(address); await driver.waitForSelector({ css: balanceSelector, text: `${balance} ETH`, @@ -722,10 +720,10 @@ async function unlockWallet( } } -const logInWithBalanceValidation = async (driver, anvilServer) => { +const logInWithBalanceValidation = async (driver, localBlockchainServer) => { await unlockWallet(driver); // Wait for balance to load - await locateAccountBalanceDOM(driver, anvilServer); + await locateAccountBalanceDOM(driver, localBlockchainServer); }; function roundToXDecimalPlaces(number, decimalPlaces) { diff --git a/test/e2e/page-objects/flows/login.flow.ts b/test/e2e/page-objects/flows/login.flow.ts index fcd0bcb22d8a..03b1fcafb12b 100644 --- a/test/e2e/page-objects/flows/login.flow.ts +++ b/test/e2e/page-objects/flows/login.flow.ts @@ -1,6 +1,7 @@ import LoginPage from '../pages/login-page'; import HomePage from '../pages/homepage'; import { Driver } from '../../webdriver/driver'; +import { Anvil } from '../../seeder/anvil'; import { Ganache } from '../../seeder/ganache'; /** @@ -24,12 +25,12 @@ export const loginWithoutBalanceValidation = async ( * This method unlocks the wallet and verifies that the user lands on the homepage with the expected balance. It is designed to be the initial step in setting up a test environment. * * @param driver - The webdriver instance. - * @param ganacheServer - The ganache server instance + * @param localBlockchainServer - The local blockchain server instance * @param password - The password used to unlock the wallet. */ export const loginWithBalanceValidation = async ( driver: Driver, - ganacheServer?: Ganache, + localBlockchainServer?: Ganache | Anvil, password?: string, ) => { await loginWithoutBalanceValidation(driver, password); @@ -38,8 +39,10 @@ export const loginWithBalanceValidation = async ( await homePage.check_pageIsLoaded(); // Verify the expected balance on the homepage - if (ganacheServer) { - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + if (localBlockchainServer) { + await homePage.check_localBlockchainBalanceIsDisplayed( + localBlockchainServer, + ); } else { await homePage.check_expectedBalanceIsDisplayed(); } diff --git a/test/e2e/page-objects/pages/homepage.ts b/test/e2e/page-objects/pages/homepage.ts index 6a8a916d4349..9a84a5bff11b 100644 --- a/test/e2e/page-objects/pages/homepage.ts +++ b/test/e2e/page-objects/pages/homepage.ts @@ -1,5 +1,6 @@ import { strict as assert } from 'assert'; import { Driver } from '../../webdriver/driver'; +import { Anvil } from '../../seeder/anvil'; import { Ganache } from '../../seeder/ganache'; import { getCleanAppState } from '../../helpers'; import HeaderNavbar from './header-navbar'; @@ -283,13 +284,15 @@ class HomePage { ); } - async check_ganacheBalanceIsDisplayed( - ganacheServer?: Ganache, + async check_localBlockchainBalanceIsDisplayed( + localBlockchainServer?: Ganache | Anvil, address = null, ): Promise { let expectedBalance: string; - if (ganacheServer) { - expectedBalance = (await ganacheServer.getBalance(address)).toString(); + if (localBlockchainServer) { + expectedBalance = ( + await localBlockchainServer.getBalance(address) + ).toString(); } else { expectedBalance = '0'; } diff --git a/test/e2e/tests/account/add-account.spec.ts b/test/e2e/tests/account/add-account.spec.ts index 3fa65b14e87d..76060611198b 100644 --- a/test/e2e/tests/account/add-account.spec.ts +++ b/test/e2e/tests/account/add-account.spec.ts @@ -26,7 +26,7 @@ describe('Add account', function () { await completeImportSRPOnboardingFlow({ driver }); const homePage = new HomePage(driver); await homePage.check_pageIsLoaded(); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); const headerNavbar = new HeaderNavbar(driver); await headerNavbar.openAccountMenu(); @@ -43,7 +43,7 @@ describe('Add account', function () { await accountListPage.check_accountDisplayedInAccountList('Account 1'); await accountListPage.switchToAccount('Account 1'); await headerNavbar.check_accountLabel('Account 1'); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); await sendTransactionToAccount({ driver, recipientAccount: 'Account 2', @@ -64,7 +64,7 @@ describe('Add account', function () { // Check wallet balance for both accounts await homePage.check_pageIsLoaded(); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); await headerNavbar.openAccountMenu(); await accountListPage.check_pageIsLoaded(); await accountListPage.check_accountDisplayedInAccountList('Account 2'); diff --git a/test/e2e/tests/metrics/dapp-viewed.spec.js b/test/e2e/tests/metrics/dapp-viewed.spec.js index c7f0774dea21..668f93e65dc5 100644 --- a/test/e2e/tests/metrics/dapp-viewed.spec.js +++ b/test/e2e/tests/metrics/dapp-viewed.spec.js @@ -92,7 +92,6 @@ describe('Dapp viewed Event @no-mmi', function () { participateInMetaMetrics: true, }) .build(), - ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), testSpecificMock: mockSegment, }, diff --git a/test/e2e/tests/network/multi-rpc.spec.ts b/test/e2e/tests/network/multi-rpc.spec.ts index ac693361435d..f5c40259a33b 100644 --- a/test/e2e/tests/network/multi-rpc.spec.ts +++ b/test/e2e/tests/network/multi-rpc.spec.ts @@ -83,7 +83,7 @@ describe('MultiRpc:', function (this: Suite) { await completeImportSRPOnboardingFlow({ driver }); const homePage = new HomePage(driver); await homePage.check_pageIsLoaded(); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); await new HeaderNavbar(driver).clickSwitchNetworkDropDown(); const selectNetworkDialog = new SelectNetwork(driver); diff --git a/test/e2e/tests/network/switch-network.spec.ts b/test/e2e/tests/network/switch-network.spec.ts index a45e634dbbec..b320e095cc69 100644 --- a/test/e2e/tests/network/switch-network.spec.ts +++ b/test/e2e/tests/network/switch-network.spec.ts @@ -36,19 +36,19 @@ describe('Switch network - ', function (this: Suite) { // Validate the switch network functionality to Ethereum Mainnet await switchToNetworkFlow(driver, 'Ethereum Mainnet'); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); // Validate the switch network functionality to test network await switchToNetworkFlow(driver, 'Localhost 8545', true); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); // Add Arbitrum network and perform the switch network functionality await searchAndSwitchToNetworkFlow(driver, 'Arbitrum One'); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); // Validate the switch network functionality back to Ethereum Mainnet await switchToNetworkFlow(driver, 'Ethereum Mainnet'); - await homePage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homePage.check_localBlockchainBalanceIsDisplayed(ganacheServer); }, ); }); diff --git a/test/e2e/tests/onboarding/onboarding.spec.ts b/test/e2e/tests/onboarding/onboarding.spec.ts index 9409ef7e351c..979e416f5090 100644 --- a/test/e2e/tests/onboarding/onboarding.spec.ts +++ b/test/e2e/tests/onboarding/onboarding.spec.ts @@ -198,7 +198,7 @@ describe('MetaMask onboarding @no-mmi', function () { // Check the correct balance for the custom network is displayed if (secondaryGanacheServer && Array.isArray(secondaryGanacheServer)) { - await homePage.check_ganacheBalanceIsDisplayed( + await homePage.check_localBlockchainBalanceIsDisplayed( secondaryGanacheServer[0], ); } else { diff --git a/test/e2e/tests/tokens/nft/import-nft.spec.ts b/test/e2e/tests/tokens/nft/import-nft.spec.ts index 73049a8c9d0d..808bc26ac6e6 100644 --- a/test/e2e/tests/tokens/nft/import-nft.spec.ts +++ b/test/e2e/tests/tokens/nft/import-nft.spec.ts @@ -75,7 +75,7 @@ describe('Import NFT', function () { await accountListPage.check_accountDisplayedInAccountList('Account 1'); await accountListPage.switchToAccount('Account 1'); await headerNavbar.check_accountLabel('Account 1'); - await homepage.check_ganacheBalanceIsDisplayed(ganacheServer); + await homepage.check_localBlockchainBalanceIsDisplayed(ganacheServer); await homepage.check_nftNameIsDisplayed('TestDappNFTs'); await homepage.check_nftImageIsDisplayed(); }, diff --git a/test/e2e/tests/transaction/simple-send.spec.ts b/test/e2e/tests/transaction/simple-send.spec.ts index 45d45d0359e8..e3564c0cc42d 100644 --- a/test/e2e/tests/transaction/simple-send.spec.ts +++ b/test/e2e/tests/transaction/simple-send.spec.ts @@ -1,8 +1,9 @@ import { Suite } from 'mocha'; import { Driver } from '../../webdriver/driver'; +import { Anvil } from '../../seeder/anvil'; import { withFixtures } from '../../helpers'; import FixtureBuilder from '../../fixture-builder'; -import { loginWithoutBalanceValidation } from '../../page-objects/flows/login.flow'; +import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow'; import { sendTransactionToAddress } from '../../page-objects/flows/send-transaction.flow'; import HomePage from '../../page-objects/pages/homepage'; @@ -14,8 +15,14 @@ describe('Simple send eth', function (this: Suite) { title: this.test?.fullTitle(), useAnvil: true, }, - async ({ driver }: { driver: Driver }) => { - await loginWithoutBalanceValidation(driver); + async ({ + driver, + anvilServer, + }: { + driver: Driver; + anvilServer?: Anvil; + }) => { + await loginWithBalanceValidation(driver, anvilServer); await sendTransactionToAddress({ driver, recipientAddress: '0x985c30949c92df7a0bd42e0f3e3d539ece98db24', From 27e4895840e8a65a2981f2e1037f6a6b15732e00 Mon Sep 17 00:00:00 2001 From: seaona Date: Mon, 25 Nov 2024 09:49:49 +0100 Subject: [PATCH 37/46] round decimals balance --- test/e2e/seeder/anvil.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/e2e/seeder/anvil.ts b/test/e2e/seeder/anvil.ts index 56f136efd0aa..d42c41af74c4 100644 --- a/test/e2e/seeder/anvil.ts +++ b/test/e2e/seeder/anvil.ts @@ -83,7 +83,9 @@ export class Anvil { }); const balanceFormatted = Number(balanceInt) / 10 ** 18; - return balanceFormatted; + // Round to four decimal places, so we return the same value as ganache does + const balanceRounded = parseFloat(balanceFormatted.toFixed(4)); + return balanceRounded; } async getFiatBalance(): Promise { From d571b487dd865dc90f1a0698eac5f603bb35aed4 Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 26 Nov 2024 16:25:31 +0100 Subject: [PATCH 38/46] update img version to test --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 147b499b1edd..de0c2a746a45 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,13 +3,13 @@ version: 2.1 executors: node-browsers-small: docker: - - image: cimg/node:20.12.0-browsers + - image: cimg/node:20.17.0-browsers resource_class: small environment: NODE_OPTIONS: --max_old_space_size=2048 node-browsers-medium: docker: - - image: cimg/node:20.12.0-browsers + - image: cimg/node:20.17.0-browsers resource_class: medium environment: NODE_OPTIONS: --max_old_space_size=3072 @@ -21,7 +21,7 @@ executors: NODE_OPTIONS: --max_old_space_size=6144 node-browsers-medium-plus: docker: - - image: cimg/node:20.12.0-browsers + - image: cimg/node:20.17.0-browsers resource_class: medium+ environment: NODE_OPTIONS: --max_old_space_size=4096 From 2c5d9f0889068e7ec5c2f057a656ce844253c2f2 Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 26 Nov 2024 16:26:04 +0100 Subject: [PATCH 39/46] fix --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index de0c2a746a45..9a9c40ee7949 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,13 +3,13 @@ version: 2.1 executors: node-browsers-small: docker: - - image: cimg/node:20.17.0-browsers + - image: cimg/node:20.17-browsers resource_class: small environment: NODE_OPTIONS: --max_old_space_size=2048 node-browsers-medium: docker: - - image: cimg/node:20.17.0-browsers + - image: cimg/node:20.17-browsers resource_class: medium environment: NODE_OPTIONS: --max_old_space_size=3072 @@ -21,7 +21,7 @@ executors: NODE_OPTIONS: --max_old_space_size=6144 node-browsers-medium-plus: docker: - - image: cimg/node:20.17.0-browsers + - image: cimg/node:20.17-browsers resource_class: medium+ environment: NODE_OPTIONS: --max_old_space_size=4096 From 9eeac538f9b604f4f84f950dc7d9d038fd742dd3 Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 26 Nov 2024 16:26:41 +0100 Subject: [PATCH 40/46] fix --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9a9c40ee7949..2be92719ec1f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ executors: NODE_OPTIONS: --max_old_space_size=3072 node-linux-medium: machine: - image: ubuntu-2404:2024.05.1 + image: ubuntu-2404:current resource_class: medium #// linux medium: 2 CPUs, 7.5 GB RAM, 10 credits/min environment: NODE_OPTIONS: --max_old_space_size=6144 From 03299f48daeaab01aa8921a946ad255acf1a0332 Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 26 Nov 2024 16:43:40 +0100 Subject: [PATCH 41/46] 20.17 --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 9ff19494c8f1..8cfab175cf90 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20.12.0 +v20.17 From 51b384e618c247b403bb250a1a072727c6807cee Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 26 Nov 2024 17:15:25 +0100 Subject: [PATCH 42/46] tweak install path --- .depcheckrc.yml | 1 + test/helpers/foundry/foundryup.mts | 35 ++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.depcheckrc.yml b/.depcheckrc.yml index 5260be984692..50c8b760c1f4 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -40,6 +40,7 @@ ignores: - 'wait-on' - 'tsx' # used in .devcontainer - 'prettier-eslint' # used by the Prettier ESLint VSCode extension + - 'tar' # storybook - '@storybook/cli' - '@storybook/core' diff --git a/test/helpers/foundry/foundryup.mts b/test/helpers/foundry/foundryup.mts index 62629d620c91..e00ade5b242c 100755 --- a/test/helpers/foundry/foundryup.mts +++ b/test/helpers/foundry/foundryup.mts @@ -3,7 +3,7 @@ import { join, relative } from 'node:path'; import { homedir } from 'node:os'; import { Dir } from 'node:fs'; -import { opendir, symlink, unlink, copyFile, rm } from 'node:fs/promises'; +import { opendir, symlink, unlink, copyFile, rm, chmod } from 'node:fs/promises'; import { createHash } from 'node:crypto'; import { exit, cwd } from 'node:process'; import { @@ -43,6 +43,7 @@ say(`fetching ${bins} ${version} for ${platform} ${arch}`); const ext = platform === Platform.Windows ? BinFormat.Zip : BinFormat.Tar; const BIN_ARCHIVE_URL = `https://github.com/${repo}/releases/download/${tag}/foundry_${version}_${platform}_${arch}.${ext}`; const BIN_DIR = join(cwd(), 'node_modules', '.bin'); +const GLOBAL_BIN_DIR = '/usr/local/bin'; // Directory in PATH for global binaries const url = new URL(BIN_ARCHIVE_URL); const cacheKey = createHash('sha256') @@ -50,7 +51,7 @@ const cacheKey = createHash('sha256') .digest('hex'); const cachePath = join(CACHE_DIR, cacheKey); -// check the cache, if the cache dir exists we assume the correct files do, too +// Check the cache, if the cache dir exists we assume the correct files do, too let downloadedBinaries: Dir; try { say(`checking cache`); @@ -60,31 +61,41 @@ try { say(`binaries not in cache`); if ((e as NodeJS.ErrnoException).code === 'ENOENT') { say(`installing from ${url.toString()}`); - // directory doesn't exist, download and extract + // Directory doesn't exist, download and extract await extractFrom(url, binaries, cachePath); downloadedBinaries = await opendir(cachePath); } else { throw e; } } + for await (const file of downloadedBinaries) { if (!file.isFile()) continue; const target = join(file.parentPath, file.name); - const path = join(BIN_DIR, relative(cachePath, target)); - // clean up any existing files or symlinks - await unlink(path).catch(noop); + const localPath = join(BIN_DIR, relative(cachePath, target)); + const globalPath = join(GLOBAL_BIN_DIR, file.name); + + // Ensure the binary is executable + await chmod(target, 0o755); + + // Clean up any existing files or symlinks + await unlink(localPath).catch(noop); + await unlink(globalPath).catch(noop); + try { - // create new symlink - await symlink(target, path); + // Create new symlink in both local BIN_DIR and globalPath + await symlink(target, localPath); + await symlink(target, globalPath); } catch (e) { if (!(isCodedError(e) && ['EPERM', 'EXDEV'].includes(e.code))) { throw e; } - // symlinking can fail if its a cross-device/filesystem link, or for - // permissions reasons, so we'll just copy the file instead - await copyFile(target, path); + // Symlinking can fail for cross-device/filesystem links or permissions reasons + // Fallback: Copy the file instead + await copyFile(target, localPath); + await copyFile(target, globalPath); } - // check that it works by logging the version + // Check that it works by logging the version say(`installed - ${getVersion(target)}`); } From 6b9b0b281a811eb8f6dc294b8b7c1c3f7dde120f Mon Sep 17 00:00:00 2001 From: seaona Date: Tue, 26 Nov 2024 19:02:39 +0100 Subject: [PATCH 43/46] Revert "tweak install path" This reverts commit 51b384e618c247b403bb250a1a072727c6807cee. --- .depcheckrc.yml | 1 - test/helpers/foundry/foundryup.mts | 35 ++++++++++-------------------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/.depcheckrc.yml b/.depcheckrc.yml index 50c8b760c1f4..5260be984692 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -40,7 +40,6 @@ ignores: - 'wait-on' - 'tsx' # used in .devcontainer - 'prettier-eslint' # used by the Prettier ESLint VSCode extension - - 'tar' # storybook - '@storybook/cli' - '@storybook/core' diff --git a/test/helpers/foundry/foundryup.mts b/test/helpers/foundry/foundryup.mts index e00ade5b242c..62629d620c91 100755 --- a/test/helpers/foundry/foundryup.mts +++ b/test/helpers/foundry/foundryup.mts @@ -3,7 +3,7 @@ import { join, relative } from 'node:path'; import { homedir } from 'node:os'; import { Dir } from 'node:fs'; -import { opendir, symlink, unlink, copyFile, rm, chmod } from 'node:fs/promises'; +import { opendir, symlink, unlink, copyFile, rm } from 'node:fs/promises'; import { createHash } from 'node:crypto'; import { exit, cwd } from 'node:process'; import { @@ -43,7 +43,6 @@ say(`fetching ${bins} ${version} for ${platform} ${arch}`); const ext = platform === Platform.Windows ? BinFormat.Zip : BinFormat.Tar; const BIN_ARCHIVE_URL = `https://github.com/${repo}/releases/download/${tag}/foundry_${version}_${platform}_${arch}.${ext}`; const BIN_DIR = join(cwd(), 'node_modules', '.bin'); -const GLOBAL_BIN_DIR = '/usr/local/bin'; // Directory in PATH for global binaries const url = new URL(BIN_ARCHIVE_URL); const cacheKey = createHash('sha256') @@ -51,7 +50,7 @@ const cacheKey = createHash('sha256') .digest('hex'); const cachePath = join(CACHE_DIR, cacheKey); -// Check the cache, if the cache dir exists we assume the correct files do, too +// check the cache, if the cache dir exists we assume the correct files do, too let downloadedBinaries: Dir; try { say(`checking cache`); @@ -61,41 +60,31 @@ try { say(`binaries not in cache`); if ((e as NodeJS.ErrnoException).code === 'ENOENT') { say(`installing from ${url.toString()}`); - // Directory doesn't exist, download and extract + // directory doesn't exist, download and extract await extractFrom(url, binaries, cachePath); downloadedBinaries = await opendir(cachePath); } else { throw e; } } - for await (const file of downloadedBinaries) { if (!file.isFile()) continue; const target = join(file.parentPath, file.name); - const localPath = join(BIN_DIR, relative(cachePath, target)); - const globalPath = join(GLOBAL_BIN_DIR, file.name); - - // Ensure the binary is executable - await chmod(target, 0o755); - - // Clean up any existing files or symlinks - await unlink(localPath).catch(noop); - await unlink(globalPath).catch(noop); - + const path = join(BIN_DIR, relative(cachePath, target)); + // clean up any existing files or symlinks + await unlink(path).catch(noop); try { - // Create new symlink in both local BIN_DIR and globalPath - await symlink(target, localPath); - await symlink(target, globalPath); + // create new symlink + await symlink(target, path); } catch (e) { if (!(isCodedError(e) && ['EPERM', 'EXDEV'].includes(e.code))) { throw e; } - // Symlinking can fail for cross-device/filesystem links or permissions reasons - // Fallback: Copy the file instead - await copyFile(target, localPath); - await copyFile(target, globalPath); + // symlinking can fail if its a cross-device/filesystem link, or for + // permissions reasons, so we'll just copy the file instead + await copyFile(target, path); } - // Check that it works by logging the version + // check that it works by logging the version say(`installed - ${getVersion(target)}`); } From 9841a5519bc86cc9ebd85f33eadfbabeeba9447c Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 27 Nov 2024 09:46:29 +0100 Subject: [PATCH 44/46] add logs for path --- .depcheckrc.yml | 1 + package.json | 2 +- test/helpers/foundry/foundryup.mts | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.depcheckrc.yml b/.depcheckrc.yml index 5260be984692..50c8b760c1f4 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -40,6 +40,7 @@ ignores: - 'wait-on' - 'tsx' # used in .devcontainer - 'prettier-eslint' # used by the Prettier ESLint VSCode extension + - 'tar' # storybook - '@storybook/cli' - '@storybook/core' diff --git a/package.json b/package.json index f1b93902aca4..c466bf7b18ae 100644 --- a/package.json +++ b/package.json @@ -673,8 +673,8 @@ "tsx": "^4.7.1", "ttest": "^2.1.1", "typescript": "~5.4.5", - "viem": "^2.21.8", "unzipper": "^0.12.3", + "viem": "^2.21.8", "vinyl": "^2.2.1", "vinyl-buffer": "^1.0.1", "vinyl-source-stream": "^2.0.0", diff --git a/test/helpers/foundry/foundryup.mts b/test/helpers/foundry/foundryup.mts index 62629d620c91..0fb1f663d3c4 100755 --- a/test/helpers/foundry/foundryup.mts +++ b/test/helpers/foundry/foundryup.mts @@ -71,6 +71,8 @@ for await (const file of downloadedBinaries) { if (!file.isFile()) continue; const target = join(file.parentPath, file.name); const path = join(BIN_DIR, relative(cachePath, target)); + console.log("TARGET ===================", target); + console.log("PATH ===================", path); // clean up any existing files or symlinks await unlink(path).catch(noop); try { From aaef9af17e94ea39e99ec727c7e47366011f51ba Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 27 Nov 2024 10:37:55 +0100 Subject: [PATCH 45/46] determine path --- test/e2e/seeder/anvil.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/e2e/seeder/anvil.ts b/test/e2e/seeder/anvil.ts index d42c41af74c4..ed0d13dba7a3 100644 --- a/test/e2e/seeder/anvil.ts +++ b/test/e2e/seeder/anvil.ts @@ -1,5 +1,7 @@ import { createAnvil, Anvil as AnvilType } from '@viem/anvil'; import { createAnvilClients } from './anvil-clients'; +import { join } from 'path'; +import { execSync } from 'child_process'; type Hardfork = | 'Frontier' @@ -33,12 +35,28 @@ const defaultOptions = { port: 8545, }; + export class Anvil { #server: AnvilType | undefined; async start(opts = defaultOptions): Promise { const options = { ...defaultOptions, ...opts }; + // Determine the path to the anvil binary directory + const anvilBinaryDir = join(process.cwd(), 'node_modules', '.bin'); + + // Prepend the anvil binary directory to the PATH environment variable + process.env.PATH = `${anvilBinaryDir}:${process.env.PATH}`; + + // Verify that the anvil binary is accessible + try { + const versionOutput = execSync('anvil --version', { encoding: 'utf-8' }); + console.log(`Anvil version: ${versionOutput}`); + } catch (error) { + console.error('Failed to execute anvil:', error); + throw new Error('Anvil binary is not accessible.'); + } + this.#server = createAnvil(options); await this.#server.start(); } From ac507d662d77f6190561443099cc26138e8a5604 Mon Sep 17 00:00:00 2001 From: seaona Date: Wed, 27 Nov 2024 14:58:44 +0100 Subject: [PATCH 46/46] fix lint --- test/e2e/seeder/anvil.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/e2e/seeder/anvil.ts b/test/e2e/seeder/anvil.ts index ed0d13dba7a3..ed689f41cd60 100644 --- a/test/e2e/seeder/anvil.ts +++ b/test/e2e/seeder/anvil.ts @@ -1,7 +1,7 @@ -import { createAnvil, Anvil as AnvilType } from '@viem/anvil'; -import { createAnvilClients } from './anvil-clients'; import { join } from 'path'; import { execSync } from 'child_process'; +import { createAnvil, Anvil as AnvilType } from '@viem/anvil'; +import { createAnvilClients } from './anvil-clients'; type Hardfork = | 'Frontier' @@ -35,7 +35,6 @@ const defaultOptions = { port: 8545, }; - export class Anvil { #server: AnvilType | undefined;