Skip to content

Commit

Permalink
fix(demo): handle multiple preconf requests nonce
Browse files Browse the repository at this point in the history
  • Loading branch information
thedevbirb committed Jul 25, 2024
1 parent 4d3c06e commit 6708e20
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 20 deletions.
53 changes: 46 additions & 7 deletions bolt-web-demo/frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import io from "socket.io-client";
import Image from "next/image";
import { useState, useEffect } from "react";
import { useState, useEffect, useMemo } from "react";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Button } from "@/components/ui/button";
import { createPreconfPayload } from "@/lib/wallet";
import { EventType } from "@/lib/types";
import { Progress } from "@/components/ui/progress";
import { ethers } from "ethers";
import { PRIVATE_KEY, SERVER_URL } from "@/lib/constants";

type Event = {
message: string;
Expand All @@ -16,8 +18,6 @@ type Event = {
link?: string;
};

export const SERVER_URL = "http://localhost:3001";

export default function Home() {
const [events, setEvents] = useState<Array<Event>>([]);

Expand All @@ -37,6 +37,16 @@ export default function Home() {
const [beaconClientUrl, setBeaconClientUrl] = useState("");
const [providerUrl, setProviderUrl] = useState("");
const [explorerUrl, setExplorerUrl] = useState("");
const [preconfirmationRequests, setPreconfirmationRequests] = useState<
Array<{ slot: number; count: number }>
>([]);
const [nonce, setNonce] = useState(0);

const wallet = useMemo(() => {
const provider = new ethers.JsonRpcProvider(providerUrl);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
return wallet;
}, [providerUrl]);

useEffect(() => {
fetch(`${SERVER_URL}/retry-port-events`);
Expand All @@ -52,14 +62,23 @@ export default function Home() {
console.info("Event from server:", event);

if (event.type === EventType.NEW_SLOT) {
if (Number(event.message) === preconfSlot + 64) {
const slot = Number(event.message);
if (slot === preconfSlot + 64) {
setPreconfFinalized(true);
setFinalizationTimerActive(false);
dispatchEvent({
message: `Preconfirmed transaction finalized at slot ${event.message}`,
timestamp: new Date().toISOString(),
});
}

// Drop old requests
setPreconfirmationRequests((prev) =>
prev.filter((req) => req.slot < slot),
);

// Update the nonce
wallet.getNonce().then((nonce) => setNonce(nonce));
}

// If the event has a special type, handle it differently
Expand Down Expand Up @@ -105,7 +124,7 @@ export default function Home() {
return () => {
newSocket.close();
};
}, [explorerUrl, preconfSlot]);
}, [explorerUrl, preconfSlot, wallet]);

useEffect(() => {
let interval: any = null;
Expand Down Expand Up @@ -160,10 +179,30 @@ export default function Home() {
setFinalizationTime(0);

try {
const { payload, txHash } = await createPreconfPayload(providerUrl);
const nonceWithPreconfs =
nonce +
preconfirmationRequests
.map((req) => req.count)
.reduce((acc, c) => acc + c, 0);

const { payload, txHash } = await createPreconfPayload(
wallet,
nonceWithPreconfs,
);

// save the request
setPreconfirmationRequests((prev) => {
const newReq = prev.find((req) => req.slot === payload.slot);
if (newReq) {
newReq.count += 1;
return [...prev];
}
return [...prev, { slot: payload.slot, count: 1 }];
});

setPreconfSlot(payload.slot);
dispatchEvent({
message: `Preconfirmation request sent for tx: ${txHash} at slot ${payload.slot}`,
message: `Preconfirmation request sent for tx: ${txHash} at slot ${payload.slot} with nonce ${nonceWithPreconfs}`,
timestamp: new Date().toISOString(),
});

Expand Down
19 changes: 6 additions & 13 deletions bolt-web-demo/frontend/src/lib/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { SERVER_URL } from "@/app/page";
import { TransactionRequest, keccak256 } from "ethers";
import { ethers } from "ethers";

// Test private key, for which address[0] holds 1000 ETH in the Kurtosis devnet
const PRIVATE_KEY =
"39725efee3fb28614de3bacaffe4cc4bd8c436257e2c8bb887c4b5c4be45e76d";
import { KURTOSIS_CHAIN_ID, SERVER_URL } from "./constants";

type InclusionRequestPayload = {
slot: number;
Expand All @@ -13,16 +9,13 @@ type InclusionRequestPayload = {
};

export async function createPreconfPayload(
providerUrl: string
wallet: ethers.Wallet,
nonce: number,
): Promise<{ payload: InclusionRequestPayload; txHash: string }> {
// Create a Wallet instance from a private key
const provider = new ethers.JsonRpcProvider(providerUrl);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

// Define the transaction
const tx: TransactionRequest = {
chainId: (await provider.getNetwork()).chainId,
nonce: await wallet.getNonce(),
chainId: KURTOSIS_CHAIN_ID,
nonce: nonce,
from: await wallet.getAddress(),
to: "0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD",
value: ethers.parseEther("0.0069420"),
Expand Down Expand Up @@ -57,7 +50,7 @@ export async function createPreconfPayload(

export async function getLatestSlot(): Promise<number> {
const slotResponse = await fetch(`${SERVER_URL}/latest-slot`).then(
(response) => response.json()
(response) => response.json(),
);
return Number(slotResponse.slot);
}
Expand Down

0 comments on commit 6708e20

Please sign in to comment.