import std/options import pkg/chronos import pkg/ethers/testing import codex/contracts import codex/contracts/testtoken import codex/storageproofs import ../ethertest import ./examples import ./time ethersuite "On-Chain Market": let proof = exampleProof() var market: OnChainMarket var storage: Storage var token: TestToken var request: StorageRequest var slotIndex: UInt256 var periodicity: Periodicity 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], 1_000_000_000.u256) let collateral = await storage.collateralAmount() await token.approve(storage.address, collateral) await storage.deposit(collateral) market = OnChainMarket.new(storage) periodicity = Periodicity(seconds: await storage.proofPeriod()) request = StorageRequest.example request.client = accounts[0] slotIndex = (request.ask.slots div 2).u256 proc waitUntilProofRequired(slotId: SlotId) {.async.} = let currentPeriod = periodicity.periodOf(await provider.currentTime()) await provider.advanceTimeTo(periodicity.periodEnd(currentPeriod)) while not ( (await storage.isProofRequired(slotId)) and (await storage.getPointer(slotId)) < 250 ): await provider.advanceTime(periodicity.seconds) test "fails to instantiate when contract does not have a signer": let storageWithoutSigner = storage.connect(provider) expect AssertionError: discard OnChainMarket.new(storageWithoutSigner) test "knows signer address": check (await market.getSigner()) == (await provider.getSigner().getAddress()) test "supports storage requests": await token.approve(storage.address, request.price) await market.requestStorage(request) test "can retrieve previously submitted requests": check (await market.getRequest(request.id)) == none StorageRequest await token.approve(storage.address, request.price) await market.requestStorage(request) let r = await market.getRequest(request.id) check (r) == some request test "supports withdrawing of funds": await token.approve(storage.address, request.price) await market.requestStorage(request) await provider.advanceTimeTo(request.expiry) await market.withdrawFunds(request.id) test "supports request subscriptions": var receivedIds: seq[RequestId] var receivedAsks: seq[StorageAsk] proc onRequest(id: RequestId, ask: StorageAsk) = receivedIds.add(id) receivedAsks.add(ask) let subscription = await market.subscribeRequests(onRequest) await token.approve(storage.address, request.price) await market.requestStorage(request) check receivedIds == @[request.id] check receivedAsks == @[request.ask] await subscription.unsubscribe() test "supports filling of slots": await token.approve(storage.address, request.price) await market.requestStorage(request) await market.fillSlot(request.id, slotIndex, proof) test "can retrieve host that filled slot": await token.approve(storage.address, request.price) await market.requestStorage(request) check (await market.getHost(request.id, slotIndex)) == none Address await market.fillSlot(request.id, slotIndex, proof) check (await market.getHost(request.id, slotIndex)) == some accounts[0] test "support slot filled subscriptions": await token.approve(storage.address, request.price) await market.requestStorage(request) var receivedIds: seq[RequestId] var receivedSlotIndices: seq[UInt256] proc onSlotFilled(id: RequestId, slotIndex: UInt256) = receivedIds.add(id) receivedSlotIndices.add(slotIndex) let subscription = await market.subscribeSlotFilled(request.id, slotIndex, onSlotFilled) await market.fillSlot(request.id, slotIndex, proof) check receivedIds == @[request.id] check receivedSlotIndices == @[slotIndex] await subscription.unsubscribe() test "subscribes only to a certain slot": var otherSlot = slotIndex - 1 await token.approve(storage.address, request.price) await market.requestStorage(request) var receivedSlotIndices: seq[UInt256] proc onSlotFilled(requestId: RequestId, slotIndex: UInt256) = receivedSlotIndices.add(slotIndex) let subscription = await market.subscribeSlotFilled(request.id, slotIndex, onSlotFilled) await market.fillSlot(request.id, slotIndex - 1, proof) check receivedSlotIndices.len == 0 await market.fillSlot(request.id, slotIndex, proof) check receivedSlotIndices == @[slotIndex] await subscription.unsubscribe() test "support fulfillment subscriptions": await token.approve(storage.address, request.price) await market.requestStorage(request) var receivedIds: seq[RequestId] proc onFulfillment(id: RequestId) = receivedIds.add(id) let subscription = await market.subscribeFulfillment(request.id, onFulfillment) for slotIndex in 0..