mirror of
https://github.com/oceanprotocol-archive/squid-js.git
synced 2024-02-02 15:31:51 +01:00
initial implementation of templates and conditions
This commit is contained in:
parent
19287469bc
commit
5ec624b2a5
@ -0,0 +1,109 @@
|
|||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { config } from "../config"
|
||||||
|
|
||||||
|
import { Ocean, templates, conditions, generateId, Keeper } from '../../src' // @oceanprotocol/squid
|
||||||
|
|
||||||
|
const { LockRewardCondition, EscrowReward, AccessSecretStoreCondition } = conditions
|
||||||
|
const { EscrowAccessSecretStoreTemplate } = templates
|
||||||
|
|
||||||
|
describe("Register Escrow Access Secret Store Template", () => {
|
||||||
|
let ocean: Ocean
|
||||||
|
let keeper: Keeper
|
||||||
|
|
||||||
|
const agreementId = `0x${generateId()}`
|
||||||
|
const escrowAmount = 12
|
||||||
|
const did = `0x${"a".repeat(64)}`
|
||||||
|
const url = 'https://example.com/did/ocean/test-attr-example.txt'
|
||||||
|
const checksum = "b".repeat(32)
|
||||||
|
|
||||||
|
let templateManagerOwner: string
|
||||||
|
let sender: string
|
||||||
|
let receiver: string
|
||||||
|
|
||||||
|
let accessSecretStoreCondition: conditions.AccessSecretStoreCondition
|
||||||
|
let lockRewardCondition: conditions.LockRewardCondition
|
||||||
|
let escrowReward: conditions.EscrowReward
|
||||||
|
|
||||||
|
let template: templates.EscrowAccessSecretStoreTemplate
|
||||||
|
|
||||||
|
let conditionIdAccess: string
|
||||||
|
let conditionIdLock: string
|
||||||
|
let conditionIdEscrow: string
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
ocean = await Ocean.getInstance(config)
|
||||||
|
keeper = await Keeper.getInstance()
|
||||||
|
|
||||||
|
template = await EscrowAccessSecretStoreTemplate.getInstance()
|
||||||
|
|
||||||
|
// Accounts
|
||||||
|
templateManagerOwner = (await ocean.accounts.list())[0].getId()
|
||||||
|
sender = (await ocean.accounts.list())[1].getId()
|
||||||
|
receiver = (await ocean.accounts.list())[2].getId()
|
||||||
|
|
||||||
|
// Conditions
|
||||||
|
accessSecretStoreCondition = await AccessSecretStoreCondition.getInstance()
|
||||||
|
lockRewardCondition = await LockRewardCondition.getInstance()
|
||||||
|
escrowReward = await EscrowReward.getInstance()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should propose the template", async () => {
|
||||||
|
await keeper.templateStoreManager.proposeTemplate(template.getAddress(), receiver, true)
|
||||||
|
// TODO: Use a event to detect template mined
|
||||||
|
await new Promise(_ => setTimeout(_, 6 * 1000))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should approve the template", async () => {
|
||||||
|
await keeper.templateStoreManager.approveTemplate(template.getAddress(), templateManagerOwner, true)
|
||||||
|
// TODO: Use a event to detect template mined
|
||||||
|
await new Promise(_ => setTimeout(_, 6 * 1000))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should generate the condition IDs", async () => {
|
||||||
|
conditionIdAccess = await accessSecretStoreCondition.generateId(agreementId, await accessSecretStoreCondition.hashValues(did, receiver))
|
||||||
|
conditionIdLock = await lockRewardCondition.generateIdHash(agreementId, await escrowReward.getAddress(), escrowAmount)
|
||||||
|
conditionIdEscrow = await escrowReward.generateId(agreementId, await escrowReward.hashValues(escrowAmount, receiver, sender, conditionIdLock, conditionIdAccess))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should have conditions types", async () => {
|
||||||
|
const conditionTypes = await template.getConditionTypes()
|
||||||
|
|
||||||
|
assert.equal(conditionTypes.length, 3, "Expected 3 conditions.")
|
||||||
|
assert.deepEqual(
|
||||||
|
[...conditionTypes].sort(),
|
||||||
|
[accessSecretStoreCondition.getAddress(), escrowReward.getAddress(), lockRewardCondition.getAddress()].sort(),
|
||||||
|
"The conditions doesn't match",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should have condition instances asociated", async () => {
|
||||||
|
const conditions = await template.getConditions()
|
||||||
|
|
||||||
|
assert.equal(conditions.length, 3, "Expected 3 conditions.")
|
||||||
|
|
||||||
|
|
||||||
|
const conditionClasses = [AccessSecretStoreCondition, EscrowReward, LockRewardCondition]
|
||||||
|
conditionClasses
|
||||||
|
.forEach(conditionClass => {
|
||||||
|
if (!conditions.find(condition => condition instanceof conditionClass)) {
|
||||||
|
throw `${conditionClass.name} is not part of the conditions.`;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should create a new agreement", async () => {
|
||||||
|
await keeper.didRegistry.registerAttribute(did.replace("0x", ""), checksum, url, sender)
|
||||||
|
|
||||||
|
const agreement = await template.createAgreement(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
[conditionIdAccess, conditionIdLock, conditionIdEscrow],
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 0, 0],
|
||||||
|
receiver,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.isTrue(agreement.status)
|
||||||
|
})
|
||||||
|
})
|
@ -1,28 +0,0 @@
|
|||||||
import { assert } from 'chai'
|
|
||||||
|
|
||||||
import { config } from "../config"
|
|
||||||
|
|
||||||
import { Ocean, Account, ServiceAgreementTemplate, Templates } from '../../src' // @oceanprotocol/squid
|
|
||||||
|
|
||||||
describe("Register Service Agreement Templates", () => {
|
|
||||||
let ocean: Ocean
|
|
||||||
|
|
||||||
let templateOwner: Account
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
ocean = await Ocean.getInstance(config)
|
|
||||||
|
|
||||||
// Accounts
|
|
||||||
templateOwner = (await ocean.accounts.list())[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should regiester a template", async () => {
|
|
||||||
const serviceAgreementTemplate = new ServiceAgreementTemplate(new Templates.Access())
|
|
||||||
const serviceAgreementRegistered = await serviceAgreementTemplate.register(templateOwner.getId())
|
|
||||||
|
|
||||||
try {
|
|
||||||
// It can fail because is already created
|
|
||||||
assert.isTrue(serviceAgreementRegistered, "Service agreement template not registered correctly")
|
|
||||||
} catch (e) { }
|
|
||||||
})
|
|
||||||
})
|
|
@ -59,7 +59,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/oceanprotocol/squid-js#readme",
|
"homepage": "https://github.com/oceanprotocol/squid-js#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oceanprotocol/keeper-contracts": "^0.6.12",
|
"@oceanprotocol/keeper-contracts": "^0.7.0",
|
||||||
"@oceanprotocol/secret-store-client": "~0.0.14",
|
"@oceanprotocol/secret-store-client": "~0.0.14",
|
||||||
"@types/node-fetch": "^2.1.4",
|
"@types/node-fetch": "^2.1.4",
|
||||||
"bignumber.js": "^8.0.1",
|
"bignumber.js": "^8.0.1",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import AccessConditions from "./contracts/conditions/AccessConditions"
|
|
||||||
import PaymentConditions from "./contracts/conditions/PaymentConditions"
|
|
||||||
import DIDRegistry from "./contracts/DIDRegistry"
|
import DIDRegistry from "./contracts/DIDRegistry"
|
||||||
import Dispenser from "./contracts/Dispenser"
|
import Dispenser from "./contracts/Dispenser"
|
||||||
import ServiceExecutionAgreement from "./contracts/ServiceExecutionAgreement"
|
|
||||||
import OceanToken from "./contracts/Token"
|
import OceanToken from "./contracts/Token"
|
||||||
|
import { Condition, LockRewardCondition, EscrowReward, AccessSecretStoreCondition } from "./contracts/conditions"
|
||||||
|
import { EscrowAccessSecretStoreTemplate } from "./contracts/templates"
|
||||||
|
import { TemplateStoreManager } from "./contracts/managers"
|
||||||
|
|
||||||
import Web3Provider from "./Web3Provider"
|
import Web3Provider from "./Web3Provider"
|
||||||
|
|
||||||
@ -21,17 +21,30 @@ export default class Keeper {
|
|||||||
* @return {Promise<Keeper>}
|
* @return {Promise<Keeper>}
|
||||||
*/
|
*/
|
||||||
public static async getInstance(): Promise<Keeper> {
|
public static async getInstance(): Promise<Keeper> {
|
||||||
|
|
||||||
if (Keeper.instance === null) {
|
if (Keeper.instance === null) {
|
||||||
Keeper.instance = new Keeper()
|
Keeper.instance = new Keeper()
|
||||||
|
|
||||||
|
// Main contracts
|
||||||
Keeper.instance.dispenser = await Dispenser.getInstance()
|
Keeper.instance.dispenser = await Dispenser.getInstance()
|
||||||
Keeper.instance.token = await OceanToken.getInstance()
|
Keeper.instance.token = await OceanToken.getInstance()
|
||||||
Keeper.instance.serviceAgreement = await ServiceExecutionAgreement.getInstance()
|
|
||||||
Keeper.instance.accessConditions = await AccessConditions.getInstance()
|
|
||||||
Keeper.instance.paymentConditions = await PaymentConditions.getInstance()
|
|
||||||
Keeper.instance.didRegistry = await DIDRegistry.getInstance()
|
Keeper.instance.didRegistry = await DIDRegistry.getInstance()
|
||||||
|
|
||||||
|
// Managers
|
||||||
|
Keeper.instance.templateStoreManager = await TemplateStoreManager.getInstance()
|
||||||
|
|
||||||
|
// Conditions
|
||||||
|
Keeper.instance.conditions = {
|
||||||
|
lockRewardCondition: await LockRewardCondition.getInstance(),
|
||||||
|
escrowReward: await EscrowReward.getInstance(),
|
||||||
|
accessSecretStoreCondition: await AccessSecretStoreCondition.getInstance(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conditions
|
||||||
|
Keeper.instance.templates = {
|
||||||
|
escrowAccessSecretStoreTemplate: await EscrowAccessSecretStoreTemplate.getInstance(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Keeper.instance
|
return Keeper.instance
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,30 +66,44 @@ export default class Keeper {
|
|||||||
*/
|
*/
|
||||||
public dispenser: Dispenser
|
public dispenser: Dispenser
|
||||||
|
|
||||||
/**
|
|
||||||
* Service agreement smart contract instance.
|
|
||||||
* @type {ServiceExecutionAgreement}
|
|
||||||
*/
|
|
||||||
public serviceAgreement: ServiceExecutionAgreement
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access conditions smart contract instance.
|
|
||||||
* @type {AccessConditions}
|
|
||||||
*/
|
|
||||||
public accessConditions: AccessConditions
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Payment conditions smart contract instance.
|
|
||||||
* @type {PaymentConditions}
|
|
||||||
*/
|
|
||||||
public paymentConditions: PaymentConditions
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DID registry smart contract instance.
|
* DID registry smart contract instance.
|
||||||
* @type {DIDRegistry}
|
* @type {DIDRegistry}
|
||||||
*/
|
*/
|
||||||
public didRegistry: DIDRegistry
|
public didRegistry: DIDRegistry
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template store manager smart contract instance.
|
||||||
|
* @type {TemplateStoreManager}
|
||||||
|
*/
|
||||||
|
public templateStoreManager: TemplateStoreManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conditions instances.
|
||||||
|
*/
|
||||||
|
public conditions: {
|
||||||
|
lockRewardCondition: LockRewardCondition,
|
||||||
|
escrowReward: EscrowReward,
|
||||||
|
accessSecretStoreCondition: AccessSecretStoreCondition,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Templates instances.
|
||||||
|
*/
|
||||||
|
public templates: {
|
||||||
|
escrowAccessSecretStoreTemplate: EscrowAccessSecretStoreTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a condition by address.
|
||||||
|
* @param {string} address Address of deployed condition.
|
||||||
|
* @return {Condition} Condition instance.
|
||||||
|
*/
|
||||||
|
public getConditionByAddress(address: string): Condition {
|
||||||
|
return Object.values(this.conditions)
|
||||||
|
.find(condition => condition.getAddress() === address)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the network by name.
|
* Returns the network by name.
|
||||||
* @return {Promise<string>} Network name.
|
* @return {Promise<string>} Network name.
|
||||||
|
@ -3,6 +3,7 @@ import Contract from "web3-eth-contract"
|
|||||||
import {Receipt} from "web3-utils"
|
import {Receipt} from "web3-utils"
|
||||||
import Logger from "../../utils/Logger"
|
import Logger from "../../utils/Logger"
|
||||||
import ContractHandler from "../ContractHandler"
|
import ContractHandler from "../ContractHandler"
|
||||||
|
import Web3Provider from "../Web3Provider"
|
||||||
|
|
||||||
export default abstract class ContractBase {
|
export default abstract class ContractBase {
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ export default abstract class ContractBase {
|
|||||||
return this.contract.getPastEvents(eventName, options)
|
return this.contract.getPastEvents(eventName, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAddress() {
|
public getAddress(): string {
|
||||||
return this.contract.options.address
|
return this.contract.options.address
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +41,13 @@ export default abstract class ContractBase {
|
|||||||
this.contract = await ContractHandler.get(this.contractName)
|
this.contract = await ContractHandler.get(this.contractName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async sendFrom(name: string, args: any[], from?: string): Promise<Receipt> {
|
||||||
|
if (!from) {
|
||||||
|
from = (await Web3Provider.getWeb3().eth.getAccounts())[0]
|
||||||
|
}
|
||||||
|
return this.send(name, from, args)
|
||||||
|
}
|
||||||
|
|
||||||
protected async send(name: string, from: string, args: any[]): Promise<Receipt> {
|
protected async send(name: string, from: string, args: any[]): Promise<Receipt> {
|
||||||
if (!this.contract.methods[name]) {
|
if (!this.contract.methods[name]) {
|
||||||
throw new Error(`Method "${name}" is not part of contract "${this.contractName}"`)
|
throw new Error(`Method "${name}" is not part of contract "${this.contractName}"`)
|
||||||
@ -73,7 +81,7 @@ export default abstract class ContractBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async call(name: string, args: any[], from?: string): Promise<any> {
|
protected async call<T extends any>(name: string, args: any[], from?: string): Promise<T> {
|
||||||
if (!this.contract.methods[name]) {
|
if (!this.contract.methods[name]) {
|
||||||
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
|
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,6 @@ export default class DIDRegistry extends ContractBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getUpdateAt(did: string): Promise<number> {
|
public async getUpdateAt(did: string): Promise<number> {
|
||||||
const blockNum = await this.call("getUpdateAt", ["0x" + did])
|
return +await this.call("getUpdateAt", ["0x" + did])
|
||||||
|
|
||||||
return parseInt(blockNum, 10)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
import {Receipt} from "web3-utils"
|
|
||||||
import MethodReflection from "../../models/MethodReflection"
|
|
||||||
import DID from "../../ocean/DID"
|
|
||||||
import ContractBase from "./ContractBase"
|
|
||||||
|
|
||||||
export default class ServiceExecutionAgreement extends ContractBase {
|
|
||||||
|
|
||||||
public static async getInstance(): Promise<ServiceExecutionAgreement> {
|
|
||||||
const serviceAgreement: ServiceExecutionAgreement = new ServiceExecutionAgreement("ServiceExecutionAgreement")
|
|
||||||
await serviceAgreement.init()
|
|
||||||
return serviceAgreement
|
|
||||||
}
|
|
||||||
|
|
||||||
public async setupTemplate(
|
|
||||||
templateId: string,
|
|
||||||
methodReflections: MethodReflection[],
|
|
||||||
dependencyMatrix: number[],
|
|
||||||
fulfillmentIndices: number[],
|
|
||||||
fulfillmentOperator: number,
|
|
||||||
ownerAddress: string,
|
|
||||||
): Promise<Receipt> {
|
|
||||||
|
|
||||||
return this.send("setupTemplate", ownerAddress, [
|
|
||||||
templateId, methodReflections.map((r) => r.address),
|
|
||||||
methodReflections.map((r) => r.signature), dependencyMatrix, fulfillmentIndices,
|
|
||||||
fulfillmentOperator,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo get service agreement consumer
|
|
||||||
|
|
||||||
public async getTemplateStatus(templateId: string) {
|
|
||||||
|
|
||||||
return this.call("getTemplateStatus", [templateId])
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getTemplateOwner(templateId: string) {
|
|
||||||
|
|
||||||
return this.call("getTemplateOwner", [templateId])
|
|
||||||
}
|
|
||||||
|
|
||||||
public async initializeAgreement(
|
|
||||||
serviceAgreementTemplateId: string,
|
|
||||||
serviceAgreementSignatureHash: string,
|
|
||||||
consumerAddress: string,
|
|
||||||
valueHashes: string[],
|
|
||||||
timeoutValues: number[],
|
|
||||||
serviceAgreementId: string,
|
|
||||||
did: DID,
|
|
||||||
publisherAddress: string,
|
|
||||||
): Promise<Receipt> {
|
|
||||||
|
|
||||||
return this.send("initializeAgreement", publisherAddress, [
|
|
||||||
serviceAgreementTemplateId, serviceAgreementSignatureHash, consumerAddress, valueHashes,
|
|
||||||
timeoutValues, "0x" + serviceAgreementId, "0x" + did.getId(),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import {Receipt} from "web3-utils"
|
|
||||||
import ContractBase from "../ContractBase"
|
|
||||||
|
|
||||||
export default class AccessConditions extends ContractBase {
|
|
||||||
|
|
||||||
public static async getInstance(): Promise<AccessConditions> {
|
|
||||||
const accessConditions: AccessConditions = new AccessConditions("AccessConditions")
|
|
||||||
await accessConditions.init()
|
|
||||||
return accessConditions
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo add check permissions proxy
|
|
||||||
|
|
||||||
public async grantAccess(serviceAgreementId: any, documentKeyId: any, publisherAddress: string)
|
|
||||||
: Promise<Receipt> {
|
|
||||||
return this.send("grantAccess", publisherAddress, [
|
|
||||||
serviceAgreementId, "0x" + documentKeyId,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,16 @@
|
|||||||
|
import { Condition } from "./Condition.abstract"
|
||||||
|
|
||||||
|
export class AccessSecretStoreCondition extends Condition {
|
||||||
|
|
||||||
|
public static async getInstance(): Promise<AccessSecretStoreCondition> {
|
||||||
|
return Condition.getInstance("AccessSecretStoreCondition", AccessSecretStoreCondition)
|
||||||
|
}
|
||||||
|
|
||||||
|
hashValues(did: string, grantee: string) {
|
||||||
|
return super.hashValues(did, grantee)
|
||||||
|
}
|
||||||
|
|
||||||
|
fulfill(agreementId: string, did: string, grantee: string, from?: string) {
|
||||||
|
return super.fulfill(agreementId, [did, grantee], from)
|
||||||
|
}
|
||||||
|
}
|
43
src/keeper/contracts/conditions/Condition.abstract.ts
Normal file
43
src/keeper/contracts/conditions/Condition.abstract.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import ContractBase from "../ContractBase"
|
||||||
|
|
||||||
|
export enum ConditionState {
|
||||||
|
Uninitialized = 0,
|
||||||
|
Unfulfilled = 1,
|
||||||
|
Fulfilled = 2,
|
||||||
|
Aborted = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class Condition extends ContractBase {
|
||||||
|
|
||||||
|
protected constructor(contractName: string) {
|
||||||
|
super(contractName)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async getInstance(conditionName: string, conditionsClass: any): Promise<Condition> {
|
||||||
|
const condition: Condition = new (conditionsClass as any)(conditionName)
|
||||||
|
await condition.init()
|
||||||
|
return condition
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hashValues(...args: any[]): Promise<string> {
|
||||||
|
return this.call("hashValues", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fulfill(agreementId: string, ...args: any[]): Promise<ConditionState>
|
||||||
|
fulfill(agreementId: string, args: any[], from?: string): Promise<ConditionState> {
|
||||||
|
return this.sendFrom("fulfill", args, from)
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateIdHash(agreementId: string, ...values: any[]): Promise<string> {
|
||||||
|
return this.generateId(agreementId, await this.hashValues(...values))
|
||||||
|
}
|
||||||
|
|
||||||
|
generateId(agreementId: string, valueHash: string): Promise<string> {
|
||||||
|
return this.call("generateId", [agreementId, valueHash])
|
||||||
|
}
|
||||||
|
|
||||||
|
abortByTimeOut(agreementId: string, from?: string): Promise<ConditionState> {
|
||||||
|
return this.sendFrom("requestTokens", [agreementId], from)
|
||||||
|
}
|
||||||
|
}
|
24
src/keeper/contracts/conditions/EscrowReward.ts
Normal file
24
src/keeper/contracts/conditions/EscrowReward.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Condition } from "./Condition.abstract"
|
||||||
|
|
||||||
|
export class EscrowReward extends Condition {
|
||||||
|
|
||||||
|
public static async getInstance(): Promise<EscrowReward> {
|
||||||
|
return Condition.getInstance("EscrowReward", EscrowReward)
|
||||||
|
}
|
||||||
|
|
||||||
|
hashValues(amount: number, receiver: string, sender: string, lockCondition: string, releaseCondition: string) {
|
||||||
|
return super.hashValues(amount, receiver, sender, lockCondition, releaseCondition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fulfill(
|
||||||
|
agreementId: string,
|
||||||
|
amount: number,
|
||||||
|
receiver: string,
|
||||||
|
sender: string,
|
||||||
|
lockCondition: string,
|
||||||
|
releaseCondition: string,
|
||||||
|
from?: string,
|
||||||
|
) {
|
||||||
|
return super.fulfill(agreementId, [amount, receiver, sender, lockCondition, releaseCondition], from)
|
||||||
|
}
|
||||||
|
}
|
16
src/keeper/contracts/conditions/LockRewardCondition.ts
Normal file
16
src/keeper/contracts/conditions/LockRewardCondition.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Condition } from "./Condition.abstract"
|
||||||
|
|
||||||
|
export class LockRewardCondition extends Condition {
|
||||||
|
|
||||||
|
public static async getInstance(): Promise<LockRewardCondition> {
|
||||||
|
return Condition.getInstance("LockRewardCondition", LockRewardCondition)
|
||||||
|
}
|
||||||
|
|
||||||
|
hashValues(rewardAddress: string, amount: number) {
|
||||||
|
return super.hashValues(rewardAddress, amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
fulfill(agreementId: string, rewardAddress: string, amount: number, from?: string) {
|
||||||
|
return super.fulfill(agreementId, [rewardAddress, amount], from)
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
import {Receipt} from "web3-utils"
|
|
||||||
import ContractBase from "../ContractBase"
|
|
||||||
|
|
||||||
export default class PaymentConditions extends ContractBase {
|
|
||||||
|
|
||||||
public static async getInstance(): Promise<PaymentConditions> {
|
|
||||||
const paymentConditions: PaymentConditions = new PaymentConditions("PaymentConditions")
|
|
||||||
await paymentConditions.init()
|
|
||||||
return paymentConditions
|
|
||||||
}
|
|
||||||
|
|
||||||
public async lockPayment(serviceAgreementId: string, assetId: string, price: number, consumerAddress: string)
|
|
||||||
: Promise<Receipt> {
|
|
||||||
return this.send("lockPayment", consumerAddress, [
|
|
||||||
serviceAgreementId, "0x" + assetId, price,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
4
src/keeper/contracts/conditions/index.ts
Normal file
4
src/keeper/contracts/conditions/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export * from './Condition.abstract'
|
||||||
|
export { AccessSecretStoreCondition } from './AccessSecretStoreCondition'
|
||||||
|
export { EscrowReward } from './EscrowReward'
|
||||||
|
export { LockRewardCondition } from './LockRewardCondition'
|
62
src/keeper/contracts/managers/TemplateStoreManager.ts
Normal file
62
src/keeper/contracts/managers/TemplateStoreManager.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import Logger from "../../../utils/Logger"
|
||||||
|
import ContractBase from "../ContractBase"
|
||||||
|
|
||||||
|
export enum TemplateState {
|
||||||
|
Uninitialized = 0,
|
||||||
|
Proposed = 1,
|
||||||
|
Approved = 2,
|
||||||
|
Revoked = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TemplateMetadata {
|
||||||
|
state: TemplateState,
|
||||||
|
owner: string,
|
||||||
|
lastUpdatedBy: string,
|
||||||
|
blockNumberUpdated: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TemplateStoreManager extends ContractBase {
|
||||||
|
|
||||||
|
public static async getInstance(): Promise<TemplateStoreManager> {
|
||||||
|
const templateStoreManeger: TemplateStoreManager = new TemplateStoreManager("TemplateStoreManager")
|
||||||
|
await templateStoreManeger.init()
|
||||||
|
return templateStoreManeger
|
||||||
|
}
|
||||||
|
|
||||||
|
getOwner(): Promise<string> {
|
||||||
|
return this.call("owner", [])
|
||||||
|
}
|
||||||
|
|
||||||
|
public async proposeTemplate(address: string, from?: string, ignoreExists?: boolean) {
|
||||||
|
const template = await this.getTemplate(address)
|
||||||
|
if (template.blockNumberUpdated !== 0) {
|
||||||
|
Logger.warn(`Template "${address}" already exist.`)
|
||||||
|
if (!ignoreExists) {
|
||||||
|
throw new Error("Template already exist.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.sendFrom("proposeTemplate", [address], from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async approveTemplate(address: string, from?: string, ignoreApproved?: boolean) {
|
||||||
|
const template = await this.getTemplate(address)
|
||||||
|
if (template.state !== TemplateState.Proposed) {
|
||||||
|
Logger.warn(`Template "${address}" is not in "proposed" state.`)
|
||||||
|
if (!ignoreApproved) {
|
||||||
|
throw new Error(`Template not in "proposed" state.`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.sendFrom("approveTemplate", [address], from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public revokeTemplate(address: string, from?: string) {
|
||||||
|
return this.sendFrom("revokeTemplate", [address], from)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getTemplate(address: string) {
|
||||||
|
const {state, owner, lastUpdatedBy, blockNumberUpdated} = await this.call("getTemplate", [address])
|
||||||
|
return {state: +state, owner, lastUpdatedBy, blockNumberUpdated: +blockNumberUpdated} as TemplateMetadata
|
||||||
|
}
|
||||||
|
}
|
1
src/keeper/contracts/managers/index.ts
Normal file
1
src/keeper/contracts/managers/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './TemplateStoreManager'
|
52
src/keeper/contracts/templates/AgreementTemplate.abstract.ts
Normal file
52
src/keeper/contracts/templates/AgreementTemplate.abstract.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import ContractBase from "../ContractBase"
|
||||||
|
import { Condition } from "../conditions/Condition.abstract"
|
||||||
|
import Keeper from "../../Keeper"
|
||||||
|
|
||||||
|
export abstract class AgreementTemplate extends ContractBase {
|
||||||
|
|
||||||
|
protected constructor(contractName: string) {
|
||||||
|
super(contractName)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async getInstance(conditionName: string, templateClass: any): Promise<AgreementTemplate> {
|
||||||
|
const condition: AgreementTemplate = new (templateClass as any)(conditionName)
|
||||||
|
await condition.init()
|
||||||
|
return condition
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line
|
||||||
|
public createAgreement(agreementId: string, did: string, conditionIds: string[], timeLocks: number[], timeOuts: number[], ...args: any[])
|
||||||
|
public createAgreement(
|
||||||
|
agreementId: string,
|
||||||
|
did: string,
|
||||||
|
conditionIds: string[],
|
||||||
|
timeLocks: number[],
|
||||||
|
timeOuts: number[],
|
||||||
|
extraArgs: any[],
|
||||||
|
from?: string,
|
||||||
|
) {
|
||||||
|
return this.sendFrom(
|
||||||
|
"createAgreement",
|
||||||
|
[
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
conditionIds,
|
||||||
|
timeLocks,
|
||||||
|
timeOuts,
|
||||||
|
...extraArgs,
|
||||||
|
],
|
||||||
|
from,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getConditionTypes(): Promise<string[]> {
|
||||||
|
return this.call("getConditionTypes", [])
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getConditions(): Promise<Condition[]> {
|
||||||
|
const keeper = await Keeper.getInstance()
|
||||||
|
return (await this.getConditionTypes())
|
||||||
|
.map(address => keeper.getConditionByAddress(address))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
import { AgreementTemplate } from "./AgreementTemplate.abstract"
|
||||||
|
|
||||||
|
export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
|
||||||
|
|
||||||
|
public static async getInstance(): Promise<EscrowAccessSecretStoreTemplate> {
|
||||||
|
return AgreementTemplate.getInstance("EscrowAccessSecretStoreTemplate", EscrowAccessSecretStoreTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
public createAgreement(
|
||||||
|
agreementId: string,
|
||||||
|
did: string,
|
||||||
|
conditionIds: string[],
|
||||||
|
timeLocks: number[],
|
||||||
|
timeOuts: number[],
|
||||||
|
accessConsumer: string,
|
||||||
|
from?: string,
|
||||||
|
) {
|
||||||
|
return super.createAgreement(
|
||||||
|
agreementId,
|
||||||
|
did,
|
||||||
|
conditionIds,
|
||||||
|
timeLocks,
|
||||||
|
timeOuts,
|
||||||
|
[accessConsumer],
|
||||||
|
from,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
2
src/keeper/contracts/templates/index.ts
Normal file
2
src/keeper/contracts/templates/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './AgreementTemplate.abstract'
|
||||||
|
export { EscrowAccessSecretStoreTemplate } from './EscrowAccessSecretStoreTemplate'
|
@ -115,7 +115,7 @@ export default class ServiceAgreement extends OceanBase {
|
|||||||
publisher: Account,
|
publisher: Account,
|
||||||
): Promise<ServiceAgreement> {
|
): Promise<ServiceAgreement> {
|
||||||
|
|
||||||
const {serviceAgreement} = await Keeper.getInstance()
|
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||||
|
|
||||||
const service = ddo.findServiceById<"Access">(serviceDefinitionId)
|
const service = ddo.findServiceById<"Access">(serviceDefinitionId)
|
||||||
|
|
||||||
@ -228,7 +228,7 @@ export default class ServiceAgreement extends OceanBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async payAsset(assetId: string, price: number, consumer: Account): Promise<boolean> {
|
public async payAsset(assetId: string, price: number, consumer: Account): Promise<boolean> {
|
||||||
const {paymentConditions, token} = await Keeper.getInstance()
|
const {paymentConditions, token} = <any>await Keeper.getInstance()
|
||||||
|
|
||||||
await token.approve(paymentConditions.getAddress(), price, consumer.getId())
|
await token.approve(paymentConditions.getAddress(), price, consumer.getId())
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ export default class ServiceAgreement extends OceanBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async grantAccess(documentId: string, publisher: Account): Promise<boolean> {
|
public async grantAccess(documentId: string, publisher: Account): Promise<boolean> {
|
||||||
const {accessConditions} = await Keeper.getInstance()
|
const {accessConditions} = <any>await Keeper.getInstance()
|
||||||
|
|
||||||
const grantAccessReceipt =
|
const grantAccessReceipt =
|
||||||
await accessConditions.grantAccess(this.getId(), documentId, publisher.getId())
|
await accessConditions.grantAccess(this.getId(), documentId, publisher.getId())
|
||||||
|
@ -39,7 +39,7 @@ export default class ServiceAgreementTemplate extends OceanBase {
|
|||||||
.map((method: Method, i: number) => method.isTerminalCondition ? i : null)
|
.map((method: Method, i: number) => method.isTerminalCondition ? i : null)
|
||||||
.filter((index: number) => index !== null)
|
.filter((index: number) => index !== null)
|
||||||
|
|
||||||
const {serviceAgreement} = await Keeper.getInstance()
|
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||||
|
|
||||||
const owner = await this.getOwner()
|
const owner = await this.getOwner()
|
||||||
|
|
||||||
@ -91,12 +91,12 @@ export default class ServiceAgreementTemplate extends OceanBase {
|
|||||||
* gets the status of a service agreement template
|
* gets the status of a service agreement template
|
||||||
*/
|
*/
|
||||||
public async getStatus(): Promise<boolean> {
|
public async getStatus(): Promise<boolean> {
|
||||||
const {serviceAgreement} = await Keeper.getInstance()
|
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||||
return serviceAgreement.getTemplateStatus(this.getId())
|
return serviceAgreement.getTemplateStatus(this.getId())
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getOwner(): Promise<Account> {
|
public async getOwner(): Promise<Account> {
|
||||||
const {serviceAgreement} = await Keeper.getInstance()
|
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||||
|
|
||||||
return new Account(await serviceAgreement.getTemplateOwner(this.id))
|
return new Account(await serviceAgreement.getTemplateOwner(this.id))
|
||||||
}
|
}
|
||||||
|
22
src/squid.ts
22
src/squid.ts
@ -2,21 +2,21 @@ import Config from "./models/Config"
|
|||||||
import Account from "./ocean/Account"
|
import Account from "./ocean/Account"
|
||||||
import DID from "./ocean/DID"
|
import DID from "./ocean/DID"
|
||||||
import Ocean from "./ocean/Ocean"
|
import Ocean from "./ocean/Ocean"
|
||||||
import ServiceAgreement from "./ocean/ServiceAgreements/ServiceAgreement"
|
|
||||||
import ServiceAgreementTemplate from "./ocean/ServiceAgreements/ServiceAgreementTemplate"
|
|
||||||
import Access from "./ocean/ServiceAgreements/Templates/Access"
|
|
||||||
import FitchainCompute from "./ocean/ServiceAgreements/Templates/FitchainCompute"
|
|
||||||
import SecretStoreProvider from "./secretstore/SecretStoreProvider"
|
|
||||||
import Logger from "./utils/Logger"
|
import Logger from "./utils/Logger"
|
||||||
import WebServiceConnectorProvider from "./utils/WebServiceConnectorProvider"
|
import WebServiceConnectorProvider from "./utils/WebServiceConnectorProvider"
|
||||||
|
import Keeper from "./keeper/Keeper"
|
||||||
import EventListener from "./keeper/EventListener"
|
import EventListener from "./keeper/EventListener"
|
||||||
|
|
||||||
|
import * as templates from "./keeper/contracts/templates"
|
||||||
|
import * as conditions from "./keeper/contracts/conditions"
|
||||||
|
|
||||||
// Exports
|
// Exports
|
||||||
export * from "./ddo/DDO"
|
export * from "./ddo/DDO"
|
||||||
export * from "./ddo/MetaData"
|
export * from "./ddo/MetaData"
|
||||||
|
export { generateId } from "./utils/GeneratorHelpers"
|
||||||
|
|
||||||
const Templates = {Access, FitchainCompute}
|
export { AgreementTemplate } from "./keeper/contracts/templates"
|
||||||
|
export { Condition } from "./keeper/contracts/conditions"
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Ocean,
|
Ocean,
|
||||||
@ -25,10 +25,10 @@ export {
|
|||||||
Config,
|
Config,
|
||||||
DID,
|
DID,
|
||||||
EventListener,
|
EventListener,
|
||||||
|
Keeper,
|
||||||
Logger,
|
Logger,
|
||||||
SecretStoreProvider,
|
|
||||||
ServiceAgreement,
|
|
||||||
ServiceAgreementTemplate,
|
|
||||||
Templates,
|
|
||||||
WebServiceConnectorProvider,
|
WebServiceConnectorProvider,
|
||||||
|
|
||||||
|
conditions,
|
||||||
|
templates,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user