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

Merge pull request #57 from oceanprotocol/feature/trilobite_countdown

added buy asset and grant access samples, prepare for consumption
This commit is contained in:
Sebastian Gerske 2018-12-10 16:59:32 +01:00 committed by GitHub
commit c91a666fd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 1060 additions and 534 deletions

View File

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

View File

@ -64,7 +64,7 @@ const ocean: Ocean = await Ocean.getInstance({
// the threshold of nodes from the secre store that have to agree to the decrypt // the threshold of nodes from the secre store that have to agree to the decrypt
threshold: 0, threshold: 0,
// the password for the account (in the local parity node) used to sign messages for secret store // the password for the account (in the local parity node) used to sign messages for secret store
password: "unittest", password: "you password",
// the address of the account (in the local parity node) used to sign messages for secret store // the address of the account (in the local parity node) used to sign messages for secret store
address: "0xed243adfb84a6626eba46178ccb567481c6e655d", address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
}) })

396
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.26", "version": "0.2.1",
"description": "JavaScript client library for Ocean Protocol", "description": "JavaScript client library for Ocean Protocol",
"main": "./dist/node/squid.js", "main": "./dist/node/squid.js",
"browser": "./dist/browser/squid.cjs2.min.js", "browser": "./dist/browser/squid.cjs2.min.js",
@ -51,12 +51,13 @@
}, },
"homepage": "https://github.com/oceanprotocol/squid-js#readme", "homepage": "https://github.com/oceanprotocol/squid-js#readme",
"dependencies": { "dependencies": {
"@oceanprotocol/keeper-contracts": "0.3.25", "@oceanprotocol/keeper-contracts": "^0.5.0",
"@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",
"eth-ecies": "^1.0.3", "eth-ecies": "^1.0.3",
"ethereumjs-util": "^6.0.0", "ethereumjs-util": "^6.0.0",
"file-saver": "^2.0.0",
"jsonwebtoken": "^8.4.0", "jsonwebtoken": "^8.4.0",
"node-fetch": "^2.3.0", "node-fetch": "^2.3.0",
"uuid": "^3.3.2", "uuid": "^3.3.2",
@ -67,20 +68,20 @@
"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.10", "@types/node": "^10.12.12",
"chai": "^4.2.0", "chai": "^4.2.0",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"mocha": "^5.2.0", "mocha": "^5.2.0",
"nyc": "^13.1.0", "nyc": "^13.1.0",
"rollup": "^0.67.3", "rollup": "^0.67.4",
"source-map-support": "^0.5.9", "source-map-support": "^0.5.9",
"ts-loader": "^5.3.0", "truffle-hdwallet-provider": "^1.0.0-web3one.2",
"ts-node": "^7.0.1", "ts-node": "^7.0.1",
"tslint": "^5.11.0", "tslint": "^5.11.0",
"typedoc": "^0.13.0", "typedoc": "^0.13.0",
"typescript": "^3.1.6", "typescript": "^3.2.2",
"uglify-js": "^3.4.9", "uglify-js": "^3.4.9",
"webpack": "^4.26.1", "webpack": "^4.27.1",
"webpack-cli": "^3.1.2", "webpack-cli": "^3.1.2",
"webpack-concat-plugin": "^3.0.0", "webpack-concat-plugin": "^3.0.0",
"webpack-merge": "^4.1.4" "webpack-merge": "^4.1.4"

View File

@ -137,6 +137,6 @@ export default class Aquarius {
} }
public getServiceEndpoint(did) { public getServiceEndpoint(did) {
return `${this.url}/api/v1/provider/assets/metadata/${did}` return `${this.url}/api/v1/aquarius/assets/metadata/${did}`
} }
} }

View File

@ -1,6 +1,8 @@
import Config from "../models/Config" import Config from "../models/Config"
import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider" import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider"
const apiPath = "/api/v1/brizo/services"
export default class Brizo { export default class Brizo {
private url: string private url: string
@ -10,16 +12,16 @@ export default class Brizo {
} }
public getPurchaseEndpoint() { public getPurchaseEndpoint() {
return `${this.url}/api/v1/brizo/services/access/purchase?` return `${this.url}${apiPath}/access/purchase?`
} }
public getConsumeEndpoint(pubKey: string, serviceId: string, url: string) { public getConsumeEndpoint() {
return `${this.url}/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId=${serviceId}&url=${url}` return `${this.url}${apiPath}/consume`
} }
public getComputeEndpoint(pubKey: string, serviceId: string, algo: string, container: string) { public getComputeEndpoint(pubKey: string, serviceId: string, algo: string, container: string) {
// tslint:disable-next-line // tslint:disable-next-line
return `${this.url}/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId=${serviceId}&algo=${algo}&container=${container}"` return `${this.url}${apiPath}/compute?pubKey=${pubKey}&serviceId=${serviceId}&algo=${algo}&container=${container}"`
} }
public async initializeServiceAgreement( public async initializeServiceAgreement(
@ -27,17 +29,22 @@ export default class Brizo {
serviceAgreementId: string, serviceAgreementId: string,
serviceDefinitionId: string, serviceDefinitionId: string,
signature: string, signature: string,
consumerPublicKey: string): Promise<any> { consumerAddress: string): Promise<any> {
return WebServiceConnectorProvider.getConnector().post( const args = {
`${this.url}/api/v1/brizo/services/access/initialize`, did,
{ serviceAgreementId,
did, serviceDefinitionId,
serviceAgreementId, signature,
serviceDefinitionId, consumerAddress,
signature, }
consumerPublicKey,
}) return WebServiceConnectorProvider
.getConnector()
.post(
`${this.url}${apiPath}/access/initialize`,
decodeURI(JSON.stringify(args)),
)
} }
} }

View File

@ -1,14 +1,15 @@
import Dependency from "./Dependency"
import Event from "./Event" import Event from "./Event"
import Parameter from "./Parameter" import Parameter from "./Parameter"
export default class Condition { export default class Condition {
public name: string
public contractName: string = "AccessCondition" public contractName: string = "AccessCondition"
public methodName: string = "lockPayment" public functionName: string = "lockPayment"
public timeout: number = 0 public timeout: number = 0
public conditionKey: string = "0x12122434" public conditionKey: string = "0x12122434"
public parameters: Parameter[] public parameters: Parameter[]
public events: Event[] public events: Event[]
public dependencies: string[] = [] public dependencies: Dependency[] = []
public dependencyTimeoutFlags: number[] = []
public isTerminalCondition: boolean = false public isTerminalCondition: boolean = false
} }

7
src/ddo/Contract.ts Normal file
View File

@ -0,0 +1,7 @@
import Event from "./Event"
export default class Contract {
public contractName: string
public fulfillmentOperator: number
public events: Event[]
}

View File

@ -22,7 +22,7 @@ export default class DDO {
public constructor(ddo?: { public constructor(ddo?: {
id?: string, id?: string,
publicKey?: any[], publicKey?: PublicKey[],
authentication?: Authentication[], authentication?: Authentication[],
service?: Service[], service?: Service[],
}) { }) {

4
src/ddo/Dependency.ts Normal file
View File

@ -0,0 +1,4 @@
export default class Dependency {
public name: string = "lockPayment"
public timeout: number = 0
}

View File

@ -1,7 +1,7 @@
import EventHandlers from "./EventHandlers" import EventHandler from "./EventHandler"
export default class Event { export default class Event {
public name: string public name: string
public actorType: string[] public actorType: string
public handlers: EventHandlers public handler: EventHandler
} }

View File

@ -1,4 +1,4 @@
export default class EventHandlers { export default class EventHandler {
public moduleName: string = "serviceAgreement" public moduleName: string = "serviceAgreement"
public functionName: string = "fulfillAgreement" public functionName: string = "fulfillAgreement"
public version: string = "0.1" public version: string = "0.1"

View File

@ -1,6 +1,6 @@
export default class PublicKey { export default class PublicKey {
public id: string = "did:op:123456789abcdefghi#keys-1" public id: string = "did:op:123456789abcdefghi#keys-1"
public type: string = "RsaVerificationKey2018" public type: string = "Ed25519VerificationKey2018"
public owner: string = "did:op:123456789abcdefghi" public owner: string = "did:op:123456789abcdefghi"
public publicKeyPem?: string = "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n" public publicKeyPem?: string = "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
public publicKeyBase58?: string = "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" public publicKeyBase58?: string = "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"

View File

@ -1,4 +1,5 @@
import Condition from "./Condition" import Condition from "./Condition"
import Contract from "./Contract"
import MetaData from "./MetaData" import MetaData from "./MetaData"
export default class Service { export default class Service {
@ -9,5 +10,6 @@ export default class Service {
public purchaseEndpoint?: string public purchaseEndpoint?: string
public description?: string = "My public social inbox" public description?: string = "My public social inbox"
public metadata?: MetaData = {} as MetaData public metadata?: MetaData = {} as MetaData
public serviceAgreementContract?: Contract
public conditions?: Condition[] = [] public conditions?: Condition[] = []
} }

70
src/examples/BuyAsset.ts Normal file
View File

@ -0,0 +1,70 @@
import DDO from "../ddo/DDO"
import MetaData from "../ddo/MetaData"
import MetaDataBase from "../ddo/MetaDataBase"
import Service from "../ddo/Service"
import {Account, Logger, Ocean, ServiceAgreement} from "../squid"
import config from "./config"
(async () => {
const ocean: Ocean = await Ocean.getInstance(config)
const publisher: Account = (await ocean.getAccounts())[0]
const consumer: Account = (await ocean.getAccounts())[1]
const metaData = new 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",
contentUrls: [
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.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,
} as MetaDataBase,
} as MetaData)
const ddo: DDO = await ocean.registerAsset(metaData, publisher)
Logger.log("did", ddo.id)
const assetId = ddo.id.replace("did:op:", "")
const accessService = ddo.findServiceByType("Access")
await consumer.requestTokens(metaData.base.price)
const serviceAgreementSignatureResult: any = await ocean.signServiceAgreement(ddo.id,
accessService.serviceDefinitionId, consumer)
Logger.log("ServiceAgreement Id:", serviceAgreementSignatureResult.serviceAgreementId)
Logger.log("ServiceAgreement Signature:", serviceAgreementSignatureResult.serviceAgreementSignature)
const service: Service = ddo.findServiceByType("Access")
const serviceAgreement: ServiceAgreement = await ocean.executeServiceAgreement(
ddo.id,
service.serviceDefinitionId,
serviceAgreementSignatureResult.serviceAgreementId,
serviceAgreementSignatureResult.serviceAgreementSignature,
consumer,
publisher)
Logger.log("ServiceAgreement Id:", serviceAgreement.getId())
const paid = await serviceAgreement.payAsset(assetId, metaData.base.price, consumer)
Logger.log(`Asset paid: ${paid}`)
})()

View File

@ -3,18 +3,11 @@ import MetaData from "../ddo/MetaData"
import MetaDataBase from "../ddo/MetaDataBase" import MetaDataBase from "../ddo/MetaDataBase"
import Service from "../ddo/Service" import Service from "../ddo/Service"
import {Account, Logger, Ocean, ServiceAgreement} from "../squid" import {Account, Logger, Ocean, ServiceAgreement} from "../squid"
import config from "./config"
(async () => { (async () => {
const ocean: Ocean = await Ocean.getInstance({
nodeUri: "http://localhost:8545", const ocean: Ocean = await Ocean.getInstance(config)
aquariusUri: "http://localhost:5000",
brizoUri: "http://localhost:8030",
parityUri: "http://localhost:9545",
secretStoreUri: "http://localhost:12001",
threshold: 0,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
})
const publisher: Account = (await ocean.getAccounts())[0] const publisher: Account = (await ocean.getAccounts())[0]
const consumer: Account = (await ocean.getAccounts())[1] const consumer: Account = (await ocean.getAccounts())[1]
@ -54,6 +47,8 @@ import {Account, Logger, Ocean, ServiceAgreement} from "../squid"
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType("Access")
await consumer.requestTokens(metaData.base.price)
const serviceAgreementSignatureResult: any = await ocean.signServiceAgreement(ddo.id, const serviceAgreementSignatureResult: any = await ocean.signServiceAgreement(ddo.id,
accessService.serviceDefinitionId, consumer) accessService.serviceDefinitionId, consumer)
Logger.log("ServiceAgreement Id:", serviceAgreementSignatureResult.serviceAgreementId) Logger.log("ServiceAgreement Id:", serviceAgreementSignatureResult.serviceAgreementId)

View File

@ -0,0 +1,11 @@
import {Logger, Ocean} from "../squid"
import config from "./config"
(async () => {
const ocean: Ocean = await Ocean.getInstance(config)
const accounts = await ocean.getAccounts()
Logger.log(JSON.stringify(accounts, null, 2))
})()

View File

@ -0,0 +1,10 @@
import {Logger, Ocean} from "../squid"
import config from "./config"
(async () => {
const ocean: Ocean = await Ocean.getInstance(config)
const accounts = await ocean.getAccounts()
Logger.log(await accounts[0].getBalance())
})()

View File

@ -0,0 +1,10 @@
import {Logger, Ocean} from "../squid"
import config from "./config"
(async () => {
const ocean: Ocean = await Ocean.getInstance(config)
const accounts = await ocean.getAccounts()
Logger.log(JSON.stringify(accounts, null, 2))
})()

View File

@ -0,0 +1,73 @@
import DDO from "../ddo/DDO"
import MetaData from "../ddo/MetaData"
import MetaDataBase from "../ddo/MetaDataBase"
import Service from "../ddo/Service"
import {Account, Logger, Ocean, ServiceAgreement} from "../squid"
import config from "./config"
(async () => {
const ocean: Ocean = await Ocean.getInstance(config)
const publisher: Account = (await ocean.getAccounts())[0]
const consumer: Account = (await ocean.getAccounts())[1]
const metaData = new 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",
contentUrls: [
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.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,
} as MetaDataBase,
} as MetaData)
const ddo: DDO = await ocean.registerAsset(metaData, publisher)
Logger.log("did", ddo.id)
const assetId = ddo.id.replace("did:op:", "")
const accessService = ddo.findServiceByType("Access")
const serviceAgreementSignatureResult: any = await ocean.signServiceAgreement(ddo.id,
accessService.serviceDefinitionId, consumer)
Logger.log("ServiceAgreement Id:", serviceAgreementSignatureResult.serviceAgreementId)
Logger.log("ServiceAgreement Signature:", serviceAgreementSignatureResult.serviceAgreementSignature)
const service: Service = ddo.findServiceByType("Access")
const serviceAgreement: ServiceAgreement = await ocean.executeServiceAgreement(
ddo.id,
service.serviceDefinitionId,
serviceAgreementSignatureResult.serviceAgreementId,
serviceAgreementSignatureResult.serviceAgreementSignature,
consumer,
publisher)
Logger.log("ServiceAgreement Id:", serviceAgreement.getId())
await consumer.requestTokens(metaData.base.price)
const paid = await serviceAgreement.payAsset(assetId, metaData.base.price, consumer)
Logger.log(`Asset paid: ${paid}`)
const accessGranted = await serviceAgreement.grantAccess(assetId, assetId, publisher)
Logger.log(`Asset access granted: ${accessGranted}`)
})()

View File

@ -3,20 +3,12 @@ import MetaData from "../ddo/MetaData"
import MetaDataBase from "../ddo/MetaDataBase" import MetaDataBase from "../ddo/MetaDataBase"
import Service from "../ddo/Service" import Service from "../ddo/Service"
import {Account, Logger, Ocean} from "../squid" import {Account, Logger, Ocean} from "../squid"
import config from "./config"
(async () => { (async () => {
const ocean: Ocean = await Ocean.getInstance({ const ocean: Ocean = await Ocean.getInstance(config)
nodeUri: "http://localhost:8545",
aquariusUri: "http://localhost:5000",
brizoUri: "http://localhost:8030",
parityUri: "http://localhost:9545",
secretStoreUri: "http://localhost:12001",
threshold: 0,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
})
const publisher: Account = (await ocean.getAccounts())[0] const publisher: Account = (await ocean.getAccounts())[1]
const consumer: Account = (await ocean.getAccounts())[1] const consumer: Account = (await ocean.getAccounts())[1]
const metaData = new MetaData({ const metaData = new MetaData({
@ -31,12 +23,11 @@ import {Account, Logger, Ocean} from "../squid"
copyrightHolder: "Met Office", copyrightHolder: "Met Office",
encoding: "UTF-8", encoding: "UTF-8",
compression: "zip", compression: "zip",
contentType: "text/csv", contentType: "Application/pdf",
// tslint:disable-next-line // 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", workExample: "stationId,latitude,longitude,datetime,temperature,humidity423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68",
contentUrls: [ contentUrls: [
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip", "https://testocnfiles.blob.core.windows.net/testfiles/testzkp.pdf",
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip",
], ],
links: [ links: [
{sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"}, {sample1: "http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"},
@ -50,10 +41,12 @@ import {Account, Logger, Ocean} from "../squid"
} as MetaData) } as MetaData)
const ddo: DDO = await ocean.registerAsset(metaData, publisher) const ddo: DDO = await ocean.registerAsset(metaData, publisher)
Logger.log("did", ddo.id) Logger.log("Registered asset with did:", ddo.id)
const accessService = ddo.findServiceByType("Access") const accessService = ddo.findServiceByType("Access")
await consumer.requestTokens(100)
const serviceAgreementSignatureResult: any = await ocean const serviceAgreementSignatureResult: any = await ocean
.signServiceAgreement( .signServiceAgreement(
ddo.id, ddo.id,

20
src/examples/Listener.ts Normal file
View File

@ -0,0 +1,20 @@
import {Logger, Ocean} from "../squid"
// tslint:disable-next-line
import EventListener from "../keeper/EventListener"
import config from "./config"
(async () => {
Ocean.getInstance(config)
})()
const event = EventListener.subscribe("OceanToken", "Transfer", {})
Logger.log(`Listening to Transfer event of OceanToken`)
event.listen((data: any[]) => {
Logger.log(Date.now())
Logger.log("From", data[0].returnValues.from)
Logger.log("To", data[0].returnValues.to)
Logger.log("Value", data[0].returnValues.value)
})

View File

@ -2,18 +2,11 @@ import DDO from "../ddo/DDO"
import MetaData from "../ddo/MetaData" import MetaData from "../ddo/MetaData"
import MetaDataBase from "../ddo/MetaDataBase" import MetaDataBase from "../ddo/MetaDataBase"
import {Account, Logger, Ocean} from "../squid" import {Account, Logger, Ocean} from "../squid"
import config from "./config"
(async () => { (async () => {
const ocean: Ocean = await Ocean.getInstance({
nodeUri: "http://localhost:8545", const ocean: Ocean = await Ocean.getInstance(config)
aquariusUri: "http://localhost:5000",
brizoUri: "http://localhost:8030",
parityUri: "http://localhost:9545",
secretStoreUri: "http://localhost:12001",
threshold: 0,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
})
const publisher: Account = (await ocean.getAccounts())[0] const publisher: Account = (await ocean.getAccounts())[0]

View File

@ -1,22 +1,15 @@
import {Account, Logger, Ocean, ServiceAgreementTemplate, Templates} from "../squid" import {Account, Logger, Ocean, ServiceAgreementTemplate, Templates} from "../squid"
import config from "./config"
(async () => { (async () => {
const ocean: Ocean = await Ocean.getInstance({
nodeUri: "http://localhost:8545",
aquariusUri: "http://localhost:5000",
brizoUri: "http://localhost:8030",
parityUri: "http://localhost:9545",
secretStoreUri: "http://localhost:12001",
threshold: 0,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
})
const templateOwner: Account = (await ocean.getAccounts())[5] const ocean: Ocean = await Ocean.getInstance(config)
const templateOwner: Account = (await ocean.getAccounts())[0]
const serviceAgreementTemplate: ServiceAgreementTemplate = new ServiceAgreementTemplate(new Templates.Access()) const serviceAgreementTemplate: ServiceAgreementTemplate = new ServiceAgreementTemplate(new Templates.Access())
const serviceAgreementRegistered: boolean = await serviceAgreementTemplate.register(templateOwner.getId()) const serviceAgreementRegistered: boolean = await serviceAgreementTemplate.register(templateOwner.getId())
Logger.log("ServiceAgreement registered:", serviceAgreementRegistered, Logger.log("ServiceAgreementTemplate registered:", serviceAgreementRegistered,
"templateId:", serviceAgreementTemplate.getId()) "templateId:", serviceAgreementTemplate.getId())
})() })()

View File

@ -1,17 +1,9 @@
import DDO from "../ddo/DDO" import DDO from "../ddo/DDO"
import {Logger, Ocean} from "../squid" import {Logger, Ocean} from "../squid"
import config from "./config"
(async () => { (async () => {
const ocean: Ocean = await Ocean.getInstance({ const ocean: Ocean = await Ocean.getInstance(config)
nodeUri: "http://localhost:8545",
aquariusUri: "http://localhost:5000",
brizoUri: "http://localhost:8030",
parityUri: "http://localhost:9545",
secretStoreUri: "http://localhost:12001",
threshold: 0,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
})
const result: DDO[] = await ocean.searchAssetsByText("Office Humidity") const result: DDO[] = await ocean.searchAssetsByText("Office Humidity")
const names: string[] = result.map((ddo: DDO): string => { const names: string[] = result.map((ddo: DDO): string => {

View File

@ -5,18 +5,10 @@ import MetaData from "../ddo/MetaData"
import MetaDataBase from "../ddo/MetaDataBase" import MetaDataBase from "../ddo/MetaDataBase"
import Service from "../ddo/Service" import Service from "../ddo/Service"
import {Account, Logger, Ocean} from "../squid" import {Account, Logger, Ocean} from "../squid"
import config from "./config"
(async () => { (async () => {
const ocean: Ocean = await Ocean.getInstance({ const ocean: Ocean = await Ocean.getInstance(config)
nodeUri: "http://localhost:8545",
aquariusUri: "http://localhost:5000",
brizoUri: "http://localhost:8030",
parityUri: "http://localhost:9545",
secretStoreUri: "http://localhost:12001",
threshold: 0,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
})
const publisher: Account = (await ocean.getAccounts())[0] const publisher: Account = (await ocean.getAccounts())[0]
const consumer: Account = (await ocean.getAccounts())[1] const consumer: Account = (await ocean.getAccounts())[1]
@ -74,6 +66,9 @@ import {Account, Logger, Ocean} from "../squid"
Logger.log("did", ddo.id) Logger.log("did", ddo.id)
const accessService: Service = ddo.findServiceByType("Access") const accessService: Service = ddo.findServiceByType("Access")
await consumer.requestTokens(metaData.base.price)
const serviceAgreementResult: any = await ocean const serviceAgreementResult: any = await ocean
.signServiceAgreement( .signServiceAgreement(
ddo.id, ddo.id,

16
src/examples/config.ts Normal file
View File

@ -0,0 +1,16 @@
import * as HDWalletProvider from "truffle-hdwallet-provider"
import Config from "../models/Config"
import * as config from "./config/config.json"
if (false) {
const seedphrase = "xxx"
// @ts-ignore
config.web3Provider = new HDWalletProvider(
seedphrase,
config.nodeUri,
0, 10,
)
}
export default config as Config

View File

@ -0,0 +1,10 @@
{
"nodeUri": "http://localhost:8545",
"aquariusUri": "http://aquarius.dev-ocean.com:5000",
"brizoUri": "http://localhost:8030",
"parityUri": "http://localhost:9545",
"secretStoreUri": "http://localhost:12001",
"threshold": 0,
"password": "secret",
"address": "0xa99d43d86a0758d5632313b8fa3972b6088a21bb"
}

View File

@ -2,8 +2,13 @@
set -e set -e
# this has to go first
npm run run src/examples/RegisterServiceAgreementTemplates.ts npm run run src/examples/RegisterServiceAgreementTemplates.ts
npm run run src/examples/BuyAsset.ts
npm run run src/examples/ExecuteAgreement.ts
npm run run src/examples/GetAccounts.ts
npm run run src/examples/GetBalance.ts
npm run run src/examples/GrantAccess.ts
npm run run src/examples/RegisterAsset.ts npm run run src/examples/RegisterAsset.ts
npm run run src/examples/Search.ts npm run run src/examples/Search.ts
npm run run src/examples/SignAgreement.ts
npm run run src/examples/ExecuteAgreement.ts

58
src/keeper/Event.ts Normal file
View File

@ -0,0 +1,58 @@
import GenericContract from "./contracts/GenericContract"
import EventListener from "./EventListener"
import Web3Provider from "./Web3Provider"
// import Logger from "../utils/Logger"
export default class Event {
private poller = null
private lastBlock: number = 0
private interval: number = 200
constructor(private contractName: string,
private eventName: string,
private filter: any) {
}
public stopListen() {
clearInterval(this.poller)
this.poller = null
}
public async listen(callback: any) {
this.lastBlock = await Web3Provider.getWeb3().eth.getBlockNumber() + 1
this.poller = setInterval(
() => this.handler(callback),
this.interval)
}
public listenOnce(callback: any) {
this.listen((events: any[]) => {
if (events) {
EventListener.unsubscribe(this)
callback(events[0])
}
})
}
private async handler(callback: any) {
const contract = await GenericContract.getInstance(this.contractName)
try {
const events = await contract.getEventData(this.eventName, {
filter: this.filter,
fromBlock: this.lastBlock,
toBlock: "latest",
})
if (events.length > 0) {
this.lastBlock = events[events.length - 1].blockNumber + 1
callback(events)
}
} catch (err) {
// Logger.log("err")
}
}
}

View File

@ -0,0 +1,29 @@
import Event from "./Event"
export default class EventListener {
public static subscribe(contractName: string,
eventName: string,
filter: any): Event {
const event = new Event(contractName, eventName, filter)
EventListener.events.push(event)
return event
}
public static unsubscribe(event): boolean {
event.stopListen()
const i = EventListener.events.indexOf(event)
if (i > -1) {
EventListener.events.splice(i, 1)
}
return true
}
public static count() {
return EventListener.events.length
}
private static events: Event[] = []
}

View File

@ -1,3 +1,4 @@
// import Logger from "../utils/Logger"
import OceanAuth from "./contracts/Auth" import OceanAuth from "./contracts/Auth"
import AccessConditions from "./contracts/conditions/AccessConditions" import AccessConditions from "./contracts/conditions/AccessConditions"
import PaymentConditions from "./contracts/conditions/PaymentConditions" import PaymentConditions from "./contracts/conditions/PaymentConditions"
@ -53,13 +54,24 @@ export default class Keeper {
case 4: case 4:
network = "Rinkeby" network = "Rinkeby"
break break
case 77:
network = "POA_Sokol"
break
case 99:
network = "POA_Core"
break
case 42: case 42:
network = "Kovan" network = "Kovan"
break break
case 8996:
network = "Spree"
// network = "ocean_poa_net_local"
break
case 8995: case 8995:
network = "Ocean_POA_AWS" network = "Nile"
break break
default: default:
// Logger.log(`NetworkId ${networkId} not found defaulting`)
network = "Development" network = "Development"
} }
return network return network

View File

@ -15,22 +15,6 @@ export default abstract class ContractBase {
this.contractName = contractName this.contractName = contractName
} }
/*
public async listenToEventOnce(eventName: string, options: any): Promise<any> {
return new Promise<any>((resolve, reject) => {
if (!this.contract.events[eventName]) {
throw new Error(`Event ${eventName} not found on contract ${this.contractName}`)
}
this.contract.events[eventName](options, (err) => {
reject(err)
})
.on("data", (eventData: any) => {
resolve(eventData)
})
})
}
*/
public async getEventData(eventName: any, options: any): Promise<Event[]> { public async getEventData(eventName: any, options: any): Promise<Event[]> {
if (!this.contract.events[eventName]) { if (!this.contract.events[eventName]) {
throw new Error(`Event "${eventName}" not found on contract "${this.contractName}"`) throw new Error(`Event "${eventName}" not found on contract "${this.contractName}"`)

View File

@ -25,6 +25,8 @@ export default class ServiceAgreement extends ContractBase {
]) ])
} }
// todo get service agreement consumer
public async getTemplateStatus(templateId: string) { public async getTemplateStatus(templateId: string) {
return this.call("getTemplateStatus", [templateId]) return this.call("getTemplateStatus", [templateId])
@ -47,7 +49,7 @@ export default class ServiceAgreement extends ContractBase {
return this.send("executeAgreement", publisherAddress, [ return this.send("executeAgreement", publisherAddress, [
serviceAgreementTemplateId, serviceAgreementSignatureHash, consumerAddress, valueHashes, serviceAgreementTemplateId, serviceAgreementSignatureHash, consumerAddress, valueHashes,
timeoutValues, "0x" + serviceAgreementId, "0x" + did.replace("did:op:", ""), timeoutValues, serviceAgreementId, "0x" + did.replace("did:op:", ""),
]) ])
} }
} }

View File

@ -9,6 +9,8 @@ export default class AccessConditions extends ContractBase {
return accessConditions return accessConditions
} }
// todo add check permissions proxy
public async grantAccess(serviceAgreementId: any, assetId: any, documentKeyId: any, publisherAddress: string) public async grantAccess(serviceAgreementId: any, assetId: any, documentKeyId: any, publisherAddress: string)
: Promise<Receipt> { : Promise<Receipt> {
return this.send("grantAccess", publisherAddress, [ return this.send("grantAccess", publisherAddress, [

View File

@ -14,7 +14,9 @@ export default class Account extends OceanBase {
public async getEtherBalance(): Promise<number> { public async getEtherBalance(): Promise<number> {
// Logger.log("getting balance for", account); // Logger.log("getting balance for", account);
return Web3Provider.getWeb3().eth return Web3Provider
.getWeb3()
.eth
.getBalance(this.id, "latest") .getBalance(this.id, "latest")
.then((balance: string): number => { .then((balance: string): number => {
// Logger.log("balance", balance); // Logger.log("balance", balance);
@ -35,7 +37,9 @@ export default class Account extends OceanBase {
} }
public async requestTokens(amount: number): Promise<number> { public async requestTokens(amount: number): Promise<number> {
await (await Keeper.getInstance()).market.requestTokens(amount, this.id) await (await Keeper.getInstance())
.market
.requestTokens(amount, this.id)
return amount return amount
} }

View File

@ -1,15 +1,18 @@
import {saveAs} from "file-saver"
import AquariusProvider from "../aquarius/AquariusProvider" 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 Authentication from "../ddo/Authentication" import Authentication from "../ddo/Authentication"
import DDOCondition from "../ddo/Condition" import Condition from "../ddo/Condition"
import Contract from "../ddo/Contract"
import DDO from "../ddo/DDO" import DDO from "../ddo/DDO"
import Event from "../ddo/Event" import Event from "../ddo/Event"
import EventHandlers from "../ddo/EventHandlers" import EventHandler from "../ddo/EventHandler"
import MetaData from "../ddo/MetaData" import MetaData from "../ddo/MetaData"
import Parameter from "../ddo/Parameter" import PublicKey from "../ddo/PublicKey"
import Service from "../ddo/Service" import Service from "../ddo/Service"
import ContractEvent from "../keeper/Event"
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"
@ -18,11 +21,13 @@ import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Logger from "../utils/Logger" import Logger from "../utils/Logger"
import Account from "./Account" import Account from "./Account"
import IdGenerator from "./IdGenerator" import IdGenerator from "./IdGenerator"
import Condition from "./ServiceAgreements/Condition"
import ServiceAgreement from "./ServiceAgreements/ServiceAgreement" import ServiceAgreement from "./ServiceAgreements/ServiceAgreement"
import ServiceAgreementTemplate from "./ServiceAgreements/ServiceAgreementTemplate" import ServiceAgreementTemplate from "./ServiceAgreements/ServiceAgreementTemplate"
import Access from "./ServiceAgreements/Templates/Access" import Access from "./ServiceAgreements/Templates/Access"
import EventListener from "../keeper/EventListener"
import WebServiceConnectorProvider from "../utils/WebServiceConnectorProvider"
export default class Ocean { export default class Ocean {
public static async getInstance(config: Config) { public static async getInstance(config: Config) {
@ -62,74 +67,19 @@ export default class Ocean {
const aquarius = AquariusProvider.getAquarius() const aquarius = AquariusProvider.getAquarius()
const brizo = BrizoProvider.getBrizo() const brizo = BrizoProvider.getBrizo()
const id: string = IdGenerator.generateId() const assetId: string = IdGenerator.generateId()
const did: string = `did:op:${id}` const did: string = `did:op:${assetId}`
const serviceDefinitionId: string = IdGenerator.generatePrefixedId() const accessServiceDefinitionId: string = "0"
const computeServiceDefintionId: string = "1"
const metadataServiceDefinitionId: string = "2"
metadata.base.contentUrls = metadata.base.contentUrls =
await SecretStoreProvider.getSecretStore().encryptDocument(id, metadata.base.contentUrls) [await SecretStoreProvider.getSecretStore().encryptDocument(assetId, metadata.base.contentUrls)]
const template = new Access() const template = new Access()
const serviceAgreementTemplate = new ServiceAgreementTemplate(template) const serviceAgreementTemplate = new ServiceAgreementTemplate(template)
// get condition keys from template const conditions: Condition[] = await serviceAgreementTemplate.getConditions(metadata, assetId)
const conditions: Condition[] = await serviceAgreementTemplate.getConditions()
// create ddo conditions out of the keys
const ddoConditions: DDOCondition[] = conditions
.map((condition: Condition, index: number): DDOCondition => {
const events: Event[] = [
{
name: "PaymentReleased",
actorType: [
"consumer",
],
handlers: {
moduleName: "serviceAgreement",
functionName: "fulfillAgreement",
version: "0.1",
} as EventHandlers,
} as Event,
]
const mapParameterValueToName = (name) => {
switch (name) {
case "price":
return metadata.base.price
case "assetId":
return "0x" + id
case "documentKeyId":
return "0x1234"
}
return null
}
const parameters: Parameter[] = condition.parameters.map((parameter: Parameter) => {
return {
name: parameter.name,
type: parameter.type,
value: mapParameterValueToName(parameter.name),
} as Parameter
})
// Logger.log(`${condition.methodReflection.contractName}.${condition.methodReflection.methodName}`,
// JSON.stringify(parameters, null, 2))
return {
contractName: condition.methodReflection.contractName,
methodName: condition.methodReflection.methodName,
timeout: condition.timeout,
index,
conditionKey: condition.condtionKey,
parameters,
events,
dependencies: condition.dependencies,
dependencyTimeoutFlags: condition.dependencyTimeoutFlags,
isTerminalCondition: condition.isTerminalCondition,
} as DDOCondition
})
const serviceEndpoint = aquarius.getServiceEndpoint(did) const serviceEndpoint = aquarius.getServiceEndpoint(did)
@ -143,37 +93,47 @@ export default class Ocean {
publicKey: [ publicKey: [
{ {
id: did + "#keys-1", id: did + "#keys-1",
},
{
type: "Ed25519VerificationKey2018", type: "Ed25519VerificationKey2018",
},
{
owner: did, owner: did,
},
{
publicKeyBase58: await publisher.getPublicKey(), publicKeyBase58: await publisher.getPublicKey(),
}, } as PublicKey,
], ],
service: [ service: [
{ {
type: template.templateName, type: template.templateName,
purchaseEndpoint: brizo.getPurchaseEndpoint(), purchaseEndpoint: brizo.getPurchaseEndpoint(),
serviceEndpoint: brizo.getConsumeEndpoint(publisher.getId(), serviceEndpoint: brizo.getConsumeEndpoint(),
serviceDefinitionId, metadata.base.contentUrls[0]),
// the id of the service agreement? // the id of the service agreement?
serviceDefinitionId, serviceDefinitionId: accessServiceDefinitionId,
// the id of the service agreement template // the id of the service agreement template
templateId: serviceAgreementTemplate.getId(), templateId: serviceAgreementTemplate.getId(),
conditions: ddoConditions, serviceAgreementContract: {
contractName: "ServiceAgreement",
fulfillmentOperator: template.fulfillmentOperator,
events: [
{
name: "ExecuteAgreement",
actorType: "consumer",
handler: {
moduleName: "payment",
functionName: "lockPayment",
version: "0.1",
} as EventHandler,
} as Event,
],
} as Contract,
conditions,
} as Service, } as Service,
{ {
type: "Compute", type: "Compute",
serviceEndpoint: brizo.getComputeEndpoint(publisher.getId(), serviceEndpoint: brizo.getComputeEndpoint(publisher.getId(),
serviceDefinitionId, "xxx", "xxx"), computeServiceDefintionId, "xxx", "xxx"),
serviceDefinitionId: computeServiceDefintionId,
} as Service, } as Service,
{ {
type: "Metadata", type: "Metadata",
serviceEndpoint, serviceEndpoint,
serviceDefinitionId: metadataServiceDefinitionId,
metadata, metadata,
} as Service, } as Service,
], ],
@ -181,9 +141,11 @@ export default class Ocean {
const storedDdo = await aquarius.storeDDO(ddo) const storedDdo = await aquarius.storeDDO(ddo)
// Logger.log(JSON.stringify(storedDdo, null, 2))
await didRegistry.registerAttribute( await didRegistry.registerAttribute(
id, assetId,
ValueType.DID, ValueType.URL,
"Metadata", "Metadata",
serviceEndpoint, serviceEndpoint,
publisher.getId()) publisher.getId())
@ -197,11 +159,63 @@ export default class Ocean {
const ddo = await AquariusProvider.getAquarius().retrieveDDO(did) const ddo = await AquariusProvider.getAquarius().retrieveDDO(did)
const id = did.replace("did:op:", "") const id = did.replace("did:op:", "")
const serviceAgreementId: string = IdGenerator.generateId() const serviceAgreementId: string = IdGenerator.generatePrefixedId()
try { try {
const serviceAgreementSignature: string = await ServiceAgreement.signServiceAgreement(id, const serviceAgreementSignature: string = await ServiceAgreement.signServiceAgreement(id,
ddo, serviceDefinitionId, serviceAgreementId, consumer) ddo, serviceDefinitionId, serviceAgreementId, consumer)
const accessService: Service = ddo.findServiceByType("Access")
const metadataService: Service = ddo.findServiceByType("Metadata")
const price = metadataService.metadata.base.price
const balance = await consumer.getOceanBalance()
if (balance < price) {
throw new Error(`Not enough ocean tokens! Should have ${price} but has ${balance}`)
}
const event: ContractEvent = EventListener.subscribe(
accessService.serviceAgreementContract.contractName,
accessService.serviceAgreementContract.events[0].name, {
serviceAgreementId,
})
event.listenOnce(async (data) => {
const sa: ServiceAgreement = new ServiceAgreement(data.returnValues.serviceAgreementId)
await sa.payAsset(id,
metadataService.metadata.base.price,
consumer,
)
Logger.log("Completed asset payment, now access should be granted.")
})
const accessEvent: ContractEvent = EventListener.subscribe(
accessService.conditions[1].contractName,
accessService.conditions[1].events[1].name, {})
accessEvent.listenOnce(async (data) => {
Logger.log("Awesome; got a AccessGranted Event. Let's download the asset files.")
const webConnector = WebServiceConnectorProvider.getConnector()
const contentUrls = await SecretStoreProvider.getSecretStore()
.decryptDocument(id, metadataService.metadata.base.contentUrls[0])
const serviceUrl: string = accessService.serviceEndpoint
Logger.log("Consuming asset files using service url: ", serviceUrl)
for (const cUrl of contentUrls) {
let url: string = serviceUrl + `?url=${cUrl}`
url = url + `&serviceAgreementId=${serviceAgreementId}`
url = url + `&consumerAddress=${consumer.getId()}`
Logger.log("Fetching asset from: ", url)
const response: any = await webConnector.get(url)
const buffer: Buffer = await response.buffer()
const parts: string[] = cUrl.split("/")
const filename: string = parts[parts.length - 1]
Logger.debug(`Got response: filename is ${filename}, url is ${response.url}`)
const target = `${__dirname}/downloads/${filename}`
await saveAs([buffer.toString("utf8")], filename)
Logger.log("saved file to:", target)
}
Logger.log("Done downloading asset files.")
})
return { return {
serviceAgreementId, serviceAgreementId,
serviceAgreementSignature, serviceAgreementSignature,
@ -224,9 +238,9 @@ export default class Ocean {
serviceAgreementId, serviceAgreementId,
serviceDefinitionId, serviceDefinitionId,
serviceAgreementSignature, serviceAgreementSignature,
await consumer.getPublicKey()) consumer.getId())
Logger.log(result) Logger.log(result.status)
} }
public async executeServiceAgreement(did: string, public async executeServiceAgreement(did: string,

View File

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

View File

@ -0,0 +1,7 @@
import EventHandler from "./EventHandler"
export default class Event {
public name: string = "PaymentLocked"
public actorType: string = "publisher"
public handler: EventHandler
}

View File

@ -0,0 +1,5 @@
export default class EventHandler {
public moduleName: string = "accessControl"
public functionName: string = "grantAccess"
public version: string = "0.1"
}

View File

@ -1,3 +1,4 @@
import Event from "./Event"
import Parameter from "./Parameter" import Parameter from "./Parameter"
export default class Method { export default class Method {
@ -6,6 +7,7 @@ export default class Method {
public methodName: string public methodName: string
public timeout: number public timeout: number
public parameters: Parameter[] public parameters: Parameter[]
public events: Event[]
public dependencies: string[] public dependencies: string[]
public dependencyTimeoutFlags: number[] public dependencyTimeoutFlags: number[]
public isTerminalCondition: boolean public isTerminalCondition: boolean

View File

@ -117,11 +117,6 @@ export default class ServiceAgreement extends OceanBase {
return new ServiceAgreement( return new ServiceAgreement(
executeAgreementReceipt.events.ExecuteAgreement.returnValues.serviceAgreementId, executeAgreementReceipt.events.ExecuteAgreement.returnValues.serviceAgreementId,
ddo,
publisher,
new Account(consumerAddress),
executeAgreementReceipt.events.ExecuteAgreement.returnValues.state,
executeAgreementReceipt.events.ExecuteAgreement.returnValues.status,
) )
} }
@ -186,7 +181,7 @@ export default class ServiceAgreement extends OceanBase {
contionValues.push({ contionValues.push({
type: parameter.type, type: parameter.type,
value: parameter.name === "serviceId" ? "0x" + serviceAgreementId : parameter.value, value: parameter.name === "serviceId" ? serviceAgreementId : parameter.value,
} as ValuePair) } as ValuePair)
}) })
@ -196,16 +191,11 @@ export default class ServiceAgreement extends OceanBase {
return values return values
} }
private constructor(serviceAgreementId: string, constructor(serviceAgreementId: string) {
ddo: DDO,
private publisher: Account,
consumer: Account,
state: boolean,
status: boolean) {
super(serviceAgreementId) super(serviceAgreementId)
} }
public async buyAsset(assetId: string, price: number, consumer: Account): Promise<boolean> { public async payAsset(assetId: string, price: number, consumer: Account): Promise<boolean> {
const {paymentConditions, token} = await Keeper.getInstance() const {paymentConditions, token} = await Keeper.getInstance()
await token.approve(paymentConditions.getAddress(), price, consumer.getId()) await token.approve(paymentConditions.getAddress(), price, consumer.getId())
@ -217,12 +207,11 @@ export default class ServiceAgreement extends OceanBase {
return lockPaymentReceipt.status return lockPaymentReceipt.status
} }
public async grantAccess(assetId: string, documentId: string): Promise<boolean> { public async grantAccess(assetId: string, documentId: string, publisher: Account): Promise<boolean> {
const {accessConditions} = await Keeper.getInstance() const {accessConditions} = await Keeper.getInstance()
const grantAccessReceipt = const grantAccessReceipt =
await accessConditions.grantAccess(this.getId(), assetId, documentId, await accessConditions.grantAccess(this.getId(), assetId, documentId, publisher.getId())
this.publisher.getId())
return !!grantAccessReceipt.events.AccessGranted return !!grantAccessReceipt.events.AccessGranted
} }

View File

@ -1,3 +1,7 @@
import DDOCondition from "../../ddo/Condition"
import Dependency from "../../ddo/Dependency"
import MetaData from "../../ddo/MetaData"
import Parameter from "../../ddo/Parameter"
import ContractReflector from "../../keeper/ContractReflector" import ContractReflector from "../../keeper/ContractReflector"
import Keeper from "../../keeper/Keeper" import Keeper from "../../keeper/Keeper"
import Web3Provider from "../../keeper/Web3Provider" import Web3Provider from "../../keeper/Web3Provider"
@ -96,7 +100,58 @@ export default class ServiceAgreementTemplate extends OceanBase {
return new Account(await serviceAgreement.getTemplateOwner(this.id)) return new Account(await serviceAgreement.getTemplateOwner(this.id))
} }
public async getConditions(): Promise<Condition[]> { public async getConditions(metadata: MetaData, assetId: string): Promise<DDOCondition[]> {
const conditions = await this.blendConditions()
return conditions.map((condition: Condition, index: number): DDOCondition => {
const mapParameterValueToName = (name) => {
switch (name) {
case "price":
return metadata.base.price
case "assetId":
return "0x" + assetId
case "documentKeyId":
return "0x" + assetId
}
return null
}
const parameters: Parameter[] = condition.parameters.map((parameter: Parameter) => {
return {
name: parameter.name,
type: parameter.type,
value: mapParameterValueToName(parameter.name),
} as Parameter
})
// Logger.log(`${condition.methodReflection.contractName}.${condition.methodReflection.methodName}`,
// JSON.stringify(parameters, null, 2))
const dependencies: Dependency[] = condition.dependencies.map((dep, i) => {
return {
name: dep,
timeout: condition.dependencyTimeoutFlags[i],
} as Dependency
})
return {
name: condition.methodReflection.methodName,
dependencies,
timeout: condition.timeout,
isTerminalCondition: condition.isTerminalCondition,
conditionKey: condition.condtionKey,
contractName: condition.methodReflection.contractName,
functionName: condition.methodReflection.methodName,
index,
parameters,
events: condition.events,
} as DDOCondition
})
}
private async blendConditions(): Promise<Condition[]> {
const methodReflections = await this.getMethodReflections() const methodReflections = await this.getMethodReflections()
const conditions: Condition[] = methodReflections.map((methodReflection, i) => { const conditions: Condition[] = methodReflections.map((methodReflection, i) => {
@ -104,6 +159,7 @@ export default class ServiceAgreementTemplate extends OceanBase {
return { return {
methodReflection, methodReflection,
timeout: method.timeout, timeout: method.timeout,
events: method.events,
parameters: method.parameters, parameters: method.parameters,
dependencies: method.dependencies, dependencies: method.dependencies,
dependencyTimeoutFlags: method.dependencyTimeoutFlags, dependencyTimeoutFlags: method.dependencyTimeoutFlags,

View File

@ -1,4 +1,7 @@
import Event from "../Event"
import EventHandler from "../EventHandler"
import Method from "../Method" import Method from "../Method"
import Parameter from "../Parameter"
import TemplateBase from "./TemplateBase" import TemplateBase from "./TemplateBase"
export default class Access extends TemplateBase { export default class Access extends TemplateBase {
@ -15,68 +18,124 @@ export default class Access extends TemplateBase {
{ {
name: "assetId", name: "assetId",
type: "bytes32", type: "bytes32",
}, } as Parameter, {
{
name: "price", name: "price",
type: "uint256", type: "uint256",
}, } as Parameter,
],
events: [
{
name: "PaymentLocked",
actorType: "publisher",
handler: {
moduleName: "accessControl",
functionName: "grantAccess",
version: "0.1",
} as EventHandler,
} as Event,
], ],
dependencies: [], dependencies: [],
dependencyTimeoutFlags: [], dependencyTimeoutFlags: [],
isTerminalCondition: false, isTerminalCondition: false,
} as Method, } as Method, {
{
name: "grantAccess", name: "grantAccess",
contractName: "AccessConditions", contractName: "AccessConditions",
methodName: "grantAccess", methodName: "grantAccess",
timeout: 10, timeout: 0,
parameters: [ parameters: [
{ {
name: "assetId", name: "assetId",
type: "bytes32", type: "bytes32",
}, } as Parameter,
{ {
name: "documentKeyId", name: "documentKeyId",
type: "bytes32", type: "bytes32",
}, } as Parameter,
],
events: [
{
name: "AccessGranted",
actorType: "publisher",
handler: {
moduleName: "payment",
functionName: "releasePayment",
version: "0.1",
} as EventHandler,
} as Event,
{
name: "AccessGranted",
actorType: "consumer",
handler: {
moduleName: "accessControl",
functionName: "consumeAsset",
version: "0.1",
} as EventHandler,
} as Event,
{
name: "AccessTimeout",
actorType: "consumer",
handler: {
moduleName: "payment",
functionName: "refundPayment",
version: "0.1",
} as EventHandler,
} as Event,
], ],
dependencies: ["lockPayment"], dependencies: ["lockPayment"],
dependencyTimeoutFlags: [0], dependencyTimeoutFlags: [0],
isTerminalCondition: false, isTerminalCondition: false,
} as Method, } as Method, {
{
name: "releasePayment", name: "releasePayment",
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "releasePayment", methodName: "releasePayment",
timeout: 10, timeout: 0,
parameters: [ parameters: [
{ {
name: "assetId", name: "assetId",
type: "bytes32", type: "bytes32",
}, } as Parameter, {
{
name: "price", name: "price",
type: "uint256", type: "uint256",
}, } as Parameter,
],
events: [
{
name: "PaymentReleased",
actorType: "consumer",
handler: {
moduleName: "serviceAgreement",
functionName: "fulfillAgreement",
version: "0.1",
} as EventHandler,
} as Event,
], ],
dependencies: ["grantAccess"], dependencies: ["grantAccess"],
dependencyTimeoutFlags: [0], dependencyTimeoutFlags: [0],
isTerminalCondition: true, isTerminalCondition: true,
} as Method, } as Method, {
{
name: "refundPayment", name: "refundPayment",
contractName: "PaymentConditions", contractName: "PaymentConditions",
methodName: "refundPayment", methodName: "refundPayment",
timeout: 10, timeout: 10 * 60,
parameters: [ parameters: [
{ {
name: "assetId", name: "assetId",
type: "bytes32", type: "bytes32",
}, } as Parameter, {
{
name: "price", name: "price",
type: "uint256", type: "uint256",
}, } as Parameter,
],
events: [
{
name: "PaymentRefund",
actorType: "publisher",
handler: {
moduleName: "serviceAgreement",
functionName: "terminateAgreement",
version: "0.1",
} as EventHandler,
} as Event,
], ],
dependencies: ["lockPayment", "grantAccess"], dependencies: ["lockPayment", "grantAccess"],
dependencyTimeoutFlags: [0, 1], dependencyTimeoutFlags: [0, 1],

View File

@ -6,8 +6,4 @@ export default {
nodeUri: "http://localhost:8545", nodeUri: "http://localhost:8545",
parityUri: "http://localhost:9545", parityUri: "http://localhost:9545",
secretStoreUri: "http://localhost:12001", secretStoreUri: "http://localhost:12001",
threshold: 0,
password: "unittest",
address: "0xed243adfb84a6626eba46178ccb567481c6e655d",
web3Provider: null,
} as Config } as Config

82
test/keeper/Event.test.ts Normal file
View File

@ -0,0 +1,82 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import EventListener from "../../src/keeper/EventListener"
import Keeper from "../../src/keeper/Keeper"
import Account from "../../src/ocean/Account"
import Ocean from "../../src/ocean/Ocean"
import config from "../config"
import TestContractHandler from "./TestContractHandler"
let keeper: Keeper
let ocean: Ocean
let accounts: Account[]
describe("EventListener", () => {
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
keeper = await Keeper.getInstance()
assert(keeper)
ocean = await Ocean.getInstance(config)
assert(ocean)
accounts = await ocean.getAccounts()
assert(accounts)
})
describe("#listen()", () => {
it("should listen to an event", (done) => {
const acc = accounts[1]
const event = EventListener.subscribe("OceanToken",
"Transfer",
{
to: acc.getId(),
})
event.listen((events) => {
assert(events)
assert(events.length === 2)
done()
EventListener.unsubscribe(event)
})
const {market} = keeper
market.requestTokens(400, acc.getId())
market.requestTokens(400, acc.getId())
})
})
describe("#listenOnce()", () => {
it("should listen once", (done) => {
const acc = accounts[1]
const countBefore = EventListener.count()
const event = EventListener.subscribe("OceanToken",
"Transfer",
{
to: acc.getId(),
})
event.listenOnce(
(data: any) => {
assert(data)
assert(data.blockNumber)
assert(EventListener.count() === countBefore)
done()
})
const {market} = keeper
market.requestTokens(400, acc.getId())
})
})
})

View File

@ -0,0 +1,69 @@
import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider"
import EventListener from "../../src/keeper/EventListener"
import Keeper from "../../src/keeper/Keeper"
import Account from "../../src/ocean/Account"
import Ocean from "../../src/ocean/Ocean"
import config from "../config"
import TestContractHandler from "./TestContractHandler"
let keeper: Keeper
let ocean: Ocean
let accounts: Account[]
describe("EventListener", () => {
before(async () => {
ConfigProvider.setConfig(config)
await TestContractHandler.prepareContracts()
keeper = await Keeper.getInstance()
assert(keeper)
ocean = await Ocean.getInstance(config)
assert(ocean)
accounts = await ocean.getAccounts()
assert(accounts)
})
describe("#subscribe()", () => {
it("should subscribe to an event", (done) => {
const acc = accounts[1]
const countBefore = EventListener.count()
const event = EventListener.subscribe("OceanToken",
"Transfer",
{
to: acc.getId(),
})
assert(event)
const countAfter = EventListener.count()
assert(countBefore + 1 === countAfter, `${countBefore}${countAfter}`)
EventListener.unsubscribe(event)
done()
})
})
describe("#unsubscribe()", () => {
it("should unsubscribe from an event", (done) => {
const countBefore = EventListener.count()
const event = EventListener.subscribe("OceanToken",
"Transfer",
{})
const count = EventListener.count()
const unsubscribed = EventListener.unsubscribe(event)
assert(unsubscribed)
const countAfter = EventListener.count()
assert(count > countBefore, `${count}${countAfter}`)
assert(countBefore === countAfter, `${countBefore}${countAfter}`)
done()
})
})
})

View File

@ -47,7 +47,8 @@ describe("Account", () => {
const balance = await account.getEtherBalance() const balance = await account.getEtherBalance()
const web3 = Web3Provider.getWeb3() const web3 = Web3Provider.getWeb3()
assert(Number(web3.utils.toWei("100", "ether")) === balance) assert(Number(web3.utils.toWei("100", "ether")) === balance,
`ether did not match ${balance}`)
}) })
}) })
@ -59,8 +60,9 @@ describe("Account", () => {
const balance = await account.getBalance() const balance = await account.getBalance()
const web3 = Web3Provider.getWeb3() const web3 = Web3Provider.getWeb3()
assert(Number(web3.utils.toWei("100", "ether")) === balance.eth) assert(Number(web3.utils.toWei("100", "ether")) === balance.eth,
assert(0 === balance.ocn) `ether did not match ${balance.eth}`)
assert(0 === balance.ocn, `tokens did not match ${balance.ocn}`)
}) })
}) })

View File

@ -127,20 +127,24 @@ describe("Ocean", () => {
const publisher = accounts[0] const publisher = accounts[0]
const consumer = accounts[1] const consumer = accounts[1]
const ddo: DDO = await ocean.registerAsset(new MetaData(), publisher) const metaData = new MetaData()
const ddo: DDO = await ocean.registerAsset(metaData, publisher)
const service: Service = ddo.findServiceByType("Access") const service: Service = ddo.findServiceByType("Access")
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
const serviceAgreementSignature: any = await ocean.signServiceAgreement(ddo.id, await consumer.requestTokens(metaData.base.price)
const signServiceAgreementResult: any = await ocean.signServiceAgreement(ddo.id,
service.serviceDefinitionId, consumer) service.serviceDefinitionId, consumer)
assert(serviceAgreementSignature) assert(signServiceAgreementResult)
assert(serviceAgreementSignature.serviceAgreementId) assert(signServiceAgreementResult.serviceAgreementId, "no serviceAgreementId")
assert(serviceAgreementSignature.serviceAgreementSignature) assert(signServiceAgreementResult.serviceAgreementSignature, "no serviceAgreementSignature")
assert(serviceAgreementSignature.serviceAgreementSignature.startsWith("0x")) assert(signServiceAgreementResult.serviceAgreementSignature.startsWith("0x"))
assert(signServiceAgreementResult.serviceAgreementSignature.length === 132)
}) })
}) })

View File

@ -1,16 +1,12 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider" import ConfigProvider from "../../src/ConfigProvider"
import DDOCondition from "../../src/ddo/Condition" import Condition from "../../src/ddo/Condition"
import DDO from "../../src/ddo/DDO" import DDO from "../../src/ddo/DDO"
import Event from "../../src/ddo/Event"
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 Service from "../../src/ddo/Service" import Service from "../../src/ddo/Service"
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"
import Condition from "../../src/ocean/ServiceAgreements/Condition"
import ServiceAgreement from "../../src/ocean/ServiceAgreements/ServiceAgreement" import ServiceAgreement from "../../src/ocean/ServiceAgreements/ServiceAgreement"
import ServiceAgreementTemplate from "../../src/ocean/ServiceAgreements/ServiceAgreementTemplate" import ServiceAgreementTemplate from "../../src/ocean/ServiceAgreements/ServiceAgreementTemplate"
import Access from "../../src/ocean/ServiceAgreements/Templates/Access" import Access from "../../src/ocean/ServiceAgreements/Templates/Access"
@ -44,70 +40,13 @@ describe("ServiceAgreement", () => {
const serviceAgreementTemplate: ServiceAgreementTemplate = const serviceAgreementTemplate: ServiceAgreementTemplate =
new ServiceAgreementTemplate(new Access()) new ServiceAgreementTemplate(new Access())
// get condition keys from template const conditions: Condition[] = await serviceAgreementTemplate.getConditions(metadata, assetId)
const conditions: Condition[] = await serviceAgreementTemplate.getConditions()
// create ddo conditions out of the keys
const ddoConditions: DDOCondition[] = conditions
.map((condition: Condition, index): DDOCondition => {
const events: Event[] = [
{
name: "PaymentReleased",
actorType: [
"consumer",
],
handlers: {
moduleName: "serviceAgreement",
functionName: "fulfillAgreement",
version: "0.1",
} as EventHandlers,
} as Event,
]
const mapParameterValueToName = (name) => {
switch (name) {
case "price":
return metadata.base.price
case "assetId":
return "0x" + assetId
case "documentKeyId":
return "0x" + assetId
}
return null
}
const parameters: Parameter[] = condition.parameters
.map((parameter: Parameter) => {
return {
name: parameter.name,
type: parameter.type,
value: mapParameterValueToName(parameter.name),
} as Parameter
})
return {
contractName: condition.methodReflection.contractName,
methodName: condition.methodReflection.methodName,
timeout: condition.timeout,
index,
conditionKey: condition.condtionKey,
parameters,
events,
dependencies: condition.dependencies,
dependencyTimeoutFlags: condition.dependencyTimeoutFlags,
isTerminalCondition: condition.isTerminalCondition,
} as DDOCondition
})
accessService = { accessService = {
type: "Access", type: "Access",
serviceDefinitionId: IdGenerator.generateId(), serviceDefinitionId: IdGenerator.generateId(),
templateId: serviceAgreementTemplate.getId(), templateId: serviceAgreementTemplate.getId(),
conditions: ddoConditions, conditions,
} as Service } as Service
metaDataService = { metaDataService = {
@ -121,7 +60,7 @@ describe("ServiceAgreement", () => {
const did: string = `did:op:${assetId}` const did: string = `did:op:${assetId}`
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.generatePrefixedId()
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
@ -132,6 +71,7 @@ describe("ServiceAgreement", () => {
assert(serviceAgreementSignature) assert(serviceAgreementSignature)
assert(serviceAgreementSignature.startsWith("0x")) assert(serviceAgreementSignature.startsWith("0x"))
assert(serviceAgreementSignature.length === 132)
}) })
}) })
@ -140,7 +80,7 @@ describe("ServiceAgreement", () => {
const did: string = `did:op:${assetId}` const did: string = `did:op:${assetId}`
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.generatePrefixedId()
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
@ -164,7 +104,7 @@ describe("ServiceAgreement", () => {
const did: string = `did:op:${assetId}` const did: string = `did:op:${assetId}`
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.generatePrefixedId()
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
@ -183,12 +123,12 @@ describe("ServiceAgreement", () => {
}) })
}) })
describe("#buyAsset()", () => { describe("#payAsset()", () => {
it("should lock the payment in that service agreement", async () => { it("should lock the payment in that service agreement", async () => {
const did: string = `did:op:${assetId}` const did: string = `did:op:${assetId}`
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.generatePrefixedId()
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
@ -206,7 +146,7 @@ describe("ServiceAgreement", () => {
// get funds // get funds
await consumerAccount.requestTokens(metaDataService.metadata.base.price) await consumerAccount.requestTokens(metaDataService.metadata.base.price)
const paid: boolean = await serviceAgreement.buyAsset(assetId, metaDataService.metadata.base.price, const paid: boolean = await serviceAgreement.payAsset(assetId, metaDataService.metadata.base.price,
consumerAccount) consumerAccount)
assert(paid) assert(paid)
}) })
@ -217,7 +157,7 @@ describe("ServiceAgreement", () => {
const did: string = `did:op:${assetId}` const did: string = `did:op:${assetId}`
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.generatePrefixedId()
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
@ -234,12 +174,12 @@ describe("ServiceAgreement", () => {
// get funds // get funds
await consumerAccount.requestTokens(metaDataService.metadata.base.price) await consumerAccount.requestTokens(metaDataService.metadata.base.price)
const paid: boolean = await serviceAgreement.buyAsset(assetId, metaDataService.metadata.base.price, const paid: boolean = await serviceAgreement.payAsset(assetId, metaDataService.metadata.base.price,
consumerAccount) consumerAccount)
assert(paid) assert(paid)
// todo: use document id // todo: use document id
const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, assetId) const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, assetId, publisherAccount)
assert(accessGranted) assert(accessGranted)
}) })
@ -247,7 +187,7 @@ describe("ServiceAgreement", () => {
const did: string = `did:op:${assetId}` const did: string = `did:op:${assetId}`
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.generatePrefixedId()
// @ts-ignore // @ts-ignore
WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo)) WebServiceConnectorProvider.setConnector(new WebServiceConnectorMock(ddo))
@ -262,7 +202,7 @@ describe("ServiceAgreement", () => {
assert(serviceAgreement) assert(serviceAgreement)
// todo: use document id // todo: use document id
const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, assetId) const accessGranted: boolean = await serviceAgreement.grantAccess(assetId, assetId, publisherAccount)
assert(!accessGranted) assert(!accessGranted)
}) })
}) })

View File

@ -1,5 +1,6 @@
import {assert} from "chai" import {assert} from "chai"
import ConfigProvider from "../../src/ConfigProvider" import ConfigProvider from "../../src/ConfigProvider"
import MetaData from "../../src/ddo/MetaData"
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"
@ -48,7 +49,7 @@ describe("ServiceAgreementTemplate", () => {
new ServiceAgreementTemplate(access) new ServiceAgreementTemplate(access)
assert(serviceAgreementTemplate) assert(serviceAgreementTemplate)
const conds = await serviceAgreementTemplate.getConditions() const conds = await serviceAgreementTemplate.getConditions(new MetaData(), IdGenerator.generateId())
assert(conds) assert(conds)
}) })
}) })

View File

@ -5,17 +5,12 @@ const { paths } = require('./webpack.parts.js')
module.exports = { module.exports = {
entry: paths.entry, entry: paths.entry,
mode: 'none', mode: 'none',
module: {
rules: [
{ test: /\.tsx?$/, loader: "ts-loader" }
]
},
optimization: { optimization: {
minimize: true, minimize: true,
noEmitOnErrors: true noEmitOnErrors: true
}, },
resolve: { resolve: {
extensions: ['.js','.ts'], extensions: ['.js'],
modules: ['node_modules'], modules: ['node_modules'],
}, },
} }

View File

@ -9,7 +9,7 @@ const production = require('./webpack.production.js')
const AddVendorsPlugin = require('./plugins/add-vendors-plugin') const AddVendorsPlugin = require('./plugins/add-vendors-plugin')
const paths = { const paths = {
entry: path.resolve(__dirname, './src/squid.ts'), entry: path.resolve(__dirname, './dist/node/squid.js'),
bundle: path.resolve(__dirname, 'dist/browser'), bundle: path.resolve(__dirname, 'dist/browser'),
} }