Skip to content

Commit

Permalink
🪄 Utilize getBidsWithAddresses function (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
b-tarczynski authored Apr 19, 2024
1 parent eaaac13 commit a0b2fc9
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 50 deletions.
61 changes: 43 additions & 18 deletions packages/frontend/src/providers/BidsProvider/reduceBids.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Bid } from '@/types/bid'
import { Hex } from 'viem'
import { SupportedChainId } from '@/blockchain/chain'

interface BidEvent {
args: {
Expand All @@ -13,41 +12,67 @@ interface BidEvent {
interface BidsState {
bids: Map<Hex, Bid>
bidList: Bid[]
startBlock: bigint | undefined
chainId: SupportedChainId | undefined
}

export const defaultBidsState: BidsState = {
bids: new Map<Hex, Bid>(),
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<Hex, Bid>()
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<Hex, Bid>()
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<Hex, Bid>, eventArgs: BidEvent['args']) => {
Expand Down
55 changes: 23 additions & 32 deletions packages/frontend/src/providers/BidsProvider/useWatchEvents.ts
Original file line number Diff line number Diff line change
@@ -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 }
}

0 comments on commit a0b2fc9

Please sign in to comment.