129 lines
4.1 KiB
Nim
129 lines
4.1 KiB
Nim
import std/sequtils
|
|
import std/heapqueue
|
|
import pkg/questionable
|
|
import pkg/dagger/market
|
|
|
|
export market
|
|
|
|
type
|
|
MockMarket* = ref object of Market
|
|
requested*: seq[StorageRequest]
|
|
offered*: seq[StorageOffer]
|
|
selected*: seq[array[32, byte]]
|
|
subscriptions: Subscriptions
|
|
time: UInt256
|
|
waiting: HeapQueue[Expiry]
|
|
Subscriptions = object
|
|
onRequest: seq[RequestSubscription]
|
|
onOffer: seq[OfferSubscription]
|
|
onSelect: seq[SelectSubscription]
|
|
RequestSubscription* = ref object of Subscription
|
|
market: MockMarket
|
|
callback: OnRequest
|
|
OfferSubscription* = ref object of Subscription
|
|
market: MockMarket
|
|
requestId: array[32, byte]
|
|
callback: OnOffer
|
|
SelectSubscription* = ref object of Subscription
|
|
market: MockMarket
|
|
requestId: array[32, byte]
|
|
callback: OnSelect
|
|
Expiry = object
|
|
future: Future[void]
|
|
expiry: UInt256
|
|
|
|
method requestStorage*(market: MockMarket,
|
|
request: StorageRequest):
|
|
Future[StorageRequest] {.async.} =
|
|
market.requested.add(request)
|
|
let subscriptions = market.subscriptions.onRequest
|
|
for subscription in subscriptions:
|
|
subscription.callback(request.id, request.ask)
|
|
return request
|
|
|
|
method offerStorage*(market: MockMarket,
|
|
offer: StorageOffer):
|
|
Future[StorageOffer] {.async.} =
|
|
market.offered.add(offer)
|
|
let subscriptions = market.subscriptions.onOffer
|
|
for subscription in subscriptions:
|
|
if subscription.requestId == offer.requestId:
|
|
subscription.callback(offer)
|
|
return offer
|
|
|
|
proc findOffer(market: MockMarket, id: array[32, byte]): ?StorageOffer =
|
|
for offer in market.offered:
|
|
if offer.id == id:
|
|
return some offer
|
|
|
|
method selectOffer*(market: MockMarket, id: array[32, byte]) {.async.} =
|
|
market.selected.add(id)
|
|
let subscriptions = market.subscriptions.onSelect
|
|
for subscription in subscriptions:
|
|
if offer =? market.findOffer(id):
|
|
if subscription.requestId == offer.requestId:
|
|
subscription.callback(id)
|
|
|
|
method subscribeRequests*(market: MockMarket,
|
|
callback: OnRequest):
|
|
Future[Subscription] {.async.} =
|
|
let subscription = RequestSubscription(
|
|
market: market,
|
|
callback: callback
|
|
)
|
|
market.subscriptions.onRequest.add(subscription)
|
|
return subscription
|
|
|
|
method subscribeOffers*(market: MockMarket,
|
|
requestId: array[32, byte],
|
|
callback: OnOffer):
|
|
Future[Subscription] {.async.} =
|
|
let subscription = OfferSubscription(
|
|
market: market,
|
|
requestId: requestId,
|
|
callback: callback
|
|
)
|
|
market.subscriptions.onOffer.add(subscription)
|
|
return subscription
|
|
|
|
method subscribeSelection*(market: MockMarket,
|
|
requestId: array[32, byte],
|
|
callback: OnSelect):
|
|
Future[Subscription] {.async.} =
|
|
let subscription = SelectSubscription(
|
|
market: market,
|
|
requestId: requestId,
|
|
callback: callback
|
|
)
|
|
market.subscriptions.onSelect.add(subscription)
|
|
return subscription
|
|
|
|
method unsubscribe*(subscription: RequestSubscription) {.async.} =
|
|
subscription.market.subscriptions.onRequest.keepItIf(it != subscription)
|
|
|
|
method unsubscribe*(subscription: OfferSubscription) {.async.} =
|
|
subscription.market.subscriptions.onOffer.keepItIf(it != subscription)
|
|
|
|
method unsubscribe*(subscription: SelectSubscription) {.async.} =
|
|
subscription.market.subscriptions.onSelect.keepItIf(it != subscription)
|
|
|
|
func `<`(a, b: Expiry): bool =
|
|
a.expiry < b.expiry
|
|
|
|
method getTime*(market: MockMarket): Future[UInt256] {.async.} =
|
|
return market.time
|
|
|
|
method waitUntil*(market: MockMarket, expiry: UInt256): Future[void] =
|
|
let future = Future[void]()
|
|
if expiry > market.time:
|
|
market.waiting.push(Expiry(future: future, expiry: expiry))
|
|
else:
|
|
future.complete()
|
|
future
|
|
|
|
proc advanceTimeTo*(market: MockMarket, time: UInt256) =
|
|
doAssert(time >= market.time)
|
|
market.time = time
|
|
while market.waiting.len > 0 and market.waiting[0].expiry <= time:
|
|
market.waiting.pop().future.complete()
|