From ae978a738c51063b0a7914113fa11a3e073cda84 Mon Sep 17 00:00:00 2001 From: Benjamin A <97291322+Baoufa@users.noreply.github.com> Date: Tue, 28 Nov 2023 09:13:47 +0100 Subject: [PATCH] feat: add getBalance endpoint using etherscan api (#58) * feat: add balance api endpoint * feat: etherscan api key --- front/.env.local.example | 3 ++- front/src/app/api/balance/[address]/route.ts | 15 ++++++++++++ front/src/app/api/users/[id]/route.ts | 13 +++++++++- front/src/libs/factory/getBalance.ts | 14 +++++++++++ front/src/providers/BalanceProvider/index.tsx | 24 ++++++++----------- 5 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 front/src/app/api/balance/[address]/route.ts create mode 100644 front/src/libs/factory/getBalance.ts diff --git a/front/.env.local.example b/front/.env.local.example index ba60530..24e7979 100644 --- a/front/.env.local.example +++ b/front/.env.local.example @@ -1,4 +1,5 @@ NEXT_PUBLIC_STACKUP_BUNDLER_API_KEY="" -NEXT_PUBLIC_RPC_ENDPOINT="https://eth-sepolia.g.alchemy.com/v2/N5ZVikrQ0kBZLVjyY8GwbpYSLPLRuINB" +NEXT_PUBLIC_RPC_ENDPOINT="" +ETHERSCAN_API_KEY="" NEXT_PUBLIC_FACTORY_CONTRACT_ADDRESS="0xDD0f9cB4Cf53d28b976C13e7ee4a169F841924c0" RELAYER_PRIVATE_KEY="" \ No newline at end of file diff --git a/front/src/app/api/balance/[address]/route.ts b/front/src/app/api/balance/[address]/route.ts new file mode 100644 index 0000000..a36e4dd --- /dev/null +++ b/front/src/app/api/balance/[address]/route.ts @@ -0,0 +1,15 @@ +import { Hex, stringify } from "viem"; + +export async function GET(_req: Request, { params }: { params: { address: Hex } }) { + const { address } = params; + if (!address) { + return Response.json(JSON.parse(stringify({ error: "address is required" }))); + } + const result = await fetch( + `https://api-sepolia.etherscan.io/api?module=account&action=balance&address=${address}&tag=latest&apikey=${process.env.ETHERSCAN_API_KEY}`, + ); + const resultJSON = await result.json(); + const balance = BigInt(resultJSON?.result || 0); + + return Response.json(JSON.parse(stringify({ balance }))); +} diff --git a/front/src/app/api/users/[id]/route.ts b/front/src/app/api/users/[id]/route.ts index bef3078..e1090ab 100644 --- a/front/src/app/api/users/[id]/route.ts +++ b/front/src/app/api/users/[id]/route.ts @@ -15,6 +15,17 @@ export async function GET(_req: Request, { params }: { params: { id: Hex } }) { args: [BigInt(id)], }); - const balance = await PUBLIC_CLIENT.getBalance({ address: user.account }); + //const balance = await PUBLIC_CLIENT.getBalance({ address: user.account }); + let balance = BigInt(0); + + // Using etherscan api instead of getBalance as Sepolia rcp node is not inconsistent + if (user?.account) { + const result = await fetch( + `https://api-sepolia.etherscan.io/api?module=account&action=balance&address=${user.account}&tag=latest&apikey=${process.env.ETHERSCAN_API_KEY}`, + ); + const resultJSON = await result.json(); + balance = BigInt(resultJSON?.result || 0); + } + return Response.json(JSON.parse(stringify({ ...user, id: toHex(user.id), balance }))); } diff --git a/front/src/libs/factory/getBalance.ts b/front/src/libs/factory/getBalance.ts new file mode 100644 index 0000000..ca486cf --- /dev/null +++ b/front/src/libs/factory/getBalance.ts @@ -0,0 +1,14 @@ +import { Address, Hex } from "viem"; + +export type User = { id: Hex; pubKey: { x: Hex; y: Hex }; account: Address; balance: bigint }; + +export async function getBalance(address: Hex): Promise<{ balance: bigint }> { + const response = await fetch(`/api/balance/${address}`, { + method: "GET", + }); + + const user = await response.json(); + return { + balance: user.balance, + }; +} diff --git a/front/src/providers/BalanceProvider/index.tsx b/front/src/providers/BalanceProvider/index.tsx index b86de86..f2ad4fc 100644 --- a/front/src/providers/BalanceProvider/index.tsx +++ b/front/src/providers/BalanceProvider/index.tsx @@ -1,9 +1,9 @@ "use client"; -import { getUser } from "@/libs/factory/getUser"; +import { getBalance } from "@/libs/factory/getBalance"; import { useMe } from "@/providers/MeProvider"; import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react"; -import { Hex, formatEther, zeroAddress } from "viem"; +import { Hex, formatEther } from "viem"; function useBalanceHook() { // balance in usd @@ -12,15 +12,11 @@ function useBalanceHook() { const { me } = useMe(); - const getBalance = useCallback(async (keyId: Hex) => { - const user = await getUser(keyId); - if (user?.account === zeroAddress || user?.account === undefined) { - setBalance("0.00"); - return; - } + const getBalanceUSD = useCallback(async (address: Hex) => { + const res = await getBalance(address); const priceData = await fetch("/api/price?ids=ethereum¤cies=usd"); const price: number = Math.trunc((await priceData.json()).ethereum.usd * 100); - const balance = formatEther((BigInt(user.balance) * BigInt(price)) / BigInt(100)); + const balance = formatEther((BigInt(res.balance) * BigInt(price)) / BigInt(100)); setBalance(balance); }, []); @@ -31,17 +27,17 @@ function useBalanceHook() { let interval = useRef(null); useEffect(() => { - if (!me?.keyId) return; - getBalance(me?.keyId); + if (!me?.account) return; + getBalanceUSD(me?.account); interval.current && clearInterval(interval.current); interval.current = setInterval(() => { - getBalance(me?.keyId); - }, 3000); + getBalanceUSD(me?.account); + }, 5000); return () => { interval.current && clearInterval(interval.current); }; - }, [me, getBalance, increment]); + }, [me?.account, getBalanceUSD, increment]); return { balance,