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

395 lines
14 KiB
TypeScript
Raw Normal View History

2019-01-22 14:18:58 +01:00
import deprecated from "deprecated-decorator"
2018-10-25 17:26:26 +02:00
import AquariusProvider from "../aquarius/AquariusProvider"
2018-11-05 10:01:58 +01:00
import SearchQuery from "../aquarius/query/SearchQuery"
2018-11-09 10:43:29 +01:00
import BrizoProvider from "../brizo/BrizoProvider"
2018-10-16 14:56:18 +02:00
import ConfigProvider from "../ConfigProvider"
2018-11-09 10:43:29 +01:00
import Authentication from "../ddo/Authentication"
import Condition from "../ddo/Condition"
2018-11-23 16:01:42 +01:00
import Contract from "../ddo/Contract"
2018-11-05 10:01:58 +01:00
import DDO from "../ddo/DDO"
2018-11-23 16:01:42 +01:00
import Event from "../ddo/Event"
2018-12-07 15:19:16 +01:00
import EventHandler from "../ddo/EventHandler"
import MetaData from "../ddo/MetaData"
2018-12-05 12:40:38 +01:00
import PublicKey from "../ddo/PublicKey"
2018-11-05 10:01:58 +01:00
import Service from "../ddo/Service"
2018-11-23 16:01:42 +01:00
import ContractEvent from "../keeper/Event"
2018-10-05 12:34:31 +02:00
import Keeper from "../keeper/Keeper"
2018-10-16 14:56:18 +02:00
import Web3Provider from "../keeper/Web3Provider"
2018-10-25 17:18:57 +02:00
import Config from "../models/Config"
import ValueType from "../models/ValueType"
2018-11-09 10:43:29 +01:00
import SecretStoreProvider from "../secretstore/SecretStoreProvider"
import Logger from "../utils/Logger"
2018-10-05 12:34:31 +02:00
import Account from "./Account"
2018-12-17 15:54:58 +01:00
import DID from "./DID"
2018-10-26 13:37:09 +02:00
import IdGenerator from "./IdGenerator"
import ServiceAgreement from "./ServiceAgreements/ServiceAgreement"
2018-11-05 14:56:14 +01:00
import ServiceAgreementTemplate from "./ServiceAgreements/ServiceAgreementTemplate"
import Access from "./ServiceAgreements/Templates/Access"
2018-10-05 12:34:31 +02:00
2018-11-23 16:01:42 +01:00
import EventListener from "../keeper/EventListener"
2019-01-09 16:17:23 +01:00
/**
* Main interface for Ocean Protocol.
*/
2018-10-05 12:34:31 +02:00
export default class Ocean {
2019-01-09 16:17:23 +01:00
/**
* Returns the instance of Ocean.
* @param {Config} config Ocean instance configuration.
* @return {Promise<Ocean>}
*/
public static async getInstance(config: Config): Promise<Ocean> {
2018-10-16 14:56:18 +02:00
if (!Ocean.instance) {
2018-10-26 10:40:46 +02:00
ConfigProvider.setConfig(config)
Ocean.instance = new Ocean()
Ocean.instance.keeper = await Keeper.getInstance()
2018-10-16 14:56:18 +02:00
}
return Ocean.instance
2018-10-05 12:34:31 +02:00
}
2019-01-09 16:17:23 +01:00
/**
* Ocean instance.
* @type {Ocean}
*/
private static instance: Ocean = null
2019-01-09 16:17:23 +01:00
/**
* Keeper instance.
* @type {Keeper}
*/
2018-10-17 10:12:40 +02:00
private keeper: Keeper
private constructor() {
2018-10-17 10:12:40 +02:00
}
2018-10-16 14:56:18 +02:00
2019-01-09 16:17:23 +01:00
/**
* Returns the list of accounts.
* @return {Promise<Account[]>}
*/
2018-10-16 14:56:18 +02:00
public async getAccounts(): Promise<Account[]> {
// retrieve eth accounts
const ethAccounts = await Web3Provider.getWeb3().eth.getAccounts()
2018-10-17 10:12:40 +02:00
return ethAccounts.map((address: string) => new Account(address))
2018-10-16 14:56:18 +02:00
}
2019-01-09 16:17:23 +01:00
/**
* Returns a DDO by DID.
* @deprecated Replace by {@link #resolveAssetDID}
2019-01-09 16:17:23 +01:00
* @param {string} did Decentralized ID.
* @return {Promise<DDO>}
*/
2019-01-22 14:18:58 +01:00
@deprecated("resolveAssetDID")
2018-12-17 15:54:58 +01:00
public async resolveDID(did: string): Promise<DDO> {
2019-01-22 14:18:58 +01:00
return await this.resolveAssetDID(did)
}
/**
* Returns a DDO by DID.
* @param {string} did Decentralized ID.
* @return {Promise<DDO>}
*/
public async resolveAssetDID(did: string): Promise<DDO> {
2018-12-17 15:54:58 +01:00
const d: DID = DID.parse(did)
return AquariusProvider.getAquarius().retrieveDDO(d)
2018-11-19 12:16:11 +01:00
}
2019-01-09 16:17:23 +01:00
/**
* Registers a new DDO.
* @param {MetaData} metadata DDO metadata.
* @param {Account} publisher Publicher account.
* @return {Promise<DDO>}
*/
public async registerAsset(metadata: MetaData, publisher: Account): Promise<DDO> {
const {didRegistry} = this.keeper
const aquarius = AquariusProvider.getAquarius()
const brizo = BrizoProvider.getBrizo()
2018-12-17 15:54:58 +01:00
const did: DID = DID.generate()
2018-11-23 12:40:18 +01:00
const accessServiceDefinitionId: string = "0"
const computeServiceDefintionId: string = "1"
const metadataServiceDefinitionId: string = "2"
2018-10-16 14:56:18 +02:00
metadata.base.contentUrls =
2018-12-17 15:54:58 +01:00
[await SecretStoreProvider.getSecretStore()
.encryptDocument(did.getId(), metadata.base.contentUrls)]
2018-11-07 15:05:16 +01:00
const template = new Access()
const serviceAgreementTemplate = new ServiceAgreementTemplate(template)
2018-11-05 10:01:58 +01:00
2018-12-17 15:54:58 +01:00
const conditions: Condition[] = await serviceAgreementTemplate.getConditions(metadata, did.getId())
const serviceEndpoint = aquarius.getServiceEndpoint(did)
2018-11-05 10:01:58 +01:00
// create ddo itself
const ddo: DDO = new DDO({
2018-11-09 10:43:29 +01:00
authentication: [{
type: "RsaSignatureAuthentication2018",
2018-12-17 15:54:58 +01:00
publicKey: did.getDid() + "#keys-1",
2018-11-09 10:43:29 +01:00
} as Authentication],
2018-12-17 15:54:58 +01:00
id: did.getDid(),
publicKey: [
{
2018-12-17 15:54:58 +01:00
id: did.getDid() + "#keys-1",
type: "Ed25519VerificationKey2018",
2018-12-17 15:54:58 +01:00
owner: did.getDid(),
publicKeyBase58: await publisher.getPublicKey(),
2018-12-05 12:40:38 +01:00
} as PublicKey,
],
2018-11-05 10:01:58 +01:00
service: [
{
type: template.templateName,
purchaseEndpoint: brizo.getPurchaseEndpoint(),
serviceEndpoint: brizo.getConsumeEndpoint(),
2018-11-05 10:01:58 +01:00
// the id of the service agreement?
2018-11-23 12:40:18 +01:00
serviceDefinitionId: accessServiceDefinitionId,
2018-11-05 10:01:58 +01:00
// the id of the service agreement template
2018-11-05 14:56:14 +01:00
templateId: serviceAgreementTemplate.getId(),
2018-11-23 16:01:42 +01:00
serviceAgreementContract: {
contractName: "ServiceAgreement",
fulfillmentOperator: template.fulfillmentOperator,
events: [
{
name: "ExecuteAgreement",
2018-12-07 15:19:16 +01:00
actorType: "consumer",
handler: {
2018-11-23 16:01:42 +01:00
moduleName: "payment",
functionName: "lockPayment",
version: "0.1",
2018-12-07 15:19:16 +01:00
} as EventHandler,
2018-11-23 16:01:42 +01:00
} as Event,
],
} as Contract,
conditions,
2018-11-05 10:01:58 +01:00
} as Service,
{
type: "Compute",
serviceEndpoint: brizo.getComputeEndpoint(publisher.getId(),
2018-11-23 12:40:18 +01:00
computeServiceDefintionId, "xxx", "xxx"),
serviceDefinitionId: computeServiceDefintionId,
} as Service,
{
type: "Metadata",
serviceEndpoint,
2018-11-23 12:40:18 +01:00
serviceDefinitionId: metadataServiceDefinitionId,
metadata,
} as Service,
2018-11-05 10:01:58 +01:00
],
})
const storedDdo = await aquarius.storeDDO(ddo)
2018-10-05 12:34:31 +02:00
2018-11-23 14:28:41 +01:00
// Logger.log(JSON.stringify(storedDdo, null, 2))
2018-11-21 14:59:22 +01:00
await didRegistry.registerAttribute(
2018-12-17 15:54:58 +01:00
did.getId(),
ValueType.URL,
2018-11-21 14:59:22 +01:00
"Metadata",
serviceEndpoint,
publisher.getId())
return storedDdo
}
/**
* Signs a service agreement by DID.
* @deprecated Replace by {@link #purchaseAssetService}
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {Account} consumer Consumer account.
* @return {Promise<any>}
2019-01-22 14:18:58 +01:00
*
*/
2019-01-22 14:18:58 +01:00
@deprecated("purchaseAssetService")
public async signServiceAgreement(
did: string,
serviceDefinitionId: string,
consumer: Account,
): Promise<any> {
2019-01-22 14:18:58 +01:00
return await this.purchaseAssetService(did, serviceDefinitionId, consumer)
}
2019-01-09 16:17:23 +01:00
/**
* Signs a service agreement by DID.
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {Account} consumer Consumer account.
* @return {Promise<any>}
*/
public async purchaseAssetService(
did: string,
serviceDefinitionId: string,
consumer: Account,
): Promise<any> {
2018-11-12 08:33:19 +01:00
2018-12-17 15:54:58 +01:00
const d: DID = DID.parse(did as string)
const ddo = await AquariusProvider.getAquarius().retrieveDDO(d)
const serviceAgreementId: string = IdGenerator.generateId()
2018-11-12 08:33:19 +01:00
try {
2018-12-17 15:54:58 +01:00
const serviceAgreementSignature: string = await ServiceAgreement.signServiceAgreement(
2018-11-14 15:44:25 +01:00
ddo, serviceDefinitionId, serviceAgreementId, consumer)
2018-11-23 16:01:42 +01:00
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}`)
}
2018-11-23 16:09:31 +01:00
const event: ContractEvent = EventListener.subscribe(
accessService.serviceAgreementContract.contractName,
accessService.serviceAgreementContract.events[0].name, {
serviceAgreementId: `0x${serviceAgreementId}`,
2018-11-23 16:09:31 +01:00
})
2018-12-07 17:20:20 +01:00
event.listenOnce(async (data) => {
const sa: ServiceAgreement = new ServiceAgreement(data.returnValues.serviceAgreementId)
await sa.payAsset(
2018-12-17 15:54:58 +01:00
d.getId(),
2018-12-07 17:20:20 +01:00
metadataService.metadata.base.price,
consumer,
)
Logger.log("Completed asset payment, now access should be granted.")
})
2018-11-23 16:01:42 +01:00
2018-11-14 15:44:25 +01:00
return {
serviceAgreementId,
serviceAgreementSignature,
}
2018-11-12 08:33:19 +01:00
} catch (err) {
Logger.error("Signing ServiceAgreement failed!", err)
}
2018-11-12 08:33:19 +01:00
}
2019-01-09 16:17:23 +01:00
/**
* Creates a new service agreement.
* @private
2019-01-09 16:17:23 +01:00
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {string} serviceAgreementId Service agreement ID.
* @param {string} serviceAgreementSignature Service agreement signature.
* @param {Function} cb Callback executen when the access is granted.
* @param {Account} consumer Consumer account.
*/
public async initializeServiceAgreement(
did: string,
serviceDefinitionId: string,
serviceAgreementId: string,
serviceAgreementSignature: string,
cb: (files: string[]) => void,
consumer: Account,
) {
2018-12-17 15:54:58 +01:00
const d: DID = DID.parse(did)
const ddo = await AquariusProvider.getAquarius().retrieveDDO(d)
const accessService: Service = ddo.findServiceByType("Access")
const metadataService: Service = ddo.findServiceByType("Metadata")
const accessEvent: ContractEvent = EventListener.subscribe(
accessService.conditions[1].contractName,
accessService.conditions[1].events[1].name, {})
const files = new Promise(resolve => {
accessEvent.listenOnce(async () => {
Logger.log("Awesome; got a AccessGranted Event. Let's download the asset files.")
const contentUrls = await SecretStoreProvider
.getSecretStore()
.decryptDocument(d.getId(), metadataService.metadata.base.contentUrls[0])
const serviceUrl: string = accessService.serviceEndpoint
Logger.log("Consuming asset files using service url: ", serviceUrl)
const files = []
for (const cUrl of contentUrls) {
let url: string = serviceUrl + `?url=${cUrl}`
url = url + `&serviceAgreementId=${serviceAgreementId}`
url = url + `&consumerAddress=${consumer.getId()}`
files.push(url)
}
cb(files)
resolve(files)
})
})
await BrizoProvider
2018-11-21 14:59:22 +01:00
.getBrizo()
.initializeServiceAgreement(
did,
serviceAgreementId,
serviceDefinitionId,
serviceAgreementSignature,
2018-11-26 15:24:59 +01:00
consumer.getId())
await files
2018-11-19 12:16:11 +01:00
}
2019-01-09 16:17:23 +01:00
/**
* Executes a service agreement.
* @param {string} did Decentralized ID.
* @param {string} serviceDefinitionId Service definition ID.
* @param {string} serviceAgreementId Service agreement ID.
* @param {string} serviceAgreementSignature Service agreement signature.
* @param {Account} consumer Consumer account.
* @param {Account} publisher Publisher account.
* @return {Promise<ServiceAgreement>}
*/
public async executeServiceAgreement(
did: string,
serviceDefinitionId: string,
serviceAgreementId: string,
serviceAgreementSignature: string,
consumer: Account,
publisher: Account,
): Promise<ServiceAgreement> {
2018-12-17 15:54:58 +01:00
const d: DID = DID.parse(did)
const ddo = await AquariusProvider.getAquarius().retrieveDDO(d)
2018-11-21 14:59:22 +01:00
const serviceAgreement: ServiceAgreement = await ServiceAgreement
.executeServiceAgreement(
2018-12-17 15:54:58 +01:00
d,
2018-11-21 14:59:22 +01:00
ddo,
serviceDefinitionId,
serviceAgreementId,
serviceAgreementSignature,
consumer,
publisher)
2018-11-21 14:59:22 +01:00
return serviceAgreement
2018-10-05 12:34:31 +02:00
}
2018-10-26 10:40:46 +02:00
2019-01-09 16:17:23 +01:00
/**
* Search over the assets using a query.
* @param {SearchQuery} query Query to filter the assets.
* @return {Promise<DDO[]>}
*/
2018-11-12 08:33:19 +01:00
public async searchAssets(query: SearchQuery): Promise<DDO[]> {
return AquariusProvider.getAquarius().queryMetadata(query)
2018-10-26 10:40:46 +02:00
}
2018-11-05 14:58:58 +01:00
2019-01-09 16:17:23 +01:00
/**
* Search over the assets using a keyword.
* @param {SearchQuery} text Text to filter the assets.
* @return {Promise<DDO[]>}
*/
2018-11-12 08:33:19 +01:00
public async searchAssetsByText(text: string): Promise<DDO[]> {
return AquariusProvider.getAquarius().queryMetadataByText({
text,
2018-11-12 08:33:19 +01:00
page: 0,
offset: 100,
query: {
value: 1,
},
sort: {
value: 1,
},
} as SearchQuery)
2018-11-05 14:58:58 +01:00
}
2018-10-05 12:34:31 +02:00
}