Publish a Data Set

Tutorial to add dataset publishing capabilities to a basic React app.

Requirements

This is a continuation of the React App Setup tutorial, so make sure you have done all the steps described in there.

  1. React App Setup

Open src/index.js from your marketplace/ folder.

Define Asset

First, let’s add the asset that we want to publish.

To do that, we need to define the asset based on the OEP-08 metadata structure. An asset can have multiple files attached to it and each file’s url value will be encrypted during the publish process. To download that file later on, this value will be decrypted during the consume process.

Let’s create a new file src/asset.js and fill it with:

const asset = {
  base: {
    name: '10 Monkey Species Small',
    dateCreated: '2012-02-01T10:55:11Z',
    author: 'Mario',
    license: 'CC0: Public Domain',
    price: '0',
    files: [
      {
        index: 0,
        contentType: 'application/zip',
        checksum: '2bf9d229d110d1976cdf85e9f3256c7f',
        checksumType: 'MD5',
        contentLength: 12057507,
        compression: 'zip',
        encoding: 'UTF-8',
        url:
          'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/training.zip'
      },
      {
        index: 1,
        contentType: 'text/txt',
        checksum: '354d19c0733c47ef3a6cce5b633116b0',
        checksumType: 'MD5',
        contentLength: 928,
        url:
          'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/monkey_labels.txt',
        resourceId: 'test'
      },
      {
        index: 2
      }
    ],
    checksum: '',
    categories: ['image'],
    tags: ['image data', 'classification', 'animals'],
    type: 'dataset',
    description: 'EXAMPLE ONLY ',
    copyrightHolder: 'Unknown',
    workExample: 'image path, id, label',
    links: [
      {
        name: 'example model',
        url:
          'https://drive.google.com/open?id=1uuz50RGiAW8YxRcWeQVgQglZpyAebgSM'
      },
      {
        name: 'example code',
        type: 'example code',
        url: 'https://github.com/slothkong/CNN_classification_10_monkey_species'
      },
      {
        url:
          'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/links/discovery/n5151.jpg',
        name: 'n5151.jpg',
        type: 'discovery'
      },
      {
        url:
          'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/links/sample/sample.zip',
        name: 'sample.zip',
        type: 'sample'
      }
    ],
    inLanguage: 'en'
  }
}

export default asset

Then import this asset definition at the top of src/index.js:

import asset from './asset'

Handle Asset Publishing

Now that we have an asset to submit, we need a function to handle it. Just before render() { let’s add this registerAsset function:

  async registerAsset() {
    try {
      const accounts = await this.state.ocean.accounts.list()
      const ddo = await this.state.ocean.assets.create(asset, accounts[0])
      console.log('Asset successfully submitted.')
      console.log(ddo)
      alert(
        'Asset successfully submitted. Look into your console to see the response DDO object.'
      )
    } catch (error) {
      console.error(error.message)
    }
  }

The last thing we need is a button to start our registration inside the render() function:

        <button onClick={() => this.registerAsset()} disabled={!web3}>
          Register asset
        </button>

Note how we disable the button when Web3 is not available to reduce user confusion. Within the Ocean Protocol flow of registering, searching, and consuming, only searching is possible without Web3.

In your browser, you should now end up like this:

React app with publish button
React app with publish button

When you click on the Register asset button, you should get four separate dialog boxes from MetaMask, in a series, i.e. the second one only appears after you accept/approve the first one, and so on.

Have a look into console.log to see the various steps of the register process. If you have no errors in your console.log, then you have successfully registered an asset.

Successful asset publishing
Successful asset publishing

Final Result

Here is the full source of src/index.js that you should have if you followed this tutorial:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { Ocean } from '@oceanprotocol/squid'
import Web3 from 'web3'
import asset from './asset'

let web3

if (window.web3) {
  web3 = new Web3(window.web3.currentProvider)
  window.ethereum.enable()
}

class App extends Component {
  state = {
    ocean: undefined,
  }

  async componentDidMount() {
    const ocean = await new Ocean.getInstance({
      web3Provider: web3,
      nodeUri: 'https://nile.dev-ocean.com',
      aquariusUri: 'https://aquarius.marketplace.dev-ocean.com',
      brizoUri: 'https://brizo.marketplace.dev-ocean.com',
      brizoAddress: '0x4aaab179035dc57b35e2ce066919048686f82972',
      secretStoreUri: 'https://secret-store.nile.dev-ocean.com',
      verbose: true
    })
    this.setState({ ocean })
    console.log('Finished loading contracts.')
  }

  async registerAsset() {
    try {
      const accounts = await this.state.ocean.accounts.list()
      const ddo = await this.state.ocean.assets.create(asset, accounts[0])
      console.log('Asset successfully submitted.')
      console.log(ddo)
      alert(
        'Asset successfully submitted. Look into your console to see the response DDO object.'
      )
    } catch (error) {
      console.error(error.message)
    }
  }

  render() {
    return (
      <div
        style={{ fontFamily: '"Fira Code", monospace', textAlign: 'center' }}
      >
        <h1>
          <span role="img" aria-label="squid">
            🦑
          </span>
          <br /> My Little Ocean
        </h1>

        {!web3 && <p>No Web3 Browser!</p>}

        <button onClick={() => this.registerAsset()} disabled={!web3}>
          Register asset
        </button>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))

Move on to Get & Use a Data Set.