1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

more publish flow preparation

* consolidate scattered methods into publish utils
* new encrypt method
* remove DDO File typings
This commit is contained in:
Matthias Kretschmann 2021-11-11 13:40:38 +00:00
parent 8ce573b2a0
commit 704b52a3c4
Signed by: m
GPG Key ID: 606EEEF3C479A91F
19 changed files with 126 additions and 180 deletions

View File

@ -1,18 +0,0 @@
// This is all super questionable,
// but we most likely need something to represent what we get
// back from fileinfo endpoint in Provider. But then should be moved out of DDO typings.
interface FileMetadata {
url: string
contentType: string
name?: string
checksum?: string
checksumType?: string
contentLength?: string
encoding?: string
compression?: string
encrypted?: boolean
encryptionMode?: string
resourceId?: string
attributes?: { [key: string]: any }
}

View File

@ -1,5 +1,3 @@
import slugify from 'slugify'
export function getServiceByName( export function getServiceByName(
ddo: Asset | DDO, ddo: Asset | DDO,
name: 'access' | 'compute' name: 'access' | 'compute'
@ -10,16 +8,6 @@ export function getServiceByName(
return service return service
} }
export function dateToStringNoMS(date: Date): string {
return date.toISOString().replace(/\.[0-9]{3}Z/, 'Z')
}
export function transformTags(value: string): string[] {
const originalTags = value?.split(',')
const transformedTags = originalTags?.map((tag) => slugify(tag).toLowerCase())
return transformedTags
}
export function mapTimeoutStringToSeconds(timeout: string): number { export function mapTimeoutStringToSeconds(timeout: string): number {
switch (timeout) { switch (timeout) {
case 'Forever': case 'Forever':
@ -68,18 +56,3 @@ export function secondsToString(numberOfSeconds: number): string {
? `${seconds} second${numberEnding(seconds)}` ? `${seconds} second${numberEnding(seconds)}`
: 'less than a second' : 'less than a second'
} }
export function checkIfTimeoutInPredefinedValues(
timeout: string,
timeoutOptions: string[]
): boolean {
if (timeoutOptions.indexOf(timeout) > -1) {
return true
}
return false
}
export function getUrlFileExtension(fileUrl: string): string {
const splitedFileUrl = fileUrl.split('.')
return splitedFileUrl[splitedFileUrl.length - 1]
}

View File

@ -1,70 +1,16 @@
import axios, { CancelToken, AxiosResponse } from 'axios' import axios, { CancelToken, AxiosResponse } from 'axios'
import { toast } from 'react-toastify'
import { DID, Logger } from '@oceanprotocol/lib' import { DID, Logger } from '@oceanprotocol/lib'
export async function fileinfo( export interface FileMetadata {
url: string, contentType: string
providerUri: string, contentLength: string
cancelToken: CancelToken
): Promise<FileMetadata> {
try {
const response = (await axios.post(
`${providerUri}/api/v1/services/fileinfo`,
{
url,
cancelToken
}
)) as AxiosResponse<
{ valid: boolean; contentLength: string; contentType: string }[]
>
if (!response || response.status !== 200 || !response.data) {
toast.error('Could not connect to File API')
return
}
if (!response.data[0] || !response.data[0].valid) {
toast.error(
'The data file URL you entered apears to be invalid. Please check URL and try again',
{
autoClose: false,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined
}
)
return
} else {
toast.dismiss() // Remove any existing error message
toast.success('Great! That file looks good. 🐳', {
position: 'bottom-right',
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined
})
}
const { contentLength, contentType } = response.data[0]
return {
contentLength: contentLength || '',
contentType: contentType || '', // need to do that cause lib-js File interface requires contentType
url
}
} catch (error) {
Logger.error(error.message)
}
} }
export async function getFileInfo( export async function getFileInfo(
url: string | DID, url: string | DID,
providerUri: string, providerUri: string,
cancelToken: CancelToken cancelToken: CancelToken
): Promise<any> { ): Promise<FileMetadata[]> {
let postBody let postBody
try { try {
if (url instanceof DID) if (url instanceof DID)
@ -75,10 +21,12 @@ export async function getFileInfo(
postBody = { postBody = {
url url
} }
const response = await axios.post( const response: AxiosResponse<FileMetadata[]> = await axios.post(
`${providerUri}/api/v1/services/fileinfo`, `${providerUri}/api/v1/services/fileinfo`,
postBody, postBody,
{ cancelToken } {
cancelToken
}
) )
if (!response || response.status !== 200 || !response.data) return if (!response || response.status !== 200 || !response.data) return

View File

@ -4,6 +4,7 @@ import classNames from 'classnames/bind'
import cleanupContentType from '@utils/cleanupContentType' import cleanupContentType from '@utils/cleanupContentType'
import styles from './index.module.css' import styles from './index.module.css'
import Loader from '@shared/atoms/Loader' import Loader from '@shared/atoms/Loader'
import { FileMetadata } from '@utils/provider'
const cx = classNames.bind(styles) const cx = classNames.bind(styles)

View File

@ -3,6 +3,7 @@ import { prettySize } from './utils'
import cleanupContentType from '@utils/cleanupContentType' import cleanupContentType from '@utils/cleanupContentType'
import styles from './Info.module.css' import styles from './Info.module.css'
import { useField, useFormikContext } from 'formik' import { useField, useFormikContext } from 'formik'
import { FileMetadata } from '@utils/provider'
export default function FileInfo({ export default function FileInfo({
name, name,
@ -21,7 +22,7 @@ export default function FileInfo({
return ( return (
<div className={styles.info}> <div className={styles.info}>
<h3 className={styles.url}>{file.url}</h3> {/* <h3 className={styles.url}>{file}</h3> */}
<ul> <ul>
<li>URL confirmed</li> <li>URL confirmed</li>
{file.contentLength && <li>{prettySize(+file.contentLength)}</li>} {file.contentLength && <li>{prettySize(+file.contentLength)}</li>}

View File

@ -4,7 +4,7 @@ import { toast } from 'react-toastify'
import FileInfo from './Info' import FileInfo from './Info'
import CustomInput from '../URLInput/Input' import CustomInput from '../URLInput/Input'
import { InputProps } from '@shared/Form/Input' import { InputProps } from '@shared/Form/Input'
import { fileinfo } from '@utils/provider' import { getFileInfo } from '@utils/provider'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import { getOceanConfig } from '@utils/ocean' import { getOceanConfig } from '@utils/ocean'
import { useCancelToken } from '@hooks/useCancelToken' import { useCancelToken } from '@hooks/useCancelToken'
@ -22,7 +22,7 @@ export default function FilesInput(props: InputProps): ReactElement {
async function validateUrl() { async function validateUrl() {
try { try {
setIsLoading(true) setIsLoading(true)
const checkedFile = await fileinfo( const checkedFile = await getFileInfo(
fileUrl, fileUrl,
config?.providerUri, config?.providerUri,
newCancelToken() newCancelToken()

View File

@ -34,6 +34,7 @@ import ComputeJobs from '../../../Profile/History/ComputeJobs'
import { useCancelToken } from '@hooks/useCancelToken' import { useCancelToken } from '@hooks/useCancelToken'
import { useIsMounted } from '@hooks/useIsMounted' import { useIsMounted } from '@hooks/useIsMounted'
import { SortTermOptions } from '../../../../@types/aquarius/SearchQuery' import { SortTermOptions } from '../../../../@types/aquarius/SearchQuery'
import { FileMetadata } from '@utils/provider'
export default function Compute({ export default function Compute({
dtBalance, dtBalance,

View File

@ -17,6 +17,7 @@ import { secondsToString } from '@utils/ddo'
import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute' import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute'
import styles from './Consume.module.css' import styles from './Consume.module.css'
import { useIsMounted } from '@hooks/useIsMounted' import { useIsMounted } from '@hooks/useIsMounted'
import { FileMetadata } from '@utils/provider'
const previousOrderQuery = gql` const previousOrderQuery = gql`
query PreviousOrder($id: String!, $account: String!) { query PreviousOrder($id: String!, $account: String!) {

View File

@ -2,7 +2,6 @@ import React, { ChangeEvent, ReactElement } from 'react'
import { Field, Form, FormikContextType, useFormikContext } from 'formik' import { Field, Form, FormikContextType, useFormikContext } from 'formik'
import { useOcean } from '@context/Ocean' import { useOcean } from '@context/Ocean'
import Input, { InputProps } from '@shared/Form/Input' import Input, { InputProps } from '@shared/Form/Input'
import { checkIfTimeoutInPredefinedValues } from '@utils/ddo'
import FormActions from './FormActions' import FormActions from './FormActions'
import styles from './FormEditMetadata.module.css' import styles from './FormEditMetadata.module.css'
import { FormPublishData } from '../../../Publish/_types' import { FormPublishData } from '../../../Publish/_types'

View File

@ -10,7 +10,7 @@ import { useAsset } from '@context/Asset'
import { useOcean } from '@context/Ocean' import { useOcean } from '@context/Ocean'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import Web3Feedback from '@shared/Web3Feedback' import Web3Feedback from '@shared/Web3Feedback'
import { getFileInfo } from '@utils/provider' import { FileMetadata, getFileInfo } from '@utils/provider'
import { getOceanConfig } from '@utils/ocean' import { getOceanConfig } from '@utils/ocean'
import { useCancelToken } from '@hooks/useCancelToken' import { useCancelToken } from '@hooks/useCancelToken'
import { useIsMounted } from '@hooks/useIsMounted' import { useIsMounted } from '@hooks/useIsMounted'
@ -23,7 +23,7 @@ export default function AssetActions(): ReactElement {
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>() const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>()
const [dtBalance, setDtBalance] = useState<string>() const [dtBalance, setDtBalance] = useState<string>()
const [fileMetadata, setFileMetadata] = useState<FileMetadata>(Object) const [fileMetadata, setFileMetadata] = useState<FileMetadata>()
const [fileIsLoading, setFileIsLoading] = useState<boolean>(false) const [fileIsLoading, setFileIsLoading] = useState<boolean>(false)
const isCompute = Boolean( const isCompute = Boolean(
ddo?.services.filter((service) => service.type === 'compute')[0] ddo?.services.filter((service) => service.type === 'compute')[0]

View File

@ -21,21 +21,21 @@ export default function Actions({
function handleNext(e: FormEvent) { function handleNext(e: FormEvent) {
e.preventDefault() e.preventDefault()
setFieldValue('step', values.step + 1) setFieldValue('stepCurrent', values.stepCurrent + 1)
scrollToRef.current.scrollIntoView() scrollToRef.current.scrollIntoView()
} }
function handlePrevious(e: FormEvent) { function handlePrevious(e: FormEvent) {
e.preventDefault() e.preventDefault()
setFieldValue('step', values.step - 1) setFieldValue('stepCurrent', values.stepCurrent - 1)
scrollToRef.current.scrollIntoView() scrollToRef.current.scrollIntoView()
} }
return ( return (
<footer className={styles.actions}> <footer className={styles.actions}>
{values.step > 1 && <Button onClick={handlePrevious}>Back</Button>} {values.stepCurrent > 1 && <Button onClick={handlePrevious}>Back</Button>}
{values.step < wizardSteps.length ? ( {values.stepCurrent < wizardSteps.length ? (
<Button style="primary" onClick={handleNext}> <Button style="primary" onClick={handleNext}>
Continue Continue
</Button> </Button>

View File

@ -3,12 +3,10 @@ import DebugOutput from '@shared/DebugOutput'
import styles from './index.module.css' import styles from './index.module.css'
// import { transformPublishFormToMetadata } from '@utils/metadata' // import { transformPublishFormToMetadata } from '@utils/metadata'
import { FormPublishData } from './_types' import { FormPublishData } from './_types'
import { useFormikContext } from 'formik'
export default function Debug({ export default function Debug(): ReactElement {
values const { values } = useFormikContext<FormPublishData>()
}: {
values: Partial<FormPublishData>
}): ReactElement {
const ddo = { const ddo = {
'@context': 'https://w3id.org/did/v1' '@context': 'https://w3id.org/did/v1'
// dataTokenInfo: { // dataTokenInfo: {

View File

@ -5,15 +5,11 @@ import { wizardSteps } from '../_constants'
import styles from './index.module.css' import styles from './index.module.css'
export default function Navigation(): ReactElement { export default function Navigation(): ReactElement {
const { const { values, setFieldValue }: FormikContextType<FormPublishData> =
values, useFormikContext()
errors,
touched,
setFieldValue
}: FormikContextType<FormPublishData> = useFormikContext()
function handleStepClick(step: number) { function handleStepClick(step: number) {
setFieldValue('step', step) setFieldValue('stepCurrent', step)
} }
return ( return (
@ -24,7 +20,7 @@ export default function Navigation(): ReactElement {
key={step.title} key={step.title}
onClick={() => handleStepClick(step.step)} onClick={() => handleStepClick(step.step)}
// TODO: add success class // TODO: add success class
className={values.step === step.step ? styles.current : null} className={values.stepCurrent === step.step ? styles.current : null}
> >
{step.title} {step.title}
</li> </li>

View File

@ -4,7 +4,6 @@ import Tags from '@shared/atoms/Tags'
import MetaItem from '../../Asset/AssetContent/MetaItem' import MetaItem from '../../Asset/AssetContent/MetaItem'
import FileIcon from '@shared/FileIcon' import FileIcon from '@shared/FileIcon'
import Button from '@shared/atoms/Button' import Button from '@shared/atoms/Button'
import { transformTags } from '@utils/ddo'
import NetworkName from '@shared/NetworkName' import NetworkName from '@shared/NetworkName'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -4,18 +4,19 @@ import { wizardSteps } from './_constants'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import { FormPublishData } from './_types' import { FormPublishData } from './_types'
export function Steps({ step }: { step: number }): ReactElement { export function Steps(): ReactElement {
const { chainId } = useWeb3() const { chainId, accountId } = useWeb3()
const { setFieldValue } = useFormikContext<FormPublishData>() const { values, setFieldValue } = useFormikContext<FormPublishData>()
useEffect(() => { useEffect(() => {
if (!chainId) return if (!chainId || !accountId) return
setFieldValue('chainId', chainId) setFieldValue('chainId', chainId)
}, [chainId, setFieldValue]) setFieldValue('accountId', accountId)
}, [chainId, accountId, setFieldValue])
const { component } = wizardSteps.filter( const { component } = wizardSteps.filter(
(stepContent) => stepContent.step === step (stepContent) => stepContent.step === values.stepCurrent
)[0] )[0]
return component return component

View File

@ -32,8 +32,9 @@ export const wizardSteps: StepContent[] = [
] ]
export const initialValues: FormPublishData = { export const initialValues: FormPublishData = {
step: 1, stepCurrent: 1,
chainId: 1, chainId: 1,
accountId: '',
metadata: { metadata: {
type: 'dataset', type: 'dataset',
name: '', name: '',
@ -47,9 +48,9 @@ export const initialValues: FormPublishData = {
files: [], files: [],
links: [], links: [],
dataTokenOptions: { name: '', symbol: '' }, dataTokenOptions: { name: '', symbol: '' },
timeout: 'Forever', timeout: '',
access: '', access: '',
providerUrl: '' providerUrl: 'https://provider.oceanprotocol.com'
} }
], ],
pricing: { pricing: {
@ -84,17 +85,17 @@ const validationMetadata = {
} }
const validationService = { const validationService = {
files: Yup.array<FileMetadata>() files: Yup.array<string[]>()
.required('Enter a valid URL and click "ADD FILE"') .required('Enter a valid URL and click "ADD FILE"')
.nullable(), .nullable(),
links: Yup.array<FileMetadata[]>().nullable(), links: Yup.array<string[]>().nullable(),
dataTokenOptions: Yup.object().shape({ dataTokenOptions: Yup.object().shape({
name: Yup.string(), name: Yup.string(),
symbol: Yup.string() symbol: Yup.string()
}), }),
timeout: Yup.string().required('Required'), timeout: Yup.string().required('Required'),
access: Yup.string() access: Yup.string()
.matches(/Compute|Download/g, { excludeEmptyString: true }) .matches(/compute|download/g, { excludeEmptyString: true })
.required('Required'), .required('Required'),
providerUrl: Yup.string().url().nullable() providerUrl: Yup.string().url().nullable()
} }
@ -123,8 +124,9 @@ const validationPricing = {
// export const validationSchema: Yup.SchemaOf<FormPublishData> = // export const validationSchema: Yup.SchemaOf<FormPublishData> =
export const validationSchema: Yup.SchemaOf<any> = Yup.object().shape({ export const validationSchema: Yup.SchemaOf<any> = Yup.object().shape({
step: Yup.number(), stepCurrent: Yup.number(),
chainId: Yup.number(), chainId: Yup.number(),
accountId: Yup.string(),
metadata: Yup.object().shape(validationMetadata), metadata: Yup.object().shape(validationMetadata),
services: Yup.array().of(Yup.object().shape(validationService)), services: Yup.array().of(Yup.object().shape(validationService)),
pricing: Yup.object().shape(validationPricing) pricing: Yup.object().shape(validationPricing)

View File

@ -2,7 +2,7 @@ import { DataTokenOptions } from '@hooks/usePublish'
import { ReactElement } from 'react' import { ReactElement } from 'react'
export interface FormPublishService { export interface FormPublishService {
files: string | FileMetadata[] files: string | string[]
links?: string[] links?: string[]
timeout: string timeout: string
dataTokenOptions: DataTokenOptions dataTokenOptions: DataTokenOptions
@ -14,7 +14,9 @@ export interface FormPublishService {
} }
export interface FormPublishData { export interface FormPublishData {
step: number stepCurrent: number
accountId: string
chainId: number
metadata: { metadata: {
type: 'dataset' | 'algorithm' type: 'dataset' | 'algorithm'
name: string name: string
@ -25,7 +27,6 @@ export interface FormPublishData {
} }
services: FormPublishService[] services: FormPublishService[]
pricing: PriceOptions pricing: PriceOptions
chainId: number
} }
export interface StepContent { export interface StepContent {

View File

@ -1,15 +1,8 @@
import axios, { AxiosResponse } from 'axios'
import { sha256 } from 'js-sha256' import { sha256 } from 'js-sha256'
import { import slugify from 'slugify'
dateToStringNoMS,
transformTags,
getUrlFileExtension
} from '@utils/ddo'
import { FormPublishData } from './_types' import { FormPublishData } from './_types'
function encryptMe(files: string | FileMetadata[]): string {
throw new Error('Function not implemented.')
}
export function getFieldContent( export function getFieldContent(
fieldName: string, fieldName: string,
fields: FormFieldContent[] fields: FormFieldContent[]
@ -17,15 +10,52 @@ export function getFieldContent(
return fields.filter((field: FormFieldContent) => field.name === fieldName)[0] return fields.filter((field: FormFieldContent) => field.name === fieldName)[0]
} }
export function transformPublishFormToDdo( async function getEncryptedFileUrls(
files: string[],
providerUrl: string,
did: string,
accountId: string
): Promise<string> {
try {
// https://github.com/oceanprotocol/provider/blob/v4main/API.md#encrypt-endpoint
const url = `${providerUrl}/api/v1/services/encrypt`
const response: AxiosResponse<{ encryptedDocument: string }> =
await axios.post(url, {
documentId: did,
signature: '', // TODO: add signature
publisherAddress: accountId,
document: files
})
return response?.data?.encryptedDocument
} catch (error) {
console.error('Error parsing json: ' + error.message)
}
}
function getUrlFileExtension(fileUrl: string): string {
const splittedFileUrl = fileUrl.split('.')
return splittedFileUrl[splittedFileUrl.length - 1]
}
function dateToStringNoMS(date: Date): string {
return date.toISOString().replace(/\.[0-9]{3}Z/, 'Z')
}
function transformTags(value: string): string[] {
const originalTags = value?.split(',')
const transformedTags = originalTags?.map((tag) => slugify(tag).toLowerCase())
return transformedTags
}
export async function transformPublishFormToDdo(
values: FormPublishData, values: FormPublishData,
datatokenAddress: string, datatokenAddress: string,
nftAddress: string nftAddress: string
): DDO { ): Promise<DDO> {
const did = sha256(`${nftAddress}${values.chainId}`) const { chainId, accountId, metadata, services } = values
const did = sha256(`${nftAddress}${chainId}`)
const currentTime = dateToStringNoMS(new Date()) const currentTime = dateToStringNoMS(new Date())
const { type, name, description, tags, author, termsAndConditions } = const { type, name, description, tags, author, termsAndConditions } = metadata
values.metadata
const { const {
access, access,
files, files,
@ -35,11 +65,16 @@ export function transformPublishFormToDdo(
entrypoint, entrypoint,
providerUrl, providerUrl,
timeout timeout
} = values.services[0] } = services[0]
const fileUrl = typeof files !== 'string' && files[0].url const filesEncrypted = await getEncryptedFileUrls(
files as string[],
providerUrl,
did,
accountId
)
const metadata: Metadata = { const newMetadata: Metadata = {
created: currentTime, created: currentTime,
updated: currentTime, updated: currentTime,
type, type,
@ -54,7 +89,7 @@ export function transformPublishFormToDdo(
}, },
...(type === 'algorithm' && { ...(type === 'algorithm' && {
algorithm: { algorithm: {
language: getUrlFileExtension(fileUrl), language: getUrlFileExtension(files[0]),
version: '0.1', version: '0.1',
container: { container: {
entrypoint, entrypoint,
@ -66,9 +101,9 @@ export function transformPublishFormToDdo(
}) })
} }
const service: Service = { const newService: Service = {
type: access, type: access,
files: encryptMe(files), files: filesEncrypted,
datatokenAddress, datatokenAddress,
serviceEndpoint: providerUrl, serviceEndpoint: providerUrl,
timeout, timeout,
@ -92,9 +127,9 @@ export function transformPublishFormToDdo(
'@context': ['https://w3id.org/did/v1'], '@context': ['https://w3id.org/did/v1'],
id: did, id: did,
version: '4.0.0', version: '4.0.0',
chainId: values.chainId, chainId,
metadata, metadata: newMetadata,
services: [service] services: [newService]
} }
return newDdo return newDdo

View File

@ -1,6 +1,5 @@
import React, { ReactElement, useState, useRef } from 'react' import React, { ReactElement, useState, useRef } from 'react'
import { Form, Formik, FormikState } from 'formik' import { Form, Formik, FormikState } from 'formik'
import { usePublish } from '@hooks/usePublish'
import { initialValues, validationSchema } from './_constants' import { initialValues, validationSchema } from './_constants'
import { validateDockerImage } from '@utils/docker' import { validateDockerImage } from '@utils/docker'
import { Logger, Metadata } from '@oceanprotocol/lib' import { Logger, Metadata } from '@oceanprotocol/lib'
@ -15,6 +14,7 @@ import Debug from './Debug'
import Navigation from './Navigation' import Navigation from './Navigation'
import { Steps } from './Steps' import { Steps } from './Steps'
import { FormPublishData } from './_types' import { FormPublishData } from './_types'
import { sha256 } from 'js-sha256'
const formName = 'ocean-publish-form' const formName = 'ocean-publish-form'
@ -25,7 +25,7 @@ export default function PublishPage({
}): ReactElement { }): ReactElement {
const { accountId, chainId } = useWeb3() const { accountId, chainId } = useWeb3()
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId) const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
const { publish, publishError, isLoading, publishStepText } = usePublish() // const { publish, publishError, isLoading, publishStepText } = usePublish()
const [success, setSuccess] = useState<string>() const [success, setSuccess] = useState<string>()
const [error, setError] = useState<string>() const [error, setError] = useState<string>()
const scrollToRef = useRef() const scrollToRef = useRef()
@ -35,10 +35,22 @@ export default function PublishPage({
// 1. Mint NFT & datatokens & put in pool // 1. Mint NFT & datatokens & put in pool
// const txMint = await createNftWithErc() // const txMint = await createNftWithErc()
// const { nftAddress, datatokenAddress } = txMint.logs[0].args // const { nftAddress, datatokenAddress } = txMint.logs[0].args
//
// 2. Construct and publish DDO // 2. Construct and publish DDO
// const did = sha256(`${nftAddress}${chainId}`) // const did = sha256(`${nftAddress}${chainId}`)
// const ddo = transformPublishFormToDdo(values, datatokenAddress, nftAddress) // const ddo = transformPublishFormToDdo(values, datatokenAddress, nftAddress)
// const txPublish = await publish(ddo) // const txPublish = await publish(ddo)
//
// 3. Integrity check of DDO before & after publishing
// const checksumBefore = sha256(ddo)
// const ddoFromChain = await getDdoFromChain(ddo.id)
// const ddoFromChainDecrypted = await decryptDdo(ddoFromChain)
// const checksumAfter = sha256(ddoFromChainDecrypted)
// if (checksumBefore !== checksumAfter) {
// throw new Error('DDO integrity check failed!')
// }
setSuccess('Your DDO was published successfully!') setSuccess('Your DDO was published successfully!')
} catch (error) { } catch (error) {
setError(error.message) setError(error.message)
@ -109,16 +121,12 @@ export default function PublishPage({
await handleSubmit(values) await handleSubmit(values)
}} }}
> >
{({ values }) => ( <Form className={styles.form} ref={scrollToRef}>
<> <Navigation />
<Form className={styles.form} ref={scrollToRef}> <Steps />
<Navigation /> <Actions scrollToRef={scrollToRef} />
<Steps step={values.step} /> </Form>
<Actions scrollToRef={scrollToRef} /> <Debug />
</Form>
<Debug values={values} />
</>
)}
</Formik> </Formik>
)} )}
</> </>