193 lines
5.2 KiB
Nim
193 lines
5.2 KiB
Nim
import std/hashes
|
|
import std/typetraits
|
|
import pkg/contractabi
|
|
import pkg/nimcrypto
|
|
import pkg/ethers/fields
|
|
import pkg/questionable/results
|
|
import pkg/stew/byteutils
|
|
import pkg/json_serialization
|
|
import pkg/upraises
|
|
import ../utils/json
|
|
|
|
export contractabi
|
|
|
|
type
|
|
StorageRequest* = object
|
|
client* {.serialize.}: Address
|
|
ask* {.serialize.}: StorageAsk
|
|
content* {.serialize.}: StorageContent
|
|
expiry* {.serialize.}: UInt256
|
|
nonce*: Nonce
|
|
StorageAsk* = object
|
|
slots* {.serialize.}: uint64
|
|
slotSize* {.serialize.}: UInt256
|
|
duration* {.serialize.}: UInt256
|
|
proofProbability* {.serialize.}: UInt256
|
|
reward* {.serialize.}: UInt256
|
|
collateral* {.serialize.}: UInt256
|
|
maxSlotLoss* {.serialize.}: uint64
|
|
StorageContent* = object
|
|
cid* {.serialize.}: string
|
|
merkleRoot*: array[32, byte]
|
|
Slot* = object
|
|
request* {.serialize.}: StorageRequest
|
|
slotIndex* {.serialize.}: UInt256
|
|
SlotId* = distinct array[32, byte]
|
|
RequestId* = distinct array[32, byte]
|
|
Nonce* = distinct array[32, byte]
|
|
RequestState* {.pure.} = enum
|
|
New
|
|
Started
|
|
Cancelled
|
|
Finished
|
|
Failed
|
|
SlotState* {.pure.} = enum
|
|
Free
|
|
Filled
|
|
Finished
|
|
Failed
|
|
Paid
|
|
Cancelled
|
|
|
|
proc `==`*(x, y: Nonce): bool {.borrow.}
|
|
proc `==`*(x, y: RequestId): bool {.borrow.}
|
|
proc `==`*(x, y: SlotId): bool {.borrow.}
|
|
proc hash*(x: SlotId): Hash {.borrow.}
|
|
proc hash*(x: Nonce): Hash {.borrow.}
|
|
proc hash*(x: Address): Hash {.borrow.}
|
|
|
|
func toArray*(id: RequestId | SlotId | Nonce): array[32, byte] =
|
|
array[32, byte](id)
|
|
|
|
proc `$`*(id: RequestId | SlotId | Nonce): string =
|
|
id.toArray.toHex
|
|
|
|
proc fromHex*(T: type RequestId, hex: string): T =
|
|
T array[32, byte].fromHex(hex)
|
|
|
|
proc fromHex*(T: type SlotId, hex: string): T =
|
|
T array[32, byte].fromHex(hex)
|
|
|
|
proc fromHex*(T: type Nonce, hex: string): T =
|
|
T array[32, byte].fromHex(hex)
|
|
|
|
proc fromHex*[T: distinct](_: type T, hex: string): T =
|
|
type baseType = T.distinctBase
|
|
T baseType.fromHex(hex)
|
|
|
|
proc toHex*[T: distinct](id: T): string =
|
|
type baseType = T.distinctBase
|
|
baseType(id).toHex
|
|
|
|
func fromTuple(_: type StorageRequest, tupl: tuple): StorageRequest =
|
|
StorageRequest(
|
|
client: tupl[0],
|
|
ask: tupl[1],
|
|
content: tupl[2],
|
|
expiry: tupl[3],
|
|
nonce: tupl[4]
|
|
)
|
|
|
|
func fromTuple(_: type Slot, tupl: tuple): Slot =
|
|
Slot(
|
|
request: tupl[0],
|
|
slotIndex: tupl[1]
|
|
)
|
|
|
|
func fromTuple(_: type StorageAsk, tupl: tuple): StorageAsk =
|
|
StorageAsk(
|
|
slots: tupl[0],
|
|
slotSize: tupl[1],
|
|
duration: tupl[2],
|
|
proofProbability: tupl[3],
|
|
reward: tupl[4],
|
|
collateral: tupl[5],
|
|
maxSlotLoss: tupl[6]
|
|
)
|
|
|
|
func fromTuple(_: type StorageContent, tupl: tuple): StorageContent =
|
|
StorageContent(
|
|
cid: tupl[0],
|
|
merkleRoot: tupl[1]
|
|
)
|
|
|
|
func solidityType*(_: type StorageContent): string =
|
|
solidityType(StorageContent.fieldTypes)
|
|
|
|
func solidityType*(_: type StorageAsk): string =
|
|
solidityType(StorageAsk.fieldTypes)
|
|
|
|
func solidityType*(_: type StorageRequest): string =
|
|
solidityType(StorageRequest.fieldTypes)
|
|
|
|
func encode*(encoder: var AbiEncoder, content: StorageContent) =
|
|
encoder.write(content.fieldValues)
|
|
|
|
func encode*(encoder: var AbiEncoder, ask: StorageAsk) =
|
|
encoder.write(ask.fieldValues)
|
|
|
|
func encode*(encoder: var AbiEncoder, id: RequestId | SlotId | Nonce) =
|
|
encoder.write(id.toArray)
|
|
|
|
func encode*(encoder: var AbiEncoder, request: StorageRequest) =
|
|
encoder.write(request.fieldValues)
|
|
|
|
func encode*(encoder: var AbiEncoder, request: Slot) =
|
|
encoder.write(request.fieldValues)
|
|
|
|
func decode*(decoder: var AbiDecoder, T: type StorageContent): ?!T =
|
|
let tupl = ?decoder.read(StorageContent.fieldTypes)
|
|
success StorageContent.fromTuple(tupl)
|
|
|
|
func decode*(decoder: var AbiDecoder, T: type StorageAsk): ?!T =
|
|
let tupl = ?decoder.read(StorageAsk.fieldTypes)
|
|
success StorageAsk.fromTuple(tupl)
|
|
|
|
func decode*(decoder: var AbiDecoder, T: type StorageRequest): ?!T =
|
|
let tupl = ?decoder.read(StorageRequest.fieldTypes)
|
|
success StorageRequest.fromTuple(tupl)
|
|
|
|
func decode*(decoder: var AbiDecoder, T: type Slot): ?!T =
|
|
let tupl = ?decoder.read(Slot.fieldTypes)
|
|
success Slot.fromTuple(tupl)
|
|
|
|
func id*(request: StorageRequest): RequestId =
|
|
let encoding = AbiEncoder.encode((request, ))
|
|
RequestId(keccak256.digest(encoding).data)
|
|
|
|
func slotId*(requestId: RequestId, slot: UInt256): SlotId =
|
|
let encoding = AbiEncoder.encode((requestId, slot))
|
|
SlotId(keccak256.digest(encoding).data)
|
|
|
|
func slotId*(request: StorageRequest, slot: UInt256): SlotId =
|
|
slotId(request.id, slot)
|
|
|
|
func id*(slot: Slot): SlotId =
|
|
slotId(slot.request, slot.slotIndex)
|
|
|
|
func pricePerSlot*(ask: StorageAsk): UInt256 =
|
|
ask.duration * ask.reward
|
|
|
|
func price*(ask: StorageAsk): UInt256 =
|
|
ask.slots.u256 * ask.pricePerSlot
|
|
|
|
func price*(request: StorageRequest): UInt256 =
|
|
request.ask.price
|
|
|
|
func size*(ask: StorageAsk): UInt256 =
|
|
ask.slots.u256 * ask.slotSize
|
|
|
|
proc writeValue*(
|
|
writer: var JsonWriter,
|
|
value: SlotId | RequestId) {.upraises:[IOError].} =
|
|
|
|
mixin writeValue
|
|
writer.writeValue value.toArray
|
|
|
|
proc readValue*[T: SlotId | RequestId](
|
|
reader: var JsonReader,
|
|
value: var T) {.upraises: [SerializationError, IOError].} =
|
|
|
|
mixin readValue
|
|
value = T reader.readValue(T.distinctBase)
|