Remove amm pools (#1568)

* WIP remove pools

* added logs

* update checksums and logs

* Updating CodeExamples.md

* remove console logs

* remove unused params, simplify test folder structure

* contracts folder simplification, remove ss contract methods

* path fix

* remove more "staking" code

* put back `removeApprovedToken()`

* remove redundant and unused test commands

* test fix, auto-fix & auto-format

* consistent specific imports

* readme updates

* remove addDispenserContract method

* remove tokens subfolder from contracts

* update js docs and put back addDispenserContract

* use new digest for algorthms

* update nft getData to fix failing unit test

* replace pools with fre in  buyDatatokenBatch

* use proper exchange ids

* increase allowance

* fix buyBatch test and deploy issues from testcontracthandler

Co-authored-by: GitHub Actions Bot <>
Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
This commit is contained in:
Bogdan Fazakas 2022-08-16 13:54:28 +03:00 committed by GitHub
parent 451fbe028c
commit 30aba62ef7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 265 additions and 4155 deletions

View File

@ -23,9 +23,8 @@ Here are the steps:
3. [Install dependencies](#-install-dependencies)
4. [Initialize accounts and deploy contracts](#-initialize-accounts-and-deploy-contracts)
5. [Import dependencies and add variables and constants](#-import-dependencies-and-add-variables-and-constants)
6. [Publish Data NFT and a Datatoken with a liquidity pool](#-Publish-data-nft-and-a-datatoken-with-a-liquidity-pool)
7. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange)
8. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser)
6. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange)
7. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser)
## 0. Prerequisites
Before we start it is important that you have all of the necessary prerequisites installed on your computer.
@ -88,7 +87,6 @@ Start by importing all of the necessary dependencies
import { SHA256 } from 'crypto-js'
import {
AmountsOutMaxFee,
approve,
Aquarius,
balance,
@ -105,11 +103,8 @@ import {
Nft,
NftCreateData,
NftFactory,
Pool,
PoolCreationParams,
ProviderFees,
ProviderInstance,
TokenInOutMarket,
transfer,
ZERO_ADDRESS
} from '../../src'
@ -130,9 +125,6 @@ Now we define the variables which we will need later
let consumerAccount: string
let stakerAccount: string
let addresses: any
let poolNftAddress: string
let poolDatatokenAddress: string
let poolAddress: string
let freNftAddress: string
let freDatatokenAddress: string
let freAddress: string
@ -144,8 +136,6 @@ Now we define the variables which we will need later
We also define some constants that we will use:
```Typescript
const POOL_NFT_NAME = 'Datatoken 1'
const POOL_NFT_SYMBOL = 'DT1'
const FRE_NFT_NAME = 'Datatoken 2'
const FRE_NFT_SYMBOL = 'DT2'
const DISP_NFT_NAME = 'Datatoken 3'
@ -240,287 +230,9 @@ Again, lets console log the values so that we can check that they have been save
```
## 6. Publish Data NFT and a Datatoken with a liquidity pool
## 6. Publish Data NFT and a Datatoken with a fixed rate exchange
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.
### 6.1 Publish a dataset (create NFT + Datatoken) with a liquidity pool
```Typescript
const factory = new NftFactory(addresses.ERC721Factory, web3)
const nftParams: NftCreateData = {
name: POOL_NFT_NAME,
symbol: POOL_NFT_SYMBOL,
templateIndex: 1,
tokenURI: '',
transferable: true,
owner: publisherAccount
}
const datatokenParams: DatatokenCreateParams = {
templateIndex: 1,
cap: '100000',
feeAmount: '0',
paymentCollector: ZERO_ADDRESS,
feeToken: ZERO_ADDRESS,
minter: publisherAccount,
mpFeeAddress: ZERO_ADDRESS
}
const poolParams: PoolCreationParams = {
ssContract: addresses.Staking,
baseTokenAddress: addresses.Ocean,
baseTokenSender: addresses.ERC721Factory,
publisherAddress: publisherAccount,
marketFeeCollector: publisherAccount,
poolTemplateAddress: addresses.poolTemplate,
rate: '1',
baseTokenDecimals: 18,
vestingAmount: '10000',
vestedBlocks: 2500000,
initialBaseTokenLiquidity: '2000',
swapFeeLiquidityProvider: '0.001',
swapFeeMarketRunner: '0.001'
}
```
Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 Datatokens
```Typescript
await approve(
web3,
publisherAccount,
addresses.Ocean,
addresses.ERC721Factory,
poolParams.vestingAmount
)
```
Now we can make the contract call
```Typescript
const tx = await factory.createNftWithDatatokenWithPool(
publisherAccount,
nftParams,
datatokenParams,
poolParams
)
poolNftAddress = tx.events.NFTCreated.returnValues[0]
poolDatatokenAddress = tx.events.TokenCreated.returnValues[0]
poolAddress = tx.events.NewPool.returnValues[0]
```
Now, we did quite a few things there. Let's check that we successfully published a dataset (create NFT + Datatoken) with a liquidity pool
```Typescript
console.log(`Pool NFT address: ${poolNftAddress}`)
console.log(`Pool Datatoken address: ${poolDatatokenAddress}`)
console.log(`Pool address: ${poolAddress}`)
```
### 6.2 Set metadata in the pool NFT
```Typescript
const nft = new Nft(web3)
```
Now we update the ddo and set the right did
```Typescript
DDO.chainId = await web3.eth.getChainId()
DDO.id =
'did:op:' +
SHA256(web3.utils.toChecksumAddress(poolNftAddress) + DDO.chainId.toString(10))
DDO.nftAddress = poolNftAddress
```
Next we encrypt the file or files using Ocean Provider. The provider is an off chain proxy built specifically for this task
```Typescript
ASSET_URL.datatokenAddress = poolDatatokenAddress
ASSET_URL.nftAddress = poolNftAddress
const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl)
DDO.services[0].files = await encryptedFiles
DDO.services[0].datatokenAddress = poolDatatokenAddress
```
Now let's console log the result to check everything is working
```Typescript
console.log(`DID: ${DDO.id}`)
const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl)
const encryptedDDO = await providerResponse
const metadataHash = getHash(JSON.stringify(DDO))
await nft.setMetadata(
poolNftAddress,
publisherAccount,
0,
providerUrl,
'',
'0x2',
encryptedDDO,
'0x' + metadataHash
)
```
### 6.3 User should add liquidity to the pool, receiving LP tokens
```Typescript
const pool = new Pool(web3)
```
Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 Datatokens
```Typescript
await approve(web3, stakerAccount, addresses.Ocean, poolAddress, '5', true)
```
Now we can make the contract call
```Typescript
await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1')
```
### 6.4 Marketplace displays pool asset for sale
```Typescript
const pool = new Pool(web3)
const prices = await pool.getAmountInExactOut(
poolAddress,
poolDatatokenAddress,
addresses.Ocean,
'1',
'0.01'
)
```
Now let's console log the result to check everything is working
```Typescript
console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`)
```
### 6.5 Consumer buys a pool data asset, and downloads it
```Typescript
const datatoken = new Datatoken(web3)
const consumerETHBalance = await web3.eth.getBalance(consumerAccount)
```
Now let's console log the result to check everything is working
```Typescript
console.log(`Consumer ETH balance: ${consumerETHBalance}`)
let consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
```
Now let's console log consumerOCEANBalance to check everything is working
```Typescript
console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`)
let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
```
Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything is working
```Typescript
console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`)
```
Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 Datatokens
```Typescript
await approve(web3, consumerAccount, addresses.Ocean, poolAddress, '100')
const pool = new Pool(web3)
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: addresses.Ocean,
tokenOut: poolDatatokenAddress,
marketFeeAddress: consumerAccount
}
const amountsInOutMaxFee: AmountsOutMaxFee = {
maxAmountIn: '10',
tokenAmountOut: '1',
swapMarketFee: '0.1'
}
```
Now we can make the contract call
```Typescript
await pool.swapExactAmountOut(
consumerAccount,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
```
Now let's console log the Consumer OCEAN balance after swap to check everything is working
```Typescript
console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`)
consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
```
Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance
```Typescript
console.log(`Consumer ${POOL_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`)
const resolvedDDO = await aquarius.waitForAqua(DDO.id)
assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
```
The next step is to initialize the provider instance
```Typescript
const initializeData = await ProviderInstance.initialize(
resolvedDDO.id,
resolvedDDO.services[0].id,
0,
consumerAccount,
providerUrl
)
const providerFees: ProviderFees = {
providerFeeAddress: initializeData.providerFee.providerFeeAddress,
providerFeeToken: initializeData.providerFee.providerFeeToken,
providerFeeAmount: initializeData.providerFee.providerFeeAmount,
v: initializeData.providerFee.v,
r: initializeData.providerFee.r,
s: initializeData.providerFee.s,
providerData: initializeData.providerFee.providerData,
validUntil: initializeData.providerFee.validUntil
}
```
Now let's make a payment
```Typescript
const tx = await datatoken.startOrder(
poolDatatokenAddress,
consumerAccount,
consumerAccount,
0,
providerFees
)
```
Next up, let's get the URL
```Typescript
const downloadURL = await ProviderInstance.getDownloadUrl(
DDO.id,
consumerAccount,
DDO.services[0].id,
0,
tx.transactionHash,
providerUrl,
web3
)
```
Now let's console log the Download URL to check everything is working
```Typescript
console.log(`Download URL: ${downloadURL}`)
consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`)
consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
```
Now let's console log the Consumer balance after order to check everything is working
```Typescript
console.log(`Consumer ${POOL_NFT_SYMBOL} balance after order: ${consumerDTBalance}`)
try {
const fileData = await downloadFile(downloadURL)
console.log(fileData)
} catch (e) {
assert.fail('Download failed')
}
```
## 7. Publish Data NFT and a Datatoken with a fixed rate exchange
### 7.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange
### 6.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange
```Typescript
const factory = new NftFactory(addresses.ERC721Factory, web3)
@ -578,7 +290,7 @@ Now let's console log each of those values to check everything is working
```
### 7.2 Set metadata in the fixed rate exchange NFT
### 6.2 Set metadata in the fixed rate exchange NFT
```Typescript
const nft = new Nft(web3)
@ -621,7 +333,7 @@ Now let's console log the DID to check everything is working
})
```
### 7.3 Marketplace displays fixed rate asset for sale
### 6.3 Marketplace displays fixed rate asset for sale
```Typescript
const fixedRate = new FixedRateExchange(freAddress, web3)
const oceanAmount = await (
@ -634,7 +346,7 @@ Now that the market has fetched those values it can display the asset on the fro
```
### 7.4 Consumer buys a fixed rate asset data asset, and downloads it
### 6.4 Consumer buys a fixed rate asset data asset, and downloads it
```Typescript
const datatoken = new Datatoken(web3)
const DATATOKEN_AMOUNT = '10000'
@ -742,9 +454,9 @@ Lets check that the download URL was successfully received
```
## 8. Publish Data NFT and a Datatoken with a dispenser
## 7. Publish Data NFT and a Datatoken with a dispenser
### 8.1 Publish a dataset (create NFT + Datatoken) with a dispenser
### 7.1 Publish a dataset (create NFT + Datatoken) with a dispenser
```Typescript
const factory = new NftFactory(addresses.ERC721Factory, web3)
@ -794,7 +506,7 @@ Lets check that we managed to received all of those values without any problems
```
### 8.2 Set metadata in the dispenser NFT
### 7.2 Set metadata in the dispenser NFT
```Typescript
const nft = new Nft(web3)
@ -834,7 +546,7 @@ Now we need to encrypt file(s) using provider
```
### 8.3 Consumer gets a dispenser data asset, and downloads it
### 7.3 Consumer gets a dispenser data asset, and downloads it
```Typescript
const datatoken = new Datatoken(web3)
const dispenser = new Dispenser(addresses.Dispenser, web3)

View File

@ -14,8 +14,7 @@
With ocean.js, you can:
- **Publish** data services: downloadable files or compute-to-data. Create an ERC721 **data NFT** for each service, and ERC20 **datatoken** for access (1.0 datatokens to access).
- **Sell** datatokens via an OCEAN-datatoken Balancer pool (for auto price discovery), or for a fixed price. Sell data NFTs.
- **Stake OCEAN** on datatoken pools
- **Sell** datatokens for a fixed price. Sell data NFTs.
- **Transfer** data NFTs & datatokens to another owner, and **all other ERC721 & ERC20 actions** using [web3.js](https://web3js.readthedocs.io/en/v1.2.9/web3-eth-contract.html) etc.
ocean.js is part of the [Ocean Protocol](https://oceanprotocol.com) toolset.
@ -23,8 +22,7 @@ ocean.js is part of the [Ocean Protocol](https://oceanprotocol.com) toolset.
This is in alpha state. If you run into problems, please open up a [new issue](https://github.com/oceanprotocol/ocean.js/issues/new?assignees=&labels=bug&template=bug_report.md&title=).
- [📚 Prerequisites](#-prerequisites)
- [🏗 Installation](#-installation)
- [📖 Learn More](#-learn-more)
- [🏗 Installation & Usage](#-installation--usage)
- [🦑 Development](#-development)
- [✨ Code Style](#-code-style)
- [👩‍🔬 Testing](#-testing)
@ -33,7 +31,7 @@ This is in alpha state. If you run into problems, please open up a [new issue](h
- [🛳 Production](#-production)
- [⬆️ Releases](#-releases)
- [Production](#production)
- [Pre-releases](#pre-releases)
- [Pre-Releases](#pre-releases)
- [🏛 License](#-license)
## 📚 Prerequisites
@ -42,12 +40,11 @@ This is in alpha state. If you run into problems, please open up a [new issue](h
- Docker ([Managed as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/))
- A Unix based operating system (Mac or Linux)
## 🏗 Installation
## 🏗 Installation & Usage
```bash
npm install @oceanprotocol/lib
```
### 📖 Learn more
- Checkout our [code examples](CodeExamples.md) to see how you can use ocean.js.
- Refer to the [Ocean Protocol documentation](https://docs.oceanprotocol.com/) for more guides and tutorials.

View File

@ -27,25 +27,12 @@
"changelog": "auto-changelog -p",
"prepublishOnly": "npm run build",
"mocha": "TS_NODE_PROJECT='./test/tsconfig.json' mocha --config=test/.mocharc.json --node-env=test --exit",
"test:nftfactory": "npm run mocha -- 'test/unit/factories/NftFactory.test.ts'",
"test:nft": "npm run mocha -- 'test/unit/tokens/Nft.test.ts'",
"test:datatoken": "npm run mocha -- 'test/unit/tokens/Datatoken.test.ts'",
"test:router": "npm run mocha -- 'test/unit/pools/Router.test.ts'",
"test:fixed": "npm run mocha -- 'test/unit/pools/fixedRate/FixedRateExchange.test.ts'",
"test:ss": "npm run mocha -- 'test/unit/pools/ssContracts/SideStaking.test.ts'",
"test:pool": "npm run mocha -- 'test/unit/pools/balancer/Pool.test.ts'",
"test:dispenser": "npm run mocha -- 'test/unit/pools/dispenser/Dispenser.test.ts'",
"test:publishAll": "npm run mocha -- 'test/integration/PublishFlows.test.ts'",
"test:examples": "npm run mocha -- 'test/integration/CodeExamples.test.ts'",
"test:provider": "npm run mocha -- 'test/integration/Provider.test.ts'",
"test:unit": "npm run mocha -- 'test/unit/**/*.test.ts'",
"test:unit:cover": "nyc --report-dir coverage/unit --exclude 'src/@types/**/*' npm run test:unit",
"test:integration": "npm run mocha -- 'test/integration/**/*.test.ts'",
"test:compute": "npm run mocha -- 'test/integration/ComputeFlow.test.ts'",
"test:integration:cover": "nyc --report-dir coverage/integration --exclude 'src/@types/**/*' --no-clean npm run test:integration",
"create:guide": "chmod +x ./scripts/createCodeExamples.sh && ./scripts/createCodeExamples.sh",
"create:guide:mac": "chmod +x ./scripts/createCodeExamples-mac.sh && ./scripts/createCodeExamples-mac.sh",
"commit:guide": "chmod +x scripts/commitChanges.sh && scripts/commitChanges.sh"
"test:integration:cover": "nyc --report-dir coverage/integration --no-clean npm run test:integration",
"create:guide": "./scripts/createCodeExamples.sh",
"commit:guide": "./scripts/commitChanges.sh"
},
"repository": {
"type": "git",

View File

@ -1,21 +0,0 @@
#!/bin/bash
# Create markdown file
cp test/integration/CodeExamples.test.ts CodeExamples.md
# Remove unneccessay imports
sed -i '' -e "s/import { assert } from 'chai'//" CodeExamples.md
# Replace comments
sed -i '' -e 's/}) \/\/\/ //' CodeExamples.md
sed -i '' -e 's/}) \/\/\///' CodeExamples.md
sed -i '' -e 's/ \/\/\/ //' CodeExamples.md
sed -i '' -e 's/ \/\/\/ //' CodeExamples.md
sed -i '' -e 's/\/\/\/ //' CodeExamples.md
# Generate titles
sed -i '' -e "s/describe('Simple Publish & Consume Flow', async () => {//" CodeExamples.md
sed -i '' -e "s/it('/\#\#\# /" CodeExamples.md
sed -i '' -e "s/', async () => {//" CodeExamples.md
sed -i '' -e "s/before(async () => {//" CodeExamples.md

View File

@ -131,7 +131,7 @@ export interface Asset extends DDO {
/**
* Contains information about an asset's purgatory status defined in
* [`list-purgatory`](https://github.com/oceanprotocol/list-purgatory).
* Marketplace interfaces are encouraged to prevent certain user actions like adding liquidity on assets in purgatory.
* Marketplace interfaces are encouraged to prevent certain user actions like downloading on assets in purgatory.
* @type {Purgatory}
*/
purgatory: Purgatory

View File

@ -1,50 +0,0 @@
export interface PoolCreationParams {
ssContract: string
baseTokenAddress: string
baseTokenSender: string
publisherAddress: string
marketFeeCollector: string
poolTemplateAddress: string
rate: string
baseTokenDecimals: number
vestingAmount: string
vestedBlocks: number
initialBaseTokenLiquidity: string
swapFeeLiquidityProvider: string
swapFeeMarketRunner: string
}
export interface CurrentFees {
tokens: string[]
amounts: string[]
}
export interface TokenInOutMarket {
tokenIn: string
tokenOut: string
marketFeeAddress: string
tokenInDecimals?: number
tokenOutDecimals?: number
}
export interface AmountsInMaxFee {
tokenAmountIn: string
minAmountOut: string
swapMarketFee: string
maxPrice?: string
}
export interface AmountsOutMaxFee {
tokenAmountOut: string
maxAmountIn: string
swapMarketFee: string
maxPrice?: string
}
export interface PoolPriceAndFees {
tokenAmount: string
liquidityProviderSwapFeeAmount: string
oceanFeeAmount: string
publishMarketSwapFeeAmount: string
consumeMarketSwapFeeAmount: string
}

View File

@ -1,6 +1,6 @@
export interface Operation {
/**
* used only for FixedRate or Dispenser, but needs to be filled even for pool
* used for FixedRate or Dispenser
* @type {string}
*/
exchangeIds: string

View File

@ -13,6 +13,5 @@ export * from './DownloadResponse'
export * from './FixedPrice'
export * from './NFT'
export * from './NFTFactory'
export * from './Pool'
export * from './Provider'
export * from './Router'

View File

@ -50,24 +50,6 @@ export class Config {
*/
public datatokensABI?: AbiItem | AbiItem[]
/**
* Pool Template address
* @type {string}
*/
public poolTemplateAddress?: string
/**
* Pool Factory ABI
* @type {string}
*/
public poolFactoryABI?: AbiItem | AbiItem[]
/**
* Pool ABI
* @type {string}
*/
public poolABI?: AbiItem | AbiItem[]
/**
* FixedRateExchangeAddress
* @type {string}

View File

@ -13,7 +13,6 @@ const configHelperNetworksBase: Config = {
explorerUri: null,
oceanTokenAddress: null,
oceanTokenSymbol: 'OCEAN',
poolTemplateAddress: null,
fixedRateExchangeAddress: null,
dispenserAddress: null,
startBlock: 0,
@ -151,8 +150,6 @@ export class ConfigHelper {
const {
FixedPrice,
Dispenser,
Staking,
poolTemplate,
ERC721Factory,
OPFCommunityFeeCollector,
Ocean,
@ -161,14 +158,12 @@ export class ConfigHelper {
} = customAddresses[network]
configAddresses = {
nftFactoryAddress: ERC721Factory,
sideStakingAddress: Staking,
opfCommunityFeeCollector: OPFCommunityFeeCollector,
poolTemplateAddress: poolTemplate,
fixedRateExchangeAddress: FixedPrice,
dispenserAddress: Dispenser,
oceanTokenAddress: Ocean,
chainId: chainId,
startBlock: startBlock,
chainId,
startBlock,
...(process.env.AQUARIUS_URI && { metadataCacheUri: process.env.AQUARIUS_URI })
}
} else {
@ -177,8 +172,6 @@ export class ConfigHelper {
const {
FixedPrice,
Dispenser,
Staking,
poolTemplate,
OPFCommunityFeeCollector,
ERC721Factory,
Ocean,
@ -187,14 +180,12 @@ export class ConfigHelper {
} = DefaultContractsAddresses[network]
configAddresses = {
nftFactoryAddress: ERC721Factory,
sideStakingAddress: Staking,
opfCommunityFeeCollector: OPFCommunityFeeCollector,
poolTemplateAddress: poolTemplate,
fixedRateExchangeAddress: FixedPrice,
dispenserAddress: Dispenser,
oceanTokenAddress: Ocean,
chainId: chainId,
startBlock: startBlock,
chainId,
startBlock,
...(process.env.AQUARIUS_URI && { metadataCacheUri: process.env.AQUARIUS_URI })
}
}

View File

@ -4,7 +4,7 @@ import { TransactionReceipt } from 'web3-eth'
import Decimal from 'decimal.js'
import ERC20Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json'
import ERC20TemplateEnterprise from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20TemplateEnterprise.sol/ERC20TemplateEnterprise.json'
import { amountToUnits, calculateEstimatedGas, ZERO_ADDRESS } from '../../utils'
import { amountToUnits, calculateEstimatedGas, ZERO_ADDRESS } from '../utils'
import {
ConsumeMarketFee,
FreOrderParams,
@ -14,10 +14,10 @@ import {
DispenserParams,
OrderParams,
DatatokenRoles
} from '../../@types'
} from '../@types'
import { Nft } from './NFT'
import { Config } from '../../config'
import { SmartContract } from '..'
import { Config } from '../config'
import { SmartContract } from './SmartContract'
export class Datatoken extends SmartContract {
public abiEnterprise: AbiItem | AbiItem[]

View File

@ -2,9 +2,10 @@ import { AbiItem } from 'web3-utils'
import { TransactionReceipt } from 'web3-eth'
import Decimal from 'decimal.js'
import DispenserAbi from '@oceanprotocol/contracts/artifacts/contracts/pools/dispenser/Dispenser.sol/Dispenser.json'
import { calculateEstimatedGas } from '../../utils/'
import { Datatoken, SmartContractWithAddress } from '..'
import { DispenserToken } from '../../@types'
import { calculateEstimatedGas } from '../utils'
import { Datatoken } from './Datatoken'
import { SmartContractWithAddress } from './SmartContractWithAddress'
import { DispenserToken } from '../@types'
export class Dispenser extends SmartContractWithAddress {
getDefaultAbi(): AbiItem | AbiItem[] {

View File

@ -1,9 +1,9 @@
import FixedRateExchangeAbi from '@oceanprotocol/contracts/artifacts/contracts/pools/fixedRate/FixedRateExchange.sol/FixedRateExchange.json'
import { TransactionReceipt } from 'web3-core'
import { AbiItem } from 'web3-utils/types'
import { calculateEstimatedGas, ZERO_ADDRESS } from '../../utils'
import { PriceAndFees, FeesInfo, FixedPriceExchange } from '../../@types'
import { SmartContractWithAddress } from '..'
import { calculateEstimatedGas, ZERO_ADDRESS } from '../utils'
import { PriceAndFees, FeesInfo, FixedPriceExchange } from '../@types'
import { SmartContractWithAddress } from './SmartContractWithAddress'
export class FixedRateExchange extends SmartContractWithAddress {
getDefaultAbi(): AbiItem | AbiItem[] {
@ -83,7 +83,7 @@ export class FixedRateExchange extends SmartContractWithAddress {
}
/**
* Atomic swap
* Sell datatokenAmount while expecting at least minBaseTokenAmount
* @param {String} exchangeId ExchangeId
* @param {String} datatokenAmount Amount of datatokens
* @param {String} minBaseTokenAmount min amount of baseToken we want to receive back
@ -183,7 +183,7 @@ export class FixedRateExchange extends SmartContractWithAddress {
}
/**
* Set new rate
* Sets a new allowedSwapper
* @param {String} exchangeId ExchangeId
* @param {String} newAllowedSwapper newAllowedSwapper (set address zero if we want to remove allowed swapper)
* @param {String} address User account

View File

@ -1,9 +1,9 @@
import { AbiItem } from 'web3-utils'
import { TransactionReceipt } from 'web3-eth'
import ERC721Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json'
import { generateDtName, calculateEstimatedGas, setContractDefaults } from '../../utils'
import { MetadataProof, MetadataAndTokenURI, NftRoles } from '../../@types'
import { SmartContract } from '..'
import { generateDtName, calculateEstimatedGas } from '../utils'
import { MetadataProof, MetadataAndTokenURI, NftRoles } from '../@types'
import { SmartContract } from './SmartContract'
export class Nft extends SmartContract {
getDefaultAbi(): AbiItem | AbiItem[] {
@ -516,10 +516,15 @@ export class Nft extends SmartContract {
}
/**
* safeTransferNFT Used for transferring the NFT, can be used by an approved relayer
* will clean all permissions both on NFT and Datatoken level.
* Creates or update Metadata cached by Aquarius. Also, updates the METADATA_DECRYPTOR key
* @param {String} nftAddress NFT contract address
* @param {String} address Caller address NFT Owner adress
* @param {String} address Caller address NFT Owner adress
* @param {String} address Caller address NFT Owner adress
* @param {String} address Caller address NFT Owner adress
* @param {String} address Caller address NFT Owner adress
* @param {String} address Caller address NFT Owner adress
* @param {String} address Caller address NFT Owner adress
* @return {Promise<TransactionReceipt>} trxReceipt
*/
public async setMetadata<G extends boolean = false>(

View File

@ -2,17 +2,16 @@ import Web3 from 'web3'
import { TransactionReceipt } from 'web3-core'
import { AbiItem } from 'web3-utils'
import ERC721Factory from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json'
import { generateDtName, calculateEstimatedGas, ZERO_ADDRESS } from '../../utils'
import { generateDtName, calculateEstimatedGas, ZERO_ADDRESS } from '../utils'
import {
FreCreationParams,
DatatokenCreateParams,
PoolCreationParams,
DispenserCreationParams,
NftCreateData,
Template,
TokenOrder
} from '../../@types'
import { SmartContractWithAddress } from '..'
} from '../@types'
import { SmartContractWithAddress } from './SmartContractWithAddress'
/**
* Provides an interface for NFT Factory contract
@ -485,47 +484,6 @@ export class NftFactory extends SmartContractWithAddress {
return trxReceipt
}
/**
* @dev createNftWithDatatokenWithPool
* Creates a new NFT, then a Datatoken, then a Pool, all in one call
* Use this carefully, because if Pool creation fails, you are still going to pay a lot of gas
* @param address Caller address
* @param nftCreateData input data for NFT Creation
* @param dtParams input data for Datatoken Creation
* @param poolParams input data for Pool Creation
* @return {Promise<TransactionReceipt>} transaction receipt
*/
public async createNftWithDatatokenWithPool<G extends boolean = false>(
address: string,
nftCreateData: NftCreateData,
dtParams: DatatokenCreateParams,
poolParams: PoolCreationParams,
estimateGas?: G
): Promise<G extends false ? TransactionReceipt : number> {
const ercCreateData = this.getErcCreationParams(dtParams)
const poolData = await this.getPoolCreationParams(poolParams)
const estGas = await calculateEstimatedGas(
address,
this.contract.methods.createNftWithErc20WithPool,
nftCreateData,
ercCreateData,
poolData
)
if (estimateGas) return estGas
// Invoke createToken function of the contract
const trxReceipt = await this.contract.methods
.createNftWithErc20WithPool(nftCreateData, ercCreateData, poolData)
.send({
from: address,
gas: estGas + 1,
gasPrice: await this.getFairGasPrice()
})
return trxReceipt
}
/**
* @dev createNftWithDatatokenWithFixedRate
* Creates a new NFT, then a Datatoken, then a FixedRateExchange, all in one call
@ -651,31 +609,4 @@ export class NftFactory extends SmartContractWithAddress {
]
}
}
private async getPoolCreationParams(poolParams: PoolCreationParams): Promise<any> {
return {
addresses: [
poolParams.ssContract,
poolParams.baseTokenAddress,
poolParams.baseTokenSender,
poolParams.publisherAddress,
poolParams.marketFeeCollector,
poolParams.poolTemplateAddress
],
ssParams: [
Web3.utils.toWei(poolParams.rate),
poolParams.baseTokenDecimals,
Web3.utils.toWei(poolParams.vestingAmount),
poolParams.vestedBlocks,
await this.amountToUnits(
poolParams.baseTokenAddress,
poolParams.initialBaseTokenLiquidity
)
],
swapFees: [
Web3.utils.toWei(poolParams.swapFeeLiquidityProvider),
Web3.utils.toWei(poolParams.swapFeeMarketRunner)
]
}
}
}

View File

@ -1,9 +1,9 @@
import { TransactionReceipt } from 'web3-core'
import { AbiItem } from 'web3-utils'
import FactoryRouter from '@oceanprotocol/contracts/artifacts/contracts/pools/FactoryRouter.sol/FactoryRouter.json'
import { calculateEstimatedGas } from '../../utils'
import { Operation } from '../../@types'
import { SmartContractWithAddress } from '..'
import { calculateEstimatedGas } from '../utils'
import { Operation } from '../@types'
import { SmartContractWithAddress } from './SmartContractWithAddress'
/**
* Provides an interface for FactoryRouter contract
@ -48,13 +48,6 @@ export class Router extends SmartContractWithAddress {
return await this.contract.methods.isApprovedToken(address).call()
}
/** Check if an address is a side staking contract.
* @return {Promise<boolean>} true if is a SS contract
*/
public async isSideStaking(address: string): Promise<boolean> {
return await this.contract.methods.isSSContract(address).call()
}
/** Check if an address is a Fixed Rate contract.
* @return {Promise<boolean>} true if is a Fixed Rate contract
*/
@ -76,15 +69,8 @@ export class Router extends SmartContractWithAddress {
return await this.contract.methods.factory().call()
}
/** Check if an address is a pool template contract.
* @return {Promise<boolean>} true if is a Template
*/
public async isPoolTemplate(address: string): Promise<boolean> {
return await this.contract.methods.isPoolTemplate(address).call()
}
/**
* Add a new token to oceanTokens list, pools with baseToken in this list have NO opf Fee
* Adds a token to the list of tokens with reduced fees
* @param {String} address caller address
* @param {String} tokenAddress token address to add
* @return {Promise<TransactionReceipt>}
@ -116,7 +102,7 @@ export class Router extends SmartContractWithAddress {
}
/**
* Remove a token from oceanTokens list, pools without baseToken in this list have a opf Fee
* Removes a token if exists from the list of tokens with reduced fees
* @param {String} address
* @param {String} tokenAddress address to remove
* @return {Promise<TransactionReceipt>}
@ -150,71 +136,7 @@ export class Router extends SmartContractWithAddress {
}
/**
* Add a new contract to ssContract list, after is added, can be used when deploying a new pool
* @param {String} address
* @param {String} tokenAddress contract address to add
* @return {Promise<TransactionReceipt>}
*/
public async addSSContract<G extends boolean = false>(
address: string,
tokenAddress: string,
estimateGas?: G
): Promise<G extends false ? TransactionReceipt : number> {
if ((await this.getOwner()) !== address) {
throw new Error(`Caller is not Router Owner`)
}
const estGas = await calculateEstimatedGas(
address,
this.contract.methods.addSSContract,
tokenAddress
)
if (estimateGas) return estGas
// Invoke createToken function of the contract
const trxReceipt = await this.contract.methods.addSSContract(tokenAddress).send({
from: address,
gas: estGas + 1,
gasPrice: await this.getFairGasPrice()
})
return trxReceipt
}
/**
* Removes a new contract from ssContract list
* @param {String} address caller address
* @param {String} tokenAddress contract address to removed
* @return {Promise<TransactionReceipt>}
*/
public async removeSSContract<G extends boolean = false>(
address: string,
tokenAddress: string,
estimateGas?: G
): Promise<G extends false ? TransactionReceipt : number> {
if ((await this.getOwner()) !== address) {
throw new Error(`Caller is not Router Owner`)
}
const estGas = await calculateEstimatedGas(
address,
this.contract.methods.removeSSContract,
tokenAddress
)
if (estimateGas) return estGas
// Invoke createToken function of the contract
const trxReceipt = await this.contract.methods.removeSSContract(tokenAddress).send({
from: address,
gas: estGas + 1,
gasPrice: await this.getFairGasPrice()
})
return trxReceipt
}
/**
* Add a new contract to fixedRate list, after is added, can be used when deploying a new pool
* Adds an address to the list of fixed rate contracts
* @param {String} address
* @param {String} tokenAddress contract address to add
* @return {Promise<TransactionReceipt>}
@ -248,7 +170,7 @@ export class Router extends SmartContractWithAddress {
}
/**
* Removes a contract from fixedRate list
* Removes an address from the list of fixed rate contracts
* @param {String} address
* @param {String} tokenAddress contract address to add
* @return {Promise<TransactionReceipt>}
@ -282,7 +204,7 @@ export class Router extends SmartContractWithAddress {
}
/**
* Add a new contract to dispenser list, after is added, can be used when deploying a new pool
* Adds an address to the list of dispensers
* @param {String} address
* @param {String} tokenAddress contract address to add
* @return {Promise<TransactionReceipt>}
@ -316,9 +238,9 @@ export class Router extends SmartContractWithAddress {
}
/**
* Add a new contract to dispenser list, after is added, can be used when deploying a new pool
* Removes an address from the list of dispensers
* @param {String} address
* @param {String} tokenAddress contract address to add
* @param {String} tokenAddress address Contract to be removed
* @return {Promise<TransactionReceipt>}
*/
public async removeDispenserContract<G extends boolean = false>(
@ -364,7 +286,7 @@ export class Router extends SmartContractWithAddress {
}
/**
* Add a new contract to fixedRate list, after is added, can be used when deploying a new pool
* Updates OP Community Fees
* @param {String} address
* @param {number} newSwapOceanFee Amount charged for swapping with ocean approved tokens
* @param {number} newSwapNonOceanFee Amount charged for swapping with non ocean approved tokens
@ -405,70 +327,4 @@ export class Router extends SmartContractWithAddress {
return trxReceipt
}
/**
* Add a new template to poolTemplates mapping, after template is added,it can be used
* @param {String} address
* @param {String} templateAddress template address to add
* @return {Promise<TransactionReceipt>}
*/
public async addPoolTemplate<G extends boolean = false>(
address: string,
templateAddress: string,
estimateGas?: G
): Promise<G extends false ? TransactionReceipt : number> {
if ((await this.getOwner()) !== address) {
throw new Error(`Caller is not Router Owner`)
}
const estGas = await calculateEstimatedGas(
address,
this.contract.methods.addPoolTemplate,
templateAddress
)
if (estimateGas) return estGas
// Invoke createToken function of the contract
const trxReceipt = await this.contract.methods.addPoolTemplate(templateAddress).send({
from: address,
gas: estGas + 1,
gasPrice: await this.getFairGasPrice()
})
return trxReceipt
}
/**
* Remove template from poolTemplates mapping, after template is removed,it can be used anymore
* @param {String} address
* @param {String} templateAddress template address to remove
* @return {Promise<TransactionReceipt>}
*/
public async removePoolTemplate<G extends boolean = false>(
address: string,
templateAddress: string,
estimateGas?: G
): Promise<G extends false ? TransactionReceipt : number> {
if ((await this.getOwner()) !== address) {
throw new Error(`Caller is not Router Owner`)
}
const estGas = await calculateEstimatedGas(
address,
this.contract.methods.removePoolTemplate,
templateAddress
)
if (estimateGas) return estGas
// Invoke createToken function of the contract
const trxReceipt = await this.contract.methods
.removePoolTemplate(templateAddress)
.send({
from: address,
gas: estGas + 1,
gasPrice: await this.getFairGasPrice()
})
return trxReceipt
}
}

View File

@ -2,7 +2,7 @@ import Web3 from 'web3'
import { Contract } from 'web3-eth-contract'
import { AbiItem } from 'web3-utils'
import { Config } from '../config'
import { SmartContract } from '.'
import { SmartContract } from './SmartContract'
export abstract class SmartContractWithAddress extends SmartContract {
public address: string

View File

@ -1,10 +1,8 @@
export * from './SmartContract'
export * from './SmartContractWithAddress'
export * from './factories/NFTFactory'
export * from './pools/Dispenser'
export * from './pools/FixedRateExchange'
export * from './pools/Pool'
export * from './pools/Router'
export * from './pools/SideStaking'
export * from './tokens/Datatoken'
export * from './tokens/NFT'
export * from './Dispenser'
export * from './FixedRateExchange'
export * from './Router'
export * from './Datatoken'
export * from './NFT'
export * from './NFTFactory'

File diff suppressed because it is too large Load Diff

View File

@ -1,267 +0,0 @@
import { AbiItem } from 'web3-utils/types'
import { TransactionReceipt } from 'web3-core'
import SideStakingAbi from '@oceanprotocol/contracts/artifacts/contracts/pools/ssContracts/SideStaking.sol/SideStaking.json'
import { calculateEstimatedGas } from '../../utils'
import { SmartContract } from '..'
export class SideStaking extends SmartContract {
getDefaultAbi(): AbiItem | AbiItem[] {
return SideStakingAbi.abi as AbiItem[]
}
/**
* Get (total vesting amount + token released from the contract when adding liquidity)
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatoken address
* @return {String}
*/
public async getDatatokenCirculatingSupply(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const supply = await sideStaking.methods
.getDatatokenCirculatingSupply(datatokenAddress)
.call()
return supply.toString()
}
/**
* Get actual dts in circulation (vested token withdrawn from the contract +
token released from the contract when adding liquidity)
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatoken address
* @return {String}
*/
public async getDatatokenCurrentCirculatingSupply(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const supply = await sideStaking.methods
.getDatatokenCurrentCirculatingSupply(datatokenAddress)
.call()
return supply.toString()
}
/**
* Get Publisher address
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatoken address
* @return {String}
*/
public async getPublisherAddress(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const address = await sideStaking.methods.getPublisherAddress(datatokenAddress).call()
return address
}
/**
* Get
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @return {String}
*/
public async getBasetoken(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const address = await sideStaking.methods.getBaseTokenAddress(datatokenAddress).call()
return address
}
/**
* Get Pool Address
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @return {String}
*/
public async getPoolAddress(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const address = await sideStaking.methods.getPoolAddress(datatokenAddress).call()
return address
}
/**
* Get baseToken balance in the contract
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @return {String}
*/
public async getBasetokenBalance(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const balance = await sideStaking.methods.getBaseTokenBalance(datatokenAddress).call()
return balance
}
/**
* Get dt balance in the staking contract available for being added as liquidity
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @param {number} tokenDecimals optional number of decimals of the token
* @return {String}
*/
public async getDatatokenBalance(
ssAddress: string,
datatokenAddress: string,
tokenDecimals?: number
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
let balance = await sideStaking.methods.getDatatokenBalance(datatokenAddress).call()
balance = await this.unitsToAmount(datatokenAddress, balance, tokenDecimals)
return balance
}
/**
* Get block when vesting ends
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @return {String} end block for vesting amount
*/
public async getVestingEndBlock(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const block = await sideStaking.methods.getvestingEndBlock(datatokenAddress).call()
return block
}
/**
* Get total amount vesting
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @param {number} tokenDecimals optional number of decimals of the token
* @return {String}
*/
public async getVestingAmount(
ssAddress: string,
datatokenAddress: string,
tokenDecimals?: number
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
let amount = await sideStaking.methods.getvestingAmount(datatokenAddress).call()
amount = await this.unitsToAmount(datatokenAddress, amount, tokenDecimals)
return amount
}
/**
* Get last block publisher got some vested tokens
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @return {String}
*/
public async getVestingLastBlock(
ssAddress: string,
datatokenAddress: string
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const block = await sideStaking.methods.getvestingLastBlock(datatokenAddress).call()
return block
}
/**
* Get how much has been taken from the vesting amount
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @param {number} tokenDecimals optional number of decimals of the token
* @return {String}
*/
public async getVestingAmountSoFar(
ssAddress: string,
datatokenAddress: string,
tokenDecimals?: number
): Promise<string> {
const sideStaking = this.getContract(ssAddress)
let amount = await sideStaking.methods.getvestingAmountSoFar(datatokenAddress).call()
amount = await this.unitsToAmount(datatokenAddress, amount, tokenDecimals)
return amount
}
/** Send vested tokens available to the publisher address, can be called by anyone
*
* @param {String} account
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @return {TransactionReceipt}
*/
public async getVesting<G extends boolean = false>(
account: string,
ssAddress: string,
datatokenAddress: string,
estimateGas?: G
): Promise<G extends false ? TransactionReceipt : number> {
const sideStaking = this.getContract(ssAddress)
const estGas = await calculateEstimatedGas(
account,
sideStaking.methods.getVesting,
datatokenAddress
)
if (estimateGas) return estGas
const vesting = await sideStaking.methods.getVesting(datatokenAddress).send({
from: account,
gas: estGas + 1,
gasPrice: await this.getFairGasPrice()
})
return vesting
}
/** Send vested tokens available to the publisher address, can be called by anyone
*
* @param {String} account
* @param {String} ssAddress side staking contract address
* @param {String} datatokenAddress datatokenAddress
* @return {TransactionReceipt}
*/
public async setPoolSwapFee<G extends boolean = false>(
account: string,
ssAddress: string,
datatokenAddress: string,
poolAddress: string,
swapFee: number,
estimateGas?: G
): Promise<G extends false ? TransactionReceipt : number> {
const sideStaking = this.getContract(ssAddress)
const estGas = await calculateEstimatedGas(
account,
sideStaking.methods.setPoolSwapFee,
datatokenAddress,
poolAddress,
swapFee
)
if (estimateGas) return estGas
const fee = await sideStaking.methods
.setPoolSwapFee(datatokenAddress, poolAddress, swapFee)
.send({
from: account,
gas: estGas + 1,
gasPrice: await this.getFairGasPrice()
})
return fee
}
/**
* Get Router address set in side staking contract
* @param {String} ssAddress side staking contract address
* @return {String}
*/
public async getRouter(ssAddress: string): Promise<string> {
const sideStaking = this.getContract(ssAddress)
const router = await sideStaking.methods.router().call()
return router
}
}

View File

@ -12,7 +12,8 @@ export interface SearchQuery {
}
export class Aquarius {
public aquariusURL
public aquariusURL: string
/**
* Instantiate Aquarius
* @param {String} aquariusURL
@ -31,10 +32,8 @@ export class Aquarius {
try {
const response = await fetch(path, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
if (response.ok) {
@ -68,10 +67,8 @@ export class Aquarius {
const path = this.aquariusURL + '/api/aquarius/assets/ddo/' + did
const response = await fetch(path, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
if (response.ok) {
const ddo = await response.json()
@ -106,10 +103,8 @@ export class Aquarius {
const response = await fetch(path, {
method: 'POST',
body: JSON.stringify(ddo),
headers: {
'Content-Type': 'application/octet-stream'
},
signal: signal
headers: { 'Content-Type': 'application/octet-stream' },
signal
})
jsonResponse = await response.json()

View File

@ -83,10 +83,8 @@ export class Provider {
try {
const response = await fetch(path + `?userAddress=${consumerAddress}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
return (await response.json()).nonce.toString()
} catch (e) {
@ -136,10 +134,8 @@ export class Provider {
const response = await fetch(path, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/octet-stream'
},
signal: signal
headers: { 'Content-Type': 'application/octet-stream' },
signal
})
return await response.text()
} catch (e) {
@ -177,10 +173,8 @@ export class Provider {
const response = await fetch(path, {
method: 'POST',
body: JSON.stringify(args),
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
const results: FileInfo[] = await response.json()
for (const result of results) {
@ -219,10 +213,8 @@ export class Provider {
const response = await fetch(path, {
method: 'POST',
body: JSON.stringify(args),
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
const results: FileInfo[] = await response.json()
for (const result of results) {
@ -252,10 +244,8 @@ export class Provider {
try {
const response = await fetch(path, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
const envs: ComputeEnvironment[] = await response.json()
return envs
@ -307,10 +297,8 @@ export class Provider {
try {
const response = await fetch(initializeUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
const results: ProviderInitialize = await response.json()
return results
@ -346,11 +334,8 @@ export class Provider {
)
const providerData = {
datasets: assets,
algorithm: algorithm,
compute: {
env: computeEnv,
validUntil: validUntil
},
algorithm,
compute: { env: computeEnv, validUntil },
consumerAddress: accountId
}
const initializeUrl = this.getEndpointURL(serviceEndpoints, 'initializeCompute')
@ -361,10 +346,8 @@ export class Provider {
const response = await fetch(initializeUrl, {
method: 'POST',
body: JSON.stringify(providerData),
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
const results = await response.json()
return results
@ -472,10 +455,8 @@ export class Provider {
const response = await fetch(computeStartUrl, {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
if (response?.ok) {
@ -547,10 +528,8 @@ export class Provider {
const response = await fetch(computeStopUrl, {
method: 'PUT',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
if (response?.ok) {
@ -600,10 +579,8 @@ export class Provider {
try {
const response = await fetch(computeStatusUrl + url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
if (response?.ok) {
const params = await response.json()
@ -720,10 +697,8 @@ export class Provider {
const response = await fetch(computeDeleteUrl, {
method: 'DELETE',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
if (response?.ok) {
@ -754,10 +729,8 @@ export class Provider {
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: signal
headers: { 'Content-Type': 'application/json' },
signal
})
if (response?.ok) {
const params = await response.json()

View File

@ -77,11 +77,8 @@ export async function calculateEstimatedGas(
functionToEstimateGas: Function,
...args: any[]
): Promise<any> {
const estimatedGas = await functionToEstimateGas.apply(null, args).estimateGas(
{
from: from
},
(err, estGas) => (err ? GASLIMIT_DEFAULT : estGas)
)
const estimatedGas = await functionToEstimateGas
.apply(null, args)
.estimateGas({ from }, (err, estGas) => (err ? GASLIMIT_DEFAULT : estGas))
return estimatedGas
}

View File

@ -1,9 +0,0 @@
import Decimal from 'decimal.js'
export function calcMaxExactOut(balance: string): Decimal {
return new Decimal(balance).div(2)
}
export function calcMaxExactIn(balance: string): Decimal {
return new Decimal(balance).div(2)
}

View File

@ -6,6 +6,5 @@ export * from './FetchHelper'
export * from './General'
export * from './Logger'
export * from './minAbi'
export * from './PoolHelpers'
export * from './SignatureUtils'
export * from './TokenUtils'

View File

@ -1,15 +1,15 @@
import Web3 from 'web3'
import { AbiItem } from 'web3-utils/types'
import OPFCommunityFeeCollector from '@oceanprotocol/contracts/artifacts/contracts/communityFee/OPFCommunityFeeCollector.sol/OPFCommunityFeeCollector.json'
import PoolTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/balancer/BPool.sol/BPool.json'
import ERC20Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json'
import ERC721Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json'
import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json'
import Router from '@oceanprotocol/contracts/artifacts/contracts/pools/FactoryRouter.sol/FactoryRouter.json'
import SideStaking from '@oceanprotocol/contracts/artifacts/contracts/pools/ssContracts/SideStaking.sol/SideStaking.json'
import FixedRate from '@oceanprotocol/contracts/artifacts/contracts/pools/fixedRate/FixedRateExchange.sol/FixedRateExchange.json'
import Dispenser from '@oceanprotocol/contracts/artifacts/contracts/pools/dispenser/Dispenser.sol/Dispenser.json'
import ERC721Factory from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json'
// delete this once removed from contracts
import PoolTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/balancer/BPool.sol/BPool.json'
import { getAddresses, GAS_PRICE } from './config'
const estimateGasAndDeployContract = async (
@ -48,7 +48,6 @@ const estimateGasAndDeployContract = async (
export interface Addresses {
opfCommunityFeeCollectorAddress: string
poolTemplateAddress: string
datatokenTemplateAddress: string
nftTemplateAddress: string
oceanAddress: string
@ -59,6 +58,7 @@ export interface Addresses {
nftFactoryAddress: string
daiAddress: string
usdcAddress: string
poolTemplateAddress: string
}
export const deployContracts = async (web3: Web3, owner: string): Promise<Addresses> => {
@ -67,7 +67,7 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
// deploy OPF free collector
addresses.opfCommunityFeeCollectorAddress =
configAddresses.OPFCommunityFeeCollector ||
configAddresses?.OPFCommunityFeeCollector ||
(await estimateGasAndDeployContract(
web3,
OPFCommunityFeeCollector.abi as AbiItem[],
@ -76,20 +76,9 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
owner
))
// deploy pool template
addresses.poolTemplateAddress =
configAddresses.poolTemplate ||
(await estimateGasAndDeployContract(
web3,
PoolTemplate.abi as AbiItem[],
PoolTemplate.bytecode,
[],
owner
))
// deploy Datatoken template
addresses.datatokenTemplateAddress =
configAddresses.ERC20Template['1'] ||
configAddresses?.ERC20Template['1'] ||
(await estimateGasAndDeployContract(
web3,
ERC20Template.abi as AbiItem[],
@ -100,7 +89,7 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
// deploy NFT template
addresses.nftTemplateAddress =
configAddresses.ERC721Template['1'] ||
configAddresses?.ERC721Template?.['1'] ||
(await estimateGasAndDeployContract(
web3,
ERC721Template.abi as AbiItem[],
@ -111,7 +100,7 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
// deploy OCEAN mock tocken
addresses.oceanAddress =
configAddresses.Ocean ||
configAddresses?.Ocean ||
(await estimateGasAndDeployContract(
web3,
MockERC20.abi as AbiItem[],
@ -120,9 +109,20 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
owner
))
// deploy pool template to be removed once the pools are removed from contracts
addresses.poolTemplateAddress =
configAddresses?.poolTemplate ||
(await estimateGasAndDeployContract(
web3,
PoolTemplate.abi as AbiItem[],
PoolTemplate.bytecode,
[],
owner
))
// deploy router
addresses.routerAddress =
configAddresses.Router ||
configAddresses?.Router ||
(await estimateGasAndDeployContract(
web3,
Router.abi as AbiItem[],
@ -137,31 +137,20 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
owner
))
// deploy side stacking
addresses.sideStakingAddress =
configAddresses.Staking ||
(await estimateGasAndDeployContract(
web3,
SideStaking.abi as AbiItem[],
SideStaking.bytecode,
[addresses.routerAddress],
owner
))
// deploy fixed rate
addresses.fixedRateAddress =
configAddresses.FixedPrice ||
configAddresses?.FixedPrice ||
(await estimateGasAndDeployContract(
web3,
FixedRate.abi as AbiItem[],
FixedRate.bytecode,
[addresses.routerAddress, addresses.opfCommunityFeeCollectorAddress],
[addresses.routerAddress],
owner
))
// deploy dispenser
addresses.dispenserAddress =
configAddresses.Dispenser ||
configAddresses?.Dispenser ||
(await estimateGasAndDeployContract(
web3,
Dispenser.abi as AbiItem[],
@ -172,7 +161,7 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
// deploy NFT factory
addresses.nftFactoryAddress =
configAddresses.ERC721Factory ||
configAddresses?.ERC721Factory ||
(await estimateGasAndDeployContract(
web3,
ERC721Factory.abi as AbiItem[],
@ -180,7 +169,6 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
[
addresses.nftTemplateAddress,
addresses.datatokenTemplateAddress,
addresses.opfCommunityFeeCollectorAddress,
addresses.routerAddress
],
owner
@ -188,7 +176,7 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
// deploy USDC mock tocken
addresses.usdcAddress =
configAddresses.MockUSDC ||
configAddresses?.MockUSDC ||
(await estimateGasAndDeployContract(
web3,
MockERC20.abi as AbiItem[],
@ -199,7 +187,7 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
// deploy DAI mock tocken
addresses.daiAddress =
configAddresses.MockDAI ||
configAddresses?.MockDAI ||
(await estimateGasAndDeployContract(
web3,
MockERC20.abi as AbiItem[],
@ -208,7 +196,7 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
owner
))
if (!configAddresses.Router) {
if (!configAddresses?.Router) {
const RouterContract = new web3.eth.Contract(
Router.abi as AbiItem[],
addresses.routerAddress
@ -223,13 +211,6 @@ export const deployContracts = async (web3: Web3, owner: string): Promise<Addres
await RouterContract.methods
.addDispenserContract(addresses.dispenserAddress)
.send({ from: owner })
await RouterContract.methods
.addSSContract(addresses.sideStakingAddress)
.send({ from: owner })
// TODO: add OPF deployment
// await RouterContract.methods
// .changeRouterOwner(this.opfCommunityFeeCollectorAddress)
// .send({ from: owner })
}
return addresses

View File

@ -23,9 +23,8 @@
/// 3. [Install dependencies](#-install-dependencies)
/// 4. [Initialize accounts and deploy contracts](#-initialize-accounts-and-deploy-contracts)
/// 5. [Import dependencies and add variables and constants](#-import-dependencies-and-add-variables-and-constants)
/// 6. [Publish Data NFT and a Datatoken with a liquidity pool](#-Publish-data-nft-and-a-datatoken-with-a-liquidity-pool)
/// 7. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange)
/// 8. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser)
/// 6. [Publish Data NFT and a Datatoken with a fixed rate exchange](#-publish-data-nft-and-a-datatoken-with-a-fixed-rate-exchange)
/// 7. [Publish Data NFT and a Datatoken with a dispenser](#-publish-data-nft-and-a-datatoken-with-a-dispenser)
/// ## 0. Prerequisites
/// Before we start it is important that you have all of the necessary prerequisites installed on your computer.
@ -88,7 +87,6 @@
import { assert } from 'chai'
import { SHA256 } from 'crypto-js'
import {
AmountsOutMaxFee,
approve,
Aquarius,
balance,
@ -105,11 +103,8 @@ import {
Nft,
NftCreateData,
NftFactory,
Pool,
PoolCreationParams,
ProviderFees,
ProviderInstance,
TokenInOutMarket,
transfer,
ZERO_ADDRESS
} from '../../src'
@ -130,9 +125,6 @@ describe('Marketplace flow tests', async () => {
let consumerAccount: string
let stakerAccount: string
let addresses: any
let poolNftAddress: string
let poolDatatokenAddress: string
let poolAddress: string
let freNftAddress: string
let freDatatokenAddress: string
let freAddress: string
@ -144,8 +136,6 @@ describe('Marketplace flow tests', async () => {
/// We also define some constants that we will use:
/// ```Typescript
const POOL_NFT_NAME = 'Datatoken 1'
const POOL_NFT_SYMBOL = 'DT1'
const FRE_NFT_NAME = 'Datatoken 2'
const FRE_NFT_SYMBOL = 'DT2'
const DISP_NFT_NAME = 'Datatoken 3'
@ -240,287 +230,9 @@ describe('Marketplace flow tests', async () => {
}) ///
/// ```
/// ## 6. Publish Data NFT and a Datatoken with a liquidity pool
/// ## 6. Publish Data NFT and a Datatoken with a fixed rate exchange
/// 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.
it('6.1 Publish a dataset (create NFT + Datatoken) with a liquidity pool', async () => {
/// ```Typescript
const factory = new NftFactory(addresses.ERC721Factory, web3)
const nftParams: NftCreateData = {
name: POOL_NFT_NAME,
symbol: POOL_NFT_SYMBOL,
templateIndex: 1,
tokenURI: '',
transferable: true,
owner: publisherAccount
}
const datatokenParams: DatatokenCreateParams = {
templateIndex: 1,
cap: '100000',
feeAmount: '0',
paymentCollector: ZERO_ADDRESS,
feeToken: ZERO_ADDRESS,
minter: publisherAccount,
mpFeeAddress: ZERO_ADDRESS
}
const poolParams: PoolCreationParams = {
ssContract: addresses.Staking,
baseTokenAddress: addresses.Ocean,
baseTokenSender: addresses.ERC721Factory,
publisherAddress: publisherAccount,
marketFeeCollector: publisherAccount,
poolTemplateAddress: addresses.poolTemplate,
rate: '1',
baseTokenDecimals: 18,
vestingAmount: '10000',
vestedBlocks: 2500000,
initialBaseTokenLiquidity: '2000',
swapFeeLiquidityProvider: '0.001',
swapFeeMarketRunner: '0.001'
}
/// ```
/// Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 Datatokens
/// ```Typescript
await approve(
web3,
publisherAccount,
addresses.Ocean,
addresses.ERC721Factory,
poolParams.vestingAmount
)
/// ```
/// Now we can make the contract call
/// ```Typescript
const tx = await factory.createNftWithDatatokenWithPool(
publisherAccount,
nftParams,
datatokenParams,
poolParams
)
poolNftAddress = tx.events.NFTCreated.returnValues[0]
poolDatatokenAddress = tx.events.TokenCreated.returnValues[0]
poolAddress = tx.events.NewPool.returnValues[0]
/// ```
/// Now, we did quite a few things there. Let's check that we successfully published a dataset (create NFT + Datatoken) with a liquidity pool
/// ```Typescript
console.log(`Pool NFT address: ${poolNftAddress}`)
console.log(`Pool Datatoken address: ${poolDatatokenAddress}`)
console.log(`Pool address: ${poolAddress}`)
}) ///
/// ```
it('6.2 Set metadata in the pool NFT', async () => {
/// ```Typescript
const nft = new Nft(web3)
/// ```
/// Now we update the ddo and set the right did
/// ```Typescript
DDO.chainId = await web3.eth.getChainId()
DDO.id =
'did:op:' +
SHA256(web3.utils.toChecksumAddress(poolNftAddress) + DDO.chainId.toString(10))
DDO.nftAddress = poolNftAddress
/// ```
/// Next we encrypt the file or files using Ocean Provider. The provider is an off chain proxy built specifically for this task
/// ```Typescript
ASSET_URL.datatokenAddress = poolDatatokenAddress
ASSET_URL.nftAddress = poolNftAddress
const encryptedFiles = await ProviderInstance.encrypt(ASSET_URL, providerUrl)
DDO.services[0].files = await encryptedFiles
DDO.services[0].datatokenAddress = poolDatatokenAddress
/// ```
/// Now let's console log the result to check everything is working
/// ```Typescript
console.log(`DID: ${DDO.id}`)
const providerResponse = await ProviderInstance.encrypt(DDO, providerUrl)
const encryptedDDO = await providerResponse
const metadataHash = getHash(JSON.stringify(DDO))
await nft.setMetadata(
poolNftAddress,
publisherAccount,
0,
providerUrl,
'',
'0x2',
encryptedDDO,
'0x' + metadataHash
)
}) ///
/// ```
it('6.3 User should add liquidity to the pool, receiving LP tokens', async () => {
/// ```Typescript
const pool = new Pool(web3)
/// ```
/// Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 Datatokens
/// ```Typescript
await approve(web3, stakerAccount, addresses.Ocean, poolAddress, '5', true)
/// ```
/// Now we can make the contract call
/// ```Typescript
await pool.joinswapExternAmountIn(stakerAccount, poolAddress, '5', '0.1')
}) ///
/// ```
it('6.4 Marketplace displays pool asset for sale', async () => {
/// ```Typescript
const pool = new Pool(web3)
const prices = await pool.getAmountInExactOut(
poolAddress,
poolDatatokenAddress,
addresses.Ocean,
'1',
'0.01'
)
/// ```
/// Now let's console log the result to check everything is working
/// ```Typescript
console.log(`Price of 1 ${POOL_NFT_SYMBOL} is ${prices.tokenAmount} OCEAN`)
}) ///
/// ```
it('6.5 Consumer buys a pool data asset, and downloads it', async () => {
/// ```Typescript
const datatoken = new Datatoken(web3)
const consumerETHBalance = await web3.eth.getBalance(consumerAccount)
/// ```
/// Now let's console log the result to check everything is working
/// ```Typescript
console.log(`Consumer ETH balance: ${consumerETHBalance}`)
let consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
/// ```
/// Now let's console log consumerOCEANBalance to check everything is working
/// ```Typescript
console.log(`Consumer OCEAN balance before swap: ${consumerOCEANBalance}`)
let consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
/// ```
/// Now let's console log POOL_NFT_SYMBOL and consumerDTBalance to check everything is working
/// ```Typescript
console.log(`Consumer ${POOL_NFT_SYMBOL} balance before swap: ${consumerDTBalance}`)
/// ```
/// Before we call the contract we have to call `approve` so that the contract can move our tokens. This is standard when using any ERC20 Datatokens
/// ```Typescript
await approve(web3, consumerAccount, addresses.Ocean, poolAddress, '100')
const pool = new Pool(web3)
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: addresses.Ocean,
tokenOut: poolDatatokenAddress,
marketFeeAddress: consumerAccount
}
const amountsInOutMaxFee: AmountsOutMaxFee = {
maxAmountIn: '10',
tokenAmountOut: '1',
swapMarketFee: '0.1'
}
/// ```
/// Now we can make the contract call
/// ```Typescript
await pool.swapExactAmountOut(
consumerAccount,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
/// ```
/// Now let's console log the Consumer OCEAN balance after swap to check everything is working
/// ```Typescript
console.log(`Consumer OCEAN balance after swap: ${consumerOCEANBalance}`)
consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
/// ```
/// Next let's console log the POOL_NFT_SYMBOL and consumerDTBalance
/// ```Typescript
console.log(`Consumer ${POOL_NFT_SYMBOL} balance after swap: ${consumerDTBalance}`)
const resolvedDDO = await aquarius.waitForAqua(DDO.id)
assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
/// ```
/// The next step is to initialize the provider instance
/// ```Typescript
const initializeData = await ProviderInstance.initialize(
resolvedDDO.id,
resolvedDDO.services[0].id,
0,
consumerAccount,
providerUrl
)
const providerFees: ProviderFees = {
providerFeeAddress: initializeData.providerFee.providerFeeAddress,
providerFeeToken: initializeData.providerFee.providerFeeToken,
providerFeeAmount: initializeData.providerFee.providerFeeAmount,
v: initializeData.providerFee.v,
r: initializeData.providerFee.r,
s: initializeData.providerFee.s,
providerData: initializeData.providerFee.providerData,
validUntil: initializeData.providerFee.validUntil
}
/// ```
/// Now let's make a payment
/// ```Typescript
const tx = await datatoken.startOrder(
poolDatatokenAddress,
consumerAccount,
consumerAccount,
0,
providerFees
)
/// ```
/// Next up, let's get the URL
/// ```Typescript
const downloadURL = await ProviderInstance.getDownloadUrl(
DDO.id,
consumerAccount,
DDO.services[0].id,
0,
tx.transactionHash,
providerUrl,
web3
)
/// ```
/// Now let's console log the Download URL to check everything is working
/// ```Typescript
console.log(`Download URL: ${downloadURL}`)
consumerOCEANBalance = await balance(web3, addresses.Ocean, consumerAccount)
console.log(`Consumer OCEAN balance after order: ${consumerOCEANBalance}`)
consumerDTBalance = await balance(web3, poolDatatokenAddress, consumerAccount)
/// ```
/// Now let's console log the Consumer balance after order to check everything is working
/// ```Typescript
console.log(`Consumer ${POOL_NFT_SYMBOL} balance after order: ${consumerDTBalance}`)
try {
const fileData = await downloadFile(downloadURL)
console.log(fileData)
} catch (e) {
assert.fail('Download failed')
}
}) ///
/// ```
/// ## 7. Publish Data NFT and a Datatoken with a fixed rate exchange
it('7.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange', async () => {
it('6.1 Publish a dataset (create NFT + Datatoken) with a fixed rate exchange', async () => {
/// ```Typescript
const factory = new NftFactory(addresses.ERC721Factory, web3)
@ -578,7 +290,7 @@ describe('Marketplace flow tests', async () => {
}) ///
/// ```
it('7.2 Set metadata in the fixed rate exchange NFT', async () => {
it('6.2 Set metadata in the fixed rate exchange NFT', async () => {
/// ```Typescript
const nft = new Nft(web3)
@ -621,7 +333,7 @@ describe('Marketplace flow tests', async () => {
})
/// ```
it('7.3 Marketplace displays fixed rate asset for sale', async () => {
it('6.3 Marketplace displays fixed rate asset for sale', async () => {
/// ```Typescript
const fixedRate = new FixedRateExchange(freAddress, web3)
const oceanAmount = await (
@ -634,7 +346,7 @@ describe('Marketplace flow tests', async () => {
}) ///
/// ```
it('7.4 Consumer buys a fixed rate asset data asset, and downloads it', async () => {
it('6.4 Consumer buys a fixed rate asset data asset, and downloads it', async () => {
/// ```Typescript
const datatoken = new Datatoken(web3)
const DATATOKEN_AMOUNT = '10000'
@ -742,9 +454,9 @@ describe('Marketplace flow tests', async () => {
}) ///
/// ```
/// ## 8. Publish Data NFT and a Datatoken with a dispenser
/// ## 7. Publish Data NFT and a Datatoken with a dispenser
it('8.1 Publish a dataset (create NFT + Datatoken) with a dispenser', async () => {
it('7.1 Publish a dataset (create NFT + Datatoken) with a dispenser', async () => {
/// ```Typescript
const factory = new NftFactory(addresses.ERC721Factory, web3)
@ -794,7 +506,7 @@ describe('Marketplace flow tests', async () => {
}) ///
/// ```
it('8.2 Set metadata in the dispenser NFT', async () => {
it('7.2 Set metadata in the dispenser NFT', async () => {
/// ```Typescript
const nft = new Nft(web3)
@ -834,7 +546,7 @@ describe('Marketplace flow tests', async () => {
}) ///
/// ```
it('8.3 Consumer gets a dispenser data asset, and downloads it', async () => {
it('7.3 Consumer gets a dispenser data asset, and downloads it', async () => {
/// ```Typescript
const datatoken = new Datatoken(web3)
const dispenser = new Dispenser(addresses.Dispenser, web3)

View File

@ -248,12 +248,12 @@ async function createAsset(
const chain = await web3.eth.getChainId()
ddo.chainId = parseInt(chain.toString(10))
const nftParamsAsset: NftCreateData = {
name: name,
symbol: symbol,
name,
symbol,
templateIndex: 1,
tokenURI: 'aaa',
transferable: true,
owner: owner
owner
}
const datatokenParams: DatatokenCreateParams = {
templateIndex: 1,

View File

@ -16,7 +16,6 @@ import {
ValidateMetadata,
DDO,
DatatokenCreateParams,
PoolCreationParams,
FreCreationParams,
DispenserCreationParams,
Files
@ -100,91 +99,6 @@ describe('Publish tests', async () => {
)
})
it('should publish a dataset with pool (create NFT + Datatoken + pool) and with Metdata proof', async () => {
const poolDdo: DDO = { ...genericAsset }
const nftParams: NftCreateData = {
name: 'testNftPool',
symbol: 'TSTP',
templateIndex: 1,
tokenURI: '',
transferable: true,
owner: publisherAccount
}
const datatokenParams: DatatokenCreateParams = {
templateIndex: 1,
cap: '100000',
feeAmount: '0',
paymentCollector: ZERO_ADDRESS,
feeToken: ZERO_ADDRESS,
minter: publisherAccount,
mpFeeAddress: ZERO_ADDRESS
}
const poolParams: PoolCreationParams = {
ssContract: addresses.Staking,
baseTokenAddress: addresses.MockDAI,
baseTokenSender: addresses.ERC721Factory,
publisherAddress: publisherAccount,
marketFeeCollector: publisherAccount,
poolTemplateAddress: addresses.poolTemplate,
rate: '1',
baseTokenDecimals: 18,
vestingAmount: '10000',
vestedBlocks: 2500000,
initialBaseTokenLiquidity: '2000',
swapFeeLiquidityProvider: '0.001',
swapFeeMarketRunner: '0.001'
}
const bundleNFT = await factory.createNftWithDatatokenWithPool(
publisherAccount,
nftParams,
datatokenParams,
poolParams
)
const nftAddress = bundleNFT.events.NFTCreated.returnValues[0]
const datatokenAddress = bundleNFT.events.TokenCreated.returnValues[0]
assetUrl.datatokenAddress = datatokenAddress
assetUrl.nftAddress = nftAddress
const encryptedFiles = await ProviderInstance.encrypt(assetUrl, providerUrl)
poolDdo.metadata.name = 'test-dataset-pool'
poolDdo.services[0].files = await encryptedFiles
poolDdo.services[0].datatokenAddress = datatokenAddress
poolDdo.nftAddress = nftAddress
const chain = await web3.eth.getChainId()
poolDdo.chainId = chain
poolDdo.id =
'did:op:' + SHA256(web3.utils.toChecksumAddress(nftAddress) + chain.toString(10))
const AssetValidation: ValidateMetadata = await aquarius.validate(poolDdo)
assert(AssetValidation.valid === true, 'Published asset is not valid')
const encryptedDdo = await ProviderInstance.encrypt(poolDdo, providerUrl)
const encryptedResponse = await encryptedDdo
const metadataHash = getHash(JSON.stringify(poolDdo))
// just to make sure that our hash matches one computed by aquarius
assert(AssetValidation.hash === '0x' + metadataHash, 'Metadata hash is a missmatch')
await nft.setMetadata(
nftAddress,
publisherAccount,
0,
providerUrl,
'',
'0x2',
encryptedResponse,
'0x' + metadataHash,
[AssetValidation.proof]
)
const resolvedDDO = await aquarius.waitForAqua(poolDdo.id)
assert(resolvedDDO, 'Cannot fetch DDO from Aquarius')
})
it('should publish a dataset with fixed price (create NFT + Datoken + fixed price) with an explicit empty Metadata Proof', async () => {
const fixedPriceDdo: DDO = { ...genericAsset }

View File

@ -1,6 +1,6 @@
import { assert } from 'chai'
import { deployContracts, Addresses } from '../../TestContractHandler'
import { web3 } from '../../config'
import { deployContracts, Addresses } from '../TestContractHandler'
import { web3 } from '../config'
import {
NftFactory,
NftCreateData,
@ -10,8 +10,8 @@ import {
DispenserParams,
ZERO_ADDRESS,
signHash
} from '../../../src'
import { ProviderFees, FreCreationParams, FreOrderParams } from '../../../src/@types'
} from '../../src'
import { ProviderFees, FreCreationParams, FreOrderParams } from '../../src/@types'
describe('Datatoken', () => {
let nftOwner: string
@ -335,11 +335,11 @@ describe('Datatoken', () => {
const { v, r, s } = await signHash(web3, message, user3)
const providerFees: ProviderFees = {
providerFeeAddress: user3,
providerFeeToken: providerFeeToken,
providerFeeAmount: providerFeeAmount,
v: v,
r: r,
s: s,
providerFeeToken,
providerFeeAmount,
v,
r,
s,
providerData: web3.utils.toHex(web3.utils.asciiToHex(providerData)),
validUntil: providerValidUntil
}
@ -380,11 +380,11 @@ describe('Datatoken', () => {
const { v, r, s } = await signHash(web3, message, user3)
const providerFees: ProviderFees = {
providerFeeAddress: user3,
providerFeeToken: providerFeeToken,
providerFeeAmount: providerFeeAmount,
v: v,
r: r,
s: s,
providerFeeToken,
providerFeeAmount,
v,
r,
s,
providerData: web3.utils.toHex(web3.utils.asciiToHex(providerData)),
validUntil: providerValidUntil
}
@ -420,11 +420,11 @@ describe('Datatoken', () => {
const providerValidUntil = '0'
const providerFees: ProviderFees = {
providerFeeAddress: user3,
providerFeeToken: providerFeeToken,
providerFeeAmount: providerFeeAmount,
v: v,
r: r,
s: s,
providerFeeToken,
providerFeeAmount,
v,
r,
s,
providerData: web3.utils.toHex(web3.utils.asciiToHex(providerData)),
validUntil: providerValidUntil
}
@ -462,11 +462,11 @@ describe('Datatoken', () => {
const providerValidUntil = '0'
const providerFees: ProviderFees = {
providerFeeAddress: user1,
providerFeeToken: providerFeeToken,
providerFeeAmount: providerFeeAmount,
v: v,
r: r,
s: s,
providerFeeToken,
providerFeeAmount,
v,
r,
s,
providerData: web3.utils.toHex(web3.utils.asciiToHex(providerData)),
validUntil: providerValidUntil
}
@ -484,7 +484,7 @@ describe('Datatoken', () => {
const fre: FreOrderParams = {
exchangeContract: fixedRateAddress,
exchangeId: exchangeId,
exchangeId,
maxBaseTokenAmount: '1',
baseTokenAddress: contracts.daiAddress,
baseTokenDecimals: 18,

View File

@ -1,6 +1,6 @@
import { assert, expect } from 'chai'
import { deployContracts, Addresses } from '../../../TestContractHandler'
import { web3 } from '../../../config'
import { deployContracts, Addresses } from '../TestContractHandler'
import { web3 } from '../config'
import {
NftFactory,
NftCreateData,
@ -8,8 +8,8 @@ import {
DispenserParams,
Dispenser,
ZERO_ADDRESS
} from '../../../../src/'
import { DatatokenCreateParams } from '../../../../src/@types'
} from '../../src/'
import { DatatokenCreateParams } from '../../src/@types'
describe('Dispenser flow', () => {
let factoryOwner: string

View File

@ -1,7 +1,7 @@
import { assert, expect } from 'chai'
import BigNumber from 'bignumber.js'
import { deployContracts, Addresses } from '../../../TestContractHandler'
import { web3 } from '../../../config'
import { deployContracts, Addresses } from '../TestContractHandler'
import { web3 } from '../config'
import {
NftFactory,
NftCreateData,
@ -12,8 +12,8 @@ import {
balance,
unitsToAmount,
Datatoken
} from '../../../../src'
import { FreCreationParams, DatatokenCreateParams } from '../../../../src/@types'
} from '../../src'
import { FreCreationParams, DatatokenCreateParams } from '../../src/@types'
describe('Fixed Rate unit test', () => {
let factoryOwner: string

View File

@ -1,9 +1,9 @@
import { assert } from 'chai'
import { deployContracts, Addresses } from '../../TestContractHandler'
import { deployContracts, Addresses } from '../TestContractHandler'
import sha256 from 'crypto-js/sha256'
import { web3 } from '../../config'
import { NftFactory, NftCreateData, Nft, ZERO_ADDRESS } from '../../../src'
import { MetadataAndTokenURI } from '../../../src/@types'
import { web3 } from '../config'
import { NftFactory, NftCreateData, Nft, ZERO_ADDRESS } from '../../src'
import { MetadataAndTokenURI } from '../../src/@types'
describe('NFT', () => {
let nftOwner: string

View File

@ -1,6 +1,6 @@
import { assert, expect } from 'chai'
import { deployContracts, Addresses } from '../../TestContractHandler'
import { web3 } from '../../config'
import { deployContracts, Addresses } from '../TestContractHandler'
import { web3 } from '../config'
import {
NftFactory,
NftCreateData,
@ -12,13 +12,8 @@ import {
approve,
balance,
Datatoken
} from '../../../src'
import {
ProviderFees,
FreCreationParams,
DatatokenCreateParams,
PoolCreationParams
} from '../../../src/@types'
} from '../../src'
import { ProviderFees, FreCreationParams, DatatokenCreateParams } from '../../src/@types'
describe('Nft Factory test', () => {
let factoryOwner: string
@ -126,53 +121,6 @@ describe('Nft Factory test', () => {
expect((await nftFactory.getCurrentTokenCount()) === currentTokenCount + 1)
})
it('#createNftErcWithPool- should create an NFT, a Datatoken and a pool DT/DAI', async () => {
// we prepare transaction parameters objects
const poolParams: PoolCreationParams = {
ssContract: contracts.sideStakingAddress,
baseTokenAddress: contracts.daiAddress,
baseTokenSender: contracts.nftFactoryAddress,
publisherAddress: nftOwner,
marketFeeCollector: nftOwner,
poolTemplateAddress: contracts.poolTemplateAddress,
rate: '1',
baseTokenDecimals: 18,
vestingAmount: '10000',
vestedBlocks: 2500000,
initialBaseTokenLiquidity: '2000',
swapFeeLiquidityProvider: FEE,
swapFeeMarketRunner: FEE
}
await transfer(
web3,
factoryOwner,
contracts.daiAddress,
nftOwner,
poolParams.vestingAmount
)
await approve(
web3,
nftOwner,
contracts.daiAddress,
contracts.nftFactoryAddress,
poolParams.vestingAmount
)
const txReceipt = await nftFactory.createNftWithDatatokenWithPool(
nftOwner,
nftData,
dtParams,
poolParams
)
// events have been emitted
expect(txReceipt.events.NFTCreated.event === 'NFTCreated')
expect(txReceipt.events.TokenCreated.event === 'TokenCreated')
expect(txReceipt.events.NewPool.event === 'NewPool')
})
it('#createNftErcWithFixedRate- should create an NFT, a datatoken and create a Fixed Rate Exchange', async () => {
// we prepare transaction parameters objects
const freParams: FreCreationParams = {
@ -275,9 +223,9 @@ describe('Nft Factory test', () => {
providerFeeAddress: consumeFeeAddress,
providerFeeToken: consumeFeeToken,
providerFeeAmount: consumeFeeAmount,
v: v,
r: r,
s: s,
v,
r,
s,
providerData: web3.utils.toHex(web3.utils.asciiToHex(providerData)),
validUntil: providerValidUntil
}
@ -289,15 +237,15 @@ describe('Nft Factory test', () => {
const orders: TokenOrder[] = [
{
tokenAddress: dtAddress,
consumer: consumer,
serviceIndex: serviceIndex,
consumer,
serviceIndex,
_providerFee: providerFees,
_consumeMarketFee: consumeMarketFee
},
{
tokenAddress: dtAddress2,
consumer: consumer,
serviceIndex: serviceIndex,
consumer,
serviceIndex,
_providerFee: providerFees,
_consumeMarketFee: consumeMarketFee
}

View File

@ -1,6 +1,8 @@
import { assert, expect } from 'chai'
import { deployContracts, Addresses } from '../../TestContractHandler'
import { web3 } from '../../config'
import { AbiItem } from 'web3-utils/types'
import { deployContracts, Addresses } from '../TestContractHandler'
import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json'
import { web3 } from '../config'
import {
NftFactory,
NftCreateData,
@ -8,9 +10,9 @@ import {
balance,
approve,
ZERO_ADDRESS,
transfer
} from '../../../src'
import { DatatokenCreateParams, PoolCreationParams, Operation } from '../../../src/@types'
Datatoken
} from '../../src'
import { DatatokenCreateParams, FreCreationParams, Operation } from '../../src/@types'
const { keccak256 } = require('@ethersproject/keccak256')
@ -26,16 +28,12 @@ describe('Router unit test', () => {
const NFT_TOKEN_URI = 'https://oceanprotocol.com/nft/'
const DATATOKEN_NAME = 'ERC20B1'
const DATATOKEN_SYMBOL = 'ERC20DT1Symbol'
const DATATOKEN_AMMOUNT = '1000'
const RATE = '1'
const FEE = '0.001'
const FEE_ZERO = '0'
const DAI_AMOUNT = '2' // 2 DAI
const DAI_AMOUNT = '100' // 100 DAI
const CAP_AMOUNT = '1000000'
const VESTING_AMOUNT = '10000'
const TOKEN_DECIMALS = 18
const VESTED_BLOCKS = 2500000
const BASE_TOKEN_LIQUIDITY = '2000'
const EXCHANGE_IDS = keccak256('0x00')
const AMOUNTS_IN = web3.utils.toWei('1')
const AMOUNTS_OUT = web3.utils.toWei('0.1')
const MAX_PRICE = web3.utils.toWei('10')
@ -82,7 +80,7 @@ describe('Router unit test', () => {
factoryOwner,
contracts.daiAddress,
contracts.nftFactoryAddress,
web3.utils.toWei('10000')
web3.utils.toWei('100000')
)
})
@ -105,65 +103,85 @@ describe('Router unit test', () => {
expect(await router.isApprovedToken(contracts.daiAddress)).to.equal(false)
})
it('#isSideStaking - should return true if in ssContracts list', async () => {
expect(await router.isSideStaking(contracts.sideStakingAddress)).to.equal(true)
expect(await router.isSideStaking(contracts.fixedRateAddress)).to.equal(false)
})
it('#isFixedPrice - should return true if in fixedPrice list', async () => {
expect(await router.isFixedPrice(contracts.fixedRateAddress)).to.equal(true)
expect(await router.isFixedPrice(contracts.daiAddress)).to.equal(false)
})
it('#isPoolTemplate - should return true if in poolTemplates list', async () => {
expect(await router.isPoolTemplate(contracts.poolTemplateAddress)).to.equal(true)
expect(await router.isPoolTemplate(contracts.fixedRateAddress)).to.equal(false)
})
it('#buyDatatokenBatch - should buy multiple DT in one call', async () => {
// APPROVE DAI
await transfer(web3, factoryOwner, contracts.daiAddress, user1, DAI_AMOUNT)
const daiContract = new web3.eth.Contract(
MockERC20.abi as AbiItem[],
contracts.daiAddress
)
await daiContract.methods
.transfer(user1, web3.utils.toWei(DAI_AMOUNT))
.send({ from: factoryOwner })
await approve(web3, user1, contracts.daiAddress, contracts.routerAddress, DAI_AMOUNT)
// CREATE A FIRST POOL
const poolParams: PoolCreationParams = {
ssContract: contracts.sideStakingAddress,
// CREATE A FIRST FRE
const freParams: FreCreationParams = {
fixedRateAddress: contracts.fixedRateAddress,
baseTokenAddress: contracts.daiAddress,
baseTokenSender: contracts.nftFactoryAddress,
publisherAddress: factoryOwner,
marketFeeCollector: factoryOwner,
poolTemplateAddress: contracts.poolTemplateAddress,
rate: RATE,
baseTokenDecimals: TOKEN_DECIMALS,
vestingAmount: VESTING_AMOUNT,
vestedBlocks: VESTED_BLOCKS,
initialBaseTokenLiquidity: BASE_TOKEN_LIQUIDITY,
swapFeeLiquidityProvider: FEE,
swapFeeMarketRunner: FEE
owner: factoryOwner,
marketFeeCollector: user2,
baseTokenDecimals: 18,
datatokenDecimals: 18,
fixedRate: RATE,
marketFee: FEE,
allowedConsumer: ZERO_ADDRESS,
withMint: false
}
const nftFactory = new NftFactory(contracts.nftFactoryAddress, web3)
const txReceipt = await nftFactory.createNftWithDatatokenWithPool(
const txReceipt = await nftFactory.createNftWithDatatokenWithFixedRate(
factoryOwner,
NFT_DATA,
ERC_PARAMS,
poolParams
freParams
)
const datatokenAddress = txReceipt.events.TokenCreated.returnValues.newTokenAddress
const pool1 = txReceipt.events.NewPool.returnValues.poolAddress
// CREATE A SECOND POOL
const txReceipt2 = await nftFactory.createNftWithDatatokenWithPool(
const fre1 = txReceipt.events.NewFixedRate.returnValues.exchangeContract
const freId1 = txReceipt.events.NewFixedRate.returnValues.exchangeId
const datatoken = new Datatoken(web3)
await datatoken.mint(datatokenAddress, factoryOwner, '1000', factoryOwner)
await approve(
web3,
factoryOwner,
datatokenAddress,
contracts.fixedRateAddress,
DATATOKEN_AMMOUNT
)
// CREATE A SECOND FRE
const txReceipt2 = await nftFactory.createNftWithDatatokenWithFixedRate(
factoryOwner,
NFT_DATA,
ERC_PARAMS,
poolParams
freParams
)
const datatoken2Address = txReceipt2.events.TokenCreated.returnValues.newTokenAddress
const pool2 = txReceipt2.events.NewPool.returnValues.poolAddress
const fre2 = txReceipt2.events.NewFixedRate.returnValues.exchangeContract
const freId2 = txReceipt2.events.NewFixedRate.returnValues.exchangeId
await datatoken.mint(datatoken2Address, factoryOwner, '1000', factoryOwner)
await approve(
web3,
factoryOwner,
datatoken2Address,
contracts.fixedRateAddress,
DATATOKEN_AMMOUNT
)
// user1 has no dt1
expect(await balance(web3, datatokenAddress, user1)).to.equal('0')
@ -171,15 +189,14 @@ describe('Router unit test', () => {
expect(await balance(web3, datatoken2Address, user1)).to.equal('0')
// we now can prepare the Operations objects
// operation: 0 - swapExactAmountIn
// 1 - swapExactAmountOut
// 2 - FixedRateExchange
// 3 - Dispenser
const operations1: Operation = {
exchangeIds: EXCHANGE_IDS, // used only for FixedRate or Dispenser, but needs to be filled even for pool
source: pool1, // pool Address
operation: 0, // swapExactAmountIn
exchangeIds: freId1, // used only for FixedRate or Dispenser, but needs to be filled even for pool
source: fre1, // pool Address
operation: 2, // swapExactAmountIn
tokenIn: contracts.daiAddress,
amountsIn: AMOUNTS_IN, // when swapExactAmountIn is EXACT amount IN
tokenOut: datatokenAddress,
@ -190,12 +207,12 @@ describe('Router unit test', () => {
}
const operations2: Operation = {
exchangeIds: EXCHANGE_IDS, // used only for FixedRate or Dispenser, but needs to be filled even for pool
source: pool2, // pool Address
operation: 0, // swapExactAmountIn
exchangeIds: freId2, // used only for FixedRate or Dispenser, but needs to be filled even for pool
source: fre2, // pool Address
operation: 2, // swapExactAmountIn
tokenIn: contracts.daiAddress,
amountsIn: AMOUNTS_IN, // when swapExactAmountIn is EXACT amount IN
tokenOut: datatoken2Address,
tokenOut: datatokenAddress,
amountsOut: AMOUNTS_OUT, // when swapExactAmountIn is MIN amount OUT
maxPrice: MAX_PRICE, // max price (only for pools),
swapMarketFee: SWAP_MARKET_FEE,

View File

@ -1,949 +0,0 @@
import { assert, expect } from 'chai'
import { deployContracts, Addresses } from '../../../TestContractHandler'
import { web3 } from '../../../config'
import {
allowance,
approve,
NftFactory,
NftCreateData,
Pool,
unitsToAmount,
ZERO_ADDRESS,
balance,
transfer,
decimals
} from '../../../../src'
import {
PoolCreationParams,
DatatokenCreateParams,
CurrentFees,
TokenInOutMarket,
AmountsInMaxFee,
AmountsOutMaxFee
} from '../../../../src/@types'
describe('Pool unit test', () => {
let factoryOwner: string
let user1: string
let user2: string
let contracts: Addresses
let pool: Pool
let poolAddress: string
let datatoken: string
let dtParams: DatatokenCreateParams
const nftData: NftCreateData = {
name: '72120Bundle',
symbol: '72Bundle',
templateIndex: 1,
tokenURI: 'https://oceanprotocol.com/nft/',
transferable: true,
owner: null
}
before(async () => {
const accounts = await web3.eth.getAccounts()
factoryOwner = accounts[0]
user1 = accounts[3]
user2 = accounts[4]
nftData.owner = factoryOwner
dtParams = {
templateIndex: 1,
minter: factoryOwner,
paymentCollector: user2,
mpFeeAddress: factoryOwner,
feeToken: ZERO_ADDRESS,
cap: '1000000',
feeAmount: '0',
name: 'ERC20B1',
symbol: 'ERC20DT1Symbol'
}
})
it('should deploy contracts', async () => {
contracts = await deployContracts(web3, factoryOwner)
// initialize Pool instance
pool = new Pool(web3, 8996)
assert(pool != null)
await approve(
web3,
factoryOwner,
contracts.daiAddress,
contracts.nftFactoryAddress,
'2000'
)
assert(
parseInt(
await allowance(
web3,
contracts.daiAddress,
factoryOwner,
contracts.nftFactoryAddress
)
) >= 2000
)
await approve(
web3,
factoryOwner,
contracts.usdcAddress,
contracts.nftFactoryAddress,
'10000'
)
assert(
parseInt(
await allowance(
web3,
contracts.usdcAddress,
factoryOwner,
contracts.nftFactoryAddress
)
) >= 10000
)
})
describe('Test a pool with DAI (18 Decimals)', () => {
it('#create a pool', async () => {
// CREATE A POOL
// we prepare transaction parameters objects
const poolParams: PoolCreationParams = {
ssContract: contracts.sideStakingAddress,
baseTokenAddress: contracts.daiAddress,
baseTokenSender: contracts.nftFactoryAddress,
publisherAddress: factoryOwner,
marketFeeCollector: factoryOwner,
poolTemplateAddress: contracts.poolTemplateAddress,
rate: '1',
baseTokenDecimals: 18,
vestingAmount: '10000',
vestedBlocks: 2500000,
initialBaseTokenLiquidity: '2000',
swapFeeLiquidityProvider: '0.001',
swapFeeMarketRunner: '0.001'
}
const nftFactory = new NftFactory(contracts.nftFactoryAddress, web3, 8996)
const txReceipt = await nftFactory.createNftWithDatatokenWithPool(
factoryOwner,
nftData,
dtParams,
poolParams
)
datatoken = txReceipt.events.TokenCreated.returnValues.newTokenAddress
poolAddress = txReceipt.events.NewPool.returnValues.poolAddress
// user1 has no dt1
expect(await balance(web3, datatoken, user1)).to.equal('0')
})
it('#sharesBalance - should return user shares balance (datatoken balance, LPT balance, etc) ', async () => {
expect(await balance(web3, contracts.daiAddress, user1)).to.equal(
web3.utils.toWei(await pool.sharesBalance(user1, contracts.daiAddress))
)
})
it('#getNumTokens - should return num of tokens in pool (2)', async () => {
expect(await pool.getNumTokens(poolAddress)).to.equal('2')
})
it('#getPoolSharesTotalSupply - should return totalSupply of LPT', async () => {
// dt owner which added liquidity has half of pool shares (the rest is in the sidestaking contracta)
const dtOwnerLPTBalance = await pool.sharesBalance(factoryOwner, poolAddress)
expect(await pool.sharesBalance(factoryOwner, poolAddress)).to.equal(
await pool.sharesBalance(contracts.sideStakingAddress, poolAddress)
)
// total supply is twice the dtOwner balance
expect(await pool.getPoolSharesTotalSupply(poolAddress)).to.equal(
(2 * Number(dtOwnerLPTBalance)).toString()
)
})
it('#getCurrentTokens - should return current pool tokens', async () => {
const currentTokens = await pool.getCurrentTokens(poolAddress)
expect(currentTokens[0]).to.equal(datatoken)
expect(currentTokens[1]).to.equal(contracts.daiAddress)
})
it('#getFinalTokens - should return final pool tokens', async () => {
const finalTokens = await pool.getFinalTokens(poolAddress)
expect(finalTokens[0]).to.equal(datatoken)
expect(finalTokens[1]).to.equal(contracts.daiAddress)
})
it('#getController - should return the pool controller (sideStaking address)', async () => {
expect(await pool.getController(poolAddress)).to.equal(contracts.sideStakingAddress)
})
it('#isBound - should return true if token is bound into the pool', async () => {
expect(await pool.isBound(poolAddress, contracts.daiAddress)).to.equal(true)
expect(await pool.isBound(poolAddress, contracts.oceanAddress)).to.equal(false)
})
it('#getReserve - should return final pool tokens', async () => {
expect(await pool.getReserve(poolAddress, contracts.daiAddress)).to.equal('2000') // baseToken initial liquidity
// rate is 1 so we have the same amount of DTs
expect(await pool.getReserve(poolAddress, datatoken)).to.equal('2000')
})
it('#isFinalized - should return true if pool is finalized', async () => {
expect(await pool.isFinalized(poolAddress)).to.equal(true)
})
it('#getSwapFee - should return the swap fee', async () => {
expect(await pool.getSwapFee(poolAddress)).to.equal('0.001') // 0.1%
})
it('#getNormalizedWeight - should return the normalized weight', async () => {
expect(await pool.getNormalizedWeight(poolAddress, contracts.daiAddress)).to.equal(
'0.5'
)
expect(await pool.getNormalizedWeight(poolAddress, datatoken)).to.equal('0.5')
})
it('#getDenormalizedWeight - should return the denormalized weight', async () => {
expect(
await pool.getDenormalizedWeight(poolAddress, contracts.daiAddress)
).to.equal('5')
expect(await pool.getDenormalizedWeight(poolAddress, datatoken)).to.equal('5')
})
it('#getBasetoken - should return the baseToken address', async () => {
expect(await pool.getBasetoken(poolAddress)).to.equal(contracts.daiAddress)
})
it('#getDatatoken - should return the datatoken address', async () => {
expect(await pool.getDatatoken(poolAddress)).to.equal(datatoken)
})
it('#swapExactAmountIn - should swap', async () => {
await transfer(web3, factoryOwner, contracts.daiAddress, user1, '1000')
expect(await balance(web3, contracts.daiAddress, user1)).to.equal('1000')
expect(await balance(web3, datatoken, user1)).to.equal('0')
await approve(web3, user1, contracts.daiAddress, poolAddress, '10')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.daiAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsInMaxFee = {
tokenAmountIn: '10',
minAmountOut: '1',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountIn(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
expect(await balance(web3, datatoken, user1)).to.equal(
await unitsToAmount(
web3,
datatoken,
tx.events.LOG_SWAP.returnValues.tokenAmountOut
)
)
})
it('#swapExactAmountOut - should swap', async () => {
await approve(web3, user1, contracts.daiAddress, poolAddress, '100')
expect(await balance(web3, contracts.daiAddress, user1)).to.equal('990')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.daiAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsOutMaxFee = {
maxAmountIn: '100',
tokenAmountOut: '50',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountOut(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
assert(tx != null)
})
it('#joinswapExternAmountIn- user2 should add liquidity, receiving LP tokens', async () => {
const daiAmountIn = '100'
const minBPTOut = '0.1'
await approve(web3, user1, contracts.daiAddress, poolAddress, '100', true)
expect(await allowance(web3, contracts.daiAddress, user1, poolAddress)).to.equal(
'100'
)
const tx = await pool.joinswapExternAmountIn(
user1,
poolAddress,
daiAmountIn,
minBPTOut
)
assert(tx != null)
expect(tx.events.LOG_JOIN[0].event === 'LOG_JOIN')
expect(tx.events.LOG_BPT.event === 'LOG_BPT')
// 2 JOIN EVENTS BECAUSE SIDE STAKING ALSO STAKED DTs, TODO: we should add to whom has been sent in the LOG_BPT event
expect(tx.events.LOG_JOIN[0].returnValues.bptAmount).to.equal(
tx.events.LOG_JOIN[1].returnValues.bptAmount
)
})
it('#exitSwapPoolAmountIn- user2 exit the pool receiving only DAI', async () => {
const BPTAmountIn = '0.5'
const minDAIOut = '0.5'
const tx = await pool.exitSwapPoolAmountIn(
user1,
poolAddress,
BPTAmountIn,
minDAIOut
)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(contracts.daiAddress)
// DTs were also unstaked in the same transaction (went to the staking contract)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(datatoken)
})
it('#exitswapExternAmountOut- user1 exit the pool receiving only DAI', async () => {
const maxBTPIn = '0.5'
const exactDAIOut = '1'
const tx = await pool.exitSwapPoolAmountIn(
user1,
poolAddress,
maxBTPIn,
exactDAIOut
)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(contracts.daiAddress)
// DTs were also unstaked in the same transaction (went to the staking contract)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(datatoken)
})
it('#getAmountInExactOut- should get the amount in for exact out', async () => {
const exactDAIOut = '1'
const result = await pool.getAmountInExactOut(
poolAddress,
datatoken,
contracts.daiAddress,
exactDAIOut,
'0.1'
)
const amountIn = result.tokenAmount
assert(amountIn != null)
// console.log(tx)
const spotPrice = await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.daiAddress,
'0.1'
)
// amount of DAI In will be slightly bigger than spotPrice
assert(amountIn > spotPrice)
})
it('#getAmountOutExactIn - should get the amount out for exact In', async () => {
const exactDTIn = '1'
const result = await pool.getAmountOutExactIn(
poolAddress,
datatoken,
contracts.daiAddress,
exactDTIn,
'0.1'
)
const amountOut = result.tokenAmount
assert(amountOut != null)
const spotPrice = await pool.getSpotPrice(
poolAddress,
contracts.daiAddress,
datatoken,
'0.1'
)
// amount of DAI received will be slightly less than spotPrice
assert(amountOut < spotPrice)
})
it('#getSpotPrice- should get the spot price', async () => {
assert(
(await pool.getSpotPrice(poolAddress, datatoken, contracts.daiAddress, '0.1')) !=
null
)
assert(
(await pool.getSpotPrice(poolAddress, contracts.daiAddress, datatoken, '0.1')) !=
null
)
})
it('#getMarketFees- should get market fees for each token', async () => {
// we haven't performed any swap DT => DAI so there's no fee in datatoken
// but there's a fee in DAI
assert((await pool.getMarketFees(poolAddress, datatoken)) === '0')
assert((await pool.getMarketFees(poolAddress, contracts.daiAddress)) > '0')
})
it('#getCommunityFees- should get community fees for each token', async () => {
// we haven't performed any swap DT => DAI so there's no fee in datatoken
// but there's a fee in DAI
assert((await pool.getCommunityFees(poolAddress, datatoken)) === '0')
assert((await pool.getCommunityFees(poolAddress, contracts.daiAddress)) > '0')
})
it('#collectMarketFee- should collect market fees for each token', async () => {
const spotPriceBefore = await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.daiAddress,
'0.1'
)
// factoryOwner is the marketFeeCollector
assert((await pool.getMarketFeeCollector(poolAddress)) === factoryOwner)
// user2 has no DAI (we are going to send DAI fee to him)
assert((await balance(web3, contracts.daiAddress, user2)) === '0')
// only marketFeeCollector can call this, set user2 as receiver
await pool.collectMarketFee(factoryOwner, poolAddress)
// DAI fees have been collected
assert((await pool.getMarketFees(poolAddress, contracts.daiAddress)) === '0')
// Spot price hasn't changed after fee collection
assert(
(await pool.getSpotPrice(poolAddress, datatoken, contracts.daiAddress, '0.1')) ===
spotPriceBefore
)
})
it('#getMarketFeeCollector- should get market fees for each token', async () => {
// factoryOwner is the marketFeeCollector
assert((await pool.getMarketFeeCollector(poolAddress)) === factoryOwner)
})
it('#collectCommunityFee- should get community fees for each token', async () => {
const spotPriceBefore = await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.daiAddress,
'0.1'
)
// some fee are available in DAI
assert((await pool.getCommunityFees(poolAddress, contracts.daiAddress)) > '0')
// opf collector has no DAI
assert(
(await balance(
web3,
contracts.daiAddress,
contracts.opfCommunityFeeCollectorAddress
)) === '0'
)
// anyone can call callectOPF
await pool.collectOPC(factoryOwner, poolAddress)
// DAI fees have been collected
assert((await pool.getCommunityFees(poolAddress, contracts.daiAddress)) === '0')
// OPF collector got DAI
assert(
(await balance(
web3,
contracts.daiAddress,
contracts.opfCommunityFeeCollectorAddress
)) > '0'
)
// Spot price hasn't changed after fee collection
assert(
(await pool.getSpotPrice(poolAddress, datatoken, contracts.daiAddress, '0.1')) ===
spotPriceBefore
)
})
it('#updateMarketFeeCollector- should update market fee collector', async () => {
// factoryOwner is the marketFeeCollector
assert((await pool.getMarketFeeCollector(poolAddress)) === factoryOwner)
await pool.updatePublishMarketFee(
factoryOwner,
poolAddress,
user2,
await pool.getMarketFee(poolAddress)
)
assert((await pool.getMarketFeeCollector(poolAddress)) === user2)
})
})
describe('Test a pool with USDC (6 Decimals)', () => {
it('#create a pool', async () => {
// CREATE A POOL
// we prepare transaction parameters objects
const poolParams: PoolCreationParams = {
ssContract: contracts.sideStakingAddress,
baseTokenAddress: contracts.usdcAddress,
baseTokenSender: contracts.nftFactoryAddress,
publisherAddress: factoryOwner,
marketFeeCollector: factoryOwner,
poolTemplateAddress: contracts.poolTemplateAddress,
rate: '1',
baseTokenDecimals: await decimals(web3, contracts.usdcAddress),
vestingAmount: '10000',
vestedBlocks: 2500000,
initialBaseTokenLiquidity: '2000',
swapFeeLiquidityProvider: '0.001',
swapFeeMarketRunner: '0.001'
}
const nftFactory = new NftFactory(contracts.nftFactoryAddress, web3, 8996)
const txReceipt = await nftFactory.createNftWithDatatokenWithPool(
factoryOwner,
nftData,
dtParams,
poolParams
)
datatoken = txReceipt.events.TokenCreated.returnValues.newTokenAddress
poolAddress = txReceipt.events.NewPool.returnValues.poolAddress
// user1 has no dt1
expect(await balance(web3, datatoken, user1)).to.equal('0')
})
it('#calcPoolOutGivenSingleIn - should get the amount of pool OUT for exact token IN', async () => {
// since rate is 1 and the pool is just created
// amount of pool out received for same amount of different token In is equal
const tokenInAmount = '10' // 10 USDC or 10 DTs
expect(
await pool.calcPoolOutGivenSingleIn(poolAddress, datatoken, tokenInAmount)
).to.equal(
await pool.calcPoolOutGivenSingleIn(
poolAddress,
contracts.usdcAddress,
tokenInAmount
)
)
// console.log(await pool.calcPoolOutGivenSingleIn(poolAddress, datatoken, tokenInAmount))
})
it('#calcSingleInGivenPoolOut - should get the amount of token IN for exact pool token OUT', async () => {
// since rate is 1 and the pool is just created
// amount of different token In for getting same pool amount out is equal
const poolAmountOut = '1'
expect(
parseInt(
await pool.calcSingleInGivenPoolOut(poolAddress, datatoken, poolAmountOut)
)
).to.be.closeTo(
parseInt(
await pool.calcSingleInGivenPoolOut(
poolAddress,
contracts.usdcAddress,
poolAmountOut
)
),
1e9
)
})
it('#calcSingleOutGivenPoolIn - should get the amount of token OUT for exact pool token IN', async () => {
// since rate is 1 and the pool is just created
// amount amount of different token Out for rediming the same pool In is equal
const poolAmountIn = '10'
expect(
await pool.calcSingleOutGivenPoolIn(poolAddress, datatoken, poolAmountIn)
).to.equal(
await pool.calcSingleOutGivenPoolIn(
poolAddress,
contracts.usdcAddress,
poolAmountIn
)
)
})
it('#calcPoolInGivenSingleOut - should get the amount of pool IN for exact token OUT', async () => {
// since rate is 1 and the pool is just created
// amount of pool In for getting the same amount of different token Out is equal
const tokenAmountOut = '10'
expect(
parseInt(
await pool.calcPoolInGivenSingleOut(poolAddress, datatoken, tokenAmountOut)
)
).to.be.closeTo(
parseInt(
await pool.calcPoolInGivenSingleOut(
poolAddress,
contracts.usdcAddress,
tokenAmountOut
)
),
1e11
)
})
it('#sharesBalance - should return user shares balance (datatoken balance, LPT balance, etc) ', async () => {
expect(await balance(web3, contracts.usdcAddress, user1)).to.equal(
await pool.sharesBalance(user1, contracts.usdcAddress)
)
})
it('#getNumTokens - should return num of tokens in pool (2)', async () => {
expect(await pool.getNumTokens(poolAddress)).to.equal('2')
})
it('#getPoolSharesTotalSupply - should return totalSupply of LPT', async () => {
// dt owner which added liquidity has half of pool shares (the rest is in the sidestaking contracta)
const dtOwnerLPTBalance = await pool.sharesBalance(factoryOwner, poolAddress)
expect(await pool.sharesBalance(factoryOwner, poolAddress)).to.equal(
await pool.sharesBalance(contracts.sideStakingAddress, poolAddress)
)
// total supply is twice the dtOwner balance
expect(await pool.getPoolSharesTotalSupply(poolAddress)).to.equal(
(2 * Number(dtOwnerLPTBalance)).toString()
)
})
it('#getCurrentTokens - should return current pool tokens', async () => {
const currentTokens = await pool.getCurrentTokens(poolAddress)
expect(currentTokens[0]).to.equal(datatoken)
expect(currentTokens[1]).to.equal(contracts.usdcAddress)
})
it('#getFinalTokens - should return final pool tokens', async () => {
const finalTokens = await pool.getFinalTokens(poolAddress)
expect(finalTokens[0]).to.equal(datatoken)
expect(finalTokens[1]).to.equal(contracts.usdcAddress)
})
it('#getController - should return the pool controller (sideStaking address)', async () => {
expect(await pool.getController(poolAddress)).to.equal(contracts.sideStakingAddress)
})
it('#isBound - should return true if token is bound into the pool', async () => {
expect(await pool.isBound(poolAddress, contracts.usdcAddress)).to.equal(true)
expect(await pool.isBound(poolAddress, contracts.oceanAddress)).to.equal(false)
})
it('#getReserve - should return final pool tokens Reserve', async () => {
expect(await pool.getReserve(poolAddress, contracts.usdcAddress)).to.equal('2000') // baseToken initial liquidity
// rate is 1 so we have the same amount of DTs
expect(await pool.getReserve(poolAddress, datatoken)).to.equal('2000')
})
it('#isFinalized - should return true if pool is finalized', async () => {
expect(await pool.isFinalized(poolAddress)).to.equal(true)
})
it('#getSwapFee - should return the swap fee', async () => {
expect(await pool.getSwapFee(poolAddress)).to.equal('0.001') // 0.1%
})
it('#getNormalizedWeight - should return the normalized weight', async () => {
expect(await pool.getNormalizedWeight(poolAddress, contracts.usdcAddress)).to.equal(
'0.5'
)
expect(await pool.getNormalizedWeight(poolAddress, datatoken)).to.equal('0.5')
})
it('#getDenormalizedWeight - should return the denormalized weight', async () => {
expect(
await pool.getDenormalizedWeight(poolAddress, contracts.usdcAddress)
).to.equal('5')
expect(await pool.getDenormalizedWeight(poolAddress, datatoken)).to.equal('5')
})
it('#getBasetoken - should return the baseToken address', async () => {
expect(await pool.getBasetoken(poolAddress)).to.equal(contracts.usdcAddress)
})
it('#getDatatoken - should return the datatoken address', async () => {
expect(await pool.getDatatoken(poolAddress)).to.equal(datatoken)
})
it('#swapExactAmountIn - should swap', async () => {
await transfer(web3, factoryOwner, contracts.usdcAddress, user1, '1000')
expect(await balance(web3, contracts.usdcAddress, user1)).to.equal('1000')
expect(await balance(web3, datatoken, user1)).to.equal('0')
await approve(web3, user1, contracts.usdcAddress, poolAddress, '10')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.usdcAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsInMaxFee = {
tokenAmountIn: '10',
minAmountOut: '1',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountIn(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
expect(await balance(web3, datatoken, user1)).to.equal(
await unitsToAmount(
web3,
datatoken,
tx.events.LOG_SWAP.returnValues.tokenAmountOut
)
)
})
it('#swapExactAmountOut - should swap', async () => {
await approve(web3, user1, contracts.usdcAddress, poolAddress, '100')
expect(await balance(web3, contracts.usdcAddress, user1)).to.equal('990')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.usdcAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsOutMaxFee = {
maxAmountIn: '100',
tokenAmountOut: '50',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountOut(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
assert(tx != null)
// console.log(tx.events)
})
it('#joinswapExternAmountIn- user2 should add liquidity, receiving LP tokens', async () => {
const usdcAmountIn = '100'
const minBPTOut = '0.1'
await approve(web3, user1, contracts.usdcAddress, poolAddress, '100', true)
const tx = await pool.joinswapExternAmountIn(
user1,
poolAddress,
usdcAmountIn,
minBPTOut
)
assert(tx != null)
expect(tx.events.LOG_JOIN[0].event === 'LOG_JOIN')
expect(tx.events.LOG_BPT.event === 'LOG_BPT')
// 2 JOIN EVENTS BECAUSE SIDE STAKING ALSO STAKED DTs, TODO: we should add to whom has been sent in the LOG_BPT event
expect(tx.events.LOG_JOIN[0].returnValues.bptAmount).to.equal(
tx.events.LOG_JOIN[1].returnValues.bptAmount
)
})
it('#exitSwapPoolAmountIn- user2 exit the pool receiving only USDC', async () => {
const BPTAmountIn = '0.5'
const minUSDCOut = '0.5'
const tx = await pool.exitSwapPoolAmountIn(
user1,
poolAddress,
BPTAmountIn,
minUSDCOut
)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(contracts.usdcAddress)
// DTs were also unstaked in the same transaction (went to the staking contract)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(datatoken)
})
it('#getAmountInExactOut- should get the amount in for exact out', async () => {
const exactUSDCOut = '1'
const result = await pool.getAmountInExactOut(
poolAddress,
datatoken,
contracts.usdcAddress,
exactUSDCOut,
'0.1'
)
const amountIn = result.tokenAmount
assert(amountIn != null)
const spotPrice = await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.usdcAddress,
'0.1'
)
// amount of USDC In will be slightly bigger than spotPrice
assert(amountIn > spotPrice)
})
it('#getAmountOutExactIn - should get the amount out for exact In', async () => {
const exactDTIn = '1'
const result = await pool.getAmountOutExactIn(
poolAddress,
datatoken,
contracts.usdcAddress,
exactDTIn,
'0.1'
)
const amountOut = result.tokenAmount
assert(amountOut != null)
const spotPrice = await pool.getSpotPrice(
poolAddress,
contracts.usdcAddress,
datatoken,
'0.1'
)
// amount of USDC received will be slightly less than spotPrice
assert(amountOut < spotPrice)
})
it('#getSpotPrice- should get the spot price', async () => {
assert(
(await pool.getSpotPrice(poolAddress, datatoken, contracts.usdcAddress, '0.1')) !=
null
)
assert(
(await pool.getSpotPrice(poolAddress, contracts.usdcAddress, datatoken, '0.1')) !=
null
)
})
it('#getMarketFees- should get market fees for each token', async () => {
// we haven't performed any swap DT => USDC so there's no fee in datatoken
// but there's a fee in USDC
assert((await pool.getMarketFees(poolAddress, datatoken)) === '0')
assert((await pool.getMarketFees(poolAddress, contracts.usdcAddress)) > '0')
})
it('#getCommunityFees- should get community fees for each token', async () => {
// we haven't performed any swap DT => USDC so there's no fee in datatoken
// but there's a fee in USDC
assert((await pool.getCommunityFees(poolAddress, datatoken)) === '0')
assert((await pool.getCommunityFees(poolAddress, contracts.usdcAddress)) > '0')
})
it('#collectMarketFee- should collect market fees for each token', async () => {
const spotPriceBefore = await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.usdcAddress,
'0.1'
)
// factoryOwner is the marketFeeCollector
assert((await pool.getMarketFeeCollector(poolAddress)) === factoryOwner)
// user2 has no USDC (we are going to send USDC fee to him)
assert((await balance(web3, contracts.usdcAddress, user2)) === '0')
// only marketFeeCollector can call this, set user2 as receiver
await pool.collectMarketFee(factoryOwner, poolAddress)
// USDC fees have been collected
assert((await pool.getMarketFees(poolAddress, contracts.usdcAddress)) === '0')
// Spot price hasn't changed after fee collection
assert(
(await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.usdcAddress,
'0.1'
)) === spotPriceBefore
)
})
it('#getMarketFeeCollector- should get market fees for each token', async () => {
// factoryOwner is the marketFeeCollector
assert((await pool.getMarketFeeCollector(poolAddress)) === factoryOwner)
})
it('#getCurrentMarketFees- should get curent market fees for each token', async () => {
const currentMarketFees: CurrentFees = await pool.getCurrentMarketFees(poolAddress)
assert(currentMarketFees !== null)
})
it('#getCurrentOPFFees- should get curent market fees for each token', async () => {
const curentOPFFees: CurrentFees = await pool.getCurrentOPCFees(poolAddress)
assert(curentOPFFees !== null)
})
it('#collectCommunityFee- should get community fees for each token', async () => {
const spotPriceBefore = await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.usdcAddress,
'0.1'
)
// some fee are available in USDC
assert((await pool.getCommunityFees(poolAddress, contracts.usdcAddress)) > '0')
// opf collector has no USDC
assert(
(await balance(
web3,
contracts.usdcAddress,
contracts.opfCommunityFeeCollectorAddress
)) === '0'
)
// anyone can call callectOPF
await pool.collectOPC(factoryOwner, poolAddress)
// USDC fees have been collected
assert((await pool.getCommunityFees(poolAddress, contracts.usdcAddress)) === '0')
// OPF collector got USDC
assert(
(await balance(
web3,
contracts.usdcAddress,
contracts.opfCommunityFeeCollectorAddress
)) > '0'
)
// Spot price hasn't changed after fee collection
assert(
(await pool.getSpotPrice(
poolAddress,
datatoken,
contracts.usdcAddress,
'0.1'
)) === spotPriceBefore
)
})
it('#updateMarketFeeCollector- should update market fee collector', async () => {
// factoryOwner is the marketFeeCollector
assert((await pool.getMarketFeeCollector(poolAddress)) === factoryOwner)
await pool.updatePublishMarketFee(
factoryOwner,
poolAddress,
user2,
await pool.getMarketFee(poolAddress)
)
assert((await pool.getMarketFeeCollector(poolAddress)) === user2)
})
})
})

View File

@ -1,519 +0,0 @@
import { assert, expect } from 'chai'
import BigNumber from 'bignumber.js'
import { deployContracts, Addresses } from '../../../TestContractHandler'
import { web3 } from '../../../config'
import {
allowance,
amountToUnits,
approve,
NftFactory,
NftCreateData,
Pool,
SideStaking,
unitsToAmount,
ZERO_ADDRESS,
balance,
transfer,
decimals
} from '../../../../src'
import {
DatatokenCreateParams,
PoolCreationParams,
TokenInOutMarket,
AmountsInMaxFee,
AmountsOutMaxFee
} from '../../../../src/@types'
import { Contract } from 'web3-eth-contract'
describe('SideStaking unit test', () => {
let factoryOwner: string
let user1: string
let user2: string
let initialBlock: number
let contracts: Addresses
let pool: Pool
let sideStaking: SideStaking
let poolAddress: string
let datatoken: string
let datatokenContract: Contract
let daiContract: Contract
let usdcContract: Contract
const VESTED_BLOCKS = 2500000
const VESTING_AMOUNT = '10000'
const BASE_TOKEN_LIQUIDITY = 2000
const nftData: NftCreateData = {
name: '72120Bundle',
symbol: '72Bundle',
templateIndex: 1,
tokenURI: 'https://oceanprotocol.com/nft/',
transferable: true,
owner: null
}
const dtParams: DatatokenCreateParams = {
templateIndex: 1,
minter: null,
paymentCollector: null,
mpFeeAddress: null,
feeToken: ZERO_ADDRESS,
cap: '1000000',
feeAmount: '0',
name: 'ERC20B1',
symbol: 'ERC20DT1Symbol'
}
before(async () => {
const accounts = await web3.eth.getAccounts()
factoryOwner = accounts[0]
user1 = accounts[1]
user2 = accounts[2]
nftData.owner = factoryOwner
dtParams.minter = factoryOwner
dtParams.paymentCollector = user2
dtParams.mpFeeAddress = factoryOwner
})
it('should deploy contracts', async () => {
contracts = await deployContracts(web3, factoryOwner)
// initialize Pool instance
pool = new Pool(web3, 8996)
assert(pool != null)
//
sideStaking = new SideStaking(web3, 8996)
assert(sideStaking != null)
await approve(
web3,
factoryOwner,
contracts.daiAddress,
contracts.nftFactoryAddress,
BASE_TOKEN_LIQUIDITY.toString()
)
assert(
parseInt(
await allowance(
web3,
contracts.daiAddress,
factoryOwner,
contracts.nftFactoryAddress
)
) >= BASE_TOKEN_LIQUIDITY
)
await approve(
web3,
factoryOwner,
contracts.usdcAddress,
contracts.nftFactoryAddress,
BASE_TOKEN_LIQUIDITY.toString()
)
assert(
parseInt(
await allowance(
web3,
contracts.usdcAddress,
factoryOwner,
contracts.nftFactoryAddress
)
) >= BASE_TOKEN_LIQUIDITY
)
})
describe('Test a pool with DAI (18 Decimals)', () => {
it('#create a pool', async () => {
// CREATE A POOL
// we prepare transaction parameters objects
const nftFactory = new NftFactory(contracts.nftFactoryAddress, web3)
const poolParams: PoolCreationParams = {
ssContract: contracts.sideStakingAddress,
baseTokenAddress: contracts.daiAddress,
baseTokenSender: contracts.nftFactoryAddress,
publisherAddress: factoryOwner,
marketFeeCollector: factoryOwner,
poolTemplateAddress: contracts.poolTemplateAddress,
rate: '1',
baseTokenDecimals: 18,
vestingAmount: VESTING_AMOUNT,
vestedBlocks: VESTED_BLOCKS,
initialBaseTokenLiquidity: BASE_TOKEN_LIQUIDITY.toString(),
swapFeeLiquidityProvider: '0.001',
swapFeeMarketRunner: '0.001'
}
const txReceipt = await nftFactory.createNftWithDatatokenWithPool(
factoryOwner,
nftData,
dtParams,
poolParams
)
initialBlock = await web3.eth.getBlockNumber()
datatoken = txReceipt.events.TokenCreated.returnValues.newTokenAddress
poolAddress = txReceipt.events.NewPool.returnValues.poolAddress
// user1 has no dt1
expect(await balance(web3, datatoken, user1)).to.equal('0')
})
it('#getRouter - should get Router address', async () => {
expect(await sideStaking.getRouter(contracts.sideStakingAddress)).to.equal(
contracts.routerAddress
)
})
it('#getDatatokenCirculatingSupply - should get datatoken supply in circulation (vesting amount excluded)', async () => {
expect(
await sideStaking.getDatatokenCirculatingSupply(
contracts.sideStakingAddress,
datatoken
)
).to.equal(web3.utils.toWei(BASE_TOKEN_LIQUIDITY.toString()))
})
it('#getDatatokenCurrentCirculatingSupply - should get datatoken supply in circulation ', async () => {
expect(
await sideStaking.getDatatokenCurrentCirculatingSupply(
contracts.sideStakingAddress,
datatoken
)
).to.equal(web3.utils.toWei(BASE_TOKEN_LIQUIDITY.toString()))
})
it('#getBasetoken - should get baseToken address', async () => {
expect(
await sideStaking.getBasetoken(contracts.sideStakingAddress, datatoken)
).to.equal(contracts.daiAddress)
})
it('#getPoolAddress - should get pool address', async () => {
expect(
await sideStaking.getPoolAddress(contracts.sideStakingAddress, datatoken)
).to.equal(poolAddress)
})
it('#getPublisherAddress - should get publisher address', async () => {
expect(
await sideStaking.getPublisherAddress(contracts.sideStakingAddress, datatoken)
).to.equal(factoryOwner)
})
it('#getBasetokenBalance ', async () => {
expect(
await sideStaking.getBasetokenBalance(contracts.sideStakingAddress, datatoken)
).to.equal('0')
})
it('#getDatatokenBalance ', async () => {
expect(
await (
await sideStaking.getDatatokenBalance(contracts.sideStakingAddress, datatoken)
).toString()
).to.equal(
new BigNumber(2)
.exponentiatedBy(256)
.minus(1)
.dividedBy(new BigNumber(10).exponentiatedBy(18))
.minus(BASE_TOKEN_LIQUIDITY)
.toString()
)
})
it('#getVestingAmount ', async () => {
expect(
await sideStaking.getVestingAmount(contracts.sideStakingAddress, datatoken)
).to.equal('0')
})
it('#getVestingLastBlock ', async () => {
expect(
await sideStaking.getVestingLastBlock(contracts.sideStakingAddress, datatoken)
).to.equal(initialBlock.toString())
})
it('#getVestingAmountSoFar ', async () => {
expect(
await sideStaking.getVestingAmountSoFar(contracts.sideStakingAddress, datatoken)
).to.equal('0')
})
it('#swapExactAmountIn - should swap', async () => {
await transfer(web3, factoryOwner, contracts.daiAddress, user1, '1000')
await approve(web3, user1, contracts.daiAddress, poolAddress, '10')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.daiAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsInMaxFee = {
tokenAmountIn: '10',
minAmountOut: '1',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountIn(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
expect(await balance(web3, datatoken, user1)).to.equal(
await unitsToAmount(
web3,
datatoken,
tx.events.LOG_SWAP.returnValues.tokenAmountOut
)
)
})
it('#swapExactAmountOut - should swap', async () => {
await approve(web3, user1, contracts.daiAddress, poolAddress, '100')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.daiAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsOutMaxFee = {
maxAmountIn: '100',
tokenAmountOut: '50',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountOut(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
assert(tx != null)
})
it('#joinswapExternAmountIn- user1 should add liquidity, receiving LP tokens', async () => {
const daiAmountIn = '100'
const minBPTOut = '0.1'
await approve(web3, user1, contracts.daiAddress, poolAddress, '100', true)
expect(await allowance(web3, contracts.daiAddress, user1, poolAddress)).to.equal(
'100'
)
const tx = await pool.joinswapExternAmountIn(
user1,
poolAddress,
daiAmountIn,
minBPTOut
)
assert(tx != null)
expect(tx.events.LOG_JOIN[0].event === 'LOG_JOIN')
expect(tx.events.LOG_BPT.event === 'LOG_BPT')
// 2 JOIN EVENTS BECAUSE SIDE STAKING ALSO STAKED DTs, TODO: we should add to whom has been sent in the LOG_BPT event
expect(tx.events.LOG_JOIN[0].returnValues.bptAmount).to.equal(
tx.events.LOG_JOIN[1].returnValues.bptAmount
)
})
it('#exitSwapPoolAmountIn- user1 exit the pool receiving only DAI', async () => {
const BPTAmountIn = '0.5'
const minDAIOut = '0.5'
const tx = await pool.exitSwapPoolAmountIn(
user1,
poolAddress,
BPTAmountIn,
minDAIOut
)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(contracts.daiAddress)
// DTs were also unstaked in the same transaction (went to the staking contract)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(datatoken)
})
})
describe('Test a pool with USDC (6 Decimals)', () => {
it('#create a pool', async () => {
// CREATE A POOL
// we prepare transaction parameters objects
const nftFactory = new NftFactory(contracts.nftFactoryAddress, web3)
const poolParams: PoolCreationParams = {
ssContract: contracts.sideStakingAddress,
baseTokenAddress: contracts.usdcAddress,
baseTokenSender: contracts.nftFactoryAddress,
publisherAddress: factoryOwner,
marketFeeCollector: factoryOwner,
poolTemplateAddress: contracts.poolTemplateAddress,
rate: '1',
baseTokenDecimals: await decimals(web3, contracts.usdcAddress),
vestingAmount: VESTING_AMOUNT,
vestedBlocks: VESTED_BLOCKS,
initialBaseTokenLiquidity: await unitsToAmount(
web3,
contracts.usdcAddress,
await amountToUnits(
web3,
contracts.usdcAddress,
BASE_TOKEN_LIQUIDITY.toString()
)
),
swapFeeLiquidityProvider: '0.001',
swapFeeMarketRunner: '0.001'
}
const txReceipt = await nftFactory.createNftWithDatatokenWithPool(
factoryOwner,
nftData,
dtParams,
poolParams
)
initialBlock = await web3.eth.getBlockNumber()
datatoken = txReceipt.events.TokenCreated.returnValues.newTokenAddress
poolAddress = txReceipt.events.NewPool.returnValues.poolAddress
// user1 has no dt1
expect(await balance(web3, datatoken, user1)).to.equal('0')
})
it('#getBasetokenBalance ', async () => {
expect(
await sideStaking.getBasetokenBalance(contracts.sideStakingAddress, datatoken)
).to.equal('0')
})
it('#getDatatokenBalance ', async () => {
expect(
await (
await sideStaking.getDatatokenBalance(contracts.sideStakingAddress, datatoken)
).toString()
).to.equal(
new BigNumber(2)
.exponentiatedBy(256)
.minus(1)
.dividedBy(new BigNumber(10).exponentiatedBy(18))
.minus(BASE_TOKEN_LIQUIDITY)
.toString()
)
})
it('#getVestingAmount ', async () => {
expect(
await sideStaking.getVestingAmount(contracts.sideStakingAddress, datatoken)
).to.equal('0')
})
it('#getVestingLastBlock ', async () => {
expect(
await sideStaking.getVestingLastBlock(contracts.sideStakingAddress, datatoken)
).to.equal(initialBlock.toString())
})
it('#getVestingAmountSoFar ', async () => {
expect(
await sideStaking.getVestingAmountSoFar(contracts.sideStakingAddress, datatoken)
).to.equal('0')
})
it('#swapExactAmountIn - should swap', async () => {
await transfer(web3, factoryOwner, contracts.usdcAddress, user1, '1000') // 1000 USDC
await approve(web3, user1, contracts.usdcAddress, poolAddress, '10')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.usdcAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsInMaxFee = {
tokenAmountIn: '10',
minAmountOut: '1',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountIn(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
expect(await balance(web3, datatoken, user1)).to.equal(
await unitsToAmount(
web3,
datatoken,
tx.events.LOG_SWAP.returnValues.tokenAmountOut
)
)
})
it('#swapExactAmountOut - should swap', async () => {
await approve(web3, user1, contracts.usdcAddress, poolAddress, '100')
const tokenInOutMarket: TokenInOutMarket = {
tokenIn: contracts.usdcAddress,
tokenOut: datatoken,
marketFeeAddress: factoryOwner
}
const amountsInOutMaxFee: AmountsOutMaxFee = {
maxAmountIn: '100',
tokenAmountOut: '50',
swapMarketFee: '0.1'
}
const tx = await pool.swapExactAmountOut(
user1,
poolAddress,
tokenInOutMarket,
amountsInOutMaxFee
)
assert(tx != null)
})
it('#joinswapExternAmountIn- user1 should add liquidity, receiving LP tokens', async () => {
const usdcAmountIn = '100'
const minBPTOut = '0.1'
await approve(web3, user1, contracts.usdcAddress, poolAddress, '100', true)
const tx = await pool.joinswapExternAmountIn(
user1,
poolAddress,
usdcAmountIn,
minBPTOut
)
assert(tx != null)
expect(tx.events.LOG_JOIN[0].event === 'LOG_JOIN')
expect(tx.events.LOG_BPT.event === 'LOG_BPT')
// 2 JOIN EVENTS BECAUSE SIDE STAKING ALSO STAKED DTs, TODO: we should add to whom has been sent in the LOG_BPT event
expect(tx.events.LOG_JOIN[0].returnValues.bptAmount).to.equal(
tx.events.LOG_JOIN[1].returnValues.bptAmount
)
})
it('#exitSwapPoolAmountIn- user1 exit the pool receiving only USDC', async () => {
const BPTAmountIn = '0.5'
const minUSDCOut = '0.5'
const tx = await pool.exitSwapPoolAmountIn(
user1,
poolAddress,
BPTAmountIn,
minUSDCOut
)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(contracts.usdcAddress)
// DTs were also unstaked in the same transaction (went to the staking contract)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(datatoken)
})
})
})

View File

@ -4,10 +4,7 @@
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"lib": [
"ESNext",
"dom"
],
"lib": ["ESNext", "dom"],
"declaration": true,
"module": "ESNext",
"target": "ESNext",
@ -18,8 +15,5 @@
"sourceMap": true,
"declarationDir": "./dist/"
},
"include": [
"src/**/*",
"test/**/*"
]
}
"include": ["src/**/*", "test/**/*"]
}