diff --git a/backend/demo.env b/backend/demo.env index 6f2d6ca..86ab78f 100644 --- a/backend/demo.env +++ b/backend/demo.env @@ -3,7 +3,6 @@ LOG_LEVEL=debug API_HOST=127.0.0.1 API_PORT=5050 -API_KEY=dev -PAYMASTER_PRIVATE_KEY=0x -STACKUP_API_KEY= \ No newline at end of file +STACKUP_API_KEY= +SUPPORTED_NETWORKS= \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index d59fdc3..f2b6460 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "arka", - "version": "1.0.0", + "version": "1.1.1", "description": "This project was bootstrapped with Fastify-CLI.", "type": "module", "directories": { @@ -28,6 +28,8 @@ "dependencies": { "@account-abstraction/contracts": "0.6.0", "@account-abstraction/utils": "0.5.0", + "@aws-sdk/client-secrets-manager": "3.410.0", + "@fastify/cors": "^8.4.0", "@sinclair/typebox": "0.23.5", "ajv": "8.11.2", "dotenv": "16.0.3", diff --git a/backend/src/constants/ErrorMessage.ts b/backend/src/constants/ErrorMessage.ts index 3fe2905..d927743 100644 --- a/backend/src/constants/ErrorMessage.ts +++ b/backend/src/constants/ErrorMessage.ts @@ -5,4 +5,5 @@ export default { UNSUPPORTED_NETWORK_TOKEN: 'Unsupported network/token', EMPTY_BODY: 'Empty Body received', SOMETHING_WENT_WRONG: 'Something went wrong', + INVALID_MODE: 'Invalid mode selected' } \ No newline at end of file diff --git a/backend/src/constants/ReturnCode.ts b/backend/src/constants/ReturnCode.ts new file mode 100644 index 0000000..39e62fa --- /dev/null +++ b/backend/src/constants/ReturnCode.ts @@ -0,0 +1,4 @@ +export default { + SUCCESS: 200, + FAILURE: 400, +} \ No newline at end of file diff --git a/backend/src/paymaster/index.ts b/backend/src/paymaster/index.ts index 8ae323e..b6f6a41 100644 --- a/backend/src/paymaster/index.ts +++ b/backend/src/paymaster/index.ts @@ -23,14 +23,11 @@ interface stackupPaymasterResponse { } export class Paymaster { - private relayerKey: string; private stackupEndpoint: string | null; constructor( - relayerKey: string, stackupApiKey: string, ) { - this.relayerKey = relayerKey; this.stackupEndpoint = stackupApiKey ? `https://api.stackup.sh/v1/paymaster/${stackupApiKey}` : null; } @@ -58,11 +55,11 @@ export class Paymaster { } // eslint-disable-next-line @typescript-eslint/no-explicit-any - async sign(userOp: any, validUntil: string, validAfter: string, entryPoint: string, paymasterAddress: string, bundlerRpc: string) { + async sign(userOp: any, validUntil: string, validAfter: string, entryPoint: 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(this.relayerKey, provider) + const signer = new Wallet(relayerKey, provider) userOp.paymasterAndData = await this.getPaymasterAndData(userOp, validUntil, validAfter, paymasterContract, signer); const response = await provider.send('eth_estimateUserOperationGas', [userOp, entryPoint]); userOp.verificationGasLimit = response.verificationGasLimit; @@ -140,11 +137,11 @@ export class Paymaster { } } - async whitelistAddresses(address: string[], paymasterAddress: string, bundlerRpc: string) { + async whitelistAddresses(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(this.relayerKey, provider) + const signer = new Wallet(relayerKey, provider) const encodedData = paymasterContract.interface.encodeFunctionData('addBatchToWhitelist', [address]); const tx = await signer.sendTransaction({ to: paymasterAddress, data: encodedData }); await tx.wait(); @@ -162,11 +159,11 @@ export class Paymaster { return paymasterContract.check(sponsorAddress, accountAddress); } - async deposit(amount: string, paymasterAddress: string, bundlerRpc: string) { + async deposit(amount: 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(this.relayerKey, provider) + const signer = new Wallet(relayerKey, provider) const balance = await signer.getBalance(); if (ethers.utils.parseEther(amount.toString()).gte(balance)) throw new Error(`${signer.address} Balance is less than the amount to be deposited`) diff --git a/backend/src/plugins/config.ts b/backend/src/plugins/config.ts index 74065af..7223963 100644 --- a/backend/src/plugins/config.ts +++ b/backend/src/plugins/config.ts @@ -16,9 +16,7 @@ const ConfigSchema = Type.Strict( LOG_LEVEL: Type.String(), API_HOST: Type.String(), API_PORT: Type.String(), - PAYMASTER_PRIVATE_KEY: Type.String(), STACKUP_API_KEY: Type.String() || undefined, - API_KEY: Type.String(), SUPPORTED_NETWORKS: Type.String() || undefined, }) ); @@ -47,8 +45,6 @@ const configPlugin: FastifyPluginAsync = async (server) => { LOG_LEVEL: process.env.LOG_LEVEL ?? '', API_PORT: process.env.API_PORT ?? '', API_HOST: process.env.API_HOST ?? '', - API_KEY: process.env.API_KEY ?? '', - PAYMASTER_PRIVATE_KEY: process.env.PAYMASTER_PRIVATE_KEY ?? '', STACKUP_API_KEY: process.env.STACKUP_API_KEY ?? '', SUPPORTED_NETWORKS: process.env.SUPPORTED_NETWORKS ?? '', } diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts index a07fdf4..f78176c 100644 --- a/backend/src/routes/index.ts +++ b/backend/src/routes/index.ts @@ -6,18 +6,23 @@ import { Paymaster } from "../paymaster/index.js"; import SupportedNetworks from "../../config.json" assert { type: "json" }; import { TOKEN_ADDRESS } from "../constants/Pimlico.js"; import ErrorMessage from "../constants/ErrorMessage.js"; +import ReturnCode from "../constants/ReturnCode.js"; +import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager"; const routes: FastifyPluginAsync = async (server) => { const paymaster = new Paymaster( - server.config.PAYMASTER_PRIVATE_KEY, server.config.STACKUP_API_KEY, ); - function getNetworkConfig(key: any) { - if (server.config.SUPPORTED_NETWORKS !== '') { - const buffer = Buffer.from(server.config.SUPPORTED_NETWORKS, 'base64'); - const supportedNetworks = JSON.parse(buffer.toString()) - return supportedNetworks.find((chain: any) => { chain["chainId"] == key }); + const prefixSecretId = 'arka_'; + + const client = new SecretsManagerClient(); + + function getNetworkConfig(key: any, supportedNetworks: any) { + if (supportedNetworks !== '') { + const buffer = Buffer.from(supportedNetworks, 'base64'); + const SUPPORTED_NETWORKS = JSON.parse(buffer.toString()) + return SUPPORTED_NETWORKS.find((chain: any) => { return chain["chainId"] == key }); } else return SupportedNetworks.find((chain) => chain.chainId == key); } @@ -38,7 +43,7 @@ const routes: FastifyPluginAsync = async (server) => { server.get( "/healthcheck", async function (request, reply) { - return reply.code(200).send('Arka Service Running...'); + return reply.code(ReturnCode.SUCCESS).send('Arka Service Running...'); } ) @@ -48,83 +53,66 @@ const routes: FastifyPluginAsync = async (server) => { try { const body: any = request.body; const date = new Date(); - if (!body) return reply.code(400).send({ error: ErrorMessage.EMPTY_BODY }); + if (!body) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.EMPTY_BODY }); const userOp = body.params[0]; const entryPoint = body.params[1]; - // eslint-disable-next-line @typescript-eslint/no-unused-vars const context = body.params[2]; + const gasToken = context?.token ? context.token : null; + const mode = context?.mode ? String(context.mode) : null; const chainId = body.params[3]; const api_key = body.params[4]; - if (!api_key || - (api_key != server.config.API_KEY) - ) return reply.code(400).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!api_key) + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + 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 }) if ( !userOp || !entryPoint || !chainId || + !mode || isNaN(chainId) ) { - return reply.code(400).send({ error: ErrorMessage.INVALID_DATA }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); } if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - } - const hex = (Number((date.valueOf() / 1000).toFixed(0)) + 6000).toString(16); - let str = '0x' - for (let i = 0; i < 14 - hex.length; i++) { - str += '0'; - } - str += hex; - const networkConfig = getNetworkConfig(chainId); - if (!networkConfig) return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - const result = await paymaster.sign(userOp, str, "0x0000000000001234", entryPoint, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler); - if (body.jsonrpc) - return reply.code(200).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) - return reply.code(200).send(result); - } catch (err: any) { - request.log.error(err); - return reply.code(400).send({ error: err.message ?? ErrorMessage.SOMETHING_WENT_WRONG }); - } - } - ); - - server.post( - "/pimlico", - async function (request, reply) { - try { - const body: any = request.body; - - const userOp = body.params[0]; - const entryPoint = body.params[1]; - const context = body.params[2]; - const gasToken = context ? context.token : null; - const chainId = body.params[3]; - const api_key = body.params[4]; - if (!api_key || - (api_key != server.config.API_KEY) - ) return reply.code(400).send({ error: ErrorMessage.INVALID_API_KEY }) - if ( - !userOp || - !entryPoint || - !gasToken || - !chainId || - isNaN(chainId) - ) { - return reply.code(400).send({ error: ErrorMessage.INVALID_DATA }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); } - if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + if (mode.toLowerCase() == 'erc20' && !TOKEN_ADDRESS[chainId][gasToken]) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK_TOKEN }) + const networkConfig = getNetworkConfig(chainId, secrets['SUPPORTED_NETWORKS'] ?? ''); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + let result; + switch (mode.toLowerCase()) { + case 'sponsor': { + const hex = (Number((date.valueOf() / 1000).toFixed(0)) + 600).toString(16); + let str = '0x' + for (let i = 0; i < 14 - hex.length; i++) { + str += '0'; + } + str += hex; + result = await paymaster.sign(userOp, str, "0x0000000000001234", entryPoint, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler, secrets['PRIVATE_KEY']); + break; + } + case 'erc20': { + result = await paymaster.pimlico(userOp, gasToken, networkConfig.bundler, entryPoint); + break; + } + case 'default': { + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_MODE }); + } } - const networkConfig = getNetworkConfig(chainId); - if (!networkConfig) return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - if (!TOKEN_ADDRESS[chainId][gasToken]) return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK_TOKEN }) - const result = await paymaster.pimlico(userOp, gasToken, networkConfig.bundler, entryPoint); if (body.jsonrpc) - return reply.code(200).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) - return reply.code(200).send(result); + 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); - return reply.code(400).send({ error: err.message ?? ErrorMessage.SOMETHING_WENT_WRONG }); + 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 }); } } ); @@ -140,30 +128,38 @@ const routes: FastifyPluginAsync = async (server) => { const gasToken = context ? context.token : null; const chainId = body.params[2]; const api_key = body.params[3]; - if (!api_key || - (api_key != server.config.API_KEY) - ) return reply.code(400).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!api_key) + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + 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 }) if ( !entryPoint || !gasToken || !chainId || isNaN(chainId) ) { - return reply.code(400).send({ error: ErrorMessage.INVALID_DATA }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); } if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); } - const networkConfig = getNetworkConfig(chainId); - if (!networkConfig) return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - if (!TOKEN_ADDRESS[chainId][gasToken]) return reply.code(400).send({ error: "Invalid network/token" }) + const networkConfig = getNetworkConfig(chainId, secrets['SUPPORTED_NETWORKS'] ?? ''); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + if (!TOKEN_ADDRESS[chainId][gasToken]) return reply.code(ReturnCode.FAILURE).send({ error: "Invalid network/token" }) const result = await paymaster.pimlicoAddress(gasToken, networkConfig.bundler, entryPoint); if (body.jsonrpc) - return reply.code(200).send({ jsonrpc: body.jsonrpc, id: body.id, message: result.message, error: null }) - return reply.code(200).send(result); + return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, message: result.message, error: null }) + return reply.code(ReturnCode.SUCCESS).send(result); } catch (err: any) { request.log.error(err); - return reply.code(400).send({ error: err.message ?? ErrorMessage.SOMETHING_WENT_WRONG }); + 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 }); } } ) @@ -179,23 +175,31 @@ const routes: FastifyPluginAsync = async (server) => { const context = body.params[2]; const gasToken = context ? context.token : null; const api_key = body.params[3]; - if (!api_key || - (api_key != server.config.API_KEY) - ) return reply.code(400).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!api_key) + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + 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 }) if ( !userOp || !entryPoint || !gasToken ) { - return reply.code(400).send({ error: ErrorMessage.INVALID_DATA }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); } const result = await paymaster.stackup(userOp, "erc20token", gasToken, entryPoint); if (body.jsonrpc) - return reply.code(200).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) - return reply.code(200).send(result); + 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); - return reply.code(400).send({ error: err.message ?? ErrorMessage.INVALID_DATA }); + 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.INVALID_DATA }); } } ); @@ -209,31 +213,39 @@ const routes: FastifyPluginAsync = async (server) => { const address = body.params[0]; const chainId = body.params[1]; const api_key = body.params[2]; - if (!api_key || - (api_key != server.config.API_KEY) - ) return reply.code(400).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!api_key) + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + 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 }) if ( !Array.isArray(address) || address.length > 10 || !chainId || isNaN(chainId) ) { - return reply.code(400).send({ error: ErrorMessage.INVALID_DATA }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); } if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); } - const networkConfig = getNetworkConfig(chainId); - if (!networkConfig) return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + const networkConfig = getNetworkConfig(chainId, secrets['SUPPORTED_NETWORKS'] ?? ''); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); const validAddresses = await address.every(ethers.utils.isAddress); - if (!validAddresses) return reply.code(400).send({ error: "Invalid Address passed" }); - const result = await paymaster.whitelistAddresses(address, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler); + if (!validAddresses) return reply.code(ReturnCode.FAILURE).send({ error: "Invalid Address passed" }); + const result = await paymaster.whitelistAddresses(address, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler, secrets['PRIVATE_KEY']); if (body.jsonrpc) - return reply.code(200).send({ jsonrpc: body.jsonrpc, id: body.id, result, error: null }) - return reply.code(200).send(result); + 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); - return reply.code(400).send({ error: err.message ?? ErrorMessage.SOMETHING_WENT_WRONG }) + 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 }) } } ) @@ -248,9 +260,15 @@ const routes: FastifyPluginAsync = async (server) => { const accountAddress = body.params[1]; const chainId = body.params[2]; const api_key = body.params[3]; - if (!api_key || - (api_key != server.config.API_KEY) - ) return reply.code(400).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!api_key) + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + 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 }) if ( !sponsorAddress || !accountAddress || @@ -259,20 +277,22 @@ const routes: FastifyPluginAsync = async (server) => { !chainId || isNaN(chainId) ) { - return reply.code(400).send({ error: ErrorMessage.INVALID_DATA }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); } if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); } - const networkConfig = getNetworkConfig(chainId); - if (!networkConfig) return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + const networkConfig = getNetworkConfig(chainId, secrets['SUPPORTED_NETWORKS'] ?? ''); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); const response = await paymaster.checkWhitelistAddress(sponsorAddress, accountAddress, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler); if (body.jsonrpc) - return reply.code(200).send({ jsonrpc: body.jsonrpc, id: body.id, result: { message: response === true ? 'Already added' : 'Not added yet' }, error: null }) - return reply.code(200).send({ message: response === true ? 'Already added' : 'Not added yet' }); + return reply.code(ReturnCode.SUCCESS).send({ jsonrpc: body.jsonrpc, id: body.id, result: { message: response === true ? 'Already added' : 'Not added yet' }, error: null }) + return reply.code(ReturnCode.SUCCESS).send({ message: response === true ? 'Already added' : 'Not added yet' }); } catch (err: any) { request.log.error(err); - return reply.code(400).send({ error: err.message ?? ErrorMessage.SOMETHING_WENT_WRONG }) + 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 }) } } ) @@ -287,25 +307,33 @@ const routes: FastifyPluginAsync = async (server) => { const amount = body.params[0]; const chainId = body.params[1]; const api_key = body.params[2]; - if (!api_key || - (api_key != server.config.API_KEY) - ) return reply.code(400).send({ error: ErrorMessage.INVALID_API_KEY }) + if (!api_key) + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_API_KEY }) + 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 }) if ( isNaN(amount) || !chainId || isNaN(chainId) ) { - return reply.code(400).send({ error: ErrorMessage.INVALID_DATA }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.INVALID_DATA }); } if (server.config.SUPPORTED_NETWORKS == '' && !SupportedNetworks) { - return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); } - const networkConfig = getNetworkConfig(chainId); - if (!networkConfig) return reply.code(400).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); - return await paymaster.deposit(amount, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler); + const networkConfig = getNetworkConfig(chainId, secrets['SUPPORTED_NETWORKS'] ?? ''); + if (!networkConfig) return reply.code(ReturnCode.FAILURE).send({ error: ErrorMessage.UNSUPPORTED_NETWORK }); + return await paymaster.deposit(amount, networkConfig.contracts.etherspotPaymasterAddress, networkConfig.bundler, secrets['PRIVATE_KEY']); } catch (err: any) { request.log.error(err); - return reply.code(400).send({ error: err.message ?? ErrorMessage.SOMETHING_WENT_WRONG }) + 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 }) } } ) diff --git a/backend/src/server.ts b/backend/src/server.ts index bb3f8b8..b5c6c8f 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -1,4 +1,5 @@ import fastify from 'fastify'; +import cors from '@fastify/cors' import config from './plugins/config.js'; import routes from './routes/index.js'; @@ -15,6 +16,11 @@ const server = fastify({ }, }); +await server.register(cors, { + // put your options here + preflightContinue: true +}) + await server.register(config); await server.register(routes); await server.ready();