mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-11-26 20:39:05 +01:00
add pool validation and helpers
This commit is contained in:
parent
a4d3c063d9
commit
8de3d29b2f
@ -3,6 +3,7 @@ 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 { parse } from 'path'
|
||||||
|
|
||||||
declare type PoolTransactionType = 'swap' | 'join' | 'exit'
|
declare type PoolTransactionType = 'swap' | 'join' | 'exit'
|
||||||
|
|
||||||
@ -143,6 +144,189 @@ export class OceanPool extends Pool {
|
|||||||
return super.getReserve(poolAddress, dtAddress)
|
return super.getReserve(poolAddress, dtAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 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)
|
||||||
|
return String(parseFloat(balance) / 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
return String(parseFloat(balance) / 3)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buy Data Token from a pool
|
* Buy Data Token from a pool
|
||||||
* @param {String} account
|
* @param {String} account
|
||||||
@ -155,31 +339,51 @@ 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('oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
if (!maxPrice) {
|
||||||
|
maxPrice = String(2 ** 256 - 1)
|
||||||
|
}
|
||||||
const dtAddress = await this.getDTAddress(poolAddress)
|
const dtAddress = await this.getDTAddress(poolAddress)
|
||||||
|
if (
|
||||||
|
parseFloat(dtAmountWanted) >
|
||||||
|
parseFloat(await this.getMaxBuyQuantity(poolAddress, dtAddress))
|
||||||
|
) {
|
||||||
|
console.error('Buy quantity exceeds quantity allowed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const calcInGivenOut = await this.calcInGivenOut(
|
||||||
|
poolAddress,
|
||||||
|
this.oceanAddress,
|
||||||
|
dtAddress,
|
||||||
|
dtAmountWanted
|
||||||
|
)
|
||||||
|
|
||||||
|
if (parseFloat(calcInGivenOut) > parseFloat(maxOceanAmount)) {
|
||||||
|
console.error('Not enough Ocean Tokens')
|
||||||
|
return null
|
||||||
|
}
|
||||||
// TODO - check balances first
|
// TODO - check balances first
|
||||||
await super.approve(
|
await super.approve(
|
||||||
account,
|
account,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
this.web3.utils.toWei(oceanAmount)
|
this.web3.utils.toWei(maxOceanAmount)
|
||||||
)
|
)
|
||||||
|
|
||||||
return this.swapExactAmountOut(
|
return this.swapExactAmountOut(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
oceanAmount,
|
maxOceanAmount,
|
||||||
dtAddress,
|
dtAddress,
|
||||||
amount,
|
dtAmountWanted,
|
||||||
maxPrice
|
maxPrice
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -188,7 +392,7 @@ export class OceanPool extends Pool {
|
|||||||
* Sell Data Token
|
* Sell Data Token
|
||||||
* @param {String} account
|
* @param {String} account
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
* @param {String} amount Data Token amount
|
* @param {String} amount Data Token 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,23 +400,43 @@ 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 (!maxPrice) {
|
||||||
|
maxPrice = String(2 ** 256 - 1)
|
||||||
|
}
|
||||||
if (this.oceanAddress == null) {
|
if (this.oceanAddress == null) {
|
||||||
console.error('oceanAddress is not defined')
|
console.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.getMaxBuyQuantity(poolAddress, this.oceanAddress))
|
||||||
|
) {
|
||||||
|
console.error('Buy quantity exceeds quantity allowed')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const calcOutGivenIn = await this.calcOutGivenIn(
|
||||||
|
poolAddress,
|
||||||
|
dtAddress,
|
||||||
|
this.oceanAddress,
|
||||||
|
dtAmount
|
||||||
|
)
|
||||||
|
if (parseFloat(calcOutGivenIn) < parseFloat(oceanAmountWanted)) {
|
||||||
|
console.error('Not enough Data Tokens')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return this.swapExactAmountIn(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
dtAddress,
|
dtAddress,
|
||||||
amount,
|
dtAmount,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
oceanAmount,
|
oceanAmountWanted,
|
||||||
minPrice
|
maxPrice
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +453,11 @@ 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)
|
||||||
|
const maxAmount = await this.getMaxAddLiquidity(poolAddress, dtAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('Too much reserve to add')
|
||||||
|
return null
|
||||||
|
}
|
||||||
await super.approve(account, dtAddress, poolAddress, this.web3.utils.toWei(amount))
|
await super.approve(account, dtAddress, poolAddress, this.web3.utils.toWei(amount))
|
||||||
const result = await super.joinswapExternAmountIn(
|
const result = await super.joinswapExternAmountIn(
|
||||||
account,
|
account,
|
||||||
@ -254,7 +483,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.getMaxRemoveLiquidity(poolAddress, dtAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('Too much reserve to remove')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const usershares = await this.sharesBalance(account, poolAddress)
|
||||||
|
if (parseFloat(usershares) < parseFloat(maximumPoolShares)) {
|
||||||
|
console.error('Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
parseFloat(maximumPoolShares) <
|
||||||
|
parseFloat(await this.calcPoolInGivenSingleOut(poolAddress, dtAddress, amount))
|
||||||
|
) {
|
||||||
|
console.error('Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
return this.exitswapExternAmountOut(
|
return this.exitswapExternAmountOut(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
@ -280,6 +525,11 @@ export class OceanPool extends Pool {
|
|||||||
console.error('oceanAddress is not defined')
|
console.error('oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
const maxAmount = await this.getMaxAddLiquidity(poolAddress, this.oceanAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('Too much reserve to add')
|
||||||
|
return null
|
||||||
|
}
|
||||||
await super.approve(
|
await super.approve(
|
||||||
account,
|
account,
|
||||||
this.oceanAddress,
|
this.oceanAddress,
|
||||||
@ -303,7 +553,7 @@ 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,
|
||||||
@ -313,7 +563,25 @@ export class OceanPool extends Pool {
|
|||||||
console.error('oceanAddress is not defined')
|
console.error('oceanAddress is not defined')
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// TODO Check balance of PoolShares before doing exit
|
const maxAmount = await this.getMaxRemoveLiquidity(poolAddress, this.oceanAddress)
|
||||||
|
if (parseFloat(amount) > parseFloat(maxAmount)) {
|
||||||
|
console.error('Too much reserve to remove')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const usershares = await this.sharesBalance(account, poolAddress)
|
||||||
|
if (parseFloat(usershares) < parseFloat(maximumPoolShares)) {
|
||||||
|
console.error('Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
parseFloat(maximumPoolShares) <
|
||||||
|
parseFloat(
|
||||||
|
await this.calcPoolInGivenSingleOut(poolAddress, this.oceanAddress, amount)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
console.error('Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
return super.exitswapExternAmountOut(
|
return super.exitswapExternAmountOut(
|
||||||
account,
|
account,
|
||||||
poolAddress,
|
poolAddress,
|
||||||
@ -323,6 +591,27 @@ export class OceanPool extends Pool {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove pool liquidity
|
||||||
|
* @param {String} account
|
||||||
|
* @param {String} poolAddress
|
||||||
|
* @param {String} poolShares
|
||||||
|
* @return {TransactionReceipt}
|
||||||
|
*/
|
||||||
|
public async removePoolLiquidity(
|
||||||
|
account: string,
|
||||||
|
poolAddress: string,
|
||||||
|
poolShares: string
|
||||||
|
): Promise<TransactionReceipt> {
|
||||||
|
const usershares = await this.sharesBalance(account, poolAddress)
|
||||||
|
if (parseFloat(usershares) < parseFloat(poolShares)) {
|
||||||
|
console.error('Not enough poolShares')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.exitPool(account, poolAddress, poolShares, ['0', '0'])
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Data Token price from pool
|
* Get Data Token price from pool
|
||||||
* @param {String} poolAddress
|
* @param {String} poolAddress
|
||||||
@ -358,19 +647,7 @@ 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)
|
|
||||||
const swapFee = await this.getSwapFee(poolAddress)
|
|
||||||
return super.calcInGivenOut(
|
|
||||||
tokenBalanceIn,
|
|
||||||
tokenWeightIn,
|
|
||||||
tokenBalanceOut,
|
|
||||||
tokenWeightOut,
|
|
||||||
dtRequired,
|
|
||||||
swapFee
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -270,6 +270,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
|
||||||
@ -594,7 +611,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 +816,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 +824,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
@ -185,12 +185,29 @@ describe('Balancer flow', () => {
|
|||||||
assert(Number(bobDtBalance) > 0)
|
assert(Number(bobDtBalance) > 0)
|
||||||
assert(Number(bobOceanBalance) > 0)
|
assert(Number(bobOceanBalance) > 0)
|
||||||
})
|
})
|
||||||
|
it('Bob should get maximum DT liquidity that he can add to pool ', async () => {
|
||||||
|
const maxDT = await Pool.getMaxAddLiquidity(greatPool, tokenAddress)
|
||||||
|
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.getMaxAddLiquidity(greatPool, tokenAddress)
|
||||||
|
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.getMaxAddLiquidity(greatPool, tokenAddress)
|
||||||
|
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 +221,23 @@ 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.getMaxRemoveLiquidity(greatPool, tokenAddress)
|
||||||
|
if (consoleDebug) console.log('maxDT:' + maxDT)
|
||||||
|
assert(parseFloat(maxDT) > 0)
|
||||||
|
})
|
||||||
|
it('Bob should fail to remove more than maximum DT liquidity that he can remove from the pool ', async () => {
|
||||||
|
const maxDT = await Pool.getMaxRemoveLiquidity(greatPool, tokenAddress)
|
||||||
|
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 +245,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 +265,28 @@ 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.getMaxAddLiquidity(greatPool, oceanTokenAddress)
|
||||||
|
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.getMaxAddLiquidity(greatPool, oceanTokenAddress)
|
||||||
|
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.getMaxAddLiquidity(greatPool, oceanTokenAddress)
|
||||||
await Pool.addOceanLiquidity(bob, greatPool, '1')
|
await Pool.addOceanLiquidity(bob, greatPool, maxOcean)
|
||||||
|
|
||||||
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
const newbobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
||||||
|
|
||||||
@ -245,7 +300,21 @@ 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.getMaxRemoveLiquidity(greatPool, oceanTokenAddress)
|
||||||
|
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 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)
|
||||||
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
const bobDtBalance = await datatoken.balance(oceanTokenAddress, bob)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user