From ec445b0f745723c9a596fe27de9786dafa56faab Mon Sep 17 00:00:00 2001 From: Benjamin A <97291322+Baoufa@users.noreply.github.com> Date: Fri, 24 Nov 2023 12:24:33 +0100 Subject: [PATCH] fix: RPC endpoint and optimized onboarding (#50) --- front/src/app/api/users/[id]/route.ts | 15 ++----- front/src/app/api/users/save/route.ts | 44 +++++++++++-------- front/src/constants/client.ts | 15 +++---- front/src/constants/factory.ts | 19 ++++++++ front/src/providers/BalanceProvider/index.tsx | 7 ++- front/src/providers/MeProvider/index.tsx | 23 ++++++---- 6 files changed, 75 insertions(+), 48 deletions(-) diff --git a/front/src/app/api/users/[id]/route.ts b/front/src/app/api/users/[id]/route.ts index c6f9170..79d4be5 100644 --- a/front/src/app/api/users/[id]/route.ts +++ b/front/src/app/api/users/[id]/route.ts @@ -1,7 +1,6 @@ import { PUBLIC_CLIENT } from "@/constants/client"; import { FACTORY_ABI } from "@/constants/factory"; -import { Hex, createPublicClient, stringify, toHex, fallback, http } from "viem"; -import { sepolia } from "viem/chains"; +import { Hex, stringify, toHex } from "viem"; export async function GET(_req: Request, { params }: { params: { id: Hex } }) { const { id } = params; @@ -9,22 +8,14 @@ export async function GET(_req: Request, { params }: { params: { id: Hex } }) { return Response.json(JSON.parse(stringify({ error: "id is required" }))); } - const CLIENT = createPublicClient({ - chain: sepolia, - transport: fallback([ - http("https://rpc.notadegen.com/eth/sepolia"), - http("https://gateway.tenderly.co/public/sepolia "), - ]), - }); - - const user = await CLIENT.readContract({ + const user = await PUBLIC_CLIENT.readContract({ address: process.env.NEXT_PUBLIC_FACTORY_CONTRACT_ADDRESS as Hex, abi: FACTORY_ABI, functionName: "getUser", args: [BigInt(id)], }); - const balance = await CLIENT.getBalance({ address: user.account }); + const balance = await PUBLIC_CLIENT.getBalance({ address: user.account }); console.log("balance", balance); diff --git a/front/src/app/api/users/save/route.ts b/front/src/app/api/users/save/route.ts index ea12c97..38a8a1e 100644 --- a/front/src/app/api/users/save/route.ts +++ b/front/src/app/api/users/save/route.ts @@ -1,6 +1,6 @@ -import { CHAIN } from "@/constants"; +import { CHAIN, PUBLIC_CLIENT, transport } from "@/constants"; import { FACTORY_ABI } from "@/constants/factory"; -import { Hex, createPublicClient, createWalletClient, http, toHex, zeroAddress } from "viem"; +import { Hex, createWalletClient, toHex, zeroAddress } from "viem"; import { privateKeyToAccount } from "viem/accounts"; export async function POST(req: Request) { @@ -10,15 +10,10 @@ export async function POST(req: Request) { const walletClient = createWalletClient({ account, chain: CHAIN, - transport: http(), + transport, }); - const publicClient = createPublicClient({ - chain: CHAIN, - transport: http(), - }); - - const user = await publicClient.readContract({ + const user = await PUBLIC_CLIENT.readContract({ address: process.env.NEXT_PUBLIC_FACTORY_CONTRACT_ADDRESS as Hex, abi: FACTORY_ABI, functionName: "getUser", @@ -29,28 +24,41 @@ export async function POST(req: Request) { return Response.json(undefined); } - const hash = await walletClient.writeContract({ + await walletClient.writeContract({ address: process.env.NEXT_PUBLIC_FACTORY_CONTRACT_ADDRESS as Hex, abi: FACTORY_ABI, functionName: "saveUser", args: [BigInt(id), pubKey], }); - await publicClient.waitForTransactionReceipt({ hash }); - - const createdUser = await publicClient.readContract({ + const smartWalletAddress = await PUBLIC_CLIENT.readContract({ address: process.env.NEXT_PUBLIC_FACTORY_CONTRACT_ADDRESS as Hex, abi: FACTORY_ABI, - functionName: "getUser", - args: [BigInt(id)], + functionName: "getAddress", + args: [pubKey], }); + // await PUBLIC_CLIENT.waitForTransactionReceipt({ hash }); + + // const createdUser = await PUBLIC_CLIENT.readContract({ + // address: process.env.NEXT_PUBLIC_FACTORY_CONTRACT_ADDRESS as Hex, + // abi: FACTORY_ABI, + // functionName: "getUser", + // args: [BigInt(id)], + // }); + // send 1 wei to the user // so that anyone can send a transaction to the user's smart wallet - walletClient.sendTransaction({ - to: createdUser.account, + await walletClient.sendTransaction({ + to: smartWalletAddress, value: BigInt(1), }); - return Response.json({ ...createdUser, id: toHex(createdUser.id) }); + const createdUser = { + id, + account: smartWalletAddress, + pubKey, + }; + + return Response.json(createdUser); } diff --git a/front/src/constants/client.ts b/front/src/constants/client.ts index 5269307..742fbbc 100644 --- a/front/src/constants/client.ts +++ b/front/src/constants/client.ts @@ -3,19 +3,16 @@ import { sepolia, mainnet } from "viem/chains"; export const CHAIN = { ...sepolia, - // rpcUrls: { - // ...sepolia.rpcUrls, - // default: { http: ["https://rpc.ankr.com/eth_sepolia"] }, - // public: { http: ["https://rpc.ankr.com/eth_sepolia"] }, - // }, }; +export const transport = fallback([ + http("https://rpc.notadegen.com/eth/sepolia"), + http("https://gateway.tenderly.co/public/sepolia "), +]); + export const PUBLIC_CLIENT = createPublicClient({ chain: sepolia, - transport: fallback([ - http("https://ethereum-sepolia.publicnode.com"), - http("https://gateway.tenderly.co/public/sepolia "), - ]), + transport, }); export const MAINNET_PUBLIC_CLIENT = createPublicClient({ diff --git a/front/src/constants/factory.ts b/front/src/constants/factory.ts index 5439dc9..8935467 100644 --- a/front/src/constants/factory.ts +++ b/front/src/constants/factory.ts @@ -91,4 +91,23 @@ export const FACTORY_ABI = [ stateMutability: "view", type: "function", }, + { + inputs: [ + { + internalType: "bytes32[2]", + name: "publicKey", + type: "bytes32[2]", + }, + ], + name: "getAddress", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, ] as const; diff --git a/front/src/providers/BalanceProvider/index.tsx b/front/src/providers/BalanceProvider/index.tsx index 7e00001..a39035a 100644 --- a/front/src/providers/BalanceProvider/index.tsx +++ b/front/src/providers/BalanceProvider/index.tsx @@ -3,7 +3,7 @@ import { getUser } from "@/libs/factory/getUser"; import { useMe } from "@/providers/MeProvider"; import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react"; -import { Hex, formatEther } from "viem"; +import { Hex, formatEther, zeroAddress } from "viem"; function useBalanceHook() { // balance in usd @@ -14,6 +14,11 @@ function useBalanceHook() { const getBalance = useCallback(async (keyId: Hex) => { const user = await getUser(keyId); + if (user?.account === zeroAddress || user?.account === undefined) { + setBalance("0.00"); + return; + } + console.log(user.balance); const priceData = await fetch("/api/price?ids=ethereum¤cies=usd"); const price: number = Math.trunc((await priceData.json()).ethereum.usd * 100); diff --git a/front/src/providers/MeProvider/index.tsx b/front/src/providers/MeProvider/index.tsx index cc3901e..8b222a1 100644 --- a/front/src/providers/MeProvider/index.tsx +++ b/front/src/providers/MeProvider/index.tsx @@ -1,7 +1,7 @@ "use client"; import { createContext, useContext, useEffect, useState } from "react"; -import { Address, Hex } from "viem"; +import { Address, Hex, zeroAddress } from "viem"; import { WebAuthn } from "@/libs/web-authn/service/web-authn"; import { saveUser } from "@/libs/factory"; import { getUser } from "@/libs/factory/getUser"; @@ -23,7 +23,7 @@ function useMeHook() { const [isMounted, setIsMounted] = useState(false); function disconnect() { - localStorage.removeItem("hocuspocus.me"); + localStorage.removeItem("passkeys4337.me"); setMe(null); } @@ -50,8 +50,8 @@ function useMeHook() { console.log("error while saving user"); return; } - localStorage.setItem("hocuspocus.me", JSON.stringify(me)); - localStorage.setItem("hocuspocus.returning", "true"); + localStorage.setItem("passkeys4337.me", JSON.stringify(me)); + localStorage.setItem("passkeys4337.returning", "true"); walletConnect.smartWalletAddress = me.account; setIsReturning(true); setMe(me); @@ -70,18 +70,25 @@ function useMeHook() { return; } const user = await getUser(credential.rawId); + + if (user?.account === undefined || user?.account === zeroAddress) { + throw new Error("user not found"); + } + const me = { keyId: user.id as Hex, pubKey: user.pubKey, account: user.account, }; - localStorage.setItem("hocuspocus.me", JSON.stringify(me)); - localStorage.setItem("hocuspocus.returning", "true"); + localStorage.setItem("passkeys4337.me", JSON.stringify(me)); + localStorage.setItem("passkeys4337.returning", "true"); walletConnect.smartWalletAddress = me.account; setIsReturning(true); setMe(me); } catch (e) { + localStorage.removeItem("passkeys4337.returning"); + disconnect(); console.error(e); } finally { setIsLoading(false); @@ -89,8 +96,8 @@ function useMeHook() { } useEffect(() => { - const me = localStorage.getItem("hocuspocus.me"); - const returning = localStorage.getItem("hocuspocus.returning"); + const me = localStorage.getItem("passkeys4337.me"); + const returning = localStorage.getItem("passkeys4337.returning"); if (me) { try { setMe(JSON.parse(me));