Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9b4f376
Add initial version of useBatcherMaxFee hook
maximopalopoli Sep 24, 2025
df1d86a
Use hook in submit step to cap the max fee value
maximopalopoli Sep 24, 2025
4d2988d
Use hook when setting the values on bump fee modal
maximopalopoli Sep 24, 2025
2398b5a
Fix the chriteria to choose between estimated and latest
maximopalopoli Sep 24, 2025
a6337af
Update the useBatcherMaxFee component
maximopalopoli Sep 24, 2025
5880088
Revert "Use hook when setting the values on bump fee modal"
maximopalopoli Sep 24, 2025
733c02f
Remove console logs and unused property param
maximopalopoli Sep 24, 2025
f1cdc7c
Merge branch 'main' into feat/get-last-max-fee-from-batcher
maximopalopoli Sep 24, 2025
9c45678
Merge branch 'main' into feat/get-last-max-fee-from-batcher
maximopalopoli Sep 26, 2025
aa1782b
Add latestMaxFee and maxFee vars to the callbacks
maximopalopoli Sep 26, 2025
8e79834
Cap the estimated max fee with the latest one in the cost shown in modal
maximopalopoli Sep 26, 2025
f2e1e19
Merge branch 'main' into feat/get-last-max-fee-from-batcher
maximopalopoli Sep 26, 2025
3b044cb
Merge branch 'main' into feat/get-last-max-fee-from-batcher
maximopalopoli Oct 2, 2025
2d8759f
Merge branch 'main' into feat/get-last-max-fee-from-batcher
MarcosNicolau Oct 8, 2025
8f2d780
Merge branch 'main' into feat/get-last-max-fee-from-batcher
maximopalopoli Oct 9, 2025
8d5db8c
Merge branch 'main' into feat/get-last-max-fee-from-batcher
maximopalopoli Oct 21, 2025
9907047
Merge branch 'main' into feat/get-last-max-fee-from-batcher
maximopalopoli Oct 27, 2025
5713102
Merge branch 'main' into feat/get-last-max-fee-from-batcher
MarcosNicolau Oct 28, 2025
468a9ad
Merge branch 'main' into feat/get-last-max-fee-from-batcher
JuArce Oct 28, 2025
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
38 changes: 31 additions & 7 deletions web/assets/js/react/components/Modal/SubmitProof/SubmitStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import {
useAligned,
useBatcherNonce,
useBatcherMaxFee,
useBatcherPaymentService,
useEthPrice,
useBeastLeaderboardContract,
Expand Down Expand Up @@ -111,6 +112,10 @@ export const SubmitProofStep = ({
batcher_url,
user_address
);
const { maxFee: latestMaxFee, isLoading: previousMaxFeeLoading } = useBatcherMaxFee(
batcher_url,
user_address
);
const [invalidGameConfig, setInvalidGameConfig] = useState(false);
const [levelAlreadyReached, setLevelAlreadyReached] = useState(false);
const [gameIdx, setGameIdx] = useState(initialGameIdx);
Expand Down Expand Up @@ -152,12 +157,17 @@ export const SubmitProofStep = ({

useEffect(() => {
const fn = async () => {
const maxFee = await estimateMaxFeeForBatchOfProofs(16);
if (!maxFee) return;
const estimatedMaxFee = await estimateMaxFeeForBatchOfProofs(16);
if (!estimatedMaxFee) return;

const maxFee = latestMaxFee && latestMaxFee < estimatedMaxFee
? latestMaxFee
: estimatedMaxFee;

setMaxFee(maxFee);
};
fn();
}, [estimateMaxFeeForBatchOfProofs]);
}, [estimateMaxFeeForBatchOfProofs, latestMaxFee, maxFee]);

const handleCombinedProofFile = async (
e: React.ChangeEvent<HTMLInputElement>
Expand Down Expand Up @@ -244,12 +254,17 @@ export const SubmitProofStep = ({
return;
}

const maxFee = await estimateMaxFeeForBatchOfProofs(16);
if (!maxFee) {
// This value should be capped by the previous proof max fee
const estimatedMaxFee = await estimateMaxFeeForBatchOfProofs(16);
if (!estimatedMaxFee) {
alert("Could not estimate max fee");
return;
}

const maxFee = latestMaxFee && latestMaxFee < estimatedMaxFee
? latestMaxFee
: estimatedMaxFee;
Comment thread
MarcosNicolau marked this conversation as resolved.

if (nonce == null) {
alert("Nonce is still loading or failed");
return;
Expand Down Expand Up @@ -302,15 +317,20 @@ export const SubmitProofStep = ({
payment_service_addr,
chainId,
nonce,
latestMaxFee,
maxFee,
]);

const handleSend = useCallback(
Comment thread
MarcosNicolau marked this conversation as resolved.
async (proofToSubmitData: VerificationData) => {
const maxFee = await estimateMaxFeeForBatchOfProofs(16);
if (!maxFee) {
const estimatedMaxFee = await estimateMaxFeeForBatchOfProofs(16);
if (!estimatedMaxFee) {
alert("Could not estimate max fee");
return;
}
const maxFee = latestMaxFee && latestMaxFee < estimatedMaxFee
? latestMaxFee
: estimatedMaxFee;

if (nonce == null) {
alert("Nonce is still loading or failed");
Expand Down Expand Up @@ -352,6 +372,8 @@ export const SubmitProofStep = ({
payment_service_addr,
chainId,
nonce,
latestMaxFee,
maxFee,
]
);

Expand Down Expand Up @@ -646,6 +668,7 @@ export const SubmitProofStep = ({
!publicInputs ||
(balance.data || 0) < maxFee ||
nonceLoading ||
previousMaxFeeLoading ||
nonce == null ||
levelAlreadyReached
}
Expand All @@ -660,6 +683,7 @@ export const SubmitProofStep = ({
disabled={
(balance.data || 0) < maxFee ||
nonceLoading ||
previousMaxFeeLoading ||
nonce == null ||
levelAlreadyReached
}
Expand Down
1 change: 1 addition & 0 deletions web/assets/js/react/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export * from "./useIsMounted";
export * from "./useModal";
export * from "./useOnClickOutside";
export * from "./useBatcherNonce";
export * from "./useBatcherMaxFee";
export * from "./useBeastLeaderboardContract";
export * from "./useEthPrice";
72 changes: 72 additions & 0 deletions web/assets/js/react/hooks/useBatcherMaxFee.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useEffect, useState } from "react";
import { encode as cborEncode, decode as cborDecode } from 'cbor2';
import { hexToBigInt } from "viem";

type GetLastMaxFeeFromBatcherResponse = {
ProtocolVersion: string,
LastMaxFee: `0x${string}`;
EthRpcError: string;
InvalidRequest: string;
}

export function useBatcherMaxFee(batcher_url: string, address?: string) {
const [maxFee, setMaxFee] = useState<bigint | null>(null);
const [error, setError] = useState<Error | null>(null);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
let ws: WebSocket | null = null;

const fetchMaxFee = () => {
if (!address) {
return
}

ws = new WebSocket(`${batcher_url}`);
ws.binaryType = 'arraybuffer';

ws.onopen = () => {
console.log("WebSocket connection established");
};

ws.onmessage = (event) => {
try {
const cbor_data = event.data;
const data = cborDecode<GetLastMaxFeeFromBatcherResponse>(new Uint8Array(cbor_data));

if (data?.ProtocolVersion) {
const message = { GetLastMaxFee: address };
const encoded = cborEncode(message).buffer;
ws?.send(encoded);
} else if (data?.LastMaxFee) {
ws?.close();
setMaxFee(hexToBigInt(data.LastMaxFee));
setIsLoading(false);
} else if (data?.EthRpcError || data?.InvalidRequest) {
ws?.close();
setError(new Error(JSON.stringify(data)));
setIsLoading(false);
}
} catch (e) {
ws?.close();
setError(e as Error);
setIsLoading(false);
}
};

ws.onerror = () => {
ws?.close();
setError(new Error("WebSocket connection error"));
setIsLoading(false);
};
};

fetchMaxFee();

return () => {
ws?.close();
};
}, [batcher_url, address]);

return { maxFee, isLoading, error };
}