diff --git a/package-lock.json b/package-lock.json index e35c19f..5136fe7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4181,6 +4181,11 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, + "node-fetch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.0.tgz", + "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA==" + }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", diff --git a/package.json b/package.json index addb1bd..1fc043b 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "eth-ecies": "^1.0.3", "ethereumjs-util": "^5.2.0", "jsonwebtoken": "^8.3.0", + "node-fetch": "^2.2.0", "web3": "1.0.0-beta.36", "web3-utils": "1.0.0-beta.36" }, diff --git a/src/keeper/Auth.ts b/src/keeper/Auth.ts index 266341b..b8c029d 100644 --- a/src/keeper/Auth.ts +++ b/src/keeper/Auth.ts @@ -1,5 +1,7 @@ import {Receipt} from "web3-utils" +import AccessStatus from "../models/AccessStatus" import Asset from "../ocean/Asset" +import Order from "../ocean/Order" import ContractBaseWrapper from "./ContractWrapperBase" export default class OceanAuth extends ContractBaseWrapper { @@ -10,34 +12,36 @@ export default class OceanAuth extends ContractBaseWrapper { return auth } - public async getOrderStatus(orderId: string): Promise { - return this.contract.methods.statusOfAccessRequest(orderId) - .call() - .then((status: string) => parseInt(status, 10)) - } - - public async cancelAccessRequest(orderId: string, senderAddress: string): Promise { - return this.contract.methods.cancelAccessRequest(orderId) - .send({ - from: senderAddress, + public async getOrderStatus(orderId: string): Promise { + return this.call("statusOfAccessRequest", [orderId]) + .then((status: string) => { + const statusInt = parseInt(status, 10) + const statusString = AccessStatus[statusInt] + return AccessStatus[statusString] }) } - public async getEncryptedAccessToken(orderId: string, senderAddress: string): Promise { - return this.contract.methods.getEncryptedAccessToken(orderId) - .send({ - from: senderAddress, - }) + public async getEncryptedAccessToken(orderId: string, consumerAddress: string): Promise { + return this.call("getEncryptedAccessToken", [orderId], consumerAddress) } public async initiateAccessRequest(asset: Asset, publicKey: string, timeout: number, buyerAddress: string): Promise { - const args = [asset.getId(), asset.publisher.getId(), publicKey, timeout] return this.sendTransaction("initiateAccessRequest", buyerAddress, args) } - public async commitAccessRequest() { - // todo + public async commitAccessRequest(order: Order, publisherAddress: string) { + const args = [order.getId(), true, 9999999999, "discovery", "read", "slaLink", "slaType"] + return this.sendTransaction("commitAccessRequest", publisherAddress, args) } + + public async getTempPubKey(orderId: string) { + return this.call("getTempPubKey", [orderId]) + } + + public async deliverAccessToken(orderId: string, accessToken: string, publisherAddress: string) { + return this.sendTransaction("deliverAccessToken", publisherAddress, [orderId, accessToken]) + } + } diff --git a/src/keeper/ContractHandler.ts b/src/keeper/ContractHandler.ts index 9e2b7cd..0f531d2 100644 --- a/src/keeper/ContractHandler.ts +++ b/src/keeper/ContractHandler.ts @@ -8,7 +8,13 @@ const contracts: Map = new Map() export default class ContractHandler { public static async get(what: string): Contract { - return contracts.get(what) || await ContractHandler.load(what) + const where = (await (await Keeper.getInstance()).getNetworkName()).toLowerCase() + try { + return contracts.get(what) || await ContractHandler.load(what, where) + } catch (err) { + Logger.error("Failed to load", what, "from", where, err) + throw err + } } public static async deployContracts() { @@ -48,21 +54,21 @@ export default class ContractHandler { }) } - private static async load(what: string): Promise { + private static async load(what: string, where: string): Promise { const web3 = Web3Provider.getWeb3() - const where = (await (await Keeper.getInstance()).getNetworkName()).toLowerCase() - Logger.log("Loading", what, "from", where) - try { - const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${what}.${where}`) - // Logger.log('Loaded artifact', artifact) - // Logger.log("Getting instance of", what, "from", where, "at", artifact.address) - const contract = new web3.eth.Contract(artifact.abi, artifact.address) - Logger.log("Loaded", what, "from", where) - contracts.set(what, contract) - return contracts.get(what) - } catch (err) { - Logger.error("Failed to load", what, "from", where, err) + // Logger.log("Loading", what, "from", where) + const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${what}.${where}`) + // Logger.log('Loaded artifact', artifact) + const code = await web3.eth.getCode(artifact.address) + if (code === "0x0") { + // no code in the blockchain dude + throw new Error(`No code deployed at address ${artifact.address}, sorry.`) } + // Logger.log("Getting instance of", what, "from", where, "at", artifact.address) + const contract = new web3.eth.Contract(artifact.abi, artifact.address) + Logger.log("Loaded", what, "from", where) + contracts.set(what, contract) + return contracts.get(what) } private static replaceTokens(bytecode: string, tokens: any[]) { diff --git a/src/keeper/ContractWrapperBase.ts b/src/keeper/ContractWrapperBase.ts index 70980d7..e213dde 100644 --- a/src/keeper/ContractWrapperBase.ts +++ b/src/keeper/ContractWrapperBase.ts @@ -1,12 +1,13 @@ import Event from "web3" import Contract from "web3-eth-contract" +import Logger from "../utils/Logger" import ContractHandler from "./ContractHandler" export default abstract class ContractWrapperBase { protected static instance = null - protected contract: Contract = null + private contract: Contract = null private contractName: string constructor(contractName) { @@ -46,14 +47,34 @@ export default abstract class ContractWrapperBase { if (!this.contract.methods[name]) { throw new Error(`Method ${name} is not part of contract ${this.contractName}`) } - const tx = this.contract.methods[name](...args) - const gas = await tx.estimateGas(args, { - from, - }) - return tx.send({ - from, - gas, - }) + try { + const tx = this.contract.methods[name](...args) + const gas = await tx.estimateGas(args, { + from, + }) + return tx.send({ + from, + gas, + }) + } catch (err) { + const argString = JSON.stringify(args, null, 2) + Logger.error(`Sending transaction ${name} on contract ${this.contractName} failed.`) + Logger.error(`Args: ${argString} From: ${from}`) + throw err + } + } + + protected async call(name: string, args: any[], from?: string) { + if (!this.contract.methods[name]) { + throw new Error(`Method ${name} is not part of contract ${this.contractName}`) + } + try { + const method = this.contract.methods[name](...args) + return method.call(from ? {from} : null) + } catch (err) { + Logger.error(`Calling method ${name} on contract ${this.contractName} failed. Args: ${args}`, err) + throw err + } } } diff --git a/src/keeper/Market.ts b/src/keeper/Market.ts index db12026..bbf48f6 100644 --- a/src/keeper/Market.ts +++ b/src/keeper/Market.ts @@ -1,6 +1,5 @@ import BigNumber from "bignumber.js" import {Receipt} from "web3-utils" -import ConfigProvider from "../ConfigProvider" import Order from "../ocean/Order" import ContractWrapperBase from "./ContractWrapperBase" @@ -14,50 +13,34 @@ export default class OceanMarket extends ContractWrapperBase { // call functions (costs no gas) public async isAssetActive(assetId: string): Promise { - return this.contract.methods.checkAsset(assetId).call() + return this.call("checkAsset", [assetId]) } public async verifyOrderPayment(orderId: string): Promise { - return this.contract.methods.verifyPaymentReceived(orderId).call() + return this.call("verifyPaymentReceived", [orderId]) } public async getAssetPrice(assetId: string): Promise { - return this.contract.methods.getAssetPrice(assetId) - .call() + return this.call("getAssetPrice", [assetId]) .then((price: string) => new BigNumber(price).toNumber()) } public async requestTokens(amount: number, receiverAddress: string): Promise { - return this.contract.methods.requestTokens(amount) - .send({ - from: receiverAddress, - }) + return this.sendTransaction("requestTokens", receiverAddress, [amount]) } public async generateId(input: string): Promise { - return await this.contract.methods.generateId(input).call() + return this.call("generateId", [input]) } public async register(assetId: string, price: number, publisherAddress: string): Promise { - return await this.contract.methods.register(assetId, price) - .send({ - from: publisherAddress, - gas: ConfigProvider.getConfig().defaultGas, - }) + return this.sendTransaction("register", publisherAddress, [assetId, price]) } - public async payOrder(order: Order, payerAddreess: string): Promise { - - const args = [ - order.getId(), order.getAsset().publisher.getId(), - order.getAsset().price, order.getTimeout(), - ] - - return this.sendTransaction("sendPayment", payerAddreess, args) - } - - public getAssetPublisher(assetId: string): Promise { - return this.contract.methods.getAssetPublisher(assetId) - .call() + public async payOrder(order: Order, publisherAddress: string, + price: number, consumerAddress: string): Promise { + return this.sendTransaction("sendPayment", consumerAddress, [ + order.getId(), publisherAddress, price, order.getTimeout(), + ]) } } diff --git a/src/keeper/Token.ts b/src/keeper/Token.ts index 467161e..b28ac0d 100644 --- a/src/keeper/Token.ts +++ b/src/keeper/Token.ts @@ -1,6 +1,5 @@ import BigNumber from "bignumber.js" import {Receipt} from "web3-utils" -import ConfigProvider from "../ConfigProvider" import ContractBaseWrapper from "./ContractWrapperBase" export default class OceanToken extends ContractBaseWrapper { @@ -12,16 +11,11 @@ export default class OceanToken extends ContractBaseWrapper { } public async approve(marketAddress: string, price: number, buyerAddress: string): Promise { - return this.contract.methods.approve(marketAddress, price) - .send({ - from: buyerAddress, - gas: ConfigProvider.getConfig().defaultGas, - }) + return this.sendTransaction("approve", buyerAddress, [marketAddress, price]) } public async balanceOf(address: string): Promise { - return this.contract.methods.balanceOf(address) - .call() + return this.call("balanceOf", [address]) .then((balance: string) => new BigNumber(balance).toNumber()) } } diff --git a/src/models/AccessStatus.ts b/src/models/AccessStatus.ts new file mode 100644 index 0000000..e602cde --- /dev/null +++ b/src/models/AccessStatus.ts @@ -0,0 +1,9 @@ +enum AccessStatus { + Requested, + Committed, + Delivered, + Verified, + Revoked, +} + +export default AccessStatus diff --git a/src/models/Config.ts b/src/models/Config.ts index 264db95..4207965 100644 --- a/src/models/Config.ts +++ b/src/models/Config.ts @@ -1,5 +1,4 @@ export default class Config { - public defaultGas: number = 300000 public providerUri: string public nodeUri: string public web3Provider: any diff --git a/src/ocean/Asset.ts b/src/ocean/Asset.ts index 27910e4..c548dfd 100644 --- a/src/ocean/Asset.ts +++ b/src/ocean/Asset.ts @@ -1,30 +1,17 @@ import * as EthCrypto from "eth-crypto" -import EthEcies from "eth-ecies" +import * as EthEcies from "eth-ecies" import * as EthjsUtil from "ethereumjs-util" -import JWT from "jsonwebtoken" +import * as JWT from "jsonwebtoken" import Keeper from "../keeper/Keeper" import Web3Provider from "../keeper/Web3Provider" +import ProviderProvider from "../provider/ProviderProvider" import Logger from "../utils/Logger" import Account from "./Account" import OceanBase from "./OceanBase" import Order from "./Order" -declare var fetch - export default class Asset extends OceanBase { - public static async load(assetId): Promise { - const {market} = await Keeper.getInstance() - - const asset = new Asset("unknown", "unknown", - await market.getAssetPrice(assetId), - new Account(await market.getAssetPublisher(assetId))) - - asset.setId(assetId) - - return asset - } - constructor(public name: string, public description: string, public price: number, @@ -37,7 +24,7 @@ export default class Asset extends OceanBase { return market.isAssetActive(this.getId()) } - public async purchase(account: Account, timeout: number): Promise { + public async purchase(consumer: Account, timeout: number): Promise { const {token, market, auth} = await Keeper.getInstance() const key = EthCrypto.createIdentity() @@ -53,7 +40,7 @@ export default class Asset extends OceanBase { try { const marketAddr = market.getAddress() // Allow market contract to transfer funds on the consumer"s behalf - await token.approve(marketAddr, price, account.getId()) + await token.approve(marketAddr, price, consumer.getId()) Logger.log(`${price} tokens approved on market with id: ${marketAddr}`) } catch (err) { Logger.error("token.approve failed", err) @@ -62,7 +49,7 @@ export default class Asset extends OceanBase { try { // Submit the access request const initiateAccessRequestReceipt = await auth.initiateAccessRequest(this, - publicKey, timeout, account.getId()) + publicKey, timeout, consumer.getId()) const {returnValues} = initiateAccessRequestReceipt.events.AccessConsentRequested Logger.log(`Keeper AccessConsentRequested event received on asset: ${this.getId()}`) @@ -73,91 +60,44 @@ export default class Asset extends OceanBase { } return order - if (false) { - // todo: AccessRequestCommitted event is not emitted in this flow - await auth.listenToEventOnce( - "AccessRequestCommitted", { - filter: { - _id: order.getId(), - }, - }) - .then((accessRequestCommittedResult) => { - Logger.log("Got AccessRequestCommitted Event") - - return order.pay(account) - }) - .then((payAssetReceipt) => { - return auth.listenToEventOnce( - "EncryptedTokenPublished", { - filter: { - _id: order.getId(), - }, - }) - }) - .then((encryptedTokenPublishedResult) => { - Logger.log("Got EncryptedTokenPublished Event") - - const {returnValues} = encryptedTokenPublishedResult - - return this.finalizePurchaseAsset( - returnValues._id, order, key, account, - ) - }) - } } - public async finalizePurchaseAsset(accessId: string, order: Order, key: any, account: Account): Promise { + public async consume(order: Order, consumer: Account): Promise { const {auth} = await Keeper.getInstance() - const encryptedAccessToken = await auth.getEncryptedAccessToken(accessId, this.getId()) + const encryptedAccessToken = await auth.getEncryptedAccessToken(order.getId(), consumer.getId()) // grab the access token from acl contract const tokenNo0x = encryptedAccessToken.slice(2) const encryptedTokenBuffer = Buffer.from(tokenNo0x, "hex") - const privateKey = key.privateKey.slice(2) - const accessTokenEncoded = EthEcies.Decrypt(Buffer.from(privateKey, "hex"), encryptedTokenBuffer) + const privateKey = order.getKey().privateKey.slice(2) + const accessTokenEncoded: string = + EthEcies.decrypt(Buffer.from(privateKey, "hex"), encryptedTokenBuffer).toString() const accessToken = JWT.decode(accessTokenEncoded) // Returns a json object - // sign it - const hexEncrToken = `0x${encryptedTokenBuffer.toString("hex")}` + if (!accessToken) { + throw new Error(`AccessToken is not an jwt: ${accessTokenEncoded}`) + } - const signature = Web3Provider.getWeb3().eth.sign(account.getId(), hexEncrToken) - const fixedMsgSha = Web3Provider.getWeb3().utils.sha3(encryptedAccessToken) + const signature = Web3Provider.getWeb3().eth.sign(encryptedAccessToken, consumer.getId()) + const encryptedAccessTokenSha3 = Web3Provider.getWeb3().utils.sha3(encryptedAccessToken) // Download the data set from the provider using the url in the access token // decode the access token, grab the service_endpoint, request_id, // payload keys: ['consumerId', 'fixed_msg', 'sigEncJWT', 'jwt'] const payload = JSON.stringify({ - consumerId: account.getId(), - fixed_msg: fixedMsgSha, + consumerId: consumer.getId(), + fixed_msg: encryptedAccessTokenSha3, sigEncJWT: signature, jwt: accessTokenEncoded, }) - const accessUrl = await fetch(`${accessToken.service_endpoint}/${accessToken.resource_id}`, { - method: "POST", - body: payload, - headers: { - "Content-type": "application/json", - }, - }) - .then((response: any) => { - if (response.ok) { - return response.text() - } - Logger.log("Failed: ", response.status, response.statusText) - }) - .then((consumptionUrl: string) => { - Logger.log("Success accessing consume endpoint: ", consumptionUrl) - return consumptionUrl - }) - .catch((error) => { - Logger.error("Error fetching the data asset consumption url: ", error) - }) - Logger.log("consume url: ", accessUrl) - order.setAccessUrl(accessUrl) - return order + const accessUrl = await ProviderProvider.getProvider().getAccessUrl(accessToken, payload) + + Logger.log("consume url: ", accessUrl) + + return accessUrl } } diff --git a/src/ocean/Ocean.ts b/src/ocean/Ocean.ts index 6885667..c41f117 100644 --- a/src/ocean/Ocean.ts +++ b/src/ocean/Ocean.ts @@ -1,6 +1,8 @@ import ConfigProvider from "../ConfigProvider" import Keeper from "../keeper/Keeper" import Web3Provider from "../keeper/Web3Provider" +import Provider from "../provider/Provider" +import ProviderProvider from "../provider/ProviderProvider" import Logger from "../utils/Logger" import Account from "./Account" import Asset from "./Asset" @@ -12,6 +14,7 @@ export default class Ocean { if (!Ocean.instance) { ConfigProvider.configure(config) + ProviderProvider.setProvider(Provider) Ocean.instance = new Ocean(await Keeper.getInstance()) } @@ -38,12 +41,16 @@ export default class Ocean { // generate an id const assetId = await market.generateId(asset.name + asset.description) - Logger.log(`Registering: ${assetId} with price ${asset.price}`) + Logger.log(`Registering: ${assetId} with price ${asset.price} for ${asset.publisher.getId()}`) asset.setId(assetId) + const isAssetActive = await market.isAssetActive(assetId) // register asset in the market - const result = await market.register(asset.getId(), asset.price, asset.publisher.getId()) - Logger.log("Registered:", assetId, "in block", result.blockNumber) - + if (!isAssetActive) { + const result = await market.register(asset.getId(), asset.price, asset.publisher.getId()) + Logger.log("Registered:", assetId, "in block", result.blockNumber) + } else { + throw new Error("Asset already registered") + } return assetId } @@ -68,12 +75,11 @@ export default class Ocean { const {returnValues} = event const order: Order = new Order( - await Asset.load(returnValues._resourceId), + null, parseInt(returnValues._timeout, 10), null, null) order.setId(returnValues._id) - order.setStatus(await auth.getOrderStatus(returnValues._id)) order.setPaid(await market.verifyOrderPayment(returnValues._id)) return order diff --git a/src/ocean/Order.ts b/src/ocean/Order.ts index 119ff3b..c321c0d 100644 --- a/src/ocean/Order.ts +++ b/src/ocean/Order.ts @@ -1,4 +1,6 @@ +import * as EthEcies from "eth-ecies" import Keeper from "../keeper/Keeper" +import AccessStatus from "../models/AccessStatus" import Logger from "../utils/Logger" import Account from "./Account" import Asset from "./Asset" @@ -7,33 +9,15 @@ import OceanBase from "./OceanBase" export default class Order extends OceanBase { private paid: boolean - private status: number - private accessUrl: string - private accessId: string constructor(private asset: Asset, private timeout: number, private pubkey: string, private key: any) { super() } - public setAccessUrl(url: string) { - this.accessUrl = url - } - - public getAccessUrl() { - return this.accessUrl - } - - public setStatus(status: number) { - this.status = status - } - - public setAccessId(accessId: string) { - this.accessId = accessId - } - - public getStatus() { - return this.status + public async getStatus(): Promise { + const {auth} = await Keeper.getInstance() + return auth.getOrderStatus(this.id) } public setPaid(paid: boolean) { @@ -44,14 +28,6 @@ export default class Order extends OceanBase { return this.paid } - public getAsset() { - return this.asset - } - - public getPubkey() { - return this.pubkey - } - public getTimeout() { return this.timeout } @@ -60,12 +36,34 @@ export default class Order extends OceanBase { return this.key } - public async pay(account: Account): Promise { + public async pay(consumer: Account): Promise { const {market} = await Keeper.getInstance() - Logger.log(`Sending payment: ${this.getId()} ${this.accessId} - ${this.asset.publisher.getId()} ${this.asset.price} ${this.timeout}`) - const payReceipt = await market.payOrder(this, account.getId()) + Logger.log( + `Sending payment: ${this.getId()} ${this.asset.publisher.getId()} ${this.asset.price} ${this.timeout}`, + ) + const payReceipt = await market.payOrder(this, this.asset.publisher.getId(), this.asset.price, consumer.getId()) return payReceipt.events.PaymentReceived.returnValues._paymentId } + + public async commit(accessToken: string) { + const {auth} = await Keeper.getInstance() + const commitAccessRequestReceipt = await auth.commitAccessRequest(this, this.asset.publisher.getId()) + if (commitAccessRequestReceipt.events.AccessRequestRejected) { + + const {returnValues} = commitAccessRequestReceipt.events.AccessRequestRejected + throw new Error(`commitAccessRequest failed ${JSON.stringify(returnValues, null, 2)}`) + } + + const pubKey = await auth.getTempPubKey(this.getId()) + + if (this.pubkey !== pubKey) { + throw new Error("Pubkey missmatch") + } + + const encryptedAccessToken = + EthEcies.encrypt(new Buffer(pubKey, "hex"), new Buffer(accessToken)).toString("hex") + + await auth.deliverAccessToken(this.getId(), `0x${encryptedAccessToken}`, this.asset.publisher.getId()) + } } diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts new file mode 100644 index 0000000..ca86b9b --- /dev/null +++ b/src/provider/Provider.ts @@ -0,0 +1,30 @@ +import fetch from "node-fetch" +import Logger from "../utils/Logger" + +export default class Provider { + public static async getAccessUrl(accessToken: any, payload: any): Promise { + + const accessUrl = await fetch(`${accessToken.service_endpoint}/${accessToken.resource_id}`, { + method: "POST", + body: payload, + headers: { + "Content-type": "application/json", + }, + }) + .then((response: any) => { + if (response.ok) { + return response.text() + } + Logger.log("Failed: ", response.status, response.statusText) + }) + .then((consumptionUrl: string) => { + Logger.log("Success accessing consume endpoint: ", consumptionUrl) + return consumptionUrl + }) + .catch((error) => { + Logger.error("Error fetching the data asset consumption url: ", error) + }) + + return accessUrl + } +} diff --git a/src/provider/ProviderProvider.ts b/src/provider/ProviderProvider.ts new file mode 100644 index 0000000..55e45c5 --- /dev/null +++ b/src/provider/ProviderProvider.ts @@ -0,0 +1,14 @@ +export default class ProviderProvider { + + public static setProvider(provider) { + + ProviderProvider.provider = provider + } + + public static getProvider() { + + return ProviderProvider.provider + } + + private static provider +} diff --git a/test/MockProvider.ts b/test/MockProvider.ts new file mode 100644 index 0000000..28f2262 --- /dev/null +++ b/test/MockProvider.ts @@ -0,0 +1,8 @@ +import Provider from "../src/provider/Provider" + +export default class MockProvider extends Provider { + + public static async getAccessUrl(accessToken: any, payload: any): Promise { + return "http://test/test" + } +} diff --git a/test/keeper/ContractHandler.test.ts b/test/keeper/ContractHandler.test.ts index fcc6bae..a0813a1 100644 --- a/test/keeper/ContractHandler.test.ts +++ b/test/keeper/ContractHandler.test.ts @@ -13,7 +13,7 @@ describe("ContractHandler", () => { describe("#get()", () => { it("should load and get OceanToken correctly", async () => { - assert(await ContractHandler.get("OceanTokewn") !== null) + assert(await ContractHandler.get("OceanToken") !== null) }) }) diff --git a/test/ocean/Account.test.ts b/test/ocean/Account.test.ts index 768d45f..b4ec4e1 100644 --- a/test/ocean/Account.test.ts +++ b/test/ocean/Account.test.ts @@ -41,9 +41,9 @@ describe("Account", () => { describe("#getEthBalance()", () => { - it("should get initial balance", async () => { + it("should get initial ether balance", async () => { - const account: Account = accounts[1] + const account: Account = accounts[9] const balance = await account.getEthBalance() const web3 = Web3Provider.getWeb3() @@ -55,7 +55,7 @@ describe("Account", () => { it("should get initial balance", async () => { - const account: Account = accounts[1] + const account: Account = accounts[9] const balance = await account.getBalance() const web3 = Web3Provider.getWeb3() diff --git a/test/ocean/Asset.test.ts b/test/ocean/Asset.test.ts index b782e72..c6bff34 100644 --- a/test/ocean/Asset.test.ts +++ b/test/ocean/Asset.test.ts @@ -5,11 +5,15 @@ import Account from "../../src/ocean/Account" import Asset from "../../src/ocean/Asset" import Ocean from "../../src/ocean/Ocean" import Order from "../../src/ocean/Order" +import ProviderProvider from "../../src/provider/ProviderProvider" import config from "../config" +import MockProvider from "../MockProvider" const testName = "Test Asset 2" const testDescription = "This asset is pure owange" const testPrice = 100 +const timeout = 100000 +const accessToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE1Mzk3ODcxMDEsImV4cCI6NDcyNjk5NjcwNCwiYXVkIjoiIiwic3ViIjoiIiwic2VydmljZV9lbmRwb2ludCI6Imh0dHA6Ly9hZGFzZCIsInJlc291cmNlX2lkIjoiMTIzNDUifQ.2H3TRC3CAToVE9divSckwHi_HNvgOHKrtJPo8128qrKBHTk7YYb0UNfVCuYqwhGR" let ocean: Ocean let testAsset: Asset @@ -18,6 +22,8 @@ let testPublisher: Account before(async () => { ConfigProvider.configure(config) + ProviderProvider.setProvider(MockProvider) + await ContractHandler.deployContracts() ocean = await Ocean.getInstance(config) accounts = await ocean.getAccounts() @@ -50,16 +56,25 @@ describe("Asset", () => { it("should purchase an asset", async () => { // todo - const order: Order = await testAsset.purchase(accounts[5], 10000) + const consumerAccount = accounts[5] + const order: Order = await testAsset.purchase(consumerAccount, timeout) assert(order) }) }) - describe("#purchase()", () => { + describe("#consume()", () => { - it("should purchase an asset", async () => { - // todo - // await testAsset.finalizePurchaseAsset() + it("should consume an asset", async () => { + const consumerAccount = accounts[5] + await consumerAccount.requestTokens(testAsset.price) + // place order - consumer + const order: Order = await testAsset.purchase(consumerAccount, timeout) + // commit order - provider + await order.commit(accessToken) + // pay order - consumer + await order.pay(consumerAccount) + const url = await testAsset.consume(order, consumerAccount) + assert(url) }) }) }) diff --git a/test/ocean/Ocean.test.ts b/test/ocean/Ocean.test.ts index 2ed2d6e..d0776f1 100644 --- a/test/ocean/Ocean.test.ts +++ b/test/ocean/Ocean.test.ts @@ -4,17 +4,27 @@ import ContractHandler from "../../src/keeper/ContractHandler" import Account from "../../src/ocean/Account" import Asset from "../../src/ocean/Asset" import Ocean from "../../src/ocean/Ocean" -import Logger from "../../src/utils/Logger" +import Order from "../../src/ocean/Order" import config from "../config" let ocean: Ocean let accounts: Account[] +let testAsset: Asset +let testPublisher: Account + +const name = "Test Asset 3" +const description = "This asset is pure owange" +const price = 100 +const timeout = 100000000 before(async () => { ConfigProvider.configure(config) await ContractHandler.deployContracts() ocean = await Ocean.getInstance(config) accounts = await ocean.getAccounts() + + testPublisher = accounts[0] + testAsset = new Asset(name, description, price, testPublisher) }) describe("Ocean", () => { @@ -36,15 +46,7 @@ describe("Ocean", () => { it("should register an asset", async () => { - const publisher: Account = accounts[0] - - const name = "Test Asset 3" - const description = "This asset is pure owange" - const price = 100 - - const asset = new Asset(name, description, price, publisher) - - const assetId: string = await ocean.register(asset) + const assetId: string = await ocean.register(testAsset) assert(assetId.length === 66) assert(assetId.startsWith("0x")) @@ -55,9 +57,17 @@ describe("Ocean", () => { it("should list orders", async () => { - // todo - const orders = await ocean.getOrdersByConsumer(accounts[1]) - Logger.log(orders) + const testConsumer = accounts[1] + const asset: Asset = new Asset("getOrdersByConsumer test", description, price, testPublisher) + + await ocean.register(asset) + + const order: Order = await asset.purchase(testConsumer, timeout) + const orders = await ocean.getOrdersByConsumer(testConsumer) + + assert(orders.length === 1) + assert(orders[0].getId() === order.getId()) + }) }) diff --git a/test/ocean/Order.test.ts b/test/ocean/Order.test.ts index 19ada77..e53881a 100644 --- a/test/ocean/Order.test.ts +++ b/test/ocean/Order.test.ts @@ -1,21 +1,24 @@ import * as assert from "assert" import ConfigProvider from "../../src/ConfigProvider" import ContractHandler from "../../src/keeper/ContractHandler" +import AccessStatus from "../../src/models/AccessStatus" import Account from "../../src/ocean/Account" import Asset from "../../src/ocean/Asset" import Ocean from "../../src/ocean/Ocean" import Order from "../../src/ocean/Order" -import Logger from "../../src/utils/Logger" import config from "../config" -const testName = "Test Asset 333" +const testName = "Order Test Asset" const testDescription = "This asset is pure owange" const testPrice = 100 +const timeout = 1000000 +const accessToken = "eyJhbGciOiJIUzI1" let ocean: Ocean let testAsset: Asset let accounts: Account[] let testPublisher: Account +let testConsumer: Account before(async () => { ConfigProvider.configure(config) @@ -23,6 +26,7 @@ before(async () => { ocean = await Ocean.getInstance(config) accounts = await ocean.getAccounts() testPublisher = accounts[0] + testConsumer = accounts[1] // register an asset to play around with testAsset = new Asset(testName, testDescription, testPrice, testPublisher) await ocean.register(testAsset) @@ -30,17 +34,53 @@ before(async () => { describe("Order", () => { - describe("#pay()", () => { + describe("#pay()", async () => { - it("should pay for the order", async () => { + it("should pay for an order", async () => { - const order: Order = await testAsset.purchase(accounts[0], 10000) + const order: Order = await testAsset.purchase(testConsumer, timeout) assert(order) - const paymentId: string = await order.pay(accounts[0]) - Logger.log("paymentId", paymentId) + await order.commit(accessToken) + await testConsumer.requestTokens(testAsset.price) + const paymentId: string = await order.pay(testConsumer) + assert(paymentId) }) }) + describe("#commit()", async () => { + + it("should commit the order", async () => { + + const order: Order = await testAsset.purchase(testConsumer, timeout) + assert(order) + + await order.commit(accessToken) + }) + }) + + describe("#getStatus()", async () => { + + it("should get status Requested on new order", async () => { + + const order: Order = await testAsset.purchase(testConsumer, timeout) + assert(order) + + const status: AccessStatus = await order.getStatus() + assert(status === AccessStatus.Requested) + }) + + it("should get status Delivered on commited order", async () => { + + const order: Order = await testAsset.purchase(testConsumer, timeout) + assert(order) + + await order.commit(accessToken) + + const status: AccessStatus = await order.getStatus() + assert(status === AccessStatus.Delivered) + }) + }) + })