From 9557d2d9df2769f0bd1cabd56ffe8f3f86815c3d Mon Sep 17 00:00:00 2001 From: Raj Ranjan Date: Thu, 14 Dec 2023 22:03:57 +0530 Subject: [PATCH] mainnet balance checks --- config.json | 1 + server.ts | 26 +++++++++++++++++++++++--- types.ts | 2 ++ utils/mainnetBalanceCheck.ts | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 utils/mainnetBalanceCheck.ts diff --git a/config.json b/config.json index 772468f..0208946 100644 --- a/config.json +++ b/config.json @@ -30,6 +30,7 @@ "DECIMALS": 18, "RECALIBRATE": 30, "COUPON_REQUIRED": true, + "MAINNET_BALANCE_CHECK_RPC": "https://api.avax.network/ext/C/rpc", "RATELIMIT": { "MAX_LIMIT": 1, "WINDOW_SIZE": 1440 diff --git a/server.ts b/server.ts index 9aa3631..4b3034c 100644 --- a/server.ts +++ b/server.ts @@ -22,6 +22,7 @@ import { DEBUG, } from './config.json' import { CouponService } from './CouponService/couponService' +import { checkMainnetBalance } from './utils/mainnetBalanceCheck' dotenv.config() @@ -128,13 +129,32 @@ router.post('/sendToken', captcha.middleware, async (req: any, res: any) => { // drip amount (native or erc20 token) for this request as per config const dripAmount = erc20Instance?.config.DRIP_AMOUNT ?? evm.config.DRIP_AMOUNT + /** + * MAINNET BALANCE OR COUPON VALIDATION checks + * 1. If mainnet balance check is enabled, users would be required to have mainnet balance + * 2. If coupon validation is enabled, users would need a specific coupon id to get tokens + * 3. If both are enabled, then any one would be sufficient + */ + + // mainnet balance checks + const mainnetCheckEnabledRPC = erc20Instance?.config.MAINNET_BALANCE_CHECK_RPC ?? evm.config.MAINNET_BALANCE_CHECK_RPC ?? false + let mainnetCheckPassed = false + if (mainnetCheckEnabledRPC && (await checkMainnetBalance(mainnetCheckEnabledRPC, address))) { + mainnetCheckPassed = true + } + // validate coupon let couponValidity: CouponValidity = {isValid: false, amount: dripAmount} - if ( + // check coupon validation only if mainnet check failed (either no-balance or check not enabled) + !mainnetCheckPassed && + + // coupon checks couponConfig.IS_ENABLED && - (erc20Instance && erc20Instance.config.COUPON_REQUIRED) || - (erc20Instance === undefined && evm.config.COUPON_REQUIRED) + // if request is for erc20 tokens + ((erc20Instance && erc20Instance.config.COUPON_REQUIRED) || + // if request is for evm native token + (erc20Instance === undefined && evm.config.COUPON_REQUIRED)) ) { // if coupon is required but not passed in request if (coupon === undefined) { diff --git a/types.ts b/types.ts index 1817e1b..71bba96 100644 --- a/types.ts +++ b/types.ts @@ -37,6 +37,7 @@ export type ChainType = { DRIP_AMOUNT: number, RECALIBRATE?: number, COUPON_REQUIRED?: boolean, + MAINNET_BALANCE_CHECK_RPC?: string, RATELIMIT: { WINDOW_SIZE: number, MAX_LIMIT: number @@ -64,6 +65,7 @@ export type ERC20Type = { MAX_PRIORITY_FEE?: string, MAX_FEE?: string, COUPON_REQUIRED?: boolean, + MAINNET_BALANCE_CHECK_RPC?: string, } export type CouponValidity = { diff --git a/utils/mainnetBalanceCheck.ts b/utils/mainnetBalanceCheck.ts new file mode 100644 index 0000000..22ae23d --- /dev/null +++ b/utils/mainnetBalanceCheck.ts @@ -0,0 +1,19 @@ +import axios from "axios" + +export async function checkMainnetBalance(rpc: string, address: string, threshold = 0): Promise { + try { + const response = await axios.post(rpc, { + jsonrpc: "2.0", + method: "eth_getBalance", + params: [address, "latest"], + id: 1, + }) + if (parseInt(response.data.result) > threshold) { + return true + } + } catch(err) { + console.error('ERROR: checkMainnetBalance', err) + return false + } + return false +}