Skip to content

Commit

Permalink
PRO-2166-Frontend Changes (#69)
Browse files Browse the repository at this point in the history
* added remove Whitelist API

* added remove whitelist frontend
  • Loading branch information
vignesha22 authored Mar 4, 2024
1 parent 0e3f000 commit 45cbd5f
Show file tree
Hide file tree
Showing 18 changed files with 763 additions and 622 deletions.
4 changes: 2 additions & 2 deletions admin_frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion admin_frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "admin_frontend",
"version": "1.0.2",
"version": "1.0.3",
"private": true,
"dependencies": {
"@emotion/react": "11.11.3",
Expand Down
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
2 changes: 2 additions & 0 deletions backend/src/constants/ErrorMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
30 changes: 27 additions & 3 deletions backend/src/paymaster/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}

Expand All @@ -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);
}
}
}
56 changes: 56 additions & 0 deletions backend/src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
12 changes: 12 additions & 0 deletions frontend/.editorconfig
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ chrome-user-data
.vscode
*.swp
*.swo

.env.local
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/ConnectedIcon.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { Fragment } from "react";

const ColoredCircle = ({ color }) => {
const styles = { backgroundColor: color };
const styles = { backgroundColor: color };

return color ? (
<Fragment>
<span className="colored-circle" style={styles} />
</Fragment>
) : null;
return color ? (
<Fragment>
<span className="colored-circle" style={styles} />
</Fragment>
) : null;
};

export default ColoredCircle;
Loading

0 comments on commit 45cbd5f

Please sign in to comment.