diff --git a/src/keeper/ContractHandler.ts b/src/keeper/ContractHandler.ts index 06eed98..07fd85f 100644 --- a/src/keeper/ContractHandler.ts +++ b/src/keeper/ContractHandler.ts @@ -50,6 +50,8 @@ export default class ContractHandler { const market = await ContractHandler.deployContract("OceanMarket", deployerAddress, { args: [token.options.address], }) + await ContractHandler.deployContract("ServiceAgreement", deployerAddress, {}) + await ContractHandler.deployContract("DIDRegistry", deployerAddress, {}) /* not part of trilobite const dispute = await ContractHandler.deployContract("OceanDispute", deployerAddress, { args: [market.options.address, registry.options.address, plcrVoting.options.address], diff --git a/src/keeper/Keeper.ts b/src/keeper/Keeper.ts index 2af79aa..26383e9 100644 --- a/src/keeper/Keeper.ts +++ b/src/keeper/Keeper.ts @@ -1,6 +1,7 @@ -import OceanAuth from "./Auth" -import OceanMarket from "./Market" -import OceanToken from "./Token" +import OceanAuth from "./contracts/Auth" +import OceanMarket from "./contracts/Market" +import ServiceAgreement from "./contracts/ServiceAgreement" +import OceanToken from "./contracts/Token" import Web3Provider from "./Web3Provider" export default class Keeper { @@ -13,6 +14,7 @@ export default class Keeper { Keeper.instance.market = await OceanMarket.getInstance() Keeper.instance.auth = await OceanAuth.getInstance() Keeper.instance.token = await OceanToken.getInstance() + Keeper.instance.serviceAgreement = await ServiceAgreement.getInstance() } return Keeper.instance } @@ -22,6 +24,7 @@ export default class Keeper { public token: OceanToken public market: OceanMarket public auth: OceanAuth + public serviceAgreement: ServiceAgreement public async getNetworkName(): Promise { return Web3Provider.getWeb3().eth.net.getId() diff --git a/src/keeper/Auth.ts b/src/keeper/contracts/Auth.ts similarity index 79% rename from src/keeper/Auth.ts rename to src/keeper/contracts/Auth.ts index b4d9d14..92d8b58 100644 --- a/src/keeper/Auth.ts +++ b/src/keeper/contracts/Auth.ts @@ -1,7 +1,7 @@ import {Receipt} from "web3-utils" -import AccessStatus from "../models/AccessStatus" -import Asset from "../ocean/Asset" -import Order from "../ocean/Order" +import AccessStatus from "../../models/AccessStatus" +import Asset from "../../ocean/Asset" +import Order from "../../ocean/Order" import ContractBase from "./ContractBase" export default class OceanAuth extends ContractBase { @@ -28,12 +28,12 @@ export default class OceanAuth extends ContractBase { public async initiateAccessRequest(asset: Asset, publicKey: string, timeout: number, buyerAddress: string): Promise { const args = ["0x" + asset.getId(), asset.publisher.getId(), publicKey, timeout] - return this.sendTransaction("initiateAccessRequest", buyerAddress, args) + return this.send("initiateAccessRequest", buyerAddress, args) } public async commitAccessRequest(order: Order, publisherAddress: string) { const args = [order.getId(), true, 9999999999, "discovery", "read", "slaLink", "slaType"] - return this.sendTransaction("commitAccessRequest", publisherAddress, args) + return this.send("commitAccessRequest", publisherAddress, args) } public async getTempPubKey(orderId: string) { @@ -41,7 +41,7 @@ export default class OceanAuth extends ContractBase { } public async deliverAccessToken(orderId: string, accessToken: string, publisherAddress: string) { - return this.sendTransaction("deliverAccessToken", publisherAddress, [orderId, accessToken]) + return this.send("deliverAccessToken", publisherAddress, [orderId, accessToken]) } } diff --git a/src/keeper/ContractBase.ts b/src/keeper/contracts/ContractBase.ts similarity index 91% rename from src/keeper/ContractBase.ts rename to src/keeper/contracts/ContractBase.ts index 6b43717..e8c92a9 100644 --- a/src/keeper/ContractBase.ts +++ b/src/keeper/contracts/ContractBase.ts @@ -1,7 +1,8 @@ import Event from "web3" import Contract from "web3-eth-contract" -import Logger from "../utils/Logger" -import ContractHandler from "./ContractHandler" +import {Receipt} from "web3-utils" +import Logger from "../../utils/Logger" +import ContractHandler from "../ContractHandler" export default abstract class ContractBase { @@ -45,7 +46,7 @@ export default abstract class ContractBase { this.contract = await ContractHandler.get(this.contractName) } - protected async sendTransaction(name: string, from: string, args: any[]) { + protected async send(name: string, from: string, args: any[]): Promise { if (!this.contract.methods[name]) { throw new Error(`Method ${name} is not part of contract ${this.contractName}`) } @@ -66,7 +67,7 @@ export default abstract class ContractBase { } } - protected async call(name: string, args: any[], from?: string) { + protected async call(name: string, args: any[], from?: string): Promise { if (!this.contract.methods[name]) { throw new Error(`Method ${name} is not part of contract ${this.contractName}`) } diff --git a/src/keeper/contracts/DIDRegistry.ts b/src/keeper/contracts/DIDRegistry.ts new file mode 100644 index 0000000..05c23c6 --- /dev/null +++ b/src/keeper/contracts/DIDRegistry.ts @@ -0,0 +1,37 @@ +import {Receipt} from "web3-utils" +import ValueType from "../../models/ValueType" +import ContractBase from "./ContractBase" + +export default class DIDRegistry extends ContractBase { + + public static async getInstance(): Promise { + const didRegistry: DIDRegistry = new DIDRegistry("DIDRegistry") + await didRegistry.init() + return didRegistry + } + + public async registerAttribute(did: string, type: ValueType, key: string, + value: string, ownerAddress: string): Promise { + + return this.send("registerAttribute", + ownerAddress, ["0x" + did, type, key, value], + ) + } + + public async getOwner(did: string): Promise { + + return this.call("getOwner", + ["0x" + did], + ) + } + + public async getUpdateAt(did: string): Promise { + + const blockNum = await this.call("getUpdateAt", + ["0x" + did], + ) + + return parseInt(blockNum, 10) + } + +} diff --git a/src/keeper/Market.ts b/src/keeper/contracts/Market.ts similarity index 84% rename from src/keeper/Market.ts rename to src/keeper/contracts/Market.ts index b99fa57..bee7d32 100644 --- a/src/keeper/Market.ts +++ b/src/keeper/contracts/Market.ts @@ -1,6 +1,6 @@ import BigNumber from "bignumber.js" import {Receipt} from "web3-utils" -import Order from "../ocean/Order" +import Order from "../../ocean/Order" import ContractBase from "./ContractBase" export default class OceanMarket extends ContractBase { @@ -26,7 +26,7 @@ export default class OceanMarket extends ContractBase { } public async requestTokens(amount: number, receiverAddress: string): Promise { - return this.sendTransaction("requestTokens", receiverAddress, [amount]) + return this.send("requestTokens", receiverAddress, [amount]) } public async generateId(input: string): Promise { @@ -34,13 +34,13 @@ export default class OceanMarket extends ContractBase { } public async register(assetId: string, price: number, publisherAddress: string): Promise { - return this.sendTransaction("register", publisherAddress, ["0x" + assetId, price]) + return this.send("register", publisherAddress, ["0x" + assetId, price]) } public async payOrder(order: Order, publisherAddress: string, price: number, consumerAddress: string, timeout: number): Promise { - return this.sendTransaction("sendPayment", consumerAddress, [ + return this.send("sendPayment", consumerAddress, [ order.getId(), publisherAddress, price, timeout, ]) } diff --git a/src/keeper/contracts/ServiceAgreement.ts b/src/keeper/contracts/ServiceAgreement.ts new file mode 100644 index 0000000..1f3a8c9 --- /dev/null +++ b/src/keeper/contracts/ServiceAgreement.ts @@ -0,0 +1,10 @@ +import ContractBase from "./ContractBase" + +export default class ServiceAgreement extends ContractBase { + + public static async getInstance(): Promise { + const serviceAgreement: ServiceAgreement = new ServiceAgreement("ServiceAgreement") + await serviceAgreement.init() + return serviceAgreement + } +} diff --git a/src/keeper/Token.ts b/src/keeper/contracts/Token.ts similarity index 88% rename from src/keeper/Token.ts rename to src/keeper/contracts/Token.ts index 52e1bc3..1b04255 100644 --- a/src/keeper/Token.ts +++ b/src/keeper/contracts/Token.ts @@ -11,7 +11,7 @@ export default class OceanToken extends ContractBase { } public async approve(marketAddress: string, price: number, buyerAddress: string): Promise { - return this.sendTransaction("approve", buyerAddress, [marketAddress, price]) + return this.send("approve", buyerAddress, [marketAddress, price]) } public async balanceOf(address: string): Promise { diff --git a/src/models/ValueType.ts b/src/models/ValueType.ts new file mode 100644 index 0000000..4310234 --- /dev/null +++ b/src/models/ValueType.ts @@ -0,0 +1,8 @@ +enum ValueType { + DID, // DID string e.g. 'did:op:xxx' + DIDRef, // hash of DID same as in parameter (bytes32 _did) in text 0x0123abc.. or 0123abc.. + URL, // URL string e.g. 'http(s)://xx' + DDO, // DDO string in JSON e.g. '{ "id": "did:op:xxx"... +} + +export default ValueType diff --git a/test/keeper/DIDRegistry.test.ts b/test/keeper/DIDRegistry.test.ts new file mode 100644 index 0000000..86e8469 --- /dev/null +++ b/test/keeper/DIDRegistry.test.ts @@ -0,0 +1,101 @@ +import {assert} from "chai" +import ConfigProvider from "../../src/ConfigProvider" +import ContractHandler from "../../src/keeper/ContractHandler" +import DIDRegistry from "../../src/keeper/contracts/DIDRegistry" +import Web3Provider from "../../src/keeper/Web3Provider" +import ValueType from "../../src/models/ValueType" +import Account from "../../src/ocean/Account" +import IdGenerator from "../../src/ocean/IdGenerator" +import Ocean from "../../src/ocean/Ocean" +import Logger from "../../src/utils/Logger" +import config from "../config" + +let ocean: Ocean +let didRegistry: DIDRegistry + +describe("DIDRegistry", () => { + + before(async () => { + ConfigProvider.setConfig(config) + await ContractHandler.deployContracts() + ocean = await Ocean.getInstance(config) + didRegistry = await DIDRegistry.getInstance() + }) + + describe("#registerAttribute()", () => { + + it("should register an attribute in a new did", async () => { + const ownerAccount: Account = (await ocean.getAccounts())[0] + const did = IdGenerator.generateId() + const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider") + const data = "my nice provider, is nice" + const receipt = await didRegistry.registerAttribute(did, ValueType.DID, providerKey, + data, ownerAccount.getId()) + assert(receipt.status) + assert(receipt.events.DIDAttributeRegistered) + }) + + it("should register another attribute in the same did", async () => { + const ownerAccount: Account = (await ocean.getAccounts())[0] + const did = IdGenerator.generateId() + { + // register the first attribute + const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider") + const data = "my nice provider, is nice" + await didRegistry.registerAttribute(did, ValueType.DID, providerKey, + data, ownerAccount.getId()) + } + { + // register the second attribute with the same did + const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider2") + const data = "asdsad" + const receipt = await didRegistry.registerAttribute(did, ValueType.DID, providerKey, + data, ownerAccount.getId()) + assert(receipt.status) + assert(receipt.events.DIDAttributeRegistered) + } + }) + + }) + + describe("#getOwner()", () => { + + it("should get the owner of a did properly", async () => { + const ownerAccount: Account = (await ocean.getAccounts())[0] + const did = IdGenerator.generateId() + const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider") + const data = "my nice provider, is nice" + await didRegistry.registerAttribute(did, ValueType.DID, providerKey, + data, ownerAccount.getId()) + + const owner = await didRegistry.getOwner(did) + + assert(owner === ownerAccount.getId(), `Got ${owner} but expected ${ownerAccount.getId()}`) + }) + + it("should get 0x00.. for a not registered did", async () => { + const owner = await didRegistry.getOwner("1234") + assert(owner === "0x0000000000000000000000000000000000000000") + }) + + }) + + describe("#getUpdateAt()", () => { + + it("should the block number of the last update of the did attribute", async () => { + const ownerAccount: Account = (await ocean.getAccounts())[0] + const did = IdGenerator.generateId() + const providerKey = Web3Provider.getWeb3().utils.fromAscii("provider") + const data = "my nice provider, is nice" + await didRegistry.registerAttribute(did, ValueType.DID, providerKey, + data, ownerAccount.getId()) + + const updatedAt: number = await didRegistry.getUpdateAt(did) + + assert(updatedAt > 0) + Logger.log(typeof updatedAt) + }) + + }) + +}) diff --git a/test/mocks/ContractBase.Mock.ts b/test/mocks/ContractBase.Mock.ts index e956ef5..1dbef96 100644 --- a/test/mocks/ContractBase.Mock.ts +++ b/test/mocks/ContractBase.Mock.ts @@ -1,4 +1,4 @@ -import ContractBase from "../../src/keeper/ContractBase" +import ContractBase from "../../src/keeper/contracts/ContractBase" export default class ContractBaseMock extends ContractBase { public async initMock() { @@ -10,6 +10,6 @@ export default class ContractBaseMock extends ContractBase { } public async sendMock(name: string, from: string, args: any[]) { - return this.sendTransaction(name, from, args) + return this.send(name, from, args) } }