Update to latest dagger-contracts (#78)
- StorageRequest struct has changed - StorageRequested event has changed, it no longer returns the entire request, but only the id and the ask
This commit is contained in:
parent
168468a3fd
commit
1a3003e043
|
@ -59,7 +59,7 @@ method subscribeRequests(market: OnChainMarket,
|
|||
callback: OnRequest):
|
||||
Future[MarketSubscription] {.async.} =
|
||||
proc onEvent(event: StorageRequested) {.upraises:[].} =
|
||||
callback(event.request)
|
||||
callback(event.requestId, event.ask)
|
||||
let subscription = await market.contract.subscribe(StorageRequested, onEvent)
|
||||
return OnChainMarketSubscription(eventSubscription: subscription)
|
||||
|
||||
|
|
|
@ -8,36 +8,116 @@ export contractabi
|
|||
type
|
||||
StorageRequest* = object
|
||||
client*: Address
|
||||
duration*: UInt256
|
||||
size*: UInt256
|
||||
contentHash*: array[32, byte]
|
||||
proofProbability*: UInt256
|
||||
maxPrice*: UInt256
|
||||
ask*: StorageAsk
|
||||
content*: StorageContent
|
||||
expiry*: UInt256
|
||||
nonce*: array[32, byte]
|
||||
StorageAsk* = object
|
||||
size*: UInt256
|
||||
duration*: UInt256
|
||||
proofProbability*: UInt256
|
||||
maxPrice*: UInt256
|
||||
StorageContent* = object
|
||||
cid*: string
|
||||
erasure*: StorageErasure
|
||||
por*: StoragePoR
|
||||
StorageErasure* = object
|
||||
totalChunks*: uint64
|
||||
totalNodes*: uint64
|
||||
nodeId*: uint64
|
||||
StoragePoR* = object
|
||||
u*: seq[byte]
|
||||
publicKey*: seq[byte]
|
||||
name*: seq[byte]
|
||||
|
||||
func fromTuple(_: type StorageRequest, tupl: tuple): StorageRequest =
|
||||
StorageRequest(
|
||||
client: tupl[0],
|
||||
duration: tupl[1],
|
||||
size: tupl[2],
|
||||
contentHash: tupl[3],
|
||||
proofProbability: tupl[4],
|
||||
maxPrice: tupl[5],
|
||||
expiry: tupl[6],
|
||||
nonce: tupl[7]
|
||||
ask: tupl[1],
|
||||
content: tupl[2],
|
||||
expiry: tupl[3],
|
||||
nonce: tupl[4]
|
||||
)
|
||||
|
||||
func fromTuple(_: type StorageAsk, tupl: tuple): StorageAsk =
|
||||
StorageAsk(
|
||||
size: tupl[0],
|
||||
duration: tupl[1],
|
||||
proofProbability: tupl[2],
|
||||
maxPrice: tupl[3]
|
||||
)
|
||||
|
||||
func fromTuple(_: type StorageContent, tupl: tuple): StorageContent =
|
||||
StorageContent(
|
||||
cid: tupl[0],
|
||||
erasure: tupl[1],
|
||||
por: tupl[2]
|
||||
)
|
||||
|
||||
func fromTuple(_: type StorageErasure, tupl: tuple): StorageErasure =
|
||||
StorageErasure(
|
||||
totalChunks: tupl[0],
|
||||
totalNodes: tupl[1],
|
||||
nodeId: tupl[2]
|
||||
)
|
||||
|
||||
func fromTuple(_: type StoragePoR, tupl: tuple): StoragePoR =
|
||||
StoragePoR(
|
||||
u: tupl[0],
|
||||
publicKey: tupl[1],
|
||||
name: tupl[2]
|
||||
)
|
||||
|
||||
func solidityType*(_: type StoragePoR): string =
|
||||
solidityType(StoragePoR.fieldTypes)
|
||||
|
||||
func solidityType*(_: type StorageErasure): string =
|
||||
solidityType(StorageErasure.fieldTypes)
|
||||
|
||||
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, por: StoragePoR) =
|
||||
encoder.write(por.fieldValues)
|
||||
|
||||
func encode*(encoder: var AbiEncoder, erasure: StorageErasure) =
|
||||
encoder.write(erasure.fieldValues)
|
||||
|
||||
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, request: StorageRequest) =
|
||||
encoder.write(request.fieldValues)
|
||||
|
||||
func decode*(decoder: var AbiDecoder, T: type StoragePoR): ?!T =
|
||||
let tupl = ?decoder.read(StoragePoR.fieldTypes)
|
||||
success StoragePoR.fromTuple(tupl)
|
||||
|
||||
func decode*(decoder: var AbiDecoder, T: type StorageErasure): ?!T =
|
||||
let tupl = ?decoder.read(StorageErasure.fieldTypes)
|
||||
success StorageErasure.fromTuple(tupl)
|
||||
|
||||
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 id*(request: StorageRequest): array[32, byte] =
|
||||
let encoding = AbiEncoder.encode(request)
|
||||
let encoding = AbiEncoder.encode((request, ))
|
||||
keccak256.digest(encoding).data
|
||||
|
|
|
@ -13,7 +13,7 @@ type
|
|||
Id = array[32, byte]
|
||||
StorageRequested* = object of Event
|
||||
requestId*: Id
|
||||
request*: StorageRequest
|
||||
ask*: StorageAsk
|
||||
StorageOffered* = object of Event
|
||||
offerId*: Id
|
||||
offer*: StorageOffer
|
||||
|
|
|
@ -10,7 +10,7 @@ export offers
|
|||
type
|
||||
Market* = ref object of RootObj
|
||||
Subscription* = ref object of RootObj
|
||||
OnRequest* = proc(request: StorageRequest) {.gcsafe, upraises:[].}
|
||||
OnRequest* = proc(id: array[32, byte], ask: StorageAsk) {.gcsafe, upraises:[].}
|
||||
OnOffer* = proc(offer: StorageOffer) {.gcsafe, upraises:[].}
|
||||
OnSelect* = proc(offerId: array[32, byte]) {.gcsafe, upraises: [].}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ proc new*(_: type Purchasing, market: Market): Purchasing =
|
|||
|
||||
proc populate*(purchasing: Purchasing, request: StorageRequest): StorageRequest =
|
||||
result = request
|
||||
if result.proofProbability == 0.u256:
|
||||
result.proofProbability = purchasing.proofProbability
|
||||
if result.ask.proofProbability == 0.u256:
|
||||
result.ask.proofProbability = purchasing.proofProbability
|
||||
if result.expiry == 0.u256:
|
||||
result.expiry = (getTime().toUnix().u256 + purchasing.requestExpiryInterval)
|
||||
if result.nonce == array[32, byte].default:
|
||||
|
|
|
@ -24,7 +24,8 @@ type
|
|||
minPrice*: UInt256
|
||||
Negotiation = ref object
|
||||
sales: Sales
|
||||
request: StorageRequest
|
||||
requestId: array[32, byte]
|
||||
ask: StorageAsk
|
||||
availability: Availability
|
||||
offer: ?StorageOffer
|
||||
subscription: ?Subscription
|
||||
|
@ -52,17 +53,17 @@ func add*(sales: Sales, availability: Availability) =
|
|||
func remove*(sales: Sales, availability: Availability) =
|
||||
sales.available.keepItIf(it != availability)
|
||||
|
||||
func findAvailability(sales: Sales, request: StorageRequest): ?Availability =
|
||||
func findAvailability(sales: Sales, ask: StorageAsk): ?Availability =
|
||||
for availability in sales.available:
|
||||
if request.size <= availability.size.u256 and
|
||||
request.duration <= availability.duration.u256 and
|
||||
request.maxPrice >= availability.minPrice:
|
||||
if ask.size <= availability.size.u256 and
|
||||
ask.duration <= availability.duration.u256 and
|
||||
ask.maxPrice >= availability.minPrice:
|
||||
return some availability
|
||||
|
||||
proc createOffer(negotiation: Negotiation): StorageOffer =
|
||||
StorageOffer(
|
||||
requestId: negotiation.request.id,
|
||||
price: negotiation.request.maxPrice,
|
||||
requestId: negotiation.requestId,
|
||||
price: negotiation.ask.maxPrice,
|
||||
expiry: getTime().toUnix().u256 + negotiation.sales.offerExpiryInterval
|
||||
)
|
||||
|
||||
|
@ -117,13 +118,16 @@ proc start(negotiation: Negotiation) {.async.} =
|
|||
await negotiation.subscribeSelect()
|
||||
negotiation.waiting = some negotiation.waitForExpiry()
|
||||
|
||||
proc handleRequest(sales: Sales, request: StorageRequest) {.async.} =
|
||||
without availability =? sales.findAvailability(request):
|
||||
proc handleRequest(sales: Sales,
|
||||
requestId: array[32, byte],
|
||||
ask: StorageAsk) {.async.} =
|
||||
without availability =? sales.findAvailability(ask):
|
||||
return
|
||||
|
||||
let negotiation = Negotiation(
|
||||
sales: sales,
|
||||
request: request,
|
||||
requestId: requestId,
|
||||
ask: ask,
|
||||
availability: availability
|
||||
)
|
||||
|
||||
|
@ -132,8 +136,8 @@ proc handleRequest(sales: Sales, request: StorageRequest) {.async.} =
|
|||
proc start*(sales: Sales) =
|
||||
doAssert sales.subscription.isNone, "Sales already started"
|
||||
|
||||
proc onRequest(request: StorageRequest) {.gcsafe, upraises:[].} =
|
||||
asyncSpawn sales.handleRequest(request)
|
||||
proc onRequest(requestId: array[32, byte], ask: StorageAsk) {.gcsafe, upraises:[].} =
|
||||
asyncSpawn sales.handleRequest(requestId, ask)
|
||||
|
||||
proc subscribe {.async.} =
|
||||
sales.subscription = some await sales.market.subscribeRequests(onRequest)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import std/times
|
||||
import pkg/stint
|
||||
import pkg/nimcrypto
|
||||
import pkg/ethers
|
||||
import dagger/contracts
|
||||
import ../examples
|
||||
|
@ -13,11 +12,25 @@ proc example*(_: type Address): Address =
|
|||
proc example*(_: type StorageRequest): StorageRequest =
|
||||
StorageRequest(
|
||||
client: Address.example,
|
||||
duration: (10 * 60 * 60).u256, # 10 hours
|
||||
ask: StorageAsk(
|
||||
size: (1 * 1024 * 1024 * 1024).u256, # 1 Gigabyte
|
||||
contentHash: sha256.digest(0xdeadbeef'u32.toBytes).data,
|
||||
duration: (10 * 60 * 60).u256, # 10 hours
|
||||
proofProbability: 4.u256, # require a proof roughly once every 4 periods
|
||||
maxPrice: 84.u256,
|
||||
maxPrice: 84.u256
|
||||
),
|
||||
content: StorageContent(
|
||||
cid: "zb2rhheVmk3bLks5MgzTqyznLu1zqGH5jrfTA1eAZXrjx7Vob",
|
||||
erasure: StorageErasure(
|
||||
totalChunks: 12,
|
||||
totalNodes: 4,
|
||||
nodeId: 3
|
||||
),
|
||||
por: StoragePor(
|
||||
u: @(array[480, byte].example),
|
||||
publicKey: @(array[96, byte].example),
|
||||
name: @(array[512, byte].example)
|
||||
)
|
||||
),
|
||||
expiry: (getTime() + initDuration(hours=1)).toUnix.u256,
|
||||
nonce: array[32, byte].example
|
||||
)
|
||||
|
|
|
@ -45,7 +45,7 @@ ethersuite "Storage contracts":
|
|||
offer.requestId = request.id
|
||||
|
||||
switchAccount(client)
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
await storage.requestStorage(request)
|
||||
switchAccount(host)
|
||||
await token.approve(storage.address, collateralAmount)
|
||||
|
|
|
@ -30,7 +30,7 @@ ethersuite "On-Chain Market":
|
|||
request.client = accounts[0]
|
||||
offer.host = accounts[0]
|
||||
offer.requestId = request.id
|
||||
offer.price = request.maxPrice
|
||||
offer.price = request.ask.maxPrice
|
||||
|
||||
test "fails to instantiate when contract does not have a signer":
|
||||
let storageWithoutSigner = storage.connect(provider)
|
||||
|
@ -38,33 +38,36 @@ ethersuite "On-Chain Market":
|
|||
discard OnChainMarket.new(storageWithoutSigner)
|
||||
|
||||
test "supports storage requests":
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
check (await market.requestStorage(request)) == request
|
||||
|
||||
test "sets client address when submitting storage request":
|
||||
var requestWithoutClient = request
|
||||
requestWithoutClient.client = Address.default
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
let submitted = await market.requestStorage(requestWithoutClient)
|
||||
check submitted.client == accounts[0]
|
||||
|
||||
test "supports request subscriptions":
|
||||
var received: seq[StorageRequest]
|
||||
proc onRequest(request: StorageRequest) =
|
||||
received.add(request)
|
||||
var receivedIds: seq[array[32, byte]]
|
||||
var receivedAsks: seq[StorageAsk]
|
||||
proc onRequest(id: array[32, byte], ask: StorageAsk) =
|
||||
receivedIds.add(id)
|
||||
receivedAsks.add(ask)
|
||||
let subscription = await market.subscribeRequests(onRequest)
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
discard await market.requestStorage(request)
|
||||
check received == @[request]
|
||||
check receivedIds == @[request.id]
|
||||
check receivedAsks == @[request.ask]
|
||||
await subscription.unsubscribe()
|
||||
|
||||
test "supports storage offers":
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
discard await market.requestStorage(request)
|
||||
check (await market.offerStorage(offer)) == offer
|
||||
|
||||
test "sets host address when submitting storage offer":
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
discard await market.requestStorage(request)
|
||||
var offerWithoutHost = offer
|
||||
offerWithoutHost.host = Address.default
|
||||
|
@ -72,7 +75,7 @@ ethersuite "On-Chain Market":
|
|||
check submitted.host == accounts[0]
|
||||
|
||||
test "supports offer subscriptions":
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
discard await market.requestStorage(request)
|
||||
var received: seq[StorageOffer]
|
||||
proc onOffer(offer: StorageOffer) =
|
||||
|
@ -88,11 +91,11 @@ ethersuite "On-Chain Market":
|
|||
otherRequest.client = accounts[0]
|
||||
otherOffer.host = accounts[0]
|
||||
otherOffer.requestId = otherRequest.id
|
||||
otherOffer.price = otherRequest.maxPrice
|
||||
otherOffer.price = otherrequest.ask.maxPrice
|
||||
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
discard await market.requestStorage(request)
|
||||
await token.approve(storage.address, otherRequest.maxPrice)
|
||||
await token.approve(storage.address, otherrequest.ask.maxPrice)
|
||||
discard await market.requestStorage(otherRequest)
|
||||
|
||||
var submitted: seq[StorageOffer]
|
||||
|
@ -109,7 +112,7 @@ ethersuite "On-Chain Market":
|
|||
await subscription.unsubscribe()
|
||||
|
||||
test "supports selection of an offer":
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
discard await market.requestStorage(request)
|
||||
discard await market.offerStorage(offer)
|
||||
|
||||
|
@ -130,12 +133,12 @@ ethersuite "On-Chain Market":
|
|||
otherRequest.client = accounts[0]
|
||||
otherOffer.host = accounts[0]
|
||||
otherOffer.requestId = otherRequest.id
|
||||
otherOffer.price = otherRequest.maxPrice
|
||||
otherOffer.price = otherrequest.ask.maxPrice
|
||||
|
||||
await token.approve(storage.address, request.maxPrice)
|
||||
await token.approve(storage.address, request.ask.maxPrice)
|
||||
discard await market.requestStorage(request)
|
||||
discard await market.offerStorage(offer)
|
||||
await token.approve(storage.address, otherRequest.maxPrice)
|
||||
await token.approve(storage.address, otherrequest.ask.maxPrice)
|
||||
discard await market.requestStorage(otherRequest)
|
||||
discard await market.offerStorage(otherOffer)
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ method requestStorage*(market: MockMarket,
|
|||
market.requested.add(request)
|
||||
let subscriptions = market.subscriptions.onRequest
|
||||
for subscription in subscriptions:
|
||||
subscription.callback(request)
|
||||
subscription.callback(request.id, request.ask)
|
||||
return request
|
||||
|
||||
method offerStorage*(market: MockMarket,
|
||||
|
|
|
@ -16,9 +16,10 @@ suite "Purchasing":
|
|||
market = MockMarket.new()
|
||||
purchasing = Purchasing.new(market)
|
||||
request = StorageRequest(
|
||||
ask: StorageAsk(
|
||||
duration: uint16.example.u256,
|
||||
size: uint32.example.u256,
|
||||
contentHash: array[32, byte].example
|
||||
)
|
||||
)
|
||||
|
||||
proc purchaseAndWait(request: StorageRequest) {.async.} =
|
||||
|
@ -29,10 +30,9 @@ suite "Purchasing":
|
|||
test "submits a storage request when asked":
|
||||
await purchaseAndWait(request)
|
||||
let submitted = market.requested[0]
|
||||
check submitted.duration == request.duration
|
||||
check submitted.size == request.size
|
||||
check submitted.contentHash == request.contentHash
|
||||
check submitted.maxPrice == request.maxPrice
|
||||
check submitted.ask.duration == request.ask.duration
|
||||
check submitted.ask.size == request.ask.size
|
||||
check submitted.ask.maxPrice == request.ask.maxPrice
|
||||
|
||||
test "has a default value for proof probability":
|
||||
check purchasing.proofProbability != 0.u256
|
||||
|
@ -40,12 +40,12 @@ suite "Purchasing":
|
|||
test "can change default value for proof probability":
|
||||
purchasing.proofProbability = 42.u256
|
||||
await purchaseAndWait(request)
|
||||
check market.requested[0].proofProbability == 42.u256
|
||||
check market.requested[0].ask.proofProbability == 42.u256
|
||||
|
||||
test "can override proof probability per request":
|
||||
request.proofProbability = 42.u256
|
||||
request.ask.proofProbability = 42.u256
|
||||
await purchaseAndWait(request)
|
||||
check market.requested[0].proofProbability == 42.u256
|
||||
check market.requested[0].ask.proofProbability == 42.u256
|
||||
|
||||
test "has a default value for request expiration interval":
|
||||
check purchasing.requestExpiryInterval != 0.u256
|
||||
|
|
|
@ -8,7 +8,9 @@ import ./examples
|
|||
suite "Sales":
|
||||
|
||||
let availability = Availability.init(size=100, duration=60, minPrice=42.u256)
|
||||
let request = StorageRequest(duration: 60.u256, size: 100.u256, maxPrice:42.u256)
|
||||
let request = StorageRequest(
|
||||
ask: StorageAsk(duration: 60.u256, size: 100.u256, maxPrice:42.u256)
|
||||
)
|
||||
|
||||
var sales: Sales
|
||||
var market: MockMarket
|
||||
|
@ -52,7 +54,7 @@ suite "Sales":
|
|||
test "ignores request when no matching storage is available":
|
||||
sales.add(availability)
|
||||
var tooBig = request
|
||||
tooBig.size = request.size + 1
|
||||
tooBig.ask.size = request.ask.size + 1
|
||||
discard await market.requestStorage(tooBig)
|
||||
check market.offered.len == 0
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 29b5775951e774cb170b23cb6772cd7f1e7b5499
|
||||
Subproject commit 6aa2894521faa53a9896e800caf713499b33c318
|
Loading…
Reference in New Issue