diff --git a/packages/frontend/src/providers/BidsProvider/reduceBids.ts b/packages/frontend/src/providers/BidsProvider/reduceBids.ts index 7331767e..55c245bd 100644 --- a/packages/frontend/src/providers/BidsProvider/reduceBids.ts +++ b/packages/frontend/src/providers/BidsProvider/reduceBids.ts @@ -1,6 +1,5 @@ import { Bid } from '@/types/bid' import { Hex } from 'viem' -import { SupportedChainId } from '@/blockchain/chain' interface BidEvent { args: { @@ -13,41 +12,67 @@ interface BidEvent { interface BidsState { bids: Map bidList: Bid[] - startBlock: bigint | undefined - chainId: SupportedChainId | undefined } export const defaultBidsState: BidsState = { bids: new Map(), bidList: [], - startBlock: undefined, - chainId: undefined, } -export interface BidEventsState { +interface BidWithAddressPayload { + bidder: Hex + bid: { + bidderID: bigint + amount: bigint + } +} + +interface InitialBidsAction { + type: 'InitialBids' + bids: readonly BidWithAddressPayload[] +} + +interface NewBidsAction { + type: 'NewBids' events: BidEvent[] - startBlock: bigint | undefined - chainId: SupportedChainId } -export const reduceBids = (previousState: BidsState, state: BidEventsState): BidsState => { - const { events, startBlock, chainId } = state - const bids = getInitialBids(previousState, state) - events.forEach((event) => handleBid(bids, event.args)) +export type ReduceBidsAction = InitialBidsAction | NewBidsAction + +export const reduceBids = (previousState: BidsState, action: ReduceBidsAction) => { + switch (action.type) { + case 'InitialBids': + return addInitialBids(action.bids) + case 'NewBids': + return addNewBids(previousState, action.events) + } +} + +const addInitialBids = (bidsPayload: readonly BidWithAddressPayload[]): BidsState => { + const bids = new Map() + bidsPayload.forEach((bidPayload) => + bids.set(bidPayload.bidder, { + address: bidPayload.bidder, + bidderId: bidPayload.bid.bidderID, + amount: bidPayload.bid.amount, + }), + ) return { bids, bidList: Array.from(bids.values()).sort(biggerFirst), - startBlock: startBlock, - chainId: chainId, } } -const getInitialBids = (previousState: BidsState, { startBlock, chainId }: BidEventsState) => { - if (startBlock !== previousState.startBlock || chainId !== previousState.chainId) { - return new Map() +const addNewBids = (previousState: BidsState, events: BidEvent[]): BidsState => { + const bids = new Map(previousState.bids) + + events.forEach((event) => handleBid(bids, event.args)) + + return { + bids, + bidList: Array.from(bids.values()).sort(biggerFirst), } - return previousState.bids } const handleBid = (bids: Map, eventArgs: BidEvent['args']) => { diff --git a/packages/frontend/src/providers/BidsProvider/useWatchEvents.ts b/packages/frontend/src/providers/BidsProvider/useWatchEvents.ts index 5b069293..f74043b0 100644 --- a/packages/frontend/src/providers/BidsProvider/useWatchEvents.ts +++ b/packages/frontend/src/providers/BidsProvider/useWatchEvents.ts @@ -1,46 +1,37 @@ -import { parseAbiItem } from 'viem' -import { BidEventsState } from '@/providers/BidsProvider/reduceBids' -import { useBlockNumber, useChainId, useConfig, useWatchContractEvent } from 'wagmi' -import { useQuery } from '@tanstack/react-query' -import { getLogs } from 'viem/actions' -import { AUCTION_ADDRESSES, DEPLOYMENT_BLOCK } from '@/blockchain/auctionAddresses' +import { useChainId, useReadContract, useWatchContractEvent } from 'wagmi' +import { AUCTION_ADDRESSES } from '@/blockchain/auctionAddresses' import { AUCTION_ABI } from '@/blockchain/abi/auction' +import { useEffect } from 'react' +import { ReduceBidsAction } from '@/providers/BidsProvider/reduceBids' -const newBidEvent = parseAbiItem('event NewBid(address bidder, uint256 bidderID, uint256 bidAmount)') - -export const useWatchEvents = (onEvents: (eventsState: BidEventsState) => void) => { +export const useWatchEvents = (dispatch: (eventsState: ReduceBidsAction) => void) => { const chainId = useChainId() - const config = useConfig() - const client = config.getClient({ chainId }) - - const { data: blockNumber, isLoading: isBlockLoading } = useBlockNumber() - const { isLoading: areInitialBidsLoading } = useQuery({ - queryKey: ['bids', chainId], - queryFn: async () => { - const logs = await getLogs(client, { - address: AUCTION_ADDRESSES[chainId], - event: newBidEvent, - fromBlock: DEPLOYMENT_BLOCK[chainId], - toBlock: blockNumber, - }) - onEvents({ events: logs, chainId, startBlock: blockNumber }) - return logs - }, - enabled: !isBlockLoading, - staleTime: Infinity, - gcTime: Infinity, + const { data, isLoading: areInitialBidsLoading } = useReadContract({ + chainId, + abi: AUCTION_ABI, + address: AUCTION_ADDRESSES[chainId], + functionName: 'getBidsWithAddresses', }) + useEffect(() => { + if (!data) { + return + } + dispatch({ + type: 'InitialBids', + bids: data, + }) + }, [data, dispatch]) + useWatchContractEvent({ chainId, abi: AUCTION_ABI, address: AUCTION_ADDRESSES[chainId], - fromBlock: blockNumber, eventName: 'NewBid', - onLogs: (logs) => onEvents({ events: logs, chainId, startBlock: blockNumber }), - enabled: !isBlockLoading && !areInitialBidsLoading, + onLogs: (logs) => dispatch({ type: 'NewBids', events: logs }), + enabled: !areInitialBidsLoading, }) - return { isLoading: isBlockLoading || areInitialBidsLoading } + return { isLoading: areInitialBidsLoading } }