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

Merge remote-tracking branch 'remotes/origin/develop' into deploy/es-cjs-umd-min-builds

This commit is contained in:
diminator 2018-11-23 12:57:07 +01:00
commit faf974d03b
17 changed files with 737 additions and 415 deletions

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 0.1.20 current_version = 0.1.24
[bumpversion:file:package.json] [bumpversion:file:package.json]

749
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "@oceanprotocol/squid", "name": "@oceanprotocol/squid",
"version": "0.1.20", "version": "0.1.24",
"description": "JavaScript client library for Ocean Protocol", "description": "JavaScript client library for Ocean Protocol",
"main": "dist/squid.js", "main": "dist/squid.js",
"module": "dist/esm/squid.js", "module": "dist/esm/squid.js",
@ -57,7 +57,7 @@
}, },
"homepage": "https://github.com/oceanprotocol/squid-js#readme", "homepage": "https://github.com/oceanprotocol/squid-js#readme",
"dependencies": { "dependencies": {
"@oceanprotocol/keeper-contracts": "0.3.22", "@oceanprotocol/keeper-contracts": "0.3.25",
"@oceanprotocol/secret-store-client": "0.0.12", "@oceanprotocol/secret-store-client": "0.0.12",
"bignumber.js": "^8.0.1", "bignumber.js": "^8.0.1",
"eth-crypto": "^1.2.7", "eth-crypto": "^1.2.7",
@ -73,7 +73,7 @@
"devDependencies": { "devDependencies": {
"@types/chai": "^4.1.7", "@types/chai": "^4.1.7",
"@types/mocha": "^5.2.5", "@types/mocha": "^5.2.5",
"@types/node": "^10.12.7", "@types/node": "^10.12.10",
"chai": "^4.2.0", "chai": "^4.2.0",
"mocha": "^5.2.0", "mocha": "^5.2.0",
"nyc": "^13.1.0", "nyc": "^13.1.0",

View File

@ -5,6 +5,8 @@ import Logger from "../utils/Logger"
import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider" import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider"
import SearchQuery from "./query/SearchQuery" import SearchQuery from "./query/SearchQuery"
const apiPath = "/api/v1/aquarius/assets/ddo"
export default class Aquarius { export default class Aquarius {
private url: string private url: string
@ -40,7 +42,7 @@ export default class Aquarius {
public async queryMetadata(query: SearchQuery): Promise<DDO[]> { public async queryMetadata(query: SearchQuery): Promise<DDO[]> {
const result: DDO[] = await WebServiceConnectorProvider.getConnector() const result: DDO[] = await WebServiceConnectorProvider.getConnector()
.post(this.url + "/api/v1/aquarius/assets/ddo/query", JSON.stringify(query)) .post(`${this.url}${apiPath}/query`, JSON.stringify(query))
.then((response: any) => { .then((response: any) => {
if (response.ok) { if (response.ok) {
return response.json() as DDO[] return response.json() as DDO[]
@ -63,7 +65,7 @@ export default class Aquarius {
public async queryMetadataByText(query: SearchQuery): Promise<DDO[]> { public async queryMetadataByText(query: SearchQuery): Promise<DDO[]> {
const fullUrl = new URL(this.url + "/api/v1/aquarius/assets/ddo/query") const fullUrl = new URL(`${this.url}${apiPath}/query`)
fullUrl.searchParams.append("text", query.text) fullUrl.searchParams.append("text", query.text)
fullUrl.searchParams.append("sort", decodeURIComponent(JSON.stringify(query.sort))) fullUrl.searchParams.append("sort", decodeURIComponent(JSON.stringify(query.sort)))
fullUrl.searchParams.append("offset", query.offset.toString()) fullUrl.searchParams.append("offset", query.offset.toString())
@ -91,7 +93,7 @@ export default class Aquarius {
} }
public async storeDDO(ddo: DDO): Promise<DDO> { public async storeDDO(ddo: DDO): Promise<DDO> {
const fullUrl = this.url + `/api/v1/aquarius/assets/ddo` const fullUrl = `${this.url}${apiPath}`
const result: DDO = await WebServiceConnectorProvider.getConnector() const result: DDO = await WebServiceConnectorProvider.getConnector()
.post(fullUrl, DDO.serialize(ddo)) .post(fullUrl, DDO.serialize(ddo))
.then((response: any) => { .then((response: any) => {
@ -113,7 +115,7 @@ export default class Aquarius {
} }
public async retrieveDDO(did: string): Promise<DDO> { public async retrieveDDO(did: string): Promise<DDO> {
const fullUrl = this.url + `/api/v1/aquarius/assets/ddo/${did}` const fullUrl = `${this.url}${apiPath}/${did}`
const result = await WebServiceConnectorProvider.getConnector() const result = await WebServiceConnectorProvider.getConnector()
.get(fullUrl) .get(fullUrl)
.then((response: any) => { .then((response: any) => {

View File

@ -38,9 +38,7 @@ export default class DDO {
throw new Error("serviceDefinitionId not set") throw new Error("serviceDefinitionId not set")
} }
const service: Service = this.service.find((s) => { const service: Service = this.service.find((s) => s.serviceDefinitionId === serviceDefinitionId)
return s.serviceDefinitionId === serviceDefinitionId
})
return service return service
} }
@ -51,9 +49,7 @@ export default class DDO {
throw new Error("serviceType not set") throw new Error("serviceType not set")
} }
const service: Service = this.service.find((s) => { const service: Service = this.service.find((s) => s.type === serviceType)
return s.type === serviceType
})
return service return service
} }

View File

@ -60,16 +60,18 @@ export default abstract class ContractBase {
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}"`)
} }
// Logger.log(name, args)
const method = this.contract.methods[name] const method = this.contract.methods[name]
try { try {
const tx = method(...args) const methodInstance = method(...args)
const estimatedGas = await tx.estimateGas(args, { const estimatedGas = await methodInstance.estimateGas(args, {
from, from,
}) })
return tx.send({ const tx = methodInstance.send({
from, from,
gas: estimatedGas, gas: estimatedGas,
}) })
return tx
} catch (err) { } catch (err) {
const mappedArgs = this.searchMethod(name).inputs.map((input, i) => { const mappedArgs = this.searchMethod(name).inputs.map((input, i) => {
return { return {
@ -87,6 +89,7 @@ export default abstract class ContractBase {
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}`)
} }
// Logger.log(name)
try { try {
const method = this.contract.methods[name](...args) const method = this.contract.methods[name](...args)
return method.call(from ? {from} : null) return method.call(from ? {from} : null)

View File

@ -10,14 +10,18 @@ export default class ServiceAgreement extends ContractBase {
return serviceAgreement return serviceAgreement
} }
public async setupAgreementTemplate(templateId: string, methodReflections: MethodReflection[], public async setupAgreementTemplate(templateId: string,
dependencyMatrix: number[], name: any, fulfilmentOperator: number, methodReflections: MethodReflection[],
ownerAddress: string) dependencyMatrix: number[],
: Promise<Receipt> { name: any,
fulfillmentIndices: number[],
fulfillmentOperator: number,
ownerAddress: string): Promise<Receipt> {
return this.send("setupAgreementTemplate", ownerAddress, [ return this.send("setupAgreementTemplate", ownerAddress, [
templateId, methodReflections.map((r) => r.address), templateId, methodReflections.map((r) => r.address),
methodReflections.map((r) => r.signature), dependencyMatrix, name, [0], fulfilmentOperator, methodReflections.map((r) => r.signature), dependencyMatrix, name, fulfillmentIndices,
fulfillmentOperator,
]) ])
} }

View File

@ -13,7 +13,6 @@ import Service from "../ddo/Service"
import Keeper from "../keeper/Keeper" import Keeper from "../keeper/Keeper"
import Web3Provider from "../keeper/Web3Provider" import Web3Provider from "../keeper/Web3Provider"
import Config from "../models/Config" import Config from "../models/Config"
import InputType from "../models/InputType"
import ValueType from "../models/ValueType" import ValueType from "../models/ValueType"
import SecretStoreProvider from "../secretstore/SecretStoreProvider" import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Logger from "../utils/Logger" import Logger from "../utils/Logger"
@ -107,11 +106,11 @@ export default class Ocean {
return null return null
} }
const parameters: Parameter[] = condition.methodReflection.inputs.map((input: InputType) => { const parameters: Parameter[] = condition.parameters.map((parameter: Parameter) => {
return { return {
name: input.name, name: parameter.name,
type: input.type, type: parameter.type,
value: mapParameterValueToName(input.name), value: mapParameterValueToName(parameter.name),
} as Parameter } as Parameter
}) })
@ -131,6 +130,7 @@ export default class Ocean {
isTerminalCondition: condition.isTerminalCondition, isTerminalCondition: condition.isTerminalCondition,
} as DDOCondition } as DDOCondition
}) })
const serviceEndpoint = aquarius.getServiceEndpoint(did) const serviceEndpoint = aquarius.getServiceEndpoint(did)
// create ddo itself // create ddo itself

View File

@ -1,4 +1,5 @@
import MethodReflection from "../../models/MethodReflection" import MethodReflection from "../../models/MethodReflection"
import Parameter from "./Parameter"
export default class Condition { export default class Condition {
public methodReflection: MethodReflection public methodReflection: MethodReflection
@ -7,4 +8,5 @@ export default class Condition {
public dependencyTimeoutFlags: number[] public dependencyTimeoutFlags: number[]
public isTerminalCondition: boolean public isTerminalCondition: boolean
public timeout: number public timeout: number
public parameters: Parameter[]
} }

View File

@ -1,8 +1,11 @@
import Parameter from "./Parameter"
export default class Method { export default class Method {
public name: string public name: string
public contractName: string public contractName: string
public methodName: string public methodName: string
public timeout: number public timeout: number
public parameters: Parameter[]
public dependencies: string[] public dependencies: string[]
public dependencyTimeoutFlags: number[] public dependencyTimeoutFlags: number[]
public isTerminalCondition: boolean public isTerminalCondition: boolean

View File

@ -0,0 +1,4 @@
export default class Parameter {
public name: string
public type: string
}

View File

@ -19,18 +19,12 @@ export default class ServiceAgreement extends OceanBase {
// Logger.log("signing SA", serviceAgreementId) // Logger.log("signing SA", serviceAgreementId)
const service: Service = ddo.findServiceById(serviceDefinitionId) const service: Service = ddo.findServiceById(serviceDefinitionId)
const values: ValuePair[] = ServiceAgreement.getValuesFromService(service, serviceAgreementId) const values: ValuePair[][] = ServiceAgreement.getValuesFromService(service, serviceAgreementId)
const valueHashes = ServiceAgreement.createValueHashes(values) const valueHashes: string[] = ServiceAgreement.createValueHashes(values)
const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service) const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service)
const serviceAgreementHashSignature = await ServiceAgreement const serviceAgreementHashSignature = await ServiceAgreement.createSAHashSignature(service, serviceAgreementId,
.createSAHashSignature( valueHashes, timeoutValues, consumer)
service,
serviceAgreementId,
values,
valueHashes,
timeoutValues,
consumer)
return serviceAgreementHashSignature return serviceAgreementHashSignature
} }
@ -46,8 +40,8 @@ export default class ServiceAgreement extends OceanBase {
// Logger.log("executing SA", serviceAgreementId) // Logger.log("executing SA", serviceAgreementId)
const service: Service = ddo.findServiceById(serviceDefinitionId) const service: Service = ddo.findServiceById(serviceDefinitionId)
const values: ValuePair[] = ServiceAgreement.getValuesFromService(service, serviceAgreementId) const values: ValuePair[][] = ServiceAgreement.getValuesFromService(service, serviceAgreementId)
const valueHashes = ServiceAgreement.createValueHashes(values) const valueHashes: string[] = ServiceAgreement.createValueHashes(values)
const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service) const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service)
// todo get consumer from ddo // todo get consumer from ddo
@ -60,11 +54,9 @@ export default class ServiceAgreement extends OceanBase {
private static async createSAHashSignature(service: Service, private static async createSAHashSignature(service: Service,
serviceAgreementId: string, serviceAgreementId: string,
values: ValuePair[],
valueHashes: string[], valueHashes: string[],
timeoutValues: number[], timeoutValues: number[],
consumer: Account): consumer: Account): Promise<string> {
Promise<string> {
if (!service.templateId) { if (!service.templateId) {
throw new Error("TemplateId not found in ddo.") throw new Error("TemplateId not found in ddo.")
@ -74,8 +66,11 @@ export default class ServiceAgreement extends OceanBase {
return condition.conditionKey return condition.conditionKey
}) })
const serviceAgreementHash = ServiceAgreement if (conditionKeys.length !== valueHashes.length) {
.hashServiceAgreement( throw new Error("Hashing SA failed!")
}
const serviceAgreementHash = ServiceAgreement.hashServiceAgreement(
service.templateId, service.templateId,
serviceAgreementId, serviceAgreementId,
conditionKeys, conditionKeys,
@ -130,18 +125,31 @@ export default class ServiceAgreement extends OceanBase {
) )
} }
private static createValueHashes(valuePairs: ValuePair[]): any[] { private static createValueHashes(parameterValuePairs: ValuePair[][]): string[] {
return valuePairs.map((valuePair) => {
return ServiceAgreement.hashSingleValue(valuePair) const hashes: string[] = []
parameterValuePairs.map((valuePairs: ValuePair[]) => {
hashes.push(ServiceAgreement.hashValuePairArray(valuePairs))
}) })
return hashes
} }
private static hashSingleValue(data: ValuePair): string { private static hashValuePairArray(valuePairs: ValuePair[]): string {
let hash: string
try { try {
return Web3Provider.getWeb3().utils.soliditySha3(data).toString("hex") hash = Web3Provider.getWeb3().utils.soliditySha3(...valuePairs).toString("hex")
} catch (err) { } catch (err) {
Logger.error(`Hashing of ${JSON.stringify(data, null, 2)} failed.`) Logger.error(`Hashing of ${JSON.stringify(valuePairs, null, 2)} failed.`)
throw err
} }
if (!hash) {
throw new Error("hashValuePairArray failed to create hash.")
}
return hash
} }
private static hashServiceAgreement(serviceAgreementTemplateId: string, private static hashServiceAgreement(serviceAgreementTemplateId: string,
@ -168,20 +176,22 @@ export default class ServiceAgreement extends OceanBase {
return timeoutValues return timeoutValues
} }
private static getValuesFromService(service: Service, serviceAgreementId: string): ValuePair[] { private static getValuesFromService(service: Service, serviceAgreementId: string): ValuePair[][] {
const values: ValuePair[] = [] const values: ValuePair[][] = []
service.conditions.forEach((condition) => { service.conditions.forEach((condition, i) => {
const contionValues: ValuePair[] = []
condition.parameters.forEach((parameter) => { condition.parameters.forEach((parameter) => {
values.push({
contionValues.push({
type: parameter.type, type: parameter.type,
value: parameter.name === "serviceId" ? "0x" + serviceAgreementId : parameter.value, value: parameter.name === "serviceId" ? "0x" + serviceAgreementId : parameter.value,
} as ValuePair) } as ValuePair)
}) })
})
// Logger.log("Values", JSON.stringify(values, null, 2)) values[i] = contionValues
})
return values return values
} }
@ -195,14 +205,16 @@ export default class ServiceAgreement extends OceanBase {
super(serviceAgreementId) super(serviceAgreementId)
} }
public async lockPayment(assetId: string, price: number, consumer: Account): Promise<boolean> { public async buyAsset(assetId: string, price: number, consumer: Account): Promise<boolean> {
const {paymentConditions} = await Keeper.getInstance() const {paymentConditions, token} = await Keeper.getInstance()
const lockPaymentRceipt = await token.approve(paymentConditions.getAddress(), price, consumer.getId())
const lockPaymentReceipt =
await paymentConditions.lockPayment(this.getId(), assetId, price, await paymentConditions.lockPayment(this.getId(), assetId, price,
consumer.getId()) consumer.getId())
return lockPaymentRceipt.status return lockPaymentReceipt.status
} }
public async grantAccess(assetId: string, documentId: string): Promise<boolean> { public async grantAccess(assetId: string, documentId: string): Promise<boolean> {
@ -212,7 +224,7 @@ export default class ServiceAgreement extends OceanBase {
await accessConditions.grantAccess(this.getId(), assetId, documentId, await accessConditions.grantAccess(this.getId(), assetId, documentId,
this.publisher.getId()) this.publisher.getId())
return grantAccessReceipt.status return !!grantAccessReceipt.events.AccessGranted
} }
public async getStatus() { public async getStatus() {

View File

@ -12,8 +12,8 @@ import TemplateBase from "./Templates/TemplateBase"
export default class ServiceAgreementTemplate extends OceanBase { export default class ServiceAgreementTemplate extends OceanBase {
private static generateConditionsKey(serviceAgreementTemplateId: string, methodReflection: MethodReflection) private static generateConditionsKey(serviceAgreementTemplateId: string,
: string { methodReflection: MethodReflection): string {
const values = [ const values = [
{type: "bytes32", value: serviceAgreementTemplateId} as ValuePair, {type: "bytes32", value: serviceAgreementTemplateId} as ValuePair,
{type: "address", value: methodReflection.address} as ValuePair, {type: "address", value: methodReflection.address} as ValuePair,
@ -34,9 +34,11 @@ export default class ServiceAgreementTemplate extends OceanBase {
return this.compressDependencies(method.dependencies, method.dependencyTimeoutFlags) return this.compressDependencies(method.dependencies, method.dependencyTimeoutFlags)
})) }))
const {serviceAgreement} = await Keeper.getInstance() const fulfillmentIndices: number[] = this.template.Methods
.map((method: Method, i: number) => method.isTerminalCondition ? i : null)
.filter((index: number) => index !== null)
const methodReflections = await this.getMethodReflections() const {serviceAgreement} = await Keeper.getInstance()
const owner = await this.getOwner() const owner = await this.getOwner()
@ -54,10 +56,12 @@ export default class ServiceAgreementTemplate extends OceanBase {
const receipt = await serviceAgreement const receipt = await serviceAgreement
.setupAgreementTemplate( .setupAgreementTemplate(
this.template.id, this.template.id,
methodReflections, await this.getMethodReflections(),
dependencyMatrix, dependencyMatrix,
Web3Provider.getWeb3().utils.fromAscii(this.template.templateName), Web3Provider.getWeb3().utils.fromAscii(this.template.templateName),
this.template.fulfilmentOperator, templateOwnerAddress) fulfillmentIndices,
this.template.fulfillmentOperator,
templateOwnerAddress)
const {serviceTemplateId, provider} = receipt.events.SetupAgreementTemplate.returnValues const {serviceTemplateId, provider} = receipt.events.SetupAgreementTemplate.returnValues
@ -100,6 +104,7 @@ export default class ServiceAgreementTemplate extends OceanBase {
return { return {
methodReflection, methodReflection,
timeout: method.timeout, timeout: method.timeout,
parameters: method.parameters,
dependencies: method.dependencies, dependencies: method.dependencies,
dependencyTimeoutFlags: method.dependencyTimeoutFlags, dependencyTimeoutFlags: method.dependencyTimeoutFlags,
isTerminalCondition: method.isTerminalCondition, isTerminalCondition: method.isTerminalCondition,
@ -117,23 +122,32 @@ export default class ServiceAgreementTemplate extends OceanBase {
throw new Error("Deps and timeouts need the same length") throw new Error("Deps and timeouts need the same length")
} }
// map name to index const mappedDependencies: number[] = []
const mappedDependencies: number[] = dependencies.map((dep: string) => { const mappedDependencyTimeoutFlags: number[] = []
return this.template.Methods.findIndex((m) => m.name === dep)
this.template.Methods.forEach((m, i) => {
const di = dependencies.findIndex((d) => d === m.name)
mappedDependencies.push(di > -1 ? 1 : 0)
mappedDependencyTimeoutFlags.push((di > -1 && dependencyTimeoutFlags[di]) ? 1 : 0)
}) })
let compressedDependencyValue = 0 if (mappedDependencies.length !== mappedDependencyTimeoutFlags.length) {
const numBits = 2 // 1st for dependency, 2nd for timeout flag throw new Error("Deps and timeouts need the same length")
for (let i = 0; i < mappedDependencies.length; i++) {
const dependencyIndex = mappedDependencies[i]
const timeout = dependencyTimeoutFlags[i]
const offset = i * numBits
// tslint:disable-next-line
compressedDependencyValue |= dependencyIndex * 2 ** (offset + 0) // the dependency bit
// tslint:disable-next-line
compressedDependencyValue |= timeout * 2 ** (offset + 1) // the timeout bit
} }
// Logger.log(dependencies, mappedDependencies, dependencyTimeoutFlags, mappedDependencyTimeoutFlags)
let compressedDependencyValue: number = 0
const numBits: number = 2 // 1st for dependency, 2nd for timeout flag
mappedDependencies.forEach((d: number, i: number) => {
const t: number = mappedDependencyTimeoutFlags[i]
const offset: number = i * numBits
// tslint:disable-next-line
compressedDependencyValue |= d * 2 ** (offset + 0) // the dependency bit
// tslint:disable-next-line
compressedDependencyValue |= t * 2 ** (offset + 1) // the timeout bit
})
return compressedDependencyValue return compressedDependencyValue
} }

View File

@ -11,6 +11,16 @@ export default class Access extends TemplateBase {
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "lockPayment", methodName: "lockPayment",
timeout: 0, timeout: 0,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "price",
type: "uint256",
},
],
dependencies: [], dependencies: [],
dependencyTimeoutFlags: [], dependencyTimeoutFlags: [],
isTerminalCondition: false, isTerminalCondition: false,
@ -20,6 +30,16 @@ export default class Access extends TemplateBase {
contractName: "AccessConditions", contractName: "AccessConditions",
methodName: "grantAccess", methodName: "grantAccess",
timeout: 10, timeout: 10,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "documentKeyId",
type: "bytes32",
},
],
dependencies: ["lockPayment"], dependencies: ["lockPayment"],
dependencyTimeoutFlags: [0], dependencyTimeoutFlags: [0],
isTerminalCondition: false, isTerminalCondition: false,
@ -29,6 +49,16 @@ export default class Access extends TemplateBase {
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "releasePayment", methodName: "releasePayment",
timeout: 10, timeout: 10,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "price",
type: "uint256",
},
],
dependencies: ["grantAccess"], dependencies: ["grantAccess"],
dependencyTimeoutFlags: [0], dependencyTimeoutFlags: [0],
isTerminalCondition: true, isTerminalCondition: true,
@ -38,6 +68,16 @@ export default class Access extends TemplateBase {
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "refundPayment", methodName: "refundPayment",
timeout: 10, timeout: 10,
parameters: [
{
name: "assetId",
type: "bytes32",
},
{
name: "price",
type: "uint256",
},
],
dependencies: ["lockPayment", "grantAccess"], dependencies: ["lockPayment", "grantAccess"],
dependencyTimeoutFlags: [0, 1], dependencyTimeoutFlags: [0, 1],
isTerminalCondition: true, isTerminalCondition: true,

View File

@ -3,6 +3,6 @@ import Method from "../Method"
export default abstract class TemplateBase { export default abstract class TemplateBase {
public Methods: Method[] public Methods: Method[]
public templateName: string public templateName: string
public fulfilmentOperator: number = 0 public fulfillmentOperator: number = 1
public id: string = "0x00000000000000000000000000000000000000000000000000000000000000" public id: string = "0x00000000000000000000000000000000000000000000000000000000000000"
} }

View File

@ -17,7 +17,9 @@ export default class TestContractHandler extends ContractHandler {
await TestContractHandler.deployContracts(deployerAddress) await TestContractHandler.deployContracts(deployerAddress)
// register templates // register templates
Logger.log(`Registering Access Template from ${deployerAddress}`)
await new ServiceAgreementTemplate(new Access()).register(deployerAddress) await new ServiceAgreementTemplate(new Access()).register(deployerAddress)
Logger.log(`Registering FitchainCompute Template from ${deployerAddress}`)
await new ServiceAgreementTemplate(new FitchainCompute()).register(deployerAddress) await new ServiceAgreementTemplate(new FitchainCompute()).register(deployerAddress)
} }

View File

@ -7,7 +7,6 @@ import EventHandlers from "../../src/ddo/EventHandlers"
import MetaData from "../../src/ddo/MetaData" import MetaData from "../../src/ddo/MetaData"
import Parameter from "../../src/ddo/Parameter" import Parameter from "../../src/ddo/Parameter"
import Service from "../../src/ddo/Service" import Service from "../../src/ddo/Service"
import InputType from "../../src/models/InputType"
import Account from "../../src/ocean/Account" import Account from "../../src/ocean/Account"
import IdGenerator from "../../src/ocean/IdGenerator" import IdGenerator from "../../src/ocean/IdGenerator"
import Ocean from "../../src/ocean/Ocean" import Ocean from "../../src/ocean/Ocean"
@ -49,7 +48,8 @@ describe("ServiceAgreement", () => {
const conditions: Condition[] = await serviceAgreementTemplate.getConditions() const conditions: Condition[] = await serviceAgreementTemplate.getConditions()
// create ddo conditions out of the keys // create ddo conditions out of the keys
const ddoConditions: DDOCondition[] = conditions.map((condition, index): DDOCondition => { const ddoConditions: DDOCondition[] = conditions
.map((condition: Condition, index): DDOCondition => {
const events: Event[] = [ const events: Event[] = [
{ {
@ -73,17 +73,19 @@ describe("ServiceAgreement", () => {
case "assetId": case "assetId":
return "0x" + assetId return "0x" + assetId
case "documentKeyId": case "documentKeyId":
return "0x1234" return "0x" + assetId
} }
return null return null
} }
const parameters: Parameter[] = condition.methodReflection.inputs.map((input: InputType) => { const parameters: Parameter[] = condition.parameters
.map((parameter: Parameter) => {
return { return {
name: input.name, name: parameter.name,
type: input.type, type: parameter.type,
value: mapParameterValueToName(input.name), value: mapParameterValueToName(parameter.name),
} as Parameter } as Parameter
}) })
@ -117,8 +119,7 @@ describe("ServiceAgreement", () => {
describe("#signServiceAgreement()", () => { describe("#signServiceAgreement()", () => {
it("should sign an service agreement", async () => { it("should sign an service agreement", async () => {
const id: string = IdGenerator.generateId() const did: string = `did:op:${assetId}`
const did: string = `did:op:${id}`
const ddo = new DDO({id: did, service: [accessService]}) const ddo = new DDO({id: did, service: [accessService]})
const serviceAgreementId: string = IdGenerator.generateId() const serviceAgreementId: string = IdGenerator.generateId()
@ -137,8 +138,7 @@ describe("ServiceAgreement", () => {
describe("#executeServiceAgreement()", () => { describe("#executeServiceAgreement()", () => {
it("should execute an service agreement", async () => { it("should execute an service agreement", async () => {
const id: string = IdGenerator.generateId() const did: string = `did:op:${assetId}`
const did: string = `did:op:${id}`
const ddo = new DDO({id: did, service: [accessService]}) const ddo = new DDO({id: did, service: [accessService]})
const serviceAgreementId: string = IdGenerator.generateId() const serviceAgreementId: string = IdGenerator.generateId()
@ -162,8 +162,7 @@ describe("ServiceAgreement", () => {
describe("#getStatus()", () => { describe("#getStatus()", () => {
it("should get the status of a newly created service agreement", async () => { it("should get the status of a newly created service agreement", async () => {
const id: string = IdGenerator.generateId() const did: string = `did:op:${assetId}`
const did: string = `did:op:${id}`
const ddo = new DDO({id: did, service: [accessService]}) const ddo = new DDO({id: did, service: [accessService]})
const serviceAgreementId: string = IdGenerator.generateId() const serviceAgreementId: string = IdGenerator.generateId()
@ -184,16 +183,16 @@ describe("ServiceAgreement", () => {
}) })
}) })
describe("#lockPayment()", () => { describe("#buyAsset()", () => {
xit("should lock the payment in that service agreement", async () => { it("should lock the payment in that service agreement", async () => {
const id: string = IdGenerator.generateId() const did: string = `did:op:${assetId}`
const did: string = `did:op:${id}`
const ddo = new DDO({id: did, service: [accessService, metaDataService]}) const ddo = new DDO({id: did, service: [accessService, metaDataService]})
const serviceAgreementId: string = IdGenerator.generateId() const serviceAgreementId: string = IdGenerator.generateId()
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
const serviceAgreementSignature: string = const serviceAgreementSignature: string =
await ServiceAgreement.signServiceAgreement(assetId, ddo, accessService.serviceDefinitionId, await ServiceAgreement.signServiceAgreement(assetId, ddo, accessService.serviceDefinitionId,
serviceAgreementId, consumerAccount) serviceAgreementId, consumerAccount)
@ -204,17 +203,19 @@ describe("ServiceAgreement", () => {
serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount) serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount)
assert(serviceAgreement) assert(serviceAgreement)
const paid: boolean = await serviceAgreement.lockPayment(assetId, metaDataService.metadata.base.price, // get funds
await consumerAccount.requestTokens(metaDataService.metadata.base.price)
const paid: boolean = await serviceAgreement.buyAsset(assetId, metaDataService.metadata.base.price,
consumerAccount) consumerAccount)
assert(paid) assert(paid)
}) })
}) })
describe("#grantAccess()", () => { describe("#grantAccess()", () => {
xit("should grant access in that service agreement", async () => { it("should grant access in that service agreement", async () => {
const id: string = IdGenerator.generateId() const did: string = `did:op:${assetId}`
const did: string = `did:op:${id}`
const ddo = new DDO({id: did, service: [accessService]}) const ddo = new DDO({id: did, service: [accessService]})
const serviceAgreementId: string = IdGenerator.generateId() const serviceAgreementId: string = IdGenerator.generateId()
@ -230,11 +231,39 @@ describe("ServiceAgreement", () => {
serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount) serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount)
assert(serviceAgreement) assert(serviceAgreement)
const paid: boolean = await serviceAgreement.lockPayment(assetId, 10, consumerAccount) // get funds
await consumerAccount.requestTokens(metaDataService.metadata.base.price)
const paid: boolean = await serviceAgreement.buyAsset(assetId, metaDataService.metadata.base.price,
consumerAccount)
assert(paid) assert(paid)
const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, IdGenerator.generateId()) // todo: use document id
const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, assetId)
assert(accessGranted) assert(accessGranted)
}) })
it("should fail to grant grant access if there is no payment", async () => {
const did: string = `did:op:${assetId}`
const ddo = new DDO({id: did, service: [accessService]})
const serviceAgreementId: string = IdGenerator.generateId()
// @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
const serviceAgreementSignature: string =
await ServiceAgreement.signServiceAgreement(assetId, ddo, accessService.serviceDefinitionId,
serviceAgreementId, consumerAccount)
assert(serviceAgreementSignature)
const serviceAgreement: ServiceAgreement =
await ServiceAgreement.executeServiceAgreement(assetId, ddo, accessService.serviceDefinitionId,
serviceAgreementId, serviceAgreementSignature, consumerAccount, publisherAccount)
assert(serviceAgreement)
// todo: use document id
const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, assetId)
assert(!accessGranted)
})
}) })
}) })