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

View File

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

View File

@ -1,5 +1,5 @@
import { Condition } from "./Condition.abstract" import { Condition } from "./Condition.abstract"
import { zeroX } from "../../../utils" import { zeroX, didZeroX } from "../../../utils"
export class AccessSecretStoreCondition extends Condition { export class AccessSecretStoreCondition extends Condition {
@ -12,10 +12,10 @@ export class AccessSecretStoreCondition extends Condition {
} }
fulfill(agreementId: string, did: string, grantee: string, from?: string) { 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) { 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 ContractBase from "../ContractBase"
import { zeroX } from "../../../utils" import { zeroX } from "../../../utils"
import EventListener from "../../../keeper/EventListener"
import Event from "../../../keeper/Event"
export enum ConditionState { export enum ConditionState {
Uninitialized = 0, Uninitialized = 0,
@ -43,4 +45,13 @@ export abstract class Condition extends ContractBase {
abortByTimeOut(agreementId: string, from?: string) { abortByTimeOut(agreementId: string, from?: string) {
return this.sendFrom("abortByTimeOut", [zeroX(agreementId)], from) 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 { DDO } from '../../../ddo/DDO'
import { ServiceAgreementTemplate } from '../../../ddo/ServiceAgreementTemplate' import { ServiceAgreementTemplate } from '../../../ddo/ServiceAgreementTemplate'
import { zeroX, Logger } from "../../../utils" import { zeroX, Logger } from "../../../utils"
import EventListener from "../../../keeper/EventListener"
import Event from "../../../keeper/Event"
export abstract class AgreementTemplate extends ContractBase { 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[]> { public getConditionTypes(): Promise<string[]> {
return this.call("getConditionTypes", []) return this.call("getConditionTypes", [])
} }
/**
* List of condition contracts.
* @return {Promise<Condition[]>} Conditions contracts.
*/
public async getConditions(): Promise<Condition[]> { public async getConditions(): Promise<Condition[]> {
const keeper = await Keeper.getInstance() const keeper = await Keeper.getInstance()
return (await this.getConditionTypes()) return (await this.getConditionTypes())
.map(address => keeper.getConditionByAddress(address)) .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> abstract async getServiceAgreementTemplate(): Promise<ServiceAgreementTemplate>
@ -90,12 +116,18 @@ export abstract class AgreementTemplate extends ContractBase {
blocked: boolean, blocked: boolean,
blockedBy: string[] blockedBy: string[]
} }
}> { } | false> {
const agreementStore = await AgreementStoreManager.getInstance() const agreementStore = await AgreementStoreManager.getInstance()
const conditionStore = await ConditionStoreManager.getInstance() const conditionStore = await ConditionStoreManager.getInstance()
const dependencies = await this.getServiceAgreementTemplateDependencies() const dependencies = await this.getServiceAgreementTemplateDependencies()
const {conditionIds} = await agreementStore.getAgreement(agreementId) const {conditionIds} = await agreementStore.getAgreement(agreementId)
if (!conditionIds.length) {
Logger.error(`Agreement not creeated yet: "${agreementId}"`)
return false
}
const conditionIdByConddition = (await this.getConditions()) const conditionIdByConddition = (await this.getConditions())
.reduce((acc, {contractName}, i) => ({...acc, [contractName]: conditionIds[i]}), {}) .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("Template:", this.contractName)
Logger.bypass("Agreement ID:", agreementId) Logger.bypass("Agreement ID:", agreementId)
Logger.bypass("-".repeat(40)) 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) => { .forEach(({condition, contractName, state, blocked, blockedBy}, i) => {
if (i) { if (i) {
Logger.bypass("-".repeat(20)) Logger.bypass("-".repeat(20))
@ -152,4 +187,18 @@ export abstract class AgreementTemplate extends ContractBase {
}) })
Logger.bypass("-".repeat(80)) 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. * Create a agreement using EscrowAccessSecretStoreTemplate using only the most important information.
* @param {string} did Asset DID. * @param {string} did Asset DID.
@ -54,30 +71,24 @@ export class EscrowAccessSecretStoreTemplate extends AgreementTemplate {
* @param {string} from Consumer address. * @param {string} from Consumer address.
* @return {Promise<string>} Agreement ID. * @return {Promise<string>} Agreement ID.
*/ */
public async createFullAgreement(did: string, amount: number, from?: string): Promise<string> { public async createFullAgreement(did: string, amount: number, consumer: string, from?: string, agreementId?: string): Promise<string> {
const agreementId = zeroX(generateId()) agreementId = agreementId || zeroX(generateId())
const {accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId} = const {accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId} =
await this.createFullAgreementData(agreementId, did, amount, from) await this.createFullAgreementData(agreementId, did, amount, from)
await this.createAgreement( await this.createAgreement(
agreementId, agreementId,
did, did,
[accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId], [accessSecretStoreConditionId, lockRewardConditionId, escrowRewardId],
[0, 0, 0], [0, 0, 0],
[0, 0, 0], [0, 0, 0],
consumer,
from, from,
) )
return agreementId 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) { private async createFullAgreementData(agreementId: string, did: string, amount: number, from?: string) {
from = await this.getFromAddress(from) from = await this.getFromAddress(from)

View File

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

View File

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

View File

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