1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00
This commit is contained in:
alexcos20 2020-05-28 00:19:59 -07:00
parent 6d98da883b
commit 25811f93c0
16 changed files with 418 additions and 705 deletions

View File

@ -33,8 +33,6 @@
},
"dependencies": {
"@ethereum-navigator/navigator": "^0.5.0",
"@oceanprotocol/keeper-contracts": "^0.13.2",
"@oceanprotocol/secret-store-client": "^0.0.15",
"bignumber.js": "^9.0.0",
"deprecated-decorator": "^0.1.6",
"node-fetch": "^2.6.0",

View File

@ -23,7 +23,7 @@ export function generateIntantiableConfigFromConfig(
: (config.verbose as LogLevel)
return {
config,
web3: Web3Provider.getWeb3(config),
web3: config.web3Provider,
logger: new Logger(logLevel)
}
}

View File

@ -403,6 +403,10 @@ export class Aquarius {
return `${this.url}/api/v1/aquarius/assets/ddo/did:op:${did.getId()}`
}
public getURI() {
return `${this.url}`
}
private transformResult(
{ results, page, total_pages: totalPages, total_results: totalResults }: any = {
result: [],

View File

@ -1,10 +1,9 @@
import { File, MetaDataAlgorithm } from '../ddo/MetaData'
import Account from '../ocean/Account'
import { noZeroX } from '../utils'
import { noZeroX, noDidPrefixed } from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { DDO } from '../ddo/DDO'
import { ServiceType } from '../ddo/Service'
import { ComputeJob, Output } from '../ocean/Compute'
const apiPath = '/api/v1/brizo/services'
@ -26,6 +25,10 @@ export class Brizo extends Instantiable {
return (await this.ocean.utils.fetch.get(this.url)).json()
}
public getURI() {
return `${this.url}`
}
public getPurchaseEndpoint() {
return `${this.url}${apiPath}/access/initialize`
}
@ -42,187 +45,41 @@ export class Brizo extends Instantiable {
return `${this.url}${apiPath}/compute`
}
public async getEndpointFromAgreement(
type: ServiceType,
agreementId: string
): Promise<string> {
const { assets, keeper } = this.ocean
const { did } = await keeper.agreementStoreManager.getAgreement(agreementId)
const ddo: DDO = await assets.resolve(did)
const { serviceEndpoint } = ddo.findServiceByType(type)
return serviceEndpoint
}
public async initializeServiceAgreement(
did: string,
serviceAgreementId: string,
serviceIndex: number,
signature: string,
consumerAddress: string
): Promise<any> {
const args = {
did,
serviceAgreementId,
serviceIndex,
signature,
consumerAddress
}
try {
return await this.ocean.utils.fetch.post(
this.getPurchaseEndpoint(),
decodeURI(JSON.stringify(args))
)
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
}
}
public async consumeService(
agreementId: string,
serviceEndpoint: string,
account: Account,
files: File[],
destination: string,
index: number = -1
): Promise<string> {
const signature = await this.createSignature(account, agreementId)
const filesPromises = files
.filter((_, i) => index === -1 || i === index)
.map(async ({ index: i }) => {
let consumeUrl = serviceEndpoint
consumeUrl += `?index=${i}`
consumeUrl += `&serviceAgreementId=${noZeroX(agreementId)}`
consumeUrl += `&consumerAddress=${account.getId()}`
consumeUrl += `&signature=${signature}`
try {
await this.ocean.utils.fetch.downloadFile(consumeUrl, destination, i)
} catch (e) {
this.logger.error('Error consuming assets')
this.logger.error(e)
throw e
}
})
await Promise.all(filesPromises)
return destination
}
public async compute(
method: string,
serviceAgreementId: string,
consumerAccount: Account,
algorithmDid?: string,
algorithmMeta?: MetaDataAlgorithm,
jobId?: string,
output?: Output
): Promise<ComputeJob | ComputeJob[]> {
const address = consumerAccount.getId()
let signatureMessage = address
signatureMessage += jobId || ''
signatureMessage += (serviceAgreementId && `${noZeroX(serviceAgreementId)}`) || ''
const signature = await this.createHashSignature(
consumerAccount,
signatureMessage
)
const serviceEndpoint = serviceAgreementId
? await this.getEndpointFromAgreement('compute', serviceAgreementId)
: this.getComputeEndpoint()
if (!serviceEndpoint) {
throw new Error(
'Computing on asset failed, service definition is missing the `serviceEndpoint`.'
)
}
// construct Brizo URL
let url = serviceEndpoint
url += `?signature=${signature}`
url += `&consumerAddress=${address}`
url += `&serviceAgreementId=${noZeroX(serviceAgreementId)}`
url += (algorithmDid && `&algorithmDid=${algorithmDid}`) || ''
url +=
(algorithmMeta &&
`&algorithmMeta=${encodeURIComponent(JSON.stringify(algorithmMeta))}`) ||
''
url += (output && `&output=${JSON.stringify(output)}`) || ''
url += (jobId && `&jobId=${jobId}`) || ''
// switch fetch method
let fetch
switch (method) {
case 'post':
fetch = this.ocean.utils.fetch.post(url, '')
break
case 'put':
fetch = this.ocean.utils.fetch.put(url, '')
break
case 'delete':
fetch = this.ocean.utils.fetch.delete(url)
break
default:
fetch = this.ocean.utils.fetch.get(url)
break
}
const result = await fetch
.then((response: any) => {
if (response.ok) {
return response.json()
}
this.logger.error(
'Compute job failed:',
response.status,
response.statusText
)
return null
})
.catch((error: Error) => {
this.logger.error('Error with compute job')
this.logger.error(error.message)
throw error
})
return result
}
public async createSignature(account: Account, agreementId: string): Promise<string> {
const signature =
(await account.getToken()) ||
(await this.ocean.utils.signature.signText(
noZeroX(agreementId),
account.getId()
))
const signature = await this.ocean.utils.signature.signText(
noZeroX(agreementId),
account.getId()
)
return signature
}
public async createHashSignature(account: Account, message: string): Promise<string> {
const signature =
(await account.getToken()) ||
(await this.ocean.utils.signature.signWithHash(message, account.getId()))
const signature = await this.ocean.utils.signature.signWithHash(
message,
account.getId()
)
return signature
}
public async encrypt(
did: string,
signature: string,
document: any,
publisher: string
account: Account,
dtAddress: string
): Promise<string> {
const signature = this.ocean.utils.signature.signWithHash(
did,
account.getId(),
account.getPassword()
)
const args = {
documentId: did,
did,
signature,
document: JSON.stringify(document),
publisherAddress: publisher
publisherAddress: account.getId()
}
try {

View File

@ -38,6 +38,7 @@ export class DataTokens {
*/
public async create(metaDataStoreURI: string, account: Account): Promise<string> {
// TO DO
return ''
}
/**
@ -55,6 +56,7 @@ export class DataTokens {
account: Account
): Promise<string> {
// TO DO
return ''
}
/**
@ -74,6 +76,7 @@ export class DataTokens {
account: Account
): Promise<string> {
// TO DO
return ''
}
/**
@ -91,6 +94,7 @@ export class DataTokens {
toAddress?: string
): Promise<string> {
// TO DO
return ''
}
/**
@ -108,6 +112,7 @@ export class DataTokens {
account: Account
): Promise<string> {
// TO DO
return ''
}
/**
@ -125,15 +130,17 @@ export class DataTokens {
account: Account
): Promise<string> {
// TO DO
return ''
}
/**
* Get Account Balance for datatoken
* @param {String} dataTokenAddress
* @param {Account} account
* @return {Promise<string>} transactionId
* @return {Promise<number>} balance
*/
public async balance(dataTokenAddress: string, account: Account): Promise<number> {
// TO DO
return 0
}
}

View File

@ -1 +1 @@
export const OceanDataTokenABI = { }
export const OceanDataTokenABI = {}

View File

@ -1,4 +1,3 @@
import Web3Provider from '../keeper/Web3Provider'
import { Ocean } from '../ocean/Ocean'
import { Authentication } from './Authentication'
import { Proof } from './Proof'
@ -93,9 +92,10 @@ export class DDO {
/**
* Generate the checksum using the current content.
* @param {Any} web3Provider
* @return {string[]} DDO checksum.
*/
public getChecksum(): string {
public getChecksum(web3Provider: any): string {
const { attributes } = this.findServiceByType('metadata')
const { files, name, author, license } = attributes.main
@ -107,7 +107,8 @@ export class DDO {
this.id
]
return Web3Provider.getWeb3()
return web3Provider
.getWeb3()
.utils.sha3(values.join(''))
.replace(/^0x([a-f0-9]{64})(:!.+)?$/i, '0x$1')
}
@ -124,7 +125,7 @@ export class DDO {
publicKey: string,
password?: string
): Promise<Proof> {
const checksum = this.getChecksum()
const checksum = this.getChecksum(ocean.web3Provider)
const signature = await ocean.utils.signature.signText(
checksum,

View File

@ -12,14 +12,12 @@ import * as utils from './utils'
export * from './ddo/DDO'
export * from './ddo/MetaData'
export { CreateProgressStep } from './ocean/Assets'
export { ComputeJob, ComputeJobStatus } from './ocean/Compute'
export { OrderProgressStep } from './ocean/utils/ServiceUtils'
export { CreateProgressStep, OrderProgressStep } from './ocean/Assets'
export {
OceanPlatformTechStatus,
OceanPlatformTech,
OceanPlatformKeeperTech,
OceanPlatformVersions
} from './ocean/OceanVersions'
} from './ocean/Versions'
export { Ocean, Account, Config, DID, Logger, Aquarius, DataTokens, utils }

View File

@ -1,12 +1,10 @@
import BigNumber from 'bignumber.js'
import Balance from '../models/Balance'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/**
* Account information.
*/
export default class Account extends Instantiable {
export default class Accounts extends Instantiable {
private password?: string
private token?: string
@ -42,57 +40,57 @@ export default class Account extends Instantiable {
return this.password
}
//TODO - Check with Samer if authentificate is still needed or we can use sign
// TODO - Check with Samer if authentificate is still needed or we can use sign
/**
* Set account token.
* @param {string} token Token for account.
*/
public setToken(token: string): void {
this.token = token
}
*/
/**
* Returns account token.
* @return {Promise<string>} Account token.
*/
public async getToken(): Promise<string> {
return this.token || this.ocean.auth.restore(this)
}
*/
/**
* Returns if account token is stored.
* @return {Promise<boolean>} Is stored.
*/
public isTokenStored(): Promise<boolean> {
return this.ocean.auth.isStored(this)
}
*/
/**
* Authenticate the account.
*/
public authenticate() {
return this.ocean.auth.store(this)
}
*/
/**
* Balance of Ocean Token.
* Balance of Any Token.
* @return {Promise<number>}
*/
public async getTokenBalance(TokenAdress:string): Promise<number> {
//TO DO
public async getTokenBalance(TokenAdress: string): Promise<number> {
// TO DO
return 0
}
/**
* Symbol of a Token
* @return {Promise<string>}
*/
public async getTokenSymbol(TokenAdress:string): Promise<number> {
//TO DO
public async getTokenSymbol(TokenAdress: string): Promise<string> {
// TO DO
return ''
}
/**
@ -100,25 +98,13 @@ export default class Account extends Instantiable {
* @return {Promise<number>}
*/
public async getEtherBalance(): Promise<number> {
//TO DO
/*return this.web3.eth
// TO DO
/* return this.web3.eth
.getBalance(this.id, 'latest')
.then((balance: string): number => {
return new BigNumber(balance).toNumber()
})
}
/**
* Balances of Ether and Ocean Token.
* @return {Promise<Balance>}
*/
public async getBalance(TokenAddress:string): Promise<Balance> {
let symbol = await getTokenSymbol(TokenAddress)
let balance = []
balance['eth'] = await this.getEtherBalance()
balance[symbol] = await this.getTokenBalance(TokenAdress)
return(balance)
*/
return 0
}
}

51
src/ocean/Accounts.ts Normal file
View File

@ -0,0 +1,51 @@
import Account from './Account'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/**
* Account submodule of Ocean Protocol.
*/
export class Accounts extends Instantiable {
/**
* Returns the instance of OceanAccounts.
* @return {Promise<OceanAccounts>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Accounts> {
const instance = new Accounts()
instance.setInstanceConfig(config)
return instance
}
/**
* Returns the list of accounts.
* @return {Promise<Account[]>}
*/
public async list(): Promise<Account[]> {
// retrieve eth accounts
const ethAccounts: string[] = await this.web3.eth.getAccounts()
const accountPromises = ethAccounts.map(
address => new Account(address, this.instanceConfig)
)
return Promise.all(accountPromises)
}
/**
* Return account balance.
* @param {String} TokenAddress .
* @param {Account} account Account instance.
* @return {Promise<Balance>} Ether and Ocean Token balance.
*/
public balance(TokenAddress: string, account: Account): Promise<number> {
return account.getTokenBalance(TokenAddress)
}
/**
* Return account balance in ETH
* @param {Account} account Account instance.
* @return {Promise<Balance>} Ether and Ocean Token balance.
*/
public ETHbalance(account: Account): Promise<number> {
return account.getEtherBalance()
}
}

View File

@ -5,21 +5,29 @@ import { MetaData, EditableMetaData } from '../ddo/MetaData'
import { Service, ServiceAccess, ServiceComputePrivacy } from '../ddo/Service'
import Account from './Account'
import DID from './DID'
import { fillConditionsWithDDO, SubscribablePromise, didZeroX } from '../utils'
import { SubscribablePromise, didZeroX } from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { OrderProgressStep } from './utils/ServiceUtils'
import { DataTokens } from '../lib'
export enum CreateProgressStep {
CreatingDataToken,
DataTokenCreated,
EncryptingFiles,
FilesEncrypted,
GeneratingProof,
ProofGenerated,
RegisteringDid,
DidRegistred,
StoringDdo,
DdoStored
}
export enum OrderProgressStep {
CreatingAgreement,
AgreementInitialized,
LockingPayment,
LockedPayment
}
/**
* Assets submodule of Ocean Protocol.
*/
@ -36,19 +44,19 @@ export class Assets extends Instantiable {
}
/**
* Returns a DDO by DID.
* @param {string} did Decentralized ID.
* @return {Promise<DDO>}
* Creates a simple asset and a datatoken
* @param {Account} publisher Publisher account.
* @return {Promise<String>}
*/
public async resolve(did: string): Promise<DDO> {
const {
serviceEndpoint
} = await this.ocean.keeper.didRegistry.getAttributesByDid(did)
return this.ocean.aquarius.retrieveDDOByUrl(serviceEndpoint)
public createSimpleAsset(publisher: Account): Promise<string> {
const publisherURI = this.ocean.brizo.getURI()
const jsonBlob = { t: 0, url: publisherURI }
const { datatokens } = this.ocean
return datatokens.create(JSON.stringify(jsonBlob), publisher)
}
/**
* Creates a new DDO.
* Creates a new DDO and publishes it
* @param {MetaData} metadata DDO metadata.
* @param {Account} publisher Publisher account.
* @param {list} services list of Service description documents
@ -57,43 +65,43 @@ export class Assets extends Instantiable {
public create(
metadata: MetaData,
publisher: Account,
services: Service[] = []
services: Service[] = [],
dtAddress?: string
): SubscribablePromise<CreateProgressStep, DDO> {
this.logger.log('Creating asset')
return new SubscribablePromise(async observer => {
const { secretStoreUri } = this.config
const { didRegistry, templates } = this.ocean.keeper
if (services.length === 0) {
this.logger.log('You have no services. Are you sure about this?')
}
if (!dtAddress) {
this.logger.log('Creating datatoken')
observer.next(CreateProgressStep.CreatingDataToken)
const metadataStoreURI = this.ocean.aquarius.getURI()
const jsonBlob = { t: 1, url: metadataStoreURI }
const { datatokens } = this.ocean
dtAddress = await datatokens.create(JSON.stringify(jsonBlob), publisher)
this.logger.log('DataToken creted')
observer.next(CreateProgressStep.DataTokenCreated)
}
const did: DID = DID.generate()
this.logger.log('Encrypting files')
observer.next(CreateProgressStep.EncryptingFiles)
const encryptedFiles = await this.ocean.secretStore.encrypt(
const encryptedFiles = await this.ocean.brizo.encrypt(
did.getId(),
metadata.main.files,
publisher
publisher,
dtAddress
)
this.logger.log('Files encrypted')
observer.next(CreateProgressStep.FilesEncrypted)
// make sure that access service is defined if services is empty
if (services.length === 0) {
const accessService = await this.createAccessServiceAttributes(
publisher,
metadata.main.price,
metadata.main.datePublished
)
services.push(accessService)
}
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
const serviceEndpoint = this.ocean.aquarius.getServiceEndpoint(did)
let indexCount = 0
// create ddo itself
const ddo: DDO = new DDO({
id: did.getDid(),
dtAddress: dtAddress,
authentication: [
{
type: 'RsaSignatureAuthentication2018',
@ -108,15 +116,8 @@ export class Assets extends Instantiable {
}
],
service: [
{
type: 'authorization',
service: 'SecretStore',
serviceEndpoint: secretStoreUri,
attributes: { main: {} }
},
{
type: 'metadata',
serviceEndpoint,
attributes: {
// Default values
curation: {
@ -153,38 +154,12 @@ export class Assets extends Instantiable {
})) as Service[]
})
// Overwrite initial service agreement conditions
serviceAgreementTemplate.conditions = fillConditionsWithDDO(
await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplateConditions(),
ddo
)
for (const service of services) {
if (service.type === 'compute') {
service.attributes.serviceAgreementTemplate.conditions = fillConditionsWithDDO(
await templates.escrowComputeExecutionTemplate.getServiceAgreementTemplateConditions(),
ddo
)
}
}
this.logger.log('Generating proof')
observer.next(CreateProgressStep.GeneratingProof)
await ddo.addProof(this.ocean, publisher.getId(), publisher.getPassword())
this.logger.log('Proof generated')
observer.next(CreateProgressStep.ProofGenerated)
this.logger.log('Registering DID')
observer.next(CreateProgressStep.RegisteringDid)
await didRegistry.registerAttribute(
did.getId(),
ddo.getChecksum(),
[this.config.brizoAddress],
serviceEndpoint,
publisher.getId()
)
this.logger.log('DID registred')
observer.next(CreateProgressStep.DidRegistred)
this.logger.log('Storing DDO')
observer.next(CreateProgressStep.StoringDdo)
const storedDdo = await this.ocean.aquarius.storeDDO(ddo)
@ -194,407 +169,4 @@ export class Assets extends Instantiable {
return storedDdo
})
}
public async consume(
agreementId: string,
did: string,
consumerAccount: Account,
resultPath: string,
index?: number,
useSecretStore?: boolean
): Promise<string>
/* eslint-disable no-dupe-class-members */
public async consume(
agreementId: string,
did: string,
consumerAccount: Account,
resultPath?: undefined | null,
index?: number,
useSecretStore?: boolean
): Promise<true>
public async consume(
agreementId: string,
did: string,
consumerAccount: Account,
resultPath?: string,
index: number = -1,
useSecretStore?: boolean
): Promise<string | true> {
const ddo = await this.resolve(did)
const { attributes } = ddo.findServiceByType('metadata')
const accessService = ddo.findServiceByType('access')
const { files } = attributes.main
const { serviceEndpoint } = accessService
if (!serviceEndpoint) {
throw new Error(
'Consume asset failed, service definition is missing the `serviceEndpoint`.'
)
}
this.logger.log('Consuming files')
resultPath = resultPath
? `${resultPath}/datafile.${ddo.shortId()}.${accessService.index}/`
: undefined
if (!useSecretStore) {
await this.ocean.brizo.consumeService(
agreementId,
serviceEndpoint,
consumerAccount,
files,
resultPath,
index
)
} else {
const files = await this.ocean.secretStore.decrypt(
did,
ddo.findServiceByType('metadata').attributes.encryptedFiles,
consumerAccount,
ddo.findServiceByType('authorization').serviceEndpoint
)
const downloads = files
.filter(({ index: i }) => index === -1 || index === i)
.map(({ url, index: i }) =>
this.ocean.utils.fetch.downloadFile(url, resultPath, i)
)
await Promise.all(downloads)
}
this.logger.log('Files consumed')
if (resultPath) {
return resultPath
}
return true
}
/* eslint-enable no-dupe-class-members */
/**
* Start the purchase/order of an asset's service. Starts by signing the service agreement
* then sends the request to the publisher via the service endpoint (Brizo http service).
* @param {string} did Decentralized ID.
* @param {Account} consumerAccount Consumer account.
* @param {string} provider ethereum address of service provider (optional)
* @return {Promise<string>} Returns Agreement ID
*/
public order(
did: string,
consumerAccount: Account,
provider?: string
): SubscribablePromise<OrderProgressStep, string> {
return new SubscribablePromise(async observer => {
const { keeper, utils } = this.ocean
const ddo: DDO = await this.resolve(did)
const condition = keeper.conditions.accessSecretStoreCondition
const agreementId = await utils.services.order(
'access',
condition,
observer,
consumerAccount,
ddo,
provider
)
return agreementId
})
}
/**
* Returns the owner of an asset.
* @param {string} did Decentralized ID.
* @return {Promise<string>} Returns Account ID
*/
public async owner(did: string): Promise<string> {
const owner = await this.ocean.keeper.didRegistry.getDIDOwner(did)
return owner
}
/**
* Returns the creator of a asset.
* @param {string} did Decentralized ID.
* @return {Promise<string>} Returns eth address
*/
public async creator(did: string): Promise<string> {
const ddo = await this.resolve(did)
const checksum = ddo.getChecksum()
const { creator, signatureValue } = ddo.proof
const signer = await this.ocean.utils.signature.verifyText(
checksum,
signatureValue
)
if (signer.toLowerCase() !== creator.toLowerCase()) {
this.logger.warn(
`Owner of ${ddo.id} doesn't match. Expected ${creator} instead of ${signer}.`
)
}
return creator
}
/**
* Returns the assets of a owner.
* @param {string} owner Owner address.
* @return {Promise<string[]>} List of DIDs.
*/
public async ownerAssets(owner: string): Promise<string[]> {
return this.ocean.keeper.didRegistry.getAttributesByOwner(owner)
}
/**
* Transfer ownership of an asset.
* @param {string} did Asset DID.
* @param {string} newOwner Ethereum address of the new owner of the DID.
* @param {Account} account Ethereum account of original/old owner to sign and prove the ownership.
* @return {Promise<TransactionReceipt>} Returns Web3 transaction receipt.
*/
public async transferOwnership(
did: string,
newOwner: string,
account: Account
): Promise<TransactionReceipt> {
const oldOwner = await this.ocean.assets.owner(did)
const oldDdo = await this.ocean.aquarius.retrieveDDO(did)
// update owner on-chain
const txReceipt = this.ocean.keeper.didRegistry.transferDIDOwnership(
did,
newOwner,
oldOwner
)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
if (signature != null)
await this.ocean.aquarius.transferOwnership(
did,
newOwner,
oldDdo.updated,
signature
)
return txReceipt
}
/**
* Edit Metadata for a DDO.
* @param {did} string DID.
* @param {newMetadata} EditableMetaData Metadata fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async editMetadata(
did: string,
newMetadata: EditableMetaData,
account: Account
): Promise<string> {
const oldDdo = await this.ocean.aquarius.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.aquarius.editMetadata(
did,
newMetadata,
oldDdo.updated,
signature
)
return result
}
/**
* Update Compute Privacy
* @param {did} string DID.
* @param {number} serviceIndex Index of the compute service in the DDO
* @param {ServiceComputePrivacy} computePrivacy ComputePrivacy fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async updateComputePrivacy(
did: string,
serviceIndex: number,
computePrivacy: ServiceComputePrivacy,
account: Account
): Promise<string> {
const oldDdo = await this.ocean.aquarius.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.aquarius.updateComputePrivacy(
did,
serviceIndex,
computePrivacy.allowRawAlgorithm,
computePrivacy.allowNetworkAccess,
computePrivacy.trustedAlgorithms,
oldDdo.updated,
signature
)
return result
}
/**
* Retire a DDO (Delete)
* @param {did} string DID.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async retire(did: string, account: Account): Promise<string> {
const oldDdo = await this.ocean.aquarius.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.aquarius.retire(did, oldDdo.updated, signature)
return result
}
/**
* Returns the assets of a consumer.
* @param {string} consumer Consumer address.
* @return {Promise<string[]>} List of DIDs.
*/
public async consumerAssets(consumer: string): Promise<string[]> {
return (
await this.ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
consumer
)
).map(({ did }) => did)
}
/**
* Search over the assets using a query.
* @param {SearchQuery} query Query to filter the assets.
* @return {Promise<DDO[]>}
*/
public async query(query: SearchQuery) {
return this.ocean.aquarius.queryMetadata(query)
}
/**
* Search over the assets using a keyword.
* @param {SearchQuery} text Text to filter the assets.
* @return {Promise<DDO[]>}
*/
public async search(text: string) {
return this.ocean.aquarius.queryMetadataByText({
text,
page: 1,
offset: 100,
query: {
value: 1
},
sort: {
value: 1
}
} as SearchQuery)
}
public async createAccessServiceAttributes(
consumerAccount: Account,
price: string,
datePublished: string,
timeout: number = 0
): Promise<ServiceAccess> {
const { templates } = this.ocean.keeper
const serviceAgreementTemplate = await templates.escrowAccessSecretStoreTemplate.getServiceAgreementTemplate()
return {
type: 'access',
index: 2,
serviceEndpoint: this.ocean.brizo.getConsumeEndpoint(),
templateId: templates.escrowAccessSecretStoreTemplate.getId(),
attributes: {
main: {
creator: consumerAccount.getId(),
datePublished,
price,
timeout: timeout,
name: 'dataAssetAccessServiceAgreement'
},
serviceAgreementTemplate
}
}
}
/**
* Get FreeWhiteList for a DID
* @param {string} did Asset DID.
* @return {Promise<string[]>} List of addresses.
*/
public async getFreeWhiteList(did: string): Promise<string[]> {
const events = await this.ocean.keeper.didRegistry.getPastEvents(
'DIDPermissionGranted',
{
_did: didZeroX(did)
}
)
const list = events.map(({ returnValues }) => returnValues._grantee)
const filteredList = []
for (let index = 0; index < list.length; index++) {
const address = list[index]
const hasPermission = await this.ocean.keeper.didRegistry.getPermission(
did,
address
)
if (hasPermission) filteredList.push(address)
}
return filteredList
}
/**
* Add consumer to FreeWhiteList for a DID
* @param {string} did Asset DID.
* @param {string} consumer Ethereum address to add to the list.
* @param {Account} account Ethereum account of DID owner
* @return None
*/
public async addConsumerToFreeWhiteList(
did: string,
consumer: string,
account: Account
): Promise<TransactionReceipt> {
await this.ocean.keeper.didRegistry.grantPermission(
did,
consumer,
account.getId()
)
}
/**
* Remove consumer from DID's FreeWhiteList
* @param {string} did Asset DID.
* @param {string} consumer Ethereum address to add to the list.
* @param {Account} account Ethereum account of DID owner
* @return None
*/
public async removeConsumerFromFreeWhiteList(
did: string,
consumer: string,
account: Account
): Promise<TransactionReceipt> {
await this.ocean.keeper.didRegistry.revokePermission(
did,
consumer,
account.getId()
)
}
}

View File

@ -1,12 +1,11 @@
import { OceanAccounts } from './OceanAccounts'
import { Accounts } from './Accounts'
import { Assets } from './Assets'
import { OceanAuth } from './OceanAuth'
import { Compute } from './Compute'
import { OceanTokens } from './OceanTokens'
import { OceanVersions } from './OceanVersions'
import { OceanUtils } from './utils/OceanUtils'
// import { Compute } from './Compute'
import { Versions } from './Versions'
import { OceanUtils } from './utils/Utils'
import { Aquarius } from '../aquarius/Aquarius'
import { Brizo } from '../brizo/Brizo'
@ -18,7 +17,6 @@ import {
generateIntantiableConfigFromConfig
} from '../Instantiable.abstract'
/**
* Main interface for Ocean Protocol.
*/
@ -45,18 +43,17 @@ export class Ocean extends Instantiable {
instanceConfig.logger
)
instance.accounts = await OceanAccounts.getInstance(instanceConfig)
instance.auth = await OceanAuth.getInstance(instanceConfig)
instance.accounts = await Accounts.getInstance(instanceConfig)
// instance.auth = await Auth.getInstance(instanceConfig)
instance.assets = await Assets.getInstance(instanceConfig)
instance.compute = await Compute.getInstance(instanceConfig)
// instance.compute = await Compute.getInstance(instanceConfig)
instance.datatokens = new DataTokens(
instanceConfig.config.factoryAddress,
instanceConfig.config.factoryABI,
instanceConfig.config.datatokensABI,
instanceConfig.config.web3Provider
)
instance.tokens = await OceanTokens.getInstance(instanceConfig)
instance.versions = await OceanVersions.getInstance(instanceConfig)
instance.versions = await Versions.getInstance(instanceConfig)
return instance
}
@ -67,6 +64,12 @@ export class Ocean extends Instantiable {
*/
public brizo: Brizo
/**
* Web3 provider.
* @type {any}
*/
public web3Provider: any
/**
* Aquarius instance.
* @type {Aquarius}
@ -75,15 +78,16 @@ export class Ocean extends Instantiable {
/**
* Ocean account submodule
* @type {OceanAccounts}
* @type {Accounts}
*/
public accounts: OceanAccounts
public accounts: Accounts
/**
* Ocean auth submodule
* @type {OceanAuth}
*/
public auth: OceanAuth
*/
/**
* Ocean assets submodule
@ -94,8 +98,9 @@ export class Ocean extends Instantiable {
/**
* Ocean compute submodule
* @type {Compute}
*/
public compute: Compute
*/
/**
* Ocean secretStore submodule
@ -106,14 +111,15 @@ export class Ocean extends Instantiable {
/**
* Ocean tokens submodule
* @type {OceanTokens}
*/
public tokens: OceanTokens
*/
/**
* Ocean versions submodule
* @type {OceanVersions}
* @type {Versions}
*/
public versions: OceanVersions
public versions: Versions
/**
* Ocean utils submodule

97
src/ocean/Versions.ts Normal file
View File

@ -0,0 +1,97 @@
import * as metadata from '../metadata.json'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export enum OceanPlatformTechStatus {
Loading = 'Loading',
Unknown = 'Unknown',
Stopped = 'Stopped',
Working = 'Working'
}
export interface OceanPlatformTech {
name: string
version?: string
commit?: string
status: OceanPlatformTechStatus
}
export interface OceanPlatformVersions {
lib: OceanPlatformTech
aquarius: OceanPlatformTech
brizo: OceanPlatformTech
status: {
ok: boolean
}
}
/**
* Versions submodule of Ocean Protocol.
*/
export class Versions extends Instantiable {
/**
* Returns the instance of OceanVersions.
* @return {Promise<OceanVersions>}
*/
public static async getInstance(config: InstantiableConfig): Promise<Versions> {
const instance = new Versions()
instance.setInstanceConfig(config)
return instance
}
public async get(): Promise<OceanPlatformVersions> {
const versions = {} as OceanPlatformVersions
// Squid
versions.lib = {
name: 'Lib',
version: metadata.version,
commit: metadata.commit,
status: OceanPlatformTechStatus.Working
}
// Brizo
try {
const {
network,
software: name,
version
} = await this.ocean.brizo.getVersionInfo()
versions.brizo = {
name,
status: OceanPlatformTechStatus.Working,
version
}
} catch {
versions.brizo = {
name: 'Brizo',
status: OceanPlatformTechStatus.Stopped
}
}
// Aquarius
try {
const { software: name, version } = await this.ocean.aquarius.getVersionInfo()
versions.aquarius = {
name,
status: OceanPlatformTechStatus.Working,
version
}
} catch {
versions.aquarius = {
name: 'Aquarius',
status: OceanPlatformTechStatus.Stopped
}
}
// Status
const techs: OceanPlatformTech[] = Object.values(versions as any)
versions.status = {
ok: !techs.find(({ status }) => status !== OceanPlatformTechStatus.Working)
}
return versions
}
}

View File

@ -0,0 +1,103 @@
import Web3 from 'web3'
import { Logger } from '../../utils'
import { Account } from '../../lib'
export class SignatureUtils {
private web3: Web3
private logger: Logger
constructor(web3: Web3, logger: Logger) {
this.web3 = web3
this.logger = logger
}
public async signText(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(text, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(text, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
}
public async signWithHash(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const hash = this.web3.utils.utf8ToHex(text)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(hash, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(hash, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
}
public async verifyText(text: string, signature: string): Promise<string> {
return this.web3.eth.personal.ecRecover(text, signature)
}
public async getHash(message: string): Promise<string> {
let hex = ''
for (let i = 0; i < message.length; i++) {
hex += '' + message.charCodeAt(i).toString(16)
}
const hexMessage = '0x' + hex
return hexMessage as string
}
public async signForAquarius(message: string, account: Account): Promise<string> {
const hash = await this.getHash(message)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return this.web3.eth.personal.sign(
hash,
account.getId(),
account.getPassword()
)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
return null
}
}
}

34
src/ocean/utils/Utils.ts Normal file
View File

@ -0,0 +1,34 @@
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import { SignatureUtils } from './SignatureUtils'
import { WebServiceConnector } from './WebServiceConnector'
/**
* Utils internal submodule of Ocean Protocol.
*/
export class OceanUtils extends Instantiable {
/**
* Returns the instance of OceanUtils.
* @return {Promise<OceanUtils>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanUtils> {
const instance = new OceanUtils()
instance.setInstanceConfig(config)
instance.signature = new SignatureUtils(config.web3, config.logger)
instance.fetch = new WebServiceConnector(config.logger)
return instance
}
/**
* Signature utils.
* @type {SignatureUtils}
*/
public signature: SignatureUtils
/**
* Fetch utils.
* @type {WebServiceConnector}
*/
public fetch: WebServiceConnector
}

View File

@ -2,6 +2,5 @@ export * from './PromiseResolver'
export * from './Logger'
export * from './ConversionTypeHelpers'
export * from './GeneratorHelpers'
export * from './DDOHelpers'
export * from './SubscribablePromise'
export * from './SubscribableObserver'