From 5880bca147bfcf1f0fcc51f2e4b6533d443348f6 Mon Sep 17 00:00:00 2001 From: IOVGomezdn Date: Tue, 9 Apr 2024 09:41:58 -0300 Subject: [PATCH 01/44] feat: add staging-deploy.yml workflow --- .github/workflows/staging-deploy.yml | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/staging-deploy.yml diff --git a/.github/workflows/staging-deploy.yml b/.github/workflows/staging-deploy.yml new file mode 100644 index 00000000..2135334e --- /dev/null +++ b/.github/workflows/staging-deploy.yml @@ -0,0 +1,40 @@ +name: RSK Explorer staging build and deploy + +on: + push: + branches: [staging] + +jobs: + staging_build_and_deploy: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Node 16 + uses: actions/setup-node@v1 + with: + node-version: "16" + + - name: Install dependencies + run: npm ci + + - name: Build site + run: npm run build-with-tracking:testnet + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.STAGING_ROLE_ARN }} + aws-region: ${{ secrets.STAGING_AWS_REGION }} + + - name: Deploy site to S3 + run: | + aws s3 sync --sse aws:kms --sse-kms-key-id ${{ secrets.STAGING_KMS_KEY_ID }} --delete --only-show-errors --exclude .gitkeep dist/ ${{ secrets.STAGING_S3_BUCKET }} + - name: Invalidate CloudFront cache + run: | + aws cloudfront create-invalidation --distribution-id ${{ secrets.STAGING_CLOUDFRONT_DISTRIBUTION }} --paths "/*" From 5caeedab775c443f9fda420b08321ed72a70f44a Mon Sep 17 00:00:00 2001 From: IOVGomezdn Date: Wed, 8 May 2024 18:04:47 -0300 Subject: [PATCH 02/44] feat: add .env.staging and npm scripts to run and build staging environment --- .env.staging | 10 ++++++++++ package.json | 3 +++ 2 files changed, 13 insertions(+) create mode 100644 .env.staging diff --git a/.env.staging b/.env.staging new file mode 100644 index 00000000..4c10f1b5 --- /dev/null +++ b/.env.staging @@ -0,0 +1,10 @@ +VUE_APP_WS_URL=wss://explorer-testnet-api.plattie-dev.iovlabs.net +VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co +VUE_APP_STATS_URL=https://stats.testnet.rootstock.io +VUE_APP_GA_TAG=UA-136026316-1 +VUE_APP_HOTJAR_ID=1901396 +VUE_APP_STREAM_MITM_URL=/mitm/index.html +VUE_APP_DOMAIN_TESTNET='https://explorer.testnet.rootstock.io/' +VUE_APP_DOMAIN_MAINNET='https://explorer.rootstock.io/' +VUE_APP_DOMAIN_STATS_TESTNET='https://stats.testnet.rootstock.io/' +VUE_APP_DOMAIN_STATS_MAINNET='https://stats.rootstock.io/' \ No newline at end of file diff --git a/package.json b/package.json index 060a0736..9fb509f3 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,15 @@ "scripts": { "dev:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service serve", "dev:testnet": "env-cmd -f .env.testnet npx vue-cli-service serve", + "dev:staging": "env-cmd -f .env.staging npx vue-cli-service serve", "dev-with-tracking:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service serve src/main.with.tracking.js", "dev-with-tracking:testnet": "env-cmd -f .env.testnet npx vue-cli-service serve src/main.with.tracking.js", "build:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service build --modern", "build:testnet": "env-cmd -f .env.testnet npx vue-cli-service build --modern", + "build:staging": "env-cmd -f .env.staging npx vue-cli-service build --modern", "build-with-tracking:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service build src/main.with.tracking.js --modern", "build-with-tracking:testnet": "env-cmd -f .env.testnet npx vue-cli-service build src/main.with.tracking.js --modern", + "build-with-tracking:staging": "env-cmd -f .env.staging npx vue-cli-service build src/main.with.tracking.js --modern", "test:unit": "npx vue-cli-service test:unit", "test:e2e": "npx vue-cli-service test:e2e", "lint": "npx vue-cli-service lint", From 92838578b55ca7e0456c9c81b63121097348533d Mon Sep 17 00:00:00 2001 From: IOVGomezdn Date: Wed, 8 May 2024 18:06:44 -0300 Subject: [PATCH 03/44] fix: change build command in staging workflow --- .github/workflows/staging-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/staging-deploy.yml b/.github/workflows/staging-deploy.yml index 2135334e..225e11b1 100644 --- a/.github/workflows/staging-deploy.yml +++ b/.github/workflows/staging-deploy.yml @@ -24,7 +24,7 @@ jobs: run: npm ci - name: Build site - run: npm run build-with-tracking:testnet + run: npm run build-with-tracking:staging - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 From 82ed4d05c3761da81abf41a0a837cfa54c393de3 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Mon, 20 May 2024 18:03:28 -0300 Subject: [PATCH 04/44] feat: add contracts interaction view + read methods support --- .env.testnet | 1 + package-lock.json | 90 ++++++ package.json | 1 + src/components/ContractInteraction.vue | 368 +++++++++++++++++++++++++ src/jsonRpcProvider.js | 10 + src/router/addresses.js | 8 + vue.config.js | 24 +- 7 files changed, 501 insertions(+), 1 deletion(-) create mode 100644 src/components/ContractInteraction.vue create mode 100644 src/jsonRpcProvider.js diff --git a/.env.testnet b/.env.testnet index 818ae05d..a0e93036 100644 --- a/.env.testnet +++ b/.env.testnet @@ -1,4 +1,5 @@ VUE_APP_WS_URL=wss://be.explorer.testnet.rootstock.io +VUE_APP_JSON_RPC_PROVIDER=https://rpc.testnet.rootstock.io/MPVpltdu0FKIQlHMqaC5fZhek70Sng-T VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co VUE_APP_STATS_URL=https://stats.testnet.rootstock.io VUE_APP_GA_TAG=UA-136026316-1 diff --git a/package-lock.json b/package-lock.json index dd26181f..41d89f11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "core-js": "^3.6.4", "d3-format": "^1.4.3", "env-cmd": "^10.1.0", + "ethers": "^6.12.1", "highlight.js": "^9.18.3", "highlightjs-solidity": "git+https://github.com/highlightjs/highlightjs-solidity.git", "moment": "^2.27.0", @@ -68,6 +69,11 @@ "node": "8 || 10 || 12 || 14 || 16 || 17" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "dev": true, @@ -2109,6 +2115,28 @@ "node": ">=4" } }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@node-ipc/js-queue": { "version": "2.0.3", "dev": true, @@ -3475,6 +3503,11 @@ "node": ">= 10.0.0" } }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, "node_modules/after": { "version": "0.8.2", "license": "MIT" @@ -8272,6 +8305,63 @@ "node": ">= 0.6" } }, + "node_modules/ethers": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.12.1.tgz", + "integrity": "sha512-j6wcVoZf06nqEcBbDWkKg8Fp895SS96dSnTCjiXT+8vt2o02raTn4Lo9ERUuIVU5bAjoPYeA+7ytQFexFmLuVw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/event-pubsub": { "version": "4.3.0", "dev": true, diff --git a/package.json b/package.json index 060a0736..74ed9ed5 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "core-js": "^3.6.4", "d3-format": "^1.4.3", "env-cmd": "^10.1.0", + "ethers": "^6.12.1", "highlight.js": "^9.18.3", "highlightjs-solidity": "git+https://github.com/highlightjs/highlightjs-solidity.git", "moment": "^2.27.0", diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue new file mode 100644 index 00000000..5064beec --- /dev/null +++ b/src/components/ContractInteraction.vue @@ -0,0 +1,368 @@ + + + + + diff --git a/src/jsonRpcProvider.js b/src/jsonRpcProvider.js new file mode 100644 index 00000000..3acd92dd --- /dev/null +++ b/src/jsonRpcProvider.js @@ -0,0 +1,10 @@ +import { ethers } from 'ethers' + +export const jsonRpcProvider = new ethers.JsonRpcProvider(process.env.JSON_RPC_PROVIDER) + +// const getBlockNumber = async () => { +// const blockNumber = await jsonRpcProvider.getBlockNumber() +// console.log({ blockNumber }) +// } + +// getBlockNumber() diff --git a/src/router/addresses.js b/src/router/addresses.js index 45c534c1..fa87f880 100644 --- a/src/router/addresses.js +++ b/src/router/addresses.js @@ -1,6 +1,8 @@ import DataPage from '@/components/DataPage' import DataItem from '@/components/DataItem' import ContractCode from '@/components/ContractCode' +import ContractInteraction from '@/components/ContractInteraction' + import { ROUTES as r } from '../config/types' import { TRANSFER_EVENTS_SIGNATURES } from '../config/entities/lib/eventsLib' import store from '../store/' @@ -59,6 +61,12 @@ export default [ const { verification } = data if (verification && verification.match === true) return 'check' } + }, + { + name: 'Contract Interaction', + component: ContractInteraction, + render: data => (data && data.type === 'contract' && !data.isNative && data.verification), + hideTabs: true } ], dataType: 'address', diff --git a/vue.config.js b/vue.config.js index 347c8418..d91db1fd 100644 --- a/vue.config.js +++ b/vue.config.js @@ -20,7 +20,7 @@ module.exports = { .plugin('define') .tap(args => { const env = args[0]['process.env'] - const props = ['WS_URL', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] + const props = ['WS_URL', 'JSON_RPC_PROVIDER', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] props.forEach((v) => { env[v] = (process.env[v]) ? JSON.stringify(process.env[v]) : env['VUE_APP_' + v] || '""' }) @@ -54,5 +54,27 @@ module.exports = { .options({ name: 'assets/[name].[hash:8].[ext]' }) + + config.module + .rule('ethers') + .test(/\.js$/) + .include.add(/node_modules\/ethers/) + .end() + .use('babel-loader') + .loader('babel-loader') + .options({ + presets: ['@babel/preset-env'] + }) + + config.module + .rule('noble-curves') + .test(/\.js$/) + .include.add(/node_modules\/@noble\/curves/) + .end() + .use('babel-loader') + .loader('babel-loader') + .options({ + presets: ['@babel/preset-env'] + }) } } From 9fcff4e0c64e37810515171995a5a5a7cd39b684 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Mon, 20 May 2024 18:29:48 -0300 Subject: [PATCH 05/44] eslint: disable no-console rule --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index e637c66c..9dcd1396 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,7 +8,7 @@ module.exports = { '@vue/standard' ], rules: { - 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', + 'no-console': 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' }, parserOptions: { From 092c75437e37fe565d94bc62bf10655b64d8d3b4 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Mon, 20 May 2024 19:03:42 -0300 Subject: [PATCH 06/44] fix: add missing env variable for staging --- .env.staging | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.staging b/.env.staging index 4c10f1b5..f2cd533e 100644 --- a/.env.staging +++ b/.env.staging @@ -1,4 +1,5 @@ VUE_APP_WS_URL=wss://explorer-testnet-api.plattie-dev.iovlabs.net +VUE_APP_JSON_RPC_PROVIDER=https://rpc.testnet.rootstock.io/MPVpltdu0FKIQlHMqaC5fZhek70Sng-T VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co VUE_APP_STATS_URL=https://stats.testnet.rootstock.io VUE_APP_GA_TAG=UA-136026316-1 From bf4ccb9b37b1eda12d5e1f40eee08304d049d504 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Tue, 21 May 2024 16:15:25 -0300 Subject: [PATCH 07/44] feat: add network name manually. Add network env variable for testnet --- .env.staging | 1 + .env.testnet | 1 + src/jsonRpcProvider.js | 6 +++++- vue.config.js | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.env.staging b/.env.staging index f2cd533e..3b678f63 100644 --- a/.env.staging +++ b/.env.staging @@ -1,5 +1,6 @@ VUE_APP_WS_URL=wss://explorer-testnet-api.plattie-dev.iovlabs.net VUE_APP_JSON_RPC_PROVIDER=https://rpc.testnet.rootstock.io/MPVpltdu0FKIQlHMqaC5fZhek70Sng-T +VUE_APP_NETWORK=testnet VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co VUE_APP_STATS_URL=https://stats.testnet.rootstock.io VUE_APP_GA_TAG=UA-136026316-1 diff --git a/.env.testnet b/.env.testnet index a0e93036..7d5fa33c 100644 --- a/.env.testnet +++ b/.env.testnet @@ -1,5 +1,6 @@ VUE_APP_WS_URL=wss://be.explorer.testnet.rootstock.io VUE_APP_JSON_RPC_PROVIDER=https://rpc.testnet.rootstock.io/MPVpltdu0FKIQlHMqaC5fZhek70Sng-T +NETWORK=testnet VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co VUE_APP_STATS_URL=https://stats.testnet.rootstock.io VUE_APP_GA_TAG=UA-136026316-1 diff --git a/src/jsonRpcProvider.js b/src/jsonRpcProvider.js index 3acd92dd..6f782760 100644 --- a/src/jsonRpcProvider.js +++ b/src/jsonRpcProvider.js @@ -1,6 +1,10 @@ import { ethers } from 'ethers' -export const jsonRpcProvider = new ethers.JsonRpcProvider(process.env.JSON_RPC_PROVIDER) +export const jsonRpcProvider = new ethers.JsonRpcProvider( + process.env.JSON_RPC_PROVIDER, { + name: 'Rootstock', + chainId: process.env.NETWORK === 'testnet' ? 31 : 30 + }) // const getBlockNumber = async () => { // const blockNumber = await jsonRpcProvider.getBlockNumber() diff --git a/vue.config.js b/vue.config.js index d91db1fd..a26d8d01 100644 --- a/vue.config.js +++ b/vue.config.js @@ -20,7 +20,7 @@ module.exports = { .plugin('define') .tap(args => { const env = args[0]['process.env'] - const props = ['WS_URL', 'JSON_RPC_PROVIDER', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] + const props = ['WS_URL', 'NETWORK', 'JSON_RPC_PROVIDER', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] props.forEach((v) => { env[v] = (process.env[v]) ? JSON.stringify(process.env[v]) : env['VUE_APP_' + v] || '""' }) From 0dec972bcce0bf4aefedf0b371b979c343b7b5ab Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Tue, 21 May 2024 16:16:44 -0300 Subject: [PATCH 08/44] feat: add inputs validations. Minor style changes --- src/components/ContractInteraction.vue | 61 ++++++++++++++++++-------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 5064beec..2aada59b 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -23,16 +23,20 @@
-
-

{{ method.interactionData.result ?? '(result)' }}

+ +

{{ method.interactionData.result ?? 'result' }}

Error: {{ method.interactionData.message }}

@@ -43,7 +47,7 @@ + + From bcc2c83ec85c52a61ac561068e0b2d78de3f8258 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Wed, 22 May 2024 14:35:02 -0300 Subject: [PATCH 11/44] fix: display message even if contact function doesn't have outputs --- src/components/ContractMethods.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ContractMethods.vue b/src/components/ContractMethods.vue index f41c079a..9eafb284 100644 --- a/src/components/ContractMethods.vue +++ b/src/components/ContractMethods.vue @@ -4,7 +4,7 @@
-
+
-
+
From 0480458fa7abc064464bd8380864850dc1f4ef12 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Wed, 22 May 2024 17:36:01 -0300 Subject: [PATCH 12/44] fix: weird error when switching from tabs --- src/components/ContractInteraction.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 350dbd4d..27bd86c9 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -66,8 +66,13 @@ export default { verification () { return this.getData.verification || {} }, + stringifiedAbi () { + const { verification } = this + const abi = (verification) ? verification.abi : null + return (abi) ? JSON.stringify(abi, null, 2) : null + }, abi () { - return this.verification ? this.verification.abi : [] + return JSON.parse(this.stringifiedAbi) }, abiCategories () { return this.CATEGORIES From 32fcb13eac765810b2781bcd150171067561d814 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Wed, 22 May 2024 17:38:21 -0300 Subject: [PATCH 13/44] refactor: variable name --- src/components/ContractInteraction.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 27bd86c9..a41c3f7e 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -80,18 +80,18 @@ export default { parsedAbi () { const CATEGORIES = this.abiCategories - this.abi.forEach(value => { - const { type, stateMutability } = value + this.abi.forEach(fragment => { + const { type, stateMutability } = fragment if (type === 'constructor') { - this.registerAbiFragment(value, CATEGORIES.CONTRACT_CONSTRUCTOR) + this.registerAbiFragment(fragment, CATEGORIES.CONTRACT_CONSTRUCTOR) } else if (type === 'event') { - this.registerAbiFragment(value, CATEGORIES.EVENTS) + this.registerAbiFragment(fragment, CATEGORIES.EVENTS) } else if (type === 'function') { if (stateMutability === 'view') { - this.registerAbiFragment(value, CATEGORIES.READ_METHODS) + this.registerAbiFragment(fragment, CATEGORIES.READ_METHODS) } else if (stateMutability === 'nonpayable') { - this.registerAbiFragment(value, CATEGORIES.WRITE_METHODS) + this.registerAbiFragment(fragment, CATEGORIES.WRITE_METHODS) } } }) From 21344bda07e51d2ce82aeae296197c072cf4e59e Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Fri, 24 May 2024 19:30:04 -0300 Subject: [PATCH 14/44] feat: add write methods support --- src/components/ContractInteraction.vue | 222 +++++++++++++++++++------ src/components/ContractMethods.vue | 36 +++- src/jsonRpcProvider.js | 53 +++++- 3 files changed, 245 insertions(+), 66 deletions(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index a41c3f7e..7d77c068 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -7,23 +7,28 @@ -

Dev

+ + +
+

Metamask Connected!

+ Address: {{ this.signer.address }} +



- - + +
- diff --git a/src/components/ContractMethods.vue b/src/components/ContractMethods.vue index b7cd4dc3..3dad6ebf 100644 --- a/src/components/ContractMethods.vue +++ b/src/components/ContractMethods.vue @@ -2,38 +2,45 @@

{{ title }} ({{ methods.length }})

- - -
-
+ + +
+
+
+

{{ input.name || '<input>' }}

+ ({{ input.type }}) +
+ +
+
+ + +
- -
-
- -
-
- -
-
-

{{ method.interactionData.outputs[i] ?? 'result' }}

+
+
+

{{ method.interactionData.outputs[i] ?? 'result' }}

+
-
-

{{ method.interactionData.message.content }}

+

+ {{ method.interactionData.message.content }} +

+
- diff --git a/src/components/controls/Accordion.vue b/src/components/controls/Accordion.vue new file mode 100644 index 00000000..6e055ca4 --- /dev/null +++ b/src/components/controls/Accordion.vue @@ -0,0 +1,80 @@ + + + + + From a38d144db8ac572578da2ca8f9ac93896d8a3632 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Wed, 29 May 2024 12:32:42 -0300 Subject: [PATCH 18/44] fix: minor fixes --- src/components/ContractInteraction.vue | 6 +++++- src/components/ContractMethods.vue | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 43de1fa8..25f33f45 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -153,7 +153,8 @@ export default { message: { content: null, style: 'message-info' - } + }, + requested: false }) this.contractAbi[category].push(value) @@ -267,6 +268,7 @@ export default { async contractCall (methodName, inputs) { const methodIndex = this.contractAbi[this.CATEGORIES.READ_METHODS].findIndex(m => m.name === methodName) const method = this.contractAbi[this.CATEGORIES.READ_METHODS][methodIndex] + this.$set(method.interactionData, 'requested', true) this.$set(method.interactionData, 'message', { content: 'calling contract...', style: 'message-info' }) try { @@ -308,6 +310,8 @@ export default { this.$set(method.interactionData, 'outputs', []) this.$set(method.interactionData, 'message', { content: error.message, style: 'message-error' }) } + + this.$set(method.interactionData, 'requested', false) }, validateString (value) { if (typeof value !== 'string') throw new Error('Invalid string') diff --git a/src/components/ContractMethods.vue b/src/components/ContractMethods.vue index 3dad6ebf..ef30d6c4 100644 --- a/src/components/ContractMethods.vue +++ b/src/components/ContractMethods.vue @@ -13,15 +13,15 @@
- + -
+
-
+

{{ method.interactionData.outputs[i] ?? 'result' }}

From 566c7caa9b0b65a71446794dc6e52910aaca2aaf Mon Sep 17 00:00:00 2001 From: Carlos Rosado Date: Wed, 29 May 2024 11:38:21 -0600 Subject: [PATCH 19/44] feat: option to see the hash in the explorer added --- src/components/ContractInteraction.vue | 5 +++-- src/components/ContractMethods.vue | 29 ++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 25f33f45..e68c20bb 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -254,11 +254,12 @@ export default { }) const tx = await contract[methodName](...args) - this.$set(method.interactionData, 'message', { content: `Transaction sent. Waiting for confirmation... (hash: ${tx.hash})`, style: 'message-info' }) + this.$set(method.interactionData, 'hash', { content: tx.hash, style: 'message-info' }) + this.$set(method.interactionData, 'message', { content: 'Transaction sent. Waiting for confirmation... hash: ', style: 'message-info' }) await tx.wait() // receipt - this.$set(method.interactionData, 'message', { content: `Transaction confirmed. Hash: ${tx.hash}`, style: 'message-success' }) // TODO: add button for explorer tx in new tab according to network + this.$set(method.interactionData, 'message', { content: 'Transaction confirmed. Hash: ', style: 'message-success' }) // TODO: add button for explorer tx in new tab according to network } catch (error) { console.error(error) diff --git a/src/components/ContractMethods.vue b/src/components/ContractMethods.vue index ef30d6c4..4c927d99 100644 --- a/src/components/ContractMethods.vue +++ b/src/components/ContractMethods.vue @@ -26,8 +26,14 @@
-

- {{ method.interactionData.message.content }} +

+ + {{ method.interactionData.message.content }} + + {{ method.interactionData.hash.content }} + + + {{ method.interactionData?.message.content }}

@@ -35,6 +41,7 @@ @@ -350,7 +404,27 @@ export default { .tooltip .tooltip-text .trim-value .copy-icon svg { margin-top: 2px; } - + .flex-container { + display: flex; + flex-direction: column; + gap: 10px; + } + .network-changed-message { + color: $orange_900; + text-decoration: underline; + text-underline-offset: 2px; + margin-bottom: 10px; + } + .btn-reload { + border: 1px solid transparent; + padding: 10px; + animation: breathe 8s ease infinite; + background-color: transparent; + transition: color 0.3s ease; + } + .btn-reload:hover { + color: $orange_900; + } .btn-connect { border: 1px solid $newbw_700; padding: 10px; @@ -373,5 +447,20 @@ export default { margin-top: 20px; } } + + @keyframes breathe { + 0% { + box-shadow: 0 0 10px rgba(0, 255, 255, 0); + } + 30% { + box-shadow: 0 0 10px $orange_900; + } + 70% { + box-shadow: 0 0 10px $orange_900; + } + 100% { + box-shadow: 0 0 10px rgba(0, 255, 255, 0); + } +} } diff --git a/src/components/ContractMethods.vue b/src/components/ContractMethods.vue index 1d1c825a..eb64692a 100644 --- a/src/components/ContractMethods.vue +++ b/src/components/ContractMethods.vue @@ -26,14 +26,12 @@
-

- - {{ method.interactionData.message.content }} - - {{ method.interactionData.hash.content }} - +

+ {{ method.interactionData.message.content }} + + Hash: + {{ method.interactionData.hash.content }} - {{ method.interactionData?.message.content }}

@@ -203,6 +201,8 @@ export default { .interaction-message { padding: 5px; overflow: auto; + display: flex; + flex-direction: column; } .message-info { From 98c1fd720c1b4b82f13ee4b06f3201c34752f366 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Mon, 3 Jun 2024 13:18:08 -0300 Subject: [PATCH 23/44] fix: (QA) empty inputs length validation --- src/components/ContractInteraction.vue | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 9e7f6de4..7e1f0aea 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -270,8 +270,7 @@ export default { if (!contract) throw new Error('Connect to metamask first') - // inputs validations - if (inputs.length < method.inputs.length) throw new Error(`Invalid number of parameters for "${methodName}". Got ${inputs.length} expected ${method.inputs.length}!`) + this.validateInputs(inputs, method) method.inputs.forEach((input, index) => { const { type } = input @@ -305,8 +304,7 @@ export default { this.$set(method.interactionData, 'message', { content: 'calling contract...', style: 'message-info' }) try { - // inputs validations - if (inputs.length < method.inputs.length) throw new Error(`Invalid number of parameters for "${methodName}". Got ${inputs.length} expected ${method.inputs.length}!`) + this.validateInputs(inputs, method) const contract = this.getReadOnlyContractInstance() const args = inputs @@ -344,6 +342,11 @@ export default { this.$set(method.interactionData, 'requested', false) }, + validateInputs (inputs, method) { + const nonEmptyInputs = inputs.filter(input => input !== '' && input !== undefined && input !== null) + + if (nonEmptyInputs.length !== method.inputs.length) throw new Error(`Invalid number of parameters for "${method.name}". Got ${nonEmptyInputs.length} expected ${method.inputs.length}!`) + }, validateString (value) { if (typeof value !== 'string') throw new Error('Invalid string') }, From d4ce58ac1fcd50228ec83b985a86c2bf0c93266b Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Mon, 3 Jun 2024 13:22:00 -0300 Subject: [PATCH 24/44] fix: (QA) allow long outputs display by using dynamic accordion component height --- src/components/controls/Accordion.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/controls/Accordion.vue b/src/components/controls/Accordion.vue index 6e055ca4..86f6431a 100644 --- a/src/components/controls/Accordion.vue +++ b/src/components/controls/Accordion.vue @@ -75,6 +75,6 @@ export default { } .accordion-content.open { - max-height: 400px; + max-height: max-content; } From 8fd60cb9c206d86cb962fdc720aacfa713ff2762 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Wed, 5 Jun 2024 14:29:00 -0300 Subject: [PATCH 25/44] fix: consider pure function methods for smart contract calls --- src/components/ContractInteraction.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 7e1f0aea..820cb5c9 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -135,7 +135,7 @@ export default { } else if (type === 'event') { this.registerAbiFragment(fragment, CATEGORIES.EVENTS) } else if (type === 'function') { - if (stateMutability === 'view') { + if (stateMutability === 'view' || stateMutability === 'pure') { this.registerAbiFragment(fragment, CATEGORIES.READ_METHODS) } else if (stateMutability === 'nonpayable') { this.registerAbiFragment(fragment, CATEGORIES.WRITE_METHODS) From aeef058421abe531eaa77658ec58d23ab27f1a38 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Wed, 5 Jun 2024 16:35:22 -0300 Subject: [PATCH 26/44] fix: consider payable functions (send value) for smart contract calls --- src/components/ContractInteraction.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index 820cb5c9..a7a90599 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -137,7 +137,7 @@ export default { } else if (type === 'function') { if (stateMutability === 'view' || stateMutability === 'pure') { this.registerAbiFragment(fragment, CATEGORIES.READ_METHODS) - } else if (stateMutability === 'nonpayable') { + } else if (stateMutability === 'nonpayable' || stateMutability === 'payable') { this.registerAbiFragment(fragment, CATEGORIES.WRITE_METHODS) } } From b05ceb66e7e6b8f101dd9ba1c66a8301bdc47a58 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Thu, 13 Jun 2024 10:43:11 -0300 Subject: [PATCH 27/44] fix: remove json rpc provider url from testnet config --- .env.testnet | 1 - 1 file changed, 1 deletion(-) diff --git a/.env.testnet b/.env.testnet index 7d5fa33c..1a224a98 100644 --- a/.env.testnet +++ b/.env.testnet @@ -1,5 +1,4 @@ VUE_APP_WS_URL=wss://be.explorer.testnet.rootstock.io -VUE_APP_JSON_RPC_PROVIDER=https://rpc.testnet.rootstock.io/MPVpltdu0FKIQlHMqaC5fZhek70Sng-T NETWORK=testnet VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co VUE_APP_STATS_URL=https://stats.testnet.rootstock.io From 50a1bedf2801e85ad829bf3c40c3000823406749 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Thu, 13 Jun 2024 10:45:01 -0300 Subject: [PATCH 28/44] refactor: use public nodes until metamask adds support for our RPC API service and ApiKey is not exposed in metamask config --- .env.staging | 1 - src/jsonRpcProvider.js | 4 +--- vue.config.js | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.env.staging b/.env.staging index 3b678f63..4cd1d0c5 100644 --- a/.env.staging +++ b/.env.staging @@ -1,5 +1,4 @@ VUE_APP_WS_URL=wss://explorer-testnet-api.plattie-dev.iovlabs.net -VUE_APP_JSON_RPC_PROVIDER=https://rpc.testnet.rootstock.io/MPVpltdu0FKIQlHMqaC5fZhek70Sng-T VUE_APP_NETWORK=testnet VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co VUE_APP_STATS_URL=https://stats.testnet.rootstock.io diff --git a/src/jsonRpcProvider.js b/src/jsonRpcProvider.js index d21d36fb..f79542cd 100644 --- a/src/jsonRpcProvider.js +++ b/src/jsonRpcProvider.js @@ -1,7 +1,5 @@ import { ethers } from 'ethers' -const rpcServiceApiUrl = process.env.JSON_RPC_PROVIDER - export const envNetwork = process.env.NETWORK if (!['mainnet', 'testnet'].includes(envNetwork)) throw new Error(`Invalid env network provided: "${envNetwork}"`) @@ -42,7 +40,7 @@ export const rskNetworks = { } export const jsonRpcProvider = new ethers.providers.JsonRpcProvider( - rpcServiceApiUrl, + rskNetworks[envNetwork].rpcUrls[0], { name: rskNetworks[envNetwork].chainName, chainId: parseInt(rskNetworks[envNetwork].chainId) diff --git a/vue.config.js b/vue.config.js index a26d8d01..e4b829eb 100644 --- a/vue.config.js +++ b/vue.config.js @@ -20,7 +20,7 @@ module.exports = { .plugin('define') .tap(args => { const env = args[0]['process.env'] - const props = ['WS_URL', 'NETWORK', 'JSON_RPC_PROVIDER', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] + const props = ['WS_URL', 'NETWORK', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] props.forEach((v) => { env[v] = (process.env[v]) ? JSON.stringify(process.env[v]) : env['VUE_APP_' + v] || '""' }) From e0d3512c64af8f90a60a788b17be8583a86dbf22 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Thu, 13 Jun 2024 12:40:21 -0300 Subject: [PATCH 29/44] refactor: accordion smooth transition by dynamic height --- src/components/controls/Accordion.vue | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/components/controls/Accordion.vue b/src/components/controls/Accordion.vue index 86f6431a..5dbefa87 100644 --- a/src/components/controls/Accordion.vue +++ b/src/components/controls/Accordion.vue @@ -8,8 +8,10 @@ {{ isOpen ? '-' : '+' }}
-
- +
+
+ +
@@ -63,18 +65,23 @@ export default { background-color: #555; } +.accordion-content-wrapper { + display: grid; + grid-template-rows: 0fr; + transition: grid-template-rows 0.3s ease-in-out; +} + +.accordion-content-wrapper.open { + grid-template-rows: 1fr; +} + .accordion-content { - max-height: 0; overflow: hidden; padding: 0 15px; - transition: max-height 0.5s ease; color: #fff; border: 1px solid $newbw_700; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; } -.accordion-content.open { - max-height: max-content; -} From 036a6a48e8684eda8e3a1faa1c0d0329c390ebfd Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Fri, 14 Jun 2024 16:39:21 -0300 Subject: [PATCH 30/44] fix: add metamask connection message. Prevent explorer from not loading because of missing window.ethereum prop (metamask uninstalled) --- src/components/ContractInteraction.vue | 22 ++++++++++++++----- src/jsonRpcProvider.js | 30 ++++++++++++++++++++------ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/components/ContractInteraction.vue b/src/components/ContractInteraction.vue index a7a90599..37747f1c 100644 --- a/src/components/ContractInteraction.vue +++ b/src/components/ContractInteraction.vue @@ -2,8 +2,13 @@
+
+

{{ installMetamaskMsg }}

+ {{ metamaskExtensionUrl }} +

+
-

Warning: Network change detected. It's strongly recommended to reload the page to prevent loss of funds or unexpected behaviors.

+

Warning: Network change detected. It's strongly recommended to reload the page to prevent loss of funds or unexpected behaviors.

@@ -92,9 +97,11 @@ export default { readOnly: null, write: null }, - jsonRpcProvider, + jsonRpcProvider: jsonRpcProvider(), metamaskConnected: false, - installMetamaskMsg: 'MetaMask extension is not installed. Please install it first: https://metamask.io/download/', + showMetamaskNotInstalledMsg: false, + installMetamaskMsg: 'MetaMask extension is not installed. Please install it first:', + metamaskExtensionUrl: 'https://metamask.io/download/', browserProvider: null, signer: null, signerAddress: null, @@ -219,7 +226,7 @@ export default { }, async connectToRskNetwork () { await window.ethereum.request({ method: 'eth_requestAccounts' }) - this.$set(this, 'browserProvider', browserProvider) + this.$set(this, 'browserProvider', browserProvider()) const currentNetwork = await this.browserProvider.getNetwork() const currentChainId = `0x${currentNetwork.chainId.toString(16)}` @@ -255,6 +262,7 @@ export default { console.error('Error when connecting to metamask', error) } } else { + this.$set(this, 'showMetamaskNotInstalledMsg', true) console.error(this.installMetamaskMsg) } }, @@ -412,12 +420,16 @@ export default { flex-direction: column; gap: 10px; } - .network-changed-message { + .metamask-connection-message { color: $orange_900; text-decoration: underline; text-underline-offset: 2px; margin-bottom: 10px; } + + .metamask-link { + color: #fff; + } .btn-reload { border: 1px solid transparent; padding: 10px; diff --git a/src/jsonRpcProvider.js b/src/jsonRpcProvider.js index f79542cd..b56c6c59 100644 --- a/src/jsonRpcProvider.js +++ b/src/jsonRpcProvider.js @@ -39,15 +39,31 @@ export const rskNetworks = { } } -export const jsonRpcProvider = new ethers.providers.JsonRpcProvider( - rskNetworks[envNetwork].rpcUrls[0], - { - name: rskNetworks[envNetwork].chainName, - chainId: parseInt(rskNetworks[envNetwork].chainId) +export const jsonRpcProvider = () => { + try { + const provider = new ethers.providers.JsonRpcProvider( + rskNetworks[envNetwork].rpcUrls[0], + { + name: rskNetworks[envNetwork].chainName, + chainId: parseInt(rskNetworks[envNetwork].chainId) + } + ) + + return provider + } catch (error) { + console.error('Error creating jsonRpcProvider instance:', error) } -) +} + +export const browserProvider = () => { + try { + const browserProvider = new ethers.providers.Web3Provider(window.ethereum) -export const browserProvider = new ethers.providers.Web3Provider(window.ethereum) + return browserProvider + } catch (error) { + console.error('Error creating web3 browser provider instance:', error) + } +} // const getBlockNumber = async () => { // const blockNumber = await jsonRpcProvider.getBlockNumber() From 43eb559650fb3cd349fd6cb7206df74a6266f807 Mon Sep 17 00:00:00 2001 From: Nicolas Vargas Date: Wed, 26 Jun 2024 13:40:19 -0300 Subject: [PATCH 31/44] WIP: show implementation address for ERC1967 proxies --- .env.staging | 11 + .eslintrc.js | 2 +- .github/workflows/staging-deploy.yml | 40 + package-lock.json | 746 +++++++++++++++++- package.json | 4 + src/components/DataItem.vue | 5 +- src/components/ImplementationAddressField.vue | 87 ++ src/config/entities/address.js | 6 + src/jsonRpcProvider.js | 56 ++ vue.config.js | 24 +- 10 files changed, 971 insertions(+), 10 deletions(-) create mode 100644 .env.staging create mode 100644 .github/workflows/staging-deploy.yml create mode 100644 src/components/ImplementationAddressField.vue create mode 100644 src/jsonRpcProvider.js diff --git a/.env.staging b/.env.staging new file mode 100644 index 00000000..4cd1d0c5 --- /dev/null +++ b/.env.staging @@ -0,0 +1,11 @@ +VUE_APP_WS_URL=wss://explorer-testnet-api.plattie-dev.iovlabs.net +VUE_APP_NETWORK=testnet +VUE_APP_APPS_URL=https://apps.explorer.testnet.rsk.co +VUE_APP_STATS_URL=https://stats.testnet.rootstock.io +VUE_APP_GA_TAG=UA-136026316-1 +VUE_APP_HOTJAR_ID=1901396 +VUE_APP_STREAM_MITM_URL=/mitm/index.html +VUE_APP_DOMAIN_TESTNET='https://explorer.testnet.rootstock.io/' +VUE_APP_DOMAIN_MAINNET='https://explorer.rootstock.io/' +VUE_APP_DOMAIN_STATS_TESTNET='https://stats.testnet.rootstock.io/' +VUE_APP_DOMAIN_STATS_MAINNET='https://stats.rootstock.io/' \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index e637c66c..9dcd1396 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,7 +8,7 @@ module.exports = { '@vue/standard' ], rules: { - 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', + 'no-console': 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' }, parserOptions: { diff --git a/.github/workflows/staging-deploy.yml b/.github/workflows/staging-deploy.yml new file mode 100644 index 00000000..35f989a2 --- /dev/null +++ b/.github/workflows/staging-deploy.yml @@ -0,0 +1,40 @@ +name: RSK Explorer staging build and deploy + +on: + push: + branches: [staging] + +jobs: + staging_build_and_deploy: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Node 16 + uses: actions/setup-node@v1 + with: + node-version: "16" + + - name: Install dependencies + run: npm ci + + - name: Build site + run: npm run build-with-tracking:staging + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.STAGING_ROLE_ARN }} + aws-region: ${{ secrets.STAGING_AWS_REGION }} + + - name: Deploy site to S3 + run: | + aws s3 sync --sse aws:kms --sse-kms-key-id ${{ secrets.STAGING_KMS_KEY_ID }} --delete --only-show-errors --exclude .gitkeep dist/ ${{ secrets.STAGING_S3_BUCKET }} + - name: Invalidate CloudFront cache + run: | + aws cloudfront create-invalidation --distribution-id ${{ secrets.STAGING_CLOUDFRONT_DISTRIBUTION }} --paths "/*" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9c00b2b9..3d318fa7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "core-js": "^3.6.4", "d3-format": "^1.4.3", "env-cmd": "^10.1.0", + "ethers": "^5.7.0", "highlight.js": "^9.18.3", "highlightjs-solidity": "git+https://github.com/highlightjs/highlightjs-solidity.git", "keccak": "^3.0.4", @@ -1916,6 +1917,687 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", + "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", + "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", + "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", + "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.0.tgz", + "integrity": "sha512-MG6oHSQHd4ebvJrleEQQ4HhVu8Ichr0RDYEfHzsVAVjHNM+w36x9wp9r+hf1JstMXtseXDtkiVoARAG6M959AA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", + "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.0.tgz", + "integrity": "sha512-+TTrrINMzZ0aXtlwO/95uhAggKm4USLm1PbeCBR/3XZ7+Oey+3pMyddzZEyRhizHpy1HXV0FRWRMI1O3EGYibA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/@ethersproject/providers/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + }, + "node_modules/@ethersproject/random": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", + "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", + "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", + "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", + "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", + "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.0.tgz", + "integrity": "sha512-ApHcbbj+muRASVDSCl/tgxaH2LBkRMEYfLOLVa0COipx0+nlu0QKet7U2lEg0vdkh8XRSLf2nd1f1Uk9SrVSGA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", + "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, "node_modules/@hapi/address": { "version": "2.1.4", "deprecated": "Moved to 'npm install @sideway/address'", @@ -3443,6 +4125,11 @@ "node": ">= 10.0.0" } }, + "node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" + }, "node_modules/after": { "version": "0.8.2", "license": "MIT" @@ -4323,7 +5010,6 @@ }, "node_modules/brorand": { "version": "1.1.0", - "dev": true, "license": "MIT" }, "node_modules/browser-process-hrtime": { @@ -7256,7 +7942,6 @@ }, "node_modules/elliptic": { "version": "6.5.4", - "dev": true, "license": "MIT", "dependencies": { "bn.js": "^4.11.9", @@ -7270,7 +7955,6 @@ }, "node_modules/elliptic/node_modules/bn.js": { "version": "4.12.0", - "dev": true, "license": "MIT" }, "node_modules/emoji-regex": { @@ -8281,6 +8965,53 @@ "js-sha3": "^0.5.7" } }, + "node_modules/ethers": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.0.tgz", + "integrity": "sha512-5Xhzp2ZQRi0Em+0OkOcRHxPzCfoBfgtOQA+RUylSkuHbhTEaQklnYi2hsWbRgs3ztJsXVXd9VKBcO1ScWL8YfA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.0", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.0", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.0", + "@ethersproject/wordlists": "5.7.0" + } + }, "node_modules/event-pubsub": { "version": "4.3.0", "dev": true, @@ -9605,7 +10336,6 @@ }, "node_modules/hash.js": { "version": "1.1.7", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -9652,7 +10382,6 @@ }, "node_modules/hmac-drbg": { "version": "1.0.1", - "dev": true, "license": "MIT", "dependencies": { "hash.js": "^1.0.3", @@ -12322,12 +13051,10 @@ }, "node_modules/minimalistic-assert": { "version": "1.0.1", - "dev": true, "license": "ISC" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", - "dev": true, "license": "MIT" }, "node_modules/minimatch": { @@ -16570,6 +17297,11 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + }, "node_modules/select-hose": { "version": "2.0.0", "dev": true, diff --git a/package.json b/package.json index 236f19cb..a083f711 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,15 @@ "scripts": { "dev:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service serve", "dev:testnet": "env-cmd -f .env.testnet npx vue-cli-service serve", + "dev:staging": "env-cmd -f .env.staging npx vue-cli-service serve", "dev-with-tracking:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service serve src/main.with.tracking.js", "dev-with-tracking:testnet": "env-cmd -f .env.testnet npx vue-cli-service serve src/main.with.tracking.js", "build:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service build --modern", "build:testnet": "env-cmd -f .env.testnet npx vue-cli-service build --modern", + "build:staging": "env-cmd -f .env.staging npx vue-cli-service build --modern", "build-with-tracking:mainnet": "env-cmd -f .env.mainnet npx vue-cli-service build src/main.with.tracking.js --modern", "build-with-tracking:testnet": "env-cmd -f .env.testnet npx vue-cli-service build src/main.with.tracking.js --modern", + "build-with-tracking:staging": "env-cmd -f .env.staging npx vue-cli-service build src/main.with.tracking.js --modern", "test:unit": "npx vue-cli-service test:unit", "test:e2e": "npx vue-cli-service test:e2e", "lint": "npx vue-cli-service lint", @@ -25,6 +28,7 @@ "core-js": "^3.6.4", "d3-format": "^1.4.3", "env-cmd": "^10.1.0", + "ethers": "^5.7.0", "highlight.js": "^9.18.3", "highlightjs-solidity": "git+https://github.com/highlightjs/highlightjs-solidity.git", "keccak": "^3.0.4", diff --git a/src/components/DataItem.vue b/src/components/DataItem.vue index 2369b3b8..814dff50 100644 --- a/src/components/DataItem.vue +++ b/src/components/DataItem.vue @@ -37,6 +37,8 @@ import DataTable from '@/components/General/DataTable' import FieldItem from './FieldItem' import CollapsibleList from './CollapsibleList' import EventCall from './EventCall' +import ImplementationAddressField from './ImplementationAddressField' + export default { name: 'data-item', props: [ @@ -51,7 +53,8 @@ export default { FieldTitle, FieldItem, CollapsibleList, - EventCall + EventCall, + ImplementationAddressField }, mixins: [ dataMixin diff --git a/src/components/ImplementationAddressField.vue b/src/components/ImplementationAddressField.vue new file mode 100644 index 00000000..b24ee01a --- /dev/null +++ b/src/components/ImplementationAddressField.vue @@ -0,0 +1,87 @@ + + + + + + diff --git a/src/config/entities/address.js b/src/config/entities/address.js index 0a951a5f..8b7aa889 100644 --- a/src/config/entities/address.js +++ b/src/config/entities/address.js @@ -18,6 +18,7 @@ export const Addresses = () => { listLink: `/${r.addresses}`, fields: { address: null, + implementation: null, balance: { filters: valueFilters(true), default: 0, @@ -44,6 +45,11 @@ export const Address = () => { address: { trim: 'auto' }, + implementation: { + hideIfEmpty: true, + field: 'address', + renderAs: 'implementation-address-field' + }, contractInterfaces: { icon: 'link-external', hideIfEmpty: true, diff --git a/src/jsonRpcProvider.js b/src/jsonRpcProvider.js new file mode 100644 index 00000000..dac83952 --- /dev/null +++ b/src/jsonRpcProvider.js @@ -0,0 +1,56 @@ +import { ethers } from 'ethers' + +export const envNetwork = process.env.NETWORK + +if (!['mainnet', 'testnet'].includes(envNetwork)) throw new Error(`Invalid env network provided: "${envNetwork}"`) + +export const rskNetworks = { + mainnet: { + chainName: 'Rootstock Mainnet - RPC API', + chainId: '0x1e', // 30 + nativeCurrency: { + name: 'Smart Bitcoin', + symbol: 'RBTC', + decimals: 18 + }, + rpcUrls: [ + 'https://public-node.rsk.co' + ], + blockExplorerUrls: [ + 'https://explorer.rootstock.io/', + 'https://rootstock.blockscout.com/' // fallback + ] + }, + testnet: { + chainName: 'Rootstock Testnet - RPC API', + chainId: '0x1f', // 31 + nativeCurrency: { + name: 'Test Smart Bitcoin', + symbol: 'tRBTC', + decimals: 18 + }, + rpcUrls: [ + 'https://public-node.testnet.rsk.co' + ], + blockExplorerUrls: [ + 'https://explorer.testnet.rootstock.io/', + 'https://rootstock-testnet.blockscout.com/' // fallback + ] + } +} + +export const jsonRpcProvider = () => { + try { + const provider = new ethers.providers.JsonRpcProvider( + rskNetworks[envNetwork].rpcUrls[0], + { + name: rskNetworks[envNetwork].chainName, + chainId: parseInt(rskNetworks[envNetwork].chainId) + } + ) + + return provider + } catch (error) { + console.error('Error creating jsonRpcProvider instance:', error) + } +} diff --git a/vue.config.js b/vue.config.js index 347c8418..e4b829eb 100644 --- a/vue.config.js +++ b/vue.config.js @@ -20,7 +20,7 @@ module.exports = { .plugin('define') .tap(args => { const env = args[0]['process.env'] - const props = ['WS_URL', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] + const props = ['WS_URL', 'NETWORK', 'STATS_URL', 'GA_TAG', 'HOTJAR_ID', 'STREAM_MITM_URL', 'APPS_URL'] props.forEach((v) => { env[v] = (process.env[v]) ? JSON.stringify(process.env[v]) : env['VUE_APP_' + v] || '""' }) @@ -54,5 +54,27 @@ module.exports = { .options({ name: 'assets/[name].[hash:8].[ext]' }) + + config.module + .rule('ethers') + .test(/\.js$/) + .include.add(/node_modules\/ethers/) + .end() + .use('babel-loader') + .loader('babel-loader') + .options({ + presets: ['@babel/preset-env'] + }) + + config.module + .rule('noble-curves') + .test(/\.js$/) + .include.add(/node_modules\/@noble\/curves/) + .end() + .use('babel-loader') + .loader('babel-loader') + .options({ + presets: ['@babel/preset-env'] + }) } } From f14ee69107c1934f7971bcecd14f79d4b590f3e5 Mon Sep 17 00:00:00 2001 From: Carlos Rosado Date: Wed, 26 Jun 2024 11:25:35 -0600 Subject: [PATCH 32/44] fix: avoid the scroll jump and align value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit avoid the scroll jump when you are on the same page and the values ​​in the token transfers tab are aligned --- src/components/DataField.vue | 95 +++++++++++++++++++++++++++- src/components/General/DataTable.vue | 2 +- src/config/entities/event.js | 4 +- src/router/index.js | 18 ++---- 4 files changed, 101 insertions(+), 18 deletions(-) diff --git a/src/components/DataField.vue b/src/components/DataField.vue index 2a20af8c..bd750b2d 100644 --- a/src/components/DataField.vue +++ b/src/components/DataField.vue @@ -19,7 +19,22 @@ - +