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