From 0e3f0008e180b3daf0a6e61eaa962c2257c3dd7a Mon Sep 17 00:00:00 2001
From: vignesha22 <82584664+vignesha22@users.noreply.github.com>
Date: Mon, 4 Mar 2024 22:32:21 +0530
Subject: [PATCH] PRO-2207-Admin Frontend Changes (#67)
* added Admin Config changes
---
admin_frontend/.editorconfig | 12 +
admin_frontend/Dockerfile | 1 +
admin_frontend/config-overrides.js | 23 +
admin_frontend/package-lock.json | 885 +++++++++++++++++-
admin_frontend/package.json | 5 +-
admin_frontend/src/App.js | 27 +-
admin_frontend/src/components/ApiKeys.jsx | 628 +++++++------
admin_frontend/src/components/Dashboard.jsx | 712 ++++++++------
admin_frontend/src/components/Header.jsx | 62 +-
admin_frontend/src/components/NotFound.jsx | 1 -
.../src/components/ProtectedRoute.js | 24 +
admin_frontend/src/constants/common.js | 4 +-
admin_frontend/src/constants/constants.js | 8 +
.../src/constants/defaultNetworks.json | 170 ++++
admin_frontend/src/context/AuthContext.js | 86 ++
.../src/modals/AddERC20Paymaster.jsx | 257 +++++
.../src/modals/AddSupportedNetworksModal.jsx | 211 +++++
admin_frontend/src/modals/CoingeckoId.jsx | 216 +++++
.../src/modals/DeployedPaymasters.jsx | 217 +++++
.../src/modals/ViewERC20Paymaster.jsx | 91 ++
.../src/modals/ViewSupportedNetworksModal.jsx | 77 ++
backend/package.json | 2 +-
backend/src/constants/ErrorMessage.ts | 1 +
backend/src/migrations/001.default.sql | 2 +-
backend/src/plugins/config.ts | 2 +
backend/src/routes/admin.ts | 14 +
backend/src/server.ts | 8 +-
docker-compose.yml | 5 +-
frontend/Dockerfile | 1 +
frontend/demo.env | 1 +
frontend/package-lock.json | 4 +-
frontend/package.json | 2 +-
32 files changed, 3144 insertions(+), 615 deletions(-)
create mode 100644 admin_frontend/.editorconfig
create mode 100644 admin_frontend/config-overrides.js
create mode 100644 admin_frontend/src/components/ProtectedRoute.js
create mode 100644 admin_frontend/src/constants/constants.js
create mode 100644 admin_frontend/src/constants/defaultNetworks.json
create mode 100644 admin_frontend/src/context/AuthContext.js
create mode 100644 admin_frontend/src/modals/AddERC20Paymaster.jsx
create mode 100644 admin_frontend/src/modals/AddSupportedNetworksModal.jsx
create mode 100644 admin_frontend/src/modals/CoingeckoId.jsx
create mode 100644 admin_frontend/src/modals/DeployedPaymasters.jsx
create mode 100644 admin_frontend/src/modals/ViewERC20Paymaster.jsx
create mode 100644 admin_frontend/src/modals/ViewSupportedNetworksModal.jsx
create mode 100644 frontend/demo.env
diff --git a/admin_frontend/.editorconfig b/admin_frontend/.editorconfig
new file mode 100644
index 0000000..64d3d6a
--- /dev/null
+++ b/admin_frontend/.editorconfig
@@ -0,0 +1,12 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
\ No newline at end of file
diff --git a/admin_frontend/Dockerfile b/admin_frontend/Dockerfile
index 076083c..801c351 100644
--- a/admin_frontend/Dockerfile
+++ b/admin_frontend/Dockerfile
@@ -5,5 +5,6 @@ COPY src/ /admin_frontend/src
COPY package.json /admin_frontend/
COPY postcss.config.js /admin_frontend/
COPY tailwind.config.js /admin_frontend/
+COPY demo.env /frontend/.env
RUN npm install
CMD ["npm", "start"]
diff --git a/admin_frontend/config-overrides.js b/admin_frontend/config-overrides.js
new file mode 100644
index 0000000..ed199c9
--- /dev/null
+++ b/admin_frontend/config-overrides.js
@@ -0,0 +1,23 @@
+const webpack = require("webpack");
+
+module.exports = function override(config) {
+ const fallback = config.resolve.fallback || {};
+ Object.assign(fallback, {});
+ config.resolve.fallback = fallback;
+ config.plugins = (config.plugins || []).concat([
+ new webpack.ProvidePlugin({
+ process: "process/browser",
+ Buffer: ["buffer", "Buffer"],
+ }),
+ ]);
+ config.ignoreWarnings = [/Failed to parse source map/];
+ config.module.rules.push({
+ test: /\.(js|mjs|jsx)$/,
+ enforce: "pre",
+ loader: require.resolve("source-map-loader"),
+ resolve: {
+ fullySpecified: false,
+ },
+ });
+ return config;
+};
diff --git a/admin_frontend/package-lock.json b/admin_frontend/package-lock.json
index 1a3039e..736fa53 100644
--- a/admin_frontend/package-lock.json
+++ b/admin_frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "admin_frontend",
- "version": "1.0.0",
+ "version": "1.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "admin_frontend",
- "version": "1.0.0",
+ "version": "1.0.2",
"dependencies": {
"@emotion/react": "11.11.3",
"@emotion/styled": "11.11.0",
@@ -16,6 +16,8 @@
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "13.4.0",
"@testing-library/user-event": "13.5.0",
+ "buffer": "6.0.3",
+ "ethers": "5.7.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hot-toast": "2.4.1",
@@ -26,6 +28,7 @@
},
"devDependencies": {
"autoprefixer": "10.4.16",
+ "json-loader": "0.5.7",
"postcss": "8.4.33",
"tailwindcss": "3.4.1"
}
@@ -2546,6 +2549,697 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "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/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.1",
+ "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz",
+ "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==",
+ "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.2",
+ "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz",
+ "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==",
+ "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/ws": {
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "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.1",
+ "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz",
+ "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==",
+ "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/@floating-ui/core": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz",
@@ -5554,6 +6248,11 @@
"node": ">=8.9"
}
},
+ "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/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -6235,11 +6934,35 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
"integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw=="
},
+ "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/bfj": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz",
@@ -6276,6 +6999,11 @@
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
+ "node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
+ },
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@@ -6365,6 +7093,11 @@
"node": ">=8"
}
},
+ "node_modules/brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
+ },
"node_modules/browser-process-hrtime": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -6409,6 +7142,29 @@
"node-int64": "^0.4.0"
}
},
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -7732,6 +8488,25 @@
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.625.tgz",
"integrity": "sha512-DENMhh3MFgaPDoXWrVIqSPInQoLImywfCwrSmVl3cf9QHzoZSiutHwGaB/Ql3VkqcQV30rzgdM+BjKqBAJxo5Q=="
},
+ "node_modules/elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+ "dependencies": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/elliptic/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
+ },
"node_modules/emittery": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz",
@@ -8656,6 +9431,53 @@
"node": ">= 0.6"
}
},
+ "node_modules/ethers": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz",
+ "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==",
+ "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.1",
+ "@ethersproject/pbkdf2": "5.7.0",
+ "@ethersproject/properties": "5.7.0",
+ "@ethersproject/providers": "5.7.2",
+ "@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.1",
+ "@ethersproject/wordlists": "5.7.0"
+ }
+ },
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
@@ -9610,6 +10432,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
"node_modules/hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
@@ -9629,6 +10460,16 @@
"he": "bin/he"
}
},
+ "node_modules/hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
+ "dependencies": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@@ -9925,6 +10766,25 @@
"node": ">=4"
}
},
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/ignore": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
@@ -12576,6 +13436,11 @@
"jiti": "bin/jiti.js"
}
},
+ "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/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -12654,6 +13519,12 @@
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
},
+ "node_modules/json-loader": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
+ "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==",
+ "dev": true
+ },
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@@ -13148,6 +14019,11 @@
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
+ "node_modules/minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -16204,6 +17080,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",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
diff --git a/admin_frontend/package.json b/admin_frontend/package.json
index e4dadf5..c234130 100644
--- a/admin_frontend/package.json
+++ b/admin_frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "admin_frontend",
- "version": "1.0.0",
+ "version": "1.0.2",
"private": true,
"dependencies": {
"@emotion/react": "11.11.3",
@@ -11,6 +11,8 @@
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "13.4.0",
"@testing-library/user-event": "13.5.0",
+ "buffer": "6.0.3",
+ "ethers": "5.7.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hot-toast": "2.4.1",
@@ -45,6 +47,7 @@
},
"devDependencies": {
"autoprefixer": "10.4.16",
+ "json-loader": "0.5.7",
"postcss": "8.4.33",
"tailwindcss": "3.4.1"
}
diff --git a/admin_frontend/src/App.js b/admin_frontend/src/App.js
index 0f9752f..8d4c97e 100644
--- a/admin_frontend/src/App.js
+++ b/admin_frontend/src/App.js
@@ -10,6 +10,8 @@ import ApiKeysPage from "./components/ApiKeys";
// Css
import { ThemeProvider, createTheme } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
+import { AuthContextProvider } from "./context/AuthContext";
+import ProtectedRoute from "./components/ProtectedRoute";
const darkTheme = createTheme({
palette: {
@@ -23,18 +25,23 @@ function App() {
<>
-
-
-
- } />
- } />
- } />
-
-
-
+
+
+
+
+ } />
+
+
+ } />
+ } />
+
+
+
+
>
);
}
-export default App;
\ No newline at end of file
+export default App;
diff --git a/admin_frontend/src/components/ApiKeys.jsx b/admin_frontend/src/components/ApiKeys.jsx
index e5174d2..2bfd197 100644
--- a/admin_frontend/src/components/ApiKeys.jsx
+++ b/admin_frontend/src/components/ApiKeys.jsx
@@ -1,8 +1,10 @@
import { useEffect, useState } from "react";
-import AddCircleIcon from "@mui/icons-material/AddCircle";
-import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
+import { Buffer } from "buffer";
import toast from "react-hot-toast";
+
// components
+import AddCircleIcon from "@mui/icons-material/AddCircle";
+import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
import { TextField } from "@mui/material";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
@@ -15,311 +17,349 @@ import InputAdornment from "@mui/material/InputAdornment";
import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
import IconButton from "@mui/material/IconButton";
-import OutlinedInput from "@mui/material/OutlinedInput";
-import FormControl from "@mui/material/FormControl";
-import InputLabel from "@mui/material/InputLabel";
-import Checkbox from "@mui/material/Checkbox";
+import Button from "@mui/material/Button";
import Header from "./Header";
-// constants
-import { ENDPOINTS } from "../constants/common";
+//Modals
+import AddSupportedNetworksModal from "../modals/AddSupportedNetworksModal";
+import ViewSupportedNetworksModal from "../modals/ViewSupportedNetworksModal";
+import AddERC20PaymasterModal from "../modals/AddERC20Paymaster";
+import ViewERC20PaymasterModal from "../modals/ViewERC20Paymaster";
+
+//constants
+import defaultSupportedNetworks from "../constants/defaultNetworks";
+import { ENDPOINTS } from "../constants/constants";
const ApiKeysPage = () => {
- const [keys, setKeys] = useState([]);
- const [loading, setLoading] = useState(false);
- const [apiKey, setApiKey] = useState("");
- const [privateKey, setPrivateKey] = useState("");
- const [supportedNetworks, setSupportedNetworks] = useState("");
- const [customErc20Paymaster, setCustomErc20Paymaster] = useState("");
- const [txnMode, setTxnMode] = useState(0);
- const [noOfTxn, setNoOfTxn] = useState(10);
- const [showPassword, setShowPassword] = useState(false);
+ const [keys, setKeys] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [apiKey, setApiKey] = useState("");
+ const [privateKey, setPrivateKey] = useState("");
+ const [supportedNetworks, setSupportedNetworks] = useState(
+ defaultSupportedNetworks
+ );
+ const [customErc20Paymaster, setCustomErc20Paymaster] = useState({});
+ const [showPassword, setShowPassword] = useState(false);
+ const [open, setOpen] = useState(false);
+ const [customErc20Open, setCustomErc20Open] = useState(false);
+ const [viewModalOpen, setViewModalOpen] = useState(false);
+ const [viewErc20Open, setViewErc20Open] = useState(false);
+ const [edit, setEdit] = useState(false);
+ const [ERC20Tokens, setERC20Tokens] = useState([]);
+ const handleOpen = () => {
+ setSupportedNetworks(defaultSupportedNetworks);
+ setOpen(true);
+ };
+ const handleClose = () => {
+ setOpen(false);
+ };
+
+ const handleCustomErc20Open = (edit, data) => {
+ setEdit(edit);
+ setCustomErc20Paymaster(data);
+ setCustomErc20Open(true);
+ };
+ const handleCustomErc20Close = () => {
+ setCustomErc20Open(false);
+ };
+ const handleViewERC20Open = (data) => {
+ setERC20Tokens(data);
+ setViewErc20Open(true);
+ };
+
+ const handleViewERC20Close = () => {
+ setViewErc20Open(false);
+ };
+ const handleViewOpen = (networks) => {
+ setSupportedNetworks(networks);
+ setViewModalOpen(true);
+ };
- const handleClickShowPassword = () => setShowPassword(!showPassword);
+ const handleViewClose = () => {
+ setViewModalOpen(false);
+ };
- const handleMouseDownPassword = (event) => {
- event.preventDefault();
- };
+ const handleClickShowPassword = () => setShowPassword(!showPassword);
- const handleChange = (event) => {
- setTxnMode(event.target.checked ? 1 : 0);
- };
+ const handleMouseDownPassword = (event) => {
+ event.preventDefault();
+ };
- const fetchData = async () => {
- try {
- setLoading(true);
- const data = await (
- await fetch(`${process.env.REACT_APP_SERVER_URL}${ENDPOINTS['getKeys']}`, {
- method: "GET",
- })
- ).json();
- setKeys(data);
- setLoading(false);
- } catch (err) {
- if (err.message.includes("Falied to fetch"))
- toast.error("Failed to connect. Please make sure that the backend is running")
- else
- toast.error(err.message)
- }
- };
+ const fetchData = async () => {
+ try {
+ setLoading(true);
+ const data = await fetch(
+ `${process.env.REACT_APP_SERVER_URL}${ENDPOINTS["getKeys"]}`,
+ {
+ method: "GET",
+ }
+ );
+ const dataJson = await data.json();
+ dataJson.filter((element) => {
+ if (element.SUPPORTED_NETWORKS) {
+ const buffer = Buffer.from(element.SUPPORTED_NETWORKS, "base64");
+ const parsedSupportedNetowrks = JSON.parse(buffer.toString());
+ element.SUPPORTED_NETWORKS = parsedSupportedNetowrks;
+ }
+ if (element.ERC20_PAYMASTERS) {
+ const buffer = Buffer.from(element.ERC20_PAYMASTERS, "base64");
+ const parsedErc20Paymasters = JSON.parse(buffer.toString());
+ element.ERC20_PAYMASTERS = parsedErc20Paymasters;
+ }
+ return element;
+ });
+ setKeys(dataJson);
+ setLoading(false);
+ } catch (err) {
+ if (err?.message?.includes("Failed to fetch")) {
+ toast.error("There was a problem communicating with the server. Please try again, or contact Arka support team.");
+ } else toast.error(err?.message);
+ }
+ };
- useEffect(() => {
- fetchData();
- }, []);
+ useEffect(() => {
+ fetchData();
+ }, []);
- const handleSubmit = async () => {
- if (apiKey === "" || privateKey === "") {
- toast.error("Please input both API_KEY & PRIVATE_KEY field");
- return;
- }
- if (
- !/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*-_&])[A-Za-z\d@$!%*-_&]{8,}$/.test(
- apiKey
- )
- ) {
- toast.error(
- "Invalid Validation: API_KEY format. Please see the docs for more info"
- );
- return;
- }
- try {
- setLoading(true);
- const requestData = {
- API_KEY: apiKey,
- PRIVATE_KEY: privateKey,
- SUPPORTED_NETWORKS: supportedNetworks ?? "",
- ERC20_PAYMASTERS: customErc20Paymaster ?? "",
- TRANSACTION_LIMIT: txnMode,
- NO_OF_TRANSACTIONS_IN_A_MONTH: noOfTxn,
- INDEXER_ENDPOINT:
- process.env.REACT_APP_INDEXER_ENDPOINT ?? "http://localhost:3003",
- };
- const data = await fetch(`${process.env.REACT_APP_SERVER_URL}${ENDPOINTS['saveKey']}`, {
- method: "POST",
- body: JSON.stringify(requestData),
- });
- const dataJson = await data.json();
- if (!dataJson.error) {
- toast.success("Saved Successfully");
- setApiKey("");
- setPrivateKey("");
- fetchData();
- } else {
- setLoading(false);
- toast.error("Could not save");
- }
- } catch (err) {
- if (err.message.includes("Falied to fetch"))
- toast.error("Failed to connect. Please make sure that the backend is running")
- else
- toast.error(err.message)
- setLoading(false);
- }
- };
+ const handleSubmit = async () => {
+ if (apiKey === "" || privateKey === "") {
+ toast.error("Please input both API_KEY & PRIVATE_KEY field");
+ return;
+ }
+ try {
+ setLoading(true);
+ let base64Erc20 = "";
+ if (customErc20Paymaster != {})
+ base64Erc20 = Buffer.from(
+ JSON.stringify(customErc20Paymaster)
+ ).toString("base64");
+ const requestData = {
+ API_KEY: apiKey,
+ PRIVATE_KEY: privateKey,
+ SUPPORTED_NETWORKS:
+ Buffer.from(JSON.stringify(supportedNetworks)).toString("base64") ??
+ "",
+ ERC20_PAYMASTERS: base64Erc20 ?? "",
+ };
+ const data = await fetch(
+ `${process.env.REACT_APP_SERVER_URL}${ENDPOINTS["saveKey"]}`,
+ {
+ method: "POST",
+ body: JSON.stringify(requestData),
+ }
+ );
+ const dataJson = data.json();
+ if (!dataJson.error) {
+ toast.success("Saved Successfully");
+ setApiKey("");
+ setPrivateKey("");
+ fetchData();
+ } else {
+ setLoading(false);
+ toast.error(`${dataJson.message} Please try again or contant Arka support team`);
+ }
+ } catch (err) {
+ if (err?.message?.includes("Failed to fetch")) {
+ toast.error("There was a problem communicating with the server. Please try again, or contact Arka support team.");
+ } else toast.error(err?.message);
+ setLoading(false);
+ }
+ };
- const handleDelete = async (key) => {
- try {
- setLoading(true);
- const data = await (
- await fetch(`${process.env.REACT_APP_SERVER_URL}${ENDPOINTS['deleteKey']}`, {
- method: "POST",
- body: JSON.stringify({ API_KEY: key }),
- })
- ).json();
- if (!data.error) {
- toast.success("Deleted Successfully");
- fetchData();
- } else {
- setLoading(false);
- toast.error("Could not save");
- }
- } catch (err) {
- if (err.message.includes("Falied to fetch"))
- toast.error("Failed to connect. Please make sure that the backend is running")
- else
- toast.error(err.message)
- setLoading(false);
- }
- };
+ const handleDelete = async (key) => {
+ try {
+ setLoading(true);
+ const data = await fetch(
+ `${process.env.REACT_APP_SERVER_URL}${ENDPOINTS["deleteKey"]}`,
+ {
+ method: "POST",
+ body: JSON.stringify({ API_KEY: key }),
+ }
+ );
+ const dataJson = data.json();
+ if (!dataJson.error) {
+ toast.success("Deleted Successfully");
+ fetchData();
+ } else {
+ setLoading(false);
+ toast.error(`${dataJson.message} Please try again or contant Arka support team`);
+ }
+ } catch (err) {
+ if (err?.message?.includes("Failed to fetch")) {
+ toast.error("There was a problem communicating with the server. Please try again, or contact Arka support team.");
+ } else toast.error(err?.message);
+ setLoading(false);
+ }
+ };
- return (
- <>
-
-
-
-
-
- Wallet Address
- Api Key
- Private Key
- Supported Networks
- Custom ERC20 Paymasters
- Transaction Limit Mode
- No of Transactions Allowed
- Actions Available
-
-
-
-
-
-
-
-
- setApiKey(e.target.value)}
- value={apiKey}
- required
- multiline
- fullWidth
- />
-
-
-
-
- PRIVATE_KEY
-
-
-
- {showPassword ? : }
-
-
- }
- label="PRIVATE_KEY"
- multiline
- value={privateKey}
- onChange={(e) => setPrivateKey(e.target.value)}
- />
-
-
-
- setSupportedNetworks(e.target.value)}
- value={supportedNetworks}
- required
- multiline
- fullWidth
- />
-
-
- setCustomErc20Paymaster(e.target.value)}
- value={customErc20Paymaster}
- required
- multiline
- fullWidth
- />
-
-
-
-
-
- setNoOfTxn(e.target.value)}
- value={noOfTxn}
- required
- fullWidth
- />
-
-
- }
- variant="contained"
- onClick={() => {
- handleSubmit();
- }}
- >
- Add Row
-
-
-
- {keys.map((row) => (
-
- {row.WALLET_ADDRESS}
- {row.API_KEY}
-
-
-
{showPassword ? row.PRIVATE_KEY : "*****"}
-
-
-
- {showPassword ? : }
-
-
-
-
-
- {row.SUPPORTED_NETWORKS}
- {row.ERC20_PAYMASTERS}
-
- {row.TRANSACTION_LIMIT === 0 ? "OFF" : "ON"}
-
- {row.NO_OF_TRANSACTIONS_IN_A_MONTH}
-
- }
- variant="contained"
- onClick={() => {
- handleDelete(row.API_KEY);
- }}
- >
- Delete Row
-
-
-
- ))}
-
-
-
- >
- );
+ return (
+ <>
+
+
+
+
+
+ Wallet Address
+ Api Key
+ Private Key
+ Supported Networks
+ Custom ERC20 Paymasters
+ Actions Available
+
+
+
+
+
+
+
+
+ setApiKey(e.target.value)}
+ value={apiKey}
+ required
+ fullWidth
+ />
+
+
+ setPrivateKey(e.target.value)}
+ required
+ type={showPassword ? "text" : "password"}
+ InputProps={{
+ endAdornment: (
+
+
+ {showPassword ? : }
+
+
+ ),
+ }}
+ />
+
+
+ Edit
+
+
+ handleCustomErc20Open(true, {})}>
+ Edit
+
+
+
+ }
+ variant="contained"
+ onClick={() => {
+ handleSubmit();
+ }}
+ >
+ Add Row
+
+
+
+ {keys.map((row, index) => (
+
+ {row.WALLET_ADDRESS}
+ {row.API_KEY}
+
+
+
{showPassword ? row.PRIVATE_KEY : "*****"}
+
+
+
+ {showPassword ? : }
+
+
+
+
+
+
+ handleViewOpen(row.SUPPORTED_NETWORKS)}
+ >
+ View
+
+
+
+ handleViewERC20Open(row.ERC20_PAYMASTERS)}
+ >
+ View
+
+
+
+ }
+ variant="contained"
+ onClick={() => {
+ handleDelete(row.API_KEY);
+ }}
+ >
+ Delete Row
+
+
+
+ ))}
+
+
+
+
+
+
+
+ >
+ );
};
export default ApiKeysPage;
diff --git a/admin_frontend/src/components/Dashboard.jsx b/admin_frontend/src/components/Dashboard.jsx
index b513ff5..8a8d092 100644
--- a/admin_frontend/src/components/Dashboard.jsx
+++ b/admin_frontend/src/components/Dashboard.jsx
@@ -1,303 +1,439 @@
import { useEffect, useState } from "react";
+import { Buffer } from "buffer";
+
+// components
import { TextField } from "@mui/material";
import LoadingButton from "@mui/lab/LoadingButton";
+import { styled } from "styled-components";
import SaveIcon from "@mui/icons-material/Save";
import toast from "react-hot-toast";
import Header from "./Header";
+import Button from "@mui/material/Button";
+
+// context
+import { UserAuth } from "../context/AuthContext";
+
+// Modals
+import CoingeckoIdModal from "../modals/CoingeckoId";
+import DeployedPaymastersModal from "../modals/DeployedPaymasters";
+
+// contants
+import { ENDPOINTS } from "../constants/constants";
+
+const SettingsText = styled.span`
+ margin: '3px 0 4px 8px',
+ font-size: '24px',
+ padding-right: 5rem,
+ text-align: 'center',
+ color: '#cfcfcf'
+ `;
+
+const InfoTextStyle = {
+ fontSize: "small",
+ color: "grey",
+};
const Dashboard = () => {
- const defaultConfig = {
- COINGECKO_API_URL:
- "",
- COINGECKO_IDS: "",
- CRON_TIME: "",
- CUSTOM_CHAINLINK_DEPLOYED:
- "",
- DEPLOYED_ERC20_PAYMASTERS:
- "",
- PYTH_MAINNET_CHAIN_IDS: "",
- PYTH_MAINNET_URL: "",
- PYTH_TESTNET_CHAIN_IDS: "",
- PYTH_TESTNET_URL:
- "",
- id: 1,
- };
- const [config, setConfig] = useState(defaultConfig);
- const [edittedConfig, setEdittedConfig] = useState(defaultConfig);
- const [disableSave, setDisableSave] = useState(true);
- const [loading, setLoading] = useState(false);
+ const defaultConfig = {
+ COINGECKO_API_URL: "",
+ COINGECKO_IDS: "",
+ CRON_TIME: "",
+ CUSTOM_CHAINLINK_DEPLOYED: "",
+ DEPLOYED_ERC20_PAYMASTERS: "",
+ PYTH_MAINNET_CHAIN_IDS: "",
+ PYTH_MAINNET_URL: "",
+ PYTH_TESTNET_CHAIN_IDS: "",
+ PYTH_TESTNET_URL: "",
+ id: 1,
+ };
+ const [config, setConfig] = useState(defaultConfig);
+ const [edittedConfig, setEdittedConfig] = useState(defaultConfig);
+ const [disableSave, setDisableSave] = useState(true);
+ const [loading, setLoading] = useState(false);
+ const { user } = UserAuth();
+ const [signedIn, setSignedIn] = useState(false);
+ const [open, setOpen] = useState(false);
+ const [coingeckoIds, setCoingeckoIds] = useState({});
+ const [dpOpen, setDpOpen] = useState(false);
+ const [deployedPaymasters, setDeployedPaymasters] = useState({});
+ const [customChainlink, setCustomChainlink] = useState({});
+ const [customChainlinkOpen, setCustomChainlinkOpen] = useState(false);
+
+ const handleOpen = () => {
+ setOpen(true);
+ };
+ const handleClose = () => {
+ setOpen(false);
+ setDpOpen(false);
+ setCustomChainlinkOpen(false);
+ setDisableSave(false);
+ };
+
+ const handleDpOpen = () => {
+ setDpOpen(true);
+ };
+
+ const fetchData = async () => {
+ if (signedIn) {
+ try {
+ setLoading(true);
+ const data = await fetch(
+ `${process.env.REACT_APP_SERVER_URL}${ENDPOINTS["getConfig"]}`,
+ {
+ method: "GET",
+ }
+ );
+ const dataJson = data.json();
+ setConfig(dataJson);
+ setEdittedConfig(dataJson);
+ let buffer;
+ if (data.COINGECKO_IDS && data.COINGECKO_IDS !== "") {
+ buffer = Buffer.from(data.COINGECKO_IDS, "base64");
+ const coingeckoIds = JSON.parse(buffer.toString());
+ setCoingeckoIds(coingeckoIds);
+ }
+ if (
+ data.DEPLOYED_ERC20_PAYMASTERS &&
+ data.DEPLOYED_ERC20_PAYMASTERS !== ""
+ ) {
+ buffer = Buffer.from(data.DEPLOYED_ERC20_PAYMASTERS, "base64");
+ setDeployedPaymasters(JSON.parse(buffer.toString()));
+ }
+ if (
+ data.CUSTOM_CHAINLINK_DEPLOYED &&
+ data.CUSTOM_CHAINLINK_DEPLOYED !== ""
+ ) {
+ buffer = Buffer.from(data.CUSTOM_CHAINLINK_DEPLOYED, "base64");
+ setCustomChainlink(JSON.parse(buffer.toString()));
+ }
+ setDisableSave(true);
+ setLoading(false);
+ } catch (err) {
+ if (err?.message?.includes("Failed to fetch")) {
+ toast.error("Failed to access the server url");
+ } else toast.error(err?.message);
+ }
+ }
+ };
- const fetchData = async () => {
- try {
- setLoading(true);
- const data = await (
- await fetch("http://localhost:5050/getConfig", {
- method: "GET",
- })
- ).json();
- console.log("data: ", data);
- setConfig(data);
- setEdittedConfig(data);
- setDisableSave(true);
- setLoading(false);
- } catch (err) {
- toast.error(
- "Check Backend Service for more info"
- );
- }
- };
+ useEffect(() => {
+ setLoading(false);
+ if (user?.address) {
+ setSignedIn(true);
+ fetchData();
+ }
+ setLoading(false);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [user]);
- useEffect(() => {
- fetchData();
- }, []);
+ useEffect(() => {
+ fetchData();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [signedIn]);
- const handleSubmit = async (edittedConfig) => {
- try {
- setLoading(true);
- console.log("edittedConfig: ", edittedConfig);
- const data = await (
- await fetch("http://localhost:5050/saveConfig", {
- method: "POST",
- body: JSON.stringify(edittedConfig),
- })
- ).json();
- if (!data.error) {
- toast.success("Saved Successfully");
- fetchData();
- } else {
- toast.error("Could not save");
- }
- setLoading(false);
- } catch (err) {
- toast.error(
- "Check Backend Service for more info"
- );
- }
- };
+ const handleSubmit = async (edittedConfig) => {
+ if (signedIn) {
+ try {
+ setLoading(true);
+ edittedConfig.COINGECKO_IDS = Buffer.from(
+ JSON.stringify(coingeckoIds)
+ ).toString("base64");
+ edittedConfig.DEPLOYED_ERC20_PAYMASTERS = Buffer.from(
+ JSON.stringify(deployedPaymasters)
+ ).toString("base64");
+ edittedConfig.CUSTOM_CHAINLINK_DEPLOYED = Buffer.from(
+ JSON.stringify(customChainlink)
+ ).toString("base64");
+ const data = await fetch(
+ `${process.env.REACT_APP_SERVER_URL}${ENDPOINTS["saveConfig"]}`,
+ {
+ method: "POST",
+ body: JSON.stringify(edittedConfig),
+ }
+ );
+ const dataJson = data.json();
+ if (!dataJson.error) {
+ toast.success("Saved Successfully");
+ fetchData();
+ } else {
+ toast.error(`${dataJson.message} Please try again or contant Arka support team`);
+ }
+ setLoading(false);
+ } catch (err) {
+ if (err?.message?.includes("Failed to fetch")) {
+ toast.error("Failed to access the server url");
+ } else toast.error(err?.message);
+ }
+ } else {
+ toast.error("Please login to edit and save changes");
+ }
+ };
- return (
- <>
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- COINGECKO_IDS: e.target.value,
- });
- if (disableSave && e.target.value !== config.COINGECKO_IDS)
- setDisableSave(false);
- else if (!disableSave && e.target.value === config.COINGECKO_IDS)
- setDisableSave(true);
- }}
- value={edittedConfig.COINGECKO_IDS}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- COINGECKO_API_URL: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (
- !disableSave &&
- e.target.value === config.COINGECKO_API_URL
- )
- setDisableSave(true);
- }}
- value={edittedConfig.COINGECKO_API_URL}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- CRON_TIME: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (!disableSave && e.target.value === config.CRON_TIME)
- setDisableSave(true);
- }}
- value={edittedConfig.CRON_TIME}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- CUSTOM_CHAINLINK_DEPLOYED: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (
- !disableSave &&
- e.target.value === config.CUSTOM_CHAINLINK_DEPLOYED
- )
- setDisableSave(true);
- }}
- value={edittedConfig.CUSTOM_CHAINLINK_DEPLOYED}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- DEPLOYED_ERC20_PAYMASTERS: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (
- !disableSave &&
- e.target.value === config.DEPLOYED_ERC20_PAYMASTERS
- )
- setDisableSave(true);
- }}
- value={edittedConfig.DEPLOYED_ERC20_PAYMASTERS}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- PYTH_MAINNET_CHAIN_IDS: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (
- !disableSave &&
- e.target.value === config.PYTH_MAINNET_CHAIN_IDS
- )
- setDisableSave(true);
- }}
- value={edittedConfig.PYTH_MAINNET_CHAIN_IDS}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- PYTH_MAINNET_URL: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (!disableSave && e.target.value === config.PYTH_MAINNET_URL)
- setDisableSave(true);
- }}
- value={edittedConfig.PYTH_MAINNET_URL}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- PYTH_TESTNET_CHAIN_IDS: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (
- !disableSave &&
- e.target.value === config.PYTH_TESTNET_CHAIN_IDS
- )
- setDisableSave(true);
- }}
- value={edittedConfig.PYTH_TESTNET_CHAIN_IDS}
- required
- fullWidth
- multiline
- />
-
-
- {
- setEdittedConfig({
- ...edittedConfig,
- PYTH_TESTNET_URL: e.target.value,
- });
- if (disableSave) setDisableSave(false);
- else if (!disableSave && e.target.value === config.PYTH_TESTNET_URL)
- setDisableSave(true);
- }}
- value={edittedConfig.PYTH_TESTNET_URL}
- required
- fullWidth
- multiline
- />
-
- }
- variant="contained"
- onClick={() => {
- handleSubmit(edittedConfig);
- }}
- fullWidth
- >
- Save
-
- >
- );
+ return (
+ <>
+
+
+ COINGECKO_IDS
+
+ Edit
+
+
+
+
+ COINGECKO_IDS are for Deployed paymasters with custom chainlink
+ oracles. Can be left blank if you dont use custom erc20 paymasters
+ deployed
+
+
+
+ {
+ setEdittedConfig({
+ ...edittedConfig,
+ COINGECKO_API_URL: e.target.value,
+ });
+ if (disableSave) setDisableSave(false);
+ else if (
+ !disableSave &&
+ e.target.value === config.COINGECKO_API_URL
+ )
+ setDisableSave(true);
+ }}
+ value={edittedConfig.COINGECKO_API_URL}
+ required
+ fullWidth
+ multiline
+ />
+
+
+
+ COINGECKO_API_URL is the url for requesting price feeds for CRON-JOB
+
+
+
+ {
+ setEdittedConfig({
+ ...edittedConfig,
+ CRON_TIME: e.target.value,
+ });
+ if (disableSave) setDisableSave(false);
+ else if (!disableSave && e.target.value === config.CRON_TIME)
+ setDisableSave(true);
+ }}
+ value={edittedConfig.CRON_TIME}
+ required
+ fullWidth
+ />
+
+
+
+ CRON TIME requires exact cron time format as a string
+
+
+
+ Custom Chainlink for CRONJOB
+ setCustomChainlinkOpen(true)}
+ >
+ Edit
+
+
+
+
+ Custom deployments of erc20 paymaster supported by chainlink oracles
+ tokens to update the oracle price manually in the above specified cron
+ time
+
+
+
+ Deployed Paymasters for CRONJOB
+
+ Edit
+
+
+
+
+ Custom deployed erc20 paymasters to update the price feed on the
+ paymaster
+
+
+
+ {
+ setEdittedConfig({
+ ...edittedConfig,
+ PYTH_MAINNET_CHAIN_IDS: e.target.value,
+ });
+ if (disableSave) setDisableSave(false);
+ else if (
+ !disableSave &&
+ e.target.value === config.PYTH_MAINNET_CHAIN_IDS
+ )
+ setDisableSave(true);
+ }}
+ value={edittedConfig.PYTH_MAINNET_CHAIN_IDS}
+ required
+ fullWidth
+ multiline
+ />
+
+
+
+ PYTH mainnet chainIds. Can be left blank if you do not tend to use
+ PYTH oracle
+
+
+
+ {
+ setEdittedConfig({
+ ...edittedConfig,
+ PYTH_MAINNET_URL: e.target.value,
+ });
+ if (disableSave) setDisableSave(false);
+ else if (!disableSave && e.target.value === config.PYTH_MAINNET_URL)
+ setDisableSave(true);
+ }}
+ value={edittedConfig.PYTH_MAINNET_URL}
+ required
+ fullWidth
+ multiline
+ />
+
+
+
+ PYTH mainnet price feed URL. Can be left blank if you do not tend to
+ use PYTH oracle
+
+
+
+ {
+ setEdittedConfig({
+ ...edittedConfig,
+ PYTH_TESTNET_CHAIN_IDS: e.target.value,
+ });
+ if (disableSave) setDisableSave(false);
+ else if (
+ !disableSave &&
+ e.target.value === config.PYTH_TESTNET_CHAIN_IDS
+ )
+ setDisableSave(true);
+ }}
+ value={edittedConfig.PYTH_TESTNET_CHAIN_IDS}
+ required
+ fullWidth
+ multiline
+ />
+
+
+
+ PYTH testnet chainIds. Can be left blank if you do not tend to use
+ PYTH oracle
+
+
+
+ {
+ setEdittedConfig({
+ ...edittedConfig,
+ PYTH_TESTNET_URL: e.target.value,
+ });
+ if (disableSave) setDisableSave(false);
+ else if (!disableSave && e.target.value === config.PYTH_TESTNET_URL)
+ setDisableSave(true);
+ }}
+ value={edittedConfig.PYTH_TESTNET_URL}
+ required
+ fullWidth
+ multiline
+ />
+
+
+
+ PYTH testnet price feed URL. Can be left blank if you do not tend to
+ use PYTH oracle
+
+
+ }
+ variant="contained"
+ onClick={() => {
+ handleSubmit(edittedConfig);
+ }}
+ fullWidth
+ >
+ Save
+
+
+
+
+ >
+ );
};
export default Dashboard;
diff --git a/admin_frontend/src/components/Header.jsx b/admin_frontend/src/components/Header.jsx
index 5ce8be8..94c9ccf 100644
--- a/admin_frontend/src/components/Header.jsx
+++ b/admin_frontend/src/components/Header.jsx
@@ -1,23 +1,69 @@
-import React from "react";
+import { useEffect, useState } from "react";
import { styled } from "styled-components";
+import Link from "@mui/material/Link";
+import { useNavigate } from "react-router-dom";
+// context
+import { UserAuth } from "../context/AuthContext";
// assets
-import EtherspotLogo from '../assets/internal-48-etherspot@2x.png';
+import EtherspotLogo from "../assets/internal-48-etherspot@2x.png";
const LogoText = styled.span`
- margin: '3px 0 4px 8px',
- font-size: '24px',
- text-align: 'center',
+ margin: '3px 0 4px 8px',
+ font-size: '24px',
+ text-align: 'center',
color: '#cfcfcf'
- `
+ `;
const Header = ({ text }) => {
+ const { user, signIn } = UserAuth();
+ const navigate = useNavigate();
+ const [signedIn, setSignedIn] = useState(false);
+
+ useEffect(() => {
+ if (user?.address) setSignedIn(true);
+ }, [user]);
+
return (
-
+
-
+
{text}
+
+ {signedIn ? (
+ <>
+ navigate("/")}
+ >
+ Home
+
+ navigate("/apikeys")}
+ >
+ Api Keys
+
+ >
+ ) : (
+ <>>
+ )}
+ {signedIn ? (
+ {user?.address}
+ ) : (
+
+ Connect Wallet
+
+ )}
+
);
};
diff --git a/admin_frontend/src/components/NotFound.jsx b/admin_frontend/src/components/NotFound.jsx
index e591aca..6d2ce0f 100644
--- a/admin_frontend/src/components/NotFound.jsx
+++ b/admin_frontend/src/components/NotFound.jsx
@@ -1,5 +1,4 @@
const NotFound = () => {
-
return (
Page Not Found
diff --git a/admin_frontend/src/components/ProtectedRoute.js b/admin_frontend/src/components/ProtectedRoute.js
new file mode 100644
index 0000000..093ae04
--- /dev/null
+++ b/admin_frontend/src/components/ProtectedRoute.js
@@ -0,0 +1,24 @@
+import React, { useEffect } from 'react';
+import { useNavigate } from 'react-router-dom';
+import toast from "react-hot-toast";
+import { UserAuth } from '../context/AuthContext';
+
+const ProtectedRoute = ({ children }) => {
+ const { user } = UserAuth();
+ const navigate = useNavigate()
+
+ useEffect(() => {
+ if (!user) {
+ toast.error('Please connect to wallet to verify')
+ navigate('/')
+ }
+ }, [user, navigate])
+
+ return (
+ <>
+ {children}
+ >
+ )
+};
+
+export default ProtectedRoute;
diff --git a/admin_frontend/src/constants/common.js b/admin_frontend/src/constants/common.js
index b5ab577..94db3cd 100644
--- a/admin_frontend/src/constants/common.js
+++ b/admin_frontend/src/constants/common.js
@@ -1,5 +1,5 @@
export const ENDPOINTS = {
'getKeys': '/getKeys',
- 'saveKey' : '/saveKey',
+ 'saveKey': '/saveKey',
'deleteKey': '/deleteKey',
-}
\ No newline at end of file
+}
diff --git a/admin_frontend/src/constants/constants.js b/admin_frontend/src/constants/constants.js
new file mode 100644
index 0000000..0dacdcd
--- /dev/null
+++ b/admin_frontend/src/constants/constants.js
@@ -0,0 +1,8 @@
+export const ENDPOINTS = {
+ "getConfig": "/getConfig",
+ "saveConfig": "/saveConfig",
+ "getKeys": "/getKeys",
+ "saveKey": "/saveKey",
+ "deleteKey": "/deleteKey",
+ "adminLogin": "/adminLogin"
+}
diff --git a/admin_frontend/src/constants/defaultNetworks.json b/admin_frontend/src/constants/defaultNetworks.json
new file mode 100644
index 0000000..6adae86
--- /dev/null
+++ b/admin_frontend/src/constants/defaultNetworks.json
@@ -0,0 +1,170 @@
+[
+ {
+ "chainId": 1,
+ "bundler": "https://ethereum-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x7F690e93CecFca5A31E6e1dF50A33F6d3059048c"
+ }
+ },
+ {
+ "chainId": 5,
+ "bundler": "https://goerli-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xcaDBADcFeD5530A49762DFc9d1d712CcD6b09b25"
+ }
+ },
+ {
+ "chainId": 10,
+ "bundler": "https://optimism-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x805650ce74561C85baA44a8Bd13E19633Fd0F79d"
+ }
+ },
+ {
+ "chainId": 14,
+ "bundler": "https://flare-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x8A41594e5c6Fe492e437414c24eA6f401186b8d2"
+ }
+ },
+ {
+ "chainId": 56,
+ "bundler": "https://bnb-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xEA5ecE95D3A28f9faB161779d20128b449F9EC9C"
+ }
+ },
+ {
+ "chainId": 97,
+ "bundler": "https://bnbtestnet-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x153e26707DF3787183945B88121E4Eb188FDCAAA"
+ }
+ },
+ {
+ "chainId": 100,
+ "bundler": "https://gnosis-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x373aBcF1EA9e5802778E32870e7f72C8A6a90349"
+ }
+ },
+ {
+ "chainId": 114,
+ "bundler": "https://flaretestnet-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x2a18C360b525824B3e5656B5a705554f2a5036Be"
+ }
+ },
+ {
+ "chainId": 122,
+ "bundler": "https://fuse-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xEC2EE24E79C73DB13Dd9bC782856a5296626b7eb"
+ }
+ },
+ {
+ "chainId": 137,
+ "bundler": "https://polygon-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x26FeC24b0D467C9de105217B483931e8f944ff50"
+ }
+ },
+ {
+ "chainId": 420,
+ "bundler": "https://optimismgoerli-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x898c530A5fA37720DcF1843AeCC34b6B0cBaEB8a"
+ }
+ },
+ {
+ "chainId": 1001,
+ "bundler": "https://klaytntestnet-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x810FA4C915015b703db0878CF2B9344bEB254a40"
+ }
+ },
+ {
+ "chainId": 5000,
+ "bundler": "https://mantle-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x8A41594e5c6Fe492e437414c24eA6f401186b8d2"
+ }
+ },
+ {
+ "chainId": 5001,
+ "bundler": "https://mantletestnet-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xb56eC212C60C47fb7385f13b7247886FFa5E9D5C"
+ }
+ },
+ {
+ "chainId": 8217,
+ "bundler": "https://klaytn-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x4ebd86AAF89151b5303DB072e0205C668e31E5E7"
+ }
+ },
+ {
+ "chainId": 8453,
+ "bundler": "https://base-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x810FA4C915015b703db0878CF2B9344bEB254a40"
+ }
+ },
+ {
+ "chainId": 42161,
+ "bundler": "https://arbitrum-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xEC2EE24E79C73DB13Dd9bC782856a5296626b7eb"
+ }
+ },
+ {
+ "chainId": 43114,
+ "bundler": "https://avalanche-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x527569794781671319f20374A050BDbef4181aB3"
+ }
+ },
+ {
+ "chainId": 59144,
+ "bundler": "https://linea-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xB3AD9B9B06c6016f81404ee8FcCD0526F018Cf0C"
+ }
+ },
+ {
+ "chainId": 80001,
+ "bundler": "https://mumbai-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x8350355c08aDAC387b443782124A30A8942BeC2e"
+ }
+ },
+ {
+ "chainId": 84531,
+ "bundler": "https://basegoerli-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x898c530A5fA37720DcF1843AeCC34b6B0cBaEB8a"
+ }
+ },
+ {
+ "chainId": 421613,
+ "bundler": "https://arbitrumgoerli-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0x898c530A5fA37720DcF1843AeCC34b6B0cBaEB8a"
+ }
+ },
+ {
+ "chainId": 534351,
+ "bundler": "https://scrollsepolia-bundler.etherspot.io/",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xe893A26DD53b325BffAacDfA224692EfF4C448c4"
+ }
+ },
+ {
+ "chainId": 11155111,
+ "bundler": "https://sepolia-bundler.etherspot.io",
+ "contracts": {
+ "etherspotPaymasterAddress": "0xcaDBADcFeD5530A49762DFc9d1d712CcD6b09b25"
+ }
+ }
+]
diff --git a/admin_frontend/src/context/AuthContext.js b/admin_frontend/src/context/AuthContext.js
new file mode 100644
index 0000000..3d893ce
--- /dev/null
+++ b/admin_frontend/src/context/AuthContext.js
@@ -0,0 +1,86 @@
+import { createContext, useContext, useState } from 'react';
+import toast from "react-hot-toast";
+import { ENDPOINTS } from '../constants/constants';
+
+const UserContext = createContext();
+
+export const AuthContextProvider = ({ children }) => {
+ const [user, setUser] = useState();
+ const [isSigningIn, setIsSigningIn] = useState(false);
+
+ const initializeProvider = async () => {
+ const res = await window.ethereum
+ .request({ method: "eth_requestAccounts" });
+ return res[0];
+ }
+
+ const accountChangeHandler = async (accounts) => {
+ try {
+ const data = await fetch(`${process.env.REACT_APP_SERVER_URL}${ENDPOINTS['adminLogin']}`, {
+ method: "POST",
+ body: JSON.stringify({ WALLET_ADDRESS: accounts[0] }),
+ });
+ const dataJson = await data.json();
+ if (!dataJson.error) {
+ toast.success("Logged In Successfully");
+ setUser({ address: accounts[0] });
+ } else {
+ toast.error("Failed to authenticate with this wallet. Please make sure the address is associated with admin address given and try again");
+ }
+ } catch (error) {
+ if (error?.message?.includes('Failed to fetch')) {
+ toast.error('Failed to access the server url');
+ } else {
+ toast.error(error?.message);
+ }
+ setUser(null);
+ }
+ };
+
+ const signIn = async () => {
+ try {
+ if (!window.ethereum) {
+ toast.error('Cannot determine any injected wallet')
+ return null;
+ }
+ setIsSigningIn(true);
+ const address = await initializeProvider();
+ const data = await fetch(`${process.env.REACT_APP_SERVER_URL}${ENDPOINTS['adminLogin']}`, {
+ method: "POST",
+ body: JSON.stringify({ WALLET_ADDRESS: address }),
+ });
+ const dataJson = await data.json();
+ if (!dataJson.error) {
+ toast.success("Logged In Successfully");
+ setUser({ address });
+ setIsSigningIn(false);
+ return { address };
+ } else {
+ toast.error("Failed to authenticate with this wallet. Please make sure the address is associated with admin address given and try again");
+ setIsSigningIn(false);
+ return null;
+ }
+ } catch (error) {
+ if (error?.message?.includes('Failed to fetch')) {
+ toast.error('Failed to access the server url')
+ } else {
+ toast.error(error?.message);
+ }
+ setIsSigningIn(false);
+ setUser(null);
+ return null;
+ }
+ };
+
+ window.ethereum.on('accountsChanged', accountChangeHandler)
+
+ const logout = async () => {
+ setUser(null)
+ };
+
+ return
{children} ;
+};
+
+export const UserAuth = () => {
+ return useContext(UserContext);
+};
diff --git a/admin_frontend/src/modals/AddERC20Paymaster.jsx b/admin_frontend/src/modals/AddERC20Paymaster.jsx
new file mode 100644
index 0000000..0fb83b5
--- /dev/null
+++ b/admin_frontend/src/modals/AddERC20Paymaster.jsx
@@ -0,0 +1,257 @@
+import { useEffect, useState } from "react";
+import { utils } from "ethers";
+import toast from "react-hot-toast";
+
+// components
+import AddCircleIcon from "@mui/icons-material/AddCircle";
+import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
+import { TextField } from "@mui/material";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Box from "@mui/material/Box";
+import Button from "@mui/material/Button";
+import Typography from "@mui/material/Typography";
+import Modal from "@mui/material/Modal";
+
+const style = {
+ width: "100%",
+ bgcolor: "background.paper",
+ border: "2px solid #000",
+ boxShadow: 24,
+ p: 2,
+ flexDirection: "column",
+ overflowX: "scroll",
+};
+
+const defaultERC20Row = {
+ chainId: 0,
+ token: "",
+ erc20PaymasterAddress: "",
+};
+
+const AddERC20PaymasterModal = ({
+ supportedNetworks,
+ setSupportedNetworks,
+ open,
+ handleClose,
+ Edit,
+}) => {
+ const [ERC20Row, setERC20Row] = useState(defaultERC20Row);
+ const [tokens, setTokens] = useState([]);
+
+ const addRow = () => {
+ if (
+ ERC20Row.erc20PaymasterAddress === "" ||
+ ERC20Row.token === "" ||
+ ERC20Row.chainId === 0
+ ) {
+ toast.error("Please fill all textfields");
+ return;
+ }
+ if (!utils.isAddress(ERC20Row.erc20PaymasterAddress)) {
+ toast.error("Please input a valid address");
+ return;
+ }
+ if (
+ supportedNetworks == {} ||
+ !supportedNetworks[ERC20Row.chainId] ||
+ !supportedNetworks[ERC20Row.chainId][ERC20Row.token]
+ ) {
+ supportedNetworks[ERC20Row.chainId] = {
+ ...supportedNetworks[ERC20Row.chainId],
+ [ERC20Row.token]: ERC20Row.erc20PaymasterAddress,
+ };
+ setSupportedNetworks(supportedNetworks);
+ setERC20Row(defaultERC20Row);
+ Object.keys(supportedNetworks).map((key) => {
+ Object.keys(supportedNetworks[key]).map((sym) => {
+ console.log(
+ tokens.find(
+ (element) => element.chainId == key && element.token == sym
+ )
+ );
+ if (
+ !tokens.find(
+ (element) => element.chainId == key && element.token == sym
+ )
+ ) {
+ tokens.push({
+ chainId: key,
+ token: sym,
+ address: supportedNetworks[key][sym],
+ });
+ setTokens(tokens);
+ }
+ return;
+ });
+ return;
+ });
+ } else {
+ toast.error("Chain ID and Token already present");
+ }
+ };
+
+ const deleteRow = (element) => {
+ delete supportedNetworks[element.chainId][element.token];
+ if (Object.keys(supportedNetworks[element.chainId]).length === 0)
+ delete supportedNetworks[element.chainId];
+ setSupportedNetworks(supportedNetworks);
+ setTokens(
+ tokens.filter(
+ (token) =>
+ element.chainId !== token.chainId && element.token !== token.token
+ )
+ );
+ setERC20Row(defaultERC20Row);
+ };
+
+ useEffect(() => {
+ Object.keys(supportedNetworks).map((key) => {
+ Object.keys(supportedNetworks[key]).map((sym) => {
+ console.log(
+ tokens.find(
+ (element) => element.chainId == key && element.token == sym
+ )
+ );
+ if (
+ !tokens.find(
+ (element) => element.chainId == key && element.token == sym
+ )
+ ) {
+ tokens.push({
+ chainId: key,
+ token: sym,
+ address: supportedNetworks[key][sym],
+ });
+ setTokens(tokens);
+ }
+ });
+ });
+ });
+
+ return (
+
+
+
+
+ ERC20 Paymasters
+
+ Save
+
+
+
+
+
+ Chain ID
+ Token
+ ERC20 Paymaster Address
+ Actions Available
+
+
+
+
+
+ {
+ if (!isNaN(e.target.value))
+ setERC20Row({
+ ...ERC20Row,
+ chainId: Number(e.target.value),
+ });
+ }}
+ value={ERC20Row.chainId}
+ required
+ fullWidth
+ />
+
+
+
+ setERC20Row({
+ ...ERC20Row,
+ token: e.target.value,
+ })
+ }
+ value={ERC20Row.token}
+ required
+ fullWidth
+ />
+
+
+
+ setERC20Row({
+ ...ERC20Row,
+ erc20PaymasterAddress: e.target.value,
+ })
+ }
+ value={ERC20Row.erc20PaymasterAddress}
+ required
+ fullWidth
+ />
+
+
+ }
+ variant="contained"
+ onClick={addRow}
+ >
+ Add Row
+
+
+
+
+ {tokens.map((element, index) => {
+ return (
+
+ {element.chainId}
+ {element.token}
+ {element.address}
+
+ }
+ variant="contained"
+ onClick={() => deleteRow(element)}
+ >
+ Delete Row
+
+
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default AddERC20PaymasterModal;
diff --git a/admin_frontend/src/modals/AddSupportedNetworksModal.jsx b/admin_frontend/src/modals/AddSupportedNetworksModal.jsx
new file mode 100644
index 0000000..2676159
--- /dev/null
+++ b/admin_frontend/src/modals/AddSupportedNetworksModal.jsx
@@ -0,0 +1,211 @@
+import { useState } from "react";
+import { utils } from "ethers";
+import toast from "react-hot-toast";
+
+// components
+import AddCircleIcon from "@mui/icons-material/AddCircle";
+import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
+import { TextField } from "@mui/material";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Box from "@mui/material/Box";
+import Button from "@mui/material/Button";
+import Typography from "@mui/material/Typography";
+import Modal from "@mui/material/Modal";
+
+const style = {
+ width: "100%",
+ bgcolor: "background.paper",
+ border: "2px solid #000",
+ boxShadow: 24,
+ p: 2,
+ flexDirection: "column",
+ overflowX: "scroll",
+};
+
+const defaultSupportedNetworksRow = {
+ chainId: 0,
+ bundler: "",
+ contracts: {
+ etherspotPaymasterAddress: "",
+ },
+};
+
+const AddSupportedNetworksModal = ({
+ supportedNetworks,
+ setSupportedNetworks,
+ open,
+ handleClose,
+}) => {
+ const [supportedNetworkRow, setSupportedNetworkRow] = useState(
+ defaultSupportedNetworksRow
+ );
+
+ const addRow = () => {
+ if (
+ supportedNetworkRow.bundler === "" ||
+ supportedNetworkRow.contracts.etherspotPaymasterAddress === "" ||
+ supportedNetworkRow.chainId === 0
+ ) {
+ toast.error("Please fill all textfields");
+ return;
+ }
+ if (
+ !utils.isAddress(supportedNetworkRow.contracts.etherspotPaymasterAddress)
+ ) {
+ toast.error("Please input a valid address");
+ return;
+ }
+ if (
+ !supportedNetworks.find(
+ (network) => network.chainId === supportedNetworkRow.chainId
+ )
+ ) {
+ supportedNetworks.push(supportedNetworkRow);
+ setSupportedNetworks(
+ supportedNetworks.sort((a, b) => a.chainId - b.chainId)
+ );
+ setSupportedNetworkRow(defaultSupportedNetworksRow);
+ } else {
+ toast.error("Chain ID already present");
+ }
+ };
+
+ const deleteRow = (chainId) => {
+ setSupportedNetworks(
+ supportedNetworks.filter((element) => element.chainId != chainId)
+ );
+ setSupportedNetworkRow(defaultSupportedNetworksRow);
+ };
+
+ return (
+
+
+
+
+ Supported Networks
+
+ Close
+
+
+
+
+
+ Chain ID
+ Bundler URL
+ Paymaster Address
+ Actions Available
+
+
+
+
+
+ {
+ if (!isNaN(e.target.value))
+ setSupportedNetworkRow({
+ ...supportedNetworkRow,
+ chainId: Number(e.target.value),
+ });
+ }}
+ value={supportedNetworkRow.chainId}
+ required
+ fullWidth
+ />
+
+
+
+ setSupportedNetworkRow({
+ ...supportedNetworkRow,
+ bundler: e.target.value,
+ })
+ }
+ value={supportedNetworkRow.bundler}
+ required
+ fullWidth
+ />
+
+
+
+ setSupportedNetworkRow({
+ ...supportedNetworkRow,
+ contracts: {
+ etherspotPaymasterAddress: e.target.value,
+ },
+ })
+ }
+ value={
+ supportedNetworkRow.contracts.etherspotPaymasterAddress
+ }
+ required
+ fullWidth
+ />
+
+
+ }
+ variant="contained"
+ onClick={() => addRow()}
+ >
+ Add Row
+
+
+
+ {supportedNetworks.map((network, index) => {
+ return (
+
+ {network.chainId}
+ {network.bundler}
+
+ {network.contracts.etherspotPaymasterAddress}
+
+
+ }
+ variant="contained"
+ onClick={() => deleteRow(network.chainId)}
+ >
+ Delete Row
+
+
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default AddSupportedNetworksModal;
diff --git a/admin_frontend/src/modals/CoingeckoId.jsx b/admin_frontend/src/modals/CoingeckoId.jsx
new file mode 100644
index 0000000..fb07c0d
--- /dev/null
+++ b/admin_frontend/src/modals/CoingeckoId.jsx
@@ -0,0 +1,216 @@
+import { useEffect, useState } from "react";
+import toast from "react-hot-toast";
+
+// components
+import AddCircleIcon from "@mui/icons-material/AddCircle";
+import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
+import { TextField } from "@mui/material";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Box from "@mui/material/Box";
+import Button from "@mui/material/Button";
+import Typography from "@mui/material/Typography";
+import Modal from "@mui/material/Modal";
+
+const style = {
+ width: "100%",
+ bgcolor: "background.paper",
+ border: "2px solid #000",
+ boxShadow: 24,
+ p: 2,
+ flexDirection: "column",
+ overflowX: "scroll",
+};
+
+const defaultSupportedNetworksRow = {
+ chainId: "",
+ coingeckoId: "",
+};
+
+const CoingeckoIdModal = ({
+ supportedNetworks,
+ setSupportedNetworks,
+ open,
+ handleClose,
+}) => {
+ const [supportedNetworkRow, setSupportedNetworkRow] = useState(
+ defaultSupportedNetworksRow
+ );
+ const [ids, setIds] = useState([]);
+
+ const addRow = () => {
+ const tempId = ids;
+ if (
+ supportedNetworkRow.coingeckoId === "" ||
+ supportedNetworkRow.chainId === "" ||
+ supportedNetworkRow.chainId === 0
+ ) {
+ toast.error("Please fill all textfields");
+ return;
+ }
+ if (
+ !ids.find(
+ (network) =>
+ network.chainId === supportedNetworkRow.chainId &&
+ network.coingeckoId === supportedNetworkRow.coingeckoId
+ )
+ ) {
+ if (!supportedNetworks[supportedNetworkRow.chainId.toString()])
+ supportedNetworks[supportedNetworkRow.chainId.toString()] = [
+ supportedNetworkRow.coingeckoId,
+ ];
+ else {
+ supportedNetworks[supportedNetworkRow.chainId.toString()].push(
+ supportedNetworkRow.coingeckoId
+ );
+ }
+ tempId.push({
+ chainId: supportedNetworkRow.chainId,
+ coingeckoId: supportedNetworkRow.coingeckoId,
+ });
+ setIds(tempId);
+ setSupportedNetworks(supportedNetworks);
+ setSupportedNetworkRow(defaultSupportedNetworksRow);
+ } else {
+ toast.error("Chain ID already present");
+ }
+ };
+
+ const deleteRow = (network) => {
+ setIds(
+ ids.filter(
+ (element) =>
+ element.chainId !== network.chainId &&
+ element.coingeckoId !== network.coingeckoId
+ )
+ );
+ setSupportedNetworks(
+ supportedNetworks[network.chainId.toString()].filter(
+ (element) => element !== network.coingeckoId
+ )
+ );
+ setSupportedNetworkRow(defaultSupportedNetworksRow);
+ };
+
+ useEffect(() => {
+ const coingeckoIds = [];
+ for (const chain in supportedNetworks) {
+ for (const id of supportedNetworks[chain]) {
+ coingeckoIds.push({
+ chainId: chain,
+ coingeckoId: id,
+ });
+ }
+ }
+ setIds(coingeckoIds);
+ console.log(coingeckoIds);
+ }, [supportedNetworks]);
+
+ return (
+
+
+
+
+ CoinGecko IDs
+
+ Save
+
+
+
+
+
+ Chain ID
+ Coingecko ID
+ Actions Available
+
+
+
+
+
+ {
+ if (!isNaN(e.target.value))
+ setSupportedNetworkRow({
+ ...supportedNetworkRow,
+ chainId: Number(e.target.value),
+ });
+ }}
+ value={supportedNetworkRow.chainId}
+ required
+ fullWidth
+ />
+
+
+ {
+ setSupportedNetworkRow({
+ ...supportedNetworkRow,
+ coingeckoId: e.target.value,
+ });
+ }}
+ value={supportedNetworkRow.coingeckoId}
+ required
+ fullWidth
+ />
+
+
+ }
+ variant="contained"
+ onClick={addRow}
+ >
+ Add Row
+
+
+
+ {ids.map((network, index) => {
+ return (
+
+ {network.chainId}
+ {network.coingeckoId}
+
+ }
+ variant="contained"
+ onClick={() => {
+ deleteRow(network);
+ }}
+ >
+ Delete Row
+
+
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default CoingeckoIdModal;
diff --git a/admin_frontend/src/modals/DeployedPaymasters.jsx b/admin_frontend/src/modals/DeployedPaymasters.jsx
new file mode 100644
index 0000000..ccb4242
--- /dev/null
+++ b/admin_frontend/src/modals/DeployedPaymasters.jsx
@@ -0,0 +1,217 @@
+import { useEffect, useState } from "react";
+import { utils } from "ethers";
+import toast from "react-hot-toast";
+
+// components
+import AddCircleIcon from "@mui/icons-material/AddCircle";
+import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
+import { TextField } from "@mui/material";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Box from "@mui/material/Box";
+import Button from "@mui/material/Button";
+import Typography from "@mui/material/Typography";
+import Modal from "@mui/material/Modal";
+
+const style = {
+ width: "100%",
+ bgcolor: "background.paper",
+ border: "2px solid #000",
+ boxShadow: 24,
+ p: 2,
+ flexDirection: "column",
+ overflowX: "scroll",
+};
+
+const defaultSupportedNetworksRow = {
+ chainId: "",
+ address: "",
+};
+
+const DeployedPaymastersModal = ({
+ supportedNetworks,
+ setSupportedNetworks,
+ open,
+ handleClose,
+ title,
+}) => {
+ const [supportedNetworkRow, setSupportedNetworkRow] = useState(
+ defaultSupportedNetworksRow
+ );
+ const [addresses, setAddresses] = useState([]);
+
+ const addRow = () => {
+ const tempId = addresses;
+ if (
+ supportedNetworkRow.address === "" ||
+ supportedNetworkRow.chainId === "" ||
+ supportedNetworkRow.chainId === 0
+ ) {
+ toast.error("Please fill all textfields");
+ return;
+ }
+ if (!utils.isAddress(supportedNetworkRow.address)) {
+ toast.error("Please input a valid address");
+ return;
+ }
+ if (
+ !addresses.find(
+ (network) =>
+ network.chainId === supportedNetworkRow.chainId &&
+ network.address === supportedNetworkRow.address
+ )
+ ) {
+ const chain = supportedNetworkRow.chainId.toString();
+ if (!supportedNetworks[chain]) {
+ supportedNetworks[chain] = [];
+ }
+ supportedNetworks[chain].push(supportedNetworkRow.address);
+ tempId.push({
+ chainId: supportedNetworkRow.chainId,
+ address: supportedNetworkRow.address,
+ });
+ setAddresses(tempId);
+ setSupportedNetworks(supportedNetworks);
+ setSupportedNetworkRow(defaultSupportedNetworksRow);
+ } else {
+ toast.error("Chain ID already present");
+ }
+ };
+
+ const deleteRow = (network) => {
+ const tempAddr = addresses.filter(
+ (element) =>
+ element.chainId.toString() !== network.chainId.toString() &&
+ element.address !== network.address
+ );
+ setAddresses(tempAddr);
+ supportedNetworks[network.chainId] = supportedNetworks[
+ network.chainId
+ ].filter((element) => element !== network.address.toString());
+ setSupportedNetworks(supportedNetworks);
+ setSupportedNetworkRow(defaultSupportedNetworksRow);
+ };
+
+ useEffect(() => {
+ const addr = [];
+ for (const chain in supportedNetworks) {
+ for (const address of supportedNetworks[chain]) {
+ addr.push({
+ chainId: chain,
+ address,
+ });
+ }
+ }
+ console.log(addr);
+ setAddresses(addr);
+ console.log(supportedNetworks);
+ }, [supportedNetworks]);
+
+ return (
+
+
+
+
+ {title}
+
+ Save
+
+
+
+
+
+ Chain ID
+ Address
+ Actions Available
+
+
+
+
+
+ {
+ if (!isNaN(e.target.value))
+ setSupportedNetworkRow({
+ ...supportedNetworkRow,
+ chainId: Number(e.target.value),
+ });
+ }}
+ value={supportedNetworkRow.chainId}
+ required
+ multiline
+ fullWidth
+ />
+
+
+ {
+ setSupportedNetworkRow({
+ ...supportedNetworkRow,
+ address: e.target.value,
+ });
+ }}
+ value={supportedNetworkRow.address}
+ required
+ multiline
+ fullWidth
+ />
+
+
+ }
+ variant="contained"
+ onClick={addRow}
+ >
+ Add Row
+
+
+
+ {addresses.map((network, index) => {
+ return (
+
+ {network.chainId}
+ {network.address}
+
+ }
+ variant="contained"
+ onClick={() => deleteRow(network)}
+ >
+ Delete Row
+
+
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default DeployedPaymastersModal;
diff --git a/admin_frontend/src/modals/ViewERC20Paymaster.jsx b/admin_frontend/src/modals/ViewERC20Paymaster.jsx
new file mode 100644
index 0000000..47bb7dc
--- /dev/null
+++ b/admin_frontend/src/modals/ViewERC20Paymaster.jsx
@@ -0,0 +1,91 @@
+import { useEffect, useState } from "react";
+
+// components
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Box from "@mui/material/Box";
+import Button from "@mui/material/Button";
+import Typography from "@mui/material/Typography";
+import Modal from "@mui/material/Modal";
+
+const style = {
+ width: "100%",
+ bgcolor: "background.paper",
+ border: "2px solid #000",
+ boxShadow: 24,
+ p: 2,
+ flexDirection: "column",
+ overflowX: "scroll",
+};
+
+const ViewERC20PaymasterModal = ({ supportedNetworks, open, handleClose }) => {
+ const [tokens, setTokens] = useState([]);
+
+ useEffect(() => {
+ const tempTokens = [];
+ for (const key in supportedNetworks) {
+ for (const sym in supportedNetworks[key]) {
+ tempTokens.push({
+ chainId: key,
+ token: sym,
+ address: supportedNetworks[key][sym],
+ });
+ }
+ }
+ setTokens(tempTokens);
+ }, [supportedNetworks]);
+
+ return (
+
+
+
+
+ ERC20 Paymaster Address
+
+ Close
+
+
+
+
+
+ Chain ID
+ Token
+ ERC20 Paymaster Address
+
+
+
+ {tokens.map((element) => {
+ return (
+
+ {element.chainId}
+ {element.token}
+ {element.address}
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default ViewERC20PaymasterModal;
diff --git a/admin_frontend/src/modals/ViewSupportedNetworksModal.jsx b/admin_frontend/src/modals/ViewSupportedNetworksModal.jsx
new file mode 100644
index 0000000..73b2657
--- /dev/null
+++ b/admin_frontend/src/modals/ViewSupportedNetworksModal.jsx
@@ -0,0 +1,77 @@
+// components
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Box from "@mui/material/Box";
+import Button from "@mui/material/Button";
+import Typography from "@mui/material/Typography";
+import Modal from "@mui/material/Modal";
+
+const style = {
+ width: "100%",
+ bgcolor: "background.paper",
+ border: "2px solid #000",
+ boxShadow: 24,
+ p: 2,
+ flexDirection: "column",
+ overflowX: "scroll",
+};
+
+const ViewSupportedNetworksModal = ({
+ supportedNetworks,
+ open,
+ handleClose,
+}) => {
+ return (
+
+
+
+
+ Supported Networks
+
+ Close
+
+
+
+
+
+ Chain ID
+ Bundler URL
+ Paymaster Address
+
+
+
+ {supportedNetworks.map((network) => {
+ return (
+
+ {network.chainId}
+ {network.bundler}
+
+ {network.contracts.etherspotPaymasterAddress}
+
+
+ );
+ })}
+
+
+
+
+
+ );
+};
+
+export default ViewSupportedNetworksModal;
diff --git a/backend/package.json b/backend/package.json
index 262d3f5..b48d40d 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -1,6 +1,6 @@
{
"name": "arka",
- "version": "1.1.0",
+ "version": "1.1.2",
"description": "ARKA - (Albanian for Cashier's case) is the first open source Paymaster as a service software",
"type": "module",
"directories": {
diff --git a/backend/src/constants/ErrorMessage.ts b/backend/src/constants/ErrorMessage.ts
index 750e81c..06e4616 100644
--- a/backend/src/constants/ErrorMessage.ts
+++ b/backend/src/constants/ErrorMessage.ts
@@ -8,6 +8,7 @@ export default {
INVALID_MODE: 'Invalid mode selected',
DUPLICATE_RECORD: 'Duplicate record found',
QUOTA_EXCEEDED: 'Quota exceeded for this month',
+ INVALID_USER: 'Unauthorised User',
RECORD_NOT_FOUND: 'Api Key provided not found',
API_KEY_VALIDATION_FAILED: 'Api Key is not in the right format as described in readme file',
}
diff --git a/backend/src/migrations/001.default.sql b/backend/src/migrations/001.default.sql
index a0e329e..b808ab9 100644
--- a/backend/src/migrations/001.default.sql
+++ b/backend/src/migrations/001.default.sql
@@ -32,7 +32,7 @@ INSERT INTO config (
"5000",
"0 0 * * *",
"ewogICAgIjgwMDAxIjogWyIweGMzM2MzOEE3QkZFQmJCOTk3ZEQ0MDExQ0RkQWY0ZWJEMWU4ODAzQzAiXQp9",
- "panther",
+ "eyI4MDAwMSI6WyJwYW50aGVyIl19",
"https://api.coingecko.com/api/v3/simple/price?vs_currencies=usd&precision=8&ids=");
--------------------------------------------------------------------------------
diff --git a/backend/src/plugins/config.ts b/backend/src/plugins/config.ts
index 3a8d866..2cac84e 100644
--- a/backend/src/plugins/config.ts
+++ b/backend/src/plugins/config.ts
@@ -17,6 +17,7 @@ const ConfigSchema = Type.Strict(
API_HOST: Type.String(),
API_PORT: Type.String(),
SUPPORTED_NETWORKS: Type.String() || undefined,
+ ADMIN_WALLET_ADDRESS: Type.String() || undefined,
})
);
@@ -45,6 +46,7 @@ const configPlugin: FastifyPluginAsync = async (server) => {
API_PORT: process.env.API_PORT ?? '',
API_HOST: process.env.API_HOST ?? '',
SUPPORTED_NETWORKS: process.env.SUPPORTED_NETWORKS ?? '',
+ ADMIN_WALLET_ADDRESS: process.env.ADMIN_WALLET_ADDRESS ?? '0x80a1874E1046B1cc5deFdf4D3153838B72fF94Ac',
}
server.decorate("config", config);
diff --git a/backend/src/routes/admin.ts b/backend/src/routes/admin.ts
index f039438..850830f 100644
--- a/backend/src/routes/admin.ts
+++ b/backend/src/routes/admin.ts
@@ -8,6 +8,20 @@ import { encode, decode } from "../utils/crypto.js";
import SupportedNetworks from "../../config.json" assert { type: "json" };
const adminRoutes: FastifyPluginAsync = async (server) => {
+
+ server.post('/adminLogin', async function (request, reply) {
+ try {
+ const body: any = JSON.parse(request.body as string);
+ if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.EMPTY_BODY });
+ if (!body.WALLET_ADDRESS) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA });
+ console.log(body, server.config.ADMIN_WALLET_ADDRESS)
+ if (ethers.utils.getAddress(body.WALLET_ADDRESS) === server.config.ADMIN_WALLET_ADDRESS) return reply.code(ReturnCode.SUCCESS).send({error: null, message: "Successfully Logged in"});
+ return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_USER });
+ } catch (err: any) {
+ return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_USER });
+ }
+ })
+
server.get("/getConfig", async function (request, reply) {
try {
const result: any = await new Promise((resolve, reject) => {
diff --git a/backend/src/server.ts b/backend/src/server.ts
index a7e7f68..1627359 100644
--- a/backend/src/server.ts
+++ b/backend/src/server.ts
@@ -101,14 +101,16 @@ const initializeServer = async (): Promise
=> {
}
}
const customChainlinkDeploymentsbase64 = ConfigData.CUSTOM_CHAINLINK_DEPLOYED;
+ const coingeckoIdsbase64 = ConfigData.COINGECKO_IDS;
if (customChainlinkDeploymentsbase64) {
try {
- const buffer = Buffer.from(customChainlinkDeploymentsbase64, 'base64');
+ let buffer = Buffer.from(customChainlinkDeploymentsbase64, 'base64');
const customChainlinks = JSON.parse(buffer.toString());
+ buffer = Buffer.from(coingeckoIdsbase64, 'base64');
+ const coingeckoIds = JSON.parse(buffer.toString());
const customChainlinkDeployments = customChainlinks[chain] ?? [];
if (customChainlinkDeployments.includes(deployedPaymaster)) {
- const coingeckoIds = ConfigData.COINGECKO_IDS?.split(',') ?? [''];
- const coingeckoId = coingeckoIds[customChainlinkDeployments.indexOf(deployedPaymaster)]
+ const coingeckoId = coingeckoIds[chain][customChainlinkDeployments.indexOf(deployedPaymaster)]
const response: any = await (await fetch(`${ConfigData.COINGECKO_API_URL}${coingeckoId}`)).json();
const price = ethers.utils.parseUnits(response[coingeckoId].usd.toString(), 8);
if (price) {
diff --git a/docker-compose.yml b/docker-compose.yml
index 471bb10..382614e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,6 +2,9 @@ version: "3.8"
services:
frontend:
+ environment:
+ - REACT_APP_INDEXER_ENDPOINT=http://localhost:3003
+ - REACT_APP_SERVER_URL=http://localhost:5050
build:
context: ./frontend
dockerfile: Dockerfile
@@ -18,7 +21,7 @@ services:
- UNSAFE_MODE=false
- SUPPORTED_NETWORKS=
- CRON_PRIVATE_KEY=
- - REACT_APP_INDEXER_ENDPOINT=http://localhost:3003
+ - DEFAULT_INDEXER_ENDPOINT=http://localhost:3003
build:
context: ./backend
dockerfile: Dockerfile
diff --git a/frontend/Dockerfile b/frontend/Dockerfile
index 7311fc2..bf744d2 100644
--- a/frontend/Dockerfile
+++ b/frontend/Dockerfile
@@ -6,5 +6,6 @@ COPY package.json /frontend/
COPY config-overrides.js /frontend/
COPY postcss.config.js /frontend/
COPY tailwind.config.js /frontend/
+COPY demo.env /frontend/.env
RUN npm install
CMD ["npm", "start"]
diff --git a/frontend/demo.env b/frontend/demo.env
new file mode 100644
index 0000000..06a5d0c
--- /dev/null
+++ b/frontend/demo.env
@@ -0,0 +1 @@
+REACT_APP_SERVER_URL=http://localhost:5050
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 1286d4a..d816516 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "arka_frontend",
- "version": "1.0.0",
+ "version": "1.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "arka_frontend",
- "version": "1.0.0",
+ "version": "1.0.2",
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "7.21.11",
"@emotion/react": "^11.11.1",
diff --git a/frontend/package.json b/frontend/package.json
index 37b2add..a0e374d 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "arka_frontend",
- "version": "1.0.0",
+ "version": "1.0.2",
"private": true,
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "7.21.11",