110 lines
3.8 KiB
Nim
110 lines
3.8 KiB
Nim
import std/sequtils
|
|
import pkg/chronos
|
|
import pkg/questionable
|
|
import pkg/upraises
|
|
import ../errors
|
|
import ../utils/statemachine
|
|
import ../market
|
|
import ../clock
|
|
import ../proving
|
|
import ../contracts/requests
|
|
|
|
export market
|
|
export clock
|
|
export statemachine
|
|
export proving
|
|
|
|
type
|
|
Sales* = ref object
|
|
market*: Market
|
|
clock*: Clock
|
|
subscription*: ?market.Subscription
|
|
available: seq[Availability]
|
|
onStore: ?OnStore
|
|
onProve: ?OnProve
|
|
onClear: ?OnClear
|
|
onSale: ?OnSale
|
|
proving*: Proving
|
|
agents*: seq[SalesAgent]
|
|
SalesAgent* = ref object of StateMachineAsync
|
|
sales*: Sales
|
|
requestId*: RequestId
|
|
ask*: StorageAsk
|
|
availability*: ?Availability # TODO: when availability persistence is added, change this to not optional
|
|
request*: ?StorageRequest
|
|
slotIndex*: UInt256
|
|
failed*: market.Subscription
|
|
fulfilled*: market.Subscription
|
|
slotFilled*: market.Subscription
|
|
cancelled*: Future[void]
|
|
SaleState* = ref object of AsyncState
|
|
SaleError* = ref object of CodexError
|
|
Availability* = object
|
|
id*: array[32, byte]
|
|
size*: UInt256
|
|
duration*: UInt256
|
|
minPrice*: UInt256
|
|
AvailabilityChange* = proc(availability: Availability) {.gcsafe, upraises: [].}
|
|
# TODO: when availability changes introduced, make availability non-optional (if we need to keep it at all)
|
|
RequestEvent* = proc(state: SaleState, request: StorageRequest): Future[void] {.gcsafe, upraises: [].}
|
|
OnStore* = proc(request: StorageRequest,
|
|
slot: UInt256,
|
|
availability: ?Availability): Future[void] {.gcsafe, upraises: [].}
|
|
OnProve* = proc(request: StorageRequest,
|
|
slot: UInt256): Future[seq[byte]] {.gcsafe, upraises: [].}
|
|
OnClear* = proc(availability: ?Availability,# TODO: when availability changes introduced, make availability non-optional (if we need to keep it at all)
|
|
request: StorageRequest,
|
|
slotIndex: UInt256) {.gcsafe, upraises: [].}
|
|
OnSale* = proc(availability: ?Availability, # TODO: when availability changes introduced, make availability non-optional (if we need to keep it at all)
|
|
request: StorageRequest,
|
|
slotIndex: UInt256) {.gcsafe, upraises: [].}
|
|
|
|
proc `onStore=`*(sales: Sales, onStore: OnStore) =
|
|
sales.onStore = some onStore
|
|
|
|
proc `onProve=`*(sales: Sales, onProve: OnProve) =
|
|
sales.onProve = some onProve
|
|
|
|
proc `onClear=`*(sales: Sales, onClear: OnClear) =
|
|
sales.onClear = some onClear
|
|
|
|
proc `onSale=`*(sales: Sales, callback: OnSale) =
|
|
sales.onSale = some callback
|
|
|
|
proc onStore*(sales: Sales): ?OnStore = sales.onStore
|
|
|
|
proc onProve*(sales: Sales): ?OnProve = sales.onProve
|
|
|
|
proc onClear*(sales: Sales): ?OnClear = sales.onClear
|
|
|
|
proc onSale*(sales: Sales): ?OnSale = sales.onSale
|
|
|
|
proc available*(sales: Sales): seq[Availability] = sales.available
|
|
|
|
func add*(sales: Sales, availability: Availability) =
|
|
if not sales.available.contains(availability):
|
|
sales.available.add(availability)
|
|
# TODO: add to disk (persist), serialise to json.
|
|
|
|
func remove*(sales: Sales, availability: Availability) =
|
|
sales.available.keepItIf(it != availability)
|
|
# TODO: remove from disk availability, mark as in use by assigning
|
|
# a slotId, so that it can be used for restoration (node restart)
|
|
|
|
func findAvailability*(sales: Sales, ask: StorageAsk): ?Availability =
|
|
for availability in sales.available:
|
|
if ask.slotSize <= availability.size and
|
|
ask.duration <= availability.duration and
|
|
ask.pricePerSlot >= availability.minPrice:
|
|
return some availability
|
|
|
|
method onCancelled*(state: SaleState, request: StorageRequest) {.base, async.} =
|
|
discard
|
|
|
|
method onFailed*(state: SaleState, request: StorageRequest) {.base, async.} =
|
|
discard
|
|
|
|
method onSlotFilled*(state: SaleState, requestId: RequestId,
|
|
slotIndex: UInt256) {.base, async.} =
|
|
discard
|