131 lines
4.0 KiB
Nim
Raw Permalink Normal View History

import pkg/ethers
import pkg/questionable
2025-03-20 15:27:17 +01:00
import pkg/upraises
import ./marketplace/market
import ./marketplace/marketplace
import ../config
2025-03-18 14:55:52 +01:00
import ../component
import ../state
2025-03-20 15:27:17 +01:00
import ../types
import ./clock
2025-03-18 14:55:52 +01:00
logScope:
topics = "marketplace"
2025-03-20 15:27:17 +01:00
type
MarketplaceService* = ref object of Component
state: State
market: ?OnChainMarket
clock: Clock
2025-03-21 09:41:05 +01:00
2025-03-20 15:27:17 +01:00
OnNewRequest* = proc(id: Rid): Future[?!void] {.async: (raises: []), gcsafe.}
2025-03-20 16:20:37 +01:00
RequestInfo* = ref object
pending*: bool
2025-03-20 16:20:37 +01:00
slots*: uint64
slotSize*: uint64
pricePerBytePerSecond*: uint64
2025-03-20 15:27:17 +01:00
proc notStarted() =
raiseAssert("MarketplaceService was called before it was started.")
2025-03-21 09:41:05 +01:00
proc fetchRequestInfo(
market: OnChainMarket, rid: Rid
): Future[?RequestInfo] {.async: (raises: []).} =
2025-03-20 16:20:37 +01:00
try:
let request = await market.getRequest(rid)
if r =? request:
let price = r.ask.pricePerBytePerSecond.truncate(uint64)
return some(
RequestInfo(
pending: false,
slots: r.ask.slots,
slotSize: r.ask.slotSize,
pricePerBytePerSecond: price,
)
)
2025-03-20 16:20:37 +01:00
except CatchableError as exc:
trace "Failed to get request info", err = exc.msg
return none(RequestInfo)
2025-03-21 09:41:05 +01:00
method subscribeToNewRequests*(
m: MarketplaceService, onNewRequest: OnNewRequest
): Future[?!void] {.async: (raises: []), base.} =
2025-06-02 14:30:28 +02:00
proc resultWrapper(rid: Rid): Future[void] {.async: (raises: [CancelledError]).} =
2025-03-20 15:27:17 +01:00
let response = await onNewRequest(rid)
if error =? response.errorOption:
raiseAssert("Error result in handling of onNewRequest callback: " & error.msg)
2025-03-21 09:41:05 +01:00
proc onRequest(
id: RequestId, ask: StorageAsk, expiry: uint64
) {.gcsafe, upraises: [].} =
2025-03-20 15:27:17 +01:00
asyncSpawn resultWrapper(Rid(id))
if market =? m.market:
try:
2025-03-20 15:27:17 +01:00
discard await market.subscribeRequests(onRequest)
return success()
2025-03-20 15:27:17 +01:00
except CatchableError as exc:
return failure(exc.msg)
else:
notStarted()
2025-03-21 09:41:05 +01:00
method iteratePastNewRequestEvents*(
m: MarketplaceService, onNewRequest: OnNewRequest
): Future[?!void] {.async: (raises: []), base.} =
2025-03-20 15:27:17 +01:00
let
oneDay = 60 * 60 * 24
timespan = oneDay * 30
startTime = m.clock.now() - timespan.uint64
2025-03-18 14:55:52 +01:00
2025-03-20 15:27:17 +01:00
if market =? m.market:
try:
2025-03-26 12:56:52 +01:00
let requests =
await market.queryPastStorageRequestedEventsFromTime(startTime.int64)
2025-03-20 15:27:17 +01:00
for request in requests:
if error =? (await onNewRequest(Rid(request.requestId))).errorOption:
return failure(error.msg)
return success()
2025-03-20 15:27:17 +01:00
except CatchableError as exc:
return failure(exc.msg)
else:
notStarted()
2025-03-19 15:25:17 +01:00
2025-03-21 09:41:05 +01:00
method getRequestInfo*(
m: MarketplaceService, rid: Rid
): Future[?RequestInfo] {.async: (raises: []), base.} =
2025-03-20 16:20:37 +01:00
# If the request id exists and is running, fetch the request object and return the info object.
# otherwise, return none.
if market =? m.market:
try:
let state = await market.requestState(rid)
if s =? state:
if s == RequestState.New:
return some(RequestInfo(pending: true))
2025-03-20 16:20:37 +01:00
if s == RequestState.Started:
return await market.fetchRequestInfo(rid)
except CatchableError as exc:
trace "Failed to get request state", err = exc.msg
return none(RequestInfo)
else:
notStarted()
2025-06-02 16:16:41 +02:00
method awake*(
m: MarketplaceService
): Future[?!void] {.async: (raises: [CancelledError]).} =
2025-06-02 15:00:32 +02:00
try:
let provider = JsonRpcProvider.new(m.state.config.ethProvider)
without marketplaceAddress =? Address.init(m.state.config.marketplaceAddress):
return failure("Invalid MarketplaceAddress provided")
2025-06-02 15:00:32 +02:00
let marketplace = Marketplace.new(marketplaceAddress, provider)
m.market = some(OnChainMarket.new(marketplace))
return success()
except JsonRpcProviderError as err:
return failure(err.msg)
2025-03-18 14:55:52 +01:00
2025-03-20 15:27:17 +01:00
proc new(T: type MarketplaceService, state: State, clock: Clock): MarketplaceService =
return MarketplaceService(state: state, market: none(OnChainMarket), clock: clock)
2025-03-18 14:55:52 +01:00
2025-03-20 15:27:17 +01:00
proc createMarketplace*(state: State, clock: Clock): MarketplaceService =
return MarketplaceService.new(state, clock)