diff --git a/client/package-lock.json b/client/package-lock.json index 958c230..08e1f42 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2106,9 +2106,9 @@ } }, "@oceanprotocol/squid": { - "version": "2.0.0-beta.4", - "resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-2.0.0-beta.4.tgz", - "integrity": "sha512-SZx940zRJxN6HPB2Zsk3OMjkBUBjUiVWRvYFjKNTQqwflOe80ceGxWzKRwxcBvzz/C4TN1zXQAXHIidOR8aPMQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@oceanprotocol/squid/-/squid-2.0.0.tgz", + "integrity": "sha512-VO/7aafazsS/XWltaUKjGa78T/rmRKA5BAl7pgQXgNvFL28LOiZIJwpk5yYFdUONNEYzxAnFZ0U0TU5womKTHg==", "requires": { "@ethereum-navigator/navigator": "^0.4.1", "@oceanprotocol/keeper-contracts": "^0.13.2", @@ -2117,9 +2117,16 @@ "deprecated-decorator": "^0.1.6", "node-fetch": "^2.6.0", "save-file": "^2.3.1", - "uuid": "^3.4.0", - "web3": "^1.2.5", + "uuid": "^7.0.2", + "web3": "^1.2.6", "whatwg-url": "^8.0.0" + }, + "dependencies": { + "uuid": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz", + "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==" + } } }, "@oceanprotocol/typographies": { diff --git a/client/package.json b/client/package.json index 50cbb52..b685673 100644 --- a/client/package.json +++ b/client/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@oceanprotocol/art": "^2.2.0", - "@oceanprotocol/squid": "2.0.0-beta.4", + "@oceanprotocol/squid": "2.0.0", "@oceanprotocol/typographies": "^0.1.0", "@sindresorhus/slugify": "^0.11.0", "@truffle/hdwallet-provider": "^1.0.33", diff --git a/client/src/components/templates/Asset/AssetDetails.tsx b/client/src/components/templates/Asset/AssetDetails.tsx index 7b8d654..9ca7a55 100644 --- a/client/src/components/templates/Asset/AssetDetails.tsx +++ b/client/src/components/templates/Asset/AssetDetails.tsx @@ -9,11 +9,11 @@ import AssetFilesDetails from './AssetFilesDetails' import Report from './Report' import Web3 from 'web3' import AssetsJob from './AssetJob' +import Web3message from '../../organisms/Web3message' interface AssetDetailsProps { ocean: any metadata: MetaData - computeMetadata?: MetaData ddo: DDO } @@ -36,15 +36,13 @@ const MetaFixedItem = ({ name, value }: { name: string; value: string }) => ( export default function AssetDetails({ metadata, ddo, - computeMetadata, ocean }: AssetDetailsProps) { const { main, additionalInformation } = metadata const price = main.price && Web3.utils.fromWei(main.price.toString()) - console.log(computeMetadata) - const isCompute = computeMetadata ? true : false - console.log(isCompute) + const isCompute = !!ddo.findServiceByType('compute') + const isAccess = !!ddo.findServiceByType('access') const metaFixed = [ { @@ -131,19 +129,14 @@ export default function AssetDetails({ ))} - - {isCompute ? ( - - ) : ( + {isAccess ? ( - )} + ) : null} + {isCompute ? : null} + {isCompute || isAccess ? : null} ) } diff --git a/client/src/components/templates/Asset/AssetFilesDetails.tsx b/client/src/components/templates/Asset/AssetFilesDetails.tsx index f745772..a16308e 100644 --- a/client/src/components/templates/Asset/AssetFilesDetails.tsx +++ b/client/src/components/templates/Asset/AssetFilesDetails.tsx @@ -19,7 +19,6 @@ export default class AssetFilesDetails extends PureComponent<{ ))} - ) : (
No files attached.
diff --git a/client/src/components/templates/Asset/AssetJob.module.scss b/client/src/components/templates/Asset/AssetJob.module.scss index 248d5ee..9dbca89 100644 --- a/client/src/components/templates/Asset/AssetJob.module.scss +++ b/client/src/components/templates/Asset/AssetJob.module.scss @@ -12,34 +12,6 @@ padding-top: 10px; } -.buttonWrapper { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 120px; -} - -.error { - color: $red; - align-items: center; - justify-content: center; -} - -.bold { - font-weight: 900; -} - -.expiry { - color: $brand-grey-light; - float: right; -} - -.job { - border-top: 1px solid #e2e2e2; -} - .dragndrop { display: flex; flex-direction: column; @@ -86,15 +58,8 @@ margin-top: $spacer / 4; } -.table { - margin-top: $spacer / 2; - margin-bottom: 0; -} - -.spinner { - padding-bottom: 30px; -} - -.jobloading { - padding-left: 23px; +.error { + text-align: center; + color: $red; + font-size: $font-size-small; } diff --git a/client/src/components/templates/Asset/AssetJob.tsx b/client/src/components/templates/Asset/AssetJob.tsx index 6e88cb0..c0e3b3f 100644 --- a/client/src/components/templates/Asset/AssetJob.tsx +++ b/client/src/components/templates/Asset/AssetJob.tsx @@ -1,5 +1,5 @@ import React, { ChangeEvent, useState } from 'react' -import { DDO, MetaData } from '@oceanprotocol/squid' +import { DDO } from '@oceanprotocol/squid' import Input from '../../atoms/Form/Input' import computeOptions from '../../../data/computeOptions.json' import styles from './AssetJob.module.scss' @@ -7,15 +7,15 @@ import Spinner from '../../atoms/Spinner' import Button from '../../atoms/Button' import { messages } from './AssetFile' import ReactDropzone from 'react-dropzone' +import { readFileContent } from '../../../utils/utils' interface JobsProps { ocean: any - computeMetadata?: MetaData ddo: DDO } -export default function AssetsJobs({ ddo, computeMetadata, ocean }: JobsProps) { - let rawAlgorithmMeta = { +export default function AssetsJobs({ ddo, ocean }: JobsProps) { + const rawAlgorithmMeta = { rawcode: `console.log('Hello world'!)`, format: 'docker-image', version: '0.1', @@ -24,6 +24,7 @@ export default function AssetsJobs({ ddo, computeMetadata, ocean }: JobsProps) { const [isJobStarting, setIsJobStarting] = useState(false) const [step, setStep] = useState(99) + const [error, setError] = useState('') const [computeType, setComputeType] = useState('') const [computeValue, setComputeValue] = useState({}) @@ -46,19 +47,11 @@ export default function AssetsJobs({ ddo, computeMetadata, ocean }: JobsProps) { if (selectedComputeOption !== undefined) setComputeValue(selectedComputeOption.value) } - const readFileContent = (file: File): Promise => { - return new Promise(resolve => { - const reader = new FileReader() - reader.onload = function(e) { - resolve(reader.result as string) - } - reader.readAsText(file) - }) - } const startJob = async () => { try { setIsJobStarting(true) + setError('') const accounts = await ocean.accounts.list() const ComputeOutput = { publishAlgorithmLog: false, @@ -78,17 +71,15 @@ export default function AssetsJobs({ ddo, computeMetadata, ocean }: JobsProps) { rawAlgorithmMeta.container = computeValue rawAlgorithmMeta.rawcode = algorithmRawCode - const status = await ocean.compute.start( + await ocean.compute.start( accounts[0], agreement, undefined, - encodeURIComponent(JSON.stringify(rawAlgorithmMeta)), + rawAlgorithmMeta, ComputeOutput ) - - console.log(status) } catch (error) { - console.error(error.message) + setError('Failed to start job!') } setIsJobStarting(false) } @@ -152,6 +143,9 @@ export default function AssetsJobs({ ddo, computeMetadata, ocean }: JobsProps) { {isJobStarting ? : ''} + {error !== '' && ( +
{error}
+ )} diff --git a/client/src/components/templates/Asset/index.tsx b/client/src/components/templates/Asset/index.tsx index c6c4461..4292f7e 100644 --- a/client/src/components/templates/Asset/index.tsx +++ b/client/src/components/templates/Asset/index.tsx @@ -23,14 +23,12 @@ interface AssetState { ocean: any ddo: DDO metadata: MetaData - computeMetadata?: MetaData error: string isLoading: boolean } class Asset extends Component { public static contextType = User - public state = { ocean: undefined, ddo: ({} as any) as DDO, @@ -48,19 +46,12 @@ class Asset extends Component { try { const { ocean } = this.context const ddo = await ocean.assets.resolve(this.props.match.params.did) - const { attributes } = ddo.findServiceByType('metadata') - let computeAttributes - - try { - computeAttributes = ddo.findServiceByType('compute') - } catch (error) {} this.setState({ ocean, ddo, metadata: attributes, - computeMetadata: computeAttributes, isLoading: false }) } catch (error) { @@ -108,12 +99,7 @@ class Asset extends Component { } > - + ) diff --git a/client/src/data/form-publish.json b/client/src/data/form-publish.json index df85c27..98576ee 100644 --- a/client/src/data/form-publish.json +++ b/client/src/data/form-publish.json @@ -17,6 +17,7 @@ "type": "select", "required": true, "options": [ + "both", "access", "compute" ] diff --git a/client/src/routes/Publish/index.tsx b/client/src/routes/Publish/index.tsx index d6ba9d1..350d0d7 100644 --- a/client/src/routes/Publish/index.tsx +++ b/client/src/routes/Publish/index.tsx @@ -12,9 +12,10 @@ import { allowPricing } from '../../config' import { steps } from '../../data/form-publish.json' import Content from '../../components/atoms/Content' import withTracker from '../../hoc/withTracker' +import { createComputeService } from '../../utils/createComputeService' type AssetType = 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other' -type DatasetType = 'compute' | 'access' +type DatasetType = 'both' | 'compute' | 'access' interface PublishState { name?: string dateCreated?: string @@ -61,7 +62,7 @@ class Publish extends Component<{}, PublishState> { license: '', copyrightHolder: '', categories: '', - datasetType: 'access' as DatasetType, + datasetType: 'both' as DatasetType, currentStep: 1, isPublishing: false, @@ -259,32 +260,6 @@ class Publish extends Component<{}, PublishState> { } } - private async createComputeService( - ocean: any, - publisher: any, - price: string, - datePublished: string - ) { - const { templates } = ocean.keeper - const serviceAgreementTemplate = await templates.escrowComputeExecutionTemplate.getServiceAgreementTemplate() - const name = 'dataAssetComputingServiceAgreement' - return { - type: 'compute', - serviceEndpoint: ocean.brizo.getComputeEndpoint(), - templateId: templates.escrowComputeExecutionTemplate.getId(), - attributes: { - main: { - creator: publisher.getId(), - datePublished, - price, - timeout: 3600, - name - }, - serviceAgreementTemplate - } - } - } - private handleRegisterAsset = async (event: FormEvent) => { event.preventDefault() @@ -334,21 +309,36 @@ class Publish extends Component<{}, PublishState> { } try { - let computeService: any[] = [] - console.log('dataset type ', this.state.datasetType) - if (this.state.datasetType === 'compute') { - const service = await this.createComputeService( + const services: any[] = [] + + if ( + this.state.datasetType === 'compute' || + this.state.datasetType === 'both' + ) { + const service = await createComputeService( ocean, account[0], this.state.price, this.state.dateCreated ) - computeService = [service] - console.log('compute ', computeService) + services.push(service) } + if ( + this.state.datasetType === 'access' || + this.state.datasetType === 'both' + ) { + const service = await ocean.assets.createAccessServiceAttributes( + account[0], + this.state.price, + this.state.dateCreated + ) + services.push(service) + } + console.log(services) + const asset = await this.context.ocean.assets - .create(newAsset, account[0], computeService) + .create(newAsset, account[0], services) .next((publishingStep: number) => this.setState({ publishingStep }) ) diff --git a/client/src/utils/createComputeService.tsx b/client/src/utils/createComputeService.tsx new file mode 100644 index 0000000..5eb359f --- /dev/null +++ b/client/src/utils/createComputeService.tsx @@ -0,0 +1,25 @@ +export async function createComputeService( + ocean: any, + publisher: any, + price: string, + datePublished: string +) { + const { templates } = ocean.keeper + const serviceAgreementTemplate = await templates.escrowComputeExecutionTemplate.getServiceAgreementTemplate() + const name = 'dataAssetComputingServiceAgreement' + return { + type: 'compute', + serviceEndpoint: ocean.brizo.getComputeEndpoint(), + templateId: templates.escrowComputeExecutionTemplate.getId(), + attributes: { + main: { + creator: publisher.getId(), + datePublished, + price, + timeout: 3600, + name + }, + serviceAgreementTemplate + } + } +} diff --git a/client/src/utils/utils.test.ts b/client/src/utils/utils.test.ts index 73b8623..9c102f0 100644 --- a/client/src/utils/utils.test.ts +++ b/client/src/utils/utils.test.ts @@ -1,5 +1,11 @@ import mockAxios from 'jest-mock-axios' -import { formatBytes, pingUrl, arraySum, readFileAsync } from './utils' +import { + formatBytes, + pingUrl, + arraySum, + readFileAsync, + readFileContent +} from './utils' describe('formatBytes', () => { it('outputs as expected', () => { @@ -67,3 +73,15 @@ describe('readFileAsync', () => { expect(output).toBeInstanceOf(ArrayBuffer) }) }) + +describe('readFileContent', () => { + it('outputs as expected', async () => { + const file = new File(['ABC'], 'filename.txt', { + type: 'text/plain', + lastModified: Date.now() + }) + + const output = await readFileContent(file) + expect(output).toBeInstanceOf(String) + }) +}) diff --git a/client/src/utils/utils.ts b/client/src/utils/utils.ts index 928dc93..3e0c485 100644 --- a/client/src/utils/utils.ts +++ b/client/src/utils/utils.ts @@ -61,3 +61,16 @@ export function readFileAsync(file: File) { reader.readAsArrayBuffer(file) }) } +export function readFileContent(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader() + reader.onerror = () => { + reader.abort() + reject(new DOMException('Problem parsing input file.')) + } + reader.onload = () => { + resolve(reader.result as string) + } + reader.readAsText(file) + }) +}