diff --git a/docs/README_marketplace_flow.md b/docs/README_marketplace_flow.md new file mode 100644 index 00000000..9aca0e18 --- /dev/null +++ b/docs/README_marketplace_flow.md @@ -0,0 +1,175 @@ +# Quickstart: Marketplace Flow + +This batteries-included flow includes metadata, multiple services for one datatoken, and compute-to-data. + +It focuses on Alice's experience as a publisher, and Bob's experience as a buyer & consumer. The rest are services used by Alice and Bob. + +Here's the steps. +1. Initialize services +1. Alice publishes assets for data services (= publishes a datatoken contract and metadata) +1. Alice mints 100 tokens +1. Alice allows marketplace to sell her datatokens +1. Marketplace posts asset for sale +1. Value swap: Bob buys datatokens from marketplace +1. Bob uses a service he just purchased (download) + +Let's go through each step. + +## 0. Installation + +If you haven't installed yet: +```bash +npm i @oceanprotocol/lib +``` + +## 1. Initialize services + +This quickstart treats the publisher service, ganache-cli, metadata store, and marketplace as +externally-run services. For convenience, we run barge locally in default settings. + +```bash +git clone https://github.com/oceanprotocol/barge.git +cd barge/ +git checkout v3 +export PROVIDER_VERSION=phase2 +./start_ocean.sh --no-dashboard +``` + +## 2. Alice publishes assets for data services (= publishes a datatoken contract) + +1. Create DataToken +```javascript +import { TestContractHandler } from '../TestContractHandler' +import { DataTokens } from '../../src/datatokens/Datatokens' +import { Ocean } from '../../src/ocean/Ocean' +const Web3 = require('web3') +const web3 = new Web3('http://127.0.0.1:8545') +const factory = require('@oceanprotocol/contracts/artifacts/development/Factory.json') +const datatokensTemplate = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json') + +// Alice's config +const config = { + metadataStoreUri: 'http://aquarius:5000', + providerUri: 'http://localhost:8030', + nodeUri: `http://localhost:${process.env.ETH_PORT || 8545}`, + verbose: LogLevel.Error, + web3Provider: web3, + factoryAddress: '0x123456789...' +} +const ocean = await Ocean.getInstance(config) +const alice = (await ocean.accounts.list())[0] + +datatoken = new DataTokens( + config.factoryAddress, + factory.abi, + datatokensTemplate.abi, + web3 + ) +const data = { t: 1, url: ocean.config.metadataStoreUri } +const blob = JSON.stringify(data) + +const dataTokenAddress = await datatoken.create(blob, alice.getId()) + +``` +2. Publish asset(s) + +```javascript +const asset = { + main: { + type: 'dataset', + name: 'test-dataset', + dateCreated: new Date(Date.now()).toISOString().split('.')[0] + 'Z', // remove milliseconds + author: 'oceanprotocol-team', + license: 'MIT', + files: [ + { + url: + 'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt', + checksum: 'efb2c764274b745f5fc37f97c6b0e761', + contentLength: '4535431', + contentType: 'text/csv', + encoding: 'UTF-8', + compression: 'zip' + } + ] + } + } + +// create a service +service1 = await ocean.assets.createAccessServiceAttributes( + alice, + 10, // set the price in datatoken + new Date(Date.now()).toISOString().split('.')[0] + 'Z', // publishedDate + 0 // timeout +) + +// publish asset +const ddo = await ocean.assets.create(asset, alice, [downloadService], dataTokenAddress) + +const did = ddo.id +``` + +## 3. Alice mints 100 tokens + +```javascript +await datatoken.mint(tokenAddress, alice.getId(), 100) +``` + +## 4. Alice allows marketplace to sell her datatokens + +```javascript +await datatoken.approve( + dataTokenAddress, + '0x068ed00cf0441e4829d9784fcbe7b9e26d4bd8d0', // marketplace address, + 20, // marketplaceAllowance + alice.getId() +) +``` + +## 5. Marketplace posts asset for sale +Now, you're the marketplace:) + +```javascript + +// Market's config +const marketOcean = await Ocean.getInstance(config) +const marketplace = (await ocean.accounts.list())[1] + +const asset = await ocean.assets.resolve(ddo.id) +const accessService = await ocean.assets.getServiceByType(asset.id, 'access') +price = 20 // in USD per dataToken +assert(accessService.attributes.main.cost * price === 200) +``` + +## 6. Value swap: Bob buys datatokens from marketplace + +```javascript +// Not shown: in marketplace GUI, Bob uses Stripe to send USD to marketplace (or other methods / currencies). + +``` + +## 7. Bob uses a service he just purchased (download) +Now, you're Bob:) + +```javascript +const accessService = await ocean.assets.getServiceByType(asset.id, 'access') +const bob = (await ocean.accounts.list())[2] +await ocean.assets.order(ddo.id, accessService.type, bob.getId()).then(async (res: string) => { + res = JSON.parse(res) + return await datatoken.transfer( + res['dataToken'], + res['to'], + res['numTokens'], + res['from'] + ) + }).then(async (tx) => { + await ocean.assets.download( + ddo.id, + tx.transactionHash, + dataTokenAddress, + bob, + '~/my-datasets' + ) + }) + +``` \ No newline at end of file