diff --git a/.travis.yml b/.travis.yml index 8a150c37..1a5d0c5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,4 +47,4 @@ deploy: api_key: ${NPM_TOKEN} skip_cleanup: true on: - tags: true + tags: true \ No newline at end of file diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index b882e3f7..8e7edc80 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -15,6 +15,7 @@ import { SubscribablePromise, didZeroX } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { WebServiceConnector } from './utils/WebServiceConnector' import BigNumber from 'bignumber.js' +import { Provider } from '../provider/Provider' import { isAddress } from 'web3-utils' export enum CreateProgressStep { @@ -56,6 +57,7 @@ export class Assets extends Instantiable { * @param {String} cap Maximum cap (Number) - will be converted to wei * @param {String} name Token name * @param {String} symbol Token symbol + * @param {String} providerUri * @return {Promise} */ public create( @@ -65,7 +67,8 @@ export class Assets extends Instantiable { dtAddress?: string, cap?: string, name?: string, - symbol?: string + symbol?: string, + providerUri?: string ): SubscribablePromise { if (!isAddress(dtAddress)) { this.logger.error( @@ -109,7 +112,12 @@ export class Assets extends Instantiable { this.logger.log('Encrypting files') observer.next(CreateProgressStep.EncryptingFiles) - const encryptedFiles = await this.ocean.provider.encrypt( + let provider + if (providerUri) { + provider = new Provider(this.instanceConfig) + provider.setBaseUrl(providerUri) + } else provider = this.ocean.provider + const encryptedFiles = await provider.encrypt( did.getId(), metadata.main.files, publisher @@ -395,12 +403,13 @@ export class Assets extends Instantiable { creator: Account, cost: string, datePublished: string, - timeout = 0 + timeout = 0, + providerUri?: string ): Promise { return { type: 'access', index: 2, - serviceEndpoint: this.ocean.provider.getConsumeEndpoint(), + serviceEndpoint: providerUri || this.ocean.provider.url, attributes: { main: { creator: creator.getId(), @@ -428,14 +437,12 @@ export class Assets extends Instantiable { did: string, serviceType: string, consumerAddress: string, - serviceIndex = -1 + serviceIndex = -1, + serviceEndpoint: string ): Promise { - const res = await this.ocean.provider.initialize( - did, - serviceIndex, - serviceType, - consumerAddress - ) + const provider = new Provider(this.instanceConfig) + provider.setBaseUrl(serviceEndpoint) + const res = await provider.initialize(did, serviceIndex, serviceType, consumerAddress) if (res === null) return null const providerData = JSON.parse(res) return providerData @@ -457,11 +464,12 @@ export class Assets extends Instantiable { serviceIndex = -1, mpAddress?: string ): Promise { + let service if (serviceIndex === -1) { - const service = await this.getServiceByType(did, serviceType) + service = await this.getServiceByType(did, serviceType) serviceIndex = service.index } else { - const service = await this.getServiceByIndex(did, serviceIndex) + service = await this.getServiceByIndex(did, serviceIndex) serviceType = service.type } const { datatokens } = this.ocean @@ -470,10 +478,11 @@ export class Assets extends Instantiable { did, serviceType, consumerAddress, - serviceIndex + serviceIndex, + service.serviceEndpoint ) if (!providerData) return null - const service = await this.getServiceByIndex(did, serviceIndex) + service = await this.getServiceByIndex(did, serviceIndex) const previousOrder = await datatokens.getPreviousValidOrders( providerData.dataToken, providerData.numTokens, @@ -538,8 +547,9 @@ export class Assets extends Instantiable { destination = destination ? `${destination}/datafile.${ddo.shortId()}.${service.index}/` : undefined - - await this.ocean.provider.download( + const provider = new Provider(this.instanceConfig) + provider.setBaseUrl(serviceEndpoint) + await provider.download( did, txId, tokenAddress, diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index 597bc454..34d496d3 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -6,6 +6,7 @@ import { SubscribablePromise } from '../utils' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { Output } from './interfaces/ComputeOutput' import { ComputeJob } from './interfaces/ComputeJob' +import { Provider } from '../provider/Provider' export enum OrderProgressStep { TransferDataToken @@ -87,8 +88,13 @@ export class Compute extends Instantiable { algorithmDataToken?: string ): Promise { output = this.checkOutput(consumerAccount, output) + const ddo = await this.ocean.assets.resolve(did) + const service = ddo.findServiceByType('compute') + const { serviceEndpoint } = service if (did && txId) { - const computeJobsList = await this.ocean.provider.compute( + const provider = new Provider(this.instanceConfig) + provider.setBaseUrl(serviceEndpoint) + const computeJobsList = await provider.compute( 'post', did, consumerAccount, @@ -119,7 +125,12 @@ export class Compute extends Instantiable { did: string, jobId: string ): Promise { - const computeJobsList = await this.ocean.provider.compute( + const ddo = await this.ocean.assets.resolve(did) + const service = ddo.findServiceByType('compute') + const { serviceEndpoint } = service + const provider = new Provider(this.instanceConfig) + provider.setBaseUrl(serviceEndpoint) + const computeJobsList = await provider.compute( 'put', did, consumerAccount, @@ -143,7 +154,12 @@ export class Compute extends Instantiable { did: string, jobId: string ): Promise { - const computeJobsList = await this.ocean.provider.compute( + const ddo = await this.ocean.assets.resolve(did) + const service = ddo.findServiceByType('compute') + const { serviceEndpoint } = service + const provider = new Provider(this.instanceConfig) + provider.setBaseUrl(serviceEndpoint) + const computeJobsList = await provider.compute( 'delete', did, consumerAccount, @@ -167,7 +183,17 @@ export class Compute extends Instantiable { did?: string, jobId?: string ): Promise { - const computeJobsList = await this.ocean.provider.compute( + let provider + if (did) { + const ddo = await this.ocean.assets.resolve(did) + const service = ddo.findServiceByType('compute') + const { serviceEndpoint } = service + provider = new Provider(this.instanceConfig) + provider.setBaseUrl(serviceEndpoint) + } else { + provider = this.ocean.provider + } + const computeJobsList = await provider.compute( 'get', did, consumerAccount, @@ -191,7 +217,12 @@ export class Compute extends Instantiable { did: string, jobId: string ): Promise { - const computeJobsList = await this.ocean.provider.compute( + const ddo = await this.ocean.assets.resolve(did) + const service = ddo.findServiceByType('compute') + const { serviceEndpoint } = service + const provider = new Provider(this.instanceConfig) + provider.setBaseUrl(serviceEndpoint) + const computeJobsList = await provider.compute( 'get', did, consumerAccount, @@ -279,14 +310,15 @@ export class Compute extends Instantiable { datePublished: string, providerAttributes: any, computePrivacy?: ServiceComputePrivacy, - timeout?: number + timeout?: number, + providerUri?: string ): ServiceCompute { const name = 'dataAssetComputingService' if (!timeout) timeout = 3600 const service = { type: 'compute', index: 3, - serviceEndpoint: this.ocean.provider.getComputeEndpoint(), + serviceEndpoint: providerUri || this.ocean.provider.url, attributes: { main: { name, diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 6502f2a8..562e8cfd 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -18,16 +18,22 @@ const apiPath = '/api/v1/services' */ export class Provider extends Instantiable { public nonce: string - private get url() { - return this.config.providerUri + private baseUrl: string + public get url() { + return this.baseUrl } constructor(config: InstantiableConfig) { super() this.setInstanceConfig(config) + this.baseUrl = this.config.providerUri this.nonce = '0' } + public setBaseUrl(url: string): void { + this.baseUrl = url + } + public async createSignature(account: Account, agreementId: string): Promise { const signature = await this.ocean.utils.signature.signText( noZeroX(agreementId), @@ -264,8 +270,12 @@ export class Provider extends Instantiable { return `${this.url}${apiPath}/nonce` } + public getConsumeEndpointPath(): string { + return `${apiPath}/consume` + } + public getConsumeEndpoint(): string { - return `${this.url}${apiPath}/consume` + return `${this.url}` + this.getConsumeEndpointPath() } public getEncryptEndpoint(): string { @@ -276,11 +286,33 @@ export class Provider extends Instantiable { return `${this.url}${apiPath}/publish` } + public getComputeEndpointPath(): string { + return `${apiPath}/compute` + } + public getComputeEndpoint(): string { - return `${this.url}${apiPath}/compute` + return `${this.url}` + this.getComputeEndpointPath() } public getDownloadEndpoint(): string { return `${this.url}${apiPath}/download` } + + /** Check for a valid provider at URL + * @param {String} url + * @return {Promise} string + */ + public async isValidProvider(url: string): Promise { + try { + const response = await this.ocean.utils.fetch.get(url) + if (response?.ok) { + const params = await response.json() + if (params && params['provider-address']) return true + } + return false + } catch (error) { + this.logger.error(`Error validating provider: ${error.message}`) + return false + } + } } diff --git a/test/integration/Provider.test.ts b/test/integration/Provider.test.ts new file mode 100644 index 00000000..e3ddcb24 --- /dev/null +++ b/test/integration/Provider.test.ts @@ -0,0 +1,18 @@ +import { Ocean } from '../../src/ocean/Ocean' +import config from './config' +import { assert } from 'console' + +describe('Provider tests', () => { + let ocean + it('Initialize Ocean', async () => { + ocean = await Ocean.getInstance(config) + }) + it('Alice tests invalid provider', async () => { + const valid = ocean.provider.isValidProvider('http://example.net') + assert(valid === false) + }) + it('Alice tests valid provider', async () => { + const valid = ocean.provider.isValidProvider('http://127.0.0.1:8030') + assert(valid === true) + }) +})