Commit 6089d38d authored by Jack Short's avatar Jack Short Committed by GitHub

feat: adding price scaling for sudoswap xyk pool (#5804)

* feat: adding price scaling for sudoswap xyk pool

* big number

* updating pricing logic for xyk

* fixing sweep

* removing isnotxykpool

* sudoswap calc refactoring

* refactoring calcpoolprice to include sudoswap

* refactoring calcpoolprice

* not letting asset items equal to 0 to be added

* removing comment
parent 3c6e067e
import { parseEther } from 'ethers/lib/utils'
import gql from 'graphql-tag'
import { GenieAsset, Markets, Trait } from 'nft/types'
import { isNotXYKPool, wrapScientificNotation } from 'nft/utils'
import { wrapScientificNotation } from 'nft/utils'
import { useCallback, useMemo } from 'react'
import {
......@@ -219,7 +219,7 @@ export function useNftAssets(params: AssetFetcherParams) {
return useMemo(() => {
return {
data: assets?.filter((asset) => isNotXYKPool(asset)),
data: assets,
hasNext,
loading,
loadMore,
......@@ -279,5 +279,5 @@ export function useSweepNftAssets(params: SweepFetcherParams) {
}),
[data?.nftAssets?.edges, data?.nftAssets?.totalCount]
)
return useMemo(() => ({ data: assets?.filter((asset) => isNotXYKPool(asset)), loading }), [assets, loading])
return useMemo(() => ({ data: assets, loading }), [assets, loading])
}
......@@ -89,7 +89,7 @@ export const CollectionAsset = ({
}, [asset])
const handleAddAssetToBag = useCallback(() => {
if (BigNumber.from(asset.priceInfo?.ETHPrice ?? 0).gte(0)) {
if (BigNumber.from(asset.priceInfo?.ETHPrice ?? 0).gt(0)) {
addAssetsToBag([asset])
if (!bagExpanded && !isMobile && !bagManuallyClosed) {
setBagExpanded({ bagExpanded: true })
......
......@@ -41,7 +41,6 @@ import {
} from 'nft/types'
import {
calcPoolPrice,
calcSudoSwapPrice,
getRarityStatus,
isInSameMarketplaceCollection,
isInSameSudoSwapPool,
......@@ -307,7 +306,6 @@ export const CollectionNfts = ({ contractAddress, collectionStats, rarityVerifie
const calculatePrice = useCallback(
(asset: GenieAsset) => {
if (asset.marketplace === Markets.Sudoswap) return calcSudoSwapPrice(asset, getPoolPosition(asset))
return calcPoolPrice(asset, getPoolPosition(asset))
},
[getPoolPosition]
......
......@@ -5,7 +5,7 @@ import { formatEther, parseEther } from '@ethersproject/units'
import { SweepFetcherParams, useSweepNftAssets } from 'graphql/data/nft/Asset'
import { useBag, useCollectionFilters } from 'nft/hooks'
import { GenieAsset, isPooledMarket, Markets } from 'nft/types'
import { calcPoolPrice, calcSudoSwapPrice, formatWeiToDecimal, isInSameSudoSwapPool } from 'nft/utils'
import { calcPoolPrice, formatWeiToDecimal, isInSameSudoSwapPool } from 'nft/utils'
import { default as Slider } from 'rc-slider'
import { useEffect, useMemo, useReducer, useState } from 'react'
import styled, { useTheme } from 'styled-components/macro'
......@@ -204,7 +204,7 @@ export const Sweep = ({ contractAddress, minPrice, maxPrice }: SweepProps) => {
jointCollections.forEach((asset) => {
if (!asset.susFlag) {
if (asset.marketplace === Markets.Sudoswap) {
const poolPrice = calcSudoSwapPrice(
const poolPrice = calcPoolPrice(
asset,
sudoSwapAssetsInJointCollections
.filter((sweepAsset) => isInSameSudoSwapPool(asset, sweepAsset))
......@@ -229,7 +229,7 @@ export const Sweep = ({ contractAddress, minPrice, maxPrice }: SweepProps) => {
})
let validAssets = jointCollections.filter(
(asset) => BigNumber.from(asset.priceInfo.ETHPrice).gte(0) && !asset.susFlag
(asset) => BigNumber.from(asset.priceInfo.ETHPrice).gt(0) && !asset.susFlag
)
validAssets = validAssets.slice(
......
import { DetailsOrigin, GenieAsset, Markets, UpdatedGenieAsset, WalletAsset } from 'nft/types'
import { calcSudoSwapPrice } from './pooledAssets'
import { DetailsOrigin, GenieAsset, UpdatedGenieAsset, WalletAsset } from 'nft/types'
export function getRarityStatus(
rarityStatusCache: Map<string, boolean>,
......@@ -46,11 +44,3 @@ export const generateTweetForPurchase = (assets: UpdatedGenieAsset[], txHashUrl:
} with @Uniswap 🦄\n\nhttps://app.uniswap.org/#/nfts/collection/0x60bb1e2aa1c9acafb4d34f71585d7e959f387769\n${txHashUrl}`
return `https://twitter.com/intent/tweet?text=${encodeURIComponent(tweetText)}`
}
// TODO: remove when BE supports SudoSwap XYK pools
export const isNotXYKPool = (asset: GenieAsset): boolean => {
if (asset.marketplace !== Markets.Sudoswap) return true
if (calcSudoSwapPrice(asset) === undefined) return false
return true
}
......@@ -8,6 +8,7 @@ const PROTOCOL_FEE_MULTIPLIER = BigNumber.from('5000000000000000')
enum BondingCurve {
Linear = 'LINEAR',
Exponential = 'EXPONENTIAL',
Xyk = 'XYK',
}
interface Pool {
......@@ -32,6 +33,50 @@ const calculateScaledPrice = (currentPrice: BigNumber, poolFee: BigNumber): BigN
return currentPrice.add(protocolFee).add(tradeFee)
}
const calcSudoSwapLinearBondingCurve = (currentPrice: BigNumber, delta: BigNumber, position = 0): BigNumber => {
for (let i = 0; i <= position; i++) {
currentPrice = currentPrice.add(delta)
}
return currentPrice
}
const calcSudoSwapExponentialBondingCurve = (currentPrice: BigNumber, delta: BigNumber, position = 0): BigNumber => {
for (let i = 0; i <= position; i++) {
currentPrice = currentPrice.mul(delta).div(BigNumber.from(PRECISION))
}
return currentPrice
}
const calcSudoSwapXykBondingCurve = (
currentPrice: BigNumber,
sudoSwapPool: Pool,
position = 0
): BigNumber | undefined => {
let virtualTokenBalance = BigNumber.from(sudoSwapPool.spotPrice)
let virtualNFTBalance = BigNumber.from(sudoSwapPool.delta)
if (virtualNFTBalance.sub(BigNumber.from(1)).gt(BigNumber.from(0))) {
currentPrice = virtualTokenBalance.div(virtualNFTBalance.sub(BigNumber.from(1)))
} else {
return undefined
}
for (let i = 1; i <= position; i++) {
virtualTokenBalance = virtualTokenBalance.add(currentPrice)
virtualNFTBalance = virtualNFTBalance.sub(BigNumber.from(1))
if (!virtualNFTBalance.sub(BigNumber.from(1)).isZero()) {
currentPrice = virtualTokenBalance.div(virtualNFTBalance.sub(BigNumber.from(1)))
} else {
return undefined
}
}
return currentPrice
}
export const calcSudoSwapPrice = (asset: GenieAsset, position = 0): string | undefined => {
if (!asset.sellorders) return undefined
......@@ -45,19 +90,25 @@ export const calcSudoSwapPrice = (asset: GenieAsset, position = 0): string | und
const delta = BigNumber.from(sudoSwapPool.delta)
const poolFee = BigNumber.from(sudoSwapPool.fee)
for (let i = 0; i <= position; i++) {
if (sudoSwapPool.bondingCurve === BondingCurve.Linear) {
currentPrice = currentPrice.add(delta)
currentPrice = calcSudoSwapLinearBondingCurve(currentPrice, delta, position)
} else if (sudoSwapPool.bondingCurve === BondingCurve.Exponential) {
currentPrice = currentPrice.mul(delta).div(BigNumber.from(PRECISION))
currentPrice = calcSudoSwapExponentialBondingCurve(currentPrice, delta, position)
} else if (sudoSwapPool.bondingCurve === BondingCurve.Xyk) {
const xykCurrentPrice = calcSudoSwapXykBondingCurve(currentPrice, sudoSwapPool, position)
if (xykCurrentPrice) {
currentPrice = xykCurrentPrice
} else {
return undefined
}
} else {
return undefined
}
return calculateScaledPrice(currentPrice, poolFee).toString()
}
// TODO: a lot of the below typecasting logic can be simplified when GraphQL migration is complete
export const calcPoolPrice = (asset: GenieAsset, position = 0) => {
const calcAmmBasedPoolprice = (asset: GenieAsset, position = 0): string => {
if (!asset.sellorders) return ''
let amountToBuy: BigNumber = BigNumber.from(0)
......@@ -120,6 +171,12 @@ export const calcPoolPrice = (asset: GenieAsset, position = 0) => {
return price.toString()
}
export const calcPoolPrice = (asset: GenieAsset, position = 0): string => {
if (!asset.sellorders) return ''
if (asset.marketplace === Markets.Sudoswap) return calcSudoSwapPrice(asset, position) ?? '0'
return calcAmmBasedPoolprice(asset, position)
}
export const calcAvgGroupPoolPrice = (asset: GenieAsset, numberOfAssets: number) => {
let total = BigNumber.from(0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment