diff --git a/admin_frontend/package-lock.json b/admin_frontend/package-lock.json
index 736fa53..bd3c274 100644
--- a/admin_frontend/package-lock.json
+++ b/admin_frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "admin_frontend",
- "version": "1.0.2",
+ "version": "1.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "admin_frontend",
- "version": "1.0.2",
+ "version": "1.0.3",
"dependencies": {
"@emotion/react": "11.11.3",
"@emotion/styled": "11.11.0",
diff --git a/admin_frontend/package.json b/admin_frontend/package.json
index c234130..9c9f593 100644
--- a/admin_frontend/package.json
+++ b/admin_frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "admin_frontend",
- "version": "1.0.2",
+ "version": "1.0.3",
"private": true,
"dependencies": {
"@emotion/react": "11.11.3",
diff --git a/backend/package.json b/backend/package.json
index b48d40d..8ecc9d1 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -1,6 +1,6 @@
{
"name": "arka",
- "version": "1.1.2",
+ "version": "1.1.3",
"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 06e4616..1bf8bee 100644
--- a/backend/src/constants/ErrorMessage.ts
+++ b/backend/src/constants/ErrorMessage.ts
@@ -7,6 +7,8 @@ export default {
FAILED_TO_PROCESS: 'Failed to process the request. Please try again or contact ARKA support team',
INVALID_MODE: 'Invalid mode selected',
DUPLICATE_RECORD: 'Duplicate record found',
+ ERROR_ON_SUBMITTING_TXN: 'The wallet does not have enough funds or the gas price is too high at the moment. Please try again later or contact support team',
+ RPC_ERROR: 'rpcError while checking whitelist. Please try again later',
QUOTA_EXCEEDED: 'Quota exceeded for this month',
INVALID_USER: 'Unauthorised User',
RECORD_NOT_FOUND: 'Api Key provided not found',
diff --git a/backend/src/paymaster/index.ts b/backend/src/paymaster/index.ts
index 4c55031..8a16632 100644
--- a/backend/src/paymaster/index.ts
+++ b/backend/src/paymaster/index.ts
@@ -3,6 +3,7 @@ import { providers, Wallet, ethers, Contract } from 'ethers';
import { arrayify, defaultAbiCoder, hexConcat } from 'ethers/lib/utils.js';
import abi from "../abi/EtherspotAbi.js";
import { PimlicoPaymaster, getERC20Paymaster } from './pimlico.js';
+import ErrorMessage from 'constants/ErrorMessage.js';
export class Paymaster {
@@ -116,7 +117,30 @@ export class Paymaster {
};
} catch (err: any) {
if (err.message.includes('already whitelisted')) throw new Error(err);
- throw new Error('Error while submitting transaction');
+ throw new Error(ErrorMessage.ERROR_ON_SUBMITTING_TXN);
+ }
+ }
+
+ async removeWhitelistAddress(address: string[], paymasterAddress: string, bundlerRpc: string, relayerKey: string) {
+ try {
+ const provider = new providers.JsonRpcProvider(bundlerRpc);
+ const paymasterContract = new ethers.Contract(paymasterAddress, abi, provider);
+ const signer = new Wallet(relayerKey, provider)
+ for (let i = 0; i < address.length; i++) {
+ const isAdded = await paymasterContract.check(signer.address, address[i]);
+ if (!isAdded) {
+ throw new Error(`${address[i]} is not whitelisted`)
+ }
+ }
+ const encodedData = paymasterContract.interface.encodeFunctionData('removeBatchToWhitelist', [address]);
+ const tx = await signer.sendTransaction({ to: paymasterAddress, data: encodedData });
+ await tx.wait();
+ return {
+ message: `Successfully removed whitelisted addresses with transaction Hash ${tx.hash}`
+ };
+ } catch (err: any) {
+ if (err.message.includes('is not whitelisted')) throw new Error(err);
+ throw new Error(ErrorMessage.ERROR_ON_SUBMITTING_TXN);
}
}
@@ -127,7 +151,7 @@ export class Paymaster {
const paymasterContract = new ethers.Contract(paymasterAddress, abi, provider);
return paymasterContract.check(signer.address, accountAddress);
} catch (err) {
- throw new Error('rpcError while checking whitelist');
+ throw new Error(ErrorMessage.RPC_ERROR);
}
}
@@ -146,7 +170,7 @@ export class Paymaster {
message: `Successfully deposited with transaction Hash ${tx.hash}`
};
} catch (err) {
- throw new Error('Error while submitting transaction');
+ throw new Error(ErrorMessage.ERROR_ON_SUBMITTING_TXN);
}
}
}
diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts
index 7a2fe71..dbbc589 100644
--- a/backend/src/routes/index.ts
+++ b/backend/src/routes/index.ts
@@ -320,6 +320,62 @@ const routes: FastifyPluginAsync = async (server) => {
}
)
+ server.post("/removeWhitelist", async function (request, reply) {
+ try {
+ const body: any = request.body;
+ const query: any = request.query;
+ const address = body.params[0];
+ const chainId = query['chainId'] ?? body.params[1];
+ const api_key = query['apiKey'] ?? body.params[2];
+ if (!api_key)
+ return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY })
+ let privateKey = '';
+ let supportedNetworks;
+ if (!unsafeMode) {
+ const AWSresponse = await client.send(
+ new GetSecretValueCommand({
+ SecretId: prefixSecretId + api_key,
+ })
+ );
+ const secrets = JSON.parse(AWSresponse.SecretString ?? '{}');
+ if (!secrets['PRIVATE_KEY']) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY })
+ privateKey = secrets['PRIVATE_KEY'];
+ supportedNetworks = secrets['SUPPORTED_NETWORKS'];
+ } else {
+ const record: any = await getSQLdata(api_key);
+ console.log(record);
+ if (!record) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY })
+ privateKey = decode(record['PRIVATE_KEY']);
+ supportedNetworks = record['SUPPORTED_NETWORKS'];
+ }
+ if (!privateKey) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY })
+ if (
+ !Array.isArray(address) ||
+ address.length > 10 ||
+ !chainId ||
+ isNaN(chainId)
+ ) {
+ return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA });
+ }
+ if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) {
+ return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK });
+ }
+ const networkConfig = getNetworkConfig(chainId, supportedNetworks ?? '');
+ if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK });
+ const validAddresses = address.every(ethers.utils.isAddress);
+ if (!validAddresses) return reply.code(ReturnCode.FAILURE).send({ error: "Invalid Address passed" });
+ const result = await paymaster.removeWhitelistAddress(address, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler, privateKey);
+ if (body.jsonrpc)
+ return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null })
+ return reply.code(ReturnCode.SUCCESS).send(result);
+ } catch (err: any) {
+ request.log.error(err);
+ if (err.name == "ResourceNotFoundException")
+ return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY });
+ return reply.code(ReturnCode.FAILURE).send({ error: err.message ?? ErrorMessage.SOMETHING_WENT_WRONG })
+ }
+ })
+
server.post(
"/checkWhitelist",
async function (request, reply) {
diff --git a/frontend/.editorconfig b/frontend/.editorconfig
new file mode 100644
index 0000000..64d3d6a
--- /dev/null
+++ b/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/frontend/.gitignore b/frontend/.gitignore
index f2ad830..2c69316 100644
--- a/frontend/.gitignore
+++ b/frontend/.gitignore
@@ -14,3 +14,5 @@ chrome-user-data
.vscode
*.swp
*.swo
+
+.env.local
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index d816516..d7bc01d 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "arka_frontend",
- "version": "1.0.2",
+ "version": "1.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "arka_frontend",
- "version": "1.0.2",
+ "version": "1.0.3",
"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 a0e374d..065d6bf 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "arka_frontend",
- "version": "1.0.2",
+ "version": "1.0.3",
"private": true,
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "7.21.11",
diff --git a/frontend/src/components/ConnectedIcon.jsx b/frontend/src/components/ConnectedIcon.jsx
index 4084f53..c83d494 100644
--- a/frontend/src/components/ConnectedIcon.jsx
+++ b/frontend/src/components/ConnectedIcon.jsx
@@ -1,13 +1,13 @@
import React, { Fragment } from "react";
const ColoredCircle = ({ color }) => {
- const styles = { backgroundColor: color };
+ const styles = { backgroundColor: color };
- return color ? (
-
-
-
- ) : null;
+ return color ? (
+
+
+
+ ) : null;
};
export default ColoredCircle;
diff --git a/frontend/src/components/Dashboard.jsx b/frontend/src/components/Dashboard.jsx
index 3bdeb39..3d1ea19 100644
--- a/frontend/src/components/Dashboard.jsx
+++ b/frontend/src/components/Dashboard.jsx
@@ -28,54 +28,54 @@ import { UserAuth } from "../context/AuthContext";
import EtherspotLogo from "../assets/internal-36-etherspot@2x.png";
// constants
-import { networks } from "../utils/constant";
+import { networks, ENDPOINTS } from "../utils/constant";
import EtherspotPaymasterAbi from "../abi/EtherspotPaymasterAbi.json";
const ITEM_HEIGHT = 48;
const MenuProps = {
- PaperProps: {
- style: {
- maxHeight: ITEM_HEIGHT * 4.5,
- width: 250,
- backgroundColor: "#1c1c1c",
- color: "white",
- border: "none",
- },
- },
+ PaperProps: {
+ style: {
+ maxHeight: ITEM_HEIGHT * 4.5,
+ width: 250,
+ backgroundColor: "#1c1c1c",
+ color: "white",
+ border: "none",
+ },
+ },
};
function CustomTabPanel(props) {
- const { children, value, index, ...other } = props;
+ const { children, value, index, ...other } = props;
- return (
-
- {value === index && (
-
- {children}
-
- )}
-
- );
+ return (
+
+ {value === index && (
+
+ {children}
+
+ )}
+
+ );
}
CustomTabPanel.propTypes = {
- children: PropTypes.node,
- index: PropTypes.number.isRequired,
- value: PropTypes.number.isRequired,
+ children: PropTypes.node,
+ index: PropTypes.number.isRequired,
+ value: PropTypes.number.isRequired,
};
function a11yProps(index) {
- return {
- key: `tab-${index}`,
- "aria-controls": `tabpanel-${index}`,
- };
+ return {
+ key: `tab-${index}`,
+ "aria-controls": `tabpanel-${index}`,
+ };
}
const DashBoardPage = styled.div`
@@ -86,546 +86,580 @@ const DashBoardPage = styled.div`
`;
const Dashboard = ({ logInType }) => {
- // Definitions
- const { user, signIn } = UserAuth();
- const [value, setValue] = React.useState(0);
- const [chainId, setChainId] = useState(80001);
- const [signedIn, setSignedIn] = useState(false);
- const [networksSupported, setNetworksSupported] = useState(Object.keys(networks));
- const [supportedNetworks, setSupportedNetworks] = useState();
- const [isLoading, setIsLoading] = useState(false);
- const [paymasterBalance, setPaymasterBalance] = useState("0");
- const [useCustomPaymaster] = useState(false);
- const [customPaymasterAddress] = useState();
- const [selectedOption, setSelectedOption] = useState(0);
- const [amount, setAmount] = useState(0);
- const [checked, setChecked] = useState(false);
- const [buttonText, setButtonText] = useState("Deposit");
- const [whiteListAddress, setWhitelistAddress] = useState("");
+ // Definitions
+ const { user, signIn } = UserAuth();
+ const [value, setValue] = React.useState(0);
+ const [chainId, setChainId] = useState(80001);
+ const [signedIn, setSignedIn] = useState(false);
+ const [networksSupported, setNetworksSupported] = useState(
+ Object.keys(networks)
+ );
+ const [supportedNetworks, setSupportedNetworks] = useState();
+ const [isLoading, setIsLoading] = useState(false);
+ const [paymasterBalance, setPaymasterBalance] = useState("0");
+ const [useCustomPaymaster] = useState(false);
+ const [customPaymasterAddress] = useState();
+ const [selectedOption, setSelectedOption] = useState(0);
+ const [amount, setAmount] = useState(0);
+ const [checked, setChecked] = useState(false);
+ const [buttonText, setButtonText] = useState("Deposit");
+ const [whiteListAddress, setWhitelistAddress] = useState("");
+ const [removeWhitelist, setRemoveWhitelist] = useState(false);
+ const [whitelistButtonText, setWhitelistButtonText] =
+ useState("Add to Whitelist");
- // Functions
- const getPaymasterContract = (chainId) => {
- if (!supportedNetworks) return null;
- const provider = new ethers.providers.JsonRpcProvider(
- supportedNetworks[chainId].rpcUrl,
- {
- name: "Connected Bundler",
- chainId: Number(chainId),
- }
- );
- if (useCustomPaymaster) {
- return new ethers.Contract(
- customPaymasterAddress,
- EtherspotPaymasterAbi,
- provider
- );
- } else {
- return new ethers.Contract(
- supportedNetworks[chainId].paymasterAddress,
- EtherspotPaymasterAbi,
- provider
- );
- }
- };
+ // Functions
+ const getPaymasterContract = (chainId) => {
+ if (!supportedNetworks) return null;
+ const provider = new ethers.providers.JsonRpcProvider(
+ supportedNetworks[chainId].rpcUrl,
+ {
+ name: "Connected Bundler",
+ chainId: Number(chainId),
+ }
+ );
+ if (useCustomPaymaster) {
+ return new ethers.Contract(
+ customPaymasterAddress,
+ EtherspotPaymasterAbi,
+ provider
+ );
+ } else {
+ return new ethers.Contract(
+ supportedNetworks[chainId].paymasterAddress,
+ EtherspotPaymasterAbi,
+ provider
+ );
+ }
+ };
- const fetchData = async (address) => {
+ const fetchData = async (address) => {
try {
setIsLoading(true);
const data = await (
- await fetch("http://localhost:5050/getSupportedNetworks", {
+ await fetch(`${process.env.REACT_APP_SERVER_URL}${ENDPOINTS['getSupportedNetworks']}`, {
method: "POST",
- body: JSON.stringify({WALLET_ADDRESS: address})
+ body: JSON.stringify({ WALLET_ADDRESS: address }),
})
).json();
- const supportedNetworksChainIds = [];
- let supportedNetworks = {}
+ const supportedNetworksChainIds = [];
+ let supportedNetworks = {};
- data?.map((value) => {
- supportedNetworks[value.chainId] = {
- ...networks[value.chainId],
- chainId: value.chainId,
- rpcUrl: value.bundler,
- paymasterAddress: value.contracts.etherspotPaymasterAddress,
- }
- supportedNetworksChainIds.push(value.chainId)
- return value;
- });
- setSupportedNetworks(supportedNetworks);
- setNetworksSupported(supportedNetworksChainIds);
+ data?.map((value) => {
+ supportedNetworks[value.chainId] = {
+ ...networks[value.chainId],
+ chainId: value.chainId,
+ rpcUrl: value.bundler,
+ paymasterAddress: value.contracts.etherspotPaymasterAddress,
+ };
+ supportedNetworksChainIds.push(value.chainId);
+ return value;
+ });
+ setSupportedNetworks(supportedNetworks);
+ setNetworksSupported(supportedNetworksChainIds);
setIsLoading(false);
} catch (err) {
- toast.error(
- "Check Backend Service for more info"
- );
+ toast.error("Check Backend Service for more info");
+ }
+ };
+
+ const getPaymasterBalance = async (chainId) => {
+ try {
+ if (!isLoading) {
+ setIsLoading(true);
+ const PaymasterContract = getPaymasterContract(chainId);
+ if (PaymasterContract) {
+ const balance = await PaymasterContract.getSponsorBalance(
+ user?.address
+ );
+ setPaymasterBalance(ethers.utils.formatEther(balance));
+ }
+ setIsLoading(false);
+ }
+ } catch (err) {
+ console.error(err);
+ setPaymasterBalance("0");
}
};
- const getPaymasterBalance = async (chainId) => {
- try {
- if (!isLoading) {
- setIsLoading(true);
- const PaymasterContract = getPaymasterContract(chainId);
- if (PaymasterContract) {
- const balance = await PaymasterContract.getSponsorBalance(
- user?.address
- );
- setPaymasterBalance(ethers.utils.formatEther(balance));
- }
- setIsLoading(false);
- }
- } catch (err) {
- console.error(err);
- setPaymasterBalance("0");
- }
- };
+ useEffect(() => {
+ setIsLoading(false);
+ if (user?.address) {
+ setSignedIn(true);
+ fetchData(user.address);
+ }
+ setIsLoading(false);
+ }, [user]);
- useEffect(() => {
- setIsLoading(false);
- if (user?.address) {
- setSignedIn(true);
- fetchData(user.address);
- }
- setIsLoading(false);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [user, isLoading]);
+ useEffect(() => {
+ getPaymasterBalance(chainId);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [supportedNetworks]);
- useEffect(() => {
- getPaymasterBalance(chainId)
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [supportedNetworks]);
+ const handleChange = (event, newValue) => {
+ setValue(newValue);
+ };
- const handleChange = (event, newValue) => {
- setValue(newValue);
- };
+ const handleAmountChange = (e) => {
+ const fixed = parseFloat(e.target.value).toFixed(18).toString();
+ if (fixed.length < parseFloat(e.target.value).toString().length)
+ e.target.value = fixed;
+ setAmount(e.target.value);
+ };
- const handleAmountChange = (e) => {
- const fixed = parseFloat(e.target.value).toFixed(18).toString();
- if (fixed.length < parseFloat(e.target.value).toString().length)
- e.target.value = fixed;
- setAmount(e.target.value);
- };
+ const handleDepositChange = (e) => {
+ setChecked(e.target.checked);
+ if (e.target.checked) setButtonText("Withdraw");
+ else setButtonText("Deposit");
+ };
- const handleDepositChange = (e) => {
- setChecked(e.target.checked);
- if (e.target.checked) setButtonText("Withdraw");
- else setButtonText("Deposit");
- };
+ const handleWhitelistSwitch = (e) => {
+ setRemoveWhitelist(e.target.checked);
+ if (e.target.checked) setWhitelistButtonText("Remove from Whitelist");
+ else setWhitelistButtonText("Add to Whitelist");
+ };
- const handleWhitelistAddressChange = (e) => {
- setWhitelistAddress(e.target.value);
- };
+ const handleWhitelistAddressChange = (e) => {
+ setWhitelistAddress(e.target.value);
+ };
- const handleChangeChainId = async (event, newValue) => {
- setIsLoading(true);
- setPaymasterBalance("0");
- setChainId(newValue);
- await getPaymasterBalance(newValue);
- setIsLoading(false);
- };
+ const handleChangeChainId = async (event, newValue) => {
+ setIsLoading(true);
+ setPaymasterBalance("0");
+ setChainId(newValue);
+ await getPaymasterBalance(newValue);
+ setIsLoading(false);
+ };
- const handleOptionChange = (e) => {
- setSelectedOption(e.target.value);
- };
+ const handleOptionChange = (e) => {
+ setSelectedOption(e.target.value);
+ };
- const handleSubmit = async () => {
- try {
- setIsLoading(true);
- if (!user?.address) {
- const retUser = await signIn(logInType);
- if (!retUser) {
- toast.error("Please make sure that metamask is installed");
- } else toast.success("Logged in Successfully");
- return;
- }
- if (amount === 0) {
- toast.error("Please enter an amount to be Deposited/Withdrawn");
- }
- const PaymasterContract = getPaymasterContract(chainId);
- if (checked) {
- const encodedData = PaymasterContract.interface.encodeFunctionData(
- "withdrawFunds",
- [ethers.utils.parseEther(amount.toString())]
- );
- const txHash = await window.ethereum.request({
- method: "eth_sendTransaction",
- params: [
- {
- from: user.address, // The user's active address.
- to: PaymasterContract.address, // Required except during contract publications.
- data: encodedData,
- },
- ],
- });
- toast.loading(
- (t) => (
-
- ),
- {
- icon: "👏",
- }
- );
- } else {
- const encodedData = PaymasterContract.interface.encodeFunctionData(
- "depositFunds",
- []
- );
- const txHash = await window.ethereum.request({
- method: "eth_sendTransaction",
- params: [
- {
- from: user.address, // The user's active address.
- to: PaymasterContract.address, // Required except during contract publications.
- data: encodedData,
- value: ethers.utils.parseEther(amount.toString()).toHexString(),
- },
- ],
- });
- toast.loading(
- (t) => (
-
- ),
- {
- icon: "👏",
- }
- );
- }
- setIsLoading(false);
- } catch (e) {
- console.error(e.message);
- toast.error("Something went wrong on MetaMask");
- setIsLoading(false);
- }
- };
+ const handleSubmit = async () => {
+ try {
+ setIsLoading(true);
+ if (!user?.address) {
+ const retUser = await signIn(logInType);
+ if (!retUser) {
+ toast.error("Please make sure that metamask is installed");
+ } else toast.success("Logged in Successfully");
+ return;
+ }
+ if (amount === 0) {
+ toast.error("Please enter an amount to be Deposited/Withdrawn");
+ }
+ const PaymasterContract = getPaymasterContract(chainId);
+ if (checked) {
+ const encodedData = PaymasterContract.interface.encodeFunctionData(
+ "withdrawFunds",
+ [ethers.utils.parseEther(amount.toString())]
+ );
+ const txHash = await window.ethereum.request({
+ method: "eth_sendTransaction",
+ params: [
+ {
+ from: user.address, // The user's active address.
+ to: PaymasterContract.address, // Required except during contract publications.
+ data: encodedData,
+ },
+ ],
+ });
+ toast.loading(
+ (t) => (
+
+ ),
+ {
+ icon: "👏",
+ }
+ );
+ } else {
+ const encodedData = PaymasterContract.interface.encodeFunctionData(
+ "depositFunds",
+ []
+ );
+ const txHash = await window.ethereum.request({
+ method: "eth_sendTransaction",
+ params: [
+ {
+ from: user.address, // The user's active address.
+ to: PaymasterContract.address, // Required except during contract publications.
+ data: encodedData,
+ value: ethers.utils.parseEther(amount.toString()).toHexString(),
+ },
+ ],
+ });
+ toast.loading(
+ (t) => (
+
+ ),
+ {
+ icon: "👏",
+ }
+ );
+ }
+ setIsLoading(false);
+ } catch (e) {
+ console.error(e.message);
+ toast.error("Something went wrong while submitting. Please check your injected wallet");
+ setIsLoading(false);
+ }
+ };
- const handleWhitelistSubmit = async () => {
- try {
- setIsLoading(true);
- if (!ethers.utils.isAddress(whiteListAddress)) {
- toast.error("Invalid Address provided");
- } else {
- const PaymasterContract = getPaymasterContract(chainId);
- const checkIfAdded = await PaymasterContract.check(
- user.address,
- whiteListAddress
- );
- if (checkIfAdded) {
- toast.error("The Address has been already added to the whitelist");
- } else {
- const encodedData = PaymasterContract.interface.encodeFunctionData(
- "addToWhitelist",
- [whiteListAddress]
- );
- const txHash = await window.ethereum.request({
- method: "eth_sendTransaction",
- params: [
- {
- from: user.address, // The user's active address.
- to: PaymasterContract.address, // Required except during contract publications.
- data: encodedData,
- },
- ],
- });
- toast.loading(
- (t) => (
-
- ),
- {
- icon: "👏",
- }
- );
- }
- }
- setIsLoading(false);
- } catch (err) {
- console.error(err);
- toast.error("Something went wrong on MetaMask");
- setIsLoading(false);
- }
- };
+ const handleWhitelistSubmit = async () => {
+ try {
+ setIsLoading(true);
+ if (!ethers.utils.isAddress(whiteListAddress)) {
+ toast.error("Invalid Address provided");
+ } else {
+ const PaymasterContract = getPaymasterContract(chainId);
+ const checkIfAdded = await PaymasterContract.check(
+ user.address,
+ whiteListAddress
+ );
+ if (checkIfAdded && !removeWhitelist) {
+ toast.error("The Address has been already added to the whitelist");
+ setIsLoading(false);
+ return;
+ }
+ if (!checkIfAdded && removeWhitelist) {
+ toast.error("The Address has not been added to the whitelist");
+ setIsLoading(false);
+ return;
+ }
+ const encodedData = PaymasterContract.interface.encodeFunctionData(
+ removeWhitelist ? "removeFromWhitelist" : "addToWhitelist",
+ [whiteListAddress]
+ );
+ const txHash = await window.ethereum.request({
+ method: "eth_sendTransaction",
+ params: [
+ {
+ from: user.address, // The user's active address.
+ to: PaymasterContract.address, // Required except during contract publications.
+ data: encodedData,
+ },
+ ],
+ });
+ toast.loading(
+ (t) => (
+
+ ),
+ {
+ icon: "👏",
+ }
+ );
+ }
+ setIsLoading(false);
+ } catch (err) {
+ console.error(err);
+ toast.error("Something went wrong while submitting. Please check your injected wallet");
+ setIsLoading(false);
+ }
+ };
- return (
- <>
-
-
-
-
-
-
-
-
-
- {networksSupported?.length && supportedNetworks ? (
-
-
- {networksSupported.map((network, index) => {
- return (
- }
- iconPosition="start"
- label={networks[network].label}
- value={network}
- disabled={!signedIn}
- {...a11yProps(networks[network]?.label)}
- tabIndex={index}
- />
- );
- })}
-
-
- ) : (
- <>>
- )}
- {paymasterBalance !== "0" ? (
-
- Balance: {Number(paymasterBalance).toFixed(5)}{" "}
- getPaymasterBalance(chainId)}
- >
-
-
-
- ) : (
- <>>
- )}
-
-
-
-
-
-
- Select Paymaster
-
-
-
-
-
- Enter Amount
-
-
-
-
- ),
- }}
- sx={[
- {
- ".MuiInputBase-input": {
- color: "white",
- },
- ".MuiFormLabel-root": {
- color: "#5c5c5c",
- fontSize: "1.3rem",
- },
- },
- ]}
- />
-
-
-
-
- Deposit/Withdraw
-
-
-
-
-
-
-
-
-
-
-
-
-
- {Number(paymasterBalance) > 0 ? (
-
-
-
- Whitelist Address
-
-
-
-
-
- ) : (
- <>>
- )}
-
-
- >
- );
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {networksSupported?.length && supportedNetworks ? (
+
+
+ {networksSupported.map((network, index) => {
+ return (
+
+ }
+ iconPosition="start"
+ label={networks[network].label}
+ value={network}
+ disabled={!signedIn}
+ {...a11yProps(networks[network]?.label)}
+ tabIndex={index}
+ />
+ );
+ })}
+
+
+ ) : (
+ <>>
+ )}
+ {paymasterBalance !== "0" ? (
+
+ Balance: {Number(paymasterBalance).toFixed(5)}{" "}
+ getPaymasterBalance(chainId)}
+ >
+
+
+
+ ) : (
+ <>>
+ )}
+
+
+
+
+
+
+ Select Paymaster
+
+
+
+
+
+ Enter Amount
+
+
+
+
+ ),
+ }}
+ sx={[
+ {
+ ".MuiInputBase-input": {
+ color: "white",
+ },
+ ".MuiFormLabel-root": {
+ color: "#5c5c5c",
+ fontSize: "1.3rem",
+ },
+ },
+ ]}
+ />
+
+
+
+
+ Deposit/Withdraw
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {Number(paymasterBalance) > 0 ? (
+
+
+
+
+ Whitelist Address
+
+
+ Add
+
+ Remove
+
+
+
+
+
+
+ ) : (
+ <>>
+ )}
+
+
+ >
+ );
};
export default Dashboard;
diff --git a/frontend/src/components/Header.jsx b/frontend/src/components/Header.jsx
index 08b9559..2d8df95 100644
--- a/frontend/src/components/Header.jsx
+++ b/frontend/src/components/Header.jsx
@@ -6,35 +6,42 @@ import { styled } from "styled-components";
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',
color: '#cfcfcf'
- `
+ `;
const Header = () => {
- const { user, signIn } = UserAuth();
- const [signedIn, setSignedIn] = useState(false);
+ const { user, signIn } = UserAuth();
+ const [signedIn, setSignedIn] = useState(false);
- useEffect(() => {
- if (user?.address) setSignedIn(true);
- }, [user])
+ useEffect(() => {
+ if (user?.address) setSignedIn(true);
+ }, [user]);
- return (
-
-
-
-
Etherspot Arka
-
- { signedIn ?
{user?.address} :
-
}
-
- );
+ return (
+
+
+
+
Etherspot Arka
+
+ {signedIn ? (
+
{user?.address}
+ ) : (
+
+ )}
+
+ );
};
export default Header;
diff --git a/frontend/src/components/NotFound.jsx b/frontend/src/components/NotFound.jsx
index 647cad0..af9363d 100644
--- a/frontend/src/components/NotFound.jsx
+++ b/frontend/src/components/NotFound.jsx
@@ -4,21 +4,21 @@ import { useNavigate } from "react-router-dom";
import { UserAuth } from "../context/AuthContext";
const NotFound = () => {
- const { user } = UserAuth();
- const navigate = useNavigate();
+ const { user } = UserAuth();
+ const navigate = useNavigate();
- useEffect(() => {
- if(!user) {
- toast.error('no such user exists');
- navigate('/');
- }
- }, [user, navigate]);
+ useEffect(() => {
+ if (!user) {
+ toast.error("no such user exists");
+ navigate("/");
+ }
+ }, [user, navigate]);
- return (
-
-
Page Not Found
-
- );
+ return (
+
+
Page Not Found
+
+ );
};
export default NotFound;
diff --git a/frontend/src/components/ProtectedRoute.js b/frontend/src/components/ProtectedRoute.js
index 4eb97d7..8b7482d 100644
--- a/frontend/src/components/ProtectedRoute.js
+++ b/frontend/src/components/ProtectedRoute.js
@@ -1,4 +1,4 @@
-import React, {useEffect} from 'react';
+import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { UserAuth } from '../context/AuthContext';
diff --git a/frontend/src/components/TransactionSentToast.jsx b/frontend/src/components/TransactionSentToast.jsx
index 6ed65ab..f8f6920 100644
--- a/frontend/src/components/TransactionSentToast.jsx
+++ b/frontend/src/components/TransactionSentToast.jsx
@@ -1,30 +1,30 @@
import toast from "react-hot-toast";
const TransactionSentToast = ({ t, blockExplorerLink, txHash }) => {
- const openInExplorer = (txHash) => {
- window.open(`${blockExplorerLink}${txHash}`, "_blank");
- };
+ const openInExplorer = (txHash) => {
+ window.open(`${blockExplorerLink}${txHash}`, "_blank");
+ };
- return (
-
- Transaction Sent
-
-
-
- );
+ return (
+
+ Transaction Sent
+
+
+
+ );
};
export default TransactionSentToast;
diff --git a/frontend/src/context/AuthContext.js b/frontend/src/context/AuthContext.js
index 309e14c..4055dad 100644
--- a/frontend/src/context/AuthContext.js
+++ b/frontend/src/context/AuthContext.js
@@ -16,7 +16,7 @@ export const AuthContextProvider = ({ children }) => {
params: [address, "latest"]
})
return balance;
- } catch(err) {
+ } catch (err) {
console.error('Error on retrieving balance', err);
return 0;
}
diff --git a/frontend/src/utils/constant.js b/frontend/src/utils/constant.js
index c726b43..dbc7693 100644
--- a/frontend/src/utils/constant.js
+++ b/frontend/src/utils/constant.js
@@ -135,3 +135,7 @@ export const networks = {
blockExplorerLink: 'https://snowtrace.io/tx/'
}
}
+
+export const ENDPOINTS = {
+ 'getSupportedNetworks': '/getSupportedNetworks'
+}