1
0
mirror of https://github.com/oceanprotocol/docs.git synced 2024-11-26 19:49:26 +01:00

Merge pull request #216 from oceanprotocol/fix/react-assets

React tutorial: update asset example, code updates
This commit is contained in:
Matthias Kretschmann 2019-04-18 16:37:24 +02:00 committed by GitHub
commit 5ddc4b7899
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 143 additions and 192 deletions

View File

@ -5,60 +5,81 @@ description: 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 [React App Setup](/tutorials/react-setup/) and the [Publish a Data Set](/tutorials/react-publish-data-set/) steps.
This is a continuation of the React App Tutorial. Make sure you already did the previous steps:
Open `src/App.js` in your marketplace app.
1. [React App Setup](/tutorials/react-setup/)
2. [Publish a Data Set](/tutorials/react-publish-data-set/)
Open `src/App.js` from your `marketplace/` folder.
## Retrieve Assets
In the previous tutorial we added asset publishing. We can now search for published assets for consumption. Just after the `submitAsset()` function we can add a new function that will handle search:
```js
// src/App.js
// ...
async retrieveAssets() {
this.dbAssets = await this.ocean.assets.search("10 Monkey Species Small")
console.log(this.dbAssets)
this.search = await this.ocean.assets.search('10 Monkey Species Small')
console.log(this.search)
alert(
'Asset successfully retrieved. Look into your console to see the search response.'
)
}
// ...
```
The last thing we need is a button to start our search inside the render function just after `<button onClick={() => this.submitAsset()}>Register asset</button>`:
Now we need a button to start our search inside the render function just after `<button onClick={() => this.submitAsset()}>Register asset</button>`:
```jsx
// src/App.js
// ...
<button onClick={() => this.retrieveAssets()}>Retrieve assets</button>
// ...
```
## Consume Assets
The retrieved assets can now be consumed so in this tutorial we consume the first one. The following code goes after the `async retrieveAssets()` function.
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 `retrieveAssets()` function:
```js
// src/App.js
// ...
async consumeAsset() {
// get all accounts
const accounts = await this.ocean.accounts.list()
// get first asset
const consumeAsset = this.dbAssets[0]
const consumeAsset = this.search.results[0]
// get service we want to execute
const service = consumeAsset.findServiceByType('Access')
// order service agreement
const agreement = await this.ocean.assets.order(
consumeAsset.id,
service.serviceDefinitionId,
accounts[0]
consumeAsset.id,
service.serviceDefinitionId,
accounts[0]
)
// consume it
await this.ocean.assets.consume(
agreement,
consumeAsset.id,
service.serviceDefinitionId,
accounts[0],
''
agreement,
consumeAsset.id,
service.serviceDefinitionId,
accounts[0],
'',
0
)
}
}
// ...
```
We still need a button to start consumption. In the render function, just after the `<button onClick={()=>this.retrieveAssets()}>Retrieve assets</button>` line, add:
```jsx
// src/App.js
// ...
<button onClick={() => this.consumeAsset()}>Consume asset</button>
// ...
```
With all these buttons in place, you should see this:
@ -69,87 +90,25 @@ Tip: Before clicking the `Retrieve assets` button, it might help to reload the p
Go ahead and click the `Retrieve assets` button, and then the `Consume asset` button. Approve all the MetaMask dialog boxes.
If you have no errors in your `console.log` and can see your asset files listed, you have a working marketplace.
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.
> Note: Consuming an asset will throw an error `Requested did is not found in the keeper network`. We are currently [investigating why that is happening](https://github.com/oceanprotocol/barge/issues/144) in either squid-js or Brizo and will remove this note once we verified a fix is in place in one of those components.
## Final Result
Here is the full source of `src/App.js` that you should have if you followed this tutorial:
```jsx
// src/App.js
import React, { Component } from 'react'
import './App.css'
import { Ocean } from '@oceanprotocol/squid'
import * as Web3 from 'web3'
import Web3 from 'web3'
import asset from './asset'
const web3 = new Web3(window.web3.currentProvider)
window.ethereum.enable()
const asset = {
base: {
name: '10 Monkey Species Small',
dateCreated: '2012-02-01T10:55:11Z',
author: 'Mario',
license: 'CC0: Public Domain',
contentType: 'jpg/txt',
price: 10,
files: [
{
checksum: '2bf9d229d110d1976cdf85e9f3256c7f',
checksumType: 'MD5',
contentLength: 12057507,
url:
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/training.zip'
},
{
checksum: '354d19c0733c47ef3a6cce5b633116b0',
checksumType: 'MD5',
contentLength: 928,
url:
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/monkey_labels.txt'
},
{
url:
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/validation.zip'
}
],
checksum: '',
categories: ['image'],
tags: ['image data', 'classification', 'animals'],
type: 'dataset',
description: 'EXAMPLE ONLY ',
size: '3.1gb',
copyrightHolder: 'Unknown',
encoding: 'UTF-8',
compression: 'zip',
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'
}
}
class App extends Component {
async componentDidMount() {
this.ocean = await new Ocean.getInstance({
@ -161,25 +120,32 @@ class App extends Component {
parityUri: 'http://localhost:8545',
secretStoreUri: 'http://localhost:12001'
})
console.log('Finished loading contracts!')
console.log('Finished loading contracts.')
}
async submitAsset() {
const accounts = await this.ocean.accounts.list()
const ddo = await this.ocean.assets.create(asset, accounts[0])
alert('Asset successfully submitted: ', JSON.stringify(ddo))
console.log('Asset successfully submitted.')
console.log(ddo)
alert(
'Asset successfully submitted. Look into your console to see the response DDO object.'
)
}
async retrieveAssets() {
this.dbAssets = await this.ocean.assets.search('10 Monkey Species Small')
console.log(this.dbAssets)
this.search = await this.ocean.assets.search('10 Monkey Species Small')
console.log(this.search)
alert(
'Asset successfully retrieved. Look into your console to see the search response.'
)
}
async consumeAsset() {
// get all accounts
const accounts = await this.ocean.accounts.list()
// get first asset
const consumeAsset = this.dbAssets[0]
const consumeAsset = this.search.results[0]
// get service we want to execute
const service = consumeAsset.findServiceByType('Access')
// order service agreement
@ -194,7 +160,8 @@ class App extends Component {
consumeAsset.id,
service.serviceDefinitionId,
accounts[0],
''
'',
0
)
}
@ -203,6 +170,7 @@ class App extends Component {
<div className="App App-header">
<h1>Marketplace app</h1>
<button onClick={() => this.submitAsset()}>Register asset</button>
<hr />
<button onClick={() => this.retrieveAssets()}>Retrieve assets</button>
<button onClick={() => this.consumeAsset()}>Consume asset</button>
</div>

View File

@ -7,15 +7,20 @@ description: Tutorial to add dataset publishing capabilities to a basic React ap
This is a continuation of the [React App Setup](/tutorials/react-setup/) tutorial, so make sure you have done all the steps described in there.
Open `src/App.js` in your marketplace app from the [React App Setup](/tutorials/react-setup/) tutorial.
1. [React App Setup](/tutorials/react-setup/)
Open `src/App.js` from your `marketplace/` folder.
## Define Asset
First, let's add the [asset](/concepts/terminology/#asset-or-data-asset) that we want to publish.
To do that, we need to add the following code after `window.ethereum.enable()` line, defining our asset based on the [OEP-08](https://github.com/oceanprotocol/OEPs/tree/master/8) metadata structure:
To do that, we need to define the asset based on the [OEP-08](https://github.com/oceanprotocol/OEPs/tree/master/8) 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:
```js
// src/asset.js
const asset = {
base: {
name: '10 Monkey Species Small',
@ -26,22 +31,28 @@ const asset = {
price: 10,
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'
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/monkey_labels.txt',
resourceId: 'test'
},
{
url:
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/validation.zip'
index: 2
}
],
checksum: '',
@ -49,10 +60,7 @@ const asset = {
tags: ['image data', 'classification', 'animals'],
type: 'dataset',
description: 'EXAMPLE ONLY ',
size: '3.1gb',
copyrightHolder: 'Unknown',
encoding: 'UTF-8',
compression: 'zip',
workExample: 'image path, id, label',
links: [
{
@ -81,111 +89,68 @@ const asset = {
inLanguage: 'en'
}
}
export default asset
```
Then import this asset definition at the top of `src/App.js`:
```js
// src/App.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 function:
```js
```jsx
// src/App.js
// ...
async submitAsset() {
const accounts = await this.ocean.accounts.list()
const ddo = await this.ocean.assets.create(asset, accounts[0])
alert('Asset successfully submitted: ', JSON.stringify(ddo))
console.log('Asset successfully submitted.')
console.log(ddo)
alert(
'Asset successfully submitted. Look into your console to see the response DDO object.'
)
}
// ...
```
The last thing we need is a button to start our registration inside the render function just after `<h1>Marketplace app</h1>`:
```jsx
// src/App.js
// ...
<button onClick={() => this.submitAsset()}>Register asset</button>
// ...
```
Tip: Before clicking the `Register asset` button, it might help to reload the page.
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.
If you have no errors in your `console.log`, then you have successfully registered an asset.
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.
## Final Result
Here is the full source of `src/App.js` that you should have if you followed this tutorial:
```jsx
// src/App.js
import React, { Component } from 'react'
import './App.css'
import { Ocean } from '@oceanprotocol/squid'
import * as Web3 from 'web3'
import Web3 from 'web3'
import asset from './asset'
const web3 = new Web3(window.web3.currentProvider)
window.ethereum.enable()
const asset = {
base: {
name: '10 Monkey Species Small',
dateCreated: '2012-02-01T10:55:11Z',
author: 'Mario',
license: 'CC0: Public Domain',
contentType: 'jpg/txt',
price: 10,
files: [
{
checksum: '2bf9d229d110d1976cdf85e9f3256c7f',
checksumType: 'MD5',
contentLength: 12057507,
url:
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/training.zip'
},
{
checksum: '354d19c0733c47ef3a6cce5b633116b0',
checksumType: 'MD5',
contentLength: 928,
url:
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/monkey_labels.txt'
},
{
url:
'https://s3.amazonaws.com/datacommons-seeding-us-east/10_Monkey_Species_Small/assets/validation.zip'
}
],
checksum: '',
categories: ['image'],
tags: ['image data', 'classification', 'animals'],
type: 'dataset',
description: 'EXAMPLE ONLY ',
size: '3.1gb',
copyrightHolder: 'Unknown',
encoding: 'UTF-8',
compression: 'zip',
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'
}
}
class App extends Component {
async componentDidMount() {
this.ocean = await new Ocean.getInstance({
@ -197,13 +162,17 @@ class App extends Component {
parityUri: 'http://localhost:8545',
secretStoreUri: 'http://localhost:12001'
})
console.log('Finished loading contracts!')
console.log('Finished loading contracts.')
}
async submitAsset() {
const accounts = await this.ocean.accounts.list()
const ddo = await this.ocean.assets.create(asset, accounts[0])
alert('Asset successfully submitted: ', JSON.stringify(ddo))
console.log('Asset successfully submitted.')
console.log(ddo)
alert(
'Asset successfully submitted. Look into your console to see the response DDO object.'
)
}
render() {

View File

@ -7,20 +7,28 @@ description: This tutorial shows how you can build a basic [React](https://react
- `Node.js` >= 10 is installed. You can check using `node -v`
- `npm` >= 5.2 is installed. You can check using `npm -v`
- Git clone the [oceanprotocol/barge](https://github.com/oceanprotocol/barge) repository, then in that directory:
- [Docker](https://www.docker.com/products/docker-desktop) & [Docker Compose](https://docs.docker.com/compose/install/)
- A Web3 capable browser, like Firefox/Chrome with [MetaMask](https://metamask.io) installed
- `Spree`, a local Ocean test network
- (Optional) If you want to use Azure Storage or Amazon S3 storage, then go through the tutorials to set those up: [Azure](/tutorials/azure-for-brizo/) or [Amazon](/tutorials/amazon-s3-for-brizo/). Note that if you're using Azure Storage, you must edit the `barge/brizo.env` file and set all `AZURE_`... values.
- Git clone the [oceanprotocol/barge](https://github.com/oceanprotocol/barge) repository, then in that directory:
- (Optional but recommended) Clean out all your old Docker stuff using `docker system prune --all --volumes`
- Use Barge to run a local Spree Testnet:
- Use the startup script in Barge to run a [local Spree Testnet](https://docs.oceanprotocol.com/concepts/testnets/#a-spree-testnet-for-local-development):
```bash
export KEEPER_VERSION=v0.9.1
export AQUARIUS_VERSION=v0.2.2
export BRIZO_VERSION=v0.3.5
./start_ocean.sh --latest --no-pleuston --local-spree-node
export KEEPER_VERSION=v0.9.1 && \
export AQUARIUS_VERSION=v0.2.2 && \
export BRIZO_VERSION=v0.3.5 && \
./start_ocean.sh --no-pleuston
```
- Once your local Spree network is running, [get some Spree Ether](/tutorials/get-ether-and-ocean-tokens/#get-ether-for-a-local-spree-testnet) in a local account managed by MetaMask.
- Note that compiling and deploying the contracts in your local Docker network takes some time so it can take a few minutes until the network is ready to be interacted with. That usually is the case once `keeper-contracts_1` container doesn't show any messages anymore.
- [Some `Spree` Ether](/tutorials/get-ether-and-ocean-tokens/#get-ether-for-a-local-spree-testnet) in your MetaMask account. You can execute this, replacing `<YOUR ADDRESS>` with your MetaMask account address:
```bash
curl --data '{"jsonrpc":"2.0","method":"personal_sendTransaction","params":[{"from":"0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e","to":"<YOUR ADDRESS>","value":"0x7FFFFFFFFFFFFFFFFFF"}, "node0"],"id":0}' -H "Content-Type: application/json" -X POST localhost:8545
```
## New Create React App
@ -30,11 +38,11 @@ First, kickstart your new React app by creating a boilerplate with Create React
npx create-react-app marketplace
```
This will create a folder named `marketplace` with a boilerplate React app. Go into that new folder and add the Ocean Protocol JavaScript library and Web3 packages to the app's dependencies:
This will create a folder named `marketplace` with a boilerplate React app. Go into that new folder and add the [Ocean Protocol JavaScript library](https://github.com/oceanprotocol/squid-js) to the app's dependencies:
```bash
cd marketplace/
npm install @oceanprotocol/squid@0.5.5 web3
npm install @oceanprotocol/squid@0.5.6
```
At this point you can already run `npm start` which starts the app in your browser at [localhost:3000](http://localhost:3000):
@ -46,6 +54,7 @@ At this point you can already run `npm start` which starts the app in your brows
Let's make it ours, open `src/App.js` and replace the whole source with:
```jsx
// src/App.js
import React, { Component } from 'react'
import './App.css'
@ -65,8 +74,9 @@ export default App
Below the `import './App.css'` line, let's import the packages we installed, set up web3 and unlock MetaMask accounts (if locked):
```js
// src/App.js
import { Ocean } from '@oceanprotocol/squid'
import * as Web3 from 'web3'
import Web3 from 'web3'
const web3 = new Web3(window.web3.currentProvider)
window.ethereum.enable()
@ -77,7 +87,7 @@ After those steps you should see this, and MetaMask should have asked you to all
![React App 02](images/react-app-02.png)
![React App 03](images/react-app-03.png)
Note: If you see an error like `inpage.js:1 MetaMask - RPC Error: Internal JSON-RPC error.` in your `console.log`, don't worry about it. It's a MetaMask thing.
> Note: If you see an error like `inpage.js:1 MetaMask - RPC Error: Internal JSON-RPC error.` in your `console.log`, don't worry about it. It's a MetaMask thing.
## Create Ocean Instance
@ -86,18 +96,21 @@ Now that we are successfully connected with Web3, we can set up our Ocean instan
At the beginning of your component (i.e. right after the `class App extends Component {` line), create a new Ocean instance with all configuration within the `componentDidMount` lifecycle method. All Ocean Protocol operations can be executed from this Ocean instance.
```js
// src/App.js
//...
async componentDidMount() {
this.ocean = await new Ocean.getInstance({
web3Provider: web3,
nodeUri: "http://localhost:8545",
aquariusUri: "http://localhost:5000",
brizoUri: "http://localhost:8030",
brizoAddress: "0x00bd138abd70e2f00903268f3db08f2d25677c9e",
parityUri: "http://localhost:8545",
secretStoreUri: "http://localhost:12001"
nodeUri: 'http://localhost:8545',
aquariusUri: 'http://localhost:5000',
brizoUri: 'http://localhost:8030',
brizoAddress: '0x00bd138abd70e2f00903268f3db08f2d25677c9e',
parityUri: 'http://localhost:8545',
secretStoreUri: 'http://localhost:12001'
})
console.log("Finished loading contracts!")
console.log('Finished loading contracts.')
}
//...
```
## Final Result
@ -109,10 +122,11 @@ That's it, if you have no errors in your `console.log` then you have successfull
Here is the full source of `src/App.js` that you should have if you followed this tutorial:
```jsx
// src/App.js
import React, { Component } from 'react'
import './App.css'
import { Ocean } from '@oceanprotocol/squid'
import * as Web3 from 'web3'
import Web3 from 'web3'
const web3 = new Web3(window.web3.currentProvider)
window.ethereum.enable()
@ -128,7 +142,7 @@ class App extends Component {
parityUri: 'http://localhost:8545',
secretStoreUri: 'http://localhost:12001'
})
console.log('Finished loading contracts!')
console.log('Finished loading contracts.')
}
render() {

2
external/squid-js vendored

@ -1 +1 @@
Subproject commit 9545a95b7f090ef195f67b65d94b3c77f8ec9e26
Subproject commit 4432ecb4a635ec36eab264193c8cdfc805c77409