1
0
mirror of https://github.com/oceanprotocol-archive/squid-js.git synced 2024-02-02 15:31:51 +01:00

Upgrade asset.create, asset.order and agreement related methods to work with Keeper 0.8.x.

This commit is contained in:
Pedro Gutiérrez 2019-03-14 15:47:31 +01:00 committed by Pedro Gutiérrez
parent b1715be11a
commit c976d52378
12 changed files with 322 additions and 254 deletions

View File

@ -1,118 +0,0 @@
import { assert } from 'chai'
import { config } from "../config"
import { Ocean, MetaData, DDO, DID, Account, ServiceAgreement } from '../../src' // @oceanprotocol/squid
describe("Buy Asset", () => {
let ocean: Ocean
let publisher: Account
let consumer: Account
let metadata: Partial<MetaData>
let ddo: DDO
let did: DID
let serviceAgreementSignatureResult: {agreementId: string, signature: string}
let serviceAgreement: ServiceAgreement
before(async () => {
ocean = await Ocean.getInstance(config)
// Accounts
publisher = (await ocean.accounts.list())[0]
publisher.setPassword(process.env.ACCOUNT_PASSWORD)
consumer = (await ocean.accounts.list())[1]
// Data
metadata = {
base: {
name: "Office Humidity",
type: "dataset",
description: "Weather information of UK including temperature and humidity",
size: "3.1gb",
dateCreated: "2012-02-01T10:55:11+00:00",
author: "Met Office",
license: "CC-BY",
copyrightHolder: "Met Office",
encoding: "UTF-8",
compression: "zip",
contentType: "text/csv",
// tslint:disable-next-line
workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
files: [
{
url: "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
checksum: "085340abffh21495345af97c6b0e761",
contentLength: "12324",
},
{
url: "https://testocnfiles.blob.core.windows.net/testfiles/testzkp2.zip",
},
],
links: [
{sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"},
{sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"},
{fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"},
],
inLanguage: "en",
tags: "weather, uk, 2011, temperature, humidity",
price: 10,
},
}
})
it("should regiester a asset", async () => {
ddo = await ocean.assets.create(metadata as any, publisher)
did = DID.parse(ddo.id)
assert.isDefined(ddo, "Register has not returned a DDO")
assert.match(ddo.id, /^did:op:[a-f0-9]{64}$/, "DDO id is not valid")
assert.isAtLeast(ddo.authentication.length, 1, "Default authentication not added")
assert.isDefined(ddo.findServiceByType("Access"), "DDO Access service doesn't exist")
})
it("should be able to request tokens for consumer", async () => {
const initialBalance = (await consumer.getBalance()).ocn;
await consumer.requestTokens(metadata.base.price)
assert.equal((await consumer.getBalance()).ocn, initialBalance + metadata.base.price, "OCN Tokens not delivered")
})
it("should sign the service agreement", async () => {
const accessService = ddo.findServiceByType("Access")
serviceAgreementSignatureResult = await ocean.agreements.prepare(ddo.id, accessService.serviceDefinitionId, consumer)
const {agreementId, signature} = serviceAgreementSignatureResult
assert.match(agreementId, /^[a-f0-9]{64}$/, "Service agreement ID seems not valid")
assert.match(signature, /^0x[a-f0-9]{130}$/, "Service agreement signature seems not valid")
})
it("should execute the service agreement", async () => {
const accessService = ddo.findServiceByType("Access")
serviceAgreement = await ocean.agreements.create(
ddo.id,
accessService.serviceDefinitionId,
serviceAgreementSignatureResult.agreementId,
serviceAgreementSignatureResult.signature,
consumer,
publisher,
)
assert.match(serviceAgreement.getId(), /^0x[a-f0-9]{64}$/, "Service agreement ID seems not valid")
})
it("should pay asset trough the service agreement", async () => {
const paid = await serviceAgreement.payAsset(did.getId(), metadata.base.price, consumer)
assert.isTrue(paid, "The asset has not been paid correctly")
})
xit("should consume the assets", async () => {
const accessService = ddo.findServiceByType("Access")
await ocean.assets.consume(serviceAgreementSignatureResult.agreementId, ddo.id, accessService.serviceDefinitionId, consumer)
})
})

View File

@ -0,0 +1,110 @@
import { assert } from "chai"
import * as Web3 from "web3";
import * as fs from "fs";
import { config } from "../config"
import { Ocean, MetaData, Account, DDO } from "../../src" // @oceanprotocol/squid
describe("Consume Asset (Brizo)", () => {
let ocean: Ocean
let publisher: Account
let consumer: Account
let ddo: DDO
let agreementId: string
const testHash = Math.random().toString(36).substr(2)
let metadata: Partial<MetaData>
let metadataGenerator = (name: string) => ({
...metadata,
base: {
...metadata.base,
name: `${name}${testHash}`,
},
})
before(async () => {
ocean = await Ocean.getInstance({
...config,
web3Provider: new Web3.providers.HttpProvider("http://localhost:8545", 0, "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e", "node0"),
})
// Accounts
publisher = new Account("0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e")
publisher.setPassword("node0")
consumer = new Account("0x068Ed00cF0441e4829D9784fCBe7b9e26D4BD8d0")
consumer.setPassword("secret")
// Data
metadata = {
base: {
name: undefined,
type: "dataset",
description: "Weather information of UK including temperature and humidity",
size: "3.1gb",
dateCreated: "2012-02-01T10:55:11+00:00",
author: "Met Office",
license: "CC-BY",
copyrightHolder: "Met Office",
encoding: "UTF-8",
compression: "zip",
contentType: "text/csv",
// tslint:disable-next-line
workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
files: [
{
url: "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.pdf",
checksum: "085340abffh21495345af97c6b0e761",
contentLength: "12324",
},
{
url: "https://raw.githubusercontent.com/oceanprotocol/squid-js/develop/README.md",
},
],
links: [
{sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"},
{sample2: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"},
{fieldsDescription: "http://data.ceda.ac.uk/badc/ukcp09/"},
],
inLanguage: "en",
tags: "weather, uk, 2011, temperature, humidity",
price: 10,
},
}
})
it("should regiester an asset", async () => {
ddo = await ocean.assets.create(metadataGenerator("ToBeConsumed") as any, publisher);
assert.instanceOf(ddo, DDO)
})
it("should order the asset", async () => {
const accessService = ddo.findServiceByType("Access")
await consumer.requestTokens(metadata.base.price)
agreementId = await ocean.assets.order(ddo.id, accessService.serviceDefinitionId, consumer)
assert.isDefined(agreementId)
})
it("should consume and store the assets", async () => {
const accessService = ddo.findServiceByType("Access")
const folder = "/tmp/ocean/squid-js"
const path = await ocean.assets.consume(agreementId, ddo.id, accessService.serviceDefinitionId, consumer, folder)
assert.include(path, folder, "The storage path is not correct.")
const files = await new Promise(resolve => {
fs.readdir(path, (err, files) => {
resolve(files)
});
})
assert.deepEqual(files, ["README.md", "testzkp.pdf"], "Stored files are not correct.")
})
})

129
package-lock.json generated
View File

@ -129,9 +129,9 @@
}
},
"@oceanprotocol/keeper-contracts": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/@oceanprotocol/keeper-contracts/-/keeper-contracts-0.8.2.tgz",
"integrity": "sha512-NGAscVL6FScs9goCI1zD1nhbFrjbfoUvZYlW1zZMC82teVzgdxVUkefJe3kXW3ocjGUHS4eqjOwtx3y2/E2iCg=="
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/@oceanprotocol/keeper-contracts/-/keeper-contracts-0.8.5.tgz",
"integrity": "sha512-GRVsKAAX60PikLyeA6SEPm1NKOPCHW5C225H4Cpe+hww+qEbGu7Y2/Y+svWSXzfxElUanRZBdZfiEx4tdudIoQ=="
},
"@oceanprotocol/secret-store-client": {
"version": "0.0.14",
@ -189,10 +189,13 @@
}
},
"@types/handlebars": {
"version": "4.0.40",
"resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.40.tgz",
"integrity": "sha512-sGWNtsjNrLOdKha2RV1UeF8+UbQnPSG7qbe5wwbni0mw4h2gHXyPFUMOC+xwGirIiiydM/HSqjDO4rk6NFB18w==",
"dev": true
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.1.0.tgz",
"integrity": "sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA==",
"dev": true,
"requires": {
"handlebars": "*"
}
},
"@types/highlight.js": {
"version": "9.12.3",
@ -201,9 +204,9 @@
"dev": true
},
"@types/lodash": {
"version": "4.14.122",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.122.tgz",
"integrity": "sha512-9IdED8wU93ty8gP06ninox+42SBSJHp2IAamsSYMUY76mshRTeUsid/gtbl8ovnOwy8im41ib4cxTiIYMXGKew==",
"version": "4.14.123",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz",
"integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==",
"dev": true
},
"@types/marked": {
@ -225,9 +228,9 @@
"dev": true
},
"@types/node": {
"version": "10.12.29",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.29.tgz",
"integrity": "sha512-J/tnbnj8HcsBgCe2apZbdUpQ7hs4d7oZNTYA5bekWdP0sr2NGsOpI/HRdDroEi209tEvTcTtxhD0FfED3DhEcw=="
"version": "10.14.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.1.tgz",
"integrity": "sha512-Rymt08vh1GaW4vYB6QP61/5m/CFLGnFZP++bJpWbiNxceNa6RBipDmb413jvtSf/R1gg5a/jQVl2jY4XVRscEA=="
},
"@types/node-fetch": {
"version": "2.1.6",
@ -238,9 +241,9 @@
},
"dependencies": {
"@types/node": {
"version": "11.10.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.10.4.tgz",
"integrity": "sha512-wa09itaLE8L705aXd8F80jnFpxz3Y1/KRHfKsYL2bPc0XF+wEWu8sR9n5bmeu8Ba1N9z2GRNzm/YdHcghLkLKg=="
"version": "11.11.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.3.tgz",
"integrity": "sha512-wp6IOGu1lxsfnrD+5mX6qwSwWuqsdkKKxTN4aQc4wByHAKZJf9/D4KXPQ1POUjEbnCP5LMggB0OEFNY9OTsMqg=="
}
}
},
@ -2366,14 +2369,32 @@
}
},
"find-cache-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz",
"integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
"dev": true,
"requires": {
"commondir": "^1.0.1",
"make-dir": "^1.0.0",
"make-dir": "^2.0.0",
"pkg-dir": "^3.0.0"
},
"dependencies": {
"make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"dev": true,
"requires": {
"pify": "^4.0.1",
"semver": "^5.6.0"
}
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true
}
}
},
"find-up": {
@ -4323,9 +4344,9 @@
}
},
"nan": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
"integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw=="
"version": "2.13.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.0.tgz",
"integrity": "sha512-5DDQvN0luhXdut8SCwzm/ZuAX2W+fwhqNzfq7CZ+OJzQ6NwpcqmIGyLD1R8MEt7BeErzcsI0JLr4pND2pNp2Cw=="
},
"nano-json-stream-parser": {
"version": "0.1.2",
@ -6175,9 +6196,9 @@
}
},
"rollup": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.4.1.tgz",
"integrity": "sha512-YWf5zeR6SWtqZmCnuYs4a+ZJetj8NT4yfBMPXekWHW4L3144jM+J2AWagQVejB0FwCqjEUP9l8o4hg1rPDfQlg==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-1.6.0.tgz",
"integrity": "sha512-qu9iWyuiOxAuBM8cAwLuqPclYdarIpayrkfQB7aTGTiyYPbvx+qVF33sIznfq4bxZCiytQux/FvZieUBAXivCw==",
"dev": true,
"requires": {
"@types/estree": "0.0.39",
@ -6186,9 +6207,9 @@
},
"dependencies": {
"@types/node": {
"version": "11.10.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.10.4.tgz",
"integrity": "sha512-wa09itaLE8L705aXd8F80jnFpxz3Y1/KRHfKsYL2bPc0XF+wEWu8sR9n5bmeu8Ba1N9z2GRNzm/YdHcghLkLKg==",
"version": "11.11.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.3.tgz",
"integrity": "sha512-wp6IOGu1lxsfnrD+5mX6qwSwWuqsdkKKxTN4aQc4wByHAKZJf9/D4KXPQ1POUjEbnCP5LMggB0OEFNY9OTsMqg==",
"dev": true
}
}
@ -6614,9 +6635,9 @@
}
},
"source-map-support": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz",
"integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==",
"version": "0.5.11",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz",
"integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
@ -6894,20 +6915,20 @@
}
},
"terser": {
"version": "3.16.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-3.16.1.tgz",
"integrity": "sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==",
"version": "3.17.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
"integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==",
"dev": true,
"requires": {
"commander": "~2.17.1",
"commander": "^2.19.0",
"source-map": "~0.6.1",
"source-map-support": "~0.5.9"
"source-map-support": "~0.5.10"
},
"dependencies": {
"commander": {
"version": "2.17.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
"integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
"dev": true
},
"source-map": {
@ -7155,9 +7176,9 @@
"dev": true
},
"tslint": {
"version": "5.13.1",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.13.1.tgz",
"integrity": "sha512-fplQqb2miLbcPhyHoMV4FU9PtNRbgmm/zI5d3SZwwmJQM6V0eodju+hplpyfhLWpmwrDNfNYU57uYRb8s0zZoQ==",
"version": "5.14.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz",
"integrity": "sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==",
"dev": true,
"requires": {
"babel-code-frame": "^6.22.0",
@ -7172,7 +7193,7 @@
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.8.0",
"tsutils": "^2.27.2"
"tsutils": "^2.29.0"
},
"dependencies": {
"commander": {
@ -7477,9 +7498,9 @@
}
},
"upath": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
"integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
"integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
"dev": true
},
"uri-js": {
@ -7997,16 +8018,22 @@
}
},
"mem": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz",
"integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz",
"integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==",
"dev": true,
"requires": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^1.0.0",
"mimic-fn": "^2.0.0",
"p-is-promise": "^2.0.0"
}
},
"mimic-fn": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz",
"integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==",
"dev": true
},
"os-locale": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",

View File

@ -59,7 +59,7 @@
},
"homepage": "https://github.com/oceanprotocol/squid-js#readme",
"dependencies": {
"@oceanprotocol/keeper-contracts": "^0.8.2",
"@oceanprotocol/keeper-contracts": "^0.8.5",
"@oceanprotocol/secret-store-client": "~0.0.14",
"@types/node-fetch": "^2.1.4",
"bignumber.js": "^8.0.1",

View File

@ -69,7 +69,7 @@ export default abstract class ContractBase {
})
return tx
} catch (err) {
const mappedArgs = this.searchMethod(name).inputs.map((input, i) => {
const mappedArgs = this.searchMethod(name, args).inputs.map((input, i) => {
return {
name: input.name,
value: args[i],
@ -99,10 +99,11 @@ export default abstract class ContractBase {
}
}
private searchMethod(methodName: string) {
const foundMethod = this.contract.options.jsonInterface
private searchMethod(methodName: string, args: any[] = []) {
const methods = this.contract.options.jsonInterface
.map(method => ({...method, signature: (method as any).signature}))
.find((method: any) => method.name === methodName)
.filter((method: any) => method.name === methodName)
const foundMethod = methods.find(({inputs}) => inputs.length === args.length) || methods[0]
if (!foundMethod) {
throw new Error(`Method "${methodName}" is not part of contract "${this.contractName}"`)
}

View File

@ -1,5 +1,5 @@
import { Condition } from "./Condition.abstract"
import { zeroX } from "../../../utils"
import { zeroX, didZeroX } from "../../../utils"
export class AccessSecretStoreCondition extends Condition {
@ -12,10 +12,10 @@ export class AccessSecretStoreCondition extends Condition {
}
fulfill(agreementId: string, did: string, grantee: string, from?: string) {
return super.fulfill(agreementId, [did, grantee].map(zeroX), from)
return super.fulfill(agreementId, [didZeroX(did), grantee].map(zeroX), from)
}
checkPermissions(grantee: string, did: string, from?: string) {
return this.call<boolean>("checkPermissions", [grantee, did].map(zeroX), from)
return this.call<boolean>("checkPermissions", [grantee, didZeroX(did)].map(zeroX), from)
}
}

View File

@ -1,5 +1,7 @@
import ContractBase from "../ContractBase"
import { zeroX } from "../../../utils"
import EventListener from "../../../keeper/EventListener"
import Event from "../../../keeper/Event"
export enum ConditionState {
Uninitialized = 0,
@ -43,4 +45,13 @@ export abstract class Condition extends ContractBase {
abortByTimeOut(agreementId: string, from?: string) {
return this.sendFrom("abortByTimeOut", [zeroX(agreementId)], from)
}
public getConditionFulfilledEvent(agreementId: string): Event {
return EventListener
.subscribe(
this.contractName,
"Fulfilled",
{agreementId: zeroX(agreementId)},
)
}
}

View File

@ -5,6 +5,8 @@ import Keeper from "../../Keeper"
import { DDO } from '../../../ddo/DDO'
import { ServiceAgreementTemplate } from '../../../ddo/ServiceAgreementTemplate'
import { zeroX, Logger } from "../../../utils"
import EventListener from "../../../keeper/EventListener"
import Event from "../../../keeper/Event"
export abstract class AgreementTemplate extends ContractBase {
@ -43,17 +45,41 @@ export abstract class AgreementTemplate extends ContractBase {
)
}
/**
* Conditions address list.
* @return {Promise<string[]>} Conditions address.
*/
public getConditionTypes(): Promise<string[]> {
return this.call("getConditionTypes", [])
}
/**
* List of condition contracts.
* @return {Promise<Condition[]>} Conditions contracts.
*/
public async getConditions(): Promise<Condition[]> {
const keeper = await Keeper.getInstance()
return (await this.getConditionTypes())
.map(address => keeper.getConditionByAddress(address))
}
abstract getAgreementIdsFromDDO(agreementId: string, ddo: DDO, from: string): Promise<string[]>
/**
* Get agreement conditions IDs.
* @param {string} agreementId Agreement ID.
* @param {DDO} ddo DDO.
* @param {string} from Consumer address.
* @return {Promise<string[]>} Condition IDs.
*/
abstract getAgreementIdsFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string): Promise<string[]>
/**
* Create a new agreement using the data of a DDO.
* @param {string} agreementId Agreement ID.
* @param {DDO} ddo DDO.
* @param {string} from Creator address.
* @return {Promise<boolean>} Success.
*/
abstract createAgreementFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string): Promise<boolean>
abstract async getServiceAgreementTemplate(): Promise<ServiceAgreementTemplate>
@ -90,12 +116,18 @@ export abstract class AgreementTemplate extends ContractBase {
blocked: boolean,
blockedBy: string[]
}
}> {
} | false> {
const agreementStore = await AgreementStoreManager.getInstance()
const conditionStore = await ConditionStoreManager.getInstance()
const dependencies = await this.getServiceAgreementTemplateDependencies()
const {conditionIds} = await agreementStore.getAgreement(agreementId)
if (!conditionIds.length) {
Logger.error(`Agreement not creeated yet: "${agreementId}"`)
return false
}
const conditionIdByConddition = (await this.getConditions())
.reduce((acc, {contractName}, i) => ({...acc, [contractName]: conditionIds[i]}), {})
@ -139,7 +171,10 @@ export abstract class AgreementTemplate extends ContractBase {
Logger.bypass("Template:", this.contractName)
Logger.bypass("Agreement ID:", agreementId)
Logger.bypass("-".repeat(40))
Object.values(status)
if (!status) {
Logger.bypass("Agreement not created yet!")
}
Object.values(status || [])
.forEach(({condition, contractName, state, blocked, blockedBy}, i) => {
if (i) {
Logger.bypass("-".repeat(20))
@ -152,4 +187,18 @@ export abstract class AgreementTemplate extends ContractBase {
})
Logger.bypass("-".repeat(80))
}
/**
* Generates and returns the agreement creation event.
* @param {string} agreementId Agreement ID.
* @return {Event} Agreement created event.
*/
public getAgreementCreatedEvent(agreementId: string): Event {
return EventListener
.subscribe(
this.contractName,
"AgreementCreated",
{agreementId: zeroX(agreementId)},
)
}
}

View File

@ -47,6 +47,23 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
)
}
public async createAgreementFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string) {
return !!await this.createFullAgreement(
ddo.shortId(),
ddo.findServiceByType("Metadata").metadata.base.price,
consumer,
from,
agreementId,
)
}
public async getAgreementIdsFromDDO(agreementId: string, ddo: DDO, consumer: string, from?: string) {
const {accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId} =
await this.createFullAgreementData(agreementId, ddo.shortId(), ddo.findServiceByType("Metadata").metadata.base.price, from)
return [accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId]
}
/**
* Create a agreement using EscrowAccessSecretStoreTemplate using only the most important information.
* @param {string} did Asset DID.
@ -54,30 +71,24 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
* @param {string} from Consumer address.
* @return {Promise<string>} Agreement ID.
*/
public async createFullAgreement(did: string, amount: number, from?: string): Promise<string> {
const agreementId = zeroX(generateId())
public async createFullAgreement(did: string, amount: number, consumer: string, from?: string, agreementId?: string): Promise<string> {
agreementId = agreementId || zeroX(generateId())
const {accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId} =
await this.createFullAgreementData(agreementId, did, amount, from)
await this.createAgreement(
agreementId,
did,
[accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId],
[0, 0, 0],
[0, 0, 0],
consumer,
from,
)
return agreementId
}
public async getAgreementIdsFromDDO(agreementId: string, ddo: DDO, from: string) {
const {accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId} =
await this.createFullAgreementData(agreementId, ddo.shortId(), ddo.findServiceByType("Metadata").metadata.base.price, from)
return [accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId]
}
private async createFullAgreementData(agreementId: string, did: string, amount: number, from?: string) {
from = await this.getFromAddress(from)

View File

@ -3,7 +3,6 @@ import BrizoProvider from "../brizo/BrizoProvider"
import { generateId } from "../utils/GeneratorHelpers"
import Account from "./Account"
import DID from "./DID"
import { DDO } from "../ddo/DDO"
import ServiceAgreement from "./ServiceAgreements/ServiceAgreement"
import { Keeper } from "../keeper/Keeper"
import { zeroX, didPrefixed } from "../utils"
@ -57,6 +56,7 @@ export default class OceanAgreements {
serviceDefinitionId: string,
consumer: Account,
): Promise<AgreementPrepareResult> {
const d: DID = DID.parse(did as string)
const ddo = await AquariusProvider.getAquarius().retrieveDDO(d)
const agreementId: string = generateId()
@ -65,7 +65,7 @@ export default class OceanAgreements {
const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName
const agreementConditionsIds = await keeper
.getTemplateByName(templateName)
.getAgreementIdsFromDDO(agreementId, ddo, consumer.getId())
.getAgreementIdsFromDDO(agreementId, ddo, consumer.getId(), consumer.getId())
const signature = await ServiceAgreement.signServiceAgreement(
ddo,
@ -118,7 +118,7 @@ export default class OceanAgreements {
* @param {string} signature Service agreement signature.
* @param {Account} consumer Consumer account.
* @param {Account} publisher Publisher account.
* @return {Promise<ServiceAgreement>}
* @return {Promise<boolean>}
*/
public async create(
did: string,
@ -127,23 +127,17 @@ export default class OceanAgreements {
signature: string,
consumer: Account,
publisher: Account,
): Promise<ServiceAgreement> {
) {
const keeper = await Keeper.getInstance()
const d: DID = DID.parse(did)
const ddo = await AquariusProvider.getAquarius().retrieveDDO(d)
// TODO: Use Keeper 0.7+
const templateName = ddo.findServiceById<"Access">(serviceDefinitionId).serviceAgreementTemplate.contractName
await keeper
.getTemplateByName(templateName)
.createAgreementFromDDO(agreementId, ddo, consumer.getId(), publisher.getId())
// const serviceAgreement: ServiceAgreement = await ServiceAgreement
// .executeServiceAgreement(
// d,
// ddo,
// agreementId,
// serviceDefinitionId,
// signature,
// consumer,
// publisher)
// return serviceAgreement
return undefined
return true
}
}

View File

@ -39,7 +39,8 @@ export default class OceanAgreementsConditions {
await this.keeper.token.approve(lockRewardCondition.getAddress(), amount, from.getId())
return await lockRewardCondition.fulfill(agreementId, escrowReward.getAddress(), amount, from.getId())
const receipt = await lockRewardCondition.fulfill(agreementId, escrowReward.getAddress(), amount, from.getId())
return !!receipt.events.Fulfilled
}
@ -53,7 +54,8 @@ export default class OceanAgreementsConditions {
public async grantAccess(agreementId: string, did: string, grantee: string, from: Account = new Account()) {
const {accessSecretStoreCondition} = this.keeper.conditions
return await accessSecretStoreCondition.fulfill(agreementId, did, grantee, from.getId())
const receipt = await accessSecretStoreCondition.fulfill(agreementId, did, grantee, from.getId())
return !!receipt.events.Fulfilled
}
/**
@ -82,7 +84,7 @@ export default class OceanAgreementsConditions {
const conditionIdAccess = await accessSecretStoreCondition.generateIdHash(agreementId, did, consumer)
const conditionIdLock = await lockRewardCondition.generateIdHash(agreementId, await escrowReward.getAddress(), amount)
return await escrowReward.fulfill(
const receipt = await escrowReward.fulfill(
agreementId,
amount,
consumer,
@ -91,5 +93,6 @@ export default class OceanAgreementsConditions {
conditionIdAccess,
from.getId(),
)
return !!receipt.events.Fulfilled
}
}

View File

@ -2,20 +2,18 @@ import AquariusProvider from "../aquarius/AquariusProvider"
import { SearchQuery } from "../aquarius/query/SearchQuery"
import BrizoProvider from "../brizo/BrizoProvider"
import ConfigProvider from "../ConfigProvider"
import { Condition } from "../ddo/Condition"
import { DDO } from "../ddo/DDO"
import { MetaData } from "../ddo/MetaData"
import { ServiceAgreementTemplate, ServiceAgreementTemplateCondition } from "../ddo/ServiceAgreementTemplate"
import { Service, ServiceAuthorization } from "../ddo/Service"
import EventListener from "../keeper/EventListener"
import Keeper from "../keeper/Keeper"
import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Logger from "../utils/Logger"
import { Logger, fillConditionsWithDDO } from "../utils"
import Account from "./Account"
import DID from "./DID"
import OceanAgreements from "./OceanAgreements"
import ServiceAgreement from "./ServiceAgreements/ServiceAgreement"
import ServiceAgreementTemplate from "./ServiceAgreements/ServiceAgreementTemplate"
import Access from "./ServiceAgreements/Templates/Access"
/**
* Assets submodule of Ocean Protocol.
@ -58,7 +56,7 @@ export default class OceanAssets {
*/
public async create(metadata: MetaData, publisher: Account, services: Service[] = []): Promise<DDO> {
const {secretStoreUri} = ConfigProvider.getConfig()
const {didRegistry} = await Keeper.getInstance()
const {didRegistry, templates} = await Keeper.getInstance()
const aquarius = AquariusProvider.getAquarius()
const brizo = BrizoProvider.getBrizo()
@ -72,21 +70,18 @@ export default class OceanAssets {
const encryptedFiles = await SecretStoreProvider.getSecretStore(secretStoreConfig).encryptDocument(did.getId(), metadata.base.files)
const template = new Access()
const serviceAgreementTemplate = new ServiceAgreementTemplate(template)
const conditions: Condition[] = await serviceAgreementTemplate.getConditions(metadata, did.getId())
const serviceAgreementTemplate: ServiceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
const serviceEndpoint = aquarius.getServiceEndpoint(did)
let serviceDefinitionIdCount = 0
// create ddo itself
const ddo: DDO = new DDO({
id: did.getDid(),
authentication: [{
type: "RsaSignatureAuthentication2018",
publicKey: did.getDid() + "#keys-1",
}],
id: did.getDid(),
publicKey: [
{
id: did.getDid() + "#keys-1",
@ -97,29 +92,12 @@ export default class OceanAssets {
],
service: [
{
type: template.templateName,
type: "Access",
purchaseEndpoint: brizo.getPurchaseEndpoint(),
serviceEndpoint: brizo.getConsumeEndpoint(),
// the id of the service agreement?
serviceDefinitionId: String(serviceDefinitionIdCount++),
// the id of the service agreement template
templateId: serviceAgreementTemplate.getId(),
serviceAgreementContract: {
contractName: "ServiceExecutionAgreement",
fulfillmentOperator: template.fulfillmentOperator,
events: [
{
name: "AgreementInitialized",
actorType: "consumer",
handler: {
moduleName: "payment",
functionName: "lockPayment",
version: "0.1",
},
},
],
},
conditions,
templateId: templates.escrowAccessSecretStoreTemplate.getAddress(),
serviceAgreementTemplate,
},
{
type: "Compute",
@ -166,11 +144,15 @@ export default class OceanAssets {
.reverse() as Service[],
})
// Overwritte initial service agreement conditions
const rawConditions: ServiceAgreementTemplateCondition[] = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplateConditions()
const conditions: ServiceAgreementTemplateCondition[] = fillConditionsWithDDO(rawConditions, ddo)
serviceAgreementTemplate.conditions = conditions
ddo.addChecksum()
await ddo.addProof(publisher.getId(), publisher.getPassword())
const storedDdo = await aquarius.storeDDO(ddo)
await didRegistry.registerAttribute(
did.getId(),
ddo.getChecksum(),
@ -256,20 +238,22 @@ export default class OceanAssets {
const ddo = await this.resolve(did)
const keeper = await Keeper.getInstance()
const templateName = ddo.findServiceByType("Access").serviceAgreementTemplate.contractName
const template = await keeper.getTemplateByName(templateName)
const accessCondition = await keeper.conditions.accessSecretStoreCondition
const paymentFlow = new Promise((resolve, reject) => {
EventListener
.subscribe(
"ServiceExecutionAgreement",
"AgreementInitialized",
{agreementId: "0x" + agreementId},
)
template
.getAgreementCreatedEvent(agreementId)
.listenOnce(async (...args) => {
Logger.log("Agreement initialized")
const serviceAgreement = new ServiceAgreement("0x" + agreementId)
const {metadata} = ddo.findServiceByType("Metadata")
Logger.log("Locking payment")
const paid = await serviceAgreement.payAsset(ddo.shortId(), metadata.base.price, consumer)
const paid = await oceanAgreements.conditions.lockReward(agreementId, metadata.base.price, consumer)
if (paid) {
Logger.log("Payment was OK")
@ -281,12 +265,8 @@ export default class OceanAssets {
}
})
EventListener
.subscribe(
"AccessConditions",
"AccessGranted",
{agreementId: "0x" + agreementId},
)
accessCondition
.getConditionFulfilledEvent(agreementId)
.listenOnce(async (...args) => {
Logger.log("Access granted")
resolve()