Get & Use a Data Set

Tutorial to get and use a data set in a basic React app.

Requirements

This is a continuation of the React App Tutorial. Make sure you already did the previous steps:

  1. React App Setup
  2. Publish a Data Set

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

Search Assets

In the previous tutorial we added asset publishing. We can now search for published assets for consumption.

We will store the search results in the local component state so we have to set its initial state first:

  state = {
    ocean: undefined,
    results: []
  }

Just after the registerAsset() function we add a new searchAssets function that will handle search:

  async searchAssets() {
    try {
      const search = await this.state.ocean.assets.search(
        '10 Monkey Species Small'
      )
      this.setState({ results: search.results })
      console.log(search)
      alert(
        'Asset successfully retrieved. Look into your console to see the search response.'
      )
    } catch (error) {
      console.error(error.message)
    }
  }

Now we need a button to start our search inside the render() function, just after the Register asset button:

        <hr />
        <button onClick={() => this.searchAssets()}>Search assets</button>

Consume Asset

Consuming means downloading one or multiple files attached to an asset. During that process the initial url value we added during the publish process for each file will be decrpyted and the file can be downloaded.

With the following code we start the consume process with the first search result, then go on to download its first attached file. Put it after the searchAssets() function:

  async consumeAsset() {
    try {
      // get all accounts
      const accounts = await this.state.ocean.accounts.list()
      // get first asset from search results
      const consumeAsset = this.state.results[0]
      // get service we want to execute
      const service = consumeAsset.findServiceByType('Access')
      // order service agreement
      const agreement = await this.state.ocean.assets.order(
        consumeAsset.id,
        service.serviceDefinitionId,
        accounts[0]
      )
      // consume it
      await this.state.ocean.assets.consume(
        agreement,
        consumeAsset.id,
        service.serviceDefinitionId,
        accounts[0],
        '',
        0
      )
    } catch (error) {
      console.error(error.message)
    }
  }

We still need a button to start consumption. In the render function, just after the Search assets button, add:

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

With all these buttons in place, you should see this:

React app with all actions in place
React app with all actions in place

Go ahead and click the Search assets button, and then the Consume asset button. Approve all the MetaMask dialog boxes.

Have a look into console.log to see the various steps of the search and consume process. If you have no errors in your console.log and can see your asset files listed, you have a working marketplace.

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,
    results: []
  }

  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',
      // local Spree connection
      // nodeUri: 'http://localhost:8545',
      // aquariusUri: 'http://aquarius:5000',
      // brizoUri: 'http://localhost:8030',
      // brizoAddress: '0x00bd138abd70e2f00903268f3db08f2d25677c9e',
      // secretStoreUri: 'http://localhost:12001',
      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)
    }
  }

  async searchAssets() {
    try {
      const search = await this.state.ocean.assets.search(
        '10 Monkey Species Small'
      )
      this.setState({ results: search.results })
      console.log(search)
      alert(
        'Asset successfully retrieved. Look into your console to see the search response.'
      )
    } catch (error) {
      console.error(error.message)
    }
  }

  async consumeAsset() {
    try {
      // get all accounts
      const accounts = await this.state.ocean.accounts.list()
      // get first asset from search results
      const consumeAsset = this.state.results[0]
      // get service we want to execute
      const service = consumeAsset.findServiceByType('Access')
      // order service agreement
      const agreement = await this.state.ocean.assets.order(
        consumeAsset.id,
        service.serviceDefinitionId,
        accounts[0]
      )
      // consume it
      await this.state.ocean.assets.consume(
        agreement,
        consumeAsset.id,
        service.serviceDefinitionId,
        accounts[0],
        '',
        0
      )
    } 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>
        <hr />
        <button onClick={() => this.searchAssets()}>Search assets</button>
        <button onClick={() => this.consumeAsset()} disabled={!web3}>
          Consume asset
        </button>
      </div>
    )
  }
}

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

Git repository and CodeSandbox

All code snippets in this tutorial are sourced from the oceanprotocol/react-tutorial GitHub repository:

react-tutorial

🦄🦑 React + web3.js + squid.js interacting in the most minimal way with Ocean Protocol

The final source of this tutorial is also available as a CodeSandbox:

Edit react-tutorial