From 1055ef991ca52cd9d7650480b3d996605ce42d3d Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 21 Apr 2022 15:45:11 +0200 Subject: [PATCH 01/58] 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 02/58] 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 03/58] 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 04/58] 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 5f20019aba89f316ea474e02e06a1d290cad405f Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 25 Apr 2022 15:58:28 +0200 Subject: [PATCH 05/58] add marketplace flow test --- package.json | 1 + test/integration/MarketplaceFlow.test.ts | 0 2 files changed, 1 insertion(+) create mode 100644 test/integration/MarketplaceFlow.test.ts diff --git a/package.json b/package.json index ce728ea2..d17104da 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "test:factory": "npm run mocha -- 'test/unit/NftFactory.test.ts'", "test:router": "npm run mocha -- 'test/unit/pools/Router.test.ts'", "test:publishAll": "npm run mocha -- 'test/integration/PublishFlows.test.ts'", + "test:marketplace": "npm run mocha -- 'test/integration/MarketplaceFlow.test.ts'", "test:unit": "npm run mocha -- 'test/unit/**/*.test.ts'", "test:unit:cover": "nyc --report-dir coverage/unit npm run test:unit", "test:integration": "npm run mocha -- 'test/integration/**/*.test.ts'", diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts new file mode 100644 index 00000000..e69de29b From 992220abfcdd4cfe612678fe7470904ff9b1b428 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Tue, 26 Apr 2022 15:15:08 +0200 Subject: [PATCH 06/58] add MarketplaceFlow test code --- test/integration/MarketplaceFlow.test.ts | 172 +++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index e69de29b..80af2bad 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -0,0 +1,172 @@ +import { assert } from 'chai' +import { SHA256 } from 'crypto-js' +import { + approve, + Aquarius, + Config, + Datatoken, + downloadFile, + Erc20CreateParams, + getHash, + Nft, + NftCreateData, + NftFactory, + Pool, + PoolCreationParams, + ProviderFees, + ProviderInstance, + ZERO_ADDRESS +} from '../../src' +import { getTestConfig, web3 } from '../config' +import { Addresses, deployContracts } from '../TestContractHandler' + +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: '', + version: '4.0.0', + chainId: 4, + nftAddress: '0x0', + metadata: { + created: '2021-12-20T14:35:20Z', + updated: '2021-12-20T14:35:20Z', + type: 'dataset', + name: 'dataset-name', + description: 'Ocean protocol test dataset description', + author: 'oceanprotocol-team', + license: 'MIT' + }, + services: [ + { + id: 'testFakeId', + type: 'access', + files: '', + datatokenAddress: '0x0', + serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', + timeout: 0 + } + ] +} + +describe('Marketplace flow tests', async () => { + let config: Config + let aquarius: Aquarius + let providerUrl: any + let publisherAccount: string + let consumerAccount: string + let contracts: Addresses + + before(async () => { + const accounts = await web3.eth.getAccounts() + publisherAccount = accounts[0] + consumerAccount = accounts[1] + + console.log(`Publisher account address: ${publisherAccount}`) + console.log(`Consumer account address: ${consumerAccount}`) + + config = await getTestConfig(web3) + aquarius = new Aquarius(config.metadataCacheUri) + providerUrl = 'http://127.0.0.1:8030' // config.providerUri + + console.log(`Aquarius URL: ${config.metadataCacheUri}`) + console.log(`Provider URL: ${providerUrl}`) + + contracts = await deployContracts(web3, publisherAccount) + + await approve( + web3, + publisherAccount, + contracts.oceanAddress, + contracts.erc721FactoryAddress, + '10000' + ) + }) + + it('should publish a dataset (create NFT + ERC20)', async () => { + const nft = new Nft(web3) + const datatoken = new Datatoken(web3) + const factory = new NftFactory(contracts.erc721FactoryAddress, web3) + + const nftParams: NftCreateData = { + name: 'Datatoken 1', + symbol: 'DT1', + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: publisherAccount + } + + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: publisherAccount, + mpFeeAddress: ZERO_ADDRESS + } + + const poolParams: PoolCreationParams = { + ssContract: contracts.sideStakingAddress, + baseTokenAddress: contracts.oceanAddress, + baseTokenSender: contracts.erc721FactoryAddress, + publisherAddress: publisherAccount, + marketFeeCollector: publisherAccount, + poolTemplateAddress: contracts.poolTemplateAddress, + rate: '1', + baseTokenDecimals: 18, + vestingAmount: '10000', + vestedBlocks: 2500000, + initialBaseTokenLiquidity: '2000', + swapFeeLiquidityProvider: '0.001', + swapFeeMarketRunner: '0.001' + } + + const tx = await factory.createNftErc20WithPool( + publisherAccount, + nftParams, + erc20Params, + poolParams + ) + + const erc721Address = tx.events.NFTCreated.returnValues[0] + const datatokenAddress = tx.events.TokenCreated.returnValues[0] + const poolAdress = tx.events.NewPool.returnValues[0] + + console.log(`NFT address: ${erc721Address}`) + console.log(`Datatoken address: ${datatokenAddress}`) + console.log(`Pool address: ${poolAdress}`) + + // update ddo and set the right did + ddo.chainId = await web3.eth.getChainId() + ddo.id = + 'did:op:' + + SHA256(web3.utils.toChecksumAddress(erc721Address) + ddo.chainId.toString(10)) + ddo.nftAddress = erc721Address + // encrypt file(s) using provider + const encryptedFiles = await ProviderInstance.encrypt(assetUrl, providerUrl) + ddo.services[0].files = await encryptedFiles + ddo.services[0].datatokenAddress = datatokenAddress + + console.log(`DID: ${ddo.id}`) + + // Marketplace displays asset for sale + const pool = new Pool(web3) + const prices = await pool.getAmountInExactOut( + poolAdress, + datatokenAddress, + contracts.oceanAddress, + '1', + '0.01' + ) + console.log(prices) + console.log(`Price of 1 ${nftParams.symbol} is ${prices.tokenAmount}`) + }) +}) From ca1fb4579717c164bb03f5dc2434de505118b011 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Wed, 27 Apr 2022 10:31:19 +0200 Subject: [PATCH 07/58] consumer buys data asset, and downloads it --- test/integration/MarketplaceFlow.test.ts | 250 +++++++++++++++++------ 1 file changed, 186 insertions(+), 64 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 80af2bad..493c2aab 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -1,8 +1,10 @@ import { assert } from 'chai' import { SHA256 } from 'crypto-js' import { + AmountsOutMaxFee, approve, Aquarius, + balance, Config, Datatoken, downloadFile, @@ -15,46 +17,12 @@ import { PoolCreationParams, ProviderFees, ProviderInstance, + TokenInOutMarket, ZERO_ADDRESS } from '../../src' import { getTestConfig, web3 } from '../config' import { Addresses, deployContracts } from '../TestContractHandler' -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: '', - version: '4.0.0', - chainId: 4, - nftAddress: '0x0', - metadata: { - created: '2021-12-20T14:35:20Z', - updated: '2021-12-20T14:35:20Z', - type: 'dataset', - name: 'dataset-name', - description: 'Ocean protocol test dataset description', - author: 'oceanprotocol-team', - license: 'MIT' - }, - services: [ - { - id: 'testFakeId', - type: 'access', - files: '', - datatokenAddress: '0x0', - serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', - timeout: 0 - } - ] -} - describe('Marketplace flow tests', async () => { let config: Config let aquarius: Aquarius @@ -62,22 +30,68 @@ describe('Marketplace flow tests', async () => { let publisherAccount: string let consumerAccount: string let contracts: Addresses + let erc721Address: string + let datatokenAddress: string + let poolAddress: string + + const NFT_NAME = 'Datatoken 1' + const NFT_SYMBOL = 'DT1' + const CAP_AMOUNT = '100000' + + const ASSET_URL = [ + { + 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: '', + version: '4.0.0', + chainId: 4, + nftAddress: '0x0', + metadata: { + created: '2021-12-20T14:35:20Z', + updated: '2021-12-20T14:35:20Z', + type: 'dataset', + name: 'dataset-name', + description: 'Ocean protocol test dataset description', + author: 'oceanprotocol-team', + license: 'MIT' + }, + services: [ + { + id: 'testFakeId', + type: 'access', + files: '', + datatokenAddress: '0x0', + serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', + timeout: 0 + } + ] + } before(async () => { - const accounts = await web3.eth.getAccounts() - publisherAccount = accounts[0] - consumerAccount = accounts[1] - - console.log(`Publisher account address: ${publisherAccount}`) - console.log(`Consumer account address: ${consumerAccount}`) - config = await getTestConfig(web3) aquarius = new Aquarius(config.metadataCacheUri) providerUrl = 'http://127.0.0.1:8030' // config.providerUri console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) + }) + it('initialize accounts', async () => { + const accounts = await web3.eth.getAccounts() + publisherAccount = accounts[0] + consumerAccount = accounts[1] + + console.log(`Publisher account address: ${publisherAccount}`) + console.log(`Consumer account address: ${consumerAccount}`) + }) + + it('deploy contracts', async () => { contracts = await deployContracts(web3, publisherAccount) await approve( @@ -89,14 +103,12 @@ describe('Marketplace flow tests', async () => { ) }) - it('should publish a dataset (create NFT + ERC20)', async () => { - const nft = new Nft(web3) - const datatoken = new Datatoken(web3) + it('publish a dataset (create NFT + ERC20) with a liquidity pool', async () => { const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { - name: 'Datatoken 1', - symbol: 'DT1', + name: NFT_NAME, + symbol: NFT_SYMBOL, templateIndex: 1, tokenURI: '', transferable: true, @@ -105,7 +117,7 @@ describe('Marketplace flow tests', async () => { const erc20Params: Erc20CreateParams = { templateIndex: 1, - cap: '100000', + cap: CAP_AMOUNT, feeAmount: '0', paymentCollector: ZERO_ADDRESS, feeToken: ZERO_ADDRESS, @@ -136,37 +148,147 @@ describe('Marketplace flow tests', async () => { poolParams ) - const erc721Address = tx.events.NFTCreated.returnValues[0] - const datatokenAddress = tx.events.TokenCreated.returnValues[0] - const poolAdress = tx.events.NewPool.returnValues[0] + erc721Address = tx.events.NFTCreated.returnValues[0] + datatokenAddress = tx.events.TokenCreated.returnValues[0] + poolAddress = tx.events.NewPool.returnValues[0] console.log(`NFT address: ${erc721Address}`) console.log(`Datatoken address: ${datatokenAddress}`) - console.log(`Pool address: ${poolAdress}`) + console.log(`Pool address: ${poolAddress}`) // update ddo and set the right did - ddo.chainId = await web3.eth.getChainId() - ddo.id = + DDO.chainId = await web3.eth.getChainId() + DDO.id = 'did:op:' + - SHA256(web3.utils.toChecksumAddress(erc721Address) + ddo.chainId.toString(10)) - ddo.nftAddress = erc721Address + SHA256(web3.utils.toChecksumAddress(erc721Address) + DDO.chainId.toString(10)) + DDO.nftAddress = erc721Address // encrypt file(s) using provider - const encryptedFiles = await ProviderInstance.encrypt(assetUrl, providerUrl) - ddo.services[0].files = await encryptedFiles - ddo.services[0].datatokenAddress = datatokenAddress + const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) + DDO.services[0].files = await encryptedFiles + DDO.services[0].datatokenAddress = datatokenAddress - console.log(`DID: ${ddo.id}`) + console.log(`DID: ${DDO.id}`) + }) - // Marketplace displays asset for sale + it('set metadata in the NFT', async () => { + const nft = new Nft(web3) + const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) + const encryptedDDO = await providerResponse + const metadataHash = getHash(JSON.stringify(DDO)) + await nft.setMetadata( + erc721Address, + publisherAccount, + 0, + providerUrl, + '', + '0x2', + encryptedDDO, + '0x' + metadataHash + ) + // TODO: const resolvedDDO = await aquarius.waitForAqua(DDO.id) + // TODO: assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + }) + + it('marketplace displays asset for sale', async () => { const pool = new Pool(web3) const prices = await pool.getAmountInExactOut( - poolAdress, + poolAddress, datatokenAddress, contracts.oceanAddress, '1', '0.01' ) - console.log(prices) - console.log(`Price of 1 ${nftParams.symbol} is ${prices.tokenAmount}`) + console.log(`Price of 1 ${NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) + }) + + it('consumer buys data asset, and downloads it', async () => { + const datatoken = new Datatoken(web3) + + const consumerETHBalance = await web3.eth.getBalance(consumerAccount) + console.log(`Consumer ETH balance: ${consumerETHBalance}`) + let consumerOCEANBalance = await balance( + web3, + contracts.oceanAddress, + publisherAccount + ) + console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) + let consumerDTBalance = await balance(web3, datatokenAddress, publisherAccount) + console.log(`Consumer ${NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) + + await approve(web3, publisherAccount, contracts.oceanAddress, poolAddress, '100') + + const pool = new Pool(web3) + const tokenInOutMarket: TokenInOutMarket = { + tokenIn: contracts.oceanAddress, + tokenOut: datatokenAddress, + marketFeeAddress: publisherAccount + } + const amountsInOutMaxFee: AmountsOutMaxFee = { + maxAmountIn: '10', + tokenAmountOut: '1', + swapMarketFee: '0.1' + } + await pool.swapExactAmountOut( + publisherAccount, + poolAddress, + tokenInOutMarket, + amountsInOutMaxFee + ) + + consumerOCEANBalance = await balance(web3, contracts.oceanAddress, publisherAccount) + console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) + consumerDTBalance = await balance(web3, datatokenAddress, publisherAccount) + console.log(`Consumer ${NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) + + // initialize provider + const initializeData = await ProviderInstance.initialize( + DDO.id, + DDO.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, + publisherAccount, + publisherAccount, + 0, + providerFees + ) + // get the url + const downloadURL = await ProviderInstance.getDownloadUrl( + DDO.id, + publisherAccount, + DDO.services[0].id, + 0, + txid.transactionHash, + providerUrl, + web3 + ) + + console.log(`Download URL: ${downloadURL}`) + + consumerOCEANBalance = await balance(web3, contracts.oceanAddress, publisherAccount) + console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) + consumerDTBalance = await balance(web3, datatokenAddress, publisherAccount) + console.log(`Consumer ${NFT_SYMBOL} balance after order: ${consumerDTBalance}`) + + try { + const fileData = await downloadFile(downloadURL) + console.log(fileData) + } catch (e) { + assert.fail('Download failed') + } }) }) From 5745ba4d9474754dff68fb8b95c3a3922002472d Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Wed, 27 Apr 2022 10:38:49 +0200 Subject: [PATCH 08/58] show initializeData --- test/integration/MarketplaceFlow.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 493c2aab..5f4f6e52 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -248,6 +248,7 @@ describe('Marketplace flow tests', async () => { consumerAccount, providerUrl ) + console.log(initializeData) const providerFees: ProviderFees = { providerFeeAddress: initializeData.providerFee.providerFeeAddress, providerFeeToken: initializeData.providerFee.providerFeeToken, From af28d889cd8f61b8f1ef3833900a0787e9d1cbbb Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Wed, 27 Apr 2022 10:52:33 +0200 Subject: [PATCH 09/58] add aquarius.waitForAqua() --- test/integration/MarketplaceFlow.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 5f4f6e52..f6f8e909 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -240,10 +240,13 @@ describe('Marketplace flow tests', async () => { consumerDTBalance = await balance(web3, datatokenAddress, publisherAccount) console.log(`Consumer ${NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) + const resolvedDDO = await aquarius.waitForAqua(DDO.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + // initialize provider const initializeData = await ProviderInstance.initialize( - DDO.id, - DDO.services[0].id, + resolvedDDO.id, + resolvedDDO.services[0].id, 0, consumerAccount, providerUrl From 64c464239c6a0d6c7b8b1aad4f5e13deeebf9ca1 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 27 Apr 2022 17:23:18 +0300 Subject: [PATCH 10/58] 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 77db0f7e9fbe8d65769e4373e9bf398c11d93d89 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Wed, 27 Apr 2022 17:57:21 +0200 Subject: [PATCH 11/58] add markdown documentation comments --- test/integration/MarketplaceFlow.test.ts | 108 ++++++++++++++++++++--- 1 file changed, 95 insertions(+), 13 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index f6f8e909..9a2ed80b 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -1,3 +1,71 @@ +/// # Quickstart: Marketplace Flow + +/// This quickstart describes a batteries-included flow including using off-chain services for metadata (Aquarius) and consuming datasets (Provider). + +/// For pool creation, it is used as base token, OCEAN token. The base token can be changed into something else, such as USDC, DAI etc., but it will require an extra fee. + +/// 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 are the steps: + +/// 1. Initialize services +/// 2. Create a new node.js project +/// 3. Install dependancies +/// 4. Publish Data NFT, Datatoken & Pool +/// 5. Market displays the asset for sale +/// 6. Consumer buys data asset, and downloads it + +/// Let's go through each step. + +/// ## 1. Initialize services + +/// We start by initializing the services. To do this, we clone the Barge repository and run it. This will run the current default versions of [Aquarius](https://github.com/oceanprotocol/aquarius), [Provider](https://github.com/oceanprotocol/provider), and [Ganache](https://github.com/trufflesuite/ganache) with [our contracts](https://github.com/oceanprotocol/contracts) deployed to it. + +/// ```bash +/// git clone https://github.com/oceanprotocol/barge.git +/// cd barge/ +/// ./start_ocean.sh --with-provider2 --no-dashboard +/// ``` + +/// ## 2. Create a new node.js project + +/// Start by creating a new Node.js project. Open a new terminal and enter the following commands: + +/// ```bash +/// mkdir marketplace-quickstart +/// cd marketplace-quickstart +/// npm init +/// # Answer the questions in the command line prompt +/// cat > marketplace.js +/// # On linux press CTRL + D to save +/// ``` + +/// ## 3. Install dependancies + +/// Open the package.json file in a text editor and update the dependancies to include the following: + +/// ```JSON +/// "dependencies": { +/// "@oceanprotocol/contracts": "1.0.0-alpha.28", +/// "@oceanprotocol/lib": "1.0.0-next.37", +/// "crypto-js": "^4.1.1", +/// "web3": "^1.7.3" +/// } +/// ``` + +/// Now in your terminal run the following command: + +/// ```bash +/// npm install +/// ``` + +/// ## 4. Publish Data NFT, Datatoken & Pool + +/// Now open the `marketplace.js` file in your text editor. + +/// Start by importing all of the necessary dependencies + +/// ```Typescript import { assert } from 'chai' import { SHA256 } from 'crypto-js' import { @@ -22,8 +90,15 @@ import { } from '../../src' import { getTestConfig, web3 } from '../config' import { Addresses, deployContracts } from '../TestContractHandler' +/// ``` +/// + + /// Variables and constants needed for the test: + + /// ```Typescript let config: Config let aquarius: Aquarius let providerUrl: any @@ -34,10 +109,11 @@ describe('Marketplace flow tests', async () => { let datatokenAddress: string let poolAddress: string - const NFT_NAME = 'Datatoken 1' const NFT_SYMBOL = 'DT1' - const CAP_AMOUNT = '100000' + /// ``` + /// We will need a file to publish, so here we define the file that we intend to publish. + /// ```Typescript const ASSET_URL = [ { type: 'url', @@ -45,7 +121,10 @@ describe('Marketplace flow tests', async () => { 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: '', @@ -72,7 +151,9 @@ describe('Marketplace flow tests', async () => { } ] } + /// ``` + /// ```Typescript before(async () => { config = await getTestConfig(web3) aquarius = new Aquarius(config.metadataCacheUri) @@ -93,22 +174,14 @@ describe('Marketplace flow tests', async () => { it('deploy contracts', async () => { contracts = await deployContracts(web3, publisherAccount) - - await approve( - web3, - publisherAccount, - contracts.oceanAddress, - contracts.erc721FactoryAddress, - '10000' - ) }) it('publish a dataset (create NFT + ERC20) with a liquidity pool', async () => { const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { - name: NFT_NAME, - symbol: NFT_SYMBOL, + name: 'Datatoken 1', + symbol: 'DT1', templateIndex: 1, tokenURI: '', transferable: true, @@ -117,7 +190,7 @@ describe('Marketplace flow tests', async () => { const erc20Params: Erc20CreateParams = { templateIndex: 1, - cap: CAP_AMOUNT, + cap: '100000', feeAmount: '0', paymentCollector: ZERO_ADDRESS, feeToken: ZERO_ADDRESS, @@ -141,6 +214,14 @@ describe('Marketplace flow tests', async () => { swapFeeMarketRunner: '0.001' } + await approve( + web3, + publisherAccount, + contracts.oceanAddress, + contracts.erc721FactoryAddress, + '10000' + ) + const tx = await factory.createNftErc20WithPool( publisherAccount, nftParams, @@ -296,3 +377,4 @@ describe('Marketplace flow tests', async () => { } }) }) +/// ``` From 06c1046943f518c02146eec2227cb22908e56f71 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 08:53:03 +0200 Subject: [PATCH 12/58] update provider url --- test/integration/MarketplaceFlow.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 9a2ed80b..aafe7f26 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -157,7 +157,7 @@ describe('Marketplace flow tests', async () => { before(async () => { config = await getTestConfig(web3) aquarius = new Aquarius(config.metadataCacheUri) - providerUrl = 'http://127.0.0.1:8030' // config.providerUri + providerUrl = config.providerUri console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) @@ -181,7 +181,7 @@ describe('Marketplace flow tests', async () => { const nftParams: NftCreateData = { name: 'Datatoken 1', - symbol: 'DT1', + symbol: NFT_SYMBOL, templateIndex: 1, tokenURI: '', transferable: true, @@ -266,8 +266,6 @@ describe('Marketplace flow tests', async () => { encryptedDDO, '0x' + metadataHash ) - // TODO: const resolvedDDO = await aquarius.waitForAqua(DDO.id) - // TODO: assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') }) it('marketplace displays asset for sale', async () => { From 431808777c36a60be4c168c3ec69fd612f527d4b Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 09:10:19 +0200 Subject: [PATCH 13/58] add markdown comments --- test/integration/MarketplaceFlow.test.ts | 30 +++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index aafe7f26..23155b2d 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -153,6 +153,7 @@ describe('Marketplace flow tests', async () => { } /// ``` + /// We load the configuration: /// ```Typescript before(async () => { config = await getTestConfig(web3) @@ -162,8 +163,10 @@ describe('Marketplace flow tests', async () => { console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) }) + /// ``` - it('initialize accounts', async () => { + it('Initialize accounts', async () => { + /// ```Typescript const accounts = await web3.eth.getAccounts() publisherAccount = accounts[0] consumerAccount = accounts[1] @@ -171,12 +174,16 @@ describe('Marketplace flow tests', async () => { console.log(`Publisher account address: ${publisherAccount}`) console.log(`Consumer account address: ${consumerAccount}`) }) + /// ``` - it('deploy contracts', async () => { + it('Deploy contracts', async () => { + /// ```Typescript contracts = await deployContracts(web3, publisherAccount) }) + /// ``` - it('publish a dataset (create NFT + ERC20) with a liquidity pool', async () => { + it('Publish a dataset (create NFT + ERC20) with a liquidity pool', async () => { + /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { @@ -236,6 +243,12 @@ describe('Marketplace flow tests', async () => { console.log(`NFT address: ${erc721Address}`) console.log(`Datatoken address: ${datatokenAddress}`) console.log(`Pool address: ${poolAddress}`) + }) + /// ``` + + it('Set metadata in the NFT', async () => { + /// ```Typescript + const nft = new Nft(web3) // update ddo and set the right did DDO.chainId = await web3.eth.getChainId() @@ -249,10 +262,7 @@ describe('Marketplace flow tests', async () => { DDO.services[0].datatokenAddress = datatokenAddress console.log(`DID: ${DDO.id}`) - }) - it('set metadata in the NFT', async () => { - const nft = new Nft(web3) const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) const encryptedDDO = await providerResponse const metadataHash = getHash(JSON.stringify(DDO)) @@ -267,8 +277,10 @@ describe('Marketplace flow tests', async () => { '0x' + metadataHash ) }) + /// ``` - it('marketplace displays asset for sale', async () => { + it('Marketplace displays asset for sale', async () => { + /// ```Typescript const pool = new Pool(web3) const prices = await pool.getAmountInExactOut( poolAddress, @@ -279,8 +291,10 @@ describe('Marketplace flow tests', async () => { ) console.log(`Price of 1 ${NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) }) + /// ``` - it('consumer buys data asset, and downloads it', async () => { + it('Consumer buys data asset, and downloads it', async () => { + /// ```Typescript const datatoken = new Datatoken(web3) const consumerETHBalance = await web3.eth.getBalance(consumerAccount) From 8e1e3ec06be6ec080298eb79eefe4a7b5597e8ff Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 09:16:19 +0200 Subject: [PATCH 14/58] send OCEAN tokens to consumer account --- test/integration/MarketplaceFlow.test.ts | 26 +++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 23155b2d..cc584b33 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -67,7 +67,9 @@ /// ```Typescript import { assert } from 'chai' +import { AbiItem } from 'web3-utils/types' import { SHA256 } from 'crypto-js' +import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' import { AmountsOutMaxFee, approve, @@ -297,24 +299,34 @@ describe('Marketplace flow tests', async () => { /// ```Typescript const datatoken = new Datatoken(web3) + // we send some OCEAN to consumer account + const oceanContract = new web3.eth.Contract( + MockERC20.abi as AbiItem[], + contracts.daiAddress + ) + + await oceanContract.methods + .transfer(consumerAccount, web3.utils.toWei('2')) + .send({ from: publisherAccount }) + const consumerETHBalance = await web3.eth.getBalance(consumerAccount) console.log(`Consumer ETH balance: ${consumerETHBalance}`) let consumerOCEANBalance = await balance( web3, contracts.oceanAddress, - publisherAccount + consumerAccount ) console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) - let consumerDTBalance = await balance(web3, datatokenAddress, publisherAccount) + let consumerDTBalance = await balance(web3, datatokenAddress, consumerAccount) console.log(`Consumer ${NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) - await approve(web3, publisherAccount, contracts.oceanAddress, poolAddress, '100') + await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') const pool = new Pool(web3) const tokenInOutMarket: TokenInOutMarket = { tokenIn: contracts.oceanAddress, tokenOut: datatokenAddress, - marketFeeAddress: publisherAccount + marketFeeAddress: consumerAccount } const amountsInOutMaxFee: AmountsOutMaxFee = { maxAmountIn: '10', @@ -322,15 +334,15 @@ describe('Marketplace flow tests', async () => { swapMarketFee: '0.1' } await pool.swapExactAmountOut( - publisherAccount, + consumerAccount, poolAddress, tokenInOutMarket, amountsInOutMaxFee ) - consumerOCEANBalance = await balance(web3, contracts.oceanAddress, publisherAccount) + consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, datatokenAddress, publisherAccount) + consumerDTBalance = await balance(web3, datatokenAddress, consumerAccount) console.log(`Consumer ${NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) const resolvedDDO = await aquarius.waitForAqua(DDO.id) From 7bb77d6443a3aee6d2a8a4f4d55724458129197f Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 09:18:28 +0200 Subject: [PATCH 15/58] fix lint issues --- test/integration/MarketplaceFlow.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index cc584b33..a79f5137 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -168,7 +168,7 @@ describe('Marketplace flow tests', async () => { /// ``` it('Initialize accounts', async () => { - /// ```Typescript + /// ```Typescript const accounts = await web3.eth.getAccounts() publisherAccount = accounts[0] consumerAccount = accounts[1] @@ -179,13 +179,13 @@ describe('Marketplace flow tests', async () => { /// ``` it('Deploy contracts', async () => { - /// ```Typescript + /// ```Typescript contracts = await deployContracts(web3, publisherAccount) }) /// ``` it('Publish a dataset (create NFT + ERC20) with a liquidity pool', async () => { - /// ```Typescript + /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { @@ -249,7 +249,7 @@ describe('Marketplace flow tests', async () => { /// ``` it('Set metadata in the NFT', async () => { - /// ```Typescript + /// ```Typescript const nft = new Nft(web3) // update ddo and set the right did @@ -282,7 +282,7 @@ describe('Marketplace flow tests', async () => { /// ``` it('Marketplace displays asset for sale', async () => { - /// ```Typescript + /// ```Typescript const pool = new Pool(web3) const prices = await pool.getAmountInExactOut( poolAddress, @@ -296,7 +296,7 @@ describe('Marketplace flow tests', async () => { /// ``` it('Consumer buys data asset, and downloads it', async () => { - /// ```Typescript + /// ```Typescript const datatoken = new Datatoken(web3) // we send some OCEAN to consumer account From 8060ad683b970de3a1ce0abc0644f530a8acef3e Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 09:29:01 +0200 Subject: [PATCH 16/58] fix OCEAN address --- test/integration/MarketplaceFlow.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index a79f5137..9a98e516 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -302,7 +302,7 @@ describe('Marketplace flow tests', async () => { // we send some OCEAN to consumer account const oceanContract = new web3.eth.Contract( MockERC20.abi as AbiItem[], - contracts.daiAddress + contracts.oceanAddress ) await oceanContract.methods From 7354814f49a842e10b1c97189191678d6d09888c Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 09:37:39 +0200 Subject: [PATCH 17/58] fix consumer address --- test/integration/MarketplaceFlow.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 9a98e516..13777550 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -370,15 +370,15 @@ describe('Marketplace flow tests', async () => { // make the payment const txid = await datatoken.startOrder( datatokenAddress, - publisherAccount, - publisherAccount, + consumerAccount, + consumerAccount, 0, providerFees ) // get the url const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, - publisherAccount, + consumerAccount, DDO.services[0].id, 0, txid.transactionHash, @@ -388,9 +388,9 @@ describe('Marketplace flow tests', async () => { console.log(`Download URL: ${downloadURL}`) - consumerOCEANBalance = await balance(web3, contracts.oceanAddress, publisherAccount) + consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, datatokenAddress, publisherAccount) + consumerDTBalance = await balance(web3, datatokenAddress, consumerAccount) console.log(`Consumer ${NFT_SYMBOL} balance after order: ${consumerDTBalance}`) try { From f7cfc5e6a86e2a74fedf756aa5f09cb894a39ce1 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 23:12:28 +0200 Subject: [PATCH 18/58] send some OCEAN to consumer account --- test/integration/MarketplaceFlow.test.ts | 33 +++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 13777550..80ddf91c 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -66,7 +66,7 @@ /// Start by importing all of the necessary dependencies /// ```Typescript -import { assert } from 'chai' +import { assert, expect } from 'chai' import { AbiItem } from 'web3-utils/types' import { SHA256 } from 'crypto-js' import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' @@ -184,6 +184,25 @@ describe('Marketplace flow tests', async () => { }) /// ``` + it('We send some OCEAN to consumer account', async () => { + /// ```Typescript + const oceanContract = new web3.eth.Contract( + MockERC20.abi as AbiItem[], + contracts.oceanAddress + ) + + const balanceBefore = await oceanContract.methods.balanceOf(consumerAccount).call() + + await oceanContract.methods + .transfer(consumerAccount, web3.utils.toWei('10')) + .send({ from: publisherAccount }) + + expect(await oceanContract.methods.balanceOf(consumerAccount).call()).to.equal( + (+balanceBefore + +web3.utils.toWei('10')).toString() + ) + }) + /// ``` + it('Publish a dataset (create NFT + ERC20) with a liquidity pool', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) @@ -228,7 +247,7 @@ describe('Marketplace flow tests', async () => { publisherAccount, contracts.oceanAddress, contracts.erc721FactoryAddress, - '10000' + poolParams.vestingAmount ) const tx = await factory.createNftErc20WithPool( @@ -299,16 +318,6 @@ describe('Marketplace flow tests', async () => { /// ```Typescript const datatoken = new Datatoken(web3) - // we send some OCEAN to consumer account - const oceanContract = new web3.eth.Contract( - MockERC20.abi as AbiItem[], - contracts.oceanAddress - ) - - await oceanContract.methods - .transfer(consumerAccount, web3.utils.toWei('2')) - .send({ from: publisherAccount }) - const consumerETHBalance = await web3.eth.getBalance(consumerAccount) console.log(`Consumer ETH balance: ${consumerETHBalance}`) let consumerOCEANBalance = await balance( From 978fc0bc5d0c4b4f945b11f9b1c8280bacbaaa1f Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 23:35:53 +0200 Subject: [PATCH 19/58] user should add liquidity to the pool, receiving LP tokens --- test/integration/MarketplaceFlow.test.ts | 25 +++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 80ddf91c..96d7ff89 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -66,7 +66,7 @@ /// Start by importing all of the necessary dependencies /// ```Typescript -import { assert, expect } from 'chai' +import { assert } from 'chai' import { AbiItem } from 'web3-utils/types' import { SHA256 } from 'crypto-js' import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' @@ -106,6 +106,7 @@ describe('Marketplace flow tests', async () => { let providerUrl: any let publisherAccount: string let consumerAccount: string + let liquidityAccount: string let contracts: Addresses let erc721Address: string let datatokenAddress: string @@ -172,9 +173,11 @@ describe('Marketplace flow tests', async () => { const accounts = await web3.eth.getAccounts() publisherAccount = accounts[0] consumerAccount = accounts[1] + liquidityAccount = accounts[2] console.log(`Publisher account address: ${publisherAccount}`) console.log(`Consumer account address: ${consumerAccount}`) + console.log(`Liquidity account address: ${liquidityAccount}`) }) /// ``` @@ -184,22 +187,20 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('We send some OCEAN to consumer account', async () => { + it('We send some OCEAN to consumer and liquidity account', async () => { /// ```Typescript const oceanContract = new web3.eth.Contract( MockERC20.abi as AbiItem[], contracts.oceanAddress ) - const balanceBefore = await oceanContract.methods.balanceOf(consumerAccount).call() - await oceanContract.methods .transfer(consumerAccount, web3.utils.toWei('10')) .send({ from: publisherAccount }) - expect(await oceanContract.methods.balanceOf(consumerAccount).call()).to.equal( - (+balanceBefore + +web3.utils.toWei('10')).toString() - ) + await oceanContract.methods + .transfer(liquidityAccount, web3.utils.toWei('10')) + .send({ from: publisherAccount }) }) /// ``` @@ -300,6 +301,16 @@ describe('Marketplace flow tests', async () => { }) /// ``` + it('User should add liquidity to the pool, receiving LP tokens', async () => { + /// ```Typescript + const pool = new Pool(web3) + + await approve(web3, liquidityAccount, contracts.oceanAddress, poolAddress, '5', true) + + await pool.joinswapExternAmountIn(liquidityAccount, poolAddress, '5', '0.1') + }) + /// ``` + it('Marketplace displays asset for sale', async () => { /// ```Typescript const pool = new Pool(web3) From 41c7a34fa5e62f2e79e2bfad5c20da40d09f7692 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 23:40:33 +0200 Subject: [PATCH 20/58] rename nft and datatoken variables --- test/integration/MarketplaceFlow.test.ts | 34 ++++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 96d7ff89..b603a228 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -108,8 +108,8 @@ describe('Marketplace flow tests', async () => { let consumerAccount: string let liquidityAccount: string let contracts: Addresses - let erc721Address: string - let datatokenAddress: string + let poolNftAddress: string + let poolDatatokenAddress: string let poolAddress: string const NFT_SYMBOL = 'DT1' @@ -258,12 +258,12 @@ describe('Marketplace flow tests', async () => { poolParams ) - erc721Address = tx.events.NFTCreated.returnValues[0] - datatokenAddress = tx.events.TokenCreated.returnValues[0] + poolNftAddress = tx.events.NFTCreated.returnValues[0] + poolDatatokenAddress = tx.events.TokenCreated.returnValues[0] poolAddress = tx.events.NewPool.returnValues[0] - console.log(`NFT address: ${erc721Address}`) - console.log(`Datatoken address: ${datatokenAddress}`) + console.log(`NFT address: ${poolNftAddress}`) + console.log(`Datatoken address: ${poolDatatokenAddress}`) console.log(`Pool address: ${poolAddress}`) }) /// ``` @@ -276,12 +276,12 @@ describe('Marketplace flow tests', async () => { DDO.chainId = await web3.eth.getChainId() DDO.id = 'did:op:' + - SHA256(web3.utils.toChecksumAddress(erc721Address) + DDO.chainId.toString(10)) - DDO.nftAddress = erc721Address + SHA256(web3.utils.toChecksumAddress(poolNftAddress) + DDO.chainId.toString(10)) + DDO.nftAddress = poolNftAddress // encrypt file(s) using provider const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) DDO.services[0].files = await encryptedFiles - DDO.services[0].datatokenAddress = datatokenAddress + DDO.services[0].datatokenAddress = poolDatatokenAddress console.log(`DID: ${DDO.id}`) @@ -289,7 +289,7 @@ describe('Marketplace flow tests', async () => { const encryptedDDO = await providerResponse const metadataHash = getHash(JSON.stringify(DDO)) await nft.setMetadata( - erc721Address, + poolNftAddress, publisherAccount, 0, providerUrl, @@ -316,7 +316,7 @@ describe('Marketplace flow tests', async () => { const pool = new Pool(web3) const prices = await pool.getAmountInExactOut( poolAddress, - datatokenAddress, + poolDatatokenAddress, contracts.oceanAddress, '1', '0.01' @@ -337,7 +337,7 @@ describe('Marketplace flow tests', async () => { consumerAccount ) console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) - let consumerDTBalance = await balance(web3, datatokenAddress, consumerAccount) + let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) console.log(`Consumer ${NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') @@ -345,7 +345,7 @@ describe('Marketplace flow tests', async () => { const pool = new Pool(web3) const tokenInOutMarket: TokenInOutMarket = { tokenIn: contracts.oceanAddress, - tokenOut: datatokenAddress, + tokenOut: poolDatatokenAddress, marketFeeAddress: consumerAccount } const amountsInOutMaxFee: AmountsOutMaxFee = { @@ -362,7 +362,7 @@ describe('Marketplace flow tests', async () => { consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, datatokenAddress, consumerAccount) + consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) console.log(`Consumer ${NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) const resolvedDDO = await aquarius.waitForAqua(DDO.id) @@ -389,7 +389,7 @@ describe('Marketplace flow tests', async () => { } // make the payment const txid = await datatoken.startOrder( - datatokenAddress, + poolDatatokenAddress, consumerAccount, consumerAccount, 0, @@ -410,7 +410,7 @@ describe('Marketplace flow tests', async () => { consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, datatokenAddress, consumerAccount) + consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) console.log(`Consumer ${NFT_SYMBOL} balance after order: ${consumerDTBalance}`) try { @@ -420,5 +420,5 @@ describe('Marketplace flow tests', async () => { assert.fail('Download failed') } }) + /// ``` }) -/// ``` From 7e4ca995f8e86e4f0150770251fa019b7e18749e Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Thu, 28 Apr 2022 23:47:14 +0200 Subject: [PATCH 21/58] refactor variable names --- test/integration/MarketplaceFlow.test.ts | 37 +++++++++++++++--------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index b603a228..f974ce68 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -111,8 +111,17 @@ describe('Marketplace flow tests', async () => { let poolNftAddress: string let poolDatatokenAddress: string let poolAddress: string + let freNftAddress: string + let freDatatokenAddress: string + let dispenserNftAddress: string + let dispenserDatatokenAddress: string - const NFT_SYMBOL = 'DT1' + const POOL_NFT_NAME = 'Datatoken 1' + const POOL_NFT_SYMBOL = 'DT1' + const FRE_NFT_NAME = 'Datatoken 2' + const FRE_NFT_SYMBOL = 'DT2' + const DISP_NFT_NAME = 'Datatoken 3' + const DISP_NFT_SYMBOL = 'DT3' /// ``` /// We will need a file to publish, so here we define the file that we intend to publish. @@ -187,7 +196,7 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('We send some OCEAN to consumer and liquidity account', async () => { + it('We send some OCEAN to consumer and liquidity accounts', async () => { /// ```Typescript const oceanContract = new web3.eth.Contract( MockERC20.abi as AbiItem[], @@ -195,22 +204,22 @@ describe('Marketplace flow tests', async () => { ) await oceanContract.methods - .transfer(consumerAccount, web3.utils.toWei('10')) + .transfer(consumerAccount, web3.utils.toWei('100')) .send({ from: publisherAccount }) await oceanContract.methods - .transfer(liquidityAccount, web3.utils.toWei('10')) + .transfer(liquidityAccount, web3.utils.toWei('100')) .send({ from: publisherAccount }) }) /// ``` - it('Publish a dataset (create NFT + ERC20) with a liquidity pool', async () => { + it('Publish a dataset (create NFT + Datatoken) with a liquidity pool', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { - name: 'Datatoken 1', - symbol: NFT_SYMBOL, + name: POOL_NFT_NAME, + symbol: POOL_NFT_SYMBOL, templateIndex: 1, tokenURI: '', transferable: true, @@ -262,13 +271,13 @@ describe('Marketplace flow tests', async () => { poolDatatokenAddress = tx.events.TokenCreated.returnValues[0] poolAddress = tx.events.NewPool.returnValues[0] - console.log(`NFT address: ${poolNftAddress}`) - console.log(`Datatoken address: ${poolDatatokenAddress}`) + console.log(`Pool NFT address: ${poolNftAddress}`) + console.log(`Pool Datatoken address: ${poolDatatokenAddress}`) console.log(`Pool address: ${poolAddress}`) }) /// ``` - it('Set metadata in the NFT', async () => { + it('Set metadata in the Pool NFT', async () => { /// ```Typescript const nft = new Nft(web3) @@ -321,7 +330,7 @@ describe('Marketplace flow tests', async () => { '1', '0.01' ) - console.log(`Price of 1 ${NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) + console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) }) /// ``` @@ -338,7 +347,7 @@ describe('Marketplace flow tests', async () => { ) console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) - console.log(`Consumer ${NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) + console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') @@ -363,7 +372,7 @@ describe('Marketplace flow tests', async () => { consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) - console.log(`Consumer ${NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) + console.log(`Consumer ${POOL_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) const resolvedDDO = await aquarius.waitForAqua(DDO.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') @@ -411,7 +420,7 @@ describe('Marketplace flow tests', async () => { consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) - console.log(`Consumer ${NFT_SYMBOL} balance after order: ${consumerDTBalance}`) + console.log(`Consumer ${POOL_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) try { const fileData = await downloadFile(downloadURL) From e70a81d756f5a9a4cc548a9905f6e90b15aba29b Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Fri, 29 Apr 2022 10:23:16 +0200 Subject: [PATCH 22/58] publish a dataset (create NFT + Datatoken) with a fixed rate exchange --- test/integration/MarketplaceFlow.test.ts | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index f974ce68..94334813 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -79,6 +79,7 @@ import { Datatoken, downloadFile, Erc20CreateParams, + FreCreationParams, getHash, Nft, NftCreateData, @@ -113,6 +114,7 @@ describe('Marketplace flow tests', async () => { let poolAddress: string let freNftAddress: string let freDatatokenAddress: string + let freAddress: string let dispenserNftAddress: string let dispenserDatatokenAddress: string @@ -430,4 +432,57 @@ describe('Marketplace flow tests', async () => { } }) /// ``` + + it('Publish a dataset (create NFT + Datatoken) with a fixed rate exchange', async () => { + /// ```Typescript + const factory = new NftFactory(contracts.erc721FactoryAddress, web3) + + const nftParams: NftCreateData = { + name: FRE_NFT_NAME, + symbol: FRE_NFT_SYMBOL, + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: publisherAccount + } + + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: publisherAccount, + mpFeeAddress: ZERO_ADDRESS + } + + const freParams: FreCreationParams = { + fixedRateAddress: contracts.fixedRateAddress, + baseTokenAddress: contracts.oceanAddress, + owner: publisherAccount, + marketFeeCollector: publisherAccount, + baseTokenDecimals: 18, + datatokenDecimals: 18, + fixedRate: '1', + marketFee: '0.001', + allowedConsumer: ZERO_ADDRESS, + withMint: false + } + + const tx = await factory.createNftErc20WithFixedRate( + publisherAccount, + nftParams, + erc20Params, + freParams + ) + + freNftAddress = tx.events.NFTCreated.returnValues[0] + freDatatokenAddress = tx.events.TokenCreated.returnValues[0] + freAddress = tx.events.NewFixedRate.returnValues[0] + + console.log(`Fixed rate exchange NFT address: ${poolNftAddress}`) + console.log(`Fixed rate exchange Datatoken address: ${poolDatatokenAddress}`) + console.log(`Fixed rate exchange address: ${poolAddress}`) + }) + /// ``` }) From 86005ba09108b638eeccce3d8c33c7646d60602c Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Sun, 1 May 2022 14:46:13 +0200 Subject: [PATCH 23/58] publish and consume fixed rate exchange data asset --- test/integration/MarketplaceFlow.test.ts | 157 +++++++++++++++++++++-- 1 file changed, 148 insertions(+), 9 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 94334813..515fc6cf 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -79,6 +79,7 @@ import { Datatoken, downloadFile, Erc20CreateParams, + FixedRateExchange, FreCreationParams, getHash, Nft, @@ -115,6 +116,7 @@ describe('Marketplace flow tests', async () => { let freNftAddress: string let freDatatokenAddress: string let freAddress: string + let freId: string let dispenserNftAddress: string let dispenserDatatokenAddress: string @@ -322,7 +324,7 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('Marketplace displays asset for sale', async () => { + it('Marketplace displays pool asset for sale', async () => { /// ```Typescript const pool = new Pool(web3) const prices = await pool.getAmountInExactOut( @@ -336,7 +338,7 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('Consumer buys data asset, and downloads it', async () => { + it('Consumer buys a pool data asset, and downloads it', async () => { /// ```Typescript const datatoken = new Datatoken(web3) @@ -387,7 +389,7 @@ describe('Marketplace flow tests', async () => { consumerAccount, providerUrl ) - console.log(initializeData) + const providerFees: ProviderFees = { providerFeeAddress: initializeData.providerFee.providerFeeAddress, providerFeeToken: initializeData.providerFee.providerFeeToken, @@ -399,7 +401,7 @@ describe('Marketplace flow tests', async () => { validUntil: initializeData.providerFee.validUntil } // make the payment - const txid = await datatoken.startOrder( + const tx = await datatoken.startOrder( poolDatatokenAddress, consumerAccount, consumerAccount, @@ -412,7 +414,7 @@ describe('Marketplace flow tests', async () => { consumerAccount, DDO.services[0].id, 0, - txid.transactionHash, + tx.transactionHash, providerUrl, web3 ) @@ -478,11 +480,148 @@ describe('Marketplace flow tests', async () => { freNftAddress = tx.events.NFTCreated.returnValues[0] freDatatokenAddress = tx.events.TokenCreated.returnValues[0] - freAddress = tx.events.NewFixedRate.returnValues[0] + freAddress = tx.events.NewFixedRate.returnValues.exchangeContract + freId = tx.events.NewFixedRate.returnValues.exchangeId - console.log(`Fixed rate exchange NFT address: ${poolNftAddress}`) - console.log(`Fixed rate exchange Datatoken address: ${poolDatatokenAddress}`) - console.log(`Fixed rate exchange address: ${poolAddress}`) + console.log(`Fixed rate exchange NFT address: ${freNftAddress}`) + console.log(`Fixed rate exchange Datatoken address: ${freDatatokenAddress}`) + console.log(`Fixed rate exchange address: ${freAddress}`) + console.log(`Fixed rate exchange Id: ${freId}`) + }) + /// ``` + + it('Set metadata in the Fixed Rate Exchange NFT', async () => { + /// ```Typescript + const nft = new Nft(web3) + + // update ddo and set the right did + DDO.chainId = await web3.eth.getChainId() + DDO.id = + 'did:op:' + + SHA256(web3.utils.toChecksumAddress(freNftAddress) + DDO.chainId.toString(10)) + DDO.nftAddress = freNftAddress + // encrypt file(s) using provider + const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) + DDO.services[0].files = await encryptedFiles + DDO.services[0].datatokenAddress = freDatatokenAddress + + console.log(`DID: ${DDO.id}`) + + const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) + const encryptedDDO = await providerResponse + const metadataHash = getHash(JSON.stringify(DDO)) + await nft.setMetadata( + freNftAddress, + publisherAccount, + 0, + providerUrl, + '', + '0x2', + encryptedDDO, + '0x' + metadataHash + ) + }) + /// ``` + + it('Marketplace displays fixed rate asset for sale', async () => { + /// ```Typescript + const fixedRate = new FixedRateExchange(web3, freAddress) + const oceanAmount = await ( + await fixedRate.calcBaseInGivenOutDT(freId, '1') + ).baseTokenAmount + console.log(`Price of 1 ${FRE_NFT_SYMBOL} is ${oceanAmount} OCEAN`) + }) + /// ``` + + it('Consumer buys a fixed rate asset data asset, and downloads it', async () => { + /// ```Typescript + const datatoken = new Datatoken(web3) + const DATATOKEN_AMOUNT = '10000' + + await datatoken.mint(freDatatokenAddress, publisherAccount, DATATOKEN_AMOUNT) + + const consumerETHBalance = await web3.eth.getBalance(consumerAccount) + console.log(`Consumer ETH balance: ${consumerETHBalance}`) + let consumerOCEANBalance = await balance( + web3, + contracts.oceanAddress, + consumerAccount + ) + console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) + let consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) + console.log(`Consumer ${FRE_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) + + await approve(web3, consumerAccount, contracts.oceanAddress, freAddress, '100') + await approve( + web3, + publisherAccount, + freDatatokenAddress, + freAddress, + DATATOKEN_AMOUNT + ) + + const fixedRate = new FixedRateExchange(web3, freAddress) + await fixedRate.buyDT(consumerAccount, freId, '1', '2') + + consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) + console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) + consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) + console.log(`Consumer ${FRE_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) + + const resolvedDDO = await aquarius.waitForAqua(DDO.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + + // 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 tx = await datatoken.startOrder( + freDatatokenAddress, + consumerAccount, + consumerAccount, + 0, + providerFees + ) + // get the url + const downloadURL = await ProviderInstance.getDownloadUrl( + DDO.id, + consumerAccount, + DDO.services[0].id, + 0, + tx.transactionHash, + providerUrl, + web3 + ) + + console.log(`Download URL: ${downloadURL}`) + + consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) + console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) + consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) + console.log(`Consumer ${FRE_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) + + try { + const fileData = await downloadFile(downloadURL) + console.log(fileData) + } catch (e) { + assert.fail('Download failed') + } }) /// ``` }) From b7e305fa98bb464a4d3b24ccdca38e6365d3082d Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 2 May 2022 12:17:31 +0200 Subject: [PATCH 24/58] dispense flox in marketplace test --- test/integration/MarketplaceFlow.test.ts | 169 ++++++++++++++++++++++- 1 file changed, 167 insertions(+), 2 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 515fc6cf..88181504 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -77,6 +77,8 @@ import { balance, Config, Datatoken, + Dispenser, + DispenserCreationParams, downloadFile, Erc20CreateParams, FixedRateExchange, @@ -119,6 +121,7 @@ describe('Marketplace flow tests', async () => { let freId: string let dispenserNftAddress: string let dispenserDatatokenAddress: string + let dispenserAddress: string const POOL_NFT_NAME = 'Datatoken 1' const POOL_NFT_SYMBOL = 'DT1' @@ -281,7 +284,7 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('Set metadata in the Pool NFT', async () => { + it('Set metadata in the pool NFT', async () => { /// ```Typescript const nft = new Nft(web3) @@ -490,7 +493,7 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('Set metadata in the Fixed Rate Exchange NFT', async () => { + it('Set metadata in the fixed rate exchange NFT', async () => { /// ```Typescript const nft = new Nft(web3) @@ -624,4 +627,166 @@ describe('Marketplace flow tests', async () => { } }) /// ``` + + it('Publish a dataset (create NFT + Datatoken) with a dipenser', async () => { + /// ```Typescript + const factory = new NftFactory(contracts.erc721FactoryAddress, web3) + + const nftParams: NftCreateData = { + name: DISP_NFT_NAME, + symbol: DISP_NFT_SYMBOL, + templateIndex: 1, + tokenURI: '', + transferable: true, + owner: publisherAccount + } + + const erc20Params: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: publisherAccount, + mpFeeAddress: ZERO_ADDRESS + } + + const dispenserParams: DispenserCreationParams = { + dispenserAddress: contracts.dispenserAddress, + maxTokens: '1', + maxBalance: '1', + withMint: true, + allowedSwapper: ZERO_ADDRESS + } + + const tx = await factory.createNftErc20WithDispenser( + publisherAccount, + nftParams, + erc20Params, + dispenserParams + ) + + dispenserNftAddress = tx.events.NFTCreated.returnValues[0] + dispenserDatatokenAddress = tx.events.TokenCreated.returnValues[0] + dispenserAddress = tx.events.DispenserCreated.returnValues[0] + + console.log(`Dispenser NFT address: ${dispenserNftAddress}`) + console.log(`Dispenser Datatoken address: ${dispenserDatatokenAddress}`) + console.log(`Dispenser address: ${dispenserAddress}`) + }) + /// ``` + + it('Set metadata in the dispenser NFT', async () => { + /// ```Typescript + const nft = new Nft(web3) + + // update ddo and set the right did + DDO.chainId = await web3.eth.getChainId() + DDO.id = + 'did:op:' + + SHA256(web3.utils.toChecksumAddress(dispenserNftAddress) + DDO.chainId.toString(10)) + DDO.nftAddress = dispenserNftAddress + // encrypt file(s) using provider + const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) + DDO.services[0].files = await encryptedFiles + DDO.services[0].datatokenAddress = dispenserDatatokenAddress + + console.log(`DID: ${DDO.id}`) + + const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) + const encryptedDDO = await providerResponse + const metadataHash = getHash(JSON.stringify(DDO)) + await nft.setMetadata( + dispenserNftAddress, + publisherAccount, + 0, + providerUrl, + '', + '0x2', + encryptedDDO, + '0x' + metadataHash + ) + }) + /// ``` + + it('Consumer gets a dispenser data asset, and downloads it', async () => { + /// ```Typescript + const datatoken = new Datatoken(web3) + const dispenser = new Dispenser(web3, contracts.dispenserAddress) + + let consumerDTBalance = await balance( + web3, + dispenserDatatokenAddress, + consumerAccount + ) + console.log( + `Consumer ${DISP_NFT_SYMBOL} balance before dispense: ${consumerDTBalance}` + ) + + await dispenser.dispense( + dispenserDatatokenAddress, + consumerAccount, + '1', + consumerAccount + ) + + consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount) + console.log( + `Consumer ${DISP_NFT_SYMBOL} balance after dispense: ${consumerDTBalance}` + ) + + const resolvedDDO = await aquarius.waitForAqua(DDO.id) + assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') + + // 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 tx = await datatoken.startOrder( + dispenserDatatokenAddress, + consumerAccount, + consumerAccount, + 0, + providerFees + ) + // get the url + const downloadURL = await ProviderInstance.getDownloadUrl( + DDO.id, + consumerAccount, + DDO.services[0].id, + 0, + tx.transactionHash, + providerUrl, + web3 + ) + + console.log(`Download URL: ${downloadURL}`) + + consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount) + console.log(`Consumer ${DISP_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) + + try { + const fileData = await downloadFile(downloadURL) + console.log(fileData) + } catch (e) { + assert.fail('Download failed') + } + }) + /// ``` }) From 3a757043f5b7fdf0e2c8b96d493171c367c4e720 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 2 May 2022 22:23:52 +0200 Subject: [PATCH 25/58] rename liquidityAccount to stakerAccount --- test/integration/MarketplaceFlow.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 88181504..804d2029 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -110,7 +110,7 @@ describe('Marketplace flow tests', async () => { let providerUrl: any let publisherAccount: string let consumerAccount: string - let liquidityAccount: string + let stakerAccount: string let contracts: Addresses let poolNftAddress: string let poolDatatokenAddress: string @@ -189,11 +189,11 @@ describe('Marketplace flow tests', async () => { const accounts = await web3.eth.getAccounts() publisherAccount = accounts[0] consumerAccount = accounts[1] - liquidityAccount = accounts[2] + stakerAccount = accounts[2] console.log(`Publisher account address: ${publisherAccount}`) console.log(`Consumer account address: ${consumerAccount}`) - console.log(`Liquidity account address: ${liquidityAccount}`) + console.log(`Staker account address: ${stakerAccount}`) }) /// ``` @@ -203,7 +203,7 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('We send some OCEAN to consumer and liquidity accounts', async () => { + it('We send some OCEAN to consumer and staker accounts', async () => { /// ```Typescript const oceanContract = new web3.eth.Contract( MockERC20.abi as AbiItem[], @@ -215,7 +215,7 @@ describe('Marketplace flow tests', async () => { .send({ from: publisherAccount }) await oceanContract.methods - .transfer(liquidityAccount, web3.utils.toWei('100')) + .transfer(stakerAccount, web3.utils.toWei('100')) .send({ from: publisherAccount }) }) /// ``` @@ -321,9 +321,9 @@ describe('Marketplace flow tests', async () => { /// ```Typescript const pool = new Pool(web3) - await approve(web3, liquidityAccount, contracts.oceanAddress, poolAddress, '5', true) + await approve(web3, stakerAccount, contracts.oceanAddress, poolAddress, '5', true) - await pool.joinswapExternAmountIn(liquidityAccount, poolAddress, '5', '0.1') + await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1') }) /// ``` From 6471550ae5642ded03f59d96795526a307e6c84a Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 2 May 2022 23:01:00 +0200 Subject: [PATCH 26/58] add necessary comments --- test/integration/MarketplaceFlow.test.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/test/integration/MarketplaceFlow.test.ts b/test/integration/MarketplaceFlow.test.ts index 804d2029..edd440c5 100644 --- a/test/integration/MarketplaceFlow.test.ts +++ b/test/integration/MarketplaceFlow.test.ts @@ -11,9 +11,10 @@ /// 1. Initialize services /// 2. Create a new node.js project /// 3. Install dependancies -/// 4. Publish Data NFT, Datatoken & Pool -/// 5. Market displays the asset for sale -/// 6. Consumer buys data asset, and downloads it +/// 4. Import dependencies and add variables and constants +/// 4. Publish Data NFT and a Datatoken with a liquidity pool +/// 5. Publish Data NFT and a Datatoken with a fixed rate exchange +/// 6. Publish Data NFT and a Datatoken with a dispenser /// Let's go through each step. @@ -59,7 +60,7 @@ /// npm install /// ``` -/// ## 4. Publish Data NFT, Datatoken & Pool +/// ## 4. Import dependencies and add variables and constants /// Now open the `marketplace.js` file in your text editor. @@ -220,6 +221,8 @@ describe('Marketplace flow tests', async () => { }) /// ``` + /// ## 4. Publish Data NFT and a Datatoken with a liquidity pool + it('Publish a dataset (create NFT + Datatoken) with a liquidity pool', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) @@ -438,6 +441,8 @@ describe('Marketplace flow tests', async () => { }) /// ``` + /// ## 5. Publish Data NFT and a Datatoken with a fixed rate exchange + it('Publish a dataset (create NFT + Datatoken) with a fixed rate exchange', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) @@ -628,6 +633,8 @@ describe('Marketplace flow tests', async () => { }) /// ``` + /// ## 6. Publish Data NFT and a Datatoken with a dispenser + it('Publish a dataset (create NFT + Datatoken) with a dipenser', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) From 10e86e3566b5e870d717ad6941d81a37db86e81d Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Tue, 3 May 2022 10:47:05 +0200 Subject: [PATCH 27/58] add createGuide.sh script --- scripts/createGuide.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100755 scripts/createGuide.sh diff --git a/scripts/createGuide.sh b/scripts/createGuide.sh new file mode 100755 index 00000000..f7248fbf --- /dev/null +++ b/scripts/createGuide.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Create markdown file +cp test/integration/MarketplaceFlow.test.ts MarketplaceFlow.md + +# Remove unneccessay imports +sed -i '' -e "s/import { assert } from 'chai'//" MarketplaceFlow.md + + +# Replace comments +sed -i '' -e 's/}) \/\/\/ //' MarketplaceFlow.md +sed -i '' -e 's/ \/\/\/ //' MarketplaceFlow.md +sed -i '' -e 's/ \/\/\/ //' MarketplaceFlow.md +sed -i '' -e 's/\/\/\/ //' MarketplaceFlow.md + + +# Generate titles +sed -i '' -e "s/describe('Simple Publish & Consume Flow', async () => {//" MarketplaceFlow.md +sed -i '' -e "s/it('/\#\#\# /" MarketplaceFlow.md +sed -i '' -e "s/', async () => {//" MarketplaceFlow.md +sed -i '' -e "s/before(async () => {//" MarketplaceFlow.md + From 92a3d813534a838d2ffb721fe20d636e31cc48e9 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Tue, 3 May 2022 17:19:39 +0300 Subject: [PATCH 28/58] 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 From 50e711eabc0d53d8ecf9c1e84727cb2f9ffde045 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 5 May 2022 16:19:33 +0300 Subject: [PATCH 29/58] Seperating the script for mac / linux --- CodeExamples.md | 252 +++++++++++++++--------------- package.json | 3 +- scripts/createCodeExamples-mac.sh | 20 +++ scripts/createCodeExamples.sh | 18 +-- 4 files changed, 157 insertions(+), 136 deletions(-) create mode 100755 scripts/createCodeExamples-mac.sh diff --git a/CodeExamples.md b/CodeExamples.md index bcaef145..2193a0cb 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -1,89 +1,89 @@ -/// # Ocean.js Code Examples +# Ocean.js Code Examples -/// ## Introduction +## 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 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. +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. +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. -/// These examples take you through a typical user journey that 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. +These examples take you through a typical user journey that 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. -/// 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: +Here are the steps we will be following throughout the article: -/// Here are the steps: +Here are the steps: -/// 1. Prerequisites -/// 2. Initialize services -/// 3. Create a new node.js project -/// 4. Install dependancies -/// 5. Import dependencies and add variables and constants -/// 6. Publish Data NFT and a Datatoken with a liquidity pool -/// 7. Publish Data NFT and a Datatoken with a fixed rate exchange -/// 8. Publish Data NFT and a Datatoken with a dispenser +1. Prerequisites +2. Initialize services +3. Create a new node.js project +4. Install dependancies +5. Import dependencies and add variables and constants +6. Publish Data NFT and a Datatoken with a liquidity pool +7. Publish Data NFT and a Datatoken with a fixed rate exchange +8. Publish Data NFT and a Datatoken with a dispenser -/// ## 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/ +## 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/ -/// ## 1. Initialize services +## 1. Initialize services -/// Ocean.js uses off-chain services for metadata (Aquarius) and consuming datasets (Provider). +Ocean.js uses off-chain services for metadata (Aquarius) and consuming datasets (Provider). -/// We start by initializing the services. To do this, we clone the Barge repository and run it. This will run the current default versions of [Aquarius](https://github.com/oceanprotocol/aquarius), [Provider](https://github.com/oceanprotocol/provider), and [Ganache](https://github.com/trufflesuite/ganache) with [our contracts](https://github.com/oceanprotocol/contracts) deployed to it. +We start by initializing the services. To do this, we clone the Barge repository and run it. This will run the current default versions of [Aquarius](https://github.com/oceanprotocol/aquarius), [Provider](https://github.com/oceanprotocol/provider), and [Ganache](https://github.com/trufflesuite/ganache) with [our contracts](https://github.com/oceanprotocol/contracts) deployed to it. -/// ```bash -/// git clone https://github.com/oceanprotocol/barge.git -/// cd barge/ -/// ./start_ocean.sh --with-provider2 --no-dashboard -/// ``` +```bash +git clone https://github.com/oceanprotocol/barge.git +cd barge/ +./start_ocean.sh --with-provider2 --no-dashboard +``` -/// ## 2. Create a new node.js project +## 2. Create a new node.js project -/// Start by creating a new Node.js project. Open a new terminal and enter the following commands: +Start by creating a new Node.js project. Open a new terminal and enter the following commands: -/// ```bash -/// mkdir marketplace-quickstart -/// cd marketplace-quickstart -/// npm init -/// # Answer the questions in the command line prompt -/// cat > marketplace.js -/// # On linux press CTRL + D to save -/// ``` +```bash +mkdir marketplace-quickstart +cd marketplace-quickstart +npm init +# Answer the questions in the command line prompt +cat > marketplace.js +# On linux press CTRL + D to save +``` -/// ## 3. Install dependancies +## 3. Install dependancies -/// Open the package.json file in a text editor and update the dependancies to include the following: +Open the package.json file in a text editor and update the dependancies to include the following: -/// ```JSON -/// "dependencies": { -/// "@oceanprotocol/contracts": "1.0.0-alpha.28", -/// "@oceanprotocol/lib": "1.0.0-next.37", -/// "crypto-js": "^4.1.1", -/// "web3": "^1.7.3" -/// } -/// ``` +```JSON + "dependencies": { + "@oceanprotocol/contracts": "1.0.0-alpha.28", + "@oceanprotocol/lib": "1.0.0-next.37", + "crypto-js": "^4.1.1", + "web3": "^1.7.3" + } +``` -/// Now in your terminal run the following command: +Now in your terminal run the following command: -/// ```bash -/// npm install -/// ``` +```bash +npm install +``` -/// ## 4. Import dependencies and add variables and constants +## 4. Import dependencies and add variables and constants -/// Now open the `marketplace.js` file in your text editor. +Now open the `marketplace.js` file in your text editor. -/// Start by importing all of the necessary dependencies +Start by importing all of the necessary dependencies -/// ```Typescript +```Typescript import { AbiItem } from 'web3-utils/types' import { SHA256 } from 'crypto-js' @@ -114,15 +114,15 @@ import { } from '../../src' import { getTestConfig, web3 } from '../config' import { Addresses, deployContracts } from '../TestContractHandler' -/// ``` +``` -/// + - /// Variables and constants needed for the test: +Variables and constants needed for the test: - /// ```Typescript +```Typescript let config: Config let aquarius: Aquarius let providerUrl: any @@ -147,10 +147,10 @@ describe('Marketplace flow tests', async () => { const FRE_NFT_SYMBOL = 'DT2' const DISP_NFT_NAME = 'Datatoken 3' const DISP_NFT_SYMBOL = 'DT3' - /// ``` +``` - /// We will need a file to publish, so here we define the file that we intend to publish. - /// ```Typescript + We will need a file to publish, so here we define the file that we intend to publish. +```Typescript const ASSET_URL = [ { type: 'url', @@ -158,10 +158,10 @@ describe('Marketplace flow tests', async () => { method: 'GET' } ] - /// ``` +``` - /// Next, we define the metadata that will describe our data asset. This is what we call the DDO - /// ```Typescript +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: '', @@ -188,11 +188,11 @@ describe('Marketplace flow tests', async () => { } ] } - /// ``` +``` - /// We load the configuration: - /// ```Typescript - before(async () => { +We load the configuration: +```Typescript + config = await getTestConfig(web3) aquarius = new Aquarius(config.metadataCacheUri) providerUrl = config.providerUri @@ -200,10 +200,10 @@ describe('Marketplace flow tests', async () => { console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) }) - /// ``` +``` - it('Initialize accounts', async () => { - /// ```Typescript + ### Initialize accounts +```Typescript const accounts = await web3.eth.getAccounts() publisherAccount = accounts[0] consumerAccount = accounts[1] @@ -213,16 +213,16 @@ describe('Marketplace flow tests', async () => { console.log(`Consumer account address: ${consumerAccount}`) console.log(`Staker account address: ${stakerAccount}`) }) - /// ``` +``` - it('Deploy contracts', async () => { - /// ```Typescript + ### Deploy contracts +```Typescript contracts = await deployContracts(web3, publisherAccount) }) - /// ``` +``` - it('We send some OCEAN to consumer and staker accounts', async () => { - /// ```Typescript + ### We send some OCEAN to consumer and staker accounts +```Typescript const oceanContract = new web3.eth.Contract( MockERC20.abi as AbiItem[], contracts.oceanAddress @@ -236,14 +236,14 @@ describe('Marketplace flow tests', async () => { .transfer(stakerAccount, web3.utils.toWei('100')) .send({ from: publisherAccount }) }) - /// ``` +``` - /// ## 4. Publish Data NFT and a Datatoken with a liquidity pool +## 4. Publish Data NFT and a Datatoken with a liquidity pool - /// For pool creation, the OCEAN token is used as the base token. The base token can be changed into something else, such as USDC, DAI etc., but it will require an extra fee. +For pool creation, the OCEAN token is used as the base token. The base token can be changed into something else, such as USDC, DAI etc., but it will require an extra fee. - it('Publish a dataset (create NFT + Datatoken) with a liquidity pool', async () => { - /// ```Typescript + ### Publish a dataset (create NFT + Datatoken) with a liquidity pool +```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { @@ -304,10 +304,10 @@ describe('Marketplace flow tests', async () => { console.log(`Pool Datatoken address: ${poolDatatokenAddress}`) console.log(`Pool address: ${poolAddress}`) }) - /// ``` +``` - it('Set metadata in the pool NFT', async () => { - /// ```Typescript + ### Set metadata in the pool NFT +```Typescript const nft = new Nft(web3) // update ddo and set the right did @@ -337,20 +337,20 @@ describe('Marketplace flow tests', async () => { '0x' + metadataHash ) }) - /// ``` +``` - it('User should add liquidity to the pool, receiving LP tokens', async () => { - /// ```Typescript + ### User should add liquidity to the pool, receiving LP tokens +```Typescript const pool = new Pool(web3) await approve(web3, stakerAccount, contracts.oceanAddress, poolAddress, '5', true) await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1') }) - /// ``` +``` - it('Marketplace displays pool asset for sale', async () => { - /// ```Typescript + ### Marketplace displays pool asset for sale +```Typescript const pool = new Pool(web3) const prices = await pool.getAmountInExactOut( poolAddress, @@ -361,10 +361,10 @@ describe('Marketplace flow tests', async () => { ) console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) }) - /// ``` +``` - it('Consumer buys a pool data asset, and downloads it', async () => { - /// ```Typescript + ### Consumer buys a pool data asset, and downloads it +```Typescript const datatoken = new Datatoken(web3) const consumerETHBalance = await web3.eth.getBalance(consumerAccount) @@ -458,12 +458,12 @@ describe('Marketplace flow tests', async () => { assert.fail('Download failed') } }) - /// ``` +``` - /// ## 5. Publish Data NFT and a Datatoken with a fixed rate exchange +## 5. Publish Data NFT and a Datatoken with a fixed rate exchange - it('Publish a dataset (create NFT + Datatoken) with a fixed rate exchange', async () => { - /// ```Typescript + ### Publish a dataset (create NFT + Datatoken) with a fixed rate exchange +```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { @@ -515,10 +515,10 @@ describe('Marketplace flow tests', async () => { console.log(`Fixed rate exchange address: ${freAddress}`) console.log(`Fixed rate exchange Id: ${freId}`) }) - /// ``` +``` - it('Set metadata in the fixed rate exchange NFT', async () => { - /// ```Typescript + ### Set metadata in the fixed rate exchange NFT +```Typescript const nft = new Nft(web3) // update ddo and set the right did @@ -548,20 +548,20 @@ describe('Marketplace flow tests', async () => { '0x' + metadataHash ) }) - /// ``` +``` - it('Marketplace displays fixed rate asset for sale', async () => { - /// ```Typescript + ### Marketplace displays fixed rate asset for sale +```Typescript const fixedRate = new FixedRateExchange(web3, freAddress) const oceanAmount = await ( await fixedRate.calcBaseInGivenOutDT(freId, '1') ).baseTokenAmount console.log(`Price of 1 ${FRE_NFT_SYMBOL} is ${oceanAmount} OCEAN`) }) - /// ``` +``` - it('Consumer buys a fixed rate asset data asset, and downloads it', async () => { - /// ```Typescript + ### Consumer buys a fixed rate asset data asset, and downloads it +```Typescript const datatoken = new Datatoken(web3) const DATATOKEN_AMOUNT = '10000' @@ -650,12 +650,12 @@ describe('Marketplace flow tests', async () => { assert.fail('Download failed') } }) - /// ``` +``` - /// ## 6. Publish Data NFT and a Datatoken with a dispenser +## 6. Publish Data NFT and a Datatoken with a dispenser - it('Publish a dataset (create NFT + Datatoken) with a dipenser', async () => { - /// ```Typescript + ### Publish a dataset (create NFT + Datatoken) with a dipenser +```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) const nftParams: NftCreateData = { @@ -700,10 +700,10 @@ describe('Marketplace flow tests', async () => { console.log(`Dispenser Datatoken address: ${dispenserDatatokenAddress}`) console.log(`Dispenser address: ${dispenserAddress}`) }) - /// ``` +``` - it('Set metadata in the dispenser NFT', async () => { - /// ```Typescript + ### Set metadata in the dispenser NFT +```Typescript const nft = new Nft(web3) // update ddo and set the right did @@ -733,10 +733,10 @@ describe('Marketplace flow tests', async () => { '0x' + metadataHash ) }) - /// ``` +``` - it('Consumer gets a dispenser data asset, and downloads it', async () => { - /// ```Typescript + ### Consumer gets a dispenser data asset, and downloads it +```Typescript const datatoken = new Datatoken(web3) const dispenser = new Dispenser(web3, contracts.dispenserAddress) @@ -814,5 +814,5 @@ describe('Marketplace flow tests', async () => { assert.fail('Download failed') } }) - /// ``` +``` }) diff --git a/package.json b/package.json index 176c172c..a4ebe4fa 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,8 @@ "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", - "create:guide": "chmod +x ./scripts/createCodeExamples.sh && ./scripts/createCodeExamples.sh" + "create:guide": "chmod +x ./scripts/createCodeExamples.sh && ./scripts/createCodeExamples.sh", + "create:guide:mac": "chmod +x ./scripts/createCodeExamples-mac.sh && ./scripts/createCodeExamples-mac.sh" }, "repository": { "type": "git", diff --git a/scripts/createCodeExamples-mac.sh b/scripts/createCodeExamples-mac.sh new file mode 100755 index 00000000..f69867ad --- /dev/null +++ b/scripts/createCodeExamples-mac.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Create markdown file +cp test/integration/CodeExamples.test.ts CodeExamples.md + +# Remove unneccessay imports +sed -i '' -e "s/import { assert } from 'chai'//" CodeExamples.md + + +# Replace comments +sed -i '' -e 's/}) \/\/\/ //' CodeExamples.md +sed -i '' -e 's/ \/\/\/ //' CodeExamples.md +sed -i '' -e 's/ \/\/\/ //' CodeExamples.md +sed -i '' -e 's/\/\/\/ //' CodeExamples.md + + +# Generate titles +sed -i '' -e "s/describe('Simple Publish & Consume Flow', async () => {//" CodeExamples.md +sed -i '' -e "s/it('/\#\#\# /" CodeExamples.md +sed -i '' -e "s/', async () => {//" CodeExamples.md +sed -i '' -e "s/before(async () => {//" CodeExamples.md \ No newline at end of file diff --git a/scripts/createCodeExamples.sh b/scripts/createCodeExamples.sh index f69867ad..856ff9bb 100755 --- a/scripts/createCodeExamples.sh +++ b/scripts/createCodeExamples.sh @@ -3,18 +3,18 @@ cp test/integration/CodeExamples.test.ts CodeExamples.md # Remove unneccessay imports -sed -i '' -e "s/import { assert } from 'chai'//" CodeExamples.md +sed -i "s/import { assert } from 'chai'//" CodeExamples.md # Replace comments -sed -i '' -e 's/}) \/\/\/ //' CodeExamples.md -sed -i '' -e 's/ \/\/\/ //' CodeExamples.md -sed -i '' -e 's/ \/\/\/ //' CodeExamples.md -sed -i '' -e 's/\/\/\/ //' CodeExamples.md +sed -i 's/}) \/\/\/ //' CodeExamples.md +sed -i 's/ \/\/\/ //' CodeExamples.md +sed -i 's/ \/\/\/ //' CodeExamples.md +sed -i 's/\/\/\/ //' CodeExamples.md # Generate titles -sed -i '' -e "s/describe('Simple Publish & Consume Flow', async () => {//" CodeExamples.md -sed -i '' -e "s/it('/\#\#\# /" CodeExamples.md -sed -i '' -e "s/', async () => {//" CodeExamples.md -sed -i '' -e "s/before(async () => {//" CodeExamples.md \ No newline at end of file +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 \ No newline at end of file From 0e4df185b14fb63feac2386e6a41cd6d93a6dd62 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 5 May 2022 16:27:57 +0300 Subject: [PATCH 30/58] Addign links --- CodeExamples.md | 16 ++++++++-------- test/integration/CodeExamples.test.ts | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index 2193a0cb..0a091520 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -17,14 +17,14 @@ Here are the steps we will be following throughout the article: Here are the steps: -1. Prerequisites -2. Initialize services -3. Create a new node.js project -4. Install dependancies -5. Import dependencies and add variables and constants -6. Publish Data NFT and a Datatoken with a liquidity pool -7. Publish Data NFT and a Datatoken with a fixed rate exchange -8. Publish Data NFT and a Datatoken with a dispenser +1. [Prerequisites](#-Prerequisites) +2. [Initialize services](#-initialize-services) +3. [Create a new node.js project](#-create-a-new-node.js-project) +4. [Install dependencies](#-install-dependencies) +5. [Import dependencies and add variables and constants](#-import-dependencies-and-add-variables-and-constants) +6. [Publish Data NFT and a Datatoken with a liquidity pool](#-Publish-data-nft-and-a-datatoken-with-a-liquidity-pool) +7. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange) +8. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser) ## 1. Prerequisites Before we start it is important that you have all of the necessary prerequisites installed on your computer. diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index 9ad2a572..2f2f3771 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -17,14 +17,14 @@ /// Here are the steps: -/// 1. Prerequisites -/// 2. Initialize services -/// 3. Create a new node.js project -/// 4. Install dependancies -/// 5. Import dependencies and add variables and constants -/// 6. Publish Data NFT and a Datatoken with a liquidity pool -/// 7. Publish Data NFT and a Datatoken with a fixed rate exchange -/// 8. Publish Data NFT and a Datatoken with a dispenser +/// 1. [Prerequisites](#-Prerequisites) +/// 2. [Initialize services](#-initialize-services) +/// 3. [Create a new node.js project](#-create-a-new-node.js-project) +/// 4. [Install dependencies](#-install-dependencies) +/// 5. [Import dependencies and add variables and constants](#-import-dependencies-and-add-variables-and-constants) +/// 6. [Publish Data NFT and a Datatoken with a liquidity pool](#-Publish-data-nft-and-a-datatoken-with-a-liquidity-pool) +/// 7. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange) +/// 8. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser) /// ## 1. Prerequisites /// Before we start it is important that you have all of the necessary prerequisites installed on your computer. From 75e0afa4d94dbea8fd7d5618a56345a2e075cca1 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 5 May 2022 16:47:38 +0300 Subject: [PATCH 31/58] Adding additional comments in the code --- CodeExamples.md | 88 ++++++++++++++++++++------- scripts/createCodeExamples.sh | 1 + test/integration/CodeExamples.test.ts | 88 ++++++++++++++++++++------- 3 files changed, 135 insertions(+), 42 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index 0a091520..640f4a60 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -120,7 +120,7 @@ import { Addresses, deployContracts } from '../TestContractHandler' describe('Marketplace flow tests --> -Variables and constants needed for the test: +Now we define the variables which we will need later ```Typescript let config: Config @@ -140,7 +140,10 @@ Variables and constants needed for the test: let dispenserNftAddress: string let dispenserDatatokenAddress: string let dispenserAddress: string +``` +We also define some constants that we will use: +```Typescript const POOL_NFT_NAME = 'Datatoken 1' const POOL_NFT_SYMBOL = 'DT1' const FRE_NFT_NAME = 'Datatoken 2' @@ -199,7 +202,7 @@ We load the configuration: console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) - }) + ``` ### Initialize accounts @@ -212,13 +215,13 @@ We load the configuration: console.log(`Publisher account address: ${publisherAccount}`) console.log(`Consumer account address: ${consumerAccount}`) console.log(`Staker account address: ${stakerAccount}`) - }) + ``` - ### Deploy contracts + ### Next, lets deploy the contracts ```Typescript contracts = await deployContracts(web3, publisherAccount) - }) + ``` ### We send some OCEAN to consumer and staker accounts @@ -235,7 +238,7 @@ We load the configuration: await oceanContract.methods .transfer(stakerAccount, web3.utils.toWei('100')) .send({ from: publisherAccount }) - }) + ``` ## 4. Publish Data NFT and a Datatoken with a liquidity pool @@ -303,24 +306,29 @@ For pool creation, the OCEAN token is used as the base token. The base token can console.log(`Pool NFT address: ${poolNftAddress}`) console.log(`Pool Datatoken address: ${poolDatatokenAddress}`) console.log(`Pool address: ${poolAddress}`) - }) + ``` ### Set metadata in the pool NFT ```Typescript const nft = new Nft(web3) - - // update ddo and set the right did +``` +Now we update the ddo and set the right did +```Typescript DDO.chainId = await web3.eth.getChainId() DDO.id = 'did:op:' + SHA256(web3.utils.toChecksumAddress(poolNftAddress) + DDO.chainId.toString(10)) DDO.nftAddress = poolNftAddress - // encrypt file(s) using provider +``` +Next we encrypt the file or files using Ocean Provider. The provider is an off chain proxy built specifically for this task +```Typescript const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = poolDatatokenAddress - +``` +Now let's console log the result to check everything is working +```Typescript console.log(`DID: ${DDO.id}`) const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) @@ -336,7 +344,7 @@ For pool creation, the OCEAN token is used as the base token. The base token can encryptedDDO, '0x' + metadataHash ) - }) + ``` ### User should add liquidity to the pool, receiving LP tokens @@ -346,7 +354,7 @@ For pool creation, the OCEAN token is used as the base token. The base token can await approve(web3, stakerAccount, contracts.oceanAddress, poolAddress, '5', true) await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1') - }) + ``` ### Marketplace displays pool asset for sale @@ -359,8 +367,11 @@ For pool creation, the OCEAN token is used as the base token. The base token can '1', '0.01' ) +``` +Now let's console log the result to check everything is working +```Typescript console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) - }) + ``` ### Consumer buys a pool data asset, and downloads it @@ -368,14 +379,23 @@ For pool creation, the OCEAN token is used as the base token. The base token can const datatoken = new Datatoken(web3) const consumerETHBalance = await web3.eth.getBalance(consumerAccount) +``` +Now let's console log the result to check everything is working +```Typescript console.log(`Consumer ETH balance: ${consumerETHBalance}`) let consumerOCEANBalance = await balance( web3, contracts.oceanAddress, consumerAccount ) +``` +Now let's console log consumerOCEANBalance to check everything is working +```Typescript console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) +``` +Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything is working +```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') @@ -399,8 +419,14 @@ For pool creation, the OCEAN token is used as the base token. The base token can ) consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) +``` +Now let's console log the Consumer OCEAN balance after swap to check everything is working +```Typescript console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) +``` +Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance +```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) const resolvedDDO = await aquarius.waitForAqua(DDO.id) @@ -444,11 +470,18 @@ For pool creation, the OCEAN token is used as the base token. The base token can web3 ) +``` +Now let's console log the Download URL to check everything is working +```Typescript console.log(`Download URL: ${downloadURL}`) consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) + +``` +Now let's console log the Consumer balance after order to check everything is working +```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) try { @@ -457,7 +490,7 @@ For pool creation, the OCEAN token is used as the base token. The base token can } catch (e) { assert.fail('Download failed') } - }) + ``` ## 5. Publish Data NFT and a Datatoken with a fixed rate exchange @@ -510,11 +543,14 @@ For pool creation, the OCEAN token is used as the base token. The base token can freAddress = tx.events.NewFixedRate.returnValues.exchangeContract freId = tx.events.NewFixedRate.returnValues.exchangeId +``` +Now let's console log each of those values to check everything is working +```Typescript console.log(`Fixed rate exchange NFT address: ${freNftAddress}`) console.log(`Fixed rate exchange Datatoken address: ${freDatatokenAddress}`) console.log(`Fixed rate exchange address: ${freAddress}`) console.log(`Fixed rate exchange Id: ${freId}`) - }) + ``` ### Set metadata in the fixed rate exchange NFT @@ -532,6 +568,9 @@ For pool creation, the OCEAN token is used as the base token. The base token can DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = freDatatokenAddress +``` +Now let's console log the DID to check everything is working +```Typescript console.log(`DID: ${DDO.id}`) const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) @@ -556,8 +595,11 @@ For pool creation, the OCEAN token is used as the base token. The base token can const oceanAmount = await ( await fixedRate.calcBaseInGivenOutDT(freId, '1') ).baseTokenAmount +``` +Now that the market has fetched those values it can display the asset on the front end. In our case we will just console log the results: +```Typescript console.log(`Price of 1 ${FRE_NFT_SYMBOL} is ${oceanAmount} OCEAN`) - }) + ``` ### Consumer buys a fixed rate asset data asset, and downloads it @@ -568,6 +610,10 @@ For pool creation, the OCEAN token is used as the base token. The base token can await datatoken.mint(freDatatokenAddress, publisherAccount, DATATOKEN_AMOUNT) const consumerETHBalance = await web3.eth.getBalance(consumerAccount) + +``` +Let's do a quick check of the consumer ETH balance before the swap +```Typescript console.log(`Consumer ETH balance: ${consumerETHBalance}`) let consumerOCEANBalance = await balance( web3, @@ -649,7 +695,7 @@ For pool creation, the OCEAN token is used as the base token. The base token can } catch (e) { assert.fail('Download failed') } - }) + ``` ## 6. Publish Data NFT and a Datatoken with a dispenser @@ -732,7 +778,7 @@ For pool creation, the OCEAN token is used as the base token. The base token can encryptedDDO, '0x' + metadataHash ) - }) + ``` ### Consumer gets a dispenser data asset, and downloads it @@ -813,6 +859,6 @@ For pool creation, the OCEAN token is used as the base token. The base token can } catch (e) { assert.fail('Download failed') } - }) + ``` -}) + diff --git a/scripts/createCodeExamples.sh b/scripts/createCodeExamples.sh index 856ff9bb..eeb7f4ad 100755 --- a/scripts/createCodeExamples.sh +++ b/scripts/createCodeExamples.sh @@ -8,6 +8,7 @@ sed -i "s/import { assert } from 'chai'//" CodeExamples.md # Replace comments sed -i 's/}) \/\/\/ //' CodeExamples.md +sed -i 's/}) \/\/\///' CodeExamples.md sed -i 's/ \/\/\/ //' CodeExamples.md sed -i 's/ \/\/\/ //' CodeExamples.md sed -i 's/\/\/\/ //' CodeExamples.md diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index 2f2f3771..55c4c0c5 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -120,7 +120,7 @@ import { Addresses, deployContracts } from '../TestContractHandler' describe('Marketplace flow tests', async () => { /// --> - /// Variables and constants needed for the test: + /// Now we define the variables which we will need later /// ```Typescript let config: Config @@ -140,7 +140,10 @@ describe('Marketplace flow tests', async () => { let dispenserNftAddress: string let dispenserDatatokenAddress: string let dispenserAddress: string + /// ``` + /// We also define some constants that we will use: + /// ```Typescript const POOL_NFT_NAME = 'Datatoken 1' const POOL_NFT_SYMBOL = 'DT1' const FRE_NFT_NAME = 'Datatoken 2' @@ -199,7 +202,7 @@ describe('Marketplace flow tests', async () => { console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) - }) + }) /// /// ``` it('Initialize accounts', async () => { @@ -212,13 +215,13 @@ describe('Marketplace flow tests', async () => { console.log(`Publisher account address: ${publisherAccount}`) console.log(`Consumer account address: ${consumerAccount}`) console.log(`Staker account address: ${stakerAccount}`) - }) + }) /// /// ``` - it('Deploy contracts', async () => { + it('Next, lets deploy the contracts', async () => { /// ```Typescript contracts = await deployContracts(web3, publisherAccount) - }) + }) /// /// ``` it('We send some OCEAN to consumer and staker accounts', async () => { @@ -235,7 +238,7 @@ describe('Marketplace flow tests', async () => { await oceanContract.methods .transfer(stakerAccount, web3.utils.toWei('100')) .send({ from: publisherAccount }) - }) + }) /// /// ``` /// ## 4. Publish Data NFT and a Datatoken with a liquidity pool @@ -303,24 +306,29 @@ describe('Marketplace flow tests', async () => { console.log(`Pool NFT address: ${poolNftAddress}`) console.log(`Pool Datatoken address: ${poolDatatokenAddress}`) console.log(`Pool address: ${poolAddress}`) - }) + }) /// /// ``` it('Set metadata in the pool NFT', async () => { /// ```Typescript const nft = new Nft(web3) - - // update ddo and set the right did + /// ``` + /// Now we update the ddo and set the right did + /// ```Typescript DDO.chainId = await web3.eth.getChainId() DDO.id = 'did:op:' + SHA256(web3.utils.toChecksumAddress(poolNftAddress) + DDO.chainId.toString(10)) DDO.nftAddress = poolNftAddress - // encrypt file(s) using provider + /// ``` + /// Next we encrypt the file or files using Ocean Provider. The provider is an off chain proxy built specifically for this task + /// ```Typescript const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = poolDatatokenAddress - + /// ``` + /// Now let's console log the result to check everything is working + /// ```Typescript console.log(`DID: ${DDO.id}`) const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) @@ -336,7 +344,7 @@ describe('Marketplace flow tests', async () => { encryptedDDO, '0x' + metadataHash ) - }) + }) /// /// ``` it('User should add liquidity to the pool, receiving LP tokens', async () => { @@ -346,7 +354,7 @@ describe('Marketplace flow tests', async () => { await approve(web3, stakerAccount, contracts.oceanAddress, poolAddress, '5', true) await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1') - }) + }) /// /// ``` it('Marketplace displays pool asset for sale', async () => { @@ -359,8 +367,11 @@ describe('Marketplace flow tests', async () => { '1', '0.01' ) + /// ``` + /// Now let's console log the result to check everything is working + /// ```Typescript console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) - }) + }) /// /// ``` it('Consumer buys a pool data asset, and downloads it', async () => { @@ -368,14 +379,23 @@ describe('Marketplace flow tests', async () => { const datatoken = new Datatoken(web3) const consumerETHBalance = await web3.eth.getBalance(consumerAccount) + /// ``` + /// Now let's console log the result to check everything is working + /// ```Typescript console.log(`Consumer ETH balance: ${consumerETHBalance}`) let consumerOCEANBalance = await balance( web3, contracts.oceanAddress, consumerAccount ) + /// ``` + /// Now let's console log consumerOCEANBalance to check everything is working + /// ```Typescript console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) + /// ``` + /// Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything is working + /// ```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') @@ -399,8 +419,14 @@ describe('Marketplace flow tests', async () => { ) consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) + /// ``` + /// Now let's console log the Consumer OCEAN balance after swap to check everything is working + /// ```Typescript console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) + /// ``` + /// Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance + /// ```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) const resolvedDDO = await aquarius.waitForAqua(DDO.id) @@ -444,11 +470,18 @@ describe('Marketplace flow tests', async () => { web3 ) + /// ``` + /// Now let's console log the Download URL to check everything is working + /// ```Typescript console.log(`Download URL: ${downloadURL}`) consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) + + /// ``` + /// Now let's console log the Consumer balance after order to check everything is working + /// ```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) try { @@ -457,7 +490,7 @@ describe('Marketplace flow tests', async () => { } catch (e) { assert.fail('Download failed') } - }) + }) /// /// ``` /// ## 5. Publish Data NFT and a Datatoken with a fixed rate exchange @@ -510,11 +543,14 @@ describe('Marketplace flow tests', async () => { freAddress = tx.events.NewFixedRate.returnValues.exchangeContract freId = tx.events.NewFixedRate.returnValues.exchangeId + /// ``` + /// Now let's console log each of those values to check everything is working + /// ```Typescript console.log(`Fixed rate exchange NFT address: ${freNftAddress}`) console.log(`Fixed rate exchange Datatoken address: ${freDatatokenAddress}`) console.log(`Fixed rate exchange address: ${freAddress}`) console.log(`Fixed rate exchange Id: ${freId}`) - }) + }) /// /// ``` it('Set metadata in the fixed rate exchange NFT', async () => { @@ -532,6 +568,9 @@ describe('Marketplace flow tests', async () => { DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = freDatatokenAddress + /// ``` + /// Now let's console log the DID to check everything is working + /// ```Typescript console.log(`DID: ${DDO.id}`) const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) @@ -556,8 +595,11 @@ describe('Marketplace flow tests', async () => { const oceanAmount = await ( await fixedRate.calcBaseInGivenOutDT(freId, '1') ).baseTokenAmount + /// ``` + /// Now that the market has fetched those values it can display the asset on the front end. In our case we will just console log the results: + /// ```Typescript console.log(`Price of 1 ${FRE_NFT_SYMBOL} is ${oceanAmount} OCEAN`) - }) + }) /// /// ``` it('Consumer buys a fixed rate asset data asset, and downloads it', async () => { @@ -568,6 +610,10 @@ describe('Marketplace flow tests', async () => { await datatoken.mint(freDatatokenAddress, publisherAccount, DATATOKEN_AMOUNT) const consumerETHBalance = await web3.eth.getBalance(consumerAccount) + + /// ``` + /// Let's do a quick check of the consumer ETH balance before the swap + /// ```Typescript console.log(`Consumer ETH balance: ${consumerETHBalance}`) let consumerOCEANBalance = await balance( web3, @@ -649,7 +695,7 @@ describe('Marketplace flow tests', async () => { } catch (e) { assert.fail('Download failed') } - }) + }) /// /// ``` /// ## 6. Publish Data NFT and a Datatoken with a dispenser @@ -732,7 +778,7 @@ describe('Marketplace flow tests', async () => { encryptedDDO, '0x' + metadataHash ) - }) + }) /// /// ``` it('Consumer gets a dispenser data asset, and downloads it', async () => { @@ -813,6 +859,6 @@ describe('Marketplace flow tests', async () => { } catch (e) { assert.fail('Download failed') } - }) + }) /// /// ``` -}) +}) /// From 74afc0407f355af4be531296511cc4282f9ea2e9 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 5 May 2022 16:52:33 +0300 Subject: [PATCH 32/58] Updating mac script --- scripts/createCodeExamples-mac.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/createCodeExamples-mac.sh b/scripts/createCodeExamples-mac.sh index f69867ad..2fe8bac5 100755 --- a/scripts/createCodeExamples-mac.sh +++ b/scripts/createCodeExamples-mac.sh @@ -8,6 +8,7 @@ sed -i '' -e "s/import { assert } from 'chai'//" CodeExamples.md # Replace comments sed -i '' -e 's/}) \/\/\/ //' CodeExamples.md +sed -i '' -e 's/}) \/\/\///' CodeExamples.md sed -i '' -e 's/ \/\/\/ //' CodeExamples.md sed -i '' -e 's/ \/\/\/ //' CodeExamples.md sed -i '' -e 's/\/\/\/ //' CodeExamples.md From d39c091999557f3b2a22719f1c4d1cb3a52d5313 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 5 May 2022 17:35:06 +0300 Subject: [PATCH 33/58] Updating comments --- CodeExamples.md | 103 +++++++++++++++++++----- test/integration/CodeExamples.test.ts | 109 +++++++++++++++++++++----- 2 files changed, 172 insertions(+), 40 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index 640f4a60..ad36ce4f 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -199,7 +199,9 @@ We load the configuration: config = await getTestConfig(web3) aquarius = new Aquarius(config.metadataCacheUri) providerUrl = config.providerUri - +``` +As we go along it's a good idea to console log the values so that you check they are right +```Typescript console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) @@ -211,7 +213,9 @@ We load the configuration: publisherAccount = accounts[0] consumerAccount = accounts[1] stakerAccount = accounts[2] - +``` +Again, lets console log the values so that we can check that they have been saved properly +```Typescript console.log(`Publisher account address: ${publisherAccount}`) console.log(`Consumer account address: ${consumerAccount}`) console.log(`Staker account address: ${stakerAccount}`) @@ -283,7 +287,9 @@ For pool creation, the OCEAN token is used as the base token. The base token can swapFeeLiquidityProvider: '0.001', swapFeeMarketRunner: '0.001' } - +``` +Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens +```Typescript await approve( web3, publisherAccount, @@ -292,6 +298,9 @@ For pool creation, the OCEAN token is used as the base token. The base token can poolParams.vestingAmount ) +``` +Now we can make the contract call +```Typescript const tx = await factory.createNftErc20WithPool( publisherAccount, nftParams, @@ -302,7 +311,9 @@ For pool creation, the OCEAN token is used as the base token. The base token can poolNftAddress = tx.events.NFTCreated.returnValues[0] poolDatatokenAddress = tx.events.TokenCreated.returnValues[0] poolAddress = tx.events.NewPool.returnValues[0] - +``` +Now, we did quite a few things there. Let's check that we successfully published a dataset (create NFT + Datatoken) with a liquidity pool +```Typescript console.log(`Pool NFT address: ${poolNftAddress}`) console.log(`Pool Datatoken address: ${poolDatatokenAddress}`) console.log(`Pool address: ${poolAddress}`) @@ -351,8 +362,14 @@ Now let's console log the result to check everything is working ```Typescript const pool = new Pool(web3) +``` +Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens +```Typescript await approve(web3, stakerAccount, contracts.oceanAddress, poolAddress, '5', true) +``` +Now we can make the contract call +```Typescript await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1') ``` @@ -398,6 +415,9 @@ Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything ```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) +``` +Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens +```Typescript await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') const pool = new Pool(web3) @@ -411,6 +431,10 @@ Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything tokenAmountOut: '1', swapMarketFee: '0.1' } + +``` +Now we can make the contract call +```Typescript await pool.swapExactAmountOut( consumerAccount, poolAddress, @@ -432,7 +456,9 @@ Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance const resolvedDDO = await aquarius.waitForAqua(DDO.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - // initialize provider +``` +The next step is to initialize the provider instance +```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, resolvedDDO.services[0].id, @@ -451,7 +477,10 @@ Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance providerData: initializeData.providerFee.providerData, validUntil: initializeData.providerFee.validUntil } - // make the payment + +``` +Now let's make a payment +```Typescript const tx = await datatoken.startOrder( poolDatatokenAddress, consumerAccount, @@ -459,7 +488,10 @@ Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance 0, providerFees ) - // get the url + +``` +Next up, let's get the URL +```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, consumerAccount, @@ -557,13 +589,18 @@ Now let's console log each of those values to check everything is working ```Typescript const nft = new Nft(web3) - // update ddo and set the right did +``` +Now we are going to update the ddo and set the did +```Typescript DDO.chainId = await web3.eth.getChainId() DDO.id = 'did:op:' + SHA256(web3.utils.toChecksumAddress(freNftAddress) + DDO.chainId.toString(10)) DDO.nftAddress = freNftAddress - // encrypt file(s) using provider + +``` +Next, let's encrypt the file(s) using provider +```Typescript const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = freDatatokenAddress @@ -624,6 +661,9 @@ Let's do a quick check of the consumer ETH balance before the swap let consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) console.log(`Consumer ${FRE_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) +``` +Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens +```Typescript await approve(web3, consumerAccount, contracts.oceanAddress, freAddress, '100') await approve( web3, @@ -634,6 +674,9 @@ Let's do a quick check of the consumer ETH balance before the swap ) const fixedRate = new FixedRateExchange(web3, freAddress) +``` +Now we can make the contract call +```Typescript await fixedRate.buyDT(consumerAccount, freId, '1', '2') consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) @@ -644,7 +687,9 @@ Let's do a quick check of the consumer ETH balance before the swap const resolvedDDO = await aquarius.waitForAqua(DDO.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - // initialize provider +``` +Next, we need to initialize the provider +```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, resolvedDDO.services[0].id, @@ -663,7 +708,10 @@ Let's do a quick check of the consumer ETH balance before the swap providerData: initializeData.providerFee.providerData, validUntil: initializeData.providerFee.validUntil } - // make the payment + +``` +Lets now make the payment +```Typescript const tx = await datatoken.startOrder( freDatatokenAddress, consumerAccount, @@ -671,7 +719,9 @@ Let's do a quick check of the consumer ETH balance before the swap 0, providerFees ) - // get the url +``` +Now we can get the url +```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, consumerAccount, @@ -682,6 +732,9 @@ Let's do a quick check of the consumer ETH balance before the swap web3 ) +``` +Lets check that the download URL was successfully received +```Typescript console.log(`Download URL: ${downloadURL}`) consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) @@ -752,13 +805,18 @@ Let's do a quick check of the consumer ETH balance before the swap ```Typescript const nft = new Nft(web3) - // update ddo and set the right did +``` +Lets start by updating the ddo and setting the did +```Typescript DDO.chainId = await web3.eth.getChainId() DDO.id = 'did:op:' + SHA256(web3.utils.toChecksumAddress(dispenserNftAddress) + DDO.chainId.toString(10)) DDO.nftAddress = dispenserNftAddress - // encrypt file(s) using provider + +``` +Now we need to encrypt file(s) using provider +```Typescript const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = dispenserDatatokenAddress @@ -809,8 +867,9 @@ Let's do a quick check of the consumer ETH balance before the swap const resolvedDDO = await aquarius.waitForAqua(DDO.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - - // initialize provider +``` +At this point we need to encrypt file(s) using provider +```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, resolvedDDO.services[0].id, @@ -829,7 +888,9 @@ Let's do a quick check of the consumer ETH balance before the swap providerData: initializeData.providerFee.providerData, validUntil: initializeData.providerFee.validUntil } - // make the payment +``` +Now we need to make the payment +```Typescript const tx = await datatoken.startOrder( dispenserDatatokenAddress, consumerAccount, @@ -837,7 +898,9 @@ Let's do a quick check of the consumer ETH balance before the swap 0, providerFees ) - // get the url +``` +Now we can get the download URL +```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, consumerAccount, @@ -847,7 +910,9 @@ Let's do a quick check of the consumer ETH balance before the swap providerUrl, web3 ) - +``` +Let's check we received the download URL ok +```Typescript console.log(`Download URL: ${downloadURL}`) consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount) diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index 55c4c0c5..8392658b 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -199,7 +199,9 @@ describe('Marketplace flow tests', async () => { config = await getTestConfig(web3) aquarius = new Aquarius(config.metadataCacheUri) providerUrl = config.providerUri - + /// ``` + /// As we go along it's a good idea to console log the values so that you check they are right + /// ```Typescript console.log(`Aquarius URL: ${config.metadataCacheUri}`) console.log(`Provider URL: ${providerUrl}`) }) /// @@ -211,7 +213,9 @@ describe('Marketplace flow tests', async () => { publisherAccount = accounts[0] consumerAccount = accounts[1] stakerAccount = accounts[2] - + /// ``` + /// Again, lets console log the values so that we can check that they have been saved properly + /// ```Typescript console.log(`Publisher account address: ${publisherAccount}`) console.log(`Consumer account address: ${consumerAccount}`) console.log(`Staker account address: ${stakerAccount}`) @@ -283,7 +287,9 @@ describe('Marketplace flow tests', async () => { swapFeeLiquidityProvider: '0.001', swapFeeMarketRunner: '0.001' } - + /// ``` + /// Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens + /// ```Typescript await approve( web3, publisherAccount, @@ -292,6 +298,9 @@ describe('Marketplace flow tests', async () => { poolParams.vestingAmount ) + /// ``` + /// Now we can make the contract call + /// ```Typescript const tx = await factory.createNftErc20WithPool( publisherAccount, nftParams, @@ -302,7 +311,9 @@ describe('Marketplace flow tests', async () => { poolNftAddress = tx.events.NFTCreated.returnValues[0] poolDatatokenAddress = tx.events.TokenCreated.returnValues[0] poolAddress = tx.events.NewPool.returnValues[0] - + /// ``` + /// Now, we did quite a few things there. Let's check that we successfully published a dataset (create NFT + Datatoken) with a liquidity pool + /// ```Typescript console.log(`Pool NFT address: ${poolNftAddress}`) console.log(`Pool Datatoken address: ${poolDatatokenAddress}`) console.log(`Pool address: ${poolAddress}`) @@ -351,8 +362,14 @@ describe('Marketplace flow tests', async () => { /// ```Typescript const pool = new Pool(web3) + /// ``` + /// Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens + /// ```Typescript await approve(web3, stakerAccount, contracts.oceanAddress, poolAddress, '5', true) + /// ``` + /// Now we can make the contract call + /// ```Typescript await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1') }) /// /// ``` @@ -398,6 +415,9 @@ describe('Marketplace flow tests', async () => { /// ```Typescript console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) + /// ``` + /// Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens + /// ```Typescript await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') const pool = new Pool(web3) @@ -411,6 +431,10 @@ describe('Marketplace flow tests', async () => { tokenAmountOut: '1', swapMarketFee: '0.1' } + + /// ``` + /// Now we can make the contract call + /// ```Typescript await pool.swapExactAmountOut( consumerAccount, poolAddress, @@ -432,7 +456,9 @@ describe('Marketplace flow tests', async () => { const resolvedDDO = await aquarius.waitForAqua(DDO.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - // initialize provider + /// ``` + /// The next step is to initialize the provider instance + /// ```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, resolvedDDO.services[0].id, @@ -451,7 +477,10 @@ describe('Marketplace flow tests', async () => { providerData: initializeData.providerFee.providerData, validUntil: initializeData.providerFee.validUntil } - // make the payment + + /// ``` + /// Now let's make a payment + /// ```Typescript const tx = await datatoken.startOrder( poolDatatokenAddress, consumerAccount, @@ -459,7 +488,10 @@ describe('Marketplace flow tests', async () => { 0, providerFees ) - // get the url + + /// ``` + /// Next up, let's get the URL + /// ```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, consumerAccount, @@ -557,13 +589,18 @@ describe('Marketplace flow tests', async () => { /// ```Typescript const nft = new Nft(web3) - // update ddo and set the right did + /// ``` + /// Now we are going to update the ddo and set the did + /// ```Typescript DDO.chainId = await web3.eth.getChainId() DDO.id = 'did:op:' + SHA256(web3.utils.toChecksumAddress(freNftAddress) + DDO.chainId.toString(10)) DDO.nftAddress = freNftAddress - // encrypt file(s) using provider + + /// ``` + /// Next, let's encrypt the file(s) using provider + /// ```Typescript const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = freDatatokenAddress @@ -624,6 +661,9 @@ describe('Marketplace flow tests', async () => { let consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) console.log(`Consumer ${FRE_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) + /// ``` + /// Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens + /// ```Typescript await approve(web3, consumerAccount, contracts.oceanAddress, freAddress, '100') await approve( web3, @@ -634,6 +674,9 @@ describe('Marketplace flow tests', async () => { ) const fixedRate = new FixedRateExchange(web3, freAddress) + /// ``` + /// Now we can make the contract call + /// ```Typescript await fixedRate.buyDT(consumerAccount, freId, '1', '2') consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) @@ -644,7 +687,9 @@ describe('Marketplace flow tests', async () => { const resolvedDDO = await aquarius.waitForAqua(DDO.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - // initialize provider + /// ``` + /// Next, we need to initialize the provider + /// ```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, resolvedDDO.services[0].id, @@ -663,7 +708,10 @@ describe('Marketplace flow tests', async () => { providerData: initializeData.providerFee.providerData, validUntil: initializeData.providerFee.validUntil } - // make the payment + + /// ``` + /// Lets now make the payment + /// ```Typescript const tx = await datatoken.startOrder( freDatatokenAddress, consumerAccount, @@ -671,7 +719,9 @@ describe('Marketplace flow tests', async () => { 0, providerFees ) - // get the url + /// ``` + /// Now we can get the url + /// ```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, consumerAccount, @@ -682,6 +732,9 @@ describe('Marketplace flow tests', async () => { web3 ) + /// ``` + /// Lets check that the download URL was successfully received + /// ```Typescript console.log(`Download URL: ${downloadURL}`) consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) @@ -741,24 +794,31 @@ describe('Marketplace flow tests', async () => { dispenserNftAddress = tx.events.NFTCreated.returnValues[0] dispenserDatatokenAddress = tx.events.TokenCreated.returnValues[0] dispenserAddress = tx.events.DispenserCreated.returnValues[0] - + /// ``` + /// Lets check that we managed to received all of those values without any problems + /// ```Typescript console.log(`Dispenser NFT address: ${dispenserNftAddress}`) console.log(`Dispenser Datatoken address: ${dispenserDatatokenAddress}`) console.log(`Dispenser address: ${dispenserAddress}`) - }) + }) /// /// ``` it('Set metadata in the dispenser NFT', async () => { /// ```Typescript const nft = new Nft(web3) - // update ddo and set the right did + /// ``` + /// Lets start by updating the ddo and setting the did + /// ```Typescript DDO.chainId = await web3.eth.getChainId() DDO.id = 'did:op:' + SHA256(web3.utils.toChecksumAddress(dispenserNftAddress) + DDO.chainId.toString(10)) DDO.nftAddress = dispenserNftAddress - // encrypt file(s) using provider + + /// ``` + /// Now we need to encrypt file(s) using provider + /// ```Typescript const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) DDO.services[0].files = await encryptedFiles DDO.services[0].datatokenAddress = dispenserDatatokenAddress @@ -809,8 +869,9 @@ describe('Marketplace flow tests', async () => { const resolvedDDO = await aquarius.waitForAqua(DDO.id) assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - - // initialize provider + /// ``` + /// At this point we need to encrypt file(s) using provider + /// ```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, resolvedDDO.services[0].id, @@ -829,7 +890,9 @@ describe('Marketplace flow tests', async () => { providerData: initializeData.providerFee.providerData, validUntil: initializeData.providerFee.validUntil } - // make the payment + /// ``` + /// Now we need to make the payment + /// ```Typescript const tx = await datatoken.startOrder( dispenserDatatokenAddress, consumerAccount, @@ -837,7 +900,9 @@ describe('Marketplace flow tests', async () => { 0, providerFees ) - // get the url + /// ``` + /// Now we can get the download URL + /// ```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, consumerAccount, @@ -847,7 +912,9 @@ describe('Marketplace flow tests', async () => { providerUrl, web3 ) - + /// ``` + /// Let's check we received the download URL ok + /// ```Typescript console.log(`Download URL: ${downloadURL}`) consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount) From a8354af5488bc430b36e24b17aa7b29aa64d7d66 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Fri, 6 May 2022 09:57:17 +0300 Subject: [PATCH 34/58] Updating test command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4ebe4fa..4e9181ee 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "test:factory": "npm run mocha -- 'test/unit/NftFactory.test.ts'", "test:router": "npm run mocha -- 'test/unit/pools/Router.test.ts'", "test:publishAll": "npm run mocha -- 'test/integration/PublishFlows.test.ts'", - "test:marketplace": "npm run mocha -- 'test/integration/MarketplaceFlow.test.ts'", + "test:examples": "npm run mocha -- 'test/integration/CodeExamples.test.ts'", "test:unit": "npm run mocha -- 'test/unit/**/*.test.ts'", "test:unit:cover": "nyc --report-dir coverage/unit npm run test:unit", "test:integration": "npm run mocha -- 'test/integration/**/*.test.ts'", From 287082e1f7cf918ef6af5543a2a8e1a51c5b8794 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Fri, 6 May 2022 11:15:17 +0200 Subject: [PATCH 35/58] add DDO type --- test/integration/SimplePublishConsumeFlow.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/SimplePublishConsumeFlow.test.ts b/test/integration/SimplePublishConsumeFlow.test.ts index 99b4e87f..0dab2e4e 100644 --- a/test/integration/SimplePublishConsumeFlow.test.ts +++ b/test/integration/SimplePublishConsumeFlow.test.ts @@ -12,7 +12,7 @@ import { Nft, downloadFile } from '../../src' -import { ProviderFees, Erc20CreateParams } from '../../src/@types' +import { ProviderFees, Erc20CreateParams, DDO } from '../../src/@types' const assetUrl = [ { @@ -21,7 +21,7 @@ const assetUrl = [ method: 'GET' } ] -const ddo = { +const ddo: DDO = { '@context': ['https://w3id.org/did/v1'], id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', version: '4.0.0', From 4968d2d63dea6a528ce4aaace345b289d50859a7 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Fri, 6 May 2022 16:04:30 +0300 Subject: [PATCH 36/58] Updating comments and numbering --- test/integration/CodeExamples.test.ts | 50 ++++++++++++++------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index 8392658b..5e0432fa 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -9,7 +9,7 @@ /// 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. -/// These examples take you through a typical user journey that 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. +/// These examples take you through a typical user journey that focuses on the experience of a publisher, and a buyer / consumer. /// 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). @@ -17,16 +17,17 @@ /// Here are the steps: -/// 1. [Prerequisites](#-Prerequisites) -/// 2. [Initialize services](#-initialize-services) -/// 3. [Create a new node.js project](#-create-a-new-node.js-project) -/// 4. [Install dependencies](#-install-dependencies) +/// 0. [Prerequisites](#-Prerequisites) +/// 1. [Initialize services](#-initialize-services) +/// 2. [Create a new node.js project](#-create-a-new-node.js-project) +/// 3. [Install dependencies](#-install-dependencies) +/// 4. [Initialize accounts and deploy contracts](#-initialize-accounts-and-deploy-contracts) /// 5. [Import dependencies and add variables and constants](#-import-dependencies-and-add-variables-and-constants) /// 6. [Publish Data NFT and a Datatoken with a liquidity pool](#-Publish-data-nft-and-a-datatoken-with-a-liquidity-pool) /// 7. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange) /// 8. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser) -/// ## 1. Prerequisites +/// ## 0. 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 @@ -207,7 +208,8 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Initialize accounts', async () => { + /// ## 5. Initialize accounts and deploy contracts + it('5.1 Initialize accounts', async () => { /// ```Typescript const accounts = await web3.eth.getAccounts() publisherAccount = accounts[0] @@ -222,13 +224,13 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Next, lets deploy the contracts', async () => { + it('5.2 Next, lets deploy the contracts', async () => { /// ```Typescript contracts = await deployContracts(web3, publisherAccount) }) /// /// ``` - it('We send some OCEAN to consumer and staker accounts', async () => { + it('5.3 We send some OCEAN to consumer and staker accounts', async () => { /// ```Typescript const oceanContract = new web3.eth.Contract( MockERC20.abi as AbiItem[], @@ -245,11 +247,11 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - /// ## 4. Publish Data NFT and a Datatoken with a liquidity pool + /// ## 6. Publish Data NFT and a Datatoken with a liquidity pool /// For pool creation, the OCEAN token is used as the base token. The base token can be changed into something else, such as USDC, DAI etc., but it will require an extra fee. - it('Publish a dataset (create NFT + Datatoken) with a liquidity pool', async () => { + it('6.1 Publish a dataset (create NFT + Datatoken) with a liquidity pool', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) @@ -320,7 +322,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Set metadata in the pool NFT', async () => { + it('6.2 Set metadata in the pool NFT', async () => { /// ```Typescript const nft = new Nft(web3) /// ``` @@ -358,7 +360,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('User should add liquidity to the pool, receiving LP tokens', async () => { + it('6.3 User should add liquidity to the pool, receiving LP tokens', async () => { /// ```Typescript const pool = new Pool(web3) @@ -374,7 +376,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Marketplace displays pool asset for sale', async () => { + it('6.4 Marketplace displays pool asset for sale', async () => { /// ```Typescript const pool = new Pool(web3) const prices = await pool.getAmountInExactOut( @@ -391,7 +393,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Consumer buys a pool data asset, and downloads it', async () => { + it('6.5 Consumer buys a pool data asset, and downloads it', async () => { /// ```Typescript const datatoken = new Datatoken(web3) @@ -525,9 +527,9 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - /// ## 5. Publish Data NFT and a Datatoken with a fixed rate exchange + /// ## 7. Publish Data NFT and a Datatoken with a fixed rate exchange - it('Publish a dataset (create NFT + Datatoken) with a fixed rate exchange', async () => { + it('7.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) @@ -585,7 +587,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Set metadata in the fixed rate exchange NFT', async () => { + it('7.2 Set metadata in the fixed rate exchange NFT', async () => { /// ```Typescript const nft = new Nft(web3) @@ -626,7 +628,7 @@ describe('Marketplace flow tests', async () => { }) /// ``` - it('Marketplace displays fixed rate asset for sale', async () => { + it('7.3 Marketplace displays fixed rate asset for sale', async () => { /// ```Typescript const fixedRate = new FixedRateExchange(web3, freAddress) const oceanAmount = await ( @@ -639,7 +641,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Consumer buys a fixed rate asset data asset, and downloads it', async () => { + it('7.4 Consumer buys a fixed rate asset data asset, and downloads it', async () => { /// ```Typescript const datatoken = new Datatoken(web3) const DATATOKEN_AMOUNT = '10000' @@ -751,9 +753,9 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - /// ## 6. Publish Data NFT and a Datatoken with a dispenser + /// ## 8. Publish Data NFT and a Datatoken with a dispenser - it('Publish a dataset (create NFT + Datatoken) with a dipenser', async () => { + it('8.1 Publish a dataset (create NFT + Datatoken) with a dispenser', async () => { /// ```Typescript const factory = new NftFactory(contracts.erc721FactoryAddress, web3) @@ -803,7 +805,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Set metadata in the dispenser NFT', async () => { + it('8.2 Set metadata in the dispenser NFT', async () => { /// ```Typescript const nft = new Nft(web3) @@ -841,7 +843,7 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` - it('Consumer gets a dispenser data asset, and downloads it', async () => { + it('8.3 Consumer gets a dispenser data asset, and downloads it', async () => { /// ```Typescript const datatoken = new Datatoken(web3) const dispenser = new Dispenser(web3, contracts.dispenserAddress) From 1749b0d989fc50c6129bef7fac7c6709d0ea09da Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 9 May 2022 09:01:05 +0200 Subject: [PATCH 37/58] update call to Dispenser constructor --- test/integration/CodeExamples.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index 5e0432fa..531b7010 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -846,7 +846,7 @@ describe('Marketplace flow tests', async () => { it('8.3 Consumer gets a dispenser data asset, and downloads it', async () => { /// ```Typescript const datatoken = new Datatoken(web3) - const dispenser = new Dispenser(web3, contracts.dispenserAddress) + const dispenser = new Dispenser(web3, null, contracts.dispenserAddress) let consumerDTBalance = await balance( web3, From 55fec840c30bbde3cf73fa7e9e1e77fc8b953bca Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Mon, 9 May 2022 11:19:34 +0200 Subject: [PATCH 38/58] get addresses from config file instead of deploying it --- test/integration/CodeExamples.test.ts | 59 +++++++++++++-------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index 531b7010..670502d6 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -113,8 +113,7 @@ import { TokenInOutMarket, ZERO_ADDRESS } from '../../src' -import { getTestConfig, web3 } from '../config' -import { Addresses, deployContracts } from '../TestContractHandler' +import { getAddresses, getTestConfig, web3 } from '../config' /// ``` /// - -Now we define the variables which we will need later - -```Typescript - let config: Config - let aquarius: Aquarius - let providerUrl: any - let publisherAccount: string - let consumerAccount: string - let stakerAccount: string - let contracts: Addresses - let poolNftAddress: string - let poolDatatokenAddress: string - let poolAddress: string - let freNftAddress: string - let freDatatokenAddress: string - let freAddress: string - let freId: string - let dispenserNftAddress: string - let dispenserDatatokenAddress: string - let dispenserAddress: string -``` - -We also define some constants that we will use: -```Typescript - const POOL_NFT_NAME = 'Datatoken 1' - const POOL_NFT_SYMBOL = 'DT1' - const FRE_NFT_NAME = 'Datatoken 2' - const FRE_NFT_SYMBOL = 'DT2' - const DISP_NFT_NAME = 'Datatoken 3' - const DISP_NFT_SYMBOL = 'DT3' -``` - - We will need a file to publish, so here we define the file that we intend to publish. -```Typescript - const ASSET_URL = [ - { - 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 DDO = { - '@context': ['https://w3id.org/did/v1'], - id: '', - version: '4.0.0', - chainId: 4, - nftAddress: '0x0', - metadata: { - created: '2021-12-20T14:35:20Z', - updated: '2021-12-20T14:35:20Z', - type: 'dataset', - name: 'dataset-name', - description: 'Ocean protocol test dataset description', - author: 'oceanprotocol-team', - license: 'MIT' - }, - services: [ - { - id: 'testFakeId', - type: 'access', - files: '', - datatokenAddress: '0x0', - serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', - timeout: 0 - } - ] - } -``` - -We load the configuration: -```Typescript - - config = await getTestConfig(web3) - aquarius = new Aquarius(config.metadataCacheUri) - providerUrl = config.providerUri -``` -As we go along it's a good idea to console log the values so that you check they are right -```Typescript - console.log(`Aquarius URL: ${config.metadataCacheUri}`) - console.log(`Provider URL: ${providerUrl}`) - -``` - - ### Initialize accounts -```Typescript - const accounts = await web3.eth.getAccounts() - publisherAccount = accounts[0] - consumerAccount = accounts[1] - stakerAccount = accounts[2] -``` -Again, lets console log the values so that we can check that they have been saved properly -```Typescript - console.log(`Publisher account address: ${publisherAccount}`) - console.log(`Consumer account address: ${consumerAccount}`) - console.log(`Staker account address: ${stakerAccount}`) - -``` - - ### Next, lets deploy the contracts -```Typescript - contracts = await deployContracts(web3, publisherAccount) - -``` - - ### We send some OCEAN to consumer and staker accounts -```Typescript - const oceanContract = new web3.eth.Contract( - MockERC20.abi as AbiItem[], - contracts.oceanAddress - ) - - await oceanContract.methods - .transfer(consumerAccount, web3.utils.toWei('100')) - .send({ from: publisherAccount }) - - await oceanContract.methods - .transfer(stakerAccount, web3.utils.toWei('100')) - .send({ from: publisherAccount }) - -``` - -## 4. Publish Data NFT and a Datatoken with a liquidity pool - -For pool creation, the OCEAN token is used as the base token. The base token can be changed into something else, such as USDC, DAI etc., but it will require an extra fee. - - ### Publish a dataset (create NFT + Datatoken) with a liquidity pool -```Typescript - const factory = new NftFactory(contracts.erc721FactoryAddress, web3) - - const nftParams: NftCreateData = { - name: POOL_NFT_NAME, - symbol: POOL_NFT_SYMBOL, - templateIndex: 1, - tokenURI: '', - transferable: true, - owner: publisherAccount - } - - const erc20Params: Erc20CreateParams = { - templateIndex: 1, - cap: '100000', - feeAmount: '0', - paymentCollector: ZERO_ADDRESS, - feeToken: ZERO_ADDRESS, - minter: publisherAccount, - mpFeeAddress: ZERO_ADDRESS - } - - const poolParams: PoolCreationParams = { - ssContract: contracts.sideStakingAddress, - baseTokenAddress: contracts.oceanAddress, - baseTokenSender: contracts.erc721FactoryAddress, - publisherAddress: publisherAccount, - marketFeeCollector: publisherAccount, - poolTemplateAddress: contracts.poolTemplateAddress, - rate: '1', - baseTokenDecimals: 18, - vestingAmount: '10000', - vestedBlocks: 2500000, - initialBaseTokenLiquidity: '2000', - swapFeeLiquidityProvider: '0.001', - swapFeeMarketRunner: '0.001' - } -``` -Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens -```Typescript - await approve( - web3, - publisherAccount, - contracts.oceanAddress, - contracts.erc721FactoryAddress, - poolParams.vestingAmount - ) - -``` -Now we can make the contract call -```Typescript - const tx = await factory.createNftErc20WithPool( - publisherAccount, - nftParams, - erc20Params, - poolParams - ) - - poolNftAddress = tx.events.NFTCreated.returnValues[0] - poolDatatokenAddress = tx.events.TokenCreated.returnValues[0] - poolAddress = tx.events.NewPool.returnValues[0] -``` -Now, we did quite a few things there. Let's check that we successfully published a dataset (create NFT + Datatoken) with a liquidity pool -```Typescript - console.log(`Pool NFT address: ${poolNftAddress}`) - console.log(`Pool Datatoken address: ${poolDatatokenAddress}`) - console.log(`Pool address: ${poolAddress}`) - -``` - - ### Set metadata in the pool NFT -```Typescript - const nft = new Nft(web3) -``` -Now we update the ddo and set the right did -```Typescript - DDO.chainId = await web3.eth.getChainId() - DDO.id = - 'did:op:' + - SHA256(web3.utils.toChecksumAddress(poolNftAddress) + DDO.chainId.toString(10)) - DDO.nftAddress = poolNftAddress -``` -Next we encrypt the file or files using Ocean Provider. The provider is an off chain proxy built specifically for this task -```Typescript - const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) - DDO.services[0].files = await encryptedFiles - DDO.services[0].datatokenAddress = poolDatatokenAddress -``` -Now let's console log the result to check everything is working -```Typescript - console.log(`DID: ${DDO.id}`) - - const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) - const encryptedDDO = await providerResponse - const metadataHash = getHash(JSON.stringify(DDO)) - await nft.setMetadata( - poolNftAddress, - publisherAccount, - 0, - providerUrl, - '', - '0x2', - encryptedDDO, - '0x' + metadataHash - ) - -``` - - ### User should add liquidity to the pool, receiving LP tokens -```Typescript - const pool = new Pool(web3) - -``` -Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens -```Typescript - await approve(web3, stakerAccount, contracts.oceanAddress, poolAddress, '5', true) - -``` -Now we can make the contract call -```Typescript - await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1') - -``` - - ### Marketplace displays pool asset for sale -```Typescript - const pool = new Pool(web3) - const prices = await pool.getAmountInExactOut( - poolAddress, - poolDatatokenAddress, - contracts.oceanAddress, - '1', - '0.01' - ) -``` -Now let's console log the result to check everything is working -```Typescript - console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`) - -``` - - ### Consumer buys a pool data asset, and downloads it -```Typescript - const datatoken = new Datatoken(web3) - - const consumerETHBalance = await web3.eth.getBalance(consumerAccount) -``` -Now let's console log the result to check everything is working -```Typescript - console.log(`Consumer ETH balance: ${consumerETHBalance}`) - let consumerOCEANBalance = await balance( - web3, - contracts.oceanAddress, - consumerAccount - ) -``` -Now let's console log consumerOCEANBalance to check everything is working -```Typescript - console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) - let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) -``` -Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything is working -```Typescript - console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) - -``` -Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens -```Typescript - await approve(web3, consumerAccount, contracts.oceanAddress, poolAddress, '100') - - const pool = new Pool(web3) - const tokenInOutMarket: TokenInOutMarket = { - tokenIn: contracts.oceanAddress, - tokenOut: poolDatatokenAddress, - marketFeeAddress: consumerAccount - } - const amountsInOutMaxFee: AmountsOutMaxFee = { - maxAmountIn: '10', - tokenAmountOut: '1', - swapMarketFee: '0.1' - } - -``` -Now we can make the contract call -```Typescript - await pool.swapExactAmountOut( - consumerAccount, - poolAddress, - tokenInOutMarket, - amountsInOutMaxFee - ) - - consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) -``` -Now let's console log the Consumer OCEAN balance after swap to check everything is working -```Typescript - console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) -``` -Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance -```Typescript - console.log(`Consumer ${POOL_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) - - const resolvedDDO = await aquarius.waitForAqua(DDO.id) - assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - -``` -The next step is to initialize the provider instance -```Typescript - 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 - } - -``` -Now let's make a payment -```Typescript - const tx = await datatoken.startOrder( - poolDatatokenAddress, - consumerAccount, - consumerAccount, - 0, - providerFees - ) - -``` -Next up, let's get the URL -```Typescript - const downloadURL = await ProviderInstance.getDownloadUrl( - DDO.id, - consumerAccount, - DDO.services[0].id, - 0, - tx.transactionHash, - providerUrl, - web3 - ) - -``` -Now let's console log the Download URL to check everything is working -```Typescript - console.log(`Download URL: ${downloadURL}`) - - consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) - console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount) - -``` -Now let's console log the Consumer balance after order to check everything is working -```Typescript - console.log(`Consumer ${POOL_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) - - try { - const fileData = await downloadFile(downloadURL) - console.log(fileData) - } catch (e) { - assert.fail('Download failed') - } - -``` - -## 5. Publish Data NFT and a Datatoken with a fixed rate exchange - - ### Publish a dataset (create NFT + Datatoken) with a fixed rate exchange -```Typescript - const factory = new NftFactory(contracts.erc721FactoryAddress, web3) - - const nftParams: NftCreateData = { - name: FRE_NFT_NAME, - symbol: FRE_NFT_SYMBOL, - templateIndex: 1, - tokenURI: '', - transferable: true, - owner: publisherAccount - } - - const erc20Params: Erc20CreateParams = { - templateIndex: 1, - cap: '100000', - feeAmount: '0', - paymentCollector: ZERO_ADDRESS, - feeToken: ZERO_ADDRESS, - minter: publisherAccount, - mpFeeAddress: ZERO_ADDRESS - } - - const freParams: FreCreationParams = { - fixedRateAddress: contracts.fixedRateAddress, - baseTokenAddress: contracts.oceanAddress, - owner: publisherAccount, - marketFeeCollector: publisherAccount, - baseTokenDecimals: 18, - datatokenDecimals: 18, - fixedRate: '1', - marketFee: '0.001', - allowedConsumer: ZERO_ADDRESS, - withMint: false - } - - const tx = await factory.createNftErc20WithFixedRate( - publisherAccount, - nftParams, - erc20Params, - freParams - ) - - freNftAddress = tx.events.NFTCreated.returnValues[0] - freDatatokenAddress = tx.events.TokenCreated.returnValues[0] - freAddress = tx.events.NewFixedRate.returnValues.exchangeContract - freId = tx.events.NewFixedRate.returnValues.exchangeId - -``` -Now let's console log each of those values to check everything is working -```Typescript - console.log(`Fixed rate exchange NFT address: ${freNftAddress}`) - console.log(`Fixed rate exchange Datatoken address: ${freDatatokenAddress}`) - console.log(`Fixed rate exchange address: ${freAddress}`) - console.log(`Fixed rate exchange Id: ${freId}`) - -``` - - ### Set metadata in the fixed rate exchange NFT -```Typescript - const nft = new Nft(web3) - -``` -Now we are going to update the ddo and set the did -```Typescript - DDO.chainId = await web3.eth.getChainId() - DDO.id = - 'did:op:' + - SHA256(web3.utils.toChecksumAddress(freNftAddress) + DDO.chainId.toString(10)) - DDO.nftAddress = freNftAddress - -``` -Next, let's encrypt the file(s) using provider -```Typescript - const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) - DDO.services[0].files = await encryptedFiles - DDO.services[0].datatokenAddress = freDatatokenAddress - -``` -Now let's console log the DID to check everything is working -```Typescript - console.log(`DID: ${DDO.id}`) - - const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) - const encryptedDDO = await providerResponse - const metadataHash = getHash(JSON.stringify(DDO)) - await nft.setMetadata( - freNftAddress, - publisherAccount, - 0, - providerUrl, - '', - '0x2', - encryptedDDO, - '0x' + metadataHash - ) - }) -``` - - ### Marketplace displays fixed rate asset for sale -```Typescript - const fixedRate = new FixedRateExchange(web3, freAddress) - const oceanAmount = await ( - await fixedRate.calcBaseInGivenOutDT(freId, '1') - ).baseTokenAmount -``` -Now that the market has fetched those values it can display the asset on the front end. In our case we will just console log the results: -```Typescript - console.log(`Price of 1 ${FRE_NFT_SYMBOL} is ${oceanAmount} OCEAN`) - -``` - - ### Consumer buys a fixed rate asset data asset, and downloads it -```Typescript - const datatoken = new Datatoken(web3) - const DATATOKEN_AMOUNT = '10000' - - await datatoken.mint(freDatatokenAddress, publisherAccount, DATATOKEN_AMOUNT) - - const consumerETHBalance = await web3.eth.getBalance(consumerAccount) - -``` -Let's do a quick check of the consumer ETH balance before the swap -```Typescript - console.log(`Consumer ETH balance: ${consumerETHBalance}`) - let consumerOCEANBalance = await balance( - web3, - contracts.oceanAddress, - consumerAccount - ) - console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`) - let consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) - console.log(`Consumer ${FRE_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`) - -``` -Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens -```Typescript - await approve(web3, consumerAccount, contracts.oceanAddress, freAddress, '100') - await approve( - web3, - publisherAccount, - freDatatokenAddress, - freAddress, - DATATOKEN_AMOUNT - ) - - const fixedRate = new FixedRateExchange(web3, freAddress) -``` -Now we can make the contract call -```Typescript - await fixedRate.buyDT(consumerAccount, freId, '1', '2') - - consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) - console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) - console.log(`Consumer ${FRE_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`) - - const resolvedDDO = await aquarius.waitForAqua(DDO.id) - assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') - -``` -Next, we need to initialize the provider -```Typescript - 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 - } - -``` -Lets now make the payment -```Typescript - const tx = await datatoken.startOrder( - freDatatokenAddress, - consumerAccount, - consumerAccount, - 0, - providerFees - ) -``` -Now we can get the url -```Typescript - const downloadURL = await ProviderInstance.getDownloadUrl( - DDO.id, - consumerAccount, - DDO.services[0].id, - 0, - tx.transactionHash, - providerUrl, - web3 - ) - -``` -Lets check that the download URL was successfully received -```Typescript - console.log(`Download URL: ${downloadURL}`) - - consumerOCEANBalance = await balance(web3, contracts.oceanAddress, consumerAccount) - console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`) - consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount) - console.log(`Consumer ${FRE_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) - - try { - const fileData = await downloadFile(downloadURL) - console.log(fileData) - } catch (e) { - assert.fail('Download failed') - } - -``` - -## 6. Publish Data NFT and a Datatoken with a dispenser - - ### Publish a dataset (create NFT + Datatoken) with a dipenser -```Typescript - const factory = new NftFactory(contracts.erc721FactoryAddress, web3) - - const nftParams: NftCreateData = { - name: DISP_NFT_NAME, - symbol: DISP_NFT_SYMBOL, - templateIndex: 1, - tokenURI: '', - transferable: true, - owner: publisherAccount - } - - const erc20Params: Erc20CreateParams = { - templateIndex: 1, - cap: '100000', - feeAmount: '0', - paymentCollector: ZERO_ADDRESS, - feeToken: ZERO_ADDRESS, - minter: publisherAccount, - mpFeeAddress: ZERO_ADDRESS - } - - const dispenserParams: DispenserCreationParams = { - dispenserAddress: contracts.dispenserAddress, - maxTokens: '1', - maxBalance: '1', - withMint: true, - allowedSwapper: ZERO_ADDRESS - } - - const tx = await factory.createNftErc20WithDispenser( - publisherAccount, - nftParams, - erc20Params, - dispenserParams - ) - - dispenserNftAddress = tx.events.NFTCreated.returnValues[0] - dispenserDatatokenAddress = tx.events.TokenCreated.returnValues[0] - dispenserAddress = tx.events.DispenserCreated.returnValues[0] - - console.log(`Dispenser NFT address: ${dispenserNftAddress}`) - console.log(`Dispenser Datatoken address: ${dispenserDatatokenAddress}`) - console.log(`Dispenser address: ${dispenserAddress}`) - }) -``` - - ### Set metadata in the dispenser NFT -```Typescript - const nft = new Nft(web3) - -``` -Lets start by updating the ddo and setting the did -```Typescript - DDO.chainId = await web3.eth.getChainId() - DDO.id = - 'did:op:' + - SHA256(web3.utils.toChecksumAddress(dispenserNftAddress) + DDO.chainId.toString(10)) - DDO.nftAddress = dispenserNftAddress - -``` -Now we need to encrypt file(s) using provider -```Typescript - const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl) - DDO.services[0].files = await encryptedFiles - DDO.services[0].datatokenAddress = dispenserDatatokenAddress - - console.log(`DID: ${DDO.id}`) - - const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl) - const encryptedDDO = await providerResponse - const metadataHash = getHash(JSON.stringify(DDO)) - await nft.setMetadata( - dispenserNftAddress, - publisherAccount, - 0, - providerUrl, - '', - '0x2', - encryptedDDO, - '0x' + metadataHash - ) - -``` - - ### Consumer gets a dispenser data asset, and downloads it -```Typescript - const datatoken = new Datatoken(web3) - const dispenser = new Dispenser(web3, contracts.dispenserAddress) - - let consumerDTBalance = await balance( - web3, - dispenserDatatokenAddress, - consumerAccount - ) - console.log( - `Consumer ${DISP_NFT_SYMBOL} balance before dispense: ${consumerDTBalance}` - ) - - await dispenser.dispense( - dispenserDatatokenAddress, - consumerAccount, - '1', - consumerAccount - ) - - consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount) - console.log( - `Consumer ${DISP_NFT_SYMBOL} balance after dispense: ${consumerDTBalance}` - ) - - const resolvedDDO = await aquarius.waitForAqua(DDO.id) - assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') -``` -At this point we need to encrypt file(s) using provider -```Typescript - 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 - } -``` -Now we need to make the payment -```Typescript - const tx = await datatoken.startOrder( - dispenserDatatokenAddress, - consumerAccount, - consumerAccount, - 0, - providerFees - ) -``` -Now we can get the download URL -```Typescript - const downloadURL = await ProviderInstance.getDownloadUrl( - DDO.id, - consumerAccount, - DDO.services[0].id, - 0, - tx.transactionHash, - providerUrl, - web3 - ) -``` -Let's check we received the download URL ok -```Typescript - console.log(`Download URL: ${downloadURL}`) - - consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount) - console.log(`Consumer ${DISP_NFT_SYMBOL} balance after order: ${consumerDTBalance}`) - - try { - const fileData = await downloadFile(downloadURL) - console.log(fileData) - } catch (e) { - assert.fail('Download failed') - } - -``` - From 8b164b9f85759856b98c87b61e0039b91e150e3e Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Tue, 17 May 2022 11:38:30 +0300 Subject: [PATCH 41/58] Adding create:guide command to CI --- .github/workflows/ci.yml | 12 ++++++++++++ .gitignore | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b6f457c..1c7e0085 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -191,4 +191,16 @@ jobs: create_guide: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '16' + - name: Cache node_modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-lint-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-lint-${{ env.cache-name }}- - run: npm run create:guide \ No newline at end of file diff --git a/.gitignore b/.gitignore index 822ec977..67ab7f5c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ src/**/*.js src/metadata\.json .idea .vscode -.DS_Store \ No newline at end of file +.DS_Store +CodeExamples.md \ No newline at end of file From 77af85cd3a4ec66d7e4e9e315640927b142d998b Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 10:47:12 +0300 Subject: [PATCH 42/58] Adding commit to CI --- .github/workflows/ci.yml | 22 +++++++++++++++++++++- .npmignore | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c7e0085..e1f1b4e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -203,4 +203,24 @@ jobs: path: ~/.npm key: ${{ runner.os }}-lint-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: ${{ runner.os }}-lint-${{ env.cache-name }}- - - run: npm run create:guide \ No newline at end of file + - run: npm run create:guide + - name: checkout + uses: actions/checkout@v2 + + - name: save current date + run: | + # do some operation that changes a file in the git repo + date > time.txt + + - name: setup git config + run: | + # setup the username and email. I tend to use 'GitHub Actions Bot' with no email by default + git config user.name "GitHub Actions Bot" + git config user.email "<>" + + - name: commit + run: | + # Stage the file, commit and push + git add time.txt + git commit -m "new date commit" + git push origin master \ No newline at end of file diff --git a/.npmignore b/.npmignore index 24f8bac1..772f8440 100644 --- a/.npmignore +++ b/.npmignore @@ -19,4 +19,4 @@ ganache* .editorconfig .eslintrc SQUID_INTERFACE.md -CodeExamples.md + From 36d7b124148aa91ecffd178f14923ebdd1a0d070 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 11:02:22 +0300 Subject: [PATCH 43/58] Updating CI to checkout current branch --- .github/workflows/ci.yml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ea1efa5..26d8ce11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -191,7 +191,16 @@ jobs: - uses: actions/setup-node@v2 with: node-version: '16' - - name: Cache node_modules + + - name: checkout + uses: actions/checkout@v2 + + - name: save current date + run: | + # do some operation that changes a file in the git repo + date > time.txt + + - name: Create code examples file uses: actions/cache@v2 env: cache-name: cache-node-modules @@ -200,13 +209,6 @@ jobs: key: ${{ runner.os }}-lint-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: ${{ runner.os }}-lint-${{ env.cache-name }}- - run: npm run create:guide - - name: checkout - uses: actions/checkout@v2 - - - name: save current date - run: | - # do some operation that changes a file in the git repo - date > time.txt - name: setup git config run: | @@ -217,6 +219,8 @@ jobs: - name: commit run: | # Stage the file, commit and push - git add time.txt - git commit -m "new date commit" - git push origin master \ No newline at end of file + BRANCH=$(git branch --show-current) + git checkout "${BRANCH}" + git add CodeExamples.md + git commit -m "Updating CodeExamples.md" + git push \ No newline at end of file From 868de7c17863e90404e165819d2d73983765f5ed Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 11:47:02 +0300 Subject: [PATCH 44/58] fixing linting & solving conflict --- .github/workflows/ci.yml | 5 ++- .../SimplePublishConsumeFlow.test.ts | 41 ------------------- 2 files changed, 3 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26d8ce11..962ca189 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,8 +219,9 @@ jobs: - name: commit run: | # Stage the file, commit and push - BRANCH=$(git branch --show-current) - git checkout "${BRANCH}" + BRANCH=${GITHUB_REF#refs/heads/} + echo ${BRANCH} + git checkout ${BRANCH} git add CodeExamples.md git commit -m "Updating CodeExamples.md" git push \ No newline at end of file diff --git a/test/integration/SimplePublishConsumeFlow.test.ts b/test/integration/SimplePublishConsumeFlow.test.ts index 6cd62f15..1036ed69 100644 --- a/test/integration/SimplePublishConsumeFlow.test.ts +++ b/test/integration/SimplePublishConsumeFlow.test.ts @@ -14,47 +14,6 @@ import { ZERO_ADDRESS } from '../../src' import { ProviderFees, Erc20CreateParams, DDO } from '../../src/@types' -<<<<<<< HEAD - -const assetUrl = [ - { - type: 'url', - url: 'https://raw.githubusercontent.com/oceanprotocol/testdatasets/main/shs_dataset_test.txt', - method: 'GET' - } -] -const ddo: 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 - } - ] -} -======= ->>>>>>> 620b5d3a24e3d76a7b9ac1fc78a370add76f549a describe('Simple Publish & consume test', async () => { let config: Config From 3963f9bfbcf019133956d9fe1ac82e0fd57511b0 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 11:56:12 +0300 Subject: [PATCH 45/58] Updating branch name - base head ref in github actions --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 962ca189..2172a57e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,7 +219,7 @@ jobs: - name: commit run: | # Stage the file, commit and push - BRANCH=${GITHUB_REF#refs/heads/} + BRANCH=${GITHUB_HEAD_REF#refs/heads/} echo ${BRANCH} git checkout ${BRANCH} git add CodeExamples.md From 35e59520816160717f5c716f10ef35a703a50b53 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 12:09:54 +0300 Subject: [PATCH 46/58] Adding git remote origin to CI --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2172a57e..525d31fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,9 +219,10 @@ jobs: - name: commit run: | # Stage the file, commit and push + git remote add origin https://github.com/oceanprotocol/ocean.js.git BRANCH=${GITHUB_HEAD_REF#refs/heads/} echo ${BRANCH} - git checkout ${BRANCH} + git checkout origin/${BRANCH} git add CodeExamples.md git commit -m "Updating CodeExamples.md" git push \ No newline at end of file From 80ff80e0f3fffe73c8685e4f573879f4dba86e68 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 12:17:37 +0300 Subject: [PATCH 47/58] Updating gitignore --- .github/workflows/ci.yml | 2 +- .gitignore | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 525d31fe..50e4b3fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,7 +219,7 @@ jobs: - name: commit run: | # Stage the file, commit and push - git remote add origin https://github.com/oceanprotocol/ocean.js.git + git pull BRANCH=${GITHUB_HEAD_REF#refs/heads/} echo ${BRANCH} git checkout origin/${BRANCH} diff --git a/.gitignore b/.gitignore index 67ab7f5c..822ec977 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,4 @@ src/**/*.js src/metadata\.json .idea .vscode -.DS_Store -CodeExamples.md \ No newline at end of file +.DS_Store \ No newline at end of file From ca76294eec4c1bbabadc692faa2534f403abed85 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 12:21:55 +0300 Subject: [PATCH 48/58] Updating CI --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50e4b3fc..78070f59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -219,7 +219,6 @@ jobs: - name: commit run: | # Stage the file, commit and push - git pull BRANCH=${GITHUB_HEAD_REF#refs/heads/} echo ${BRANCH} git checkout origin/${BRANCH} From 9adcf46ab2a5e0e4fe6e457328ffe09aaf3ed5b7 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 12:45:07 +0300 Subject: [PATCH 49/58] Checking out current branch with actions/checkout@v2 --- .github/workflows/ci.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78070f59..7e59b44d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,13 +192,12 @@ jobs: with: node-version: '16' - - name: checkout + - name: checkout current branch uses: actions/checkout@v2 - - - name: save current date - run: | - # do some operation that changes a file in the git repo - date > time.txt + with: + repository: 'oceanprotocol/ocean.js' + path: 'ocean.js' + ref: ${GITHUB_HEAD_REF#refs/heads/} - name: Create code examples file uses: actions/cache@v2 @@ -219,9 +218,7 @@ jobs: - name: commit run: | # Stage the file, commit and push - BRANCH=${GITHUB_HEAD_REF#refs/heads/} - echo ${BRANCH} - git checkout origin/${BRANCH} + git status git add CodeExamples.md git commit -m "Updating CodeExamples.md" git push \ No newline at end of file From ee3a128f595096221bc7ffc7cbee22052e451abb Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 12:53:43 +0300 Subject: [PATCH 50/58] Updating branch name ref --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e59b44d..217e24ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,7 +197,7 @@ jobs: with: repository: 'oceanprotocol/ocean.js' path: 'ocean.js' - ref: ${GITHUB_HEAD_REF#refs/heads/} + ref: echo ${GITHUB_HEAD_REF#refs/heads/} - name: Create code examples file uses: actions/cache@v2 From 396aee2c739df630f9984519e129e063a9cb49e0 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:01:35 +0300 Subject: [PATCH 51/58] Checking out current branch --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 217e24ea..9e47b1c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,7 +197,10 @@ jobs: with: repository: 'oceanprotocol/ocean.js' path: 'ocean.js' - ref: echo ${GITHUB_HEAD_REF#refs/heads/} + run: | + branch=${GITHUB_HEAD_REF#refs/heads/} + echo ${branch} + git checkout ${branch} - name: Create code examples file uses: actions/cache@v2 From 70a82f6e2f8badc7aabd95fcfebb76a7b3421c83 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:06:50 +0300 Subject: [PATCH 52/58] Adding git status check --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e47b1c2..4c6f0b28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -201,6 +201,7 @@ jobs: branch=${GITHUB_HEAD_REF#refs/heads/} echo ${branch} git checkout ${branch} + git status - name: Create code examples file uses: actions/cache@v2 From 5469ac05787467d77abcbd1216b0f799a4a17dd3 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:13:04 +0300 Subject: [PATCH 53/58] Seperating CI steps --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c6f0b28..385d8535 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,11 +192,13 @@ jobs: with: node-version: '16' - - name: checkout current branch + - name: checkout ocean.js repo uses: actions/checkout@v2 with: repository: 'oceanprotocol/ocean.js' path: 'ocean.js' + + - name: checkout current branch run: | branch=${GITHUB_HEAD_REF#refs/heads/} echo ${branch} From 23526370e760d3352a37ea36dfe93c30111fc43e Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:22:45 +0300 Subject: [PATCH 54/58] Updating git commands --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 385d8535..e49c9e5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,9 +197,11 @@ jobs: with: repository: 'oceanprotocol/ocean.js' path: 'ocean.js' + ref: main - name: checkout current branch run: | + git pull branch=${GITHUB_HEAD_REF#refs/heads/} echo ${branch} git checkout ${branch} From 067510370aa557a44b14556437cd116bacb161cc Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:34:29 +0300 Subject: [PATCH 55/58] Updating git pull steps --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e49c9e5d..864d0f8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -201,9 +201,10 @@ jobs: - name: checkout current branch run: | - git pull + git status branch=${GITHUB_HEAD_REF#refs/heads/} echo ${branch} + git pull origin ${branch} git checkout ${branch} git status From 8832ea1b4821495564e91e5b60eff539d088b090 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:40:40 +0300 Subject: [PATCH 56/58] Checkout pull request head commit --- .github/workflows/ci.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 864d0f8f..800f5a2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,16 +197,7 @@ jobs: with: repository: 'oceanprotocol/ocean.js' path: 'ocean.js' - ref: main - - - name: checkout current branch - run: | - git status - branch=${GITHUB_HEAD_REF#refs/heads/} - echo ${branch} - git pull origin ${branch} - git checkout ${branch} - git status + ref: ${{ github.event.pull_request.head.sha }} - name: Create code examples file uses: actions/cache@v2 From 1ed340cd86f22f098f2269e21e21e9c813e79717 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:46:08 +0300 Subject: [PATCH 57/58] Updating push command --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 800f5a2a..393d3d93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -221,4 +221,6 @@ jobs: git status git add CodeExamples.md git commit -m "Updating CodeExamples.md" - git push \ No newline at end of file + branch=${GITHUB_HEAD_REF#refs/heads/} + echo Pushing changes to branch: ${branch} + git push origin HEAD:${branch} \ No newline at end of file From 2249ed8a43774ed1d3b6de023e10321309b1086f Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 May 2022 13:55:36 +0300 Subject: [PATCH 58/58] Force push --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 393d3d93..897501e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -223,4 +223,4 @@ jobs: git commit -m "Updating CodeExamples.md" branch=${GITHUB_HEAD_REF#refs/heads/} echo Pushing changes to branch: ${branch} - git push origin HEAD:${branch} \ No newline at end of file + git push origin HEAD:${branch} --force \ No newline at end of file