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') + }) +})