@oceanprotocol/lib 1.0.0-next.9 → 1.1.1

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +408 -1
  2. package/CodeExamples.md +929 -0
  3. package/README.md +12 -80
  4. package/dist/lib.js +1 -1
  5. package/dist/lib.js.map +1 -1
  6. package/dist/lib.modern.js +1 -1
  7. package/dist/lib.modern.js.map +1 -1
  8. package/dist/lib.module.js +1 -1
  9. package/dist/lib.module.js.map +1 -1
  10. package/dist/lib.umd.js +1 -1
  11. package/dist/lib.umd.js.map +1 -1
  12. package/dist/src/@types/Asset.d.ts +83 -0
  13. package/dist/src/@types/Compute.d.ts +18 -1
  14. package/dist/src/@types/DDO/DDO.d.ts +43 -0
  15. package/dist/src/@types/DDO/Event.d.ts +20 -0
  16. package/dist/src/@types/DDO/Metadata.d.ts +92 -0
  17. package/dist/src/@types/DDO/Service.d.ts +72 -6
  18. package/dist/src/{interfaces/DispenserInterface.d.ts → @types/Dispenser.d.ts} +0 -0
  19. package/dist/src/@types/Erc20.d.ts +21 -0
  20. package/dist/src/{interfaces/Erc721Interface.d.ts → @types/Erc721.d.ts} +2 -2
  21. package/dist/src/@types/File.d.ts +23 -0
  22. package/dist/src/@types/FileInfo.d.ts +38 -0
  23. package/dist/src/{interfaces/FixedRateInterface.d.ts → @types/FixedPrice.d.ts} +7 -1
  24. package/dist/src/{interfaces/PoolInterface.d.ts → @types/Pool.d.ts} +11 -2
  25. package/dist/src/@types/Provider.d.ts +9 -0
  26. package/dist/src/@types/Router.d.ts +59 -0
  27. package/dist/src/@types/index.d.ts +8 -1
  28. package/dist/src/aquarius/Aquarius.d.ts +23 -1
  29. package/dist/src/factories/NFTFactory.d.ts +222 -14
  30. package/dist/src/index.d.ts +1 -1
  31. package/dist/src/models/Config.d.ts +128 -0
  32. package/dist/src/pools/Router.d.ts +189 -8
  33. package/dist/src/pools/balancer/Pool.d.ts +354 -29
  34. package/dist/src/pools/dispenser/Dispenser.d.ts +109 -2
  35. package/dist/src/pools/fixedRate/FixedRateExchange.d.ts +309 -17
  36. package/dist/src/pools/index.d.ts +2 -0
  37. package/dist/src/pools/ssContracts/SideStaking.d.ts +110 -7
  38. package/dist/src/provider/Provider.d.ts +127 -8
  39. package/dist/src/tokens/Datatoken.d.ts +347 -8
  40. package/dist/src/tokens/NFT.d.ts +297 -5
  41. package/dist/src/utils/ContractUtils.d.ts +13 -4
  42. package/dist/src/utils/DatatokenName.d.ts +4 -0
  43. package/dist/src/utils/General.d.ts +4 -0
  44. package/dist/src/utils/PoolHelpers.d.ts +8 -0
  45. package/dist/src/utils/SignatureUtils.d.ts +0 -2
  46. package/dist/src/utils/TokenUtils.d.ts +82 -3
  47. package/dist/src/utils/index.d.ts +2 -0
  48. package/dist/test/TestContractHandler.d.ts +8 -36
  49. package/dist/test/config.d.ts +5 -0
  50. package/dist/test/{unit/NftFactory.test.d.ts → integration/CodeExamples.test.d.ts} +0 -0
  51. package/dist/test/unit/factories/NftFactory.test.d.ts +1 -0
  52. package/package.json +42 -37
  53. package/dist/src/@types/FileMetadata.d.ts +0 -9
  54. package/dist/src/interfaces/Erc20Interface.d.ts +0 -11
  55. package/dist/src/interfaces/RouterInterface.d.ts +0 -12
  56. package/dist/src/interfaces/index.d.ts +0 -5
  57. package/dist/test/integration/config.d.ts +0 -3
  58. package/dist/test/unit/config.d.ts +0 -3
  59. package/docs/beginners_guide.md +0 -338
  60. package/docs/get-test-OCEAN.md +0 -24
  61. package/docs/overview.md +0 -394
  62. package/docs/quickstart_marketplace.md +0 -423
  63. package/docs/quickstart_simple.md +0 -272
  64. package/docs/services.md +0 -94
  65. package/docs/wallets.md +0 -98
@@ -0,0 +1,929 @@
1
+ # Ocean.js Code Examples
2
+
3
+ ## Introduction
4
+
5
+ The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along.
6
+ The process involves creating a Data NFT (which represents the base-IP on-chain) and a datatoken (which will be used to purchase the dataset). This guide provides all the code you need and no prior knowledge is required. It is helpful if you have some experience with javascript but it is not necessary.
7
+
8
+ Selling your data over the blockchain puts you in charge of how it is used and can be a great source of passive income. There are many AI startups that have deep expertise in machine learning but need more data to improve their models. Selling your data via the blockchain gives you a level of security that you would be unable to achieve if you were selling via a centralised marketplace.
9
+
10
+ In this guide we'll be making use of the Ocean.js library. Ocean Protocol provides you with everything you need to quickly get setup and start selling data over the blockchain.
11
+
12
+ These examples take you through a typical user journey that focuses on the experience of a publisher, and a buyer / consumer.
13
+
14
+ If you have any questions or issues at any point while following along to this article please reach out to us on [discord](https://discord.gg/TnXjkR5).
15
+
16
+ Here are the steps we will be following throughout the article:
17
+
18
+ Here are the steps:
19
+
20
+ 0. [Prerequisites](#-Prerequisites)
21
+ 1. [Initialize services](#-initialize-services)
22
+ 2. [Create a new node.js project](#-create-a-new-node.js-project)
23
+ 3. [Install dependencies](#-install-dependencies)
24
+ 4. [Initialize accounts and deploy contracts](#-initialize-accounts-and-deploy-contracts)
25
+ 5. [Import dependencies and add variables and constants](#-import-dependencies-and-add-variables-and-constants)
26
+ 6. [Publish Data NFT and a Datatoken with a liquidity pool](#-Publish-data-nft-and-a-datatoken-with-a-liquidity-pool)
27
+ 7. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange)
28
+ 8. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser)
29
+
30
+ ## 0. Prerequisites
31
+ Before we start it is important that you have all of the necessary prerequisites installed on your computer.
32
+ - **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.
33
+ - **Git**. Instructions for installing Git can be found here: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
34
+ - **Node.js** can be downloaded from here: https://nodejs.org/en/download/
35
+ - **Docker** can be installed from here: https://docs.docker.com/get-docker/. Please note that Docker must run as a non-root user, you can set this up by following these instructions: https://docs.docker.com/engine/install/linux-postinstall/
36
+
37
+ ## 1. Initialize services
38
+
39
+ Ocean.js uses off-chain services for metadata (Aquarius) and consuming datasets (Provider).
40
+
41
+ We start by initializing the services. To do this, we clone the Barge repository and run it. This will run the current default versions of [Aquarius](https://github.com/oceanprotocol/aquarius), [Provider](https://github.com/oceanprotocol/provider), and [Ganache](https://github.com/trufflesuite/ganache) with [our contracts](https://github.com/oceanprotocol/contracts) deployed to it.
42
+
43
+ ```bash
44
+ git clone https://github.com/oceanprotocol/barge.git
45
+ cd barge/
46
+ ./start_ocean.sh --with-provider2 --no-dashboard
47
+ ```
48
+
49
+ ## 2. Create a new node.js project
50
+
51
+ Start by creating a new Node.js project. Open a new terminal and enter the following commands:
52
+
53
+ ```bash
54
+ mkdir marketplace-quickstart
55
+ cd marketplace-quickstart
56
+ npm init
57
+ # Answer the questions in the command line prompt
58
+ cat > marketplace.js
59
+ # On linux press CTRL + D to save
60
+ ```
61
+
62
+ ## 3. Install dependancies
63
+
64
+ Open the package.json file in a text editor and update the dependancies to include the following:
65
+
66
+ ```JSON
67
+ "dependencies": {
68
+ "@oceanprotocol/contracts": "1.0.0-alpha.28",
69
+ "@oceanprotocol/lib": "1.0.0-next.37",
70
+ "crypto-js": "^4.1.1",
71
+ "web3": "^1.7.3"
72
+ }
73
+ ```
74
+
75
+ Now in your terminal run the following command:
76
+
77
+ ```bash
78
+ npm install
79
+ ```
80
+
81
+ ## 4. Import dependencies and add variables and constants
82
+
83
+ Now open the `marketplace.js` file in your text editor.
84
+
85
+ Start by importing all of the necessary dependencies
86
+
87
+ ```Typescript
88
+
89
+ import { SHA256 } from 'crypto-js'
90
+ import {
91
+ AmountsOutMaxFee,
92
+ approve,
93
+ Aquarius,
94
+ balance,
95
+ Config,
96
+ Datatoken,
97
+ Dispenser,
98
+ DispenserCreationParams,
99
+ downloadFile,
100
+ Erc20CreateParams,
101
+ Files,
102
+ FixedRateExchange,
103
+ FreCreationParams,
104
+ getHash,
105
+ Nft,
106
+ NftCreateData,
107
+ NftFactory,
108
+ Pool,
109
+ PoolCreationParams,
110
+ ProviderFees,
111
+ ProviderInstance,
112
+ TokenInOutMarket,
113
+ transfer,
114
+ ZERO_ADDRESS
115
+ } from '../../src'
116
+ import { getAddresses, getTestConfig, web3 } from '../config'
117
+ ```
118
+
119
+ <!--
120
+ describe('Marketplace flow tests
121
+ -->
122
+
123
+ Now we define the variables which we will need later
124
+
125
+ ```Typescript
126
+ let config: Config
127
+ let aquarius: Aquarius
128
+ let providerUrl: any
129
+ let publisherAccount: string
130
+ let consumerAccount: string
131
+ let stakerAccount: string
132
+ let addresses: any
133
+ let poolNftAddress: string
134
+ let poolDatatokenAddress: string
135
+ let poolAddress: string
136
+ let freNftAddress: string
137
+ let freDatatokenAddress: string
138
+ let freAddress: string
139
+ let freId: string
140
+ let dispenserNftAddress: string
141
+ let dispenserDatatokenAddress: string
142
+ let dispenserAddress: string
143
+ ```
144
+
145
+ We also define some constants that we will use:
146
+ ```Typescript
147
+ const POOL_NFT_NAME = 'Datatoken 1'
148
+ const POOL_NFT_SYMBOL = 'DT1'
149
+ const FRE_NFT_NAME = 'Datatoken 2'
150
+ const FRE_NFT_SYMBOL = 'DT2'
151
+ const DISP_NFT_NAME = 'Datatoken 3'
152
+ const DISP_NFT_SYMBOL = 'DT3'
153
+ ```
154
+
155
+ We will need a file to publish, so here we define the file that we intend to publish.
156
+ ```Typescript
157
+ const ASSET_URL: Files = {
158
+ datatokenAddress: '0x0',
159
+ nftAddress: '0x0',
160
+ files: [
161
+ {
162
+ type: 'url',
163
+ url: 'https://raw.githubusercontent.com/oceanprotocol/testdatasets/main/shs_dataset_test.txt',
164
+ method: 'GET'
165
+ }
166
+ ]
167
+ }
168
+ ```
169
+
170
+ Next, we define the metadata that will describe our data asset. This is what we call the DDO
171
+ ```Typescript
172
+ const DDO = {
173
+ '@context': ['https://w3id.org/did/v1'],
174
+ id: '',
175
+ version: '4.1.0',
176
+ chainId: 4,
177
+ nftAddress: '0x0',
178
+ metadata: {
179
+ created: '2021-12-20T14:35:20Z',
180
+ updated: '2021-12-20T14:35:20Z',
181
+ type: 'dataset',
182
+ name: 'dataset-name',
183
+ description: 'Ocean protocol test dataset description',
184
+ author: 'oceanprotocol-team',
185
+ license: 'MIT'
186
+ },
187
+ services: [
188
+ {
189
+ id: 'testFakeId',
190
+ type: 'access',
191
+ files: '',
192
+ datatokenAddress: '0x0',
193
+ serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com',
194
+ timeout: 0
195
+ }
196
+ ]
197
+ }
198
+ ```
199
+
200
+ We load the configuration:
201
+ ```Typescript
202
+
203
+ config = await getTestConfig(web3)
204
+ aquarius = new Aquarius(config.metadataCacheUri)
205
+ providerUrl = config.providerUri
206
+ ```
207
+ As we go along it's a good idea to console log the values so that you check they are right
208
+ ```Typescript
209
+ console.log(`Aquarius URL: ${config.metadataCacheUri}`)
210
+ console.log(`Provider URL: ${providerUrl}`)
211
+
212
+ ```
213
+
214
+ ## 5. Initialize accounts and deploy contracts
215
+ ### 5.1 Initialize accounts
216
+ ```Typescript
217
+ const accounts = await web3.eth.getAccounts()
218
+ publisherAccount = accounts[0]
219
+ consumerAccount = accounts[1]
220
+ stakerAccount = accounts[2]
221
+ ```
222
+ Again, lets console log the values so that we can check that they have been saved properly
223
+ ```Typescript
224
+ console.log(`Publisher account address: ${publisherAccount}`)
225
+ console.log(`Consumer account address: ${consumerAccount}`)
226
+ console.log(`Staker account address: ${stakerAccount}`)
227
+
228
+ ```
229
+
230
+ ### 5.2 Next, lets get the address of the deployed contracts
231
+ ```Typescript
232
+ addresses = getAddresses()
233
+
234
+ ```
235
+
236
+ ### 5.3 We send some OCEAN to consumer and staker accounts
237
+ ```Typescript
238
+ transfer(web3, publisherAccount, addresses.Ocean, consumerAccount, '100')
239
+ transfer(web3, publisherAccount, addresses.Ocean, stakerAccount, '100')
240
+
241
+ ```
242
+
243
+ ## 6. Publish Data NFT and a Datatoken with a liquidity pool
244
+
245
+ For pool creation, the OCEAN token is used as the base token. The base token can be changed into something else, such as USDC, DAI etc., but it will require an extra fee.
246
+
247
+ ### 6.1 Publish a dataset (create NFT + Datatoken) with a liquidity pool
248
+ ```Typescript
249
+ const factory = new NftFactory(addresses.ERC721Factory, web3)
250
+
251
+ const nftParams: NftCreateData = {
252
+ name: POOL_NFT_NAME,
253
+ symbol: POOL_NFT_SYMBOL,
254
+ templateIndex: 1,
255
+ tokenURI: '',
256
+ transferable: true,
257
+ owner: publisherAccount
258
+ }
259
+
260
+ const erc20Params: Erc20CreateParams = {
261
+ templateIndex: 1,
262
+ cap: '100000',
263
+ feeAmount: '0',
264
+ paymentCollector: ZERO_ADDRESS,
265
+ feeToken: ZERO_ADDRESS,
266
+ minter: publisherAccount,
267
+ mpFeeAddress: ZERO_ADDRESS
268
+ }
269
+
270
+ const poolParams: PoolCreationParams = {
271
+ ssContract: addresses.Staking,
272
+ baseTokenAddress: addresses.Ocean,
273
+ baseTokenSender: addresses.ERC721Factory,
274
+ publisherAddress: publisherAccount,
275
+ marketFeeCollector: publisherAccount,
276
+ poolTemplateAddress: addresses.poolTemplate,
277
+ rate: '1',
278
+ baseTokenDecimals: 18,
279
+ vestingAmount: '10000',
280
+ vestedBlocks: 2500000,
281
+ initialBaseTokenLiquidity: '2000',
282
+ swapFeeLiquidityProvider: '0.001',
283
+ swapFeeMarketRunner: '0.001'
284
+ }
285
+ ```
286
+ Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens
287
+ ```Typescript
288
+ await approve(
289
+ web3,
290
+ publisherAccount,
291
+ addresses.Ocean,
292
+ addresses.ERC721Factory,
293
+ poolParams.vestingAmount
294
+ )
295
+
296
+ ```
297
+ Now we can make the contract call
298
+ ```Typescript
299
+ const tx = await factory.createNftErc20WithPool(
300
+ publisherAccount,
301
+ nftParams,
302
+ erc20Params,
303
+ poolParams
304
+ )
305
+
306
+ poolNftAddress = tx.events.NFTCreated.returnValues[0]
307
+ poolDatatokenAddress = tx.events.TokenCreated.returnValues[0]
308
+ poolAddress = tx.events.NewPool.returnValues[0]
309
+ ```
310
+ Now, we did quite a few things there. Let's check that we successfully published a dataset (create NFT + Datatoken) with a liquidity pool
311
+ ```Typescript
312
+ console.log(`Pool NFT address: ${poolNftAddress}`)
313
+ console.log(`Pool Datatoken address: ${poolDatatokenAddress}`)
314
+ console.log(`Pool address: ${poolAddress}`)
315
+
316
+ ```
317
+
318
+ ### 6.2 Set metadata in the pool NFT
319
+ ```Typescript
320
+ const nft = new Nft(web3)
321
+ ```
322
+ Now we update the ddo and set the right did
323
+ ```Typescript
324
+ DDO.chainId = await web3.eth.getChainId()
325
+ DDO.id =
326
+ 'did:op:' +
327
+ SHA256(web3.utils.toChecksumAddress(poolNftAddress) + DDO.chainId.toString(10))
328
+ DDO.nftAddress = poolNftAddress
329
+ ```
330
+ Next we encrypt the file or files using Ocean Provider. The provider is an off chain proxy built specifically for this task
331
+ ```Typescript
332
+ ASSET_URL.datatokenAddress = poolDatatokenAddress
333
+ ASSET_URL.nftAddress = poolNftAddress
334
+ const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl)
335
+ DDO.services[0].files = await encryptedFiles
336
+ DDO.services[0].datatokenAddress = poolDatatokenAddress
337
+ ```
338
+ Now let's console log the result to check everything is working
339
+ ```Typescript
340
+ console.log(`DID: ${DDO.id}`)
341
+
342
+ const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl)
343
+ const encryptedDDO = await providerResponse
344
+ const metadataHash = getHash(JSON.stringify(DDO))
345
+ await nft.setMetadata(
346
+ poolNftAddress,
347
+ publisherAccount,
348
+ 0,
349
+ providerUrl,
350
+ '',
351
+ '0x2',
352
+ encryptedDDO,
353
+ '0x' + metadataHash
354
+ )
355
+
356
+ ```
357
+
358
+ ### 6.3 User should add liquidity to the pool, receiving LP tokens
359
+ ```Typescript
360
+ const pool = new Pool(web3)
361
+
362
+ ```
363
+ Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens
364
+ ```Typescript
365
+ await approve(web3, stakerAccount, addresses.Ocean, poolAddress, '5', true)
366
+
367
+ ```
368
+ Now we can make the contract call
369
+ ```Typescript
370
+ await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1')
371
+
372
+ ```
373
+
374
+ ### 6.4 Marketplace displays pool asset for sale
375
+ ```Typescript
376
+ const pool = new Pool(web3)
377
+ const prices = await pool.getAmountInExactOut(
378
+ poolAddress,
379
+ poolDatatokenAddress,
380
+ addresses.Ocean,
381
+ '1',
382
+ '0.01'
383
+ )
384
+ ```
385
+ Now let's console log the result to check everything is working
386
+ ```Typescript
387
+ console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`)
388
+
389
+ ```
390
+
391
+ ### 6.5 Consumer buys a pool data asset, and downloads it
392
+ ```Typescript
393
+ const datatoken = new Datatoken(web3)
394
+
395
+ const consumerETHBalance = await web3.eth.getBalance(consumerAccount)
396
+ ```
397
+ Now let's console log the result to check everything is working
398
+ ```Typescript
399
+ console.log(`Consumer ETH balance: ${consumerETHBalance}`)
400
+ let consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
401
+ ```
402
+ Now let's console log consumerOCEANBalance to check everything is working
403
+ ```Typescript
404
+ console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`)
405
+ let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
406
+ ```
407
+ Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything is working
408
+ ```Typescript
409
+ console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`)
410
+
411
+ ```
412
+ Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens
413
+ ```Typescript
414
+ await approve(web3, consumerAccount, addresses.Ocean, poolAddress, '100')
415
+
416
+ const pool = new Pool(web3)
417
+ const tokenInOutMarket: TokenInOutMarket = {
418
+ tokenIn: addresses.Ocean,
419
+ tokenOut: poolDatatokenAddress,
420
+ marketFeeAddress: consumerAccount
421
+ }
422
+ const amountsInOutMaxFee: AmountsOutMaxFee = {
423
+ maxAmountIn: '10',
424
+ tokenAmountOut: '1',
425
+ swapMarketFee: '0.1'
426
+ }
427
+
428
+ ```
429
+ Now we can make the contract call
430
+ ```Typescript
431
+ await pool.swapExactAmountOut(
432
+ consumerAccount,
433
+ poolAddress,
434
+ tokenInOutMarket,
435
+ amountsInOutMaxFee
436
+ )
437
+
438
+ consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
439
+ ```
440
+ Now let's console log the Consumer OCEAN balance after swap to check everything is working
441
+ ```Typescript
442
+ console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`)
443
+ consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
444
+ ```
445
+ Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance
446
+ ```Typescript
447
+ console.log(`Consumer ${POOL_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`)
448
+
449
+ const resolvedDDO = await aquarius.waitForAqua(DDO.id)
450
+ assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
451
+
452
+ ```
453
+ The next step is to initialize the provider instance
454
+ ```Typescript
455
+ const initializeData = await ProviderInstance.initialize(
456
+ resolvedDDO.id,
457
+ resolvedDDO.services[0].id,
458
+ 0,
459
+ consumerAccount,
460
+ providerUrl
461
+ )
462
+
463
+ const providerFees: ProviderFees = {
464
+ providerFeeAddress: initializeData.providerFee.providerFeeAddress,
465
+ providerFeeToken: initializeData.providerFee.providerFeeToken,
466
+ providerFeeAmount: initializeData.providerFee.providerFeeAmount,
467
+ v: initializeData.providerFee.v,
468
+ r: initializeData.providerFee.r,
469
+ s: initializeData.providerFee.s,
470
+ providerData: initializeData.providerFee.providerData,
471
+ validUntil: initializeData.providerFee.validUntil
472
+ }
473
+
474
+ ```
475
+ Now let's make a payment
476
+ ```Typescript
477
+ const tx = await datatoken.startOrder(
478
+ poolDatatokenAddress,
479
+ consumerAccount,
480
+ consumerAccount,
481
+ 0,
482
+ providerFees
483
+ )
484
+
485
+ ```
486
+ Next up, let's get the URL
487
+ ```Typescript
488
+ const downloadURL = await ProviderInstance.getDownloadUrl(
489
+ DDO.id,
490
+ consumerAccount,
491
+ DDO.services[0].id,
492
+ 0,
493
+ tx.transactionHash,
494
+ providerUrl,
495
+ web3
496
+ )
497
+
498
+ ```
499
+ Now let's console log the Download URL to check everything is working
500
+ ```Typescript
501
+ console.log(`Download URL: ${downloadURL}`)
502
+
503
+ consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
504
+ console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`)
505
+ consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
506
+
507
+ ```
508
+ Now let's console log the Consumer balance after order to check everything is working
509
+ ```Typescript
510
+ console.log(`Consumer ${POOL_NFT_SYMBOL} balance after order: ${consumerDTBalance}`)
511
+
512
+ try {
513
+ const fileData = await downloadFile(downloadURL)
514
+ console.log(fileData)
515
+ } catch (e) {
516
+ assert.fail('Download failed')
517
+ }
518
+
519
+ ```
520
+
521
+ ## 7. Publish Data NFT and a Datatoken with a fixed rate exchange
522
+
523
+ ### 7.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange
524
+ ```Typescript
525
+ const factory = new NftFactory(addresses.ERC721Factory, web3)
526
+
527
+ const nftParams: NftCreateData = {
528
+ name: FRE_NFT_NAME,
529
+ symbol: FRE_NFT_SYMBOL,
530
+ templateIndex: 1,
531
+ tokenURI: '',
532
+ transferable: true,
533
+ owner: publisherAccount
534
+ }
535
+
536
+ const erc20Params: Erc20CreateParams = {
537
+ templateIndex: 1,
538
+ cap: '100000',
539
+ feeAmount: '0',
540
+ paymentCollector: ZERO_ADDRESS,
541
+ feeToken: ZERO_ADDRESS,
542
+ minter: publisherAccount,
543
+ mpFeeAddress: ZERO_ADDRESS
544
+ }
545
+
546
+ const freParams: FreCreationParams = {
547
+ fixedRateAddress: addresses.FixedPrice,
548
+ baseTokenAddress: addresses.Ocean,
549
+ owner: publisherAccount,
550
+ marketFeeCollector: publisherAccount,
551
+ baseTokenDecimals: 18,
552
+ datatokenDecimals: 18,
553
+ fixedRate: '1',
554
+ marketFee: '0.001',
555
+ allowedConsumer: ZERO_ADDRESS,
556
+ withMint: false
557
+ }
558
+
559
+ const tx = await factory.createNftErc20WithFixedRate(
560
+ publisherAccount,
561
+ nftParams,
562
+ erc20Params,
563
+ freParams
564
+ )
565
+
566
+ freNftAddress = tx.events.NFTCreated.returnValues[0]
567
+ freDatatokenAddress = tx.events.TokenCreated.returnValues[0]
568
+ freAddress = tx.events.NewFixedRate.returnValues.exchangeContract
569
+ freId = tx.events.NewFixedRate.returnValues.exchangeId
570
+
571
+ ```
572
+ Now let's console log each of those values to check everything is working
573
+ ```Typescript
574
+ console.log(`Fixed rate exchange NFT address: ${freNftAddress}`)
575
+ console.log(`Fixed rate exchange Datatoken address: ${freDatatokenAddress}`)
576
+ console.log(`Fixed rate exchange address: ${freAddress}`)
577
+ console.log(`Fixed rate exchange Id: ${freId}`)
578
+
579
+ ```
580
+
581
+ ### 7.2 Set metadata in the fixed rate exchange NFT
582
+ ```Typescript
583
+ const nft = new Nft(web3)
584
+
585
+ ```
586
+ Now we are going to update the ddo and set the did
587
+ ```Typescript
588
+ DDO.chainId = await web3.eth.getChainId()
589
+ DDO.id =
590
+ 'did:op:' +
591
+ SHA256(web3.utils.toChecksumAddress(freNftAddress) + DDO.chainId.toString(10))
592
+ DDO.nftAddress = freNftAddress
593
+
594
+ ```
595
+ Next, let's encrypt the file(s) using provider
596
+ ```Typescript
597
+ ASSET_URL.datatokenAddress = freDatatokenAddress
598
+ ASSET_URL.nftAddress = freNftAddress
599
+ const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl)
600
+ DDO.services[0].files = await encryptedFiles
601
+ DDO.services[0].datatokenAddress = freDatatokenAddress
602
+
603
+ ```
604
+ Now let's console log the DID to check everything is working
605
+ ```Typescript
606
+ console.log(`DID: ${DDO.id}`)
607
+
608
+ const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl)
609
+ const encryptedDDO = await providerResponse
610
+ const metadataHash = getHash(JSON.stringify(DDO))
611
+ await nft.setMetadata(
612
+ freNftAddress,
613
+ publisherAccount,
614
+ 0,
615
+ providerUrl,
616
+ '',
617
+ '0x2',
618
+ encryptedDDO,
619
+ '0x' + metadataHash
620
+ )
621
+ })
622
+ ```
623
+
624
+ ### 7.3 Marketplace displays fixed rate asset for sale
625
+ ```Typescript
626
+ const fixedRate = new FixedRateExchange(web3, freAddress)
627
+ const oceanAmount = await (
628
+ await fixedRate.calcBaseInGivenOutDT(freId, '1')
629
+ ).baseTokenAmount
630
+ ```
631
+ 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:
632
+ ```Typescript
633
+ console.log(`Price of 1 ${FRE_NFT_SYMBOL} is ${oceanAmount} OCEAN`)
634
+
635
+ ```
636
+
637
+ ### 7.4 Consumer buys a fixed rate asset data asset, and downloads it
638
+ ```Typescript
639
+ const datatoken = new Datatoken(web3)
640
+ const DATATOKEN_AMOUNT = '10000'
641
+
642
+ await datatoken.mint(freDatatokenAddress, publisherAccount, DATATOKEN_AMOUNT)
643
+
644
+ const consumerETHBalance = await web3.eth.getBalance(consumerAccount)
645
+
646
+ ```
647
+ Let's do a quick check of the consumer ETH balance before the swap
648
+ ```Typescript
649
+ console.log(`Consumer ETH balance: ${consumerETHBalance}`)
650
+ let consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
651
+ console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`)
652
+ let consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount)
653
+ console.log(`Consumer ${FRE_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`)
654
+
655
+ ```
656
+ Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 tokens
657
+ ```Typescript
658
+ await approve(web3, consumerAccount, addresses.Ocean, freAddress, '100')
659
+ await approve(
660
+ web3,
661
+ publisherAccount,
662
+ freDatatokenAddress,
663
+ freAddress,
664
+ DATATOKEN_AMOUNT
665
+ )
666
+
667
+ const fixedRate = new FixedRateExchange(web3, freAddress)
668
+ ```
669
+ Now we can make the contract call
670
+ ```Typescript
671
+ await fixedRate.buyDT(consumerAccount, freId, '1', '2')
672
+
673
+ consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
674
+ console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`)
675
+ consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount)
676
+ console.log(`Consumer ${FRE_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`)
677
+
678
+ const resolvedDDO = await aquarius.waitForAqua(DDO.id)
679
+ assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
680
+
681
+ ```
682
+ Next, we need to initialize the provider
683
+ ```Typescript
684
+ const initializeData = await ProviderInstance.initialize(
685
+ resolvedDDO.id,
686
+ resolvedDDO.services[0].id,
687
+ 0,
688
+ consumerAccount,
689
+ providerUrl
690
+ )
691
+
692
+ const providerFees: ProviderFees = {
693
+ providerFeeAddress: initializeData.providerFee.providerFeeAddress,
694
+ providerFeeToken: initializeData.providerFee.providerFeeToken,
695
+ providerFeeAmount: initializeData.providerFee.providerFeeAmount,
696
+ v: initializeData.providerFee.v,
697
+ r: initializeData.providerFee.r,
698
+ s: initializeData.providerFee.s,
699
+ providerData: initializeData.providerFee.providerData,
700
+ validUntil: initializeData.providerFee.validUntil
701
+ }
702
+
703
+ ```
704
+ Lets now make the payment
705
+ ```Typescript
706
+ const tx = await datatoken.startOrder(
707
+ freDatatokenAddress,
708
+ consumerAccount,
709
+ consumerAccount,
710
+ 0,
711
+ providerFees
712
+ )
713
+ ```
714
+ Now we can get the url
715
+ ```Typescript
716
+ const downloadURL = await ProviderInstance.getDownloadUrl(
717
+ DDO.id,
718
+ consumerAccount,
719
+ DDO.services[0].id,
720
+ 0,
721
+ tx.transactionHash,
722
+ providerUrl,
723
+ web3
724
+ )
725
+
726
+ ```
727
+ Lets check that the download URL was successfully received
728
+ ```Typescript
729
+ console.log(`Download URL: ${downloadURL}`)
730
+
731
+ consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
732
+ console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`)
733
+ consumerDTBalance = await balance(web3, freDatatokenAddress, consumerAccount)
734
+ console.log(`Consumer ${FRE_NFT_SYMBOL} balance after order: ${consumerDTBalance}`)
735
+
736
+ try {
737
+ const fileData = await downloadFile(downloadURL)
738
+ console.log(fileData)
739
+ } catch (e) {
740
+ assert.fail('Download failed')
741
+ }
742
+
743
+ ```
744
+
745
+ ## 8. Publish Data NFT and a Datatoken with a dispenser
746
+
747
+ ### 8.1 Publish a dataset (create NFT + Datatoken) with a dispenser
748
+ ```Typescript
749
+ const factory = new NftFactory(addresses.ERC721Factory, web3)
750
+
751
+ const nftParams: NftCreateData = {
752
+ name: DISP_NFT_NAME,
753
+ symbol: DISP_NFT_SYMBOL,
754
+ templateIndex: 1,
755
+ tokenURI: '',
756
+ transferable: true,
757
+ owner: publisherAccount
758
+ }
759
+
760
+ const erc20Params: Erc20CreateParams = {
761
+ templateIndex: 1,
762
+ cap: '100000',
763
+ feeAmount: '0',
764
+ paymentCollector: ZERO_ADDRESS,
765
+ feeToken: ZERO_ADDRESS,
766
+ minter: publisherAccount,
767
+ mpFeeAddress: ZERO_ADDRESS
768
+ }
769
+
770
+ const dispenserParams: DispenserCreationParams = {
771
+ dispenserAddress: addresses.Dispenser,
772
+ maxTokens: '1',
773
+ maxBalance: '1',
774
+ withMint: true,
775
+ allowedSwapper: ZERO_ADDRESS
776
+ }
777
+
778
+ const tx = await factory.createNftErc20WithDispenser(
779
+ publisherAccount,
780
+ nftParams,
781
+ erc20Params,
782
+ dispenserParams
783
+ )
784
+
785
+ dispenserNftAddress = tx.events.NFTCreated.returnValues[0]
786
+ dispenserDatatokenAddress = tx.events.TokenCreated.returnValues[0]
787
+ dispenserAddress = tx.events.DispenserCreated.returnValues[0]
788
+ ```
789
+ Lets check that we managed to received all of those values without any problems
790
+ ```Typescript
791
+ console.log(`Dispenser NFT address: ${dispenserNftAddress}`)
792
+ console.log(`Dispenser Datatoken address: ${dispenserDatatokenAddress}`)
793
+ console.log(`Dispenser address: ${dispenserAddress}`)
794
+
795
+ ```
796
+
797
+ ### 8.2 Set metadata in the dispenser NFT
798
+ ```Typescript
799
+ const nft = new Nft(web3)
800
+
801
+ ```
802
+ Lets start by updating the ddo and setting the did
803
+ ```Typescript
804
+ DDO.chainId = await web3.eth.getChainId()
805
+ DDO.id =
806
+ 'did:op:' +
807
+ SHA256(web3.utils.toChecksumAddress(dispenserNftAddress) + DDO.chainId.toString(10))
808
+ DDO.nftAddress = dispenserNftAddress
809
+
810
+ ```
811
+ Now we need to encrypt file(s) using provider
812
+ ```Typescript
813
+ ASSET_URL.datatokenAddress = dispenserDatatokenAddress
814
+ ASSET_URL.nftAddress = dispenserNftAddress
815
+ const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl)
816
+ DDO.services[0].files = await encryptedFiles
817
+ DDO.services[0].datatokenAddress = dispenserDatatokenAddress
818
+
819
+ console.log(`DID: ${DDO.id}`)
820
+
821
+ const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl)
822
+ const encryptedDDO = await providerResponse
823
+ const metadataHash = getHash(JSON.stringify(DDO))
824
+ await nft.setMetadata(
825
+ dispenserNftAddress,
826
+ publisherAccount,
827
+ 0,
828
+ providerUrl,
829
+ '',
830
+ '0x2',
831
+ encryptedDDO,
832
+ '0x' + metadataHash
833
+ )
834
+
835
+ ```
836
+
837
+ ### 8.3 Consumer gets a dispenser data asset, and downloads it
838
+ ```Typescript
839
+ const datatoken = new Datatoken(web3)
840
+ const dispenser = new Dispenser(web3, null, addresses.Dispenser)
841
+
842
+ let consumerDTBalance = await balance(
843
+ web3,
844
+ dispenserDatatokenAddress,
845
+ consumerAccount
846
+ )
847
+ console.log(
848
+ `Consumer ${DISP_NFT_SYMBOL} balance before dispense: ${consumerDTBalance}`
849
+ )
850
+
851
+ await dispenser.dispense(
852
+ dispenserDatatokenAddress,
853
+ consumerAccount,
854
+ '1',
855
+ consumerAccount
856
+ )
857
+
858
+ consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount)
859
+ console.log(
860
+ `Consumer ${DISP_NFT_SYMBOL} balance after dispense: ${consumerDTBalance}`
861
+ )
862
+
863
+ const resolvedDDO = await aquarius.waitForAqua(DDO.id)
864
+ assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
865
+ ```
866
+ At this point we need to encrypt file(s) using provider
867
+ ```Typescript
868
+ const initializeData = await ProviderInstance.initialize(
869
+ resolvedDDO.id,
870
+ resolvedDDO.services[0].id,
871
+ 0,
872
+ consumerAccount,
873
+ providerUrl
874
+ )
875
+
876
+ const providerFees: ProviderFees = {
877
+ providerFeeAddress: initializeData.providerFee.providerFeeAddress,
878
+ providerFeeToken: initializeData.providerFee.providerFeeToken,
879
+ providerFeeAmount: initializeData.providerFee.providerFeeAmount,
880
+ v: initializeData.providerFee.v,
881
+ r: initializeData.providerFee.r,
882
+ s: initializeData.providerFee.s,
883
+ providerData: initializeData.providerFee.providerData,
884
+ validUntil: initializeData.providerFee.validUntil
885
+ }
886
+ ```
887
+ Now we need to make the payment
888
+ ```Typescript
889
+ const tx = await datatoken.startOrder(
890
+ dispenserDatatokenAddress,
891
+ consumerAccount,
892
+ consumerAccount,
893
+ 0,
894
+ providerFees
895
+ )
896
+ ```
897
+ Now we can get the download URL
898
+ ```Typescript
899
+ const downloadURL = await ProviderInstance.getDownloadUrl(
900
+ DDO.id,
901
+ consumerAccount,
902
+ DDO.services[0].id,
903
+ 0,
904
+ tx.transactionHash,
905
+ providerUrl,
906
+ web3
907
+ )
908
+ ```
909
+ Let's check we received the download URL ok
910
+ ```Typescript
911
+ console.log(`Download URL: ${downloadURL}`)
912
+
913
+ consumerDTBalance = await balance(web3, dispenserDatatokenAddress, consumerAccount)
914
+ console.log(`Consumer ${DISP_NFT_SYMBOL} balance after order: ${consumerDTBalance}`)
915
+
916
+ try {
917
+ const fileData = await downloadFile(downloadURL)
918
+ console.log(fileData)
919
+ } catch (e) {
920
+ assert.fail('Download failed')
921
+ }
922
+
923
+ ```
924
+
925
+
926
+ ## Editing this file
927
+ Please note that CodeExamples.md is an autogenerated file, you should not edit it directly.
928
+ Updates should be done in `test/integration/CodeExamples.test.ts` and all markdown should have three forward slashes before it
929
+ e.g. `/// # H1 Title`