From aef17e96d41d55d89ee5671f0164c2845fbb25ae Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 21 Dec 2022 10:51:50 +0000 Subject: [PATCH 1/8] Creating Key-value example readme --- KeyValueExamples.md | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 KeyValueExamples.md diff --git a/KeyValueExamples.md b/KeyValueExamples.md new file mode 100644 index 00000000..400b2d02 --- /dev/null +++ b/KeyValueExamples.md @@ -0,0 +1,57 @@ + + +# Quickstart: Key-value database + +Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). + +Let's see how! + +Here are the steps: + +1. Setup +2. Publish data NFT +3. Add key-value pair to data NFT +4. Retrieve value from data NFT + +## 1. Setup + +Ensure that you've already (a) [installed Ocean](install.md), and (b) [set up locally](setup-local.md) or [remotely](setup-remote.md). + +## 2. Publish data NFT + +```javascript +// from ocean_lib.models.arguments import DataNFTArguments +// data_nft = ocean.data_nft_factory.create(DataNFTArguments('NFT1', 'NFT1'), alice) +``` + +## 3. Add key-value pair to data NFT + +```javascript +// # Key-value pair +// key = "fav_color" +// value = b"blue" + +// # prep key for setter +// from web3.main import Web3 +// key_hash = Web3.keccak(text=key) # Contract/ERC725 requires keccak256 hash + +// # set +// data_nft.setNewData(key_hash, value, {"from": alice}) +``` + +## 4. Retrieve value from data NFT + +```javascript +// value2_hex = data_nft.getData(key_hash) +// value2 = value2_hex.decode('ascii') +// print(f"Found that {key} = {value2}") +``` + +That's it! Note the simplicity. All data was stored and retrieved from on-chain. We don't need Ocean Provider or Ocean Aquarius for these use cases (though the latter can help for fast querying & retrieval). + +We can also encrypt the data. Other quickstarts explore this. + +Under the hood, it uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. From 3919bf7b2d36757c484763f587346a4d4eb9d15b Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 21 Dec 2022 14:56:50 +0000 Subject: [PATCH 2/8] Adding the key-value store steps to CodeExamples.test.ts --- package.json | 1 + test/integration/CodeExamples.test.ts | 29 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/package.json b/package.json index cf1e8e4e..7a502980 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "test:unit": "npm run mocha -- 'test/unit/**/*.test.ts'", "test:unit:cover": "nyc --report-dir coverage/unit --exclude 'src/@types/**/*' npm run test:unit", "test:integration": "npm run mocha -- 'test/integration/**/*.test.ts'", + "test:guide": "npm run mocha -- 'test/integration/CodeExamples.test.ts'", "test:integration:cover": "nyc --report-dir coverage/integration --no-clean npm run test:integration", "create:guide": "./scripts/createCodeExamples.sh test/integration/CodeExamples.test.ts", "create:guidec2d": "./scripts/createCodeExamples.sh test/integration/ComputeExamples.test.ts", diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index fd1737ca..c40a8d2c 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -676,6 +676,35 @@ describe('Marketplace flow tests', async () => { } }) /// /// ``` + + it('8.1 Add key-value pair to data NFT', async () => { + /// ```Typescript + const nft = new Nft(web3) + const data = 'SomeData' + try { + /// Use the `setData` method to update the nft key value store with some data + await nft.setData(freNftAddress, publisherAccount, '1', data) + } catch (e) { + console.error(e) + assert.fail('Download failed') + } + /// ``` + }) /// + + it('8.2 Add key-value pair to data NFT', async () => { + /// ```Typescript + const nft = new Nft(web3) + try { + /// Use the `getData` method to get the data stored in the nft key value store + const data = await nft.getData(freNftAddress, '1') + console.log('Data: ', data) + } catch (e) { + console.error(e) + assert.fail('Download failed') + } + /// ``` + }) /// + /// ``` }) /// /// ## Editing this file From 726e34c8fc013523d7db6bad7a86687c9a462f2d Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 21 Dec 2022 15:04:30 +0000 Subject: [PATCH 3/8] Updating guide and formatting --- CodeExamples.md | 43 ++++++++++++++++++++ KeyValueExamples.md | 57 --------------------------- test/integration/CodeExamples.test.ts | 20 ++++++++-- 3 files changed, 60 insertions(+), 60 deletions(-) delete mode 100644 KeyValueExamples.md diff --git a/CodeExamples.md b/CodeExamples.md index fc3fe46b..afc4f547 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -677,6 +677,49 @@ Let's check we received the download URL ok ``` + ### 8.1 Add key-value pair to data NFT +Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). + +Let's see how! + +Here are the steps: + +1. Setup (same as above) +2. Publish data NFT (same as above) +3. Add key-value pair to data NFT (use the `setData` method) +4. Retrieve value from data NFT (use the `getData` method) + +Let's start by using the `setData` method to update the nft key value store with some data +```Typescript + const nft = new Nft(web3) + const data = 'SomeData' + try { + await nft.setData(freNftAddress, publisherAccount, '1', data) + } catch (e) { + console.error(e) + assert.fail('Download failed') + } +``` + +Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. + + + ### 8.2 Add key-value pair to data NFT +```Typescript + const nft = new Nft(web3) + try { + Use the `getData` method to get the data stored in the nft key value store + const data = await nft.getData(freNftAddress, '1') + console.log('Data: ', data) + } catch (e) { + console.error(e) + assert.fail('Download failed') + } +``` + +That's it! Note the simplicity. All data was stored and retrieved from on-chain. We don't need Ocean Provider or Ocean Aquarius for these use cases (though the latter can help for fast querying & retrieval). + + ## Editing this file Please note that CodeExamples.md is an autogenerated file, you should not edit it directly. diff --git a/KeyValueExamples.md b/KeyValueExamples.md deleted file mode 100644 index 400b2d02..00000000 --- a/KeyValueExamples.md +++ /dev/null @@ -1,57 +0,0 @@ - - -# Quickstart: Key-value database - -Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). - -Let's see how! - -Here are the steps: - -1. Setup -2. Publish data NFT -3. Add key-value pair to data NFT -4. Retrieve value from data NFT - -## 1. Setup - -Ensure that you've already (a) [installed Ocean](install.md), and (b) [set up locally](setup-local.md) or [remotely](setup-remote.md). - -## 2. Publish data NFT - -```javascript -// from ocean_lib.models.arguments import DataNFTArguments -// data_nft = ocean.data_nft_factory.create(DataNFTArguments('NFT1', 'NFT1'), alice) -``` - -## 3. Add key-value pair to data NFT - -```javascript -// # Key-value pair -// key = "fav_color" -// value = b"blue" - -// # prep key for setter -// from web3.main import Web3 -// key_hash = Web3.keccak(text=key) # Contract/ERC725 requires keccak256 hash - -// # set -// data_nft.setNewData(key_hash, value, {"from": alice}) -``` - -## 4. Retrieve value from data NFT - -```javascript -// value2_hex = data_nft.getData(key_hash) -// value2 = value2_hex.decode('ascii') -// print(f"Found that {key} = {value2}") -``` - -That's it! Note the simplicity. All data was stored and retrieved from on-chain. We don't need Ocean Provider or Ocean Aquarius for these use cases (though the latter can help for fast querying & retrieval). - -We can also encrypt the data. Other quickstarts explore this. - -Under the hood, it uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index c40a8d2c..c7ab5738 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -678,20 +678,33 @@ describe('Marketplace flow tests', async () => { /// ``` it('8.1 Add key-value pair to data NFT', async () => { + /// Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). + + /// Let's see how! + + /// Here are the steps: + + /// 1. Setup (same as above) + /// 2. Publish data NFT (same as above) + /// 3. Add key-value pair to data NFT (use the `setData` method) + /// 4. Retrieve value from data NFT (use the `getData` method) + + /// Let's start by using the `setData` method to update the nft key value store with some data /// ```Typescript const nft = new Nft(web3) const data = 'SomeData' try { - /// Use the `setData` method to update the nft key value store with some data await nft.setData(freNftAddress, publisherAccount, '1', data) } catch (e) { console.error(e) assert.fail('Download failed') } /// ``` + + /// Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. }) /// - it('8.2 Add key-value pair to data NFT', async () => { + it('8.2 get the key-value pair data from the NFT', async () => { /// ```Typescript const nft = new Nft(web3) try { @@ -703,8 +716,9 @@ describe('Marketplace flow tests', async () => { assert.fail('Download failed') } /// ``` + + /// That's it! Note the simplicity. All data was stored and retrieved from on-chain. We don't need Ocean Provider or Ocean Aquarius for these use cases (though the latter can help for fast querying & retrieval). }) /// - /// ``` }) /// /// ## Editing this file From 6ab1d1a58622351f17719a7064f21ace59712940 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Wed, 21 Dec 2022 15:19:48 +0000 Subject: [PATCH 4/8] Updating CodeExamples.md --- CodeExamples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeExamples.md b/CodeExamples.md index afc4f547..82a47a1f 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -704,7 +704,7 @@ Let's start by using the `setData` method to update the nft key value store with Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. - ### 8.2 Add key-value pair to data NFT + ### 8.2 get the key-value pair data from the NFT ```Typescript const nft = new Nft(web3) try { From 0d80190cab9ac9af0f72b2bd77a94ce4aaf5c93f Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 22 Dec 2022 14:07:27 +0000 Subject: [PATCH 5/8] Removing test:guide command --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 7a502980..cf1e8e4e 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "test:unit": "npm run mocha -- 'test/unit/**/*.test.ts'", "test:unit:cover": "nyc --report-dir coverage/unit --exclude 'src/@types/**/*' npm run test:unit", "test:integration": "npm run mocha -- 'test/integration/**/*.test.ts'", - "test:guide": "npm run mocha -- 'test/integration/CodeExamples.test.ts'", "test:integration:cover": "nyc --report-dir coverage/integration --no-clean npm run test:integration", "create:guide": "./scripts/createCodeExamples.sh test/integration/CodeExamples.test.ts", "create:guidec2d": "./scripts/createCodeExamples.sh test/integration/ComputeExamples.test.ts", From 5d3bcde5bd66588f18efdacc7cd1aafe1c158f0e Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 22 Dec 2022 14:09:47 +0000 Subject: [PATCH 6/8] Updating assertion failure messages --- CodeExamples.md | 123 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 31 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index 82a47a1f..4e509182 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -27,7 +27,9 @@ Here are the steps: 7. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser) ## 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 - **Node.js** can be downloaded from here: https://nodejs.org/en/download/ @@ -138,6 +140,7 @@ Now we define the variables which we will need later ``` We also define some constants that we will use: + ```Typescript const FRE_NFT_NAME = 'Datatoken 2' const FRE_NFT_SYMBOL = 'DT2' @@ -145,7 +148,8 @@ We also define some constants that we will use: const DISP_NFT_SYMBOL = 'DT3' ``` - We will need a file to publish, so here we define the file that we intend to publish. +We will need a file to publish, so here we define the file that we intend to publish. + ```Typescript const ASSET_URL: Files = { datatokenAddress: '0x0', @@ -161,6 +165,7 @@ We also define some constants that we will use: ``` 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'], @@ -191,34 +196,42 @@ Next, we define the metadata that will describe our data asset. This is what we ``` 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}`) - + ``` ## 5. Initialize accounts and deploy contracts - ### 5.1 Next, lets get the address of the deployed contracts + +### 5.1 Next, lets get the address of the deployed contracts + ```Typescript addresses = getAddresses() - + ``` - ### 5.2 Initialize accounts +### 5.2 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}`) @@ -256,25 +269,28 @@ Again, lets console log the values so that we can check that they have been save web3.utils.toWei('1000') ) --> - + ``` - ### 5.2 Next, lets get the address of the deployed contracts +### 5.2 Next, lets get the address of the deployed contracts + ```Typescript addresses = getAddresses() - + ``` - ### 5.3 We send some OCEAN to consumer and staker accounts +### 5.3 We send some OCEAN to consumer and staker accounts + ```Typescript transfer(web3, config, publisherAccount, addresses.Ocean, consumerAccount, '100') transfer(web3, config, publisherAccount, addresses.Ocean, stakerAccount, '100') - + ``` ## 6. Publish Data NFT and a Datatoken with a fixed rate exchange - ### 6.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange +### 6.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange + ```Typescript const factory = new NftFactory(addresses.ERC721Factory, web3) @@ -323,21 +339,26 @@ Again, lets console log the values so that we can check that they have been save 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}`) - + ``` - ### 6.2 Set metadata in the fixed rate exchange NFT +### 6.2 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 = @@ -346,7 +367,9 @@ Now we are going to update the ddo and set the did DDO.nftAddress = freNftAddress ``` + Next, let's encrypt the file(s) using provider + ```Typescript ASSET_URL.datatokenAddress = freDatatokenAddress ASSET_URL.nftAddress = freNftAddress @@ -355,7 +378,9 @@ Next, let's encrypt the file(s) using provider DDO.services[0].datatokenAddress = freDatatokenAddress ``` + Now let's console log the DID to check everything is working + ```Typescript console.log(`DID: ${DDO.id}`) @@ -375,20 +400,24 @@ Now let's console log the DID to check everything is working }) ``` - ### 6.3 Marketplace displays fixed rate asset for sale +### 6.3 Marketplace displays fixed rate asset for sale + ```Typescript const fixedRate = new FixedRateExchange(freAddress, web3) const oceanAmount = await ( await fixedRate.calcBaseInGivenDatatokensOut(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`) - + ``` - ### 6.4 Consumer buys a fixed rate asset data asset, and downloads it +### 6.4 Consumer buys a fixed rate asset data asset, and downloads it + ```Typescript const datatoken = new Datatoken(web3) const DATATOKEN_AMOUNT = '10000' @@ -398,7 +427,9 @@ Now that the market has fetched those values it can display the asset on the fro 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, addresses.Ocean, consumerAccount) @@ -407,7 +438,9 @@ Let's do a quick check of the consumer ETH balance before the swap 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 Datatokens + ```Typescript await approve(web3, config, consumerAccount, addresses.Ocean, freAddress, '100') await approve( @@ -421,7 +454,9 @@ Before we call the contract we have to call `approve` so that the contract can m const fixedRate = new FixedRateExchange(freAddress, web3) ``` + Now we can make the contract call + ```Typescript await fixedRate.buyDatatokens(consumerAccount, freId, '1', '2') @@ -434,7 +469,9 @@ Now we can make the contract call assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') ``` + Next, we need to initialize the provider + ```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, @@ -456,7 +493,9 @@ Next, we need to initialize the provider } ``` + Lets now make the payment + ```Typescript const tx = await datatoken.startOrder( freDatatokenAddress, @@ -466,7 +505,9 @@ Lets now make the payment providerFees ) ``` + Now we can get the url + ```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, @@ -479,7 +520,9 @@ Now we can get the url ) ``` + Lets check that the download URL was successfully received + ```Typescript console.log(`Download URL: ${downloadURL}`) @@ -494,12 +537,13 @@ Lets check that the download URL was successfully received } catch (e) { assert.fail('Download failed') } - + ``` ## 7. Publish Data NFT and a Datatoken with a dispenser - ### 7.1 Publish a dataset (create NFT + Datatoken) with a dispenser +### 7.1 Publish a dataset (create NFT + Datatoken) with a dispenser + ```Typescript const factory = new NftFactory(addresses.ERC721Factory, web3) @@ -541,20 +585,25 @@ Lets check that the download URL was successfully received 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}`) - + ``` - ### 7.2 Set metadata in the dispenser NFT +### 7.2 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 = @@ -563,7 +612,9 @@ Lets start by updating the ddo and setting the did DDO.nftAddress = dispenserNftAddress ``` + Now we need to encrypt file(s) using provider + ```Typescript ASSET_URL.datatokenAddress = dispenserDatatokenAddress ASSET_URL.nftAddress = dispenserNftAddress @@ -586,10 +637,11 @@ Now we need to encrypt file(s) using provider encryptedDDO, '0x' + metadataHash ) - + ``` - ### 7.3 Consumer gets a dispenser data asset, and downloads it +### 7.3 Consumer gets a dispenser data asset, and downloads it + ```Typescript const datatoken = new Datatoken(web3) const dispenser = new Dispenser(addresses.Dispenser, web3) @@ -618,7 +670,9 @@ Now we need to encrypt file(s) using provider 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, @@ -639,7 +693,9 @@ At this point we need to encrypt file(s) using provider validUntil: initializeData.providerFee.validUntil } ``` + Now we need to make the payment + ```Typescript const tx = await datatoken.startOrder( dispenserDatatokenAddress, @@ -649,7 +705,9 @@ Now we need to make the payment providerFees ) ``` + Now we can get the download URL + ```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, @@ -661,7 +719,9 @@ Now we can get the download URL web3 ) ``` + Let's check we received the download URL ok + ```Typescript console.log(`Download URL: ${downloadURL}`) @@ -674,10 +734,11 @@ Let's check we received the download URL ok } catch (e) { assert.fail('Download failed') } - + ``` - ### 8.1 Add key-value pair to data NFT +### 8.1 Add key-value pair to data NFT + Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). Let's see how! @@ -690,6 +751,7 @@ Here are the steps: 4. Retrieve value from data NFT (use the `getData` method) Let's start by using the `setData` method to update the nft key value store with some data + ```Typescript const nft = new Nft(web3) const data = 'SomeData' @@ -697,14 +759,14 @@ Let's start by using the `setData` method to update the nft key value store with await nft.setData(freNftAddress, publisherAccount, '1', data) } catch (e) { console.error(e) - assert.fail('Download failed') + assert.fail('Failed to set data in NFT ERC725 key value store', e) } ``` Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. - - ### 8.2 get the key-value pair data from the NFT +### 8.2 get the key-value pair data from the NFT + ```Typescript const nft = new Nft(web3) try { @@ -713,15 +775,14 @@ Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments console.log('Data: ', data) } catch (e) { console.error(e) - assert.fail('Download failed') + assert.fail('Failed to get data from NFT ERC725 key value store', e) } ``` That's it! Note the simplicity. All data was stored and retrieved from on-chain. We don't need Ocean Provider or Ocean Aquarius for these use cases (though the latter can help for fast querying & retrieval). - - ## Editing this file + Please note that CodeExamples.md is an autogenerated file, you should not edit it directly. Updates should be done in `test/integration/CodeExamples.test.ts` and all markdown should have three forward slashes before it e.g. `/// # H1 Title` From 2bb4f751a263c88b9a42ff261f5df83648e1acfa Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 22 Dec 2022 14:17:10 +0000 Subject: [PATCH 7/8] updating assertion messages --- test/integration/CodeExamples.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index c7ab5738..64c73714 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -697,7 +697,7 @@ describe('Marketplace flow tests', async () => { await nft.setData(freNftAddress, publisherAccount, '1', data) } catch (e) { console.error(e) - assert.fail('Download failed') + assert.fail('Failed to set data in NFT ERC725 key value store', e) } /// ``` @@ -713,7 +713,7 @@ describe('Marketplace flow tests', async () => { console.log('Data: ', data) } catch (e) { console.error(e) - assert.fail('Download failed') + assert.fail('Failed to get data from NFT ERC725 key value store', e) } /// ``` From 39ac4a40462938c5f1b1f482eaf05bce2812c360 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Thu, 22 Dec 2022 14:25:01 +0000 Subject: [PATCH 8/8] Combining tests and checking that the data received is correct --- CodeExamples.md | 131 ++++++++------------------ test/integration/CodeExamples.test.ts | 42 +++++---- 2 files changed, 60 insertions(+), 113 deletions(-) diff --git a/CodeExamples.md b/CodeExamples.md index 4e509182..462e57ff 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -27,9 +27,7 @@ Here are the steps: 7. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser) ## 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 - **Node.js** can be downloaded from here: https://nodejs.org/en/download/ @@ -140,7 +138,6 @@ Now we define the variables which we will need later ``` We also define some constants that we will use: - ```Typescript const FRE_NFT_NAME = 'Datatoken 2' const FRE_NFT_SYMBOL = 'DT2' @@ -148,8 +145,7 @@ We also define some constants that we will use: const DISP_NFT_SYMBOL = 'DT3' ``` -We will need a file to publish, so here we define the file that we intend to publish. - + We will need a file to publish, so here we define the file that we intend to publish. ```Typescript const ASSET_URL: Files = { datatokenAddress: '0x0', @@ -165,7 +161,6 @@ We will need a file to publish, so here we define the file that we intend to pub ``` 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'], @@ -196,42 +191,34 @@ Next, we define the metadata that will describe our data asset. This is what we ``` 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}`) - + ``` ## 5. Initialize accounts and deploy contracts - -### 5.1 Next, lets get the address of the deployed contracts - + ### 5.1 Next, lets get the address of the deployed contracts ```Typescript addresses = getAddresses() - + ``` -### 5.2 Initialize accounts - + ### 5.2 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}`) @@ -269,28 +256,25 @@ Again, lets console log the values so that we can check that they have been save web3.utils.toWei('1000') ) --> - + ``` -### 5.2 Next, lets get the address of the deployed contracts - + ### 5.2 Next, lets get the address of the deployed contracts ```Typescript addresses = getAddresses() - + ``` -### 5.3 We send some OCEAN to consumer and staker accounts - + ### 5.3 We send some OCEAN to consumer and staker accounts ```Typescript transfer(web3, config, publisherAccount, addresses.Ocean, consumerAccount, '100') transfer(web3, config, publisherAccount, addresses.Ocean, stakerAccount, '100') - + ``` ## 6. Publish Data NFT and a Datatoken with a fixed rate exchange -### 6.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange - + ### 6.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange ```Typescript const factory = new NftFactory(addresses.ERC721Factory, web3) @@ -339,26 +323,21 @@ Again, lets console log the values so that we can check that they have been save 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}`) - + ``` -### 6.2 Set metadata in the fixed rate exchange NFT - + ### 6.2 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 = @@ -367,9 +346,7 @@ Now we are going to update the ddo and set the did DDO.nftAddress = freNftAddress ``` - Next, let's encrypt the file(s) using provider - ```Typescript ASSET_URL.datatokenAddress = freDatatokenAddress ASSET_URL.nftAddress = freNftAddress @@ -378,9 +355,7 @@ Next, let's encrypt the file(s) using provider DDO.services[0].datatokenAddress = freDatatokenAddress ``` - Now let's console log the DID to check everything is working - ```Typescript console.log(`DID: ${DDO.id}`) @@ -400,24 +375,20 @@ Now let's console log the DID to check everything is working }) ``` -### 6.3 Marketplace displays fixed rate asset for sale - + ### 6.3 Marketplace displays fixed rate asset for sale ```Typescript const fixedRate = new FixedRateExchange(freAddress, web3) const oceanAmount = await ( await fixedRate.calcBaseInGivenDatatokensOut(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`) - + ``` -### 6.4 Consumer buys a fixed rate asset data asset, and downloads it - + ### 6.4 Consumer buys a fixed rate asset data asset, and downloads it ```Typescript const datatoken = new Datatoken(web3) const DATATOKEN_AMOUNT = '10000' @@ -427,9 +398,7 @@ Now that the market has fetched those values it can display the asset on the fro 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, addresses.Ocean, consumerAccount) @@ -438,9 +407,7 @@ Let's do a quick check of the consumer ETH balance before the swap 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 Datatokens - ```Typescript await approve(web3, config, consumerAccount, addresses.Ocean, freAddress, '100') await approve( @@ -454,9 +421,7 @@ Before we call the contract we have to call `approve` so that the contract can m const fixedRate = new FixedRateExchange(freAddress, web3) ``` - Now we can make the contract call - ```Typescript await fixedRate.buyDatatokens(consumerAccount, freId, '1', '2') @@ -469,9 +434,7 @@ Now we can make the contract call assert(resolvedDDO, 'Cannot fetch DDO from Aquarius') ``` - Next, we need to initialize the provider - ```Typescript const initializeData = await ProviderInstance.initialize( resolvedDDO.id, @@ -493,9 +456,7 @@ Next, we need to initialize the provider } ``` - Lets now make the payment - ```Typescript const tx = await datatoken.startOrder( freDatatokenAddress, @@ -505,9 +466,7 @@ Lets now make the payment providerFees ) ``` - Now we can get the url - ```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, @@ -520,9 +479,7 @@ Now we can get the url ) ``` - Lets check that the download URL was successfully received - ```Typescript console.log(`Download URL: ${downloadURL}`) @@ -537,13 +494,12 @@ Lets check that the download URL was successfully received } catch (e) { assert.fail('Download failed') } - + ``` ## 7. Publish Data NFT and a Datatoken with a dispenser -### 7.1 Publish a dataset (create NFT + Datatoken) with a dispenser - + ### 7.1 Publish a dataset (create NFT + Datatoken) with a dispenser ```Typescript const factory = new NftFactory(addresses.ERC721Factory, web3) @@ -585,25 +541,20 @@ Lets check that the download URL was successfully received 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}`) - + ``` -### 7.2 Set metadata in the dispenser NFT - + ### 7.2 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 = @@ -612,9 +563,7 @@ Lets start by updating the ddo and setting the did DDO.nftAddress = dispenserNftAddress ``` - Now we need to encrypt file(s) using provider - ```Typescript ASSET_URL.datatokenAddress = dispenserDatatokenAddress ASSET_URL.nftAddress = dispenserNftAddress @@ -637,11 +586,10 @@ Now we need to encrypt file(s) using provider encryptedDDO, '0x' + metadataHash ) - + ``` -### 7.3 Consumer gets a dispenser data asset, and downloads it - + ### 7.3 Consumer gets a dispenser data asset, and downloads it ```Typescript const datatoken = new Datatoken(web3) const dispenser = new Dispenser(addresses.Dispenser, web3) @@ -670,9 +618,7 @@ Now we need to encrypt file(s) using provider 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, @@ -693,9 +639,7 @@ At this point we need to encrypt file(s) using provider validUntil: initializeData.providerFee.validUntil } ``` - Now we need to make the payment - ```Typescript const tx = await datatoken.startOrder( dispenserDatatokenAddress, @@ -705,9 +649,7 @@ Now we need to make the payment providerFees ) ``` - Now we can get the download URL - ```Typescript const downloadURL = await ProviderInstance.getDownloadUrl( DDO.id, @@ -719,9 +661,7 @@ Now we can get the download URL web3 ) ``` - Let's check we received the download URL ok - ```Typescript console.log(`Download URL: ${downloadURL}`) @@ -734,10 +674,10 @@ Let's check we received the download URL ok } catch (e) { assert.fail('Download failed') } - + ``` -### 8.1 Add key-value pair to data NFT +## 8. Using ERC725 Key-Value Store Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). @@ -750,39 +690,42 @@ Here are the steps: 3. Add key-value pair to data NFT (use the `setData` method) 4. Retrieve value from data NFT (use the `getData` method) + ### 8.1 Add key-value pair to data NFT Let's start by using the `setData` method to update the nft key value store with some data - ```Typescript const nft = new Nft(web3) const data = 'SomeData' try { await nft.setData(freNftAddress, publisherAccount, '1', data) } catch (e) { - console.error(e) assert.fail('Failed to set data in NFT ERC725 key value store', e) } ``` Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. -### 8.2 get the key-value pair data from the NFT +### 8.2 get the key-value pair data from the NFT' + +Use the `getData` method to get the data stored in the nft key value store ```Typescript - const nft = new Nft(web3) try { - Use the `getData` method to get the data stored in the nft key value store - const data = await nft.getData(freNftAddress, '1') - console.log('Data: ', data) + const response = await nft.getData(freNftAddress, '1') + console.log('getData response: ', response) + assert( + response === data, + 'Wrong data received when getting data from NFT ERC725 key value store' + ) } catch (e) { - console.error(e) assert.fail('Failed to get data from NFT ERC725 key value store', e) } ``` That's it! Note the simplicity. All data was stored and retrieved from on-chain. We don't need Ocean Provider or Ocean Aquarius for these use cases (though the latter can help for fast querying & retrieval). + + ## Editing this file - Please note that CodeExamples.md is an autogenerated file, you should not edit it directly. Updates should be done in `test/integration/CodeExamples.test.ts` and all markdown should have three forward slashes before it e.g. `/// # H1 Title` diff --git a/test/integration/CodeExamples.test.ts b/test/integration/CodeExamples.test.ts index 64c73714..59ff4b2a 100644 --- a/test/integration/CodeExamples.test.ts +++ b/test/integration/CodeExamples.test.ts @@ -677,18 +677,20 @@ describe('Marketplace flow tests', async () => { }) /// /// ``` + /// ## 8. Using ERC725 Key-Value Store + + /// Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). + + /// Let's see how! + + /// Here are the steps: + + /// 1. Setup (same as above) + /// 2. Publish data NFT (same as above) + /// 3. Add key-value pair to data NFT (use the `setData` method) + /// 4. Retrieve value from data NFT (use the `getData` method) + it('8.1 Add key-value pair to data NFT', async () => { - /// Data NFTs can store arbitrary key-value pairs on-chain. This opens up their usage for a broad variety of applications, such as comments & ratings, attestations, and privately sharing data (when the value is encrypted). - - /// Let's see how! - - /// Here are the steps: - - /// 1. Setup (same as above) - /// 2. Publish data NFT (same as above) - /// 3. Add key-value pair to data NFT (use the `setData` method) - /// 4. Retrieve value from data NFT (use the `getData` method) - /// Let's start by using the `setData` method to update the nft key value store with some data /// ```Typescript const nft = new Nft(web3) @@ -696,23 +698,25 @@ describe('Marketplace flow tests', async () => { try { await nft.setData(freNftAddress, publisherAccount, '1', data) } catch (e) { - console.error(e) assert.fail('Failed to set data in NFT ERC725 key value store', e) } /// ``` /// Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs. - }) /// - it('8.2 get the key-value pair data from the NFT', async () => { + /// ### 8.2 get the key-value pair data from the NFT' + + /// Use the `getData` method to get the data stored in the nft key value store + /// ```Typescript - const nft = new Nft(web3) try { - /// Use the `getData` method to get the data stored in the nft key value store - const data = await nft.getData(freNftAddress, '1') - console.log('Data: ', data) + const response = await nft.getData(freNftAddress, '1') + console.log('getData response: ', response) + assert( + response === data, + 'Wrong data received when getting data from NFT ERC725 key value store' + ) } catch (e) { - console.error(e) assert.fail('Failed to get data from NFT ERC725 key value store', e) } /// ```