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:
parent
451fbe028c
commit
30aba62ef7
310
CodeExamples.md
310
CodeExamples.md
|
@ -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)
|
||||
|
|
11
README.md
11
README.md
|
@ -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.
|
||||
|
|
19
package.json
19
package.json
|
@ -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",
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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[]
|
|
@ -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[] {
|
|
@ -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
|
|
@ -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>(
|
|
@ -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)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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,
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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,
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -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/**/*"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue