@oceanprotocol/lib 2.7.0-next.2 → 3.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/CodeExamples.md +273 -166
- package/ComputeExamples.md +109 -102
- package/README.md +1 -1
- package/dist/lib.js +1 -1
- package/dist/lib.js.map +1 -1
- package/dist/lib.modern.js +1 -1
- package/dist/lib.modern.js.map +1 -1
- package/dist/lib.module.js +1 -1
- package/dist/lib.module.js.map +1 -1
- package/dist/lib.umd.js +1 -1
- package/dist/lib.umd.js.map +1 -1
- package/dist/src/@types/Contracts.d.ts +26 -0
- package/dist/src/@types/DDO/Metadata.d.ts +2 -2
- package/dist/src/@types/File.d.ts +1 -1
- package/dist/src/@types/ReturnTypes.d.ts +3 -2
- package/dist/src/@types/index.d.ts +1 -0
- package/dist/src/config/Config.d.ts +1 -1
- package/dist/src/config/ConfigHelper.d.ts +6 -0
- package/dist/src/contracts/Datatoken.d.ts +90 -72
- package/dist/src/contracts/Dispenser.d.ts +27 -27
- package/dist/src/contracts/FixedRateExchange.d.ts +57 -60
- package/dist/src/contracts/NFT.d.ts +57 -34
- package/dist/src/contracts/NFTFactory.d.ts +78 -57
- package/dist/src/contracts/Router.d.ts +33 -18
- package/dist/src/contracts/SmartContract.d.ts +35 -12
- package/dist/src/contracts/SmartContractWithAddress.d.ts +7 -8
- package/dist/src/contracts/df/DfRewards.d.ts +6 -7
- package/dist/src/contracts/df/DfStrategyV1.d.ts +3 -5
- package/dist/src/contracts/ve/VeAllocate.d.ts +4 -7
- package/dist/src/contracts/ve/VeFeeDistributor.d.ts +6 -7
- package/dist/src/contracts/ve/VeFeeEstimate.d.ts +2 -2
- package/dist/src/contracts/ve/VeOcean.d.ts +12 -13
- package/dist/src/services/Aquarius.d.ts +3 -4
- package/dist/src/services/Provider.d.ts +124 -76
- package/dist/src/utils/ContractUtils.d.ts +34 -16
- package/dist/src/utils/DatatokenName.d.ts +5 -2
- package/dist/src/utils/DdoHelpers.d.ts +11 -0
- package/dist/src/utils/FetchHelper.d.ts +11 -0
- package/dist/src/utils/General.d.ts +1 -0
- package/dist/src/utils/ProviderErrors.d.ts +1 -0
- package/dist/src/utils/SignatureUtils.d.ts +8 -2
- package/dist/src/utils/TokenUtils.d.ts +43 -43
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/minAbi.d.ts +38 -2
- package/dist/test/config.d.ts +17 -3
- package/dist/test/integration/helpers.d.ts +7 -0
- package/package.json +10 -5
- package/dist/test/TestContractHandler.d.ts +0 -16
- /package/dist/test/integration/{SimplePublishConsumeFlow.test.d.ts → PublishEditConsume.test.d.ts} +0 -0
package/CodeExamples.md
CHANGED
|
@@ -17,14 +17,17 @@ Here are the steps we will be following throughout the article:
|
|
|
17
17
|
|
|
18
18
|
Here are the steps:
|
|
19
19
|
|
|
20
|
-
0. [Prerequisites](
|
|
21
|
-
1. [Initialize services](
|
|
22
|
-
2. [Create a new node.js project](
|
|
23
|
-
3. [Install dependencies](
|
|
24
|
-
4. [
|
|
25
|
-
5. [
|
|
26
|
-
6. [Publish Data NFT and a Datatoken with a fixed rate exchange](
|
|
27
|
-
7. [
|
|
20
|
+
0. [Prerequisites](#0-prerequisites)
|
|
21
|
+
1. [Initialize services](#1-initialize-services)
|
|
22
|
+
2. [Create a new node.js project](#2-create-a-new-nodejs-project)
|
|
23
|
+
3. [Install dependencies](#3-install-dependancies)
|
|
24
|
+
4. [Import dependencies and add variables and constants](#4-import-dependencies-and-add-variables-and-constants)
|
|
25
|
+
5. [Load the configuration, initialize accounts and deploy contracts](#5-load-the-configuration-initialize-accounts-and-deploy-contracts)
|
|
26
|
+
6. [Publish Data NFT and a Datatoken with a fixed rate exchange](#6-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange)
|
|
27
|
+
7. [Consume a fixed rate asset data asset'](#7-consume-a-fixed-rate-asset-data-asset)
|
|
28
|
+
8. [Publish Data NFT and a Datatoken with a dispenser](#8-publish-data-nft-and-a-datatoken-with-a-dispenserr)
|
|
29
|
+
9. [Consume a dispenser data asset](#9-consume-a-dispenser-data-asset)
|
|
30
|
+
10. [Using ERC725 Key-Value Store](#10-using-erc725-key-value-store)
|
|
28
31
|
|
|
29
32
|
## 0. Prerequisites
|
|
30
33
|
Before we start it is important that you have all of the necessary prerequisites installed on your computer.
|
|
@@ -67,7 +70,7 @@ Open the package.json file in a text editor and update the dependancies to inclu
|
|
|
67
70
|
"@oceanprotocol/contracts": "1.0.0-alpha.28",
|
|
68
71
|
"@oceanprotocol/lib": "1.0.0-next.37",
|
|
69
72
|
"crypto-js": "^4.1.1",
|
|
70
|
-
"
|
|
73
|
+
"ethers": "^5.7.2"
|
|
71
74
|
}
|
|
72
75
|
```
|
|
73
76
|
|
|
@@ -84,9 +87,11 @@ Now open the `marketplace.js` file in your text editor.
|
|
|
84
87
|
Start by importing all of the necessary dependencies
|
|
85
88
|
|
|
86
89
|
```Typescript
|
|
90
|
+
import fs from 'fs'
|
|
87
91
|
|
|
88
|
-
import {
|
|
92
|
+
import { ethers, providers, Signer } from 'ethers'
|
|
89
93
|
import { SHA256 } from 'crypto-js'
|
|
94
|
+
import { homedir } from 'os'
|
|
90
95
|
import {
|
|
91
96
|
approve,
|
|
92
97
|
Aquarius,
|
|
@@ -108,10 +113,14 @@ import {
|
|
|
108
113
|
ProviderInstance,
|
|
109
114
|
transfer,
|
|
110
115
|
ZERO_ADDRESS,
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
sendTx,
|
|
117
|
+
ConfigHelper,
|
|
118
|
+
configHelperNetworks,
|
|
119
|
+
amountToUnits,
|
|
120
|
+
ValidateMetadata,
|
|
121
|
+
getEventFromTx,
|
|
122
|
+
DDO
|
|
113
123
|
} from '@oceanprotocol/lib'
|
|
114
|
-
import { getAddresses, getTestConfig, web3 } from '../config'
|
|
115
124
|
```
|
|
116
125
|
|
|
117
126
|
<!--
|
|
@@ -121,12 +130,14 @@ describe('Marketplace flow tests
|
|
|
121
130
|
Now we define the variables which we will need later
|
|
122
131
|
|
|
123
132
|
```Typescript
|
|
133
|
+
let provider: ethers.providers.JsonRpcProvider
|
|
124
134
|
let config: Config
|
|
125
135
|
let aquarius: Aquarius
|
|
136
|
+
let datatoken: Datatoken
|
|
126
137
|
let providerUrl: any
|
|
127
|
-
let publisherAccount:
|
|
128
|
-
let consumerAccount:
|
|
129
|
-
let stakerAccount:
|
|
138
|
+
let publisherAccount: Signer
|
|
139
|
+
let consumerAccount: Signer
|
|
140
|
+
let stakerAccount: Signer
|
|
130
141
|
let addresses: any
|
|
131
142
|
let freNftAddress: string
|
|
132
143
|
let freDatatokenAddress: string
|
|
@@ -135,6 +146,7 @@ Now we define the variables which we will need later
|
|
|
135
146
|
let dispenserNftAddress: string
|
|
136
147
|
let dispenserDatatokenAddress: string
|
|
137
148
|
let dispenserAddress: string
|
|
149
|
+
let fixedDDO
|
|
138
150
|
```
|
|
139
151
|
|
|
140
152
|
We also define some constants that we will use:
|
|
@@ -162,11 +174,11 @@ We also define some constants that we will use:
|
|
|
162
174
|
|
|
163
175
|
Next, we define the metadata that will describe our data asset. This is what we call the DDO
|
|
164
176
|
```Typescript
|
|
165
|
-
const DDO = {
|
|
177
|
+
const genericAsset: DDO = {
|
|
166
178
|
'@context': ['https://w3id.org/did/v1'],
|
|
167
179
|
id: '',
|
|
168
180
|
version: '4.1.0',
|
|
169
|
-
chainId:
|
|
181
|
+
chainId: 4,
|
|
170
182
|
nftAddress: '0x0',
|
|
171
183
|
metadata: {
|
|
172
184
|
created: '2021-12-20T14:35:20Z',
|
|
@@ -175,56 +187,65 @@ Next, we define the metadata that will describe our data asset. This is what we
|
|
|
175
187
|
name: 'dataset-name',
|
|
176
188
|
description: 'Ocean protocol test dataset description',
|
|
177
189
|
author: 'oceanprotocol-team',
|
|
178
|
-
license: 'MIT'
|
|
190
|
+
license: 'MIT',
|
|
191
|
+
tags: ['white-papers'],
|
|
192
|
+
additionalInformation: { 'test-key': 'test-value' },
|
|
193
|
+
links: ['http://data.ceda.ac.uk/badc/ukcp09/']
|
|
179
194
|
},
|
|
180
195
|
services: [
|
|
181
196
|
{
|
|
182
197
|
id: 'testFakeId',
|
|
183
198
|
type: 'access',
|
|
199
|
+
description: 'Download service',
|
|
184
200
|
files: '',
|
|
185
201
|
datatokenAddress: '0x0',
|
|
186
|
-
serviceEndpoint: '
|
|
202
|
+
serviceEndpoint: 'http://172.15.0.4:8030',
|
|
187
203
|
timeout: 0
|
|
188
204
|
}
|
|
189
205
|
]
|
|
190
206
|
}
|
|
191
207
|
```
|
|
192
208
|
|
|
193
|
-
|
|
209
|
+
## 5. Load the configuration, initialize accounts and deploy contracts
|
|
194
210
|
```Typescript
|
|
195
211
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
provider = new providers.JsonRpcProvider(
|
|
213
|
+
process.env.NODE_URI || configHelperNetworks[1].nodeUri
|
|
214
|
+
)
|
|
215
|
+
publisherAccount = (await provider.getSigner(0)) as Signer
|
|
216
|
+
consumerAccount = (await provider.getSigner(1)) as Signer
|
|
217
|
+
stakerAccount = (await provider.getSigner(2)) as Signer
|
|
218
|
+
const config = new ConfigHelper().getConfig(
|
|
219
|
+
parseInt(String((await publisherAccount.provider.getNetwork()).chainId))
|
|
220
|
+
)
|
|
221
|
+
config.providerUri = process.env.PROVIDER_URL || config.providerUri
|
|
222
|
+
aquarius = new Aquarius(config?.metadataCacheUri)
|
|
223
|
+
providerUrl = config?.providerUri
|
|
224
|
+
addresses = JSON.parse(
|
|
225
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
226
|
+
fs.readFileSync(
|
|
227
|
+
process.env.ADDRESS_FILE ||
|
|
228
|
+
`${homedir}/.ocean/ocean-contracts/artifacts/address.json`,
|
|
229
|
+
'utf8'
|
|
230
|
+
)
|
|
231
|
+
).development
|
|
199
232
|
```
|
|
200
233
|
As we go along it's a good idea to console log the values so that you check they are right
|
|
201
234
|
```Typescript
|
|
202
235
|
console.log(`Aquarius URL: ${config.metadataCacheUri}`)
|
|
203
236
|
console.log(`Provider URL: ${providerUrl}`)
|
|
237
|
+
console.log(`Deployed contracts address: ${addresses}`)
|
|
238
|
+
console.log(`Publisher account address: ${await publisherAccount.getAddress()}`)
|
|
239
|
+
console.log(`Consumer account address: ${await consumerAccount.getAddress()}`)
|
|
240
|
+
console.log(`Staker account address: ${await stakerAccount.getAddress()}`)
|
|
204
241
|
|
|
205
242
|
```
|
|
206
243
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
addresses = getAddresses()
|
|
211
|
-
|
|
212
|
-
```
|
|
244
|
+
### 5.1 Mint OCEAN to publisher account
|
|
245
|
+
You can skip this step if you are running your script against a remote network,
|
|
246
|
+
you need to mint oceans to mentioned accounts only if you are using barge to test your script
|
|
213
247
|
|
|
214
|
-
### 5.2 Initialize accounts
|
|
215
248
|
```Typescript
|
|
216
|
-
const accounts = await web3.eth.getAccounts()
|
|
217
|
-
publisherAccount = accounts[0]
|
|
218
|
-
consumerAccount = accounts[1]
|
|
219
|
-
stakerAccount = accounts[2]
|
|
220
|
-
```
|
|
221
|
-
Again, lets console log the values so that we can check that they have been saved properly
|
|
222
|
-
```Typescript
|
|
223
|
-
console.log(`Publisher account address: ${publisherAccount}`)
|
|
224
|
-
console.log(`Consumer account address: ${consumerAccount}`)
|
|
225
|
-
console.log(`Staker account address: ${stakerAccount}`)
|
|
226
|
-
<!--
|
|
227
|
-
// mint ocean to publisherAccount
|
|
228
249
|
const minAbi = [
|
|
229
250
|
{
|
|
230
251
|
constant: false,
|
|
@@ -238,37 +259,40 @@ Again, lets console log the values so that we can check that they have been save
|
|
|
238
259
|
stateMutability: 'nonpayable',
|
|
239
260
|
type: 'function'
|
|
240
261
|
}
|
|
241
|
-
]
|
|
242
|
-
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
web3.utils.toWei('1000')
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
const tokenContract = new ethers.Contract(addresses.Ocean, minAbi, publisherAccount)
|
|
265
|
+
const estGasPublisher = await tokenContract.estimateGas.mint(
|
|
266
|
+
await publisherAccount.getAddress(),
|
|
267
|
+
amountToUnits(null, null, '1000', 18)
|
|
248
268
|
)
|
|
249
269
|
await sendTx(
|
|
270
|
+
estGasPublisher,
|
|
250
271
|
publisherAccount,
|
|
251
|
-
estGas,
|
|
252
|
-
web3,
|
|
253
272
|
1,
|
|
254
|
-
tokenContract.
|
|
255
|
-
publisherAccount,
|
|
256
|
-
|
|
273
|
+
tokenContract.mint,
|
|
274
|
+
await publisherAccount.getAddress(),
|
|
275
|
+
amountToUnits(null, null, '1000', 18)
|
|
257
276
|
)
|
|
258
|
-
-->
|
|
259
|
-
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### 5.2 Next, lets get the address of the deployed contracts
|
|
263
|
-
```Typescript
|
|
264
|
-
addresses = getAddresses()
|
|
265
277
|
|
|
266
278
|
```
|
|
267
279
|
|
|
268
280
|
### 5.3 We send some OCEAN to consumer and staker accounts
|
|
269
281
|
```Typescript
|
|
270
|
-
transfer(
|
|
271
|
-
|
|
282
|
+
transfer(
|
|
283
|
+
publisherAccount,
|
|
284
|
+
config,
|
|
285
|
+
addresses.Ocean,
|
|
286
|
+
await consumerAccount.getAddress(),
|
|
287
|
+
'100'
|
|
288
|
+
)
|
|
289
|
+
transfer(
|
|
290
|
+
publisherAccount,
|
|
291
|
+
config,
|
|
292
|
+
addresses.Ocean,
|
|
293
|
+
await stakerAccount.getAddress(),
|
|
294
|
+
'100'
|
|
295
|
+
)
|
|
272
296
|
|
|
273
297
|
```
|
|
274
298
|
|
|
@@ -276,7 +300,7 @@ Again, lets console log the values so that we can check that they have been save
|
|
|
276
300
|
|
|
277
301
|
### 6.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange
|
|
278
302
|
```Typescript
|
|
279
|
-
const factory = new NftFactory(addresses.ERC721Factory,
|
|
303
|
+
const factory = new NftFactory(addresses.ERC721Factory, publisherAccount)
|
|
280
304
|
|
|
281
305
|
const nftParams: NftCreateData = {
|
|
282
306
|
name: FRE_NFT_NAME,
|
|
@@ -284,7 +308,7 @@ Again, lets console log the values so that we can check that they have been save
|
|
|
284
308
|
templateIndex: 1,
|
|
285
309
|
tokenURI: '',
|
|
286
310
|
transferable: true,
|
|
287
|
-
owner: publisherAccount
|
|
311
|
+
owner: await publisherAccount.getAddress()
|
|
288
312
|
}
|
|
289
313
|
|
|
290
314
|
const datatokenParams: DatatokenCreateParams = {
|
|
@@ -293,15 +317,15 @@ Again, lets console log the values so that we can check that they have been save
|
|
|
293
317
|
feeAmount: '0',
|
|
294
318
|
paymentCollector: ZERO_ADDRESS,
|
|
295
319
|
feeToken: ZERO_ADDRESS,
|
|
296
|
-
minter: publisherAccount,
|
|
320
|
+
minter: await publisherAccount.getAddress(),
|
|
297
321
|
mpFeeAddress: ZERO_ADDRESS
|
|
298
322
|
}
|
|
299
323
|
|
|
300
324
|
const freParams: FreCreationParams = {
|
|
301
325
|
fixedRateAddress: addresses.FixedPrice,
|
|
302
326
|
baseTokenAddress: addresses.Ocean,
|
|
303
|
-
owner: publisherAccount,
|
|
304
|
-
marketFeeCollector: publisherAccount,
|
|
327
|
+
owner: await publisherAccount.getAddress(),
|
|
328
|
+
marketFeeCollector: await publisherAccount.getAddress(),
|
|
305
329
|
baseTokenDecimals: 18,
|
|
306
330
|
datatokenDecimals: 18,
|
|
307
331
|
fixedRate: '1',
|
|
@@ -310,17 +334,22 @@ Again, lets console log the values so that we can check that they have been save
|
|
|
310
334
|
withMint: false
|
|
311
335
|
}
|
|
312
336
|
|
|
313
|
-
const
|
|
314
|
-
publisherAccount,
|
|
337
|
+
const bundleNFT = await factory.createNftWithDatatokenWithFixedRate(
|
|
315
338
|
nftParams,
|
|
316
339
|
datatokenParams,
|
|
317
340
|
freParams
|
|
318
341
|
)
|
|
319
342
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
343
|
+
const trxReceipt = await bundleNFT.wait()
|
|
344
|
+
// events have been emitted
|
|
345
|
+
const nftCreatedEvent = getEventFromTx(trxReceipt, 'NFTCreated')
|
|
346
|
+
const tokenCreatedEvent = getEventFromTx(trxReceipt, 'TokenCreated')
|
|
347
|
+
const newFreEvent = getEventFromTx(trxReceipt, 'NewFixedRate')
|
|
348
|
+
|
|
349
|
+
freNftAddress = nftCreatedEvent.args.newTokenAddress
|
|
350
|
+
freDatatokenAddress = tokenCreatedEvent.args.newTokenAddress
|
|
351
|
+
freAddress = newFreEvent.args.exchangeContract
|
|
352
|
+
freId = newFreEvent.args.exchangeId
|
|
324
353
|
|
|
325
354
|
```
|
|
326
355
|
Now let's console log each of those values to check everything is working
|
|
@@ -334,54 +363,64 @@ Now let's console log each of those values to check everything is working
|
|
|
334
363
|
|
|
335
364
|
### 6.2 Set metadata in the fixed rate exchange NFT
|
|
336
365
|
```Typescript
|
|
337
|
-
const nft = new Nft(
|
|
366
|
+
const nft = new Nft(
|
|
367
|
+
publisherAccount,
|
|
368
|
+
(await publisherAccount.provider.getNetwork()).chainId
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
fixedDDO = { ...genericAsset }
|
|
338
372
|
|
|
339
373
|
```
|
|
340
374
|
Now we are going to update the ddo and set the did
|
|
341
375
|
```Typescript
|
|
342
|
-
|
|
343
|
-
|
|
376
|
+
|
|
377
|
+
fixedDDO.chainId = (await publisherAccount.provider.getNetwork()).chainId
|
|
378
|
+
fixedDDO.id =
|
|
344
379
|
'did:op:' +
|
|
345
|
-
SHA256(
|
|
346
|
-
|
|
380
|
+
SHA256(ethers.utils.getAddress(freNftAddress) + fixedDDO.chainId.toString(10))
|
|
381
|
+
fixedDDO.nftAddress = freNftAddress
|
|
347
382
|
|
|
348
383
|
```
|
|
349
384
|
Next, let's encrypt the file(s) using provider
|
|
350
385
|
```Typescript
|
|
351
386
|
ASSET_URL.datatokenAddress = freDatatokenAddress
|
|
352
387
|
ASSET_URL.nftAddress = freNftAddress
|
|
353
|
-
|
|
388
|
+
fixedDDO.services[0].files = await ProviderInstance.encrypt(
|
|
354
389
|
ASSET_URL,
|
|
355
|
-
|
|
390
|
+
fixedDDO.chainId,
|
|
356
391
|
providerUrl
|
|
357
392
|
)
|
|
358
|
-
|
|
359
|
-
DDO.services[0].datatokenAddress = freDatatokenAddress
|
|
393
|
+
fixedDDO.services[0].datatokenAddress = freDatatokenAddress
|
|
360
394
|
|
|
361
395
|
```
|
|
362
396
|
Now let's console log the DID to check everything is working
|
|
363
397
|
```Typescript
|
|
364
|
-
console.log(`DID: ${
|
|
398
|
+
console.log(`DID: ${fixedDDO.id}`)
|
|
365
399
|
|
|
366
|
-
const providerResponse = await ProviderInstance.encrypt(
|
|
400
|
+
const providerResponse = await ProviderInstance.encrypt(
|
|
401
|
+
fixedDDO,
|
|
402
|
+
fixedDDO.chainId,
|
|
403
|
+
providerUrl
|
|
404
|
+
)
|
|
367
405
|
const encryptedDDO = await providerResponse
|
|
368
|
-
const
|
|
406
|
+
const isAssetValid: ValidateMetadata = await aquarius.validate(fixedDDO)
|
|
407
|
+
assert(isAssetValid.valid === true, 'Published asset is not valid')
|
|
369
408
|
await nft.setMetadata(
|
|
370
409
|
freNftAddress,
|
|
371
|
-
publisherAccount,
|
|
410
|
+
await publisherAccount.getAddress(),
|
|
372
411
|
0,
|
|
373
412
|
providerUrl,
|
|
374
413
|
'',
|
|
375
|
-
|
|
414
|
+
ethers.utils.hexlify(2),
|
|
376
415
|
encryptedDDO,
|
|
377
|
-
|
|
416
|
+
isAssetValid.hash
|
|
378
417
|
)
|
|
379
418
|
})
|
|
380
419
|
```
|
|
381
420
|
|
|
382
421
|
### 6.3 Marketplace displays fixed rate asset for sale
|
|
383
422
|
```Typescript
|
|
384
|
-
const fixedRate = new FixedRateExchange(freAddress,
|
|
423
|
+
const fixedRate = new FixedRateExchange(freAddress, publisherAccount)
|
|
385
424
|
const oceanAmount = await (
|
|
386
425
|
await fixedRate.calcBaseInGivenDatatokensOut(freId, '1')
|
|
387
426
|
).baseTokenAmount
|
|
@@ -392,49 +431,79 @@ Now that the market has fetched those values it can display the asset on the fro
|
|
|
392
431
|
|
|
393
432
|
```
|
|
394
433
|
|
|
395
|
-
|
|
434
|
+
## 7. Consume a fixed rate asset data asset
|
|
435
|
+
|
|
436
|
+
### 7.1 Consumer buys a fixed rate asset data asset, and downloads it
|
|
396
437
|
```Typescript
|
|
397
|
-
|
|
438
|
+
datatoken = new Datatoken(publisherAccount)
|
|
398
439
|
const DATATOKEN_AMOUNT = '10000'
|
|
399
440
|
|
|
400
|
-
await datatoken.mint(
|
|
441
|
+
await datatoken.mint(
|
|
442
|
+
freDatatokenAddress,
|
|
443
|
+
await publisherAccount.getAddress(),
|
|
444
|
+
DATATOKEN_AMOUNT
|
|
445
|
+
)
|
|
401
446
|
|
|
402
|
-
const
|
|
447
|
+
const consumerBalance = await provider.getBalance(await consumerAccount.getAddress())
|
|
448
|
+
const consumerETHBalance = ethers.utils.formatEther(consumerBalance)
|
|
403
449
|
|
|
404
450
|
```
|
|
405
451
|
Let's do a quick check of the consumer ETH balance before the swap
|
|
406
452
|
```Typescript
|
|
407
453
|
console.log(`Consumer ETH balance: ${consumerETHBalance}`)
|
|
408
|
-
let consumerOCEANBalance = await balance(
|
|
454
|
+
let consumerOCEANBalance = await balance(
|
|
455
|
+
consumerAccount,
|
|
456
|
+
addresses.Ocean,
|
|
457
|
+
await consumerAccount.getAddress()
|
|
458
|
+
)
|
|
409
459
|
console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`)
|
|
410
|
-
let consumerDTBalance = await balance(
|
|
460
|
+
let consumerDTBalance = await balance(
|
|
461
|
+
consumerAccount,
|
|
462
|
+
freDatatokenAddress,
|
|
463
|
+
await consumerAccount.getAddress()
|
|
464
|
+
)
|
|
411
465
|
console.log(`Consumer ${FRE_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`)
|
|
412
466
|
|
|
413
467
|
```
|
|
414
468
|
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
|
|
415
469
|
```Typescript
|
|
416
|
-
await approve(web3, config, consumerAccount, addresses.Ocean, freAddress, '100')
|
|
417
470
|
await approve(
|
|
418
|
-
|
|
471
|
+
consumerAccount,
|
|
419
472
|
config,
|
|
473
|
+
await consumerAccount.getAddress(),
|
|
474
|
+
addresses.Ocean,
|
|
475
|
+
freAddress,
|
|
476
|
+
'100'
|
|
477
|
+
)
|
|
478
|
+
await approve(
|
|
420
479
|
publisherAccount,
|
|
480
|
+
config,
|
|
481
|
+
await publisherAccount.getAddress(),
|
|
421
482
|
freDatatokenAddress,
|
|
422
483
|
freAddress,
|
|
423
484
|
DATATOKEN_AMOUNT
|
|
424
485
|
)
|
|
425
486
|
|
|
426
|
-
const fixedRate = new FixedRateExchange(freAddress,
|
|
487
|
+
const fixedRate = new FixedRateExchange(freAddress, consumerAccount)
|
|
427
488
|
```
|
|
428
489
|
Now we can make the contract call
|
|
429
490
|
```Typescript
|
|
430
|
-
await fixedRate.buyDatatokens(
|
|
491
|
+
await fixedRate.buyDatatokens(freId, '1', '2')
|
|
431
492
|
|
|
432
|
-
consumerOCEANBalance = await balance(
|
|
493
|
+
consumerOCEANBalance = await balance(
|
|
494
|
+
consumerAccount,
|
|
495
|
+
addresses.Ocean,
|
|
496
|
+
await consumerAccount.getAddress()
|
|
497
|
+
)
|
|
433
498
|
console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`)
|
|
434
|
-
consumerDTBalance = await balance(
|
|
499
|
+
consumerDTBalance = await balance(
|
|
500
|
+
consumerAccount,
|
|
501
|
+
freDatatokenAddress,
|
|
502
|
+
await consumerAccount.getAddress()
|
|
503
|
+
)
|
|
435
504
|
console.log(`Consumer ${FRE_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`)
|
|
436
505
|
|
|
437
|
-
const resolvedDDO = await aquarius.waitForAqua(
|
|
506
|
+
const resolvedDDO = await aquarius.waitForAqua(fixedDDO.id)
|
|
438
507
|
assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
|
|
439
508
|
|
|
440
509
|
```
|
|
@@ -444,7 +513,7 @@ Next, we need to initialize the provider
|
|
|
444
513
|
resolvedDDO.id,
|
|
445
514
|
resolvedDDO.services[0].id,
|
|
446
515
|
0,
|
|
447
|
-
consumerAccount,
|
|
516
|
+
await consumerAccount.getAddress(),
|
|
448
517
|
providerUrl
|
|
449
518
|
)
|
|
450
519
|
|
|
@@ -459,27 +528,29 @@ Next, we need to initialize the provider
|
|
|
459
528
|
validUntil: initializeData.providerFee.validUntil
|
|
460
529
|
}
|
|
461
530
|
|
|
531
|
+
datatoken = new Datatoken(consumerAccount)
|
|
532
|
+
|
|
462
533
|
```
|
|
463
534
|
Lets now make the payment
|
|
464
535
|
```Typescript
|
|
465
536
|
const tx = await datatoken.startOrder(
|
|
466
537
|
freDatatokenAddress,
|
|
467
|
-
consumerAccount,
|
|
468
|
-
consumerAccount,
|
|
538
|
+
await consumerAccount.getAddress(),
|
|
469
539
|
0,
|
|
470
540
|
providerFees
|
|
471
541
|
)
|
|
542
|
+
const orderTx = await tx.wait()
|
|
543
|
+
const orderStartedTx = getEventFromTx(orderTx, 'OrderStarted')
|
|
472
544
|
```
|
|
473
545
|
Now we can get the url
|
|
474
546
|
```Typescript
|
|
475
547
|
const downloadURL = await ProviderInstance.getDownloadUrl(
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
DDO.services[0].id,
|
|
548
|
+
fixedDDO.id,
|
|
549
|
+
fixedDDO.services[0].id,
|
|
479
550
|
0,
|
|
480
|
-
|
|
551
|
+
orderStartedTx.transactionHash,
|
|
481
552
|
providerUrl,
|
|
482
|
-
|
|
553
|
+
consumerAccount
|
|
483
554
|
)
|
|
484
555
|
|
|
485
556
|
```
|
|
@@ -487,9 +558,17 @@ Lets check that the download URL was successfully received
|
|
|
487
558
|
```Typescript
|
|
488
559
|
console.log(`Download URL: ${downloadURL}`)
|
|
489
560
|
|
|
490
|
-
consumerOCEANBalance = await balance(
|
|
561
|
+
consumerOCEANBalance = await balance(
|
|
562
|
+
consumerAccount,
|
|
563
|
+
addresses.Ocean,
|
|
564
|
+
await consumerAccount.getAddress()
|
|
565
|
+
)
|
|
491
566
|
console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`)
|
|
492
|
-
consumerDTBalance = await balance(
|
|
567
|
+
consumerDTBalance = await balance(
|
|
568
|
+
consumerAccount,
|
|
569
|
+
freDatatokenAddress,
|
|
570
|
+
await consumerAccount.getAddress()
|
|
571
|
+
)
|
|
493
572
|
console.log(`Consumer ${FRE_NFT_SYMBOL} balance after order: ${consumerDTBalance}`)
|
|
494
573
|
|
|
495
574
|
try {
|
|
@@ -501,11 +580,11 @@ Lets check that the download URL was successfully received
|
|
|
501
580
|
|
|
502
581
|
```
|
|
503
582
|
|
|
504
|
-
##
|
|
583
|
+
## 8. Publish Data NFT and a Datatoken with a dispenser
|
|
505
584
|
|
|
506
|
-
###
|
|
585
|
+
### 8.1 Publish a dataset (create NFT + Datatoken) with a dispenser
|
|
507
586
|
```Typescript
|
|
508
|
-
const factory = new NftFactory(addresses.ERC721Factory,
|
|
587
|
+
const factory = new NftFactory(addresses.ERC721Factory, publisherAccount)
|
|
509
588
|
|
|
510
589
|
const nftParams: NftCreateData = {
|
|
511
590
|
name: DISP_NFT_NAME,
|
|
@@ -513,7 +592,7 @@ Lets check that the download URL was successfully received
|
|
|
513
592
|
templateIndex: 1,
|
|
514
593
|
tokenURI: '',
|
|
515
594
|
transferable: true,
|
|
516
|
-
owner: publisherAccount
|
|
595
|
+
owner: await publisherAccount.getAddress()
|
|
517
596
|
}
|
|
518
597
|
|
|
519
598
|
const datatokenParams: DatatokenCreateParams = {
|
|
@@ -522,7 +601,7 @@ Lets check that the download URL was successfully received
|
|
|
522
601
|
feeAmount: '0',
|
|
523
602
|
paymentCollector: ZERO_ADDRESS,
|
|
524
603
|
feeToken: ZERO_ADDRESS,
|
|
525
|
-
minter: publisherAccount,
|
|
604
|
+
minter: await publisherAccount.getAddress(),
|
|
526
605
|
mpFeeAddress: ZERO_ADDRESS
|
|
527
606
|
}
|
|
528
607
|
|
|
@@ -534,16 +613,19 @@ Lets check that the download URL was successfully received
|
|
|
534
613
|
allowedSwapper: ZERO_ADDRESS
|
|
535
614
|
}
|
|
536
615
|
|
|
537
|
-
const
|
|
538
|
-
publisherAccount,
|
|
616
|
+
const bundleNFT = await factory.createNftWithDatatokenWithDispenser(
|
|
539
617
|
nftParams,
|
|
540
618
|
datatokenParams,
|
|
541
619
|
dispenserParams
|
|
542
620
|
)
|
|
621
|
+
const trxReceipt = await bundleNFT.wait()
|
|
622
|
+
const nftCreatedEvent = getEventFromTx(trxReceipt, 'NFTCreated')
|
|
623
|
+
const tokenCreatedEvent = getEventFromTx(trxReceipt, 'TokenCreated')
|
|
624
|
+
const dispenserCreatedEvent = getEventFromTx(trxReceipt, 'DispenserCreated')
|
|
543
625
|
|
|
544
|
-
dispenserNftAddress =
|
|
545
|
-
dispenserDatatokenAddress =
|
|
546
|
-
dispenserAddress =
|
|
626
|
+
dispenserNftAddress = nftCreatedEvent.args.newTokenAddress
|
|
627
|
+
dispenserDatatokenAddress = tokenCreatedEvent.args.newTokenAddress
|
|
628
|
+
dispenserAddress = dispenserCreatedEvent.args.newTokenAddress // double check this
|
|
547
629
|
```
|
|
548
630
|
Lets check that we managed to received all of those values without any problems
|
|
549
631
|
```Typescript
|
|
@@ -553,59 +635,67 @@ Lets check that we managed to received all of those values without any problems
|
|
|
553
635
|
|
|
554
636
|
```
|
|
555
637
|
|
|
556
|
-
###
|
|
638
|
+
### 8.2 Set metadata in the dispenser NFT
|
|
557
639
|
```Typescript
|
|
558
|
-
const nft = new Nft(
|
|
640
|
+
const nft = new Nft(
|
|
641
|
+
publisherAccount,
|
|
642
|
+
(await publisherAccount.provider.getNetwork()).chainId
|
|
643
|
+
)
|
|
559
644
|
|
|
560
645
|
```
|
|
561
646
|
Lets start by updating the ddo and setting the did
|
|
562
647
|
```Typescript
|
|
563
|
-
|
|
564
|
-
DDO.id =
|
|
565
|
-
'did:op:' +
|
|
566
|
-
SHA256(web3.utils.toChecksumAddress(dispenserNftAddress) + DDO.chainId.toString(10))
|
|
567
|
-
DDO.nftAddress = dispenserNftAddress
|
|
648
|
+
fixedDDO.chainId = (await publisherAccount.provider.getNetwork()).chainId
|
|
568
649
|
|
|
650
|
+
fixedDDO.id =
|
|
651
|
+
'did:op:' +
|
|
652
|
+
SHA256(ethers.utils.getAddress(dispenserNftAddress) + fixedDDO.chainId.toString(10))
|
|
653
|
+
fixedDDO.nftAddress = dispenserNftAddress
|
|
569
654
|
```
|
|
570
655
|
Now we need to encrypt file(s) using provider
|
|
571
656
|
```Typescript
|
|
572
657
|
ASSET_URL.datatokenAddress = dispenserDatatokenAddress
|
|
573
658
|
ASSET_URL.nftAddress = dispenserNftAddress
|
|
574
|
-
|
|
659
|
+
fixedDDO.services[0].files = await ProviderInstance.encrypt(
|
|
575
660
|
ASSET_URL,
|
|
576
|
-
|
|
661
|
+
fixedDDO.chainId,
|
|
577
662
|
providerUrl
|
|
578
663
|
)
|
|
579
|
-
|
|
580
|
-
DDO.services[0].datatokenAddress = dispenserDatatokenAddress
|
|
664
|
+
fixedDDO.services[0].datatokenAddress = dispenserDatatokenAddress
|
|
581
665
|
|
|
582
|
-
console.log(`DID: ${
|
|
666
|
+
console.log(`DID: ${fixedDDO.id}`)
|
|
583
667
|
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
668
|
+
const encryptedDDO = await ProviderInstance.encrypt(
|
|
669
|
+
fixedDDO,
|
|
670
|
+
fixedDDO.chainId,
|
|
671
|
+
providerUrl
|
|
672
|
+
)
|
|
673
|
+
const isAssetValid: ValidateMetadata = await aquarius.validate(fixedDDO)
|
|
674
|
+
assert(isAssetValid.valid === true, 'Published asset is not valid')
|
|
587
675
|
await nft.setMetadata(
|
|
588
676
|
dispenserNftAddress,
|
|
589
|
-
publisherAccount,
|
|
677
|
+
await publisherAccount.getAddress(),
|
|
590
678
|
0,
|
|
591
679
|
providerUrl,
|
|
592
680
|
'',
|
|
593
|
-
|
|
681
|
+
ethers.utils.hexlify(2),
|
|
594
682
|
encryptedDDO,
|
|
595
|
-
|
|
683
|
+
isAssetValid.hash
|
|
596
684
|
)
|
|
597
685
|
|
|
598
686
|
```
|
|
599
687
|
|
|
600
|
-
|
|
688
|
+
## 9. Consume a dispenser data asset
|
|
689
|
+
|
|
690
|
+
### 9.1 Consumer gets a dispenser data asset, and downloads it
|
|
601
691
|
```Typescript
|
|
602
|
-
|
|
603
|
-
const dispenser = new Dispenser(addresses.Dispenser,
|
|
692
|
+
datatoken = new Datatoken(publisherAccount)
|
|
693
|
+
const dispenser = new Dispenser(addresses.Dispenser, consumerAccount)
|
|
604
694
|
|
|
605
695
|
let consumerDTBalance = await balance(
|
|
606
|
-
|
|
696
|
+
consumerAccount,
|
|
607
697
|
dispenserDatatokenAddress,
|
|
608
|
-
consumerAccount
|
|
698
|
+
await consumerAccount.getAddress()
|
|
609
699
|
)
|
|
610
700
|
console.log(
|
|
611
701
|
`Consumer ${DISP_NFT_SYMBOL} balance before dispense: ${consumerDTBalance}`
|
|
@@ -613,18 +703,24 @@ Now we need to encrypt file(s) using provider
|
|
|
613
703
|
|
|
614
704
|
await dispenser.dispense(
|
|
615
705
|
dispenserDatatokenAddress,
|
|
616
|
-
consumerAccount,
|
|
617
706
|
'1',
|
|
618
|
-
consumerAccount
|
|
707
|
+
await consumerAccount.getAddress()
|
|
619
708
|
)
|
|
620
709
|
|
|
621
|
-
consumerDTBalance = await balance(
|
|
710
|
+
consumerDTBalance = await balance(
|
|
711
|
+
consumerAccount,
|
|
712
|
+
dispenserDatatokenAddress,
|
|
713
|
+
await consumerAccount.getAddress()
|
|
714
|
+
)
|
|
622
715
|
console.log(
|
|
623
716
|
`Consumer ${DISP_NFT_SYMBOL} balance after dispense: ${consumerDTBalance}`
|
|
624
717
|
)
|
|
625
718
|
|
|
626
|
-
const resolvedDDO = await aquarius.waitForAqua(
|
|
719
|
+
const resolvedDDO = await aquarius.waitForAqua(fixedDDO.id)
|
|
627
720
|
assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
|
|
721
|
+
|
|
722
|
+
datatoken = new Datatoken(consumerAccount)
|
|
723
|
+
|
|
628
724
|
```
|
|
629
725
|
At this point we need to encrypt file(s) using provider
|
|
630
726
|
```Typescript
|
|
@@ -632,7 +728,7 @@ At this point we need to encrypt file(s) using provider
|
|
|
632
728
|
resolvedDDO.id,
|
|
633
729
|
resolvedDDO.services[0].id,
|
|
634
730
|
0,
|
|
635
|
-
consumerAccount,
|
|
731
|
+
await consumerAccount.getAddress(),
|
|
636
732
|
providerUrl
|
|
637
733
|
)
|
|
638
734
|
|
|
@@ -651,29 +747,33 @@ Now we need to make the payment
|
|
|
651
747
|
```Typescript
|
|
652
748
|
const tx = await datatoken.startOrder(
|
|
653
749
|
dispenserDatatokenAddress,
|
|
654
|
-
consumerAccount,
|
|
655
|
-
consumerAccount,
|
|
750
|
+
await consumerAccount.getAddress(),
|
|
656
751
|
0,
|
|
657
752
|
providerFees
|
|
658
753
|
)
|
|
754
|
+
const orderTx = await tx.wait()
|
|
755
|
+
const orderStartedTx = getEventFromTx(orderTx, 'OrderStarted')
|
|
659
756
|
```
|
|
660
757
|
Now we can get the download URL
|
|
661
758
|
```Typescript
|
|
662
759
|
const downloadURL = await ProviderInstance.getDownloadUrl(
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
DDO.services[0].id,
|
|
760
|
+
fixedDDO.id,
|
|
761
|
+
fixedDDO.services[0].id,
|
|
666
762
|
0,
|
|
667
|
-
|
|
763
|
+
orderStartedTx.transactionHash,
|
|
668
764
|
providerUrl,
|
|
669
|
-
|
|
765
|
+
consumerAccount
|
|
670
766
|
)
|
|
671
767
|
```
|
|
672
768
|
Let's check we received the download URL ok
|
|
673
769
|
```Typescript
|
|
674
770
|
console.log(`Download URL: ${downloadURL}`)
|
|
675
771
|
|
|
676
|
-
consumerDTBalance = await balance(
|
|
772
|
+
consumerDTBalance = await balance(
|
|
773
|
+
consumerAccount,
|
|
774
|
+
dispenserDatatokenAddress,
|
|
775
|
+
await consumerAccount.getAddress()
|
|
776
|
+
)
|
|
677
777
|
console.log(`Consumer ${DISP_NFT_SYMBOL} balance after order: ${consumerDTBalance}`)
|
|
678
778
|
|
|
679
779
|
try {
|
|
@@ -685,7 +785,7 @@ Let's check we received the download URL ok
|
|
|
685
785
|
|
|
686
786
|
```
|
|
687
787
|
|
|
688
|
-
##
|
|
788
|
+
## 10. Using ERC725 Key-Value Store
|
|
689
789
|
|
|
690
790
|
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).
|
|
691
791
|
|
|
@@ -698,33 +798,40 @@ Here are the steps:
|
|
|
698
798
|
3. Add key-value pair to data NFT (use the `setData` method)
|
|
699
799
|
4. Retrieve value from data NFT (use the `getData` method)
|
|
700
800
|
|
|
701
|
-
###
|
|
801
|
+
### 10.1 Add key-value pair to data NFT
|
|
702
802
|
Let's start by using the `setData` method to update the nft key value store with some data
|
|
703
803
|
```Typescript
|
|
704
|
-
const nft = new Nft(
|
|
804
|
+
const nft = new Nft(publisherAccount)
|
|
705
805
|
const data = 'SomeData'
|
|
706
806
|
try {
|
|
707
|
-
await nft.setData(
|
|
807
|
+
await nft.setData(
|
|
808
|
+
freNftAddress,
|
|
809
|
+
await publisherAccount.getAddress(),
|
|
810
|
+
'0x1234',
|
|
811
|
+
data
|
|
812
|
+
)
|
|
708
813
|
} catch (e) {
|
|
814
|
+
console.log('e = ', e)
|
|
709
815
|
assert.fail('Failed to set data in NFT ERC725 key value store', e)
|
|
710
816
|
}
|
|
711
817
|
```
|
|
712
818
|
|
|
713
819
|
Under the hood, this uses [ERC725](https://erc725alliance.org/), which augments ERC721 with a well-defined way to set and get key-value pairs.
|
|
714
820
|
|
|
715
|
-
###
|
|
821
|
+
### 10.2 get the key-value pair data from the NFT'
|
|
716
822
|
|
|
717
823
|
Use the `getData` method to get the data stored in the nft key value store
|
|
718
824
|
|
|
719
825
|
```Typescript
|
|
720
826
|
try {
|
|
721
|
-
const response = await nft.getData(freNftAddress, '
|
|
827
|
+
const response = await nft.getData(freNftAddress, '0x1234')
|
|
722
828
|
console.log('getData response: ', response)
|
|
723
829
|
assert(
|
|
724
830
|
response === data,
|
|
725
831
|
'Wrong data received when getting data from NFT ERC725 key value store'
|
|
726
832
|
)
|
|
727
833
|
} catch (e) {
|
|
834
|
+
console.log('e = ', e)
|
|
728
835
|
assert.fail('Failed to get data from NFT ERC725 key value store', e)
|
|
729
836
|
}
|
|
730
837
|
```
|