Skip to content

Commit

Permalink
refactor(marketplace): generic querying of historical marketplace eve…
Browse files Browse the repository at this point in the history
…nts (#872)

* refactor(marketplace): move marketplace events to the Market abstraction

Move marketplace contract events to the Market abstraction so the types can be shared across all modules that call the Market abstraction.

* Remove unneeded conversion

* Switch to generic implementation of event querying

* change parent type to MarketplaceEvent
  • Loading branch information
emizzle authored Aug 16, 2024
1 parent 1530312 commit 63ee4ca
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 53 deletions.
21 changes: 8 additions & 13 deletions codex/contracts/market.nim
Original file line number Diff line number Diff line change
Expand Up @@ -347,23 +347,18 @@ method subscribeProofSubmission*(market: OnChainMarket,
method unsubscribe*(subscription: OnChainMarketSubscription) {.async.} =
await subscription.eventSubscription.unsubscribe()

method queryPastStorageRequests*(market: OnChainMarket,
blocksAgo: int):
Future[seq[PastStorageRequest]] {.async.} =
method queryPastEvents*[T: MarketplaceEvent](
market: OnChainMarket,
_: type T,
blocksAgo: int): Future[seq[T]] {.async.} =

convertEthersError:
let contract = market.contract
let provider = contract.provider

let head = await provider.getBlockNumber()
let fromBlock = BlockTag.init(head - blocksAgo.abs.u256)

let events = await contract.queryFilter(StorageRequested,
fromBlock,
BlockTag.latest)
return events.map(event =>
PastStorageRequest(
requestId: event.requestId,
ask: event.ask,
expiry: event.expiry
)
)
return await contract.queryFilter(T,
fromBlock,
BlockTag.latest)
19 changes: 0 additions & 19 deletions codex/contracts/marketplace.nim
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,6 @@ export requests

type
Marketplace* = ref object of Contract
StorageRequested* = object of Event
requestId*: RequestId
ask*: StorageAsk
expiry*: UInt256
SlotFilled* = object of Event
requestId* {.indexed.}: RequestId
slotIndex*: UInt256
SlotFreed* = object of Event
requestId* {.indexed.}: RequestId
slotIndex*: UInt256
RequestFulfilled* = object of Event
requestId* {.indexed.}: RequestId
RequestCancelled* = object of Event
requestId* {.indexed.}: RequestId
RequestFailed* = object of Event
requestId* {.indexed.}: RequestId
ProofSubmitted* = object of Event
id*: SlotId


proc config*(marketplace: Marketplace): MarketplaceConfig {.contract, view.}
proc token*(marketplace: Marketplace): Address {.contract, view.}
Expand Down
28 changes: 23 additions & 5 deletions codex/market.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,28 @@ type
OnRequestCancelled* = proc(requestId: RequestId) {.gcsafe, upraises:[].}
OnRequestFailed* = proc(requestId: RequestId) {.gcsafe, upraises:[].}
OnProofSubmitted* = proc(id: SlotId) {.gcsafe, upraises:[].}
PastStorageRequest* = object
ProofChallenge* = array[32, byte]

# Marketplace events -- located here due to the Market abstraction
MarketplaceEvent* = Event
StorageRequested* = object of MarketplaceEvent
requestId*: RequestId
ask*: StorageAsk
expiry*: UInt256
ProofChallenge* = array[32, byte]
SlotFilled* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
slotIndex*: UInt256
SlotFreed* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
slotIndex*: UInt256
RequestFulfilled* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
RequestCancelled* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
RequestFailed* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
ProofSubmitted* = object of MarketplaceEvent
id*: SlotId

method getZkeyHash*(market: Market): Future[?string] {.base, async.} =
raiseAssert("not implemented")
Expand Down Expand Up @@ -202,7 +219,8 @@ method subscribeProofSubmission*(market: Market,
method unsubscribe*(subscription: Subscription) {.base, async, upraises:[].} =
raiseAssert("not implemented")

method queryPastStorageRequests*(market: Market,
blocksAgo: int):
Future[seq[PastStorageRequest]] {.base, async.} =
method queryPastEvents*[T: MarketplaceEvent](
market: Market,
_: type T,
blocksAgo: int): Future[seq[T]] {.base, async.} =
raiseAssert("not implemented")
21 changes: 13 additions & 8 deletions tests/codex/helpers/mockmarket.nim
Original file line number Diff line number Diff line change
Expand Up @@ -420,16 +420,21 @@ method subscribeProofSubmission*(mock: MockMarket,
mock.subscriptions.onProofSubmitted.add(subscription)
return subscription

method queryPastStorageRequests*(market: MockMarket,
blocksAgo: int):
Future[seq[PastStorageRequest]] {.async.} =
# MockMarket does not have the concept of blocks, so simply return all
# previous events
return market.requested.map(request =>
PastStorageRequest(requestId: request.id,
method queryPastEvents*[T: MarketplaceEvent](
market: MockMarket,
_: type T,
blocksAgo: int): Future[seq[T]] {.async.} =

if T of StorageRequested:
return market.requested.map(request =>
StorageRequested(requestId: request.id,
ask: request.ask,
expiry: request.expiry)
)
)
elif T of SlotFilled:
return market.filled.map(slot =>
SlotFilled(requestId: slot.requestId, slotIndex: slot.slotIndex)
)

method unsubscribe*(subscription: RequestSubscription) {.async.} =
subscription.market.subscriptions.onRequest.keepItIf(it != subscription)
Expand Down
33 changes: 25 additions & 8 deletions tests/contracts/testMarket.nim
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ ethersuite "On-Chain Market":
let slotId = request.slotId(slotIndex)
check (await market.slotState(slotId)) == SlotState.Filled

test "can query past events":
test "can query past StorageRequested events":
var request1 = StorageRequest.example
var request2 = StorageRequest.example
request1.client = accounts[0]
Expand All @@ -335,21 +335,38 @@ ethersuite "On-Chain Market":

# `market.requestStorage` executes an `approve` tx before the
# `requestStorage` tx, so that's two PoA blocks per `requestStorage` call (6
# blocks for 3 calls). `fromBlock` and `toBlock` are inclusive, so to check
# 6 blocks, we only need to check 5 "blocks ago". We don't need to check the
# `approve` for the first `requestStorage` call, so that's 1 less again = 4
# "blocks ago".
# blocks for 3 calls). We don't need to check the `approve` for the first
# `requestStorage` call, so we only need to check 5 "blocks ago". "blocks
# ago".

proc getsPastRequest(): Future[bool] {.async.} =
let reqs = await market.queryPastStorageRequests(5)
let reqs = await market.queryPastEvents(StorageRequested, 5)
reqs.mapIt(it.requestId) == @[request.id, request1.id, request2.id]

check eventually await getsPastRequest()

test "can query past SlotFilled events":
await market.requestStorage(request)
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateral)
await market.fillSlot(request.id, 1.u256, proof, request.ask.collateral)
await market.fillSlot(request.id, 2.u256, proof, request.ask.collateral)
let slotId = request.slotId(slotIndex)

# `market.fill` executes an `approve` tx before the `fillSlot` tx, so that's
# two PoA blocks per `fillSlot` call (6 blocks for 3 calls). We don't need
# to check the `approve` for the first `fillSlot` call, so we only need to
# check 5 "blocks ago".
let events = await market.queryPastEvents(SlotFilled, 5)
check events == @[
SlotFilled(requestId: request.id, slotIndex: 0.u256),
SlotFilled(requestId: request.id, slotIndex: 1.u256),
SlotFilled(requestId: request.id, slotIndex: 2.u256),
]

test "past event query can specify negative `blocksAgo` parameter":
await market.requestStorage(request)

check eventually (
(await market.queryPastStorageRequests(blocksAgo = -2)) ==
(await market.queryPastStorageRequests(blocksAgo = 2))
(await market.queryPastEvents(StorageRequested, blocksAgo = -2)) ==
(await market.queryPastEvents(StorageRequested, blocksAgo = 2))
)

0 comments on commit 63ee4ca

Please sign in to comment.