Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: balance refresh and tx gas #49

Merged
merged 1 commit into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions front/src/app/api/users/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
import { PUBLIC_CLIENT } from "@/constants/client";
import { FACTORY_ABI } from "@/constants/factory";
import { Hex, stringify, toHex } from "viem";
import { Hex, createPublicClient, stringify, toHex, fallback, http } from "viem";
import { sepolia } from "viem/chains";

export async function GET(_req: Request, { params }: { params: { id: Hex } }) {
const { id } = params;
if (!id) {
return Response.json(JSON.parse(stringify({ error: "id is required" })));
}

const user = await PUBLIC_CLIENT.readContract({
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({
address: process.env.NEXT_PUBLIC_FACTORY_CONTRACT_ADDRESS as Hex,
abi: FACTORY_ABI,
functionName: "getUser",
args: [BigInt(id)],
});

const balance = await PUBLIC_CLIENT.getBalance({ address: user.account });
const balance = await CLIENT.getBalance({ address: user.account });

console.log("balance", balance);

return Response.json(JSON.parse(stringify({ ...user, id: toHex(user.id), balance })));
}
4 changes: 1 addition & 3 deletions front/src/app/api/users/save/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,10 @@ export async function POST(req: Request) {

// send 1 wei to the user
// so that anyone can send a transaction to the user's smart wallet
const hash2 = await walletClient.sendTransaction({
walletClient.sendTransaction({
to: createdUser.account,
value: BigInt(1),
});

await publicClient.waitForTransactionReceipt({ hash: hash2 });

return Response.json({ ...createdUser, id: toHex(createdUser.id) });
}
10 changes: 6 additions & 4 deletions front/src/components/SendTxModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { Chain, EstimateFeesPerGasReturnType, Hash, Hex } from "viem";
import { Chain, EstimateFeesPerGasReturnType, Hash, Hex, parseEther } from "viem";
import { smartWallet } from "@/libs/smart-wallet";
import { useEffect, useRef, useState } from "react";
import { Flex, Link, Button, Heading, Text, TextField, Callout } from "@radix-ui/themes";
Expand Down Expand Up @@ -55,10 +55,10 @@ export default function SendTxModal() {
function handleUserInputAmount(e: any) {
const value = e.target.value;
const amount = Number(value);
if ((amount > balance && value !== "") || value === "") {
if ((amount > Number(balance) && value !== "") || value === "") {
setIsBelowBalance(false);
}
if (amount <= balance && value !== "") {
if (amount <= Number(balance) && value !== "") {
setIsBelowBalance(true);
}
setUserInputAmount(value);
Expand Down Expand Up @@ -112,12 +112,13 @@ export default function SendTxModal() {
).json();
const { maxFeePerGas, maxPriorityFeePerGas }: EstimateFeesPerGasReturnType =
await smartWallet.client.estimateFeesPerGas();

const userOp = await builder.buildUserOp({
calls: [
{
dest: destination.toLowerCase() as Hex,
value:
(BigInt(userInputAmount) * BigInt(1e18)) /
BigInt(parseEther(userInputAmount)) /
(BigInt(Math.trunc(price.ethereum.usd * 100)) / BigInt(100)), // 100 is the price precision
data: emptyHex,
},
Expand Down Expand Up @@ -259,6 +260,7 @@ export default function SendTxModal() {
min={0}
max={balance?.toString() || 0}
size={"3"}
step={0.01}
// style={{ paddingRight: "1rem" }}
value={userInputAmount}
onChange={handleUserInputAmount}
Expand Down
20 changes: 11 additions & 9 deletions front/src/constants/client.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { createPublicClient, http } from "viem";
import { createPublicClient, fallback, http } from "viem";
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"] },
},
// rpcUrls: {
// ...sepolia.rpcUrls,
// default: { http: ["https://rpc.ankr.com/eth_sepolia"] },
// public: { http: ["https://rpc.ankr.com/eth_sepolia"] },
// },
};

export const PUBLIC_CLIENT = createPublicClient({
chain: CHAIN,
transport: http(),
chain: sepolia,
transport: fallback([
http("https://ethereum-sepolia.publicnode.com"),
http("https://gateway.tenderly.co/public/sepolia "),
]),
});

export const MAINNET_PUBLIC_CLIENT = createPublicClient({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ export const waitForUserOperationReceipt = <TChain extends Chain | undefined>(
_unobserve();
};

const _userOperationReceipt = await getUserOperationReceipt(client, { hash });
try {
const _userOperationReceipt = await getUserOperationReceipt(client, { hash });

if (_userOperationReceipt !== null) {
userOperationReceipt = _userOperationReceipt;
}
if (_userOperationReceipt !== null) {
userOperationReceipt = _userOperationReceipt;
}

if (userOperationReceipt) {
done(() => emit.resolve(userOperationReceipt));
return;
}
if (userOperationReceipt) {
done(() => emit.resolve(userOperationReceipt));
return;
}
} catch (error) {}
}, pollingInterval);
});
});
Expand Down
12 changes: 9 additions & 3 deletions front/src/libs/smart-wallet/service/userOps/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class UserOpBuilder {
});

// set gas limits with the estimated values + some extra gas for safety
userOp.callGasLimit = callGasLimit;
userOp.callGasLimit = BigInt(callGasLimit);
userOp.preVerificationGas = BigInt(preVerificationGas) * BigInt(10);
userOp.verificationGasLimit =
BigInt(verificationGasLimit) + BigInt(150_000) + BigInt(initCodeGas) + BigInt(1_000_000);
Expand All @@ -116,7 +116,7 @@ export class UserOpBuilder {
const msgToSign = encodePacked(["uint8", "uint48", "bytes32"], [1, 0, userOpHash]);

// get signature from webauthn
const signature = await this.getSignature(msgToSign);
const signature = await this.getSignature(msgToSign, keyId);

return this.toParams({ ...userOp, signature });
}
Expand All @@ -137,9 +137,15 @@ export class UserOpBuilder {
};
}

public async getSignature(msgToSign: Hex): Promise<Hex> {
public async getSignature(msgToSign: Hex, keyId: Hex): Promise<Hex> {
const credentials: P256Credential = (await WebAuthn.get(msgToSign)) as P256Credential;

if (credentials.rawId !== keyId) {
throw new Error(
"Incorrect passkeys used for tx signing. Please sign the transaction with the correct logged-in account",
);
}

const signature = encodePacked(
["uint8", "uint48", "bytes"],
[
Expand Down
4 changes: 2 additions & 2 deletions front/src/libs/smart-wallet/service/userOps/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { UserOperation } from "@/libs/smart-wallet/service/userOps/types";
import { toHex, zeroAddress } from "viem";

export const DEFAULT_CALL_GAS_LIMIT = BigInt(200_000);
export const DEFAULT_VERIFICATION_GAS_LIMIT = BigInt(2_000_000);
export const DEFAULT_PRE_VERIFICATION_GAS = BigInt(65_000);
export const DEFAULT_VERIFICATION_GAS_LIMIT = BigInt(2_000_000); // 2M
export const DEFAULT_PRE_VERIFICATION_GAS = BigInt(80_000); //65000

export const DEFAULT_USER_OP: UserOperation = {
sender: zeroAddress,
Expand Down
3 changes: 0 additions & 3 deletions front/src/libs/wallet-connect/hook/useWalletConnectHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import { SessionTypes } from "@walletconnect/types";
import { WC_CONFIG } from "../config";
import { on } from "events";
import { useMe } from "@/providers/MeProvider";
import { EthSendTransactionParams } from "../config/EIP155";
import { useModal } from "@/providers/ModalProvider";
import WCSendTransactionModal from "@/components/WCSendTransactionModal";

interface ISessions {
[topic: string]: SessionTypes.Struct;
Expand Down
24 changes: 18 additions & 6 deletions front/src/providers/BalanceProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,42 @@

import { getUser } from "@/libs/factory/getUser";
import { useMe } from "@/providers/MeProvider";
import { createContext, useCallback, useContext, useEffect, useState } from "react";
import { Hex } from "viem";
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
import { Hex, formatEther } from "viem";

function useBalanceHook() {
// balance in usd
const [balance, setBalance] = useState<number>(0);
const [balance, setBalance] = useState<string>("0.00");
const [increment, setIncrement] = useState<number>(0);

const { me } = useMe();

const getBalance = useCallback(async (keyId: Hex) => {
const user = await getUser(keyId);
const ethBalance = Number(user.balance) / 1e18;
console.log(user.balance);
const priceData = await fetch("/api/price?ids=ethereum&currencies=usd");
const price: number = (await priceData.json()).ethereum.usd;
setBalance(ethBalance * price);
const price: number = Math.trunc((await priceData.json()).ethereum.usd * 100);
const balance = formatEther((BigInt(user.balance) * BigInt(price)) / BigInt(100));
setBalance(balance);
}, []);

const refreshBalance = useCallback(() => {
setIncrement((prev) => prev + 1);
}, []);

let interval = useRef<any>(null);

useEffect(() => {
if (!me?.keyId) return;
getBalance(me?.keyId);
interval.current && clearInterval(interval.current);
interval.current = setInterval(() => {
getBalance(me?.keyId);
}, 3000);

return () => {
clearInterval(interval.current);
};
}, [me, getBalance, increment]);

return {
Expand Down