mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
Merge pull request #348 from oceanprotocol/feature/pool_validations
add pool validation and helpers
This commit is contained in:
commit
5c2cef618e
@ -21,9 +21,14 @@ before_script:
|
|||||||
- cd barge
|
- cd barge
|
||||||
- git checkout v3
|
- git checkout v3
|
||||||
- export ADDRESS_FILE="${HOME}/.ocean/ocean-contracts/artifacts/address.json"
|
- export ADDRESS_FILE="${HOME}/.ocean/ocean-contracts/artifacts/address.json"
|
||||||
|
- mkdir "${HOME}/.ocean/"
|
||||||
|
- mkdir "${HOME}/.ocean/ocean-contracts/"
|
||||||
|
- mkdir "${HOME}/.ocean/ocean-contracts/artifacts"
|
||||||
|
- touch $ADDRESS_FILE
|
||||||
|
- echo "{}" >> $ADDRESS_FILE
|
||||||
- export AQUARIUS_URI="http://172.15.0.5:5000"
|
- export AQUARIUS_URI="http://172.15.0.5:5000"
|
||||||
- export DEPLOY_CONTRACTS=true
|
- export DEPLOY_CONTRACTS="true"
|
||||||
- export CONTRACTS_VERSION=v0.5.3
|
- export CONTRACTS_VERSION=v0.5.5
|
||||||
- bash -x start_ocean.sh --no-dashboard 2>&1 > start_ocean.log &
|
- bash -x start_ocean.sh --no-dashboard 2>&1 > start_ocean.log &
|
||||||
- cd ..
|
- cd ..
|
||||||
- ./scripts/waitforcontracts.sh
|
- ./scripts/waitforcontracts.sh
|
||||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -939,9 +939,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@oceanprotocol/contracts": {
|
"@oceanprotocol/contracts": {
|
||||||
"version": "0.5.3",
|
"version": "0.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.5.tgz",
|
||||||
"integrity": "sha512-gJ8qQACJgxOPIrPE0OFQ09iYXBAisOGg56EmelQlsMUgp0yY0DKgBntDP83S/Ho1yBjGygqfxCjQrPH63hh/PA=="
|
"integrity": "sha512-Omwlh3KxPm2JOuLd6DW4teAQhGaIv0fRTopCvctey0XGsf3DcbJpwS0A0YfgLQnvCyyVMKsiq90YCqpJ3SO/cw=="
|
||||||
},
|
},
|
||||||
"@octokit/auth-token": {
|
"@octokit/auth-token": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ethereum-navigator/navigator": "^0.5.0",
|
"@ethereum-navigator/navigator": "^0.5.0",
|
||||||
"@oceanprotocol/contracts": "^0.5.3",
|
"@oceanprotocol/contracts": "^0.5.5",
|
||||||
"decimal.js": "^10.2.0",
|
"decimal.js": "^10.2.0",
|
||||||
"fs": "0.0.1-security",
|
"fs": "0.0.1-security",
|
||||||
"lzma": "^2.3.2",
|
"lzma": "^2.3.2",
|
||||||
|
@ -3,3 +3,7 @@ if [ "${DEPLOY_CONTRACTS}" = "true" ]; then
|
|||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
cat "barge/start_ocean.log"
|
||||||
|
ls -lh "${HOME}/.ocean/ocean-contracts/"
|
||||||
|
ls -lh "${HOME}/.ocean/ocean-contracts/artifacts/"
|
||||||
|
cat "${HOME}/.ocean/ocean-contracts/artifacts/address.json"
|
||||||
|
@ -3,6 +3,8 @@ import { AbiItem } from 'web3-utils/types'
|
|||||||
import { TransactionReceipt } from 'web3-core'
|
import { TransactionReceipt } from 'web3-core'
|
||||||
import { Pool } from './Pool'
|
import { Pool } from './Pool'
|
||||||
import { EventData, Filter } from 'web3-eth-contract'
|
import { EventData, Filter } from 'web3-eth-contract'
|
||||||
|
import BigNumber from 'bignumber.js'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
|
||||||
declare type PoolTransactionType = 'swap' | 'join' | 'exit'
|
declare type PoolTransactionType = 'swap' | 'join' | 'exit'
|
||||||
|
|
||||||
@ -63,31 +65,43 @@ export class OceanPool extends Pool {
|
|||||||
fee: string
|
fee: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.error('ERROR: oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (parseFloat(fee) > 0.1) {
|
if (parseFloat(fee) > 0.1) {
|
||||||
console.error('Swap fee too high. The maximum allowed swapFee is 0.1 (10%).')
|
console.error('ERROR: Swap fee too high. The maximum allowed swapFee is 0.1 (10%).')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (parseFloat(weight) > 9 || parseFloat(weight) < 1) {
|
if (parseFloat(weight) > 9 || parseFloat(weight) < 1) {
|
||||||
console.error('Weight out of bounds (min 1, max9)')
|
console.error('ERROR: Weight out of bounds (min 1, max9)')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const address = await super.createPool(account)
|
const address = await super.createPool(account)
|
||||||
const oceanWeight = 10 - parseFloat(weight)
|
const oceanWeight = 10 - parseFloat(weight)
|
||||||
const oceanAmount = (parseFloat(amount) * oceanWeight) / parseFloat(weight)
|
const oceanAmount = (parseFloat(amount) * oceanWeight) / parseFloat(weight)
|
||||||
this.dtAddress = token
|
this.dtAddress = token
|
||||||
|
let txid
|
||||||
await this.approve(account, token, address, this.web3.utils.toWei(String(amount)))
|
txid = await this.approve(
|
||||||
await this.approve(
|
account,
|
||||||
|
token,
|
||||||
|
address,
|
||||||
|
this.web3.utils.toWei(String(amount))
|
||||||
|
)
|
||||||
|
if (!txid) {
|
||||||
|
console.error('ERROR: Failed to call approve DT token')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
txid = await this.approve(
|
||||||
account,
|
account,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
address,
|
address,
|
||||||
this.web3.utils.toWei(String(oceanAmount))
|
this.web3.utils.toWei(String(oceanAmount))
|
||||||
)
|
)
|
||||||
|
if (!txid) {
|
||||||
await super.setup(
|
console.error('ERROR: Failed to call approve OCEAN token')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
txid = await super.setup(
|
||||||
account,
|
account,
|
||||||
address,
|
address,
|
||||||
token,
|
token,
|
||||||
@ -98,7 +112,10 @@ export class OceanPool extends Pool {
|
|||||||
this.web3.utils.toWei(String(oceanWeight)),
|
this.web3.utils.toWei(String(oceanWeight)),
|
||||||
this.web3.utils.toWei(fee)
|
this.web3.utils.toWei(fee)
|
||||||
)
|
)
|
||||||
|
if (!txid) {
|
||||||
|
console.error('ERROR: Failed to create a new pool')
|
||||||
|
return null
|
||||||
|
}
|
||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,14 +144,14 @@ export class OceanPool extends Pool {
|
|||||||
*/
|
*/
|
||||||
public async getOceanReserve(poolAddress: string): Promise<string> {
|
public async getOceanReserve(poolAddress: string): Promise<string> {
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.error('ERROR: oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return super.getReserve(poolAddress, this.oceanAddress)
|
return super.getReserve(poolAddress, this.oceanAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Data Token balance of a pool
|
* Get datatoken balance of a pool
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
* @return {String}
|
* @return {String}
|
||||||
*/
|
*/
|
||||||
@ -144,10 +161,309 @@ export class OceanPool extends Pool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buy Data Token from a pool
|
* Returns max amount that you can buy.
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenAddress
|
||||||
|
*/
|
||||||
|
public async getMaxBuyQuantity(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenAddress: string
|
||||||
|
): Promise<string> {
|
||||||
|
const balance = await super.getReserve(poolAddress, tokenAddress)
|
||||||
|
return String(parseFloat(balance) / 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max amount of OCEAN that you can buy.
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenAddress
|
||||||
|
*/
|
||||||
|
public async getOceanMaxBuyQuantity(poolAddress: string): Promise<string> {
|
||||||
|
return this.getMaxBuyQuantity(poolAddress, this.oceanAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max amount of DT that you can buy.
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenAddress
|
||||||
|
*/
|
||||||
|
public async getDTMaxBuyQuantity(poolAddress: string): Promise<string> {
|
||||||
|
return this.getMaxBuyQuantity(poolAddress, await this.getDTAddress(poolAddress))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns tokenInAmount required to get tokenOutAmount
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenInAddress
|
||||||
|
* @param tokenOutAddress
|
||||||
|
* @param tokenOutAmount
|
||||||
|
*/
|
||||||
|
public async calcInGivenOut(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenInAddress: string,
|
||||||
|
tokenOutAddress: string,
|
||||||
|
tokenOutAmount: string
|
||||||
|
): Promise<string> {
|
||||||
|
const result = await super.calcInGivenOut(
|
||||||
|
poolAddress,
|
||||||
|
await super.getReserve(poolAddress, tokenInAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenInAddress),
|
||||||
|
await super.getReserve(poolAddress, tokenOutAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenOutAddress),
|
||||||
|
tokenOutAmount,
|
||||||
|
await this.getSwapFee(poolAddress)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns tokenOutAmount given tokenInAmount
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenInAddress
|
||||||
|
* @param tokenOutAddress
|
||||||
|
* @param tokenInAmount
|
||||||
|
*/
|
||||||
|
public async calcOutGivenIn(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenInAddress: string,
|
||||||
|
tokenOutAddress: string,
|
||||||
|
tokenInAmount: string
|
||||||
|
): Promise<string> {
|
||||||
|
const result = await super.calcOutGivenIn(
|
||||||
|
poolAddress,
|
||||||
|
await super.getReserve(poolAddress, tokenInAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenInAddress),
|
||||||
|
await super.getReserve(poolAddress, tokenOutAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenOutAddress),
|
||||||
|
tokenInAmount,
|
||||||
|
await super.getSwapFee(poolAddress)
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns no of shares receved for adding a token to the pool
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenInAddress
|
||||||
|
* @param tokenInAmount
|
||||||
|
*/
|
||||||
|
public async calcPoolOutGivenSingleIn(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenInAddress: string,
|
||||||
|
tokenInAmount: string
|
||||||
|
): Promise<string> {
|
||||||
|
const result = super.calcPoolOutGivenSingleIn(
|
||||||
|
poolAddress,
|
||||||
|
await super.getReserve(poolAddress, tokenInAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenInAddress),
|
||||||
|
await super.getPoolSharesTotalSupply(poolAddress),
|
||||||
|
await super.getTotalDenormalizedWeight(poolAddress),
|
||||||
|
tokenInAmount,
|
||||||
|
await super.getSwapFee(poolAddress)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns no of tokens required to get a specific no of poolShares
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenInAddress
|
||||||
|
* @param poolShares
|
||||||
|
*/
|
||||||
|
public async calcSingleInGivenPoolOut(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenInAddress: string,
|
||||||
|
poolShares: string
|
||||||
|
): Promise<string> {
|
||||||
|
const result = super.calcSingleInGivenPoolOut(
|
||||||
|
poolAddress,
|
||||||
|
await super.getReserve(poolAddress, tokenInAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenInAddress),
|
||||||
|
await super.getPoolSharesTotalSupply(poolAddress),
|
||||||
|
await super.getTotalDenormalizedWeight(poolAddress),
|
||||||
|
poolShares,
|
||||||
|
await super.getSwapFee(poolAddress)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns no of tokens received for spending a specific no of poolShares
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenOutAddress
|
||||||
|
* @param poolShares
|
||||||
|
*/
|
||||||
|
public async calcSingleOutGivenPoolIn(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenOutAddress: string,
|
||||||
|
poolShares: string
|
||||||
|
): Promise<string> {
|
||||||
|
const result = super.calcSingleOutGivenPoolIn(
|
||||||
|
poolAddress,
|
||||||
|
await super.getReserve(poolAddress, tokenOutAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenOutAddress),
|
||||||
|
await super.getPoolSharesTotalSupply(poolAddress),
|
||||||
|
await super.getTotalDenormalizedWeight(poolAddress),
|
||||||
|
poolShares,
|
||||||
|
await super.getSwapFee(poolAddress)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns no of pool shares required to receive a specified amount of tokens
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenOutAddress
|
||||||
|
* @param tokenOutAmount
|
||||||
|
*/
|
||||||
|
public async calcPoolInGivenSingleOut(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenOutAddress: string,
|
||||||
|
tokenOutAmount: string
|
||||||
|
): Promise<string> {
|
||||||
|
const result = super.calcPoolInGivenSingleOut(
|
||||||
|
poolAddress,
|
||||||
|
await super.getReserve(poolAddress, tokenOutAddress),
|
||||||
|
await super.getDenormalizedWeight(poolAddress, tokenOutAddress),
|
||||||
|
await super.getPoolSharesTotalSupply(poolAddress),
|
||||||
|
await super.getTotalDenormalizedWeight(poolAddress),
|
||||||
|
tokenOutAmount,
|
||||||
|
await super.getSwapFee(poolAddress)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns no of pool shares required to receive specified amount of DT
|
||||||
|
* @param poolAddress
|
||||||
|
* @param dtAmount
|
||||||
|
*/
|
||||||
|
public async getPoolSharesRequiredToRemoveDT(
|
||||||
|
poolAddress: string,
|
||||||
|
dtAmount: string
|
||||||
|
): Promise<string> {
|
||||||
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
|
return this.calcPoolInGivenSingleOut(poolAddress, dtAddress, dtAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns DT amnount received after spending poolShares
|
||||||
|
* @param poolAddress
|
||||||
|
* @param poolShares
|
||||||
|
*/
|
||||||
|
public async getDTRemovedforPoolShares(
|
||||||
|
poolAddress: string,
|
||||||
|
poolShares: string
|
||||||
|
): Promise<string> {
|
||||||
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
|
return this.calcSingleOutGivenPoolIn(poolAddress, dtAddress, poolShares)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns no of pool shares required to receive specified amount of DT
|
||||||
|
* @param poolAddress
|
||||||
|
* @param dtAmount
|
||||||
|
*/
|
||||||
|
public async getPoolSharesRequiredToRemoveOcean(
|
||||||
|
poolAddress: string,
|
||||||
|
oceanAmount: string
|
||||||
|
): Promise<string> {
|
||||||
|
return this.calcPoolInGivenSingleOut(poolAddress, this.oceanAddress, oceanAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Ocean amnount received after spending poolShares
|
||||||
|
* @param poolAddress
|
||||||
|
* @param poolShares
|
||||||
|
*/
|
||||||
|
public async getOceanRemovedforPoolShares(
|
||||||
|
poolAddress: string,
|
||||||
|
poolShares: string
|
||||||
|
): Promise<string> {
|
||||||
|
return this.calcSingleOutGivenPoolIn(poolAddress, this.oceanAddress, poolShares)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max DT amount that you can add to the pool
|
||||||
|
* @param poolAddress
|
||||||
|
*/
|
||||||
|
public async getDTMaxAddLiquidity(poolAddress: string): Promise<string> {
|
||||||
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
|
return this.getMaxAddLiquidity(poolAddress, dtAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max Ocean amount that you can add to the pool
|
||||||
|
* @param poolAddress
|
||||||
|
*/
|
||||||
|
public async getOceanMaxAddLiquidity(poolAddress: string): Promise<string> {
|
||||||
|
return this.getMaxAddLiquidity(poolAddress, this.oceanAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max amount of tokens that you can add to the pool
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenAddress
|
||||||
|
*/
|
||||||
|
public async getMaxAddLiquidity(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenAddress: string
|
||||||
|
): Promise<string> {
|
||||||
|
const balance = await super.getReserve(poolAddress, tokenAddress)
|
||||||
|
if (parseFloat(balance) > 0) {
|
||||||
|
const result = new BigNumber(this.web3.utils.toWei(balance))
|
||||||
|
.dividedBy(3)
|
||||||
|
.integerValue(BigNumber.ROUND_DOWN)
|
||||||
|
.minus(1)
|
||||||
|
return this.web3.utils.fromWei(result.toString())
|
||||||
|
} else return '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max amount of tokens that you can withdraw from the pool
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenAddress
|
||||||
|
*/
|
||||||
|
public async getMaxRemoveLiquidity(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenAddress: string
|
||||||
|
): Promise<string> {
|
||||||
|
const balance = await super.getReserve(poolAddress, tokenAddress)
|
||||||
|
if (parseFloat(balance) > 0) {
|
||||||
|
const result = new BigNumber(this.web3.utils.toWei(balance))
|
||||||
|
.dividedBy(4)
|
||||||
|
.integerValue(BigNumber.ROUND_DOWN)
|
||||||
|
.minus(1)
|
||||||
|
return this.web3.utils.fromWei(result.toString())
|
||||||
|
} else return '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max amount of DT that you can withdraw from the pool
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenAddress
|
||||||
|
*/
|
||||||
|
public async getDTMaxRemoveLiquidity(poolAddress: string): Promise<string> {
|
||||||
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
|
return this.getMaxRemoveLiquidity(poolAddress, dtAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns max amount of Ocean that you can withdraw from the pool
|
||||||
|
* @param poolAddress
|
||||||
|
* @param tokenAddress
|
||||||
|
*/
|
||||||
|
public async getOceanMaxRemoveLiquidity(poolAddress: string): Promise<string> {
|
||||||
|
return this.getMaxRemoveLiquidity(poolAddress, this.oceanAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buy datatoken from a pool
|
||||||
* @param {String} account
|
* @param {String} account
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
* @param {String} amount Data Token amount
|
* @param {String} amount datatoken amount
|
||||||
* @param {String} oceanAmount Ocean Token amount payed
|
* @param {String} oceanAmount Ocean Token amount payed
|
||||||
* @param {String} maxPrice Maximum price to pay
|
* @param {String} maxPrice Maximum price to pay
|
||||||
* @return {TransactionReceipt}
|
* @return {TransactionReceipt}
|
||||||
@ -155,40 +471,54 @@ export class OceanPool extends Pool {
|
|||||||
public async buyDT(
|
public async buyDT(
|
||||||
account: string,
|
account: string,
|
||||||
poolAddress: string,
|
poolAddress: string,
|
||||||
amount: string,
|
dtAmountWanted: string,
|
||||||
oceanAmount: string,
|
maxOceanAmount: string,
|
||||||
maxPrice: string
|
maxPrice?: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.error('ERROR: undefined ocean token contract address')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const dtAddress = await this.getDTAddress(poolAddress)
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
|
if (
|
||||||
|
parseFloat(dtAmountWanted) > parseFloat(await this.getDTMaxBuyQuantity(poolAddress))
|
||||||
|
) {
|
||||||
|
console.error('ERROR: Buy quantity exceeds quantity allowed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const calcInGivenOut = await this.getOceanNeeded(poolAddress, dtAmountWanted)
|
||||||
|
|
||||||
|
if (parseFloat(calcInGivenOut) > parseFloat(maxOceanAmount)) {
|
||||||
|
console.error('ERROR: Not enough Ocean Tokens')
|
||||||
|
return null
|
||||||
|
}
|
||||||
// TODO - check balances first
|
// TODO - check balances first
|
||||||
await super.approve(
|
const txid = await super.approve(
|
||||||
account,
|
account,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
this.web3.utils.toWei(oceanAmount)
|
this.web3.utils.toWei(maxOceanAmount)
|
||||||
)
|
)
|
||||||
|
if (!txid) {
|
||||||
|
console.error('ERROR: OCEAN approve failed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
return this.swapExactAmountOut(
|
return this.swapExactAmountOut(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
oceanAmount,
|
maxOceanAmount,
|
||||||
dtAddress,
|
dtAddress,
|
||||||
amount,
|
dtAmountWanted,
|
||||||
maxPrice
|
maxPrice
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sell Data Token
|
* Sell datatoken
|
||||||
* @param {String} account
|
* @param {String} account
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
* @param {String} amount Data Token amount
|
* @param {String} amount datatoken amount to be sold
|
||||||
* @param {String} oceanAmount Ocean Token amount expected
|
* @param {String} oceanAmount Ocean Token amount expected
|
||||||
* @param {String} maxPrice Minimum price to sell
|
* @param {String} maxPrice Minimum price to sell
|
||||||
* @return {TransactionReceipt}
|
* @return {TransactionReceipt}
|
||||||
@ -196,31 +526,54 @@ export class OceanPool extends Pool {
|
|||||||
public async sellDT(
|
public async sellDT(
|
||||||
account: string,
|
account: string,
|
||||||
poolAddress: string,
|
poolAddress: string,
|
||||||
amount: string,
|
dtAmount: string,
|
||||||
oceanAmount: string,
|
oceanAmountWanted: string,
|
||||||
minPrice: string
|
maxPrice?: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.error('ERROR: oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const dtAddress = await this.getDTAddress(poolAddress)
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
return this.swapExactAmountOut(
|
if (
|
||||||
|
parseFloat(oceanAmountWanted) >
|
||||||
|
parseFloat(await this.getOceanMaxBuyQuantity(poolAddress))
|
||||||
|
) {
|
||||||
|
console.error('ERROR: Buy quantity exceeds quantity allowed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const calcOutGivenIn = await this.getOceanReceived(poolAddress, dtAmount)
|
||||||
|
|
||||||
|
if (parseFloat(calcOutGivenIn) < parseFloat(oceanAmountWanted)) {
|
||||||
|
console.error('ERROR: Not enough datatokens')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const txid = await super.approve(
|
||||||
|
account,
|
||||||
|
dtAddress,
|
||||||
|
poolAddress,
|
||||||
|
this.web3.utils.toWei(dtAmount)
|
||||||
|
)
|
||||||
|
if (!txid) {
|
||||||
|
console.error('ERROR: DT approve failed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return this.swapExactAmountIn(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
dtAddress,
|
dtAddress,
|
||||||
amount,
|
dtAmount,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
oceanAmount,
|
oceanAmountWanted,
|
||||||
minPrice
|
maxPrice
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add Data Token amount to pool liquidity
|
* Add datatoken amount to pool liquidity
|
||||||
* @param {String} account
|
* @param {String} account
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
* @param {String} amount Data Token amount
|
* @param {String} amount datatoken amount
|
||||||
* @return {TransactionReceipt}
|
* @return {TransactionReceipt}
|
||||||
*/
|
*/
|
||||||
public async addDTLiquidity(
|
public async addDTLiquidity(
|
||||||
@ -229,7 +582,21 @@ export class OceanPool extends Pool {
|
|||||||
amount: string
|
amount: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
const dtAddress = await this.getDTAddress(poolAddress)
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
await super.approve(account, dtAddress, poolAddress, this.web3.utils.toWei(amount))
|
const maxAmount = await this.getMaxAddLiquidity(poolAddress, dtAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('ERROR: Too much reserve to add')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const txid = await super.approve(
|
||||||
|
account,
|
||||||
|
dtAddress,
|
||||||
|
poolAddress,
|
||||||
|
this.web3.utils.toWei(amount)
|
||||||
|
)
|
||||||
|
if (!txid) {
|
||||||
|
console.error('ERROR: DT approve failed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
const result = await super.joinswapExternAmountIn(
|
const result = await super.joinswapExternAmountIn(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
@ -241,10 +608,10 @@ export class OceanPool extends Pool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove Data Token amount from pool liquidity
|
* Remove datatoken amount from pool liquidity
|
||||||
* @param {String} account
|
* @param {String} account
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
* @param {String} amount Data Token amount
|
* @param {String} amount datatoken amount
|
||||||
* @return {TransactionReceipt}
|
* @return {TransactionReceipt}
|
||||||
*/
|
*/
|
||||||
public async removeDTLiquidity(
|
public async removeDTLiquidity(
|
||||||
@ -254,7 +621,23 @@ export class OceanPool extends Pool {
|
|||||||
maximumPoolShares: string
|
maximumPoolShares: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
const dtAddress = await this.getDTAddress(poolAddress)
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
// TODO Check balance of PoolShares before doing exit
|
const maxAmount = await this.getDTMaxRemoveLiquidity(poolAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('ERROR: Too much reserve to remove')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const usershares = await this.sharesBalance(account, poolAddress)
|
||||||
|
if (parseFloat(usershares) < parseFloat(maximumPoolShares)) {
|
||||||
|
console.error('ERROR: Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
parseFloat(maximumPoolShares) <
|
||||||
|
parseFloat(await this.getPoolSharesRequiredToRemoveDT(poolAddress, amount))
|
||||||
|
) {
|
||||||
|
console.error('ERROR: Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
return this.exitswapExternAmountOut(
|
return this.exitswapExternAmountOut(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
@ -277,15 +660,24 @@ export class OceanPool extends Pool {
|
|||||||
amount: string
|
amount: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.error('ERROR: oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
await super.approve(
|
const maxAmount = await this.getOceanMaxAddLiquidity(poolAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('ERROR: Too much reserve to add')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const txid = await super.approve(
|
||||||
account,
|
account,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
this.web3.utils.toWei(amount)
|
this.web3.utils.toWei(amount)
|
||||||
)
|
)
|
||||||
|
if (!txid) {
|
||||||
|
console.error('ERROR: OCEAN approve failed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
const result = await super.joinswapExternAmountIn(
|
const result = await super.joinswapExternAmountIn(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
@ -303,17 +695,33 @@ export class OceanPool extends Pool {
|
|||||||
* @param {String} amount Ocean Token amount in OCEAN
|
* @param {String} amount Ocean Token amount in OCEAN
|
||||||
* @return {TransactionReceipt}
|
* @return {TransactionReceipt}
|
||||||
*/
|
*/
|
||||||
public removeOceanLiquidity(
|
public async removeOceanLiquidity(
|
||||||
account: string,
|
account: string,
|
||||||
poolAddress: string,
|
poolAddress: string,
|
||||||
amount: string,
|
amount: string,
|
||||||
maximumPoolShares: string
|
maximumPoolShares: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.error('ERROR: oceanAddress is not defined')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const maxAmount = await this.getOceanMaxRemoveLiquidity(poolAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('ERROR: Too much reserve to remove')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const usershares = await this.sharesBalance(account, poolAddress)
|
||||||
|
if (parseFloat(usershares) < parseFloat(maximumPoolShares)) {
|
||||||
|
console.error('ERROR: Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
parseFloat(maximumPoolShares) <
|
||||||
|
parseFloat(await this.getPoolSharesRequiredToRemoveOcean(poolAddress, amount))
|
||||||
|
) {
|
||||||
|
console.error('ERROR: Not enough poolShares')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// TODO Check balance of PoolShares before doing exit
|
|
||||||
return super.exitswapExternAmountOut(
|
return super.exitswapExternAmountOut(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
@ -324,20 +732,45 @@ export class OceanPool extends Pool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Data Token price from pool
|
* Remove pool liquidity
|
||||||
|
* @param {String} account
|
||||||
|
* @param {String} poolAddress
|
||||||
|
* @param {String} poolShares
|
||||||
|
* @param {String} minDT Minimum DT expected (defaults 0)
|
||||||
|
* @param {String} poolShares Minim Ocean expected (defaults 0)
|
||||||
|
* @return {TransactionReceipt}
|
||||||
|
*/
|
||||||
|
public async removePoolLiquidity(
|
||||||
|
account: string,
|
||||||
|
poolAddress: string,
|
||||||
|
poolShares: string,
|
||||||
|
minDT = '0',
|
||||||
|
minOcean = '0'
|
||||||
|
): Promise<TransactionReceipt> {
|
||||||
|
const usershares = await this.sharesBalance(account, poolAddress)
|
||||||
|
if (parseFloat(usershares) < parseFloat(poolShares)) {
|
||||||
|
console.error('ERROR: Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.exitPool(account, poolAddress, poolShares, [minDT, minOcean])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get datatoken price from pool
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
* @return {String}
|
* @return {String}
|
||||||
*/
|
*/
|
||||||
public async getDTPrice(poolAddress: string): Promise<string> {
|
public async getDTPrice(poolAddress: string): Promise<string> {
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.error('ERROR: oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return this.getOceanNeeded(poolAddress, '1')
|
return this.getOceanNeeded(poolAddress, '1')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search all pools that have Data Token in their composition
|
* Search all pools that have datatoken in their composition
|
||||||
* @param {String} dtAddress
|
* @param {String} dtAddress
|
||||||
* @return {String[]}
|
* @return {String[]}
|
||||||
*/
|
*/
|
||||||
@ -358,19 +791,17 @@ export class OceanPool extends Pool {
|
|||||||
|
|
||||||
public async getOceanNeeded(poolAddress: string, dtRequired: string): Promise<string> {
|
public async getOceanNeeded(poolAddress: string, dtRequired: string): Promise<string> {
|
||||||
const dtAddress = await this.getDTAddress(poolAddress)
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
const tokenBalanceIn = await this.getReserve(poolAddress, this.oceanAddress)
|
return this.calcInGivenOut(poolAddress, this.oceanAddress, dtAddress, dtRequired)
|
||||||
const tokenWeightIn = await this.getDenormalizedWeight(poolAddress, this.oceanAddress)
|
}
|
||||||
const tokenBalanceOut = await this.getReserve(poolAddress, dtAddress)
|
|
||||||
const tokenWeightOut = await this.getDenormalizedWeight(poolAddress, dtAddress)
|
public async getOceanReceived(poolAddress: string, dtSold: string): Promise<string> {
|
||||||
const swapFee = await this.getSwapFee(poolAddress)
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
return super.calcInGivenOut(
|
return this.calcOutGivenIn(poolAddress, dtAddress, this.oceanAddress, dtSold)
|
||||||
tokenBalanceIn,
|
}
|
||||||
tokenWeightIn,
|
|
||||||
tokenBalanceOut,
|
public async getDTNeeded(poolAddress: string, OceanRequired: string): Promise<string> {
|
||||||
tokenWeightOut,
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
dtRequired,
|
return this.calcInGivenOut(poolAddress, dtAddress, this.oceanAddress, OceanRequired)
|
||||||
swapFee
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,9 +2,13 @@ import Web3 from 'web3'
|
|||||||
import { AbiItem } from 'web3-utils/types'
|
import { AbiItem } from 'web3-utils/types'
|
||||||
import { TransactionReceipt } from 'web3-core'
|
import { TransactionReceipt } from 'web3-core'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
|
import BigNumber from 'bignumber.js'
|
||||||
import jsonpoolABI from '@oceanprotocol/contracts/artifacts/BPool.json'
|
import jsonpoolABI from '@oceanprotocol/contracts/artifacts/BPool.json'
|
||||||
import { PoolFactory } from './PoolFactory'
|
import { PoolFactory } from './PoolFactory'
|
||||||
|
|
||||||
|
const MaxUint256: BigNumber = new BigNumber(
|
||||||
|
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||||
|
)
|
||||||
/**
|
/**
|
||||||
* Provides an interface to Balancer BPool & BFactory
|
* Provides an interface to Balancer BPool & BFactory
|
||||||
*/
|
*/
|
||||||
@ -270,6 +274,23 @@ export class Pool extends PoolFactory {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get total supply of pool shares
|
||||||
|
* @param {String} poolAddress
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
async getPoolSharesTotalSupply(poolAddress: string): Promise<string> {
|
||||||
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||||
|
let amount = null
|
||||||
|
try {
|
||||||
|
const result = await pool.methods.totalSupply().call()
|
||||||
|
amount = this.web3.utils.fromWei(result)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
return amount
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get tokens composing this pool
|
* Get tokens composing this pool
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
@ -483,7 +504,7 @@ export class Pool extends PoolFactory {
|
|||||||
tokenAmountIn: string,
|
tokenAmountIn: string,
|
||||||
tokenOut: string,
|
tokenOut: string,
|
||||||
minAmountOut: string,
|
minAmountOut: string,
|
||||||
maxPrice: string
|
maxPrice?: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
||||||
from: account
|
from: account
|
||||||
@ -496,7 +517,7 @@ export class Pool extends PoolFactory {
|
|||||||
this.web3.utils.toWei(tokenAmountIn),
|
this.web3.utils.toWei(tokenAmountIn),
|
||||||
tokenOut,
|
tokenOut,
|
||||||
this.web3.utils.toWei(minAmountOut),
|
this.web3.utils.toWei(minAmountOut),
|
||||||
this.web3.utils.toWei(maxPrice)
|
maxPrice ? this.web3.utils.toWei(maxPrice) : MaxUint256
|
||||||
)
|
)
|
||||||
.send({ from: account, gas: this.GASLIMIT_DEFAULT })
|
.send({ from: account, gas: this.GASLIMIT_DEFAULT })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -523,7 +544,7 @@ export class Pool extends PoolFactory {
|
|||||||
maxAmountIn: string,
|
maxAmountIn: string,
|
||||||
tokenOut: string,
|
tokenOut: string,
|
||||||
minAmountOut: string,
|
minAmountOut: string,
|
||||||
maxPrice: string
|
maxPrice?: string
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
||||||
from: account
|
from: account
|
||||||
@ -536,7 +557,7 @@ export class Pool extends PoolFactory {
|
|||||||
this.web3.utils.toWei(maxAmountIn),
|
this.web3.utils.toWei(maxAmountIn),
|
||||||
tokenOut,
|
tokenOut,
|
||||||
this.web3.utils.toWei(minAmountOut),
|
this.web3.utils.toWei(minAmountOut),
|
||||||
this.web3.utils.toWei(maxPrice)
|
maxPrice ? this.web3.utils.toWei(maxPrice) : MaxUint256
|
||||||
)
|
)
|
||||||
.send({ from: account, gas: this.GASLIMIT_DEFAULT })
|
.send({ from: account, gas: this.GASLIMIT_DEFAULT })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -594,7 +615,7 @@ export class Pool extends PoolFactory {
|
|||||||
account: string,
|
account: string,
|
||||||
poolAddress: string,
|
poolAddress: string,
|
||||||
poolAmountIn: string,
|
poolAmountIn: string,
|
||||||
minAmountsOut: string
|
minAmountsOut: string[]
|
||||||
): Promise<TransactionReceipt> {
|
): Promise<TransactionReceipt> {
|
||||||
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress, {
|
||||||
from: account
|
from: account
|
||||||
@ -799,6 +820,7 @@ export class Pool extends PoolFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async calcInGivenOut(
|
public async calcInGivenOut(
|
||||||
|
poolAddress: string,
|
||||||
tokenBalanceIn: string,
|
tokenBalanceIn: string,
|
||||||
tokenWeightIn: string,
|
tokenWeightIn: string,
|
||||||
tokenBalanceOut: string,
|
tokenBalanceOut: string,
|
||||||
@ -806,14 +828,168 @@ export class Pool extends PoolFactory {
|
|||||||
tokenAmountOut: string,
|
tokenAmountOut: string,
|
||||||
swapFee: string
|
swapFee: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const weightRatio = new Decimal(tokenWeightOut).div(new Decimal(tokenWeightIn))
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||||
const diff = new Decimal(tokenBalanceOut).minus(tokenAmountOut)
|
let amount = null
|
||||||
const y = new Decimal(tokenBalanceOut).div(diff)
|
try {
|
||||||
const foo = y.pow(weightRatio).minus(new Decimal(1))
|
const result = await pool.methods
|
||||||
const tokenAmountIn = new Decimal(tokenBalanceIn)
|
.calcInGivenOut(
|
||||||
.times(foo)
|
this.web3.utils.toWei(tokenBalanceIn),
|
||||||
.div(new Decimal(1).minus(new Decimal(swapFee)))
|
this.web3.utils.toWei(tokenWeightIn),
|
||||||
|
this.web3.utils.toWei(tokenBalanceOut),
|
||||||
|
this.web3.utils.toWei(tokenWeightOut),
|
||||||
|
this.web3.utils.toWei(tokenAmountOut),
|
||||||
|
this.web3.utils.toWei(swapFee)
|
||||||
|
)
|
||||||
|
.call()
|
||||||
|
amount = this.web3.utils.fromWei(result)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
return amount
|
||||||
|
}
|
||||||
|
|
||||||
return tokenAmountIn.toString()
|
public async calcOutGivenIn(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenBalanceIn: string,
|
||||||
|
tokenWeightIn: string,
|
||||||
|
tokenBalanceOut: string,
|
||||||
|
tokenWeightOut: string,
|
||||||
|
tokenAmountIn: string,
|
||||||
|
swapFee: string
|
||||||
|
): Promise<string> {
|
||||||
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||||
|
let amount = null
|
||||||
|
try {
|
||||||
|
const result = await pool.methods
|
||||||
|
.calcOutGivenIn(
|
||||||
|
this.web3.utils.toWei(tokenBalanceIn),
|
||||||
|
this.web3.utils.toWei(tokenWeightIn),
|
||||||
|
this.web3.utils.toWei(tokenBalanceOut),
|
||||||
|
this.web3.utils.toWei(tokenWeightOut),
|
||||||
|
this.web3.utils.toWei(tokenAmountIn),
|
||||||
|
this.web3.utils.toWei(swapFee)
|
||||||
|
)
|
||||||
|
.call()
|
||||||
|
amount = this.web3.utils.fromWei(result)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
return amount
|
||||||
|
}
|
||||||
|
|
||||||
|
public async calcPoolOutGivenSingleIn(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenBalanceIn: string,
|
||||||
|
tokenWeightIn: string,
|
||||||
|
poolSupply: string,
|
||||||
|
totalWeight: string,
|
||||||
|
tokenAmountIn: string,
|
||||||
|
swapFee: string
|
||||||
|
): Promise<string> {
|
||||||
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||||
|
let amount = null
|
||||||
|
try {
|
||||||
|
const result = await pool.methods
|
||||||
|
.calcPoolOutGivenSingleIn(
|
||||||
|
this.web3.utils.toWei(tokenBalanceIn),
|
||||||
|
this.web3.utils.toWei(tokenWeightIn),
|
||||||
|
this.web3.utils.toWei(poolSupply),
|
||||||
|
this.web3.utils.toWei(totalWeight),
|
||||||
|
this.web3.utils.toWei(tokenAmountIn),
|
||||||
|
this.web3.utils.toWei(swapFee)
|
||||||
|
)
|
||||||
|
.call()
|
||||||
|
amount = this.web3.utils.fromWei(result)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
return amount
|
||||||
|
}
|
||||||
|
|
||||||
|
public async calcSingleInGivenPoolOut(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenBalanceIn: string,
|
||||||
|
tokenWeightIn: string,
|
||||||
|
poolSupply: string,
|
||||||
|
totalWeight: string,
|
||||||
|
poolAmountOut: string,
|
||||||
|
swapFee: string
|
||||||
|
): Promise<string> {
|
||||||
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||||
|
let amount = null
|
||||||
|
try {
|
||||||
|
const result = await pool.methods
|
||||||
|
.calcSingleInGivenPoolOut(
|
||||||
|
this.web3.utils.toWei(tokenBalanceIn),
|
||||||
|
this.web3.utils.toWei(tokenWeightIn),
|
||||||
|
this.web3.utils.toWei(poolSupply),
|
||||||
|
this.web3.utils.toWei(totalWeight),
|
||||||
|
this.web3.utils.toWei(poolAmountOut),
|
||||||
|
this.web3.utils.toWei(swapFee)
|
||||||
|
)
|
||||||
|
.call()
|
||||||
|
amount = this.web3.utils.fromWei(result)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
return amount
|
||||||
|
}
|
||||||
|
|
||||||
|
public async calcSingleOutGivenPoolIn(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenBalanceOut: string,
|
||||||
|
tokenWeightOut: string,
|
||||||
|
poolSupply: string,
|
||||||
|
totalWeight: string,
|
||||||
|
poolAmountIn: string,
|
||||||
|
swapFee: string
|
||||||
|
): Promise<string> {
|
||||||
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||||
|
let amount = null
|
||||||
|
try {
|
||||||
|
const result = await pool.methods
|
||||||
|
.calcSingleOutGivenPoolIn(
|
||||||
|
this.web3.utils.toWei(tokenBalanceOut),
|
||||||
|
this.web3.utils.toWei(tokenWeightOut),
|
||||||
|
this.web3.utils.toWei(poolSupply),
|
||||||
|
this.web3.utils.toWei(totalWeight),
|
||||||
|
this.web3.utils.toWei(poolAmountIn),
|
||||||
|
this.web3.utils.toWei(swapFee)
|
||||||
|
)
|
||||||
|
.call()
|
||||||
|
amount = this.web3.utils.fromWei(result)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
return amount
|
||||||
|
}
|
||||||
|
|
||||||
|
public async calcPoolInGivenSingleOut(
|
||||||
|
poolAddress: string,
|
||||||
|
tokenBalanceOut: string,
|
||||||
|
tokenWeightOut: string,
|
||||||
|
poolSupply: string,
|
||||||
|
totalWeight: string,
|
||||||
|
tokenAmountOut: string,
|
||||||
|
swapFee: string
|
||||||
|
): Promise<string> {
|
||||||
|
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
|
||||||
|
let amount = null
|
||||||
|
try {
|
||||||
|
const result = await pool.methods
|
||||||
|
.calcPoolInGivenSingleOut(
|
||||||
|
this.web3.utils.toWei(tokenBalanceOut),
|
||||||
|
this.web3.utils.toWei(tokenWeightOut),
|
||||||
|
this.web3.utils.toWei(poolSupply),
|
||||||
|
this.web3.utils.toWei(totalWeight),
|
||||||
|
this.web3.utils.toWei(tokenAmountOut),
|
||||||
|
this.web3.utils.toWei(swapFee)
|
||||||
|
)
|
||||||
|
.call()
|
||||||
|
amount = this.web3.utils.fromWei(result)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
return amount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,4 +417,13 @@ export class DataTokens {
|
|||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getStartOrderEventSignature(): string {
|
||||||
|
const abi = this.datatokensABI as AbiItem[]
|
||||||
|
const eventdata = abi.find(function (o) {
|
||||||
|
if (o.name === 'OrderStarted' && o.type === 'event') return o
|
||||||
|
})
|
||||||
|
const topic = this.web3.eth.abi.encodeEventSignature(eventdata as any)
|
||||||
|
return topic
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,15 +612,12 @@ export class Assets extends Instantiable {
|
|||||||
): Promise<Order[]> {
|
): Promise<Order[]> {
|
||||||
const results: Order[] = []
|
const results: Order[] = []
|
||||||
const address = account.getId().toLowerCase()
|
const address = account.getId().toLowerCase()
|
||||||
|
const { datatokens } = this.ocean
|
||||||
|
const topic1 = '0x000000000000000000000000' + address.substring(2)
|
||||||
const events = await this.web3.eth.getPastLogs({
|
const events = await this.web3.eth.getPastLogs({
|
||||||
topics: [
|
topics: [[datatokens.getStartOrderEventSignature(), null, topic1]],
|
||||||
[
|
fromBlock: fromBlock || 0,
|
||||||
'0xe1c4fa794edfa8f619b8257a077398950357b9c6398528f94480307352f9afcc',
|
toBlock: 'latest'
|
||||||
null,
|
|
||||||
'0x000000000000000000000000' + address.substring(address.length - 40)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
fromBlock: fromBlock || 0
|
|
||||||
})
|
})
|
||||||
for (let i = 0; i < events.length; i++) {
|
for (let i = 0; i < events.length; i++) {
|
||||||
const order: Order = {
|
const order: Order = {
|
||||||
@ -631,18 +628,20 @@ export class Assets extends Instantiable {
|
|||||||
consumer: '0x' + events[i].topics[1].substring(events[i].topics[1].length - 40),
|
consumer: '0x' + events[i].topics[1].substring(events[i].topics[1].length - 40),
|
||||||
payer: '0x' + events[i].topics[2].substring(events[i].topics[2].length - 40)
|
payer: '0x' + events[i].topics[2].substring(events[i].topics[2].length - 40)
|
||||||
}
|
}
|
||||||
const params = this.web3.eth.abi.decodeParameters(
|
try {
|
||||||
['uint256', 'uint256', 'uint256', 'uint256'],
|
const params = this.web3.eth.abi.decodeParameters(
|
||||||
events[i].data
|
['uint256', 'uint256', 'uint256', 'uint256'],
|
||||||
)
|
events[i].data
|
||||||
order.serviceId = parseInt(params[1])
|
)
|
||||||
order.timestamp = parseInt(params[2])
|
order.serviceId = parseInt(params[1])
|
||||||
order.amount = this.web3.utils.fromWei(params[0])
|
order.timestamp = parseInt(params[2])
|
||||||
order.did = didPrefixed(didNoZeroX(order.dtAddress))
|
order.amount = this.web3.utils.fromWei(params[0])
|
||||||
const service = await this.getServiceByIndex(order.did, order.serviceId)
|
order.did = didPrefixed(didNoZeroX(order.dtAddress))
|
||||||
order.serviceType = service.type
|
const service = await this.getServiceByIndex(order.did, order.serviceId)
|
||||||
if (!serviceType || (serviceType && serviceType === service.type))
|
order.serviceType = service.type
|
||||||
results.push(order)
|
if (!serviceType || (serviceType && serviceType === service.type))
|
||||||
|
results.push(order)
|
||||||
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ const configs: ConfigHelperConfig[] = [
|
|||||||
|
|
||||||
export class ConfigHelper {
|
export class ConfigHelper {
|
||||||
/* Load contract addresses from env ADDRESS_FILE (generated by ocean-contracts) */
|
/* Load contract addresses from env ADDRESS_FILE (generated by ocean-contracts) */
|
||||||
public getAddressesFromEnv(): Partial<ConfigHelperConfig> {
|
public getAddressesFromEnv(network: string): Partial<ConfigHelperConfig> {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(
|
const data = JSON.parse(
|
||||||
fs.readFileSync(
|
fs.readFileSync(
|
||||||
@ -78,13 +78,14 @@ export class ConfigHelper {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const { DTFactory, BFactory, FixedRateExchange, Metadata } = data?.ganache
|
const { DTFactory, BFactory, FixedRateExchange, Metadata, Ocean } = data[network]
|
||||||
|
|
||||||
const configAddresses: Partial<ConfigHelperConfig> = {
|
const configAddresses: Partial<ConfigHelperConfig> = {
|
||||||
factoryAddress: DTFactory,
|
factoryAddress: DTFactory,
|
||||||
poolFactoryAddress: BFactory,
|
poolFactoryAddress: BFactory,
|
||||||
fixedRateExchangeAddress: FixedRateExchange,
|
fixedRateExchangeAddress: FixedRateExchange,
|
||||||
metadataContractAddress: Metadata,
|
metadataContractAddress: Metadata,
|
||||||
|
oceanTokenAddress: Ocean,
|
||||||
...(process.env.AQUARIUS_URI && { metadataStoreUri: process.env.AQUARIUS_URI })
|
...(process.env.AQUARIUS_URI && { metadataStoreUri: process.env.AQUARIUS_URI })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,10 +108,8 @@ export class ConfigHelper {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network === 'development') {
|
const contractAddressesConfig = this.getAddressesFromEnv(config.network)
|
||||||
const contractAddressesConfig = this.getAddressesFromEnv()
|
config = { ...config, ...contractAddressesConfig }
|
||||||
config = { ...config, ...contractAddressesConfig }
|
|
||||||
}
|
|
||||||
|
|
||||||
const nodeUri = infuraProjectId
|
const nodeUri = infuraProjectId
|
||||||
? `${config.nodeUri}/${infuraProjectId}`
|
? `${config.nodeUri}/${infuraProjectId}`
|
||||||
|
@ -283,7 +283,7 @@ describe('Compute flow', () => {
|
|||||||
tokenAddressAlgorithm
|
tokenAddressAlgorithm
|
||||||
)
|
)
|
||||||
assert(algorithmAsset.dataToken === tokenAddressAlgorithm)
|
assert(algorithmAsset.dataToken === tokenAddressAlgorithm)
|
||||||
await sleep(6000)
|
await sleep(60000)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Alice mints 100 DTs and tranfers them to the compute marketplace', async () => {
|
it('Alice mints 100 DTs and tranfers them to the compute marketplace', async () => {
|
||||||
@ -445,7 +445,7 @@ describe('Compute flow', () => {
|
|||||||
alice
|
alice
|
||||||
)
|
)
|
||||||
assert(newDdo !== null)
|
assert(newDdo !== null)
|
||||||
await sleep(6000)
|
await sleep(60000)
|
||||||
const metaData = await ocean.assets.getServiceByType(ddo.id, 'compute')
|
const metaData = await ocean.assets.getServiceByType(ddo.id, 'compute')
|
||||||
assert.equal(
|
assert.equal(
|
||||||
metaData.attributes.main.privacy.allowRawAlgorithm,
|
metaData.attributes.main.privacy.allowRawAlgorithm,
|
||||||
|
@ -112,7 +112,7 @@ describe('Marketplace flow', () => {
|
|||||||
)
|
)
|
||||||
ddo = await ocean.assets.create(asset, alice, [service1], tokenAddress)
|
ddo = await ocean.assets.create(asset, alice, [service1], tokenAddress)
|
||||||
assert(ddo.dataToken === tokenAddress)
|
assert(ddo.dataToken === tokenAddress)
|
||||||
await sleep(6000)
|
await sleep(60000)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Alice mints 100 tokens', async () => {
|
it('Alice mints 100 tokens', async () => {
|
||||||
@ -212,7 +212,7 @@ describe('Marketplace flow', () => {
|
|||||||
}
|
}
|
||||||
const newDdo = await ocean.assets.editMetadata(ddo.id, newMetaData, alice)
|
const newDdo = await ocean.assets.editMetadata(ddo.id, newMetaData, alice)
|
||||||
assert(newDdo !== null)
|
assert(newDdo !== null)
|
||||||
await sleep(6000)
|
await sleep(60000)
|
||||||
const metaData = await ocean.assets.getServiceByType(ddo.id, 'metadata')
|
const metaData = await ocean.assets.getServiceByType(ddo.id, 'metadata')
|
||||||
assert.equal(metaData.attributes.main.name, newMetaData.title)
|
assert.equal(metaData.attributes.main.name, newMetaData.title)
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
@ -27,7 +27,7 @@ describe('Balancer flow', () => {
|
|||||||
let contracts: TestContractHandler
|
let contracts: TestContractHandler
|
||||||
let datatoken: DataTokens
|
let datatoken: DataTokens
|
||||||
let tokenAddress: string
|
let tokenAddress: string
|
||||||
let consoleDebug: false
|
let consoleDebug: true
|
||||||
let greatPool: string
|
let greatPool: string
|
||||||
const tokenAmount = '1000'
|
const tokenAmount = '1000'
|
||||||
const transferAmount = '200'
|
const transferAmount = '200'
|
||||||
@ -171,26 +171,55 @@ describe('Balancer flow', () => {
|
|||||||
const requiredOcean = await Pool.getOceanNeeded(alicePoolAddress, '1')
|
const requiredOcean = await Pool.getOceanNeeded(alicePoolAddress, '1')
|
||||||
assert(Number(requiredOcean) > 0)
|
assert(Number(requiredOcean) > 0)
|
||||||
})
|
})
|
||||||
|
it('Get amount of DT needed to buy 1 Ocean', async () => {
|
||||||
|
const requiredOcean = await Pool.getDTNeeded(alicePoolAddress, '1')
|
||||||
|
assert(Number(requiredOcean) > 0)
|
||||||
|
})
|
||||||
|
|
||||||
it('Bob should search for pools with this DT', async () => {
|
it('Bob should search for pools with this DT', async () => {
|
||||||
const pools = await Pool.searchPoolforDT(tokenAddress)
|
const pools = await Pool.searchPoolforDT(tokenAddress)
|
||||||
assert(pools.length > 0)
|
assert(pools.length > 0)
|
||||||
greatPool = pools[0]
|
greatPool = pools[0]
|
||||||
})
|
})
|
||||||
it('Bob should buy a DT ', async () => {
|
it('Bob should buy 2 DT ', async () => {
|
||||||
const maxPrice = parseFloat(currentDtPrice) * 2
|
const maxPrice = parseFloat(currentDtPrice) * 2
|
||||||
await Pool.buyDT(bob, greatPool, '1', '2', String(maxPrice))
|
await Pool.buyDT(bob, greatPool, '2', '4')
|
||||||
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
|
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
|
||||||
const bobOceanBalance = await datatoken.balance(oceanTokenAddress, bob)
|
const bobOceanBalance = await datatoken.balance(oceanTokenAddress, bob)
|
||||||
assert(Number(bobDtBalance) > 0)
|
assert(Number(bobDtBalance) > 0)
|
||||||
assert(Number(bobOceanBalance) > 0)
|
assert(Number(bobOceanBalance) > 0)
|
||||||
})
|
})
|
||||||
|
it('Bob should sell 1 DT ', async () => {
|
||||||
|
const maxPrice = parseFloat(currentDtPrice) * 2
|
||||||
|
await Pool.sellDT(bob, greatPool, '1', '1')
|
||||||
|
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
|
||||||
|
const bobOceanBalance = await datatoken.balance(oceanTokenAddress, bob)
|
||||||
|
assert(Number(bobDtBalance) === 1)
|
||||||
|
assert(Number(bobOceanBalance) > 0)
|
||||||
|
})
|
||||||
|
it('Bob should get maximum DT liquidity that he can add to pool ', async () => {
|
||||||
|
const maxDT = await Pool.getDTMaxAddLiquidity(greatPool)
|
||||||
|
if (consoleDebug) console.error('maxDT:' + maxDT)
|
||||||
|
assert(parseFloat(maxDT) > 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Bob should fail to add more than maximum DT liquidity that he can add to pool ', async () => {
|
||||||
|
const maxDT = await Pool.getDTMaxAddLiquidity(greatPool)
|
||||||
|
const tx = await Pool.addDTLiquidity(bob, greatPool, String(parseFloat(maxDT) * 2))
|
||||||
|
assert(tx === null)
|
||||||
|
})
|
||||||
it('Bob should add DT liquidity to pool ', async () => {
|
it('Bob should add DT liquidity to pool ', async () => {
|
||||||
|
const maxDT = await Pool.getDTMaxAddLiquidity(greatPool)
|
||||||
|
if (consoleDebug) console.error('maxDT:' + maxDT)
|
||||||
const currentDtReserve = await Pool.getDTReserve(greatPool)
|
const currentDtReserve = await Pool.getDTReserve(greatPool)
|
||||||
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
|
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
|
||||||
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
|
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
|
||||||
if (consoleDebug) console.log('BOB DT Balance:' + bobDtBalance)
|
if (consoleDebug) console.log('BOB DT Balance:' + bobDtBalance)
|
||||||
await Pool.addDTLiquidity(bob, greatPool, bobDtBalance)
|
await Pool.addDTLiquidity(
|
||||||
|
bob,
|
||||||
|
greatPool,
|
||||||
|
String(Math.min(parseFloat(maxDT), parseFloat(bobDtBalance)))
|
||||||
|
)
|
||||||
|
|
||||||
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
|
const newbobDtBalance = await datatoken.balance(tokenAddress, bob)
|
||||||
|
|
||||||
@ -204,7 +233,37 @@ describe('Balancer flow', () => {
|
|||||||
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
|
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
|
||||||
assert(parseFloat(sharesBalance) > 0)
|
assert(parseFloat(sharesBalance) > 0)
|
||||||
})
|
})
|
||||||
|
it('Bob should get maximum DT liquidity that he can remove from pool ', async () => {
|
||||||
|
const maxDT = await Pool.getDTMaxRemoveLiquidity(greatPool)
|
||||||
|
if (consoleDebug) console.log('maxDT:' + maxDT)
|
||||||
|
assert(parseFloat(maxDT) > 0)
|
||||||
|
})
|
||||||
|
it('Bob should know how many Pool Shares he needs to remove 1 DT ', async () => {
|
||||||
|
const poolShares = await Pool.getPoolSharesRequiredToRemoveDT(greatPool, '1')
|
||||||
|
if (consoleDebug) console.log('poolShares:' + poolShares)
|
||||||
|
assert(parseFloat(poolShares) > 0)
|
||||||
|
})
|
||||||
|
it('Bob should know how many DT gets in exchange of his Pool Shares', async () => {
|
||||||
|
const poolShares = await Pool.getDTRemovedforPoolShares(
|
||||||
|
greatPool,
|
||||||
|
await Pool.sharesBalance(bob, greatPool)
|
||||||
|
)
|
||||||
|
if (consoleDebug) console.log('poolShares:' + poolShares)
|
||||||
|
assert(parseFloat(poolShares) > 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Bob should fail to remove more than maximum DT liquidity that he can remove from the pool ', async () => {
|
||||||
|
const maxDT = await Pool.getDTMaxRemoveLiquidity(greatPool)
|
||||||
|
if (consoleDebug) console.log('maxDT:' + maxDT)
|
||||||
|
const poolShares = await Pool.sharesBalance(bob, greatPool)
|
||||||
|
const tx = await Pool.removeDTLiquidity(
|
||||||
|
bob,
|
||||||
|
greatPool,
|
||||||
|
String(parseFloat(maxDT) * 2),
|
||||||
|
poolShares
|
||||||
|
)
|
||||||
|
assert(tx === null)
|
||||||
|
})
|
||||||
it('Bob should remove DT liquidity from pool ', async () => {
|
it('Bob should remove DT liquidity from pool ', async () => {
|
||||||
const currentDtReserve = await Pool.getDTReserve(greatPool)
|
const currentDtReserve = await Pool.getDTReserve(greatPool)
|
||||||
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
|
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
|
||||||
@ -212,7 +271,14 @@ describe('Balancer flow', () => {
|
|||||||
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
|
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
|
||||||
const poolShares = await Pool.sharesBalance(bob, greatPool)
|
const poolShares = await Pool.sharesBalance(bob, greatPool)
|
||||||
if (consoleDebug) console.log('poolShares:' + poolShares)
|
if (consoleDebug) console.log('poolShares:' + poolShares)
|
||||||
await Pool.removeDTLiquidity(bob, greatPool, '0.75', poolShares)
|
const maxDT = await Pool.getMaxRemoveLiquidity(greatPool, tokenAddress)
|
||||||
|
if (consoleDebug) console.log('maxDT:' + maxDT)
|
||||||
|
await Pool.removeDTLiquidity(
|
||||||
|
bob,
|
||||||
|
greatPool,
|
||||||
|
String(Math.min(parseFloat(maxDT), parseFloat('0.75'))),
|
||||||
|
poolShares
|
||||||
|
)
|
||||||
|
|
||||||
const newDtReserve = await Pool.getDTReserve(greatPool)
|
const newDtReserve = await Pool.getDTReserve(greatPool)
|
||||||
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
|
if (consoleDebug) console.log('newDtReserve:' + newDtReserve)
|
||||||
@ -225,13 +291,33 @@ describe('Balancer flow', () => {
|
|||||||
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
|
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Bob should get maximum Ocean liquidity that he can add to pool ', async () => {
|
||||||
|
const maxOcean = await Pool.getOceanMaxAddLiquidity(greatPool)
|
||||||
|
assert(parseFloat(maxOcean) > 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Bob should fail to add more than maximum Ocean liquidity that he can add to pool ', async () => {
|
||||||
|
const maxOcean = await Pool.getOceanMaxAddLiquidity(greatPool)
|
||||||
|
const tx = await Pool.addOceanLiquidity(
|
||||||
|
bob,
|
||||||
|
greatPool,
|
||||||
|
String(parseFloat(maxOcean) * 2)
|
||||||
|
)
|
||||||
|
assert(tx === null)
|
||||||
|
})
|
||||||
|
|
||||||
it('Bob should add Ocean liquidity to pool ', async () => {
|
it('Bob should add Ocean liquidity to pool ', async () => {
|
||||||
const currentDtReserve = await Pool.getOceanReserve(greatPool)
|
const currentDtReserve = await Pool.getOceanReserve(greatPool)
|
||||||
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
||||||
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
|
if (consoleDebug) console.log('currentDtReserve:' + currentDtReserve)
|
||||||
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
|
if (consoleDebug) console.log('bobDtBalance:' + bobDtBalance)
|
||||||
|
const maxOcean = await Pool.getOceanMaxAddLiquidity(greatPool)
|
||||||
|
|
||||||
await Pool.addOceanLiquidity(bob, greatPool, '1')
|
await Pool.addOceanLiquidity(
|
||||||
|
bob,
|
||||||
|
greatPool,
|
||||||
|
String(Math.min(parseFloat(maxOcean), parseFloat(bobDtBalance)))
|
||||||
|
)
|
||||||
|
|
||||||
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
||||||
|
|
||||||
@ -245,6 +331,34 @@ describe('Balancer flow', () => {
|
|||||||
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
|
assert(parseFloat(newDtReserve) > parseFloat(currentDtReserve))
|
||||||
assert(parseFloat(sharesBalance) > 0)
|
assert(parseFloat(sharesBalance) > 0)
|
||||||
})
|
})
|
||||||
|
it('Bob should get maximum Ocean liquidity that he can remove from pool ', async () => {
|
||||||
|
const maxOcean = await Pool.getMaxRemoveLiquidity(greatPool, oceanTokenAddress)
|
||||||
|
assert(parseFloat(maxOcean) > 0)
|
||||||
|
})
|
||||||
|
it('Bob should fail to remove more than maximum Ocean liquidity that he can remove from the pool ', async () => {
|
||||||
|
const maxOcean = await Pool.getOceanMaxRemoveLiquidity(greatPool)
|
||||||
|
const poolShares = await Pool.sharesBalance(bob, greatPool)
|
||||||
|
const tx = await Pool.removeOceanLiquidity(
|
||||||
|
bob,
|
||||||
|
greatPool,
|
||||||
|
String(parseFloat(maxOcean) * 2),
|
||||||
|
poolShares
|
||||||
|
)
|
||||||
|
assert(tx === null)
|
||||||
|
})
|
||||||
|
it('Bob should know how many Pool Shares he needs to remove 1 OCEAN ', async () => {
|
||||||
|
const poolShares = await Pool.getPoolSharesRequiredToRemoveOcean(greatPool, '1')
|
||||||
|
if (consoleDebug) console.log('poolShares:' + poolShares)
|
||||||
|
assert(parseFloat(poolShares) > 0)
|
||||||
|
})
|
||||||
|
it('Bob should know how many OCEAN gets in exchange of his Pool Shares', async () => {
|
||||||
|
const poolShares = await Pool.getOceanRemovedforPoolShares(
|
||||||
|
greatPool,
|
||||||
|
await Pool.sharesBalance(bob, greatPool)
|
||||||
|
)
|
||||||
|
if (consoleDebug) console.log('poolShares:' + poolShares)
|
||||||
|
assert(parseFloat(poolShares) > 0)
|
||||||
|
})
|
||||||
|
|
||||||
it('Bob should remove Ocean liquidity from pool ', async () => {
|
it('Bob should remove Ocean liquidity from pool ', async () => {
|
||||||
const currentDtReserve = await Pool.getOceanReserve(greatPool)
|
const currentDtReserve = await Pool.getOceanReserve(greatPool)
|
||||||
@ -269,6 +383,18 @@ describe('Balancer flow', () => {
|
|||||||
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
|
assert(parseFloat(poolShares) > parseFloat(newpoolShares))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('ALice should remove all liquidity', async () => {
|
||||||
|
const aliceShares = await Pool.sharesBalance(alice, greatPool)
|
||||||
|
const aliceDtBalance = await datatoken.balance(tokenAddress, alice)
|
||||||
|
const aliceOceanBalance = await datatoken.balance(oceanTokenAddress, alice)
|
||||||
|
await Pool.removePoolLiquidity(alice, greatPool, aliceShares)
|
||||||
|
const newAliceDtBalance = await datatoken.balance(tokenAddress, alice)
|
||||||
|
const newAliceOceanBalance = await datatoken.balance(oceanTokenAddress, alice)
|
||||||
|
const newAliceShares = await Pool.sharesBalance(alice, greatPool)
|
||||||
|
assert(parseFloat(aliceDtBalance) < parseFloat(newAliceDtBalance))
|
||||||
|
assert(parseFloat(aliceOceanBalance) < parseFloat(newAliceOceanBalance))
|
||||||
|
assert(parseFloat(aliceShares) > parseFloat(newAliceShares))
|
||||||
|
})
|
||||||
it('ALice should get all the pools that she created', async () => {
|
it('ALice should get all the pools that she created', async () => {
|
||||||
const alicePools = await Pool.getPoolsbyCreator(alice)
|
const alicePools = await Pool.getPoolsbyCreator(alice)
|
||||||
assert(alicePools.length > 0)
|
assert(alicePools.length > 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user