refactor(marketplace): generic querying of historical marketplace events (#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
This commit is contained in:
Eric 2024-08-16 04:55:25 +02:00 committed by GitHub
parent 15303125f6
commit 63ee4ca0f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 69 additions and 53 deletions

View File

@ -347,9 +347,11 @@ method subscribeProofSubmission*(market: OnChainMarket,
method unsubscribe*(subscription: OnChainMarketSubscription) {.async.} = method unsubscribe*(subscription: OnChainMarketSubscription) {.async.} =
await subscription.eventSubscription.unsubscribe() await subscription.eventSubscription.unsubscribe()
method queryPastStorageRequests*(market: OnChainMarket, method queryPastEvents*[T: MarketplaceEvent](
blocksAgo: int): market: OnChainMarket,
Future[seq[PastStorageRequest]] {.async.} = _: type T,
blocksAgo: int): Future[seq[T]] {.async.} =
convertEthersError: convertEthersError:
let contract = market.contract let contract = market.contract
let provider = contract.provider let provider = contract.provider
@ -357,13 +359,6 @@ method queryPastStorageRequests*(market: OnChainMarket,
let head = await provider.getBlockNumber() let head = await provider.getBlockNumber()
let fromBlock = BlockTag.init(head - blocksAgo.abs.u256) let fromBlock = BlockTag.init(head - blocksAgo.abs.u256)
let events = await contract.queryFilter(StorageRequested, return await contract.queryFilter(T,
fromBlock, fromBlock,
BlockTag.latest) BlockTag.latest)
return events.map(event =>
PastStorageRequest(
requestId: event.requestId,
ask: event.ask,
expiry: event.expiry
)
)

View File

@ -16,25 +16,6 @@ export requests
type type
Marketplace* = ref object of Contract 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 config*(marketplace: Marketplace): MarketplaceConfig {.contract, view.}
proc token*(marketplace: Marketplace): Address {.contract, view.} proc token*(marketplace: Marketplace): Address {.contract, view.}

View File

@ -28,11 +28,28 @@ type
OnRequestCancelled* = proc(requestId: RequestId) {.gcsafe, upraises:[].} OnRequestCancelled* = proc(requestId: RequestId) {.gcsafe, upraises:[].}
OnRequestFailed* = proc(requestId: RequestId) {.gcsafe, upraises:[].} OnRequestFailed* = proc(requestId: RequestId) {.gcsafe, upraises:[].}
OnProofSubmitted* = proc(id: SlotId) {.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 requestId*: RequestId
ask*: StorageAsk ask*: StorageAsk
expiry*: UInt256 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.} = method getZkeyHash*(market: Market): Future[?string] {.base, async.} =
raiseAssert("not implemented") raiseAssert("not implemented")
@ -202,7 +219,8 @@ method subscribeProofSubmission*(market: Market,
method unsubscribe*(subscription: Subscription) {.base, async, upraises:[].} = method unsubscribe*(subscription: Subscription) {.base, async, upraises:[].} =
raiseAssert("not implemented") raiseAssert("not implemented")
method queryPastStorageRequests*(market: Market, method queryPastEvents*[T: MarketplaceEvent](
blocksAgo: int): market: Market,
Future[seq[PastStorageRequest]] {.base, async.} = _: type T,
blocksAgo: int): Future[seq[T]] {.base, async.} =
raiseAssert("not implemented") raiseAssert("not implemented")

View File

@ -420,16 +420,21 @@ method subscribeProofSubmission*(mock: MockMarket,
mock.subscriptions.onProofSubmitted.add(subscription) mock.subscriptions.onProofSubmitted.add(subscription)
return subscription return subscription
method queryPastStorageRequests*(market: MockMarket, method queryPastEvents*[T: MarketplaceEvent](
blocksAgo: int): market: MockMarket,
Future[seq[PastStorageRequest]] {.async.} = _: type T,
# MockMarket does not have the concept of blocks, so simply return all blocksAgo: int): Future[seq[T]] {.async.} =
# previous events
return market.requested.map(request => if T of StorageRequested:
PastStorageRequest(requestId: request.id, return market.requested.map(request =>
StorageRequested(requestId: request.id,
ask: request.ask, ask: request.ask,
expiry: request.expiry) expiry: request.expiry)
) )
elif T of SlotFilled:
return market.filled.map(slot =>
SlotFilled(requestId: slot.requestId, slotIndex: slot.slotIndex)
)
method unsubscribe*(subscription: RequestSubscription) {.async.} = method unsubscribe*(subscription: RequestSubscription) {.async.} =
subscription.market.subscriptions.onRequest.keepItIf(it != subscription) subscription.market.subscriptions.onRequest.keepItIf(it != subscription)

View File

@ -324,7 +324,7 @@ ethersuite "On-Chain Market":
let slotId = request.slotId(slotIndex) let slotId = request.slotId(slotIndex)
check (await market.slotState(slotId)) == SlotState.Filled check (await market.slotState(slotId)) == SlotState.Filled
test "can query past events": test "can query past StorageRequested events":
var request1 = StorageRequest.example var request1 = StorageRequest.example
var request2 = StorageRequest.example var request2 = StorageRequest.example
request1.client = accounts[0] request1.client = accounts[0]
@ -335,21 +335,38 @@ ethersuite "On-Chain Market":
# `market.requestStorage` executes an `approve` tx before the # `market.requestStorage` executes an `approve` tx before the
# `requestStorage` tx, so that's two PoA blocks per `requestStorage` call (6 # `requestStorage` tx, so that's two PoA blocks per `requestStorage` call (6
# blocks for 3 calls). `fromBlock` and `toBlock` are inclusive, so to check # blocks for 3 calls). We don't need to check the `approve` for the first
# 6 blocks, we only need to check 5 "blocks ago". We don't need to check the # `requestStorage` call, so we only need to check 5 "blocks ago". "blocks
# `approve` for the first `requestStorage` call, so that's 1 less again = 4 # ago".
# "blocks ago".
proc getsPastRequest(): Future[bool] {.async.} = 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] reqs.mapIt(it.requestId) == @[request.id, request1.id, request2.id]
check eventually await getsPastRequest() 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": test "past event query can specify negative `blocksAgo` parameter":
await market.requestStorage(request) await market.requestStorage(request)
check eventually ( check eventually (
(await market.queryPastStorageRequests(blocksAgo = -2)) == (await market.queryPastEvents(StorageRequested, blocksAgo = -2)) ==
(await market.queryPastStorageRequests(blocksAgo = 2)) (await market.queryPastEvents(StorageRequested, blocksAgo = 2))
) )