diff --git a/dagger/contracts.nim b/dagger/contracts.nim index 24bc6321..b0ba4a07 100644 --- a/dagger/contracts.nim +++ b/dagger/contracts.nim @@ -2,8 +2,10 @@ import contracts/requests import contracts/offers import contracts/storage import contracts/deployment +import contracts/market export requests export offers export storage export deployment +export market diff --git a/dagger/contracts/market.nim b/dagger/contracts/market.nim new file mode 100644 index 00000000..c93c0ec9 --- /dev/null +++ b/dagger/contracts/market.nim @@ -0,0 +1,34 @@ +import pkg/ethers +import pkg/upraises +import ../market +import ./storage + +type + OnChainMarket* = ref object of Market + contract: Storage + signer: Signer + MarketSubscription = market.Subscription + EventSubscription = ethers.Subscription + OnChainMarketSubscription = ref object of MarketSubscription + eventSubscription: EventSubscription + +export market + +func new*(_: type OnChainMarket, contract: Storage): OnChainMarket = + OnChainMarket(contract: contract, signer: !contract.signer) + +method subscribeRequests(market: OnChainMarket, + callback: OnRequest): + Future[MarketSubscription] {.async.} = + proc onEvent(event: StorageRequested) {.upraises:[].} = + callback(event.request) + let subscription = await market.contract.subscribe(StorageRequested, onEvent) + return OnChainMarketSubscription(eventSubscription: subscription) + +method requestStorage(market: OnChainMarket, request: StorageRequest) {.async.} = + var request = request + request.client = await market.signer.getAddress() + await market.contract.requestStorage(request) + +method unsubscribe*(subscription: OnChainMarketSubscription) {.async.} = + await subscription.eventSubscription.unsubscribe() diff --git a/dagger/contracts/requests.nim b/dagger/contracts/requests.nim index 638fca3b..c88a3b4a 100644 --- a/dagger/contracts/requests.nim +++ b/dagger/contracts/requests.nim @@ -1,5 +1,7 @@ import pkg/contractabi import pkg/nimcrypto +import pkg/ethers/fields +import pkg/questionable/results export contractabi @@ -14,23 +16,27 @@ type expiry*: UInt256 nonce*: array[32, byte] -func toTuple(request: StorageRequest): auto = - ( - request.client, - request.duration, - request.size, - request.contentHash, - request.proofProbability, - request.maxPrice, - request.expiry, - request.nonce +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] ) func solidityType*(_: type StorageRequest): string = - solidityType(typeof StorageRequest.default.toTuple) + solidityType(StorageRequest.fieldTypes) func encode*(encoder: var AbiEncoder, request: StorageRequest) = - encoder.write(request.toTuple) + encoder.write(request.fieldValues) + +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) diff --git a/dagger/contracts/storage.nim b/dagger/contracts/storage.nim index 95d8a080..f88582dd 100644 --- a/dagger/contracts/storage.nim +++ b/dagger/contracts/storage.nim @@ -11,6 +11,9 @@ export contract type Storage* = ref object of Contract Id = array[32, byte] + StorageRequested* = object of Event + requestId*: Id + request*: StorageRequest proc collateralAmount*(storage: Storage): UInt256 {.contract, view.} proc slashMisses*(storage: Storage): UInt256 {.contract, view.} diff --git a/dagger/market.nim b/dagger/market.nim index 80ee9cd6..149fb03c 100644 --- a/dagger/market.nim +++ b/dagger/market.nim @@ -1,4 +1,5 @@ import pkg/chronos +import pkg/upraises import ./contracts/requests import ./contracts/offers @@ -9,8 +10,8 @@ export offers type Market* = ref object of RootObj Subscription* = ref object of RootObj - OnRequest* = proc(request: StorageRequest) {.gcsafe.} - OnOffer* = proc(offer: StorageOffer) {.gcsafe.} + OnRequest* = proc(request: StorageRequest) {.gcsafe, upraises:[].} + OnOffer* = proc(offer: StorageOffer) {.gcsafe, upraises:[].} method requestStorage*(market: Market, request: StorageRequest) {.base, async.} = raiseAssert("not implemented") diff --git a/tests/contracts/testMarket.nim b/tests/contracts/testMarket.nim new file mode 100644 index 00000000..8567e06f --- /dev/null +++ b/tests/contracts/testMarket.nim @@ -0,0 +1,34 @@ +import ./ethertest +import dagger/contracts +import dagger/contracts/testtoken +import ./examples + +ethersuite "On-Chain Market": + + var market: OnChainMarket + var storage: Storage + var token: TestToken + + setup: + let deployment = deployment() + storage = Storage.new(!deployment.address(Storage), provider.getSigner()) + token = TestToken.new(!deployment.address(TestToken), provider.getSigner()) + await token.mint(accounts[0], 1000.u256) + market = OnChainMarket.new(storage) + + test "supports storage requests": + var submitted: seq[StorageRequest] + proc onRequest(request: StorageRequest) = + submitted.add(request) + let subscription = await market.subscribeRequests(onRequest) + let request = StorageRequest( + duration: uint16.example.u256, + size: uint32.example.u256, + contentHash: array[32, byte].example + ) + await market.requestStorage(request) + check submitted.len == 1 + check submitted[0].duration == request.duration + check submitted[0].size == request.size + check submitted[0].contentHash == request.contentHash + await subscription.unsubscribe() diff --git a/tests/testContracts.nim b/tests/testContracts.nim index 9b347dc0..8dad4da5 100644 --- a/tests/testContracts.nim +++ b/tests/testContracts.nim @@ -1,4 +1,5 @@ import ./contracts/testCollateral import ./contracts/testContracts +import ./contracts/testMarket {.warning[UnusedImport]:off.}