diff --git a/src/ddo/interfaces/File.ts b/src/ddo/interfaces/File.ts index 6830cc83..e8193b51 100644 --- a/src/ddo/interfaces/File.ts +++ b/src/ddo/interfaces/File.ts @@ -11,12 +11,6 @@ export interface File { */ url?: string - /** - * Is URL accessible. - * @type {boolean} - */ - valid?: boolean - /** * File index. * @type {number} diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index fffe1bcc..9f6d6815 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -113,8 +113,8 @@ export class Assets extends Instantiable { let provider: Provider if (providerUri) { - provider = new Provider(this.instanceConfig) - provider.setBaseUrl(providerUri) + provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(providerUri) } else provider = this.ocean.provider const encryptedFiles = await provider.encrypt( did.getDid(), @@ -419,8 +419,8 @@ export class Assets extends Instantiable { serviceIndex = -1, serviceEndpoint: string ): Promise { - const provider = new Provider(this.instanceConfig) - provider.setBaseUrl(serviceEndpoint) + const provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(serviceEndpoint) const res = await provider.initialize(did, serviceIndex, serviceType, consumerAddress) if (res === null) return null const providerData = JSON.parse(res) @@ -527,8 +527,8 @@ export class Assets extends Instantiable { destination = destination ? `${destination}/datafile.${ddo.shortId()}.${service.index}/` : undefined - const provider = new Provider(this.instanceConfig) - provider.setBaseUrl(serviceEndpoint) + const provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(serviceEndpoint) await provider.download( did, txId, diff --git a/src/ocean/Compute.ts b/src/ocean/Compute.ts index 68027753..9cad3e79 100644 --- a/src/ocean/Compute.ts +++ b/src/ocean/Compute.ts @@ -92,8 +92,8 @@ export class Compute extends Instantiable { const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service if (did && txId) { - const provider = new Provider(this.instanceConfig) - provider.setBaseUrl(serviceEndpoint) + const provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.compute( 'post', did, @@ -128,8 +128,8 @@ export class Compute extends Instantiable { 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 provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.compute( 'put', did, @@ -157,8 +157,8 @@ export class Compute extends Instantiable { 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 provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.compute( 'delete', did, @@ -193,8 +193,8 @@ export class Compute extends Instantiable { const ddo = await this.ocean.assets.resolve(did) const service = ddo.findServiceByType('compute') const { serviceEndpoint } = service - provider = new Provider(this.instanceConfig) - provider.setBaseUrl(serviceEndpoint) + provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(serviceEndpoint) } else { provider = this.ocean.provider } @@ -233,8 +233,8 @@ export class Compute extends Instantiable { 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 provider = await Provider.getInstance(this.instanceConfig) + await provider.setBaseUrl(serviceEndpoint) const computeJobsList = await provider.compute( 'get', did, diff --git a/src/ocean/Ocean.ts b/src/ocean/Ocean.ts index e59d0e0e..da0a90a7 100644 --- a/src/ocean/Ocean.ts +++ b/src/ocean/Ocean.ts @@ -36,7 +36,7 @@ export class Ocean extends Instantiable { instance.utils = await OceanUtils.getInstance(instanceConfig) - instance.provider = new Provider(instanceConfig) + instance.provider = await Provider.getInstance(instanceConfig) instance.metadataCache = new MetadataCache( instanceConfig.config.metadataCacheUri, instanceConfig.logger diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 0a575b37..ae3616a6 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -10,7 +10,11 @@ import { Response } from 'node-fetch' import { DDO } from '../ddo/DDO' import DID from '../ocean/DID' -const apiPath = '/api/v1/services' +export interface ServiceEndpoint { + serviceName: string + method: string + urlPath: string +} /** * Provides an interface for provider service. @@ -21,20 +25,62 @@ const apiPath = '/api/v1/services' export class Provider extends Instantiable { public nonce: string private baseUrl: string + public servicesEndpoints: ServiceEndpoint[] + public providerAddress: string + /** + * Returns the instance of Provider. + * @return {Promise} + */ + public static async getInstance(config: InstantiableConfig): Promise { + const instance = new Provider() + instance.setInstanceConfig(config) + instance.nonce = '0' + await instance.setBaseUrl(config.config.providerUri) + return instance + } public get url(): string { return this.baseUrl } - constructor(config: InstantiableConfig) { - super() - this.setInstanceConfig(config) - this.baseUrl = this.config.providerUri - this.nonce = '0' + public async setBaseUrl(url: string): Promise { + this.baseUrl = url + this.servicesEndpoints = await this.getServiceEndpoints() + return true } - public setBaseUrl(url: string): void { - this.baseUrl = url + /** + * Returns the service endpoints that exist + * in provider. + * @return {Promise} + */ + + public async getServiceEndpoints(): Promise { + const serviceEndpoints: ServiceEndpoint[] = [] + try { + const result = await (await this.ocean.utils.fetch.get(this.url)).json() + this.providerAddress = result['provider-address'] + for (const i in result.serviceEndpoints) { + const endpoint: ServiceEndpoint = { + serviceName: i, + method: result.serviceEndpoints[i][0], + urlPath: this.url + result.serviceEndpoints[i][1] + } + serviceEndpoints.push(endpoint) + } + return serviceEndpoints + } catch (e) { + this.logger.error('Finding the service endpoints failed:', e) + + return null + } + } + + public getEndpointURL(serviceName: string): ServiceEndpoint { + if (!this.servicesEndpoints) return null + return this.servicesEndpoints.find( + (s) => s.serviceName === serviceName + ) as ServiceEndpoint } public async createSignature(account: Account, agreementId: string): Promise { @@ -64,7 +110,7 @@ export class Provider extends Instantiable { } try { const response = await this.ocean.utils.fetch.post( - this.getEncryptEndpoint(), + this.getEncryptEndpoint().urlPath, decodeURI(JSON.stringify(args)) ) return (await response.json()).encryptedDocument @@ -86,7 +132,7 @@ export class Provider extends Instantiable { } else args = { url } try { const response = await this.ocean.utils.fetch.post( - this.getFileinfoEndpoint(), + this.getFileinfoEndpoint().urlPath, JSON.stringify(args) ) const results: File[] = await response.json() @@ -104,7 +150,7 @@ export class Provider extends Instantiable { * @return {Promise} string */ public async getNonce(consumerAddress: string): Promise { - let initializeUrl = this.getNonceEndpoint() + let initializeUrl = this.getNonceEndpoint().urlPath initializeUrl += `?userAddress=${consumerAddress}` try { const response = await this.ocean.utils.fetch.get(initializeUrl) @@ -131,7 +177,7 @@ export class Provider extends Instantiable { throw new Error('Failed to resolve DID') } - let initializeUrl = this.getInitializeEndpoint() + let initializeUrl = this.getInitializeEndpoint().urlPath initializeUrl += `?documentId=${did}` initializeUrl += `&serviceId=${serviceIndex}` initializeUrl += `&serviceType=${serviceType}` @@ -162,7 +208,7 @@ export class Provider extends Instantiable { const filesPromises = files .filter((_, i) => index === -1 || i === index) .map(async ({ index: i }) => { - let consumeUrl = this.getDownloadEndpoint() + let consumeUrl = this.getDownloadEndpoint().urlPath consumeUrl += `?fileIndex=${i}` consumeUrl += `&documentId=${did}` consumeUrl += `&serviceId=${serviceIndex}` @@ -204,7 +250,21 @@ export class Provider extends Instantiable { ): Promise { const address = consumerAccount.getId() await this.getNonce(consumerAccount.getId()) - let url = this.getComputeEndpoint() + let url + switch (method) { + case 'get': + url = this.getComputeStatusEndpoint().urlPath + break + case 'post': + url = this.getComputeStartEndpoint().urlPath + break + case 'put': + url = this.getComputeStopEndpoint().urlPath + break + case 'delete': + url = this.getComputeDeleteEndpoint().urlPath + break + } url += `?documentId=${noZeroX(did)}` if (sign) { let signatureMessage = address @@ -242,7 +302,6 @@ export class Provider extends Instantiable { // 'algorithmDid': alg_ddo.did, // 'algorithmMeta': {}, // 'algorithmDataToken': alg_data_token - // switch fetch method let fetch switch (method) { @@ -287,44 +346,40 @@ export class Provider extends Instantiable { return `${this.url}` } - public getInitializeEndpoint(): string { - return `${this.url}${apiPath}/initialize` + public getInitializeEndpoint(): ServiceEndpoint { + return this.getEndpointURL('initialize') } - public getNonceEndpoint(): string { - return `${this.url}${apiPath}/nonce` + public getNonceEndpoint(): ServiceEndpoint { + return this.getEndpointURL('nonce') } - public getConsumeEndpointPath(): string { - return `${apiPath}/consume` + public getEncryptEndpoint(): ServiceEndpoint { + return this.getEndpointURL('encrypt') } - public getConsumeEndpoint(): string { - return `${this.url}` + this.getConsumeEndpointPath() + public getFileinfoEndpoint(): ServiceEndpoint { + return this.getEndpointURL('fileinfo') } - public getEncryptEndpoint(): string { - return `${this.url}${apiPath}/encrypt` + public getComputeStatusEndpoint(): ServiceEndpoint { + return this.getEndpointURL('computeStatus') } - public getFileinfoEndpoint(): string { - return `${this.url}${apiPath}/fileinfo` + public getComputeStartEndpoint(): ServiceEndpoint { + return this.getEndpointURL('computeStart') } - public getPublishEndpoint(): string { - return `${this.url}${apiPath}/publish` + public getComputeStopEndpoint(): ServiceEndpoint { + return this.getEndpointURL('computeStop') } - public getComputeEndpointPath(): string { - return `${apiPath}/compute` + public getComputeDeleteEndpoint(): ServiceEndpoint { + return this.getEndpointURL('computeDelete') } - public getComputeEndpoint(): string { - return `${this.url}` + this.getComputeEndpointPath() - } - - public getDownloadEndpoint(): string { - return `${this.url}${apiPath}/download` + public getDownloadEndpoint(): ServiceEndpoint { + return this.getEndpointURL('download') } /** Check for a valid provider at URL diff --git a/test/integration/Marketplaceflow.test.ts b/test/integration/Marketplaceflow.test.ts index 1e408beb..e4840992 100644 --- a/test/integration/Marketplaceflow.test.ts +++ b/test/integration/Marketplaceflow.test.ts @@ -243,7 +243,6 @@ describe('Marketplace flow', () => { it('Alice should check if her asset has valid url(s)', async () => { const did: DID = DID.generate(noDidPrefixed(ddo.id)) const response = await ocean.provider.fileinfo(did) - assert(response[0].valid === true) assert(response[0].contentLength === '1161') assert(response[0].contentType === 'application/json') }) diff --git a/test/integration/Provider.test.ts b/test/integration/Provider.test.ts index 0bf38f42..6d89c4d2 100644 --- a/test/integration/Provider.test.ts +++ b/test/integration/Provider.test.ts @@ -25,6 +25,7 @@ describe('Provider tests', () => { it('Check a invalid URL', async () => { const url = 'https://s3.amazonaws.com/testfiles.oceanprotocol.com/nosuchfile' const response = await ocean.provider.fileinfo(url) - assert(response[0].valid === false) + assert(response[0].contentLength === undefined) + assert(response[0].contentType === undefined) }) })