From 1055ef991ca52cd9d7650480b3d996605ce42d3d Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 21 Apr 2022 15:45:11 +0200 Subject: [PATCH 1/6] Creating script to generate readme guide --- CodeExamples.md | 328 +++++++++++++++++++++++++++++ package.json | 3 +- scripts/createGuide.sh | 6 + test/integration/ReameFlow.test.ts | 328 +++++++++++++++++++++++++++++ 4 files changed, 664 insertions(+), 1 deletion(-) create mode 100644 CodeExamples.md create mode 100755 scripts/createGuide.sh create mode 100644 test/integration/ReameFlow.test.ts diff --git a/CodeExamples.md b/CodeExamples.md new file mode 100644 index 00000000..c60a9132 --- /dev/null +++ b/CodeExamples.md @@ -0,0 +1,328 @@ +# Ocean.js Code Examples + +Start by importing all of the necessary dependencies + +```Typescript +import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' +import { assert } from 'chai' +import { SHA256 } from 'crypto-js' +import { AbiItem } from 'web3-utils' +import { + ValidateMetadata, + DDO, + Erc20CreateParams, + PoolCreationParams, + FreCreationParams, + DispenserCreationParams +} from '../../src/@types' +import { web3, getTestConfig, getAddresses } from '../config' +import { + Config, + ProviderInstance, + Aquarius, + NftFactory, + NftCreateData, + getHash, + ZERO_ADDRESS, + Nft +} from '../../src' +``` + +let nft: Nft +let factory: NftFactory +let accounts: string[] + +const files = [ + { + type: 'url', + url: 'https://raw.githubusercontent.com/oceanprotocol/testdatasets/main/shs_dataset_test.txt', + method: 'GET' + } +] +const genericAsset: DDO = { + '@context': ['https://w3id.org/did/v1'], + id: 'testFakeDid', + version: '4.0.0', + chainId: 4, + nftAddress: '0x0', + metadata: { + created: '2021-12-20T14:35:20Z', + updated: '2021-12-20T14:35:20Z', + name: 'dataset-name', + type: 'dataset', + description: 'Ocean protocol test dataset description', + author: 'oceanprotocol-team', + license: 'MIT', + tags: ['white-papers'], + additionalInformation: { 'test-key': 'test-value' }, + links: ['http://data.ceda.ac.uk/badc/ukcp09/'] + }, + services: [ + { + id: 'testFakeId', + type: 'access', + description: 'Download service', + files: '', + datatokenAddress: '0xa15024b732A8f2146423D14209eFd074e61964F3', + serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', + timeout: 0 + } + ] +} + +describe('Publish tests', async () => { + let config: Config + let addresses: any + let aquarius: Aquarius + let providerUrl: any + + before(async () => { + config = await getTestConfig(web3) + addresses = getAddresses() + aquarius = new Aquarius(config.metadataCacheUri) + providerUrl = config.providerUri + }) + + it('initialise testes classes', async () => { + nft = new Nft(web3) + factory = new NftFactory(addresses.ERC721Factory, web3) + accounts = await web3.eth.getAccounts() + const daiContract = new web3.eth.Contract( + MockERC20.abi as AbiItem[], + addresses.MockDAI + ) + await daiContract.methods + .approve(addresses.ERC721Factory, web3.utils.toWei('100000')) + .send({ from: accounts[0] }) + }) + + it('should publish a dataset with pool (create NFT + ERC20 + pool) and with Metdata proof', async () => { + const poolDdo: DDO = { ...genericAsset } + const nftParams: NftCreateData = { + name: 'testNftPool', + symbol: 'TSTP', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: accounts[0] + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: accounts[0], + mpFeeAddress: ZERO_ADDRESS + } + const poolParams: PoolCreationParams = { + ssContract: addresses.Staking, + baseTokenAddress: addresses.MockDAI, + baseTokenSender: addresses.ERC721Factory, + publisherAddress: accounts[0], + marketFeeCollector: accounts[0], + poolTemplateAddress: addresses.poolTemplate, + rate: '1', + baseTokenDecimals: 18, + vestingAmount: '10000', + vestedBlocks: 2500000, + initialBaseTokenLiquidity: '2000', + swapFeeLiquidityProvider: '0.001', + swapFeeMarketRunner: '0.001' + } + const bundleNFT = await factory.createNftErc20WithPool( + accounts[0], + nftParams, + erc20Params, + poolParams + ) + + const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] + const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] + const poolAdress = bundleNFT.events.NewPool.returnValues[0] + + const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) + + poolDdo.metadata.name = 'test-dataset-pool' + poolDdo.services[0].files = await encryptedFiles + poolDdo.services[0].datatokenAddress = datatokenAddress + + poolDdo.nftAddress = nftAddress + const chain = await web3.eth.getChainId() + poolDdo.chainId = chain + poolDdo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) + + const AssetValidation: ValidateMetadata = await aquarius.validate(poolDdo) + assert(AssetValidation.valid === true, 'Published asset is not valid') + + const encryptedDdo = await ProviderInstance.encrypt(poolDdo, providerUrl) + const encryptedResponse = await encryptedDdo + const metadataHash = getHash(JSON.stringify(poolDdo)) + // just to make sure that our hash matches one computed by aquarius + assert(AssetValidation.hash === '0x' + metadataHash, 'Metadata hash is a missmatch') + const tx = await nft.setMetadata( + nftAddress, + accounts[0], + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash, + [AssetValidation.proof] + ) + + const resolvedDDO = await aquarius.waitForAqua(poolDdo.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + }) + + it('should publish a dataset with fixed price (create NFT + ERC20 + fixed price) with an explicit empty Metadata Proof', async () => { + const fixedPriceDdo: DDO = { ...genericAsset } + const nftParams: NftCreateData = { + name: 'testNftFre', + symbol: 'TSTF', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: accounts[0] + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: accounts[0], + mpFeeAddress: ZERO_ADDRESS + } + + const fixedPriceParams: FreCreationParams = { + fixedRateAddress: addresses.FixedPrice, + baseTokenAddress: addresses.MockDAI, + owner: accounts[0], + marketFeeCollector: accounts[0], + baseTokenDecimals: 18, + datatokenDecimals: 18, + fixedRate: '1', + marketFee: '0', + allowedConsumer: accounts[0], + withMint: false + } + + const bundleNFT = await factory.createNftErc20WithFixedRate( + accounts[0], + nftParams, + erc20Params, + fixedPriceParams + ) + + const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] + const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] + const fixedPrice = bundleNFT.events.NewFixedRate.returnValues[0] + + const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) + + fixedPriceDdo.metadata.name = 'test-dataset-fixedPrice' + fixedPriceDdo.services[0].files = await encryptedFiles + fixedPriceDdo.services[0].datatokenAddress = datatokenAddress + + fixedPriceDdo.nftAddress = nftAddress + const chain = await web3.eth.getChainId() + fixedPriceDdo.chainId = chain + fixedPriceDdo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) + + const isAssetValid: ValidateMetadata = await aquarius.validate(fixedPriceDdo) + assert(isAssetValid.valid === true, 'Published asset is not valid') + + const encryptedDdo = await ProviderInstance.encrypt(fixedPriceDdo, providerUrl) + const encryptedResponse = await encryptedDdo + const metadataHash = getHash(JSON.stringify(fixedPriceDdo)) + // this is publishing with an explicit empty metadataProofs + const res = await nft.setMetadata( + nftAddress, + accounts[0], + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash, + [] + ) + const resolvedDDO = await aquarius.waitForAqua(fixedPriceDdo.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + }) + + it('should publish a dataset with dispenser (create NFT + ERC20 + dispenser) with no defined MetadataProof', async () => { + const dispenserDdo: DDO = { ...genericAsset } + const nftParams: NftCreateData = { + name: 'testNftDispenser', + symbol: 'TSTD', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: accounts[0] + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: accounts[0], + mpFeeAddress: ZERO_ADDRESS + } + + const dispenserParams: DispenserCreationParams = { + dispenserAddress: addresses.Dispenser, + maxTokens: '1', + maxBalance: '1', + withMint: true, + allowedSwapper: ZERO_ADDRESS + } + + const bundleNFT = await factory.createNftErc20WithDispenser( + accounts[0], + nftParams, + erc20Params, + dispenserParams + ) + + const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] + const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] + const dispenserAddress = bundleNFT.events.DispenserCreated.returnValues[0] + + const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) + dispenserDdo.metadata.name = 'test-dataset-dispenser' + dispenserDdo.services[0].files = await encryptedFiles + dispenserDdo.services[0].datatokenAddress = datatokenAddress + + dispenserDdo.nftAddress = nftAddress + const chain = await web3.eth.getChainId() + dispenserDdo.chainId = chain + dispenserDdo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) + + const isAssetValid: ValidateMetadata = await aquarius.validate(dispenserDdo) + assert(isAssetValid.valid === true, 'Published asset is not valid') + + const encryptedDdo = await ProviderInstance.encrypt(dispenserDdo, providerUrl) + const encryptedResponse = await encryptedDdo + const metadataHash = getHash(JSON.stringify(dispenserDdo)) + // this is publishing with any explicit metadataProofs + const res = await nft.setMetadata( + nftAddress, + accounts[0], + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash + ) + const resolvedDDO = await aquarius.waitForAqua(dispenserDdo.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + }) +}) diff --git a/package.json b/package.json index 93955a61..b4513c96 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "test:integration": "npm run mocha -- 'test/integration/**/*.test.ts'", "test:provider": "npm run mocha -- 'test/integration/Provider.test.ts'", "test:compute": "npm run mocha -- 'test/integration/ComputeFlow.test.ts'", - "test:integration:cover": "nyc --report-dir coverage/integration --no-clean npm run test:integration" + "test:integration:cover": "nyc --report-dir coverage/integration --no-clean npm run test:integration", + "create:guide": "chmod +x ./scripts/createGuide.sh && ./scripts/createGuide.sh" }, "repository": { "type": "git", diff --git a/scripts/createGuide.sh b/scripts/createGuide.sh new file mode 100755 index 00000000..23e89323 --- /dev/null +++ b/scripts/createGuide.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Create markdown file +cp test/integration/ReameFlow.test.ts CodeExamples.md + +# Replace comments +sed -i 's/\/\/\/ //' CodeExamples.md \ No newline at end of file diff --git a/test/integration/ReameFlow.test.ts b/test/integration/ReameFlow.test.ts new file mode 100644 index 00000000..e856ee99 --- /dev/null +++ b/test/integration/ReameFlow.test.ts @@ -0,0 +1,328 @@ +/// # Ocean.js Code Examples + +/// Start by importing all of the necessary dependencies + +/// ```Typescript +import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' +import { assert } from 'chai' +import { SHA256 } from 'crypto-js' +import { AbiItem } from 'web3-utils' +import { + ValidateMetadata, + DDO, + Erc20CreateParams, + PoolCreationParams, + FreCreationParams, + DispenserCreationParams +} from '../../src/@types' +import { web3, getTestConfig, getAddresses } from '../config' +import { + Config, + ProviderInstance, + Aquarius, + NftFactory, + NftCreateData, + getHash, + ZERO_ADDRESS, + Nft +} from '../../src' +/// ``` + +let nft: Nft +let factory: NftFactory +let accounts: string[] + +const files = [ + { + type: 'url', + url: 'https://raw.githubusercontent.com/oceanprotocol/testdatasets/main/shs_dataset_test.txt', + method: 'GET' + } +] +const genericAsset: DDO = { + '@context': ['https://w3id.org/did/v1'], + id: 'testFakeDid', + version: '4.0.0', + chainId: 4, + nftAddress: '0x0', + metadata: { + created: '2021-12-20T14:35:20Z', + updated: '2021-12-20T14:35:20Z', + name: 'dataset-name', + type: 'dataset', + description: 'Ocean protocol test dataset description', + author: 'oceanprotocol-team', + license: 'MIT', + tags: ['white-papers'], + additionalInformation: { 'test-key': 'test-value' }, + links: ['http://data.ceda.ac.uk/badc/ukcp09/'] + }, + services: [ + { + id: 'testFakeId', + type: 'access', + description: 'Download service', + files: '', + datatokenAddress: '0xa15024b732A8f2146423D14209eFd074e61964F3', + serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', + timeout: 0 + } + ] +} + +describe('Publish tests', async () => { + let config: Config + let addresses: any + let aquarius: Aquarius + let providerUrl: any + + before(async () => { + config = await getTestConfig(web3) + addresses = getAddresses() + aquarius = new Aquarius(config.metadataCacheUri) + providerUrl = config.providerUri + }) + + it('initialise testes classes', async () => { + nft = new Nft(web3) + factory = new NftFactory(addresses.ERC721Factory, web3) + accounts = await web3.eth.getAccounts() + const daiContract = new web3.eth.Contract( + MockERC20.abi as AbiItem[], + addresses.MockDAI + ) + await daiContract.methods + .approve(addresses.ERC721Factory, web3.utils.toWei('100000')) + .send({ from: accounts[0] }) + }) + + it('should publish a dataset with pool (create NFT + ERC20 + pool) and with Metdata proof', async () => { + const poolDdo: DDO = { ...genericAsset } + const nftParams: NftCreateData = { + name: 'testNftPool', + symbol: 'TSTP', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: accounts[0] + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: accounts[0], + mpFeeAddress: ZERO_ADDRESS + } + const poolParams: PoolCreationParams = { + ssContract: addresses.Staking, + baseTokenAddress: addresses.MockDAI, + baseTokenSender: addresses.ERC721Factory, + publisherAddress: accounts[0], + marketFeeCollector: accounts[0], + poolTemplateAddress: addresses.poolTemplate, + rate: '1', + baseTokenDecimals: 18, + vestingAmount: '10000', + vestedBlocks: 2500000, + initialBaseTokenLiquidity: '2000', + swapFeeLiquidityProvider: '0.001', + swapFeeMarketRunner: '0.001' + } + const bundleNFT = await factory.createNftErc20WithPool( + accounts[0], + nftParams, + erc20Params, + poolParams + ) + + const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] + const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] + const poolAdress = bundleNFT.events.NewPool.returnValues[0] + + const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) + + poolDdo.metadata.name = 'test-dataset-pool' + poolDdo.services[0].files = await encryptedFiles + poolDdo.services[0].datatokenAddress = datatokenAddress + + poolDdo.nftAddress = nftAddress + const chain = await web3.eth.getChainId() + poolDdo.chainId = chain + poolDdo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) + + const AssetValidation: ValidateMetadata = await aquarius.validate(poolDdo) + assert(AssetValidation.valid === true, 'Published asset is not valid') + + const encryptedDdo = await ProviderInstance.encrypt(poolDdo, providerUrl) + const encryptedResponse = await encryptedDdo + const metadataHash = getHash(JSON.stringify(poolDdo)) + // just to make sure that our hash matches one computed by aquarius + assert(AssetValidation.hash === '0x' + metadataHash, 'Metadata hash is a missmatch') + const tx = await nft.setMetadata( + nftAddress, + accounts[0], + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash, + [AssetValidation.proof] + ) + + const resolvedDDO = await aquarius.waitForAqua(poolDdo.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + }) + + it('should publish a dataset with fixed price (create NFT + ERC20 + fixed price) with an explicit empty Metadata Proof', async () => { + const fixedPriceDdo: DDO = { ...genericAsset } + const nftParams: NftCreateData = { + name: 'testNftFre', + symbol: 'TSTF', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: accounts[0] + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: accounts[0], + mpFeeAddress: ZERO_ADDRESS + } + + const fixedPriceParams: FreCreationParams = { + fixedRateAddress: addresses.FixedPrice, + baseTokenAddress: addresses.MockDAI, + owner: accounts[0], + marketFeeCollector: accounts[0], + baseTokenDecimals: 18, + datatokenDecimals: 18, + fixedRate: '1', + marketFee: '0', + allowedConsumer: accounts[0], + withMint: false + } + + const bundleNFT = await factory.createNftErc20WithFixedRate( + accounts[0], + nftParams, + erc20Params, + fixedPriceParams + ) + + const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] + const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] + const fixedPrice = bundleNFT.events.NewFixedRate.returnValues[0] + + const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) + + fixedPriceDdo.metadata.name = 'test-dataset-fixedPrice' + fixedPriceDdo.services[0].files = await encryptedFiles + fixedPriceDdo.services[0].datatokenAddress = datatokenAddress + + fixedPriceDdo.nftAddress = nftAddress + const chain = await web3.eth.getChainId() + fixedPriceDdo.chainId = chain + fixedPriceDdo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) + + const isAssetValid: ValidateMetadata = await aquarius.validate(fixedPriceDdo) + assert(isAssetValid.valid === true, 'Published asset is not valid') + + const encryptedDdo = await ProviderInstance.encrypt(fixedPriceDdo, providerUrl) + const encryptedResponse = await encryptedDdo + const metadataHash = getHash(JSON.stringify(fixedPriceDdo)) + // this is publishing with an explicit empty metadataProofs + const res = await nft.setMetadata( + nftAddress, + accounts[0], + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash, + [] + ) + const resolvedDDO = await aquarius.waitForAqua(fixedPriceDdo.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + }) + + it('should publish a dataset with dispenser (create NFT + ERC20 + dispenser) with no defined MetadataProof', async () => { + const dispenserDdo: DDO = { ...genericAsset } + const nftParams: NftCreateData = { + name: 'testNftDispenser', + symbol: 'TSTD', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: accounts[0] + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: accounts[0], + mpFeeAddress: ZERO_ADDRESS + } + + const dispenserParams: DispenserCreationParams = { + dispenserAddress: addresses.Dispenser, + maxTokens: '1', + maxBalance: '1', + withMint: true, + allowedSwapper: ZERO_ADDRESS + } + + const bundleNFT = await factory.createNftErc20WithDispenser( + accounts[0], + nftParams, + erc20Params, + dispenserParams + ) + + const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] + const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] + const dispenserAddress = bundleNFT.events.DispenserCreated.returnValues[0] + + const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) + dispenserDdo.metadata.name = 'test-dataset-dispenser' + dispenserDdo.services[0].files = await encryptedFiles + dispenserDdo.services[0].datatokenAddress = datatokenAddress + + dispenserDdo.nftAddress = nftAddress + const chain = await web3.eth.getChainId() + dispenserDdo.chainId = chain + dispenserDdo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) + + const isAssetValid: ValidateMetadata = await aquarius.validate(dispenserDdo) + assert(isAssetValid.valid === true, 'Published asset is not valid') + + const encryptedDdo = await ProviderInstance.encrypt(dispenserDdo, providerUrl) + const encryptedResponse = await encryptedDdo + const metadataHash = getHash(JSON.stringify(dispenserDdo)) + // this is publishing with any explicit metadataProofs + const res = await nft.setMetadata( + nftAddress, + accounts[0], + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash + ) + const resolvedDDO = await aquarius.waitForAqua(dispenserDdo.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + }) +}) From d1a6b54ebf1a16c3183904dd58e0435a48065308 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 21 Apr 2022 17:29:08 +0200 Subject: [PATCH 2/6] Updating script --- CodeExamples.md | 41 ++++++++++++++++++++++-------- scripts/createGuide.sh | 10 +++++++- test/integration/ReameFlow.test.ts | 33 +++++++++++++++++++----- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index c60a9132..9085df90 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -1,5 +1,7 @@ # Ocean.js Code Examples +The following guide runs you through the process of using ocean.js in a publish flow. The code examples below are all working and you can learn how to publish by following along. + Start by importing all of the necessary dependencies ```Typescript @@ -28,10 +30,16 @@ import { } from '../../src' ``` +Here we define some variables that we will use later +```Typescript let nft: Nft let factory: NftFactory let accounts: string[] +``` +We will need a file to publish, so here we define the file that we intend to publish. + +```Typescript const files = [ { type: 'url', @@ -39,6 +47,10 @@ const files = [ method: 'GET' } ] +``` + +Next, we define the metadata that will describe our data asset. This is what we call the DDO +```Typescript const genericAsset: DDO = { '@context': ['https://w3id.org/did/v1'], id: 'testFakeDid', @@ -69,21 +81,24 @@ const genericAsset: DDO = { } ] } +``` -describe('Publish tests', async () => { +## Publishing a dataset +```Typescript let config: Config let addresses: any let aquarius: Aquarius let providerUrl: any - before(async () => { + config = await getTestConfig(web3) addresses = getAddresses() aquarius = new Aquarius(config.metadataCacheUri) providerUrl = config.providerUri - }) + ``` - it('initialise testes classes', async () => { + ### initialise testes classes +```Typescript nft = new Nft(web3) factory = new NftFactory(addresses.ERC721Factory, web3) accounts = await web3.eth.getAccounts() @@ -95,8 +110,10 @@ describe('Publish tests', async () => { .approve(addresses.ERC721Factory, web3.utils.toWei('100000')) .send({ from: accounts[0] }) }) +``` - it('should publish a dataset with pool (create NFT + ERC20 + pool) and with Metdata proof', async () => { + ### should publish a dataset with pool (create NFT + ERC20 + pool) and with Metdata proof +```Typescript const poolDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftPool', @@ -176,8 +193,10 @@ describe('Publish tests', async () => { const resolvedDDO = await aquarius.waitForAqua(poolDdo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') }) +``` - it('should publish a dataset with fixed price (create NFT + ERC20 + fixed price) with an explicit empty Metadata Proof', async () => { + ### should publish a dataset with fixed price (create NFT + ERC20 + fixed price) with an explicit empty Metadata Proof +```Typescript const fixedPriceDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftFre', @@ -253,9 +272,11 @@ describe('Publish tests', async () => { ) const resolvedDDO = await aquarius.waitForAqua(fixedPriceDdo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - }) + ``` - it('should publish a dataset with dispenser (create NFT + ERC20 + dispenser) with no defined MetadataProof', async () => { + + ### should publish a dataset with dispenser (create NFT + ERC20 + dispenser) with no defined MetadataProof +```Typescript const dispenserDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftDispenser', @@ -324,5 +345,5 @@ describe('Publish tests', async () => { ) const resolvedDDO = await aquarius.waitForAqua(dispenserDdo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - }) -}) + ``` + diff --git a/scripts/createGuide.sh b/scripts/createGuide.sh index 23e89323..348f9526 100755 --- a/scripts/createGuide.sh +++ b/scripts/createGuide.sh @@ -3,4 +3,12 @@ cp test/integration/ReameFlow.test.ts CodeExamples.md # Replace comments -sed -i 's/\/\/\/ //' CodeExamples.md \ No newline at end of file +sed -i 's/}) \/\/\/ //' CodeExamples.md +sed -i 's/\/\/\/ //' CodeExamples.md + + +# Generate titles +sed -i "s/describe('/\#\# /" CodeExamples.md +sed -i "s/it('/\#\#\# /" CodeExamples.md +sed -i "s/', async () => {//" CodeExamples.md +sed -i "s/before(async () => {//" CodeExamples.md diff --git a/test/integration/ReameFlow.test.ts b/test/integration/ReameFlow.test.ts index e856ee99..538b1b65 100644 --- a/test/integration/ReameFlow.test.ts +++ b/test/integration/ReameFlow.test.ts @@ -1,5 +1,7 @@ /// # Ocean.js Code Examples +/// The following guide runs you through the process of using ocean.js in a publish flow. The code examples below are all working and you can learn how to publish by following along. + /// Start by importing all of the necessary dependencies /// ```Typescript @@ -28,10 +30,16 @@ import { } from '../../src' /// ``` +/// Here we define some variables that we will use later +/// ```Typescript let nft: Nft let factory: NftFactory let accounts: string[] +/// ``` +/// We will need a file to publish, so here we define the file that we intend to publish. + +/// ```Typescript const files = [ { type: 'url', @@ -39,6 +47,10 @@ const files = [ method: 'GET' } ] +/// ``` + +/// Next, we define the metadata that will describe our data asset. This is what we call the DDO +/// ```Typescript const genericAsset: DDO = { '@context': ['https://w3id.org/did/v1'], id: 'testFakeDid', @@ -69,8 +81,10 @@ const genericAsset: DDO = { } ] } +/// ``` -describe('Publish tests', async () => { +describe('Publishing a dataset', async () => { +/// ```Typescript let config: Config let addresses: any let aquarius: Aquarius @@ -81,9 +95,10 @@ describe('Publish tests', async () => { addresses = getAddresses() aquarius = new Aquarius(config.metadataCacheUri) providerUrl = config.providerUri - }) + }) /// ``` it('initialise testes classes', async () => { +/// ```Typescript nft = new Nft(web3) factory = new NftFactory(addresses.ERC721Factory, web3) accounts = await web3.eth.getAccounts() @@ -94,9 +109,10 @@ describe('Publish tests', async () => { await daiContract.methods .approve(addresses.ERC721Factory, web3.utils.toWei('100000')) .send({ from: accounts[0] }) - }) + }) /// ``` it('should publish a dataset with pool (create NFT + ERC20 + pool) and with Metdata proof', async () => { +/// ```Typescript const poolDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftPool', @@ -175,9 +191,10 @@ describe('Publish tests', async () => { const resolvedDDO = await aquarius.waitForAqua(poolDdo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - }) + }) /// ``` it('should publish a dataset with fixed price (create NFT + ERC20 + fixed price) with an explicit empty Metadata Proof', async () => { +/// ```Typescript const fixedPriceDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftFre', @@ -253,9 +270,11 @@ describe('Publish tests', async () => { ) const resolvedDDO = await aquarius.waitForAqua(fixedPriceDdo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - }) + }) /// ``` + it('should publish a dataset with dispenser (create NFT + ERC20 + dispenser) with no defined MetadataProof', async () => { +/// ```Typescript const dispenserDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftDispenser', @@ -324,5 +343,5 @@ describe('Publish tests', async () => { ) const resolvedDDO = await aquarius.waitForAqua(dispenserDdo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - }) -}) + }) /// ``` +}) /// From f935f9f8a590ffac6061649d993aafcea8523e54 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Mon, 25 Apr 2022 13:45:06 +0200 Subject: [PATCH 3/6] Creating markdown guide from simple publish consume flow --- CodeExamples.md | 368 +++++------------- scripts/createGuide.sh | 6 +- test/integration/ReadmeFlow.test.ts | 177 +++++++++ ...eFlow.test.ts => ReamePublishFlow.test.ts} | 13 +- 4 files changed, 286 insertions(+), 278 deletions(-) create mode 100644 test/integration/ReadmeFlow.test.ts rename test/integration/{ReameFlow.test.ts => ReamePublishFlow.test.ts} (98%) diff --git a/CodeExamples.md b/CodeExamples.md index 9085df90..a385b17e 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -1,22 +1,12 @@ # Ocean.js Code Examples -The following guide runs you through the process of using ocean.js in a publish flow. The code examples below are all working and you can learn how to publish by following along. +The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. Start by importing all of the necessary dependencies ```Typescript -import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' -import { assert } from 'chai' + import { SHA256 } from 'crypto-js' -import { AbiItem } from 'web3-utils' -import { - ValidateMetadata, - DDO, - Erc20CreateParams, - PoolCreationParams, - FreCreationParams, - DispenserCreationParams -} from '../../src/@types' import { web3, getTestConfig, getAddresses } from '../config' import { Config, @@ -24,56 +14,43 @@ import { Aquarius, NftFactory, NftCreateData, + Datatoken, getHash, - ZERO_ADDRESS, - Nft + Nft, + downloadFile } from '../../src' -``` +import { ProviderFees, Erc20CreateParams } from '../../src/@types' -Here we define some variables that we will use later -```Typescript -let nft: Nft -let factory: NftFactory -let accounts: string[] -``` - -We will need a file to publish, so here we define the file that we intend to publish. - -```Typescript -const files = [ +const assetUrl = [ { type: 'url', url: 'https://raw.githubusercontent.com/oceanprotocol/testdatasets/main/shs_dataset_test.txt', method: 'GET' } ] -``` - -Next, we define the metadata that will describe our data asset. This is what we call the DDO -```Typescript -const genericAsset: DDO = { +const ddo = { '@context': ['https://w3id.org/did/v1'], - id: 'testFakeDid', + id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', version: '4.0.0', chainId: 4, nftAddress: '0x0', metadata: { created: '2021-12-20T14:35:20Z', updated: '2021-12-20T14:35:20Z', - name: 'dataset-name', type: 'dataset', - description: 'Ocean protocol test dataset description', - author: 'oceanprotocol-team', - license: 'MIT', - tags: ['white-papers'], - additionalInformation: { 'test-key': 'test-value' }, - links: ['http://data.ceda.ac.uk/badc/ukcp09/'] + name: 'dfgdfgdg', + description: 'd dfgd fgd dfg dfgdfgd dfgdf', + tags: [''], + author: 'dd', + license: 'https://market.oceanprotocol.com/terms', + additionalInformation: { + termsAndConditions: true + } }, services: [ { - id: 'testFakeId', + id: 'notAnId', type: 'access', - description: 'Download service', files: '', datatokenAddress: '0xa15024b732A8f2146423D14209eFd074e61964F3', serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', @@ -81,10 +58,8 @@ const genericAsset: DDO = { } ] } -``` -## Publishing a dataset -```Typescript +## Simple Publish & consume test let config: Config let addresses: any let aquarius: Aquarius @@ -95,247 +70,56 @@ const genericAsset: DDO = { addresses = getAddresses() aquarius = new Aquarius(config.metadataCacheUri) providerUrl = config.providerUri - ``` - - ### initialise testes classes -```Typescript - nft = new Nft(web3) - factory = new NftFactory(addresses.ERC721Factory, web3) - accounts = await web3.eth.getAccounts() - const daiContract = new web3.eth.Contract( - MockERC20.abi as AbiItem[], - addresses.MockDAI - ) - await daiContract.methods - .approve(addresses.ERC721Factory, web3.utils.toWei('100000')) - .send({ from: accounts[0] }) }) -``` - ### should publish a dataset with pool (create NFT + ERC20 + pool) and with Metdata proof -```Typescript - const poolDdo: DDO = { ...genericAsset } + ### should publish a dataset (create NFT + ERC20) + const nft = new Nft(web3) + const datatoken = new Datatoken(web3) + const Factory = new NftFactory(addresses.ERC721Factory, web3) + const accounts = await web3.eth.getAccounts() + const publisherAccount = accounts[0] + const consumerAccount = accounts[1] const nftParams: NftCreateData = { - name: 'testNftPool', - symbol: 'TSTP', + name: 'testNFT', + symbol: 'TST', templateIndex: 1, tokenURI: '', transferable: true, - owner: accounts[0] + owner: publisherAccount } const erc20Params: Erc20CreateParams = { templateIndex: 1, cap: '100000', feeAmount: '0', - paymentCollector: ZERO_ADDRESS, - feeToken: ZERO_ADDRESS, - minter: accounts[0], - mpFeeAddress: ZERO_ADDRESS + paymentCollector: '0x0000000000000000000000000000000000000000', + feeToken: '0x0000000000000000000000000000000000000000', + minter: publisherAccount, + mpFeeAddress: '0x0000000000000000000000000000000000000000' } - const poolParams: PoolCreationParams = { - ssContract: addresses.Staking, - baseTokenAddress: addresses.MockDAI, - baseTokenSender: addresses.ERC721Factory, - publisherAddress: accounts[0], - marketFeeCollector: accounts[0], - poolTemplateAddress: addresses.poolTemplate, - rate: '1', - baseTokenDecimals: 18, - vestingAmount: '10000', - vestedBlocks: 2500000, - initialBaseTokenLiquidity: '2000', - swapFeeLiquidityProvider: '0.001', - swapFeeMarketRunner: '0.001' - } - const bundleNFT = await factory.createNftErc20WithPool( - accounts[0], + const result = await Factory.createNftWithErc20( + publisherAccount, nftParams, - erc20Params, - poolParams + erc20Params ) + const erc721Address = result.events.NFTCreated.returnValues[0] + const datatokenAddress = result.events.TokenCreated.returnValues[0] - const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] - const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] - const poolAdress = bundleNFT.events.NewPool.returnValues[0] - - const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) - - poolDdo.metadata.name = 'test-dataset-pool' - poolDdo.services[0].files = await encryptedFiles - poolDdo.services[0].datatokenAddress = datatokenAddress - - poolDdo.nftAddress = nftAddress + // create the files encrypted string + let providerResponse = await ProviderInstance.encrypt(assetUrl, providerUrl) + ddo.services[0].files = await providerResponse + ddo.services[0].datatokenAddress = datatokenAddress + // update ddo and set the right did + ddo.nftAddress = erc721Address const chain = await web3.eth.getChainId() - poolDdo.chainId = chain - poolDdo.id = - 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) + ddo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(erc721Address) + chain.toString(10)) - const AssetValidation: ValidateMetadata = await aquarius.validate(poolDdo) - assert(AssetValidation.valid === true, 'Published asset is not valid') - - const encryptedDdo = await ProviderInstance.encrypt(poolDdo, providerUrl) - const encryptedResponse = await encryptedDdo - const metadataHash = getHash(JSON.stringify(poolDdo)) - // just to make sure that our hash matches one computed by aquarius - assert(AssetValidation.hash === '0x' + metadataHash, 'Metadata hash is a missmatch') - const tx = await nft.setMetadata( - nftAddress, - accounts[0], - 0, - providerUrl, - '', - '0x2', - encryptedResponse, - '0x' + metadataHash, - [AssetValidation.proof] - ) - - const resolvedDDO = await aquarius.waitForAqua(poolDdo.id) - assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - }) -``` - - ### should publish a dataset with fixed price (create NFT + ERC20 + fixed price) with an explicit empty Metadata Proof -```Typescript - const fixedPriceDdo: DDO = { ...genericAsset } - const nftParams: NftCreateData = { - name: 'testNftFre', - symbol: 'TSTF', - templateIndex: 1, - tokenURI: '', - transferable: true, - owner: accounts[0] - } - const erc20Params: Erc20CreateParams = { - templateIndex: 1, - cap: '100000', - feeAmount: '0', - paymentCollector: ZERO_ADDRESS, - feeToken: ZERO_ADDRESS, - minter: accounts[0], - mpFeeAddress: ZERO_ADDRESS - } - - const fixedPriceParams: FreCreationParams = { - fixedRateAddress: addresses.FixedPrice, - baseTokenAddress: addresses.MockDAI, - owner: accounts[0], - marketFeeCollector: accounts[0], - baseTokenDecimals: 18, - datatokenDecimals: 18, - fixedRate: '1', - marketFee: '0', - allowedConsumer: accounts[0], - withMint: false - } - - const bundleNFT = await factory.createNftErc20WithFixedRate( - accounts[0], - nftParams, - erc20Params, - fixedPriceParams - ) - - const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] - const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] - const fixedPrice = bundleNFT.events.NewFixedRate.returnValues[0] - - const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) - - fixedPriceDdo.metadata.name = 'test-dataset-fixedPrice' - fixedPriceDdo.services[0].files = await encryptedFiles - fixedPriceDdo.services[0].datatokenAddress = datatokenAddress - - fixedPriceDdo.nftAddress = nftAddress - const chain = await web3.eth.getChainId() - fixedPriceDdo.chainId = chain - fixedPriceDdo.id = - 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) - - const isAssetValid: ValidateMetadata = await aquarius.validate(fixedPriceDdo) - assert(isAssetValid.valid === true, 'Published asset is not valid') - - const encryptedDdo = await ProviderInstance.encrypt(fixedPriceDdo, providerUrl) - const encryptedResponse = await encryptedDdo - const metadataHash = getHash(JSON.stringify(fixedPriceDdo)) - // this is publishing with an explicit empty metadataProofs + providerResponse = await ProviderInstance.encrypt(ddo, providerUrl) + const encryptedResponse = await providerResponse + const metadataHash = getHash(JSON.stringify(ddo)) const res = await nft.setMetadata( - nftAddress, - accounts[0], - 0, - providerUrl, - '', - '0x2', - encryptedResponse, - '0x' + metadataHash, - [] - ) - const resolvedDDO = await aquarius.waitForAqua(fixedPriceDdo.id) - assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - ``` - - - ### should publish a dataset with dispenser (create NFT + ERC20 + dispenser) with no defined MetadataProof -```Typescript - const dispenserDdo: DDO = { ...genericAsset } - const nftParams: NftCreateData = { - name: 'testNftDispenser', - symbol: 'TSTD', - templateIndex: 1, - tokenURI: '', - transferable: true, - owner: accounts[0] - } - const erc20Params: Erc20CreateParams = { - templateIndex: 1, - cap: '100000', - feeAmount: '0', - paymentCollector: ZERO_ADDRESS, - feeToken: ZERO_ADDRESS, - minter: accounts[0], - mpFeeAddress: ZERO_ADDRESS - } - - const dispenserParams: DispenserCreationParams = { - dispenserAddress: addresses.Dispenser, - maxTokens: '1', - maxBalance: '1', - withMint: true, - allowedSwapper: ZERO_ADDRESS - } - - const bundleNFT = await factory.createNftErc20WithDispenser( - accounts[0], - nftParams, - erc20Params, - dispenserParams - ) - - const nftAddress = bundleNFT.events.NFTCreated.returnValues[0] - const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0] - const dispenserAddress = bundleNFT.events.DispenserCreated.returnValues[0] - - const encryptedFiles = await ProviderInstance.encrypt(files, providerUrl) - dispenserDdo.metadata.name = 'test-dataset-dispenser' - dispenserDdo.services[0].files = await encryptedFiles - dispenserDdo.services[0].datatokenAddress = datatokenAddress - - dispenserDdo.nftAddress = nftAddress - const chain = await web3.eth.getChainId() - dispenserDdo.chainId = chain - dispenserDdo.id = - 'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10)) - - const isAssetValid: ValidateMetadata = await aquarius.validate(dispenserDdo) - assert(isAssetValid.valid === true, 'Published asset is not valid') - - const encryptedDdo = await ProviderInstance.encrypt(dispenserDdo, providerUrl) - const encryptedResponse = await encryptedDdo - const metadataHash = getHash(JSON.stringify(dispenserDdo)) - // this is publishing with any explicit metadataProofs - const res = await nft.setMetadata( - nftAddress, - accounts[0], + erc721Address, + publisherAccount, 0, providerUrl, '', @@ -343,7 +127,51 @@ const genericAsset: DDO = { encryptedResponse, '0x' + metadataHash ) - const resolvedDDO = await aquarius.waitForAqua(dispenserDdo.id) + const resolvedDDO = await aquarius.waitForAqua(ddo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - ``` - + // mint 1 ERC20 and send it to the consumer + await datatoken.mint(datatokenAddress, publisherAccount, '1', consumerAccount) + // initialize provider + const initializeData = await ProviderInstance.initialize( + resolvedDDO.id, + resolvedDDO.services[0].id, + 0, + consumerAccount, + providerUrl + ) + const providerFees: ProviderFees = { + providerFeeAddress: initializeData.providerFee.providerFeeAddress, + providerFeeToken: initializeData.providerFee.providerFeeToken, + providerFeeAmount: initializeData.providerFee.providerFeeAmount, + v: initializeData.providerFee.v, + r: initializeData.providerFee.r, + s: initializeData.providerFee.s, + providerData: initializeData.providerFee.providerData, + validUntil: initializeData.providerFee.validUntil + } + // make the payment + const txid = await datatoken.startOrder( + datatokenAddress, + consumerAccount, + consumerAccount, + 0, + providerFees + ) + // get the url + const downloadURL = await ProviderInstance.getDownloadUrl( + ddo.id, + consumerAccount, + ddo.services[0].id, + 0, + txid.transactionHash, + providerUrl, + web3 + ) + assert(downloadURL, 'Provider getDownloadUrl failed') + try { + const fileData = await downloadFile(downloadURL) + } catch (e) { + assert.fail('Download failed') + } + }) +}) diff --git a/scripts/createGuide.sh b/scripts/createGuide.sh index 348f9526..89381b2e 100755 --- a/scripts/createGuide.sh +++ b/scripts/createGuide.sh @@ -1,6 +1,10 @@ #!/bin/bash # Create markdown file -cp test/integration/ReameFlow.test.ts CodeExamples.md +cp test/integration/ReadmeFlow.test.ts CodeExamples.md + +# Remove unneccessay imports +sed -i "s/import { assert } from 'chai'//" CodeExamples.md + # Replace comments sed -i 's/}) \/\/\/ //' CodeExamples.md diff --git a/test/integration/ReadmeFlow.test.ts b/test/integration/ReadmeFlow.test.ts new file mode 100644 index 00000000..5b6da188 --- /dev/null +++ b/test/integration/ReadmeFlow.test.ts @@ -0,0 +1,177 @@ +/// # Ocean.js Code Examples + +/// The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. + +/// Start by importing all of the necessary dependencies + +/// ```Typescript +import { assert } from 'chai' +import { SHA256 } from 'crypto-js' +import { web3, getTestConfig, getAddresses } from '../config' +import { + Config, + ProviderInstance, + Aquarius, + NftFactory, + NftCreateData, + Datatoken, + getHash, + Nft, + downloadFile +} from '../../src' +import { ProviderFees, Erc20CreateParams } from '../../src/@types' + +const assetUrl = [ + { + type: 'url', + url: 'https://raw.githubusercontent.com/oceanprotocol/testdatasets/main/shs_dataset_test.txt', + method: 'GET' + } +] +const ddo = { + '@context': ['https://w3id.org/did/v1'], + id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', + version: '4.0.0', + chainId: 4, + nftAddress: '0x0', + metadata: { + created: '2021-12-20T14:35:20Z', + updated: '2021-12-20T14:35:20Z', + type: 'dataset', + name: 'dfgdfgdg', + description: 'd dfgd fgd dfg dfgdfgd dfgdf', + tags: [''], + author: 'dd', + license: 'https://market.oceanprotocol.com/terms', + additionalInformation: { + termsAndConditions: true + } + }, + services: [ + { + id: 'notAnId', + type: 'access', + files: '', + datatokenAddress: '0xa15024b732A8f2146423D14209eFd074e61964F3', + serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', + timeout: 0 + } + ] +} + +describe('Simple Publish & consume test', async () => { + let config: Config + let addresses: any + let aquarius: Aquarius + let providerUrl: any + + before(async () => { + config = await getTestConfig(web3) + addresses = getAddresses() + aquarius = new Aquarius(config.metadataCacheUri) + providerUrl = config.providerUri + }) + + it('should publish a dataset (create NFT + ERC20)', async () => { + const nft = new Nft(web3) + const datatoken = new Datatoken(web3) + const Factory = new NftFactory(addresses.ERC721Factory, web3) + const accounts = await web3.eth.getAccounts() + const publisherAccount = accounts[0] + const consumerAccount = accounts[1] + const nftParams: NftCreateData = { + name: 'testNFT', + symbol: 'TST', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: publisherAccount + } + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: '0x0000000000000000000000000000000000000000', + feeToken: '0x0000000000000000000000000000000000000000', + minter: publisherAccount, + mpFeeAddress: '0x0000000000000000000000000000000000000000' + } + const result = await Factory.createNftWithErc20( + publisherAccount, + nftParams, + erc20Params + ) + const erc721Address = result.events.NFTCreated.returnValues[0] + const datatokenAddress = result.events.TokenCreated.returnValues[0] + + // create the files encrypted string + let providerResponse = await ProviderInstance.encrypt(assetUrl, providerUrl) + ddo.services[0].files = await providerResponse + ddo.services[0].datatokenAddress = datatokenAddress + // update ddo and set the right did + ddo.nftAddress = erc721Address + const chain = await web3.eth.getChainId() + ddo.id = + 'did:op:' + SHA256(web3.utils.toChecksumAddress(erc721Address) + chain.toString(10)) + + providerResponse = await ProviderInstance.encrypt(ddo, providerUrl) + const encryptedResponse = await providerResponse + const metadataHash = getHash(JSON.stringify(ddo)) + const res = await nft.setMetadata( + erc721Address, + publisherAccount, + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + '0x' + metadataHash + ) + const resolvedDDO = await aquarius.waitForAqua(ddo.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + // mint 1 ERC20 and send it to the consumer + await datatoken.mint(datatokenAddress, publisherAccount, '1', consumerAccount) + // initialize provider + const initializeData = await ProviderInstance.initialize( + resolvedDDO.id, + resolvedDDO.services[0].id, + 0, + consumerAccount, + providerUrl + ) + const providerFees: ProviderFees = { + providerFeeAddress: initializeData.providerFee.providerFeeAddress, + providerFeeToken: initializeData.providerFee.providerFeeToken, + providerFeeAmount: initializeData.providerFee.providerFeeAmount, + v: initializeData.providerFee.v, + r: initializeData.providerFee.r, + s: initializeData.providerFee.s, + providerData: initializeData.providerFee.providerData, + validUntil: initializeData.providerFee.validUntil + } + // make the payment + const txid = await datatoken.startOrder( + datatokenAddress, + consumerAccount, + consumerAccount, + 0, + providerFees + ) + // get the url + const downloadURL = await ProviderInstance.getDownloadUrl( + ddo.id, + consumerAccount, + ddo.services[0].id, + 0, + txid.transactionHash, + providerUrl, + web3 + ) + assert(downloadURL, 'Provider getDownloadUrl failed') + try { + const fileData = await downloadFile(downloadURL) + } catch (e) { + assert.fail('Download failed') + } + }) +}) diff --git a/test/integration/ReameFlow.test.ts b/test/integration/ReamePublishFlow.test.ts similarity index 98% rename from test/integration/ReameFlow.test.ts rename to test/integration/ReamePublishFlow.test.ts index 538b1b65..c047cf5c 100644 --- a/test/integration/ReameFlow.test.ts +++ b/test/integration/ReamePublishFlow.test.ts @@ -84,7 +84,7 @@ const genericAsset: DDO = { /// ``` describe('Publishing a dataset', async () => { -/// ```Typescript + /// ```Typescript let config: Config let addresses: any let aquarius: Aquarius @@ -98,7 +98,7 @@ describe('Publishing a dataset', async () => { }) /// ``` it('initialise testes classes', async () => { -/// ```Typescript + /// ```Typescript nft = new Nft(web3) factory = new NftFactory(addresses.ERC721Factory, web3) accounts = await web3.eth.getAccounts() @@ -112,7 +112,7 @@ describe('Publishing a dataset', async () => { }) /// ``` it('should publish a dataset with pool (create NFT + ERC20 + pool) and with Metdata proof', async () => { -/// ```Typescript + /// ```Typescript const poolDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftPool', @@ -194,7 +194,7 @@ describe('Publishing a dataset', async () => { }) /// ``` it('should publish a dataset with fixed price (create NFT + ERC20 + fixed price) with an explicit empty Metadata Proof', async () => { -/// ```Typescript + /// ```Typescript const fixedPriceDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftFre', @@ -272,9 +272,8 @@ describe('Publishing a dataset', async () => { assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') }) /// ``` - it('should publish a dataset with dispenser (create NFT + ERC20 + dispenser) with no defined MetadataProof', async () => { -/// ```Typescript + /// ```Typescript const dispenserDdo: DDO = { ...genericAsset } const nftParams: NftCreateData = { name: 'testNftDispenser', @@ -344,4 +343,4 @@ describe('Publishing a dataset', async () => { const resolvedDDO = await aquarius.waitForAqua(dispenserDdo.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') }) /// ``` -}) /// +}) /// From 331da90db5a33449fd590ee519d17883539c54d4 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Mon, 25 Apr 2022 13:51:17 +0200 Subject: [PATCH 4/6] Updating script --- CodeExamples.md | 13 ++++++++++++- scripts/createGuide.sh | 2 +- test/integration/ReadmeFlow.test.ts | 13 ++++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index a385b17e..1a231d60 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -20,7 +20,11 @@ import { downloadFile } from '../../src' import { ProviderFees, Erc20CreateParams } from '../../src/@types' +``` +We will need a file to publish, so here we define the file that we intend to publish. + +```Typescript const assetUrl = [ { type: 'url', @@ -28,6 +32,10 @@ const assetUrl = [ method: 'GET' } ] +``` + +Next, we define the metadata that will describe our data asset. This is what we call the DDO +```Typescript const ddo = { '@context': ['https://w3id.org/did/v1'], id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', @@ -58,8 +66,10 @@ const ddo = { } ] } +``` + +```Typescript -## Simple Publish & consume test let config: Config let addresses: any let aquarius: Aquarius @@ -175,3 +185,4 @@ const ddo = { } }) }) +``` diff --git a/scripts/createGuide.sh b/scripts/createGuide.sh index 89381b2e..f49ba53a 100755 --- a/scripts/createGuide.sh +++ b/scripts/createGuide.sh @@ -12,7 +12,7 @@ sed -i 's/\/\/\/ //' CodeExamples.md # Generate titles -sed -i "s/describe('/\#\# /" CodeExamples.md +sed -i "s/describe('Simple Publish & Consume Flow', async () => {//" CodeExamples.md sed -i "s/it('/\#\#\# /" CodeExamples.md sed -i "s/', async () => {//" CodeExamples.md sed -i "s/before(async () => {//" CodeExamples.md diff --git a/test/integration/ReadmeFlow.test.ts b/test/integration/ReadmeFlow.test.ts index 5b6da188..99977526 100644 --- a/test/integration/ReadmeFlow.test.ts +++ b/test/integration/ReadmeFlow.test.ts @@ -20,7 +20,11 @@ import { downloadFile } from '../../src' import { ProviderFees, Erc20CreateParams } from '../../src/@types' +/// ``` +/// We will need a file to publish, so here we define the file that we intend to publish. + +/// ```Typescript const assetUrl = [ { type: 'url', @@ -28,6 +32,10 @@ const assetUrl = [ method: 'GET' } ] +/// ``` + +/// Next, we define the metadata that will describe our data asset. This is what we call the DDO +/// ```Typescript const ddo = { '@context': ['https://w3id.org/did/v1'], id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', @@ -58,8 +66,10 @@ const ddo = { } ] } +/// ``` -describe('Simple Publish & consume test', async () => { +/// ```Typescript +describe('Simple Publish & Consume Flow', async () => { let config: Config let addresses: any let aquarius: Aquarius @@ -175,3 +185,4 @@ describe('Simple Publish & consume test', async () => { } }) }) +/// ``` From 64c464239c6a0d6c7b8b1aad4f5e13deeebf9ca1 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 27 Apr 2022 17:23:18 +0300 Subject: [PATCH 5/6] Adding introduction to code examples guide + updating the main readme --- README.md | 60 +---- docs/overview.md | 394 ---------------------------- test/integration/ReadmeFlow.test.ts | 24 +- 3 files changed, 29 insertions(+), 449 deletions(-) delete mode 100644 docs/overview.md diff --git a/README.md b/README.md index 8e5208dd..3ac5c9f2 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ This is in alpha state. If you run into problems, please open up a [new issue](h - [📚 Prerequisites](#-prerequisites) - [🏗 Installation](#-installation) -- [🏄 Quickstart](#-quickstart): simple flow, marketplace, compute-to-data, more +- [📖 Learn More](#-learn-more) - [🦑 Development](#-development) - [✨ Code Style](#-code-style) - [👩‍🔬 Testing](#-testing) @@ -42,66 +42,18 @@ This is in alpha state. If you run into problems, please open up a [new issue](h - Docker ([Managed as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/)) - A Unix based operating system (Mac or Linux) -### Note - -Any function that uses `getPastEvents()` will only work on Eth (see: ). This includes: - -- searchPoolforDT() -- getPoolsbyCreator() -- getPoolSharesByAddress() -- getAllPoolLogs() -- getPreviousValidOrders() -- searchforDT() -- getExchangesbyCreator() -- getExchangeSwaps() -- getAllExchangesSwaps() - ## 🏗 Installation ```bash npm install @oceanprotocol/lib ``` - -## 🏄 Quickstart - -```ts -import { Ocean, Config, ConfigHelper, Logger } from '@oceanprotocol/lib' - -const defaultConfig: Config = new ConfigHelper().getConfig( - 'rinkeby', - 'YOUR_INFURA_PROJECT_ID' -) - -const config = { - ...defaultConfig, - metadataCacheUri: 'https://your-metadata-cache.com', - providerUri: 'https://your-provider.com' -} - -async function init() { - const ocean = await Ocean.getInstance(config) - return ocean -} -``` - -Here are flows to try out, from beginners to advanced. - -- **[Beginners guide](docs/beginners_guide.md)** - for developers who are completely new to blockchain, no coding experience is required. -- **[Simple flow](docs/quickstart_simple.md)** - the essence of Ocean - creating a data NFT & datatoken. -- **[Marketplace flow](docs/quickstart_marketplace.md)** - a data asset is posted for sale in a datatoken pool, then purchased. Includes metadata and Compute-to-Data. - - ### 📖 Learn more -- [Get test OCEAN](docs/get-test-OCEAN.md) - from rinkeby -- [Understand config parameters](docs/parameters.md) - envvars vs files -- [Learn about off-chain services](docs/services.md) - Ocean Provider for data services, Aquarius metadata store -- [Learn about wallets](docs/wallets.md) - on generating, storing, and accessing private keys -- [Get an overview of ocean.js](docs/overview.md) - key modules and functions - -If you have any difficulties with the quickstarts, or if you have further questions about how to use ocean.js please reach out to us on [Discord](https://discord.gg/TnXjkR5). - -If you notice any bugs or issues with ocean.js please [open an issue on github](https://github.com/oceanprotocol/ocean.js/issues/new?assignees=&labels=bug&template=bug_report.md&title=). +- Checkout our [code examples](CodeExamples.md) to see how you can use ocean.js. +- Refer to the [Ocean Protocol documentation](https://docs.oceanprotocol.com/) for more guides and tutorials. +- Visit the [Ocean Protocol website](https://docs.oceanprotocol.com/) for general information about Ocean Protocol. +- If you have any difficulties or if you have further questions about how to use ocean.js please reach out to us on [Discord](https://discord.gg/TnXjkR5). +- If you notice any bugs or issues with ocean.js please [open an issue on github](https://github.com/oceanprotocol/ocean.js/issues/new?assignees=&labels=bug&template=bug_report.md&title=). ## 🦑 Development diff --git a/docs/overview.md b/docs/overview.md deleted file mode 100644 index f02f623d..00000000 --- a/docs/overview.md +++ /dev/null @@ -1,394 +0,0 @@ -# Overview - -Here is an overview of all ot the main functions and submodules: - -### Ocean instance - -Create/get datatoken, get dtfactory, user orders (history) - -``` -import { Ocean } from '@oceanprotocol/lib' -const ocean = await Ocean.getInstance(config) -``` - -Then use the following submodules... - -# Assets - -Publish, get, list, search, order, consume/download - -```Typescript -ocean.asset.getInstance(config: InstantiableConfig): Promise; -``` - -```Typescript -ocean.asset.create(metadata: Metadata, publisher: Account, services?: Service[], dtAddress?: string, cap?: string, name?: string, symbol?: string, providerUri?: string): SubscribablePromise; -``` - -```Typescript -ocean.asset.ownerAssets(owner: string): Promise; -``` - -```Typescript -ocean.asset.resolve(did: string): Promise; -``` - -```Typescript -ocean.asset.resolveByDTAddress(dtAddress: string, offset?: number, page?: number, sort?: number): Promise; -``` - -```Typescript -ocean.asset.editMetadata(ddo: DDO, newMetadata: EditableMetadata): Promise; -``` - -```Typescript -ocean.asset.updateMetadata(ddo: DDO, consumerAccount: string): Promise; -``` - -```Typescript -ocean.asset.editServiceTimeout(ddo: DDO, serviceIndex: number, timeout: number): Promise; -``` - -```Typescript -ocean.asset.creator(did: string): Promise; -``` - -```Typescript -ocean.asset.query(query: SearchQuery): Promise; -``` - -```Typescript -ocean.asset.search(text: string): Promise; -``` - -```Typescript -ocean.asset.getServiceByType(did: string, serviceType: string): Promise; -``` - -```Typescript -ocean.asset.getServiceByIndex(did: string, serviceIndex: number): Promise; -``` - -```Typescript -ocean.asset.createAccessServiceAttributes(creator: Account, cost: string, datePublished: string, timeout?: number, providerUri?: string): Promise; -``` - -```Typescript -ocean.asset.initialize(did: string, serviceType: string, consumerAddress: string, serviceIndex: number, serviceEndpoint: string): Promise; -``` - -```Typescript -ocean.asset.order(did: string, serviceType: string, payerAddress: string, serviceIndex?: number, mpAddress?: string, consumerAddress?: string, searchPreviousOrders?: boolean): Promise; -``` - -```Typescript -ocean.asset.download(did: string, txId: string, tokenAddress: string, consumerAccount: Account, destination: string): Promise; -``` - -```Typescript -ocean.asset.simpleDownload(dtAddress: string, serviceEndpoint: string, txId: string, account: string): Promise; -``` - -```Typescript -ocean.asset.getOrderHistory(account: Account, serviceType?: string, fromBlock?: number): Promise; -``` - -# Datatoken Pool - -Create, add/remove liquidity, check liquidity, price, buy datatokens - -```Typescript -ocean.pool. -``` - -```Typescript -ocean.pool.createDTPool(account: string, token: string, amount: string, weight: string, fee: string): Promise; -``` - -```Typescript -ocean.pool.getDTAddress(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getOceanReserve(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getDTReserve(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getMaxBuyQuantity(poolAddress: string, tokenAddress: string): Promise; -``` - -```Typescript -ocean.pool.getOceanMaxBuyQuantity(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getDTMaxBuyQuantity(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.calcInGivenOut(poolAddress: string, tokenInAddress: string, tokenOutAddress: string, tokenOutAmount: string): Promise; -``` - -```Typescript -ocean.pool.calcOutGivenIn(poolAddress: string, tokenInAddress: string, tokenOutAddress: string, tokenInAmount: string): Promise; -``` - -```Typescript -ocean.pool.calcPoolOutGivenSingleIn(poolAddress: string, tokenInAddress: string, tokenInAmount: string): Promise; -``` - -```Typescript -ocean.pool.calcSingleInGivenPoolOut(poolAddress: string, tokenInAddress: string, poolShares: string): Promise; -``` - -```Typescript -ocean.pool.calcSingleOutGivenPoolIn(poolAddress: string, tokenOutAddress: string, poolShares: string): Promise; -``` - -```Typescript -ocean.pool.calcPoolInGivenSingleOut(poolAddress: string, tokenOutAddress: string, tokenOutAmount: string): Promise; -``` - -```Typescript -ocean.pool.getPoolSharesRequiredToRemoveDT(poolAddress: string, dtAmount: string): Promise; -``` - -```Typescript -ocean.pool.getDTRemovedforPoolShares(poolAddress: string, poolShares: string): Promise; -``` - -```Typescript -ocean.pool.getPoolSharesRequiredToRemoveOcean(poolAddress: string, oceanAmount: string): Promise; -``` - -```Typescript -ocean.pool.getOceanRemovedforPoolShares(poolAddress: string, poolShares: string): Promise; -``` - -```Typescript -ocean.pool.getTokensRemovedforPoolShares(poolAddress: string, poolShares: string): Promise; -``` - -```Typescript -ocean.pool.getDTMaxAddLiquidity(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getOceanMaxAddLiquidity(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getMaxAddLiquidity(poolAddress: string, tokenAddress: string): Promise; -``` - -```Typescript -ocean.pool.getMaxRemoveLiquidity(poolAddress: string, tokenAddress: string): Promise; -``` - -```Typescript -ocean.pool.getDTMaxRemoveLiquidity(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getOceanMaxRemoveLiquidity(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.buyDT(account: string, poolAddress: string, dtAmountWanted: string, maxOceanAmount: string, maxPrice?: string): Promise; -``` - -```Typescript -ocean.pool.sellDT(account: string, poolAddress: string, dtAmount: string, oceanAmountWanted: string, maxPrice?: string): Promise; -``` - -```Typescript -ocean.pool.addDTLiquidity(account: string, poolAddress: string, amount: string): Promise; -``` - -```Typescript -ocean.pool.removeDTLiquidity(account: string, poolAddress: string, amount: string, maximumPoolShares: string): Promise; -``` - -```Typescript -ocean.pool.addOceanLiquidity(account: string, poolAddress: string, amount: string): Promise; -``` - -```Typescript -ocean.pool.removeOceanLiquidity(account: string, poolAddress: string, amount: string, maximumPoolShares: string): Promise; -``` - -```Typescript -ocean.pool.removePoolLiquidity(account: string, poolAddress: string, poolShares: string, minDT?: string, minOcean?: string): Promise; -``` - -```Typescript -ocean.pool.getDTPrice(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.searchPoolforDT(dtAddress: string): Promise; -``` - -```Typescript -ocean.pool.getOceanNeeded(poolAddress: string, dtRequired: string): Promise; -``` - -```Typescript -ocean.pool.getOceanReceived(poolAddress: string, dtSold: string): Promise; -``` - -```Typescript -ocean.pool.getDTNeeded(poolAddress: string, OceanRequired: string): Promise; -``` - -```Typescript -ocean.pool.getPoolsbyCreator(account?: string): Promise; -``` - -```Typescript -ocean.pool.getPoolDetails(poolAddress: string): Promise; -``` - -```Typescript -ocean.pool.getPoolLogs(poolAddress: string, account?: string): Promise; -``` - -```Typescript -ocean.pool.getAllPoolLogs(account: string): Promise; -``` - -# Fixed rate exchange - -Create, price, buy datatokens - -```Typescript -ocean.exchange.create(datatoken: string, rate: string, address: string): Promise; -``` - -```Typescript -ocean.exchange.generateExchangeId(datatoken: string, owner: string): Promise; -``` - -```Typescript -ocean.exchange.buyDT(exchangeId: string, datatokenAmount: string, address: string): Promise; -``` - -```Typescript -ocean.exchange.getNumberOfExchanges(): Promise; -``` - -```Typescript -ocean.exchange.setRate(exchangeId: string, newRate: number, address: string): Promise; -``` - -```Typescript -ocean.exchange.activate(exchangeId: string, address: string): Promise; -``` - -```Typescript -ocean.exchange.deactivate(exchangeId: string, address: string): Promise; -``` - -```Typescript -ocean.exchange.getRate(exchangeId: string): Promise; -``` - -```Typescript -ocean.exchange.getSupply(exchangeId: string): Promise; -``` - -```Typescript -ocean.exchange.getOceanNeeded(exchangeId: string, datatokenAmount: string): Promise; -``` - -```Typescript -ocean.exchange.getExchange(exchangeId: string): Promise; -``` - -```Typescript -ocean.exchange.getExchanges(): Promise; -``` - -```Typescript -ocean.exchange.isActive(exchangeId: string): Promise; -``` - -```Typescript -ocean.exchange.CalcInGivenOut(exchangeId: string, datatokenAmount: string): Promise; -``` - -```Typescript -ocean.exchange.searchforDT(datatokenAddress: string, minSupply: string): Promise; -``` - -```Typescript -ocean.exchange.getExchangesbyCreator(account?: string): Promise; -``` - -```Typescript -ocean.exchange.getExchangeSwaps(exchangeId: string, account?: string): Promise; -``` - -```Typescript -ocean.exchange.getAllExchangesSwaps(account: string): Promise; -``` - -# Compute-to-data - -consume/start, stop, results, status, define-service - -```Typescript -ocean.compute.start(did: string, txId: string, tokenAddress: string, consumerAccount: Account, algorithmDid?: string, algorithmMeta?: MetadataAlgorithm, output?: Output, serviceIndex?: string, serviceType?: string, algorithmTransferTxId?: string, algorithmDatatoken?: string): Promise; -``` - -```Typescript -ocean.compute.stop(consumerAccount: Account, did: string, jobId: string): Promise; -``` - -```Typescript -ocean.compute.delete(consumerAccount: Account, did: string, jobId: string): Promise; -``` - -```Typescript -ocean.compute.status(consumerAccount: Account, did?: string, jobId?: string): Promise; -``` - -```Typescript -ocean.compute.result(consumerAccount: Account, did: string, jobId: string): Promise; -``` - -```Typescript -ocean.compute.createServerAttributes(serverId: string, serverType: string, cost: string, cpu: string, gpu: string, memory: string, disk: string, maxExecutionTime: number): Server; -``` - -```Typescript -ocean.compute.createContainerAttributes(image: string, tag: string, checksum: string): Container; -``` - -```Typescript -ocean.compute.createClusterAttributes(type: string, url: string): Cluster; -``` - -```Typescript -ocean.compute.createProviderAttributes(type: string, description: string, cluster: Cluster, containers: Container[], servers: Server[]): { - type: string; - description: string; - environment: { - cluster: Cluster; - supportedServers: Server[]; - supportedContainers: Container[]; - }; - }; -``` - -```Typescript -ocean.compute.createComputeService(consumerAccount: Account, cost: string, datePublished: string, providerAttributes: any, computePrivacy?: ServiceComputePrivacy, timeout?: number, providerUri?: string): ServiceCompute; -``` - -```Typescript -ocean.compute.order(consumerAccount: string, datasetDid: string, serviceIndex: number, algorithmDid?: string, algorithmMeta?: MetadataAlgorithm, mpAddress?: string): SubscribablePromise; -``` diff --git a/test/integration/ReadmeFlow.test.ts b/test/integration/ReadmeFlow.test.ts index 99977526..fc85330c 100644 --- a/test/integration/ReadmeFlow.test.ts +++ b/test/integration/ReadmeFlow.test.ts @@ -1,7 +1,29 @@ /// # Ocean.js Code Examples -/// The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. +/// ## Introduction +/// The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. +/// The process involves creating a Data NFT (which represents the base-IP on-chain) and a datatoken (which will be used to purchase the dataset). This guide provides all the code you need and no prior knowledge is required. It is helpful if you have some experience with javascript but it is not necessary. + +/// Selling your data over the blockchain puts you in charge of how it is used and can be a great source of passive income. There are many AI startups that have deep expertise in machine learning but need more data to improve their models. Selling your data via the blockchain gives you a level of security that you would be unable to achieve if you were selling via a centralised marketplace. + +/// In this guide we'll be making use of the Ocean.js library. Ocean Protocol provides you with everything you need to quickly get setup and start selling data over the blockchain. + +/// If you have any questions or issues at any point while following along to this article please reach out to us on [discord](https://discord.gg/TnXjkR5). + +/// Here are the steps we will be following throughout the article: + +/// 1. Prerequisites +/// 2. Initialize services +/// 3. Create a new node.js project +/// 4. Install dependencies +/// 5. Create a config file and update contract addresses +/// 6. Publish a new datatoken +/// 7. Mint 200 tokens +/// 8. Publish a dataset +/// 9. Allow the marketplace to sell your datatokens + +/// Let's go through each step: /// Start by importing all of the necessary dependencies /// ```Typescript From 92a3d813534a838d2ffb721fe20d636e31cc48e9 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Tue, 3 May 2022 17:19:39 +0300 Subject: [PATCH 6/6] Additional text --- CodeExamples.md | 77 +++++++++++++++++++++++------ test/integration/ReadmeFlow.test.ts | 75 ++++++++++++++++++---------- 2 files changed, 112 insertions(+), 40 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index 1a231d60..24bd8792 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -1,13 +1,58 @@ # Ocean.js Code Examples -The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. +## Introduction -Start by importing all of the necessary dependencies +The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. +The process involves creating a Data NFT (which represents the base-IP on-chain) and a datatoken (which will be used to purchase the dataset). This guide provides all the code you need and no prior knowledge is required. It is helpful if you have some experience with javascript but it is not necessary. + +Selling your data over the blockchain puts you in charge of how it is used and can be a great source of passive income. There are many AI startups that have deep expertise in machine learning but need more data to improve their models. Selling your data via the blockchain gives you a level of security that you would be unable to achieve if you were selling via a centralised marketplace. + +In this guide we'll be making use of the Ocean.js library. Ocean Protocol provides you with everything you need to quickly get setup and start selling data over the blockchain. + +If you have any questions or issues at any point while following along to this article please reach out to us on [discord](https://discord.gg/TnXjkR5). + +Here are the steps we will be following throughout the article: + +1. Prerequisites +2. Create a new node.js project +3. Install dependencies +4. Define files and metadata +5. Publish a dataset + +Let's go through each step: + +## 1. Prerequisites +Before we start it is important that you have all of the necessary prerequisites installed on your computer. +- **A Unix based operating system (Linux or Mac)**. If you are a Windows user you can try to run linux inside a virtual machine but this is outside of the scope of this article. +- **Git**. Instructions for installing Git can be found here: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +- **Node.js** can be downloaded from here: https://nodejs.org/en/download/ +- **Docker** can be installed from here: https://docs.docker.com/get-docker/. Please note that Docker must run as a non-root user, you can set this up by following these instructions: https://docs.docker.com/engine/install/linux-postinstall/ + +## 2. Create a new node.js project + +You are now ready to start your project. We start by creating a new folder and initiating a new Node.js project. Open a new terminal and enter the following commands: + +```bash +mkdir quickstart +cd quickstart +npm init +# Answer the questions in the command line prompt +cat > index.js +# On linux press CTRL + D to save +``` + +## 3. Install dependencies + +```bash +npm install @oceanprotocol/lib +``` + +Now you're ready to start coding! Let's start by opening the index.js file and importing all of the necessary dependencies ```Typescript import { SHA256 } from 'crypto-js' -import { web3, getTestConfig, getAddresses } from '../config' +import { web3, getTestConfig, getAddresses } from '../config' // We'll be using the test config setup in this example import { Config, ProviderInstance, @@ -22,6 +67,8 @@ import { import { ProviderFees, Erc20CreateParams } from '../../src/@types' ``` +## 4. Define files and metadata + We will need a file to publish, so here we define the file that we intend to publish. ```Typescript @@ -68,19 +115,14 @@ const ddo = { } ``` +## 5. Publish a dataset + ```Typescript - let config: Config - let addresses: any - let aquarius: Aquarius - let providerUrl: any - - - config = await getTestConfig(web3) - addresses = getAddresses() - aquarius = new Aquarius(config.metadataCacheUri) - providerUrl = config.providerUri - }) + const config: Config = await getTestConfig(web3) + const addresses: any = getAddresses() + const aquarius: Aquarius = new Aquarius(config.metadataCacheUri) + const providerUrl: any = config.providerUri ### should publish a dataset (create NFT + ERC20) const nft = new Nft(web3) @@ -114,7 +156,12 @@ const ddo = { const erc721Address = result.events.NFTCreated.returnValues[0] const datatokenAddress = result.events.TokenCreated.returnValues[0] - // create the files encrypted string + ``` + + ### Create the files encrypted string + + ```Typescript + let providerResponse = await ProviderInstance.encrypt(assetUrl, providerUrl) ddo.services[0].files = await providerResponse ddo.services[0].datatokenAddress = datatokenAddress diff --git a/test/integration/ReadmeFlow.test.ts b/test/integration/ReadmeFlow.test.ts index fc85330c..6a526bfa 100644 --- a/test/integration/ReadmeFlow.test.ts +++ b/test/integration/ReadmeFlow.test.ts @@ -3,33 +3,56 @@ /// ## Introduction /// The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. -/// The process involves creating a Data NFT (which represents the base-IP on-chain) and a datatoken (which will be used to purchase the dataset). This guide provides all the code you need and no prior knowledge is required. It is helpful if you have some experience with javascript but it is not necessary. +/// The process involves creating a Data NFT (which represents the base-IP on-chain) and a datatoken (which will be used to purchase the dataset). This guide provides all the code you need and no prior knowledge is required. It is helpful if you have some experience with javascript but it is not necessary. -/// Selling your data over the blockchain puts you in charge of how it is used and can be a great source of passive income. There are many AI startups that have deep expertise in machine learning but need more data to improve their models. Selling your data via the blockchain gives you a level of security that you would be unable to achieve if you were selling via a centralised marketplace. +/// Selling your data over the blockchain puts you in charge of how it is used and can be a great source of passive income. There are many AI startups that have deep expertise in machine learning but need more data to improve their models. Selling your data via the blockchain gives you a level of security that you would be unable to achieve if you were selling via a centralised marketplace. /// In this guide we'll be making use of the Ocean.js library. Ocean Protocol provides you with everything you need to quickly get setup and start selling data over the blockchain. -/// If you have any questions or issues at any point while following along to this article please reach out to us on [discord](https://discord.gg/TnXjkR5). +/// If you have any questions or issues at any point while following along to this article please reach out to us on [discord](https://discord.gg/TnXjkR5). /// Here are the steps we will be following throughout the article: /// 1. Prerequisites -/// 2. Initialize services -/// 3. Create a new node.js project -/// 4. Install dependencies -/// 5. Create a config file and update contract addresses -/// 6. Publish a new datatoken -/// 7. Mint 200 tokens -/// 8. Publish a dataset -/// 9. Allow the marketplace to sell your datatokens +/// 2. Create a new node.js project +/// 3. Install dependencies +/// 4. Define files and metadata +/// 5. Publish a dataset /// Let's go through each step: -/// Start by importing all of the necessary dependencies + +/// ## 1. Prerequisites +/// Before we start it is important that you have all of the necessary prerequisites installed on your computer. +/// - **A Unix based operating system (Linux or Mac)**. If you are a Windows user you can try to run linux inside a virtual machine but this is outside of the scope of this article. +/// - **Git**. Instructions for installing Git can be found here: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +/// - **Node.js** can be downloaded from here: https://nodejs.org/en/download/ +/// - **Docker** can be installed from here: https://docs.docker.com/get-docker/. Please note that Docker must run as a non-root user, you can set this up by following these instructions: https://docs.docker.com/engine/install/linux-postinstall/ + +/// ## 2. Create a new node.js project + +/// You are now ready to start your project. We start by creating a new folder and initiating a new Node.js project. Open a new terminal and enter the following commands: + +/// ```bash +/// mkdir quickstart +/// cd quickstart +/// npm init +/// # Answer the questions in the command line prompt +/// cat > index.js +/// # On linux press CTRL + D to save +/// ``` + +/// ## 3. Install dependencies + +/// ```bash +/// npm install @oceanprotocol/lib +/// ``` + +/// Now you're ready to start coding! Let's start by opening the index.js file and importing all of the necessary dependencies /// ```Typescript import { assert } from 'chai' import { SHA256 } from 'crypto-js' -import { web3, getTestConfig, getAddresses } from '../config' +import { web3, getTestConfig, getAddresses } from '../config' // We'll be using the test config setup in this example import { Config, ProviderInstance, @@ -44,6 +67,8 @@ import { import { ProviderFees, Erc20CreateParams } from '../../src/@types' /// ``` +/// ## 4. Define files and metadata + /// We will need a file to publish, so here we define the file that we intend to publish. /// ```Typescript @@ -90,19 +115,14 @@ const ddo = { } /// ``` +/// ## 5. Publish a dataset + /// ```Typescript describe('Simple Publish & Consume Flow', async () => { - let config: Config - let addresses: any - let aquarius: Aquarius - let providerUrl: any - - before(async () => { - config = await getTestConfig(web3) - addresses = getAddresses() - aquarius = new Aquarius(config.metadataCacheUri) - providerUrl = config.providerUri - }) + const config: Config = await getTestConfig(web3) + const addresses: any = getAddresses() + const aquarius: Aquarius = new Aquarius(config.metadataCacheUri) + const providerUrl: any = config.providerUri it('should publish a dataset (create NFT + ERC20)', async () => { const nft = new Nft(web3) @@ -136,7 +156,12 @@ describe('Simple Publish & Consume Flow', async () => { const erc721Address = result.events.NFTCreated.returnValues[0] const datatokenAddress = result.events.TokenCreated.returnValues[0] - // create the files encrypted string + /// ``` + + /// ### Create the files encrypted string + + /// ```Typescript + let providerResponse = await ProviderInstance.encrypt(assetUrl, providerUrl) ddo.services[0].files = await providerResponse ddo.services[0].datatokenAddress = datatokenAddress