From fbc0ba0ebda19e64581b5304035f610f88c49095 Mon Sep 17 00:00:00 2001 From: rrozek Date: Wed, 14 Aug 2024 04:17:13 +0200 Subject: [PATCH] add evm support in dapp analytics validation --- .../build-and-push-ecr-dev-server.yml | 4 +- .../build-and-push-ecr-prod-server.yml | 4 +- k8s/db-api/environment/dev/values-new.yaml | 48 ++++++++++ k8s/db-api/environment/dev/values.yaml | 2 +- k8s/db-api/environment/prod/values.yaml | 2 +- .../template/templates/db-api-secrets.yaml | 4 +- package-lock.json | 94 ++++++++++++++++++- package.json | 1 + src/validation/dapp-analytics-validations.ts | 74 ++++++++++++--- 9 files changed, 212 insertions(+), 21 deletions(-) create mode 100644 k8s/db-api/environment/dev/values-new.yaml diff --git a/.github/workflows/build-and-push-ecr-dev-server.yml b/.github/workflows/build-and-push-ecr-dev-server.yml index 9825f81..5620a9a 100644 --- a/.github/workflows/build-and-push-ecr-dev-server.yml +++ b/.github/workflows/build-and-push-ecr-dev-server.yml @@ -21,9 +21,9 @@ jobs: - name: Build Docker image run: docker build -t db-api . - name: Run tests with temp db - run: docker-compose -f docker-compose-test.yaml run db-api npm test + run: docker compose -f docker-compose-test.yaml run db-api npm test - name: Remove docker and volumes - run: docker-compose -f docker-compose-test.yaml down -v + run: docker compose -f docker-compose-test.yaml down -v build-push: name: Build image and push to ECR(tokenguard-dev) if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' diff --git a/.github/workflows/build-and-push-ecr-prod-server.yml b/.github/workflows/build-and-push-ecr-prod-server.yml index 891d4de..29b8e3c 100644 --- a/.github/workflows/build-and-push-ecr-prod-server.yml +++ b/.github/workflows/build-and-push-ecr-prod-server.yml @@ -21,9 +21,9 @@ jobs: - name: Build Docker image run: docker build -t db-api . - name: Run tests with temp db - run: docker-compose -f docker-compose-test.yaml run db-api npm test + run: docker compose -f docker-compose-test.yaml run db-api npm test - name: Remove docker and volumes - run: docker-compose -f docker-compose-test.yaml down -v + run: docker compose -f docker-compose-test.yaml down -v build-push: name: Build and push to ECR(tokenguard-prod) diff --git a/k8s/db-api/environment/dev/values-new.yaml b/k8s/db-api/environment/dev/values-new.yaml new file mode 100644 index 0000000..9209681 --- /dev/null +++ b/k8s/db-api/environment/dev/values-new.yaml @@ -0,0 +1,48 @@ +# values for db-api dev environment. +ecrRegistry: 123622898391.dkr.ecr.eu-west-1.amazonaws.com +eksEnvironment: tokenguard-dev + +imagePullSecrets: ~ + +ingressExternal: + enabled: false + +ingressInternal: + enabled: true + name: db-api-new-ingress-internal + rules: + - host: db-api-new.dev.tokenguard.io + http: + paths: + - backend: + service: + name: db-api-new + port: + number: 8082 + path: / + pathType: Prefix + +dbapi: + deployment: + name: db-api-new + image: + repository: "tokenguard-dev-db-api" + pullPolicy: Always + tag: "3180ea8b2301e29469454514aa1dd60c5e7c99f2" + replicaCount: 1 + env: + NODE_ENV: "development" + resources: + requests: + memory: "256Mi" + cpu: "200m" + limits: + memory: "2Gi" + cpu: "2000m" + configmap: + name: db-api-new + service: + name: db-api-new + +secrets: + name: db-api-new-secrets diff --git a/k8s/db-api/environment/dev/values.yaml b/k8s/db-api/environment/dev/values.yaml index 411f700..cbfa289 100644 --- a/k8s/db-api/environment/dev/values.yaml +++ b/k8s/db-api/environment/dev/values.yaml @@ -27,7 +27,7 @@ dbapi: image: repository: "tokenguard-dev-db-api" pullPolicy: Always - tag: "3a4626d1b83624acbfae925fc9ae71da0df890e2" + tag: "3180ea8b2301e29469454514aa1dd60c5e7c99f2" replicaCount: 1 env: NODE_ENV: "development" diff --git a/k8s/db-api/environment/prod/values.yaml b/k8s/db-api/environment/prod/values.yaml index febde2a..083337c 100644 --- a/k8s/db-api/environment/prod/values.yaml +++ b/k8s/db-api/environment/prod/values.yaml @@ -27,7 +27,7 @@ dbapi: image: repository: "tokenguard-prod-db-api" pullPolicy: Always - tag: "f367530ced7474509a6f1d86032c3bab4de06e0c" + tag: "3193831990458e3d550506dfeba77318bc57df64" replicaCount: 1 env: NODE_ENV: "production" diff --git a/k8s/db-api/template/templates/db-api-secrets.yaml b/k8s/db-api/template/templates/db-api-secrets.yaml index f4de49c..a43e621 100644 --- a/k8s/db-api/template/templates/db-api-secrets.yaml +++ b/k8s/db-api/template/templates/db-api-secrets.yaml @@ -3,8 +3,8 @@ kind: Secret metadata: name: {{ .Values.secrets.name }} stringData: - data-postgres-host: "ref+awsssm://{{ .Values.eksEnvironment }}/infrastructure/rds/postgres/address" - data-postgres-port: "ref+awsssm://{{ .Values.eksEnvironment }}/infrastructure/rds/postgres/port" + data-postgres-host: "ref+awsssm://{{ .Values.eksEnvironment }}/infrastructure/rds/postgres-prod/address" + data-postgres-port: "ref+awsssm://{{ .Values.eksEnvironment }}/infrastructure/rds/postgres-prod/port" data-postgres-username: "ref+awsssm://{{ .Values.eksEnvironment }}/application/db-api/db/data/username" data-postgres-password: "ref+awsssm://{{ .Values.eksEnvironment }}/application/db-api/db/data/password" data-postgres-dbnames: "ref+awsssm://{{ .Values.eksEnvironment }}/application/db-api/db/data/dbnames" diff --git a/package-lock.json b/package-lock.json index 7da444a..340f7dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "db-api", - "version": "1.5.1", + "version": "1.5.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "db-api", - "version": "1.5.1", + "version": "1.5.3", "dependencies": { "@polkadot/keyring": "^12.6.2", "@subsquid/ink-abi": "^3.1.0", "cors": "^2.8.5", "dotenv": "16.3.1", "errorhandler": "1.5.1", + "ethers": "^6.13.1", "express": "4.18.2", "helmet": "^7.1.0", "http-status": "^1.7.3", @@ -64,6 +65,11 @@ "node": ">=0.10.0" } }, + "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", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -2671,6 +2677,11 @@ "node": ">=0.4.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/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4078,6 +4089,65 @@ "node": ">= 0.6" } }, + "node_modules/ethers": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", + "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", + "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.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/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/ethers/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/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/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -8278,6 +8348,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "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/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 642cea3..52cb058 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "cors": "^2.8.5", "dotenv": "16.3.1", "errorhandler": "1.5.1", + "ethers": "^6.13.1", "express": "4.18.2", "helmet": "^7.1.0", "http-status": "^1.7.3", diff --git a/src/validation/dapp-analytics-validations.ts b/src/validation/dapp-analytics-validations.ts index f6ebaf2..a166374 100644 --- a/src/validation/dapp-analytics-validations.ts +++ b/src/validation/dapp-analytics-validations.ts @@ -1,7 +1,9 @@ import Joi from "joi"; -import { Abi as SubsquidAbi } from "@subsquid/ink-abi"; -import { decodeAddress } from "@polkadot/keyring"; +import { Abi as SubsquidInkAbi } from "@subsquid/ink-abi"; +import { Interface as SubsquidEvmAbi, isAddress as isEvmAddress } from "ethers"; +import { decodeAddress as decodeSubstrateAddress } from "@polkadot/keyring"; +// Validator for Substrate addresses const substrateAddressValidator = Joi.extend((joi) => ({ type: "substrateAddress", base: joi.string(), @@ -10,7 +12,7 @@ const substrateAddressValidator = Joi.extend((joi) => ({ }, validate(value, helpers) { try { - decodeAddress(value); + decodeSubstrateAddress(value); return { value }; } catch (error) { return { errors: helpers.error("substrateAddress.base") }; @@ -18,28 +20,78 @@ const substrateAddressValidator = Joi.extend((joi) => ({ }, })); -const subsquidAbiValidator = Joi.extend((joi) => ({ - type: "subsquidAbi", +// Validator for EVM addresses +const evmAddressValidator = Joi.extend((joi) => ({ + type: "evmAddress", + base: joi.string(), + messages: { + "evmAddress.base": "{{#label}} must be a valid EVM address", + }, + validate(value, helpers) { + try { + if (isEvmAddress(value)) { + return { value }; + } else { + return { errors: helpers.error("evmAddress.base") }; + } + } catch (error) { + return { errors: helpers.error("evmAddress.base") }; + } + }, +})); + +// Validator for Subsquid Ink ABI (object) +const subsquidInkAbiValidator = Joi.extend((joi) => ({ + type: "subsquidInkAbi", base: joi.object(), messages: { - "subsquidAbi.validate": - "{{#label}} does not conform to Subsquid ABI format", + "subsquidInkAbi.validate": + "{{#label}} does not conform to Subsquid Ink ABI format", + }, + validate(value, helpers) { + try { + new SubsquidInkAbi(value); + return { value }; + } catch (error) { + return { errors: helpers.error("subsquidInkAbi.validate") }; + } + }, +})); + +// Validator for EVM ABI (array) +const subsquidEvmAbiValidator = Joi.extend((joi) => ({ + type: "subsquidEvmAbi", + base: joi.array(), + messages: { + "subsquidEvmAbi.validate": + "{{#label}} does not conform to Subsquid EVM ABI format", }, validate(value, helpers) { try { - new SubsquidAbi(value); + new SubsquidEvmAbi(value); // This line checks the validity of the ABI return { value }; } catch (error) { - return { errors: helpers.error("subsquidAbi.validate") }; + return { errors: helpers.error("subsquidEvmAbi.validate") }; } }, })); +// Combined ABI Validator const abiSchema = Joi.array().items( Joi.object({ name: Joi.string(), - address: substrateAddressValidator.substrateAddress().required(), - abi: subsquidAbiValidator.subsquidAbi().required(), + address: Joi.alternatives() + .try( + substrateAddressValidator.substrateAddress(), + evmAddressValidator.evmAddress() + ) + .required(), + abi: Joi.alternatives() + .try( + subsquidInkAbiValidator.subsquidInkAbi(), + subsquidEvmAbiValidator.subsquidEvmAbi() + ) + .required(), }) );