2022-02-16 19:42:35 +01:00
|
|
|
import { approve, Pool, PoolPriceAndFees } from '@oceanprotocol/lib'
|
2022-02-14 17:27:36 +01:00
|
|
|
import Web3 from 'web3'
|
|
|
|
import { getSiteMetadata } from './siteConfig'
|
|
|
|
import { getDummyWeb3 } from './web3'
|
|
|
|
import { TransactionReceipt } from 'web3-eth'
|
|
|
|
import Decimal from 'decimal.js'
|
|
|
|
import { AccessDetails } from 'src/@types/Price'
|
2022-03-09 13:58:54 +01:00
|
|
|
import { isValidNumber } from './numbers'
|
|
|
|
import { MAX_DECIMALS } from './constants'
|
2022-02-14 17:27:36 +01:00
|
|
|
/**
|
|
|
|
* This is used to calculate the price to buy one datatoken from a pool, that is different from spot price. You need to pass either a web3 object or a chainId. If you pass a chainId a dummy web3 object will be created
|
|
|
|
* @param {AccessDetails} accessDetails
|
|
|
|
* @param {Web3?} [web3]
|
|
|
|
* @param {number?} [chainId]
|
2022-02-16 19:42:35 +01:00
|
|
|
* @return {Promise<PoolPriceAndFees>}
|
2022-02-14 17:27:36 +01:00
|
|
|
*/
|
|
|
|
export async function calculateBuyPrice(
|
|
|
|
accessDetails: AccessDetails,
|
|
|
|
chainId?: number,
|
|
|
|
web3?: Web3
|
2022-02-16 19:42:35 +01:00
|
|
|
): Promise<PoolPriceAndFees> {
|
2022-02-14 17:27:36 +01:00
|
|
|
if (!web3 && !chainId)
|
|
|
|
throw new Error("web3 and chainId can't be undefined at the same time!")
|
|
|
|
|
|
|
|
if (!web3) {
|
|
|
|
web3 = await getDummyWeb3(chainId)
|
|
|
|
}
|
|
|
|
|
|
|
|
const pool = new Pool(web3)
|
|
|
|
const { appConfig } = getSiteMetadata()
|
|
|
|
const estimatedPrice = await pool.getAmountInExactOut(
|
|
|
|
accessDetails.addressOrId,
|
|
|
|
accessDetails.baseToken.address,
|
|
|
|
accessDetails.datatoken.address,
|
|
|
|
'1',
|
|
|
|
appConfig.consumeMarketPoolSwapFee
|
|
|
|
)
|
|
|
|
|
|
|
|
return estimatedPrice
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function buyDtFromPool(
|
|
|
|
accessDetails: AccessDetails,
|
|
|
|
accountId: string,
|
|
|
|
web3: Web3
|
|
|
|
): Promise<TransactionReceipt> {
|
|
|
|
const pool = new Pool(web3)
|
|
|
|
const { appConfig } = getSiteMetadata()
|
|
|
|
// we need to calculate the actual price to buy one datatoken
|
|
|
|
const dtPrice = await calculateBuyPrice(accessDetails, null, web3)
|
|
|
|
const approveTx = await approve(
|
|
|
|
web3,
|
|
|
|
accountId,
|
|
|
|
accessDetails.baseToken.address,
|
|
|
|
accessDetails.addressOrId,
|
2022-02-16 19:42:35 +01:00
|
|
|
dtPrice.tokenAmount,
|
2022-02-14 17:27:36 +01:00
|
|
|
false
|
|
|
|
)
|
2022-03-11 12:25:51 +01:00
|
|
|
if (!approveTx) {
|
|
|
|
return
|
|
|
|
}
|
2022-02-14 17:27:36 +01:00
|
|
|
const result = await pool.swapExactAmountOut(
|
|
|
|
accountId,
|
|
|
|
accessDetails.addressOrId,
|
|
|
|
{
|
|
|
|
marketFeeAddress: appConfig.marketFeeAddress,
|
|
|
|
tokenIn: accessDetails.baseToken.address,
|
|
|
|
tokenOut: accessDetails.datatoken.address
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// this is just to be safe
|
2022-02-16 19:42:35 +01:00
|
|
|
maxAmountIn: new Decimal(dtPrice.tokenAmount).mul(10).toString(),
|
2022-02-14 17:27:36 +01:00
|
|
|
swapMarketFee: appConfig.consumeMarketPoolSwapFee,
|
|
|
|
tokenAmountOut: '1'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
2022-03-09 13:58:54 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate the base token liquidity based on shares info
|
|
|
|
* @param {string} shares
|
|
|
|
* @param {string} totalShares
|
|
|
|
* @param {string} baseTokenLiquidity
|
|
|
|
* @returns
|
|
|
|
*/
|
|
|
|
export function calculateUserLiquidity(
|
|
|
|
shares: string,
|
|
|
|
totalShares: string,
|
|
|
|
baseTokenLiquidity: string
|
|
|
|
): string {
|
|
|
|
const totalLiquidity =
|
|
|
|
isValidNumber(shares) &&
|
|
|
|
isValidNumber(totalShares) &&
|
|
|
|
isValidNumber(baseTokenLiquidity)
|
|
|
|
? new Decimal(shares)
|
|
|
|
.dividedBy(new Decimal(totalShares))
|
|
|
|
.mul(baseTokenLiquidity)
|
|
|
|
: new Decimal(0)
|
|
|
|
return totalLiquidity.toDecimalPlaces(MAX_DECIMALS).toString()
|
|
|
|
}
|
|
|
|
|
|
|
|
export function calculateUserTVL(
|
|
|
|
shares: string,
|
|
|
|
totalShares: string,
|
|
|
|
baseTokenLiquidity: string
|
|
|
|
): string {
|
|
|
|
const liquidity = calculateUserLiquidity(
|
|
|
|
shares,
|
|
|
|
totalShares,
|
|
|
|
baseTokenLiquidity
|
|
|
|
)
|
|
|
|
const tvl = new Decimal(liquidity).mul(2) // we multiply by 2 because of 50/50 weight
|
|
|
|
return tvl.toDecimalPlaces(MAX_DECIMALS).toString()
|
|
|
|
}
|