1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Restore trade tab (#1047)

* get swap fee, max values

* use baseToken instead of ocean

* build fixes

* set form trade tx - WIP

* use pool info

* logs deleted

* merge fixes

* use local ocean.js, get spot price

* handle value changes, logs deleted

* fixes after v4 merge

* valid user liquidity displayed

* get correct token amount

* more fixes

* form trade fixes

* positive input values fix

* use proper swap functions

* use appConfig's marketFeeAddress

* remove redundant setters

* use consumeMarketPoolSwapFee

* use poolInfo, remove log

* code fixes

* some more fixes

* fees fix

* use poolInfo data

* various fixes

* fixes and cleanup

* fix build

* partial decimal fix

* add swap fee

* fix sub updates

* remove console

* fix package

* fix package-lock

* remove ssh

* fix blockies and package

* fix comments

* remove unused var

Co-authored-by: ClaudiaHolhos <claudia@oceanprotocol.com>
Co-authored-by: mihaisc <mihai@oceanprotocol.com>
This commit is contained in:
claudiaHash 2022-03-03 12:49:04 +02:00 committed by GitHub
parent b63c644962
commit 8a5bddbf6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1387 additions and 3948 deletions

4611
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
"@coingecko/cryptoformat": "^0.4.4",
"@loadable/component": "^5.15.2",
"@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^1.0.0-next.21",
"@oceanprotocol/lib": "^1.0.0-next.24",
"@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.6",
"@tippyjs/react": "^4.2.6",
@ -34,7 +34,6 @@
"decimal.js": "^10.3.1",
"dom-confetti": "^0.2.2",
"dotenv": "^15.0.0",
"ethereum-blockies": "github:MyEtherWallet/blockies",
"filesize": "^8.0.6",
"formik": "^2.2.9",
"gray-matter": "^4.0.3",
@ -43,6 +42,7 @@
"jwt-decode": "^3.1.2",
"lodash.debounce": "^4.0.8",
"lodash.omit": "^4.5.0",
"myetherwallet-blockies": "^0.1.1",
"next": "^12.1.0",
"query-string": "^7.1.0",
"react": "^17.0.2",

View File

@ -10,9 +10,9 @@ export const poolDataQuery = gql`
poolData: pool(id: $pool) {
id
totalShares
liquidityProviderFee
liquidityProviderSwapFee
opcFee
marketSwapFee
publishMarketSwapFee
spotPrice
baseToken {
address

View File

@ -5,12 +5,13 @@ import {
} from 'src/@types/subgraph/PoolData'
export interface PoolInfo {
poolFee: string
marketFee: string
opfFee: string
liquidityProviderSwapFee: string
publishMarketSwapFee: string
opcFee: string
weightBaseToken: string
weightDt: string
datatokenSymbol: string
datatokenAddress: string
baseTokenSymbol: string
baseTokenAddress: string
totalPoolTokens: string

View File

@ -118,11 +118,6 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
useEffect(() => {
if (!poolData) return
// Fees - this will be renamed again in subgraph
const poolFee = getFee(poolData.liquidityProviderFee)
const marketFee = getFee(poolData.marketSwapFee)
const opfFee = getFee(poolData.opcFee)
// Total Liquidity
const totalLiquidityInOcean = isValidNumber(poolData.spotPrice)
? new Decimal(poolData.baseTokenLiquidity).add(
@ -131,12 +126,13 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
: new Decimal(0)
const newPoolInfo = {
poolFee,
marketFee,
opfFee,
liquidityProviderSwapFee: getFee(poolData.liquidityProviderSwapFee),
publishMarketSwapFee: getFee(poolData.publishMarketSwapFee),
opcFee: getFee(poolData.opcFee),
weightBaseToken: getWeight(poolData.baseTokenWeight),
weightDt: getWeight(poolData.datatokenWeight),
datatokenSymbol: poolData.datatoken.symbol,
datatokenAddress: poolData.datatoken.address,
baseTokenSymbol: poolData.baseToken.symbol,
baseTokenAddress: poolData.baseToken.address,
totalPoolTokens: poolData.totalShares,
@ -193,6 +189,7 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
if (
!poolData ||
!poolInfo?.totalPoolTokens ||
!poolInfoUser?.poolShares ||
!asset?.chainId ||
!accountId ||
!poolInfoUser

View File

@ -1,3 +1,3 @@
declare module 'ethereum-blockies' {
declare module 'myetherwallet-blockies' {
export function toDataUrl(address: string): string
}

1
src/@utils/constants.ts Normal file
View File

@ -0,0 +1 @@
export const MAX_DECIMALS = 5

View File

@ -112,9 +112,10 @@ export async function setNftMetadata(
'0x' + metadataHash,
[]
)
console.log('[setNftMetadata] est Gas set metadata --', estGasSetMetadata)
LoggerInstance.log(
'[setNftMetadata] est Gas set metadata --',
estGasSetMetadata
)
const setMetadataTx = await nft.setMetadata(
asset.nftAddress,
accountId,

View File

@ -46,7 +46,6 @@ export default function FilesInput(props: InputProps): ReactElement {
props.value.length > 0 &&
typeof props.value[0] === 'string'
) {
console.log('loadFileInfo eff')
loadFileInfo(props.value[0].toString())
}
}, [loadFileInfo, props])

View File

@ -1,4 +1,4 @@
import { toDataUrl } from 'ethereum-blockies'
import { toDataUrl } from 'myetherwallet-blockies'
import React, { ReactElement } from 'react'
import styles from './Blockies.module.css'

View File

@ -46,7 +46,7 @@ export default function Pool(): ReactElement {
baseToken: new Decimal(poolData?.baseTokenLiquidity).toString(),
datatoken: new Decimal(poolData?.datatokenLiquidity).toString()
}}
swapFee={poolInfo?.poolFee}
swapFee={poolInfo?.liquidityProviderSwapFee}
datatokenSymbol={poolInfo?.datatokenSymbol}
tokenInAddress={poolInfo?.baseTokenAddress}
tokenInSymbol={poolInfo?.baseTokenSymbol}
@ -98,7 +98,7 @@ export default function Pool(): ReactElement {
<Tooltip
content={content.pool.tooltips.liquidity.replace(
'SWAPFEE',
poolInfo?.poolFee
poolInfo?.liquidityProviderSwapFee
)}
/>
{poolInfoUser?.poolShare && (

View File

@ -1,5 +1,11 @@
import React, { ReactElement, useState } from 'react'
import { Asset, LoggerInstance } from '@oceanprotocol/lib'
import {
AmountsInMaxFee,
AmountsOutMaxFee,
LoggerInstance,
Pool,
TokenInOutMarket
} from '@oceanprotocol/lib'
import * as Yup from 'yup'
import { Formik } from 'formik'
import Actions from '../Pool/Actions'
@ -15,36 +21,33 @@ import { FormTradeData } from './_types'
import { initialValues } from './_constants'
import content from '../../../../../content/price.json'
import { AssetExtended } from 'src/@types/AssetExtended'
import { usePool } from '@context/Pool'
import { useSiteMetadata } from '@hooks/useSiteMetadata'
export default function FormTrade({
asset,
balance,
maxDt,
maxOcean
balance
}: {
asset: AssetExtended
balance: PoolBalance
maxDt: string
maxOcean: string
}): ReactElement {
const { accountId } = useWeb3()
const { web3, accountId } = useWeb3()
const { isAssetNetwork } = useAsset()
const { debug } = useUserPreferences()
const { appConfig } = useSiteMetadata()
const { poolInfo } = usePool()
const [txId, setTxId] = useState<string>()
const [coinFrom, setCoinFrom] = useState<string>('OCEAN')
const [maximumOcean, setMaximumOcean] = useState(maxOcean)
const [maximumDt, setMaximumDt] = useState(maxDt)
const [maximumBaseToken, setMaximumBaseToken] = useState('0')
const [maximumDt, setMaximumDt] = useState('0')
const [isWarningAccepted, setIsWarningAccepted] = useState(false)
const tokenAddress = ''
const tokenSymbol = ''
const validationSchema: Yup.SchemaOf<FormTradeData> = Yup.object()
.shape({
ocean: Yup.number()
baseToken: Yup.number()
.max(
Number(maximumOcean),
Number(maximumBaseToken),
(param) => `Must be less or equal to ${param.max}`
)
.min(0.001, (param) => `Must be more or equal to ${param.min}`)
@ -64,32 +67,81 @@ export default function FormTrade({
.defined()
async function handleTrade(values: FormTradeData) {
if (!web3 || !asset || !poolInfo || !values) return
try {
const impact = new Decimal(
new Decimal(100).sub(new Decimal(values.slippage))
).div(100)
const precision = 15
// const tx =
// values.type === 'buy'
// ? await ocean.pool.buyDTWithExactOcean(
// accountId,
// price.address,
// new Decimal(values.datatoken)
// .mul(impact)
// .toFixed(precision)
// .toString(),
// new Decimal(values.ocean).toFixed(precision).toString()
// )
// : await ocean.pool.sellDT(
// accountId,
// price.address,
// new Decimal(values.datatoken).toFixed(precision).toString(),
// new Decimal(values.ocean)
// .mul(impact)
// .toFixed(precision)
// .toString()
// )
// setTxId(tx?.transactionHash)
const poolInstance = new Pool(web3)
let tx
if (values.output === 'exactIn') {
const tokenInOutMarket: TokenInOutMarket = {
tokenIn:
values.type === 'sell'
? poolInfo.datatokenAddress
: poolInfo.baseTokenAddress,
tokenOut:
values.type === 'sell'
? poolInfo.baseTokenAddress
: poolInfo.datatokenAddress,
marketFeeAddress: appConfig.marketFeeAddress
}
const amountsInOutMaxFee: AmountsInMaxFee = {
tokenAmountIn:
values.type === 'sell' ? values.datatoken : values.baseToken,
minAmountOut: new Decimal(
values.type === 'sell' ? values.baseToken : values.datatoken
)
.mul(
new Decimal(1)
.minus(new Decimal(values.slippage).div(new Decimal(100)))
.toString()
)
.toString(),
swapMarketFee: appConfig.consumeMarketPoolSwapFee
}
tx = await poolInstance.swapExactAmountIn(
accountId,
asset.accessDetails.addressOrId,
tokenInOutMarket,
amountsInOutMaxFee
)
}
if (values.output === 'exactOut') {
const tokenOutMarket: TokenInOutMarket = {
tokenIn:
values.type === 'sell'
? poolInfo.datatokenAddress
: poolInfo.baseTokenAddress,
tokenOut:
values.type === 'sell'
? poolInfo.baseTokenAddress
: poolInfo.datatokenAddress,
marketFeeAddress: appConfig.marketFeeAddress
}
const amountsOutMaxFee: AmountsOutMaxFee = {
maxAmountIn: new Decimal(
values.type === 'sell' ? values.datatoken : values.baseToken
)
.mul(
new Decimal(1)
.plus(new Decimal(values.slippage).div(new Decimal(100)))
.toString()
)
.toString(),
tokenAmountOut:
values.type === 'sell' ? values.baseToken : values.datatoken,
swapMarketFee: appConfig.consumeMarketPoolSwapFee
}
tx = await poolInstance.swapExactAmountOut(
accountId,
asset.accessDetails.addressOrId,
tokenOutMarket,
amountsOutMaxFee
)
}
setTxId(tx?.transactionHash)
} catch (error) {
LoggerInstance.error(error.message)
toast.error(error.message)
@ -112,10 +164,8 @@ export default function FormTrade({
<Swap
asset={asset}
balance={balance}
maxDt={maxDt}
maxOcean={maxOcean}
setCoin={setCoinFrom}
setMaximumOcean={setMaximumOcean}
setMaximumBaseToken={setMaximumBaseToken}
setMaximumDt={setMaximumDt}
/>
) : (
@ -154,8 +204,16 @@ export default function FormTrade({
}
action={submitForm}
txId={txId}
tokenAddress={tokenAddress}
tokenSymbol={tokenSymbol}
tokenAddress={
values.type === 'buy'
? poolInfo.baseTokenAddress
: poolInfo.datatokenAddress
}
tokenSymbol={
values.type === 'buy'
? poolInfo.baseTokenSymbol
: poolInfo.datatokenSymbol
}
setSubmitting={setSubmitting}
/>

View File

@ -4,73 +4,54 @@ import { useAsset } from '@context/Asset'
import Token from '../Pool/Token'
import styles from './Output.module.css'
import { isValidNumber } from '@utils/numbers'
import Decimal from 'decimal.js'
import { FormTradeData } from './_types'
import { usePool } from '@context/Pool'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
export default function Output({
dtSymbol,
oceanSymbol,
poolAddress
poolAddress,
lpSwapFee
}: {
dtSymbol: string
oceanSymbol: string
poolAddress: string
lpSwapFee: string
}): ReactElement {
const { isAssetNetwork } = useAsset()
const [maxOutput, setMaxOutput] = useState<string>()
const [swapFee, setSwapFee] = useState<string>()
const [swapFeeValue, setSwapFeeValue] = useState<string>()
const { poolInfo } = usePool()
const [outputWithSlippage, setOutputWithSlippage] = useState<string>('0')
// Connect with form
const { values }: FormikContextType<FormTradeData> = useFormikContext()
// Get swap fee
useEffect(() => {
if (!poolAddress || !isAssetNetwork) return
async function getSwapFee() {
// const swapFee = await ocean.pool.getSwapFee(poolAddress)
// // swapFee is tricky: to get 0.1% you need to convert from 0.001
// setSwapFee(
// isValidNumber(swapFee) ? new Decimal(swapFee).mul(100).toString() : '0'
// )
const value =
values.type === 'buy'
? isValidNumber(swapFee) && isValidNumber(values.baseToken)
? new Decimal(swapFee).mul(new Decimal(values.baseToken))
: 0
: isValidNumber(swapFee) && isValidNumber(values.datatoken)
? new Decimal(swapFee).mul(new Decimal(values.datatoken))
: 0
setSwapFeeValue(value.toString())
}
getSwapFee()
}, [poolAddress, values, isAssetNetwork, swapFee])
// Get output values
useEffect(() => {
if (!poolAddress || !isAssetNetwork) return
async function getOutput() {
// Minimum received
// TODO: check if this here is redundant cause we call some of that already in Swap.tsx
const maxImpact = 1 - Number(values.slippage) / 100
const maxPrice =
values.type === 'buy'
? isValidNumber(values.datatoken) && isValidNumber(maxImpact)
? new Decimal(values.datatoken)
.mul(new Decimal(maxImpact))
.toString()
: '0'
: isValidNumber(values.baseToken) && isValidNumber(maxImpact)
? new Decimal(values.baseToken).mul(new Decimal(maxImpact)).toString()
: '0'
if (!values.baseToken || !values.datatoken || !values.output) return
setMaxOutput(maxPrice)
const output =
values.output === 'exactIn'
? new Decimal(
values.type === 'sell' ? values.baseToken : values.datatoken
)
.mul(
new Decimal(1)
.minus(new Decimal(values.slippage).div(new Decimal(100)))
.toString()
)
.toString()
: new Decimal(
values.type === 'sell' ? values.datatoken : values.baseToken
)
.mul(
new Decimal(1)
.plus(new Decimal(values.slippage).div(new Decimal(100)))
.toString()
)
.toString()
setOutputWithSlippage(output)
}
getOutput()
}, [poolAddress, values, isAssetNetwork])
@ -78,19 +59,35 @@ export default function Output({
return (
<div className={styles.output}>
<div>
<p>Minimum Received</p>
<p>
{values.output === 'exactIn' ? 'Minimum Received' : 'Maximum Sent'}
</p>
<Token
symbol={values.type === 'buy' ? dtSymbol : oceanSymbol}
balance={maxOutput}
symbol={
values.type === 'buy'
? values.output === 'exactIn'
? poolInfo.datatokenSymbol
: poolInfo.baseTokenSymbol
: values.output === 'exactIn'
? poolInfo.baseTokenSymbol
: poolInfo.datatokenSymbol
}
balance={outputWithSlippage}
/>
</div>
<div>
<p>Swap fee</p>
<Token
symbol={`${values.type === 'buy' ? oceanSymbol : dtSymbol} ${
swapFee ? `(${swapFee}%)` : ''
symbol={`${
values.type === 'buy'
? poolInfo.baseTokenSymbol
: poolInfo.datatokenSymbol
} ${
poolInfo.liquidityProviderSwapFee
? `(${poolInfo.liquidityProviderSwapFee}%)`
: ''
}`}
balance={swapFeeValue}
balance={lpSwapFee}
/>
</div>
</div>

View File

@ -7,44 +7,54 @@ import { FormikContextType, useFormikContext } from 'formik'
import Output from './Output'
import Slippage from './Slippage'
import PriceImpact from './PriceImpact'
import Decimal from 'decimal.js'
import { useAsset } from '@context/Asset'
import { useWeb3 } from '@context/Web3'
import { FormTradeData, TradeItem } from './_types'
import { Asset } from '@oceanprotocol/lib'
import {
calcMaxExactIn,
calcMaxExactOut,
LoggerInstance,
Pool,
PoolPriceAndFees
} from '@oceanprotocol/lib'
import { AssetExtended } from 'src/@types/AssetExtended'
import { usePool } from '@context/Pool'
import { useSiteMetadata } from '@hooks/useSiteMetadata'
import { MAX_DECIMALS } from '@utils/constants'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
// Decimal.set({ toExpNeg: -15, precision: 5, rounding: Decimal.ROUND_DOWN })
export default function Swap({
asset,
maxDt,
maxOcean,
balance,
setMaximumDt,
setMaximumOcean,
setMaximumBaseToken,
setCoin
}: {
asset: AssetExtended
maxDt: string
maxOcean: string
balance: PoolBalance
setMaximumDt: (value: string) => void
setMaximumOcean: (value: string) => void
setMaximumBaseToken: (value: string) => void
setCoin: (value: string) => void
}): ReactElement {
const { isAssetNetwork } = useAsset()
const [oceanItem, setOceanItem] = useState<TradeItem>({
const { web3 } = useWeb3()
const { poolInfo, poolData } = usePool()
const { appConfig } = useSiteMetadata()
const [baseTokenItem, setBaseTokenItem] = useState<TradeItem>({
amount: '0',
token: asset.accessDetails.baseToken?.symbol,
maxAmount: '0'
token: poolInfo?.baseTokenSymbol,
maxAmount: '0',
address: poolInfo?.baseTokenAddress
})
const [dtItem, setDtItem] = useState<TradeItem>({
amount: '0',
token: asset.accessDetails.datatoken.symbol,
maxAmount: '0'
token: poolInfo?.datatokenSymbol,
maxAmount: '0',
address: poolInfo?.datatokenAddress
})
const {
setFieldValue,
values,
@ -56,148 +66,260 @@ export default function Swap({
const [spotPrice, setSpotPrice] = useState<string>()
const [totalValue, setTotalValue] = useState<string>()
const [tokenAmount, setTokenAmount] = useState<string>()
const [lpSwapFee, setLpSwapFee] = useState<string>()
useEffect(() => {
if (!asset || !balance || !values?.type) return
if (!asset || !balance || !values?.type || !web3) return
const poolInstance = new Pool(web3)
async function calculateMaximum() {
const maxDtFromPool =
values.type === 'buy'
? calcMaxExactIn(poolData.datatokenLiquidity)
: calcMaxExactOut(poolData.datatokenLiquidity)
const maxBaseTokenFromPool =
values.type === 'buy'
? calcMaxExactOut(poolData.baseTokenLiquidity)
: calcMaxExactIn(poolData.baseTokenLiquidity)
const amountDataToken =
values.type === 'buy'
? new Decimal(maxDt)
? maxDtFromPool
: new Decimal(balance.baseToken).greaterThan(
calcMaxExactIn(poolData.datatokenLiquidity)
)
? calcMaxExactIn(poolData.datatokenLiquidity)
: new Decimal(balance.datatoken)
const amountOcean =
const amountBaseToken =
values.type === 'buy'
? new Decimal(balance.baseToken)
: new Decimal(maxOcean)
? new Decimal(balance.baseToken).greaterThan(
calcMaxExactIn(poolData.baseTokenLiquidity)
)
? calcMaxExactIn(poolData.baseTokenLiquidity)
: new Decimal(balance.baseToken)
: maxBaseTokenFromPool
// const maxBuyOcean = await ocean.pool.getOceanReceived(
// price.address,
// `${amountDataToken.toString()}`
// )
// const maxBuyDt = await ocean.pool.getDTReceived(
// price.address,
// `${amountOcean.toString()}`
// )
try {
const maxBuyBaseToken: PoolPriceAndFees =
await poolInstance.getAmountOutExactIn(
asset.accessDetails.addressOrId,
poolInfo.datatokenAddress,
poolInfo.baseTokenAddress,
amountDataToken.toString(),
appConfig.consumeMarketPoolSwapFee
)
// const maximumDt =
// values.type === 'buy'
// ? amountDataToken.greaterThan(new Decimal(maxBuyDt))
// ? maxBuyDt
// : amountDataToken
// : amountDataToken.greaterThan(new Decimal(balance.datatoken))
// ? balance.datatoken
// : amountDataToken
const maxBuyDt: PoolPriceAndFees =
await poolInstance.getAmountOutExactIn(
asset.accessDetails?.addressOrId,
poolInfo.baseTokenAddress,
poolInfo.datatokenAddress,
amountBaseToken.toString(),
appConfig.consumeMarketPoolSwapFee
)
const maximumDt =
values.type === 'buy'
? amountDataToken.greaterThan(new Decimal(maxBuyDt.tokenAmount))
? maxBuyDt.tokenAmount
: amountDataToken.toDecimalPlaces(MAX_DECIMALS).toString()
: amountDataToken.greaterThan(new Decimal(balance.datatoken))
? balance.datatoken
: amountDataToken.toDecimalPlaces(MAX_DECIMALS).toString()
// const maximumOcean =
// values.type === 'sell'
// ? amountOcean.greaterThan(new Decimal(maxBuyOcean))
// ? maxBuyOcean
// : amountOcean
// : amountOcean.greaterThan(new Decimal(balance.ocean))
// ? balance.ocean
// : amountOcean
const maximumBaseToken =
values.type === 'sell'
? amountBaseToken.greaterThan(
new Decimal(maxBuyBaseToken.tokenAmount)
)
? maxBuyBaseToken.tokenAmount
: amountBaseToken.toDecimalPlaces(MAX_DECIMALS).toString()
: amountBaseToken.greaterThan(new Decimal(balance.baseToken))
? balance.baseToken
: amountBaseToken.toDecimalPlaces(MAX_DECIMALS).toString()
// setMaximumDt(maximumDt.toString())
// setMaximumOcean(maximumOcean.toString())
setMaximumDt(maximumDt)
setMaximumBaseToken(maximumBaseToken)
// setOceanItem((prevState) => ({
// ...prevState,
// amount: amountOcean.toString(),
// maxAmount: maximumOcean.toString()
// }))
setBaseTokenItem((prevState) => ({
...prevState,
amount: amountBaseToken.toDecimalPlaces(MAX_DECIMALS).toString(),
maxAmount: maximumBaseToken
}))
// setDtItem((prevState) => ({
// ...prevState,
// amount: amountDataToken.toString(),
// maxAmount: maximumDt.toString()
// }))
setDtItem((prevState) => ({
...prevState,
amount: amountDataToken.toDecimalPlaces(MAX_DECIMALS).toString(),
maxAmount: maximumDt
}))
} catch (error) {
LoggerInstance.error(error.message)
}
}
calculateMaximum()
}, [
asset,
maxOcean,
maxDt,
poolData,
balance,
values?.type,
values.type,
setMaximumDt,
setMaximumOcean
setMaximumBaseToken,
asset,
web3,
dtItem.token,
baseTokenItem.token,
poolInfo.liquidityProviderSwapFee,
poolInfo.datatokenAddress,
poolInfo.baseTokenAddress,
appConfig.consumeMarketPoolSwapFee
])
const switchTokens = () => {
setFieldValue('type', values.type === 'buy' ? 'sell' : 'buy')
setCoin(values.type === 'sell' ? 'OCEAN' : asset.datatokens[0].symbol)
setCoin(
values.type === 'sell'
? poolInfo.baseTokenSymbol
: poolInfo.datatokenSymbol
)
// don't reset form because we don't want to reset type
setFieldValue('datatoken', 0)
setFieldValue('ocean', 0)
setFieldValue('baseToken', 0)
setErrors({})
}
const handleValueChange = async (name: string, value: number) => {
const tokenIn = ''
const tokenOut = ''
let newValue
try {
let tokenIn = ''
let tokenOut = ''
const poolInstance = new Pool(web3)
let newValue: PoolPriceAndFees
// if (name === 'ocean') {
// if (values.type === 'sell') {
// newValue = await ocean.pool.getDTNeeded(price.address, value.toString())
if (name === 'baseToken') {
if (values.type === 'sell') {
newValue = await poolInstance.getAmountInExactOut(
asset.accessDetails.addressOrId,
dtItem.address,
baseTokenItem.address,
value.toString(),
appConfig.consumeMarketPoolSwapFee
)
// setTotalValue(newValue)
// setTokenAmount(value.toString())
setFieldValue('output', 'exactOut')
// tokenIn = ddo.services[0].datatokenAddress
// tokenOut = ocean.pool.oceanAddress
// } else {
// newValue = await ocean.pool.getDTReceived(
// price.address,
// value.toString()
// )
setTotalValue(
new Decimal(newValue.tokenAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
setLpSwapFee(
new Decimal(newValue.liquidityProviderSwapFeeAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
setTokenAmount(value.toString())
// setTotalValue(value.toString())
// setTokenAmount(newValue)
// tokenIn = ocean.pool.oceanAddress
// tokenOut = ddo.services[0].datatokenAddress
// }
// } else {
// if (values.type === 'sell') {
// newValue = await ocean.pool.getOceanReceived(
// price.address,
// value.toString()
// )
tokenIn = poolInfo.datatokenAddress
tokenOut = poolInfo.baseTokenAddress
} else {
newValue = await poolInstance.getAmountOutExactIn(
asset.accessDetails.addressOrId,
baseTokenItem.address,
dtItem.address,
value.toString(),
appConfig.consumeMarketPoolSwapFee
)
// setTotalValue(value.toString())
// setTokenAmount(newValue)
// tokenIn = ddo.services[0].datatokenAddress
// tokenOut = ocean.pool.oceanAddress
// } else {
// newValue = await ocean.pool.getOceanNeeded(
// price.address,
// value.toString()
// )
setFieldValue('output', 'exactIn')
setTotalValue(value.toString())
setTokenAmount(
new Decimal(newValue.tokenAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
setLpSwapFee(
new Decimal(newValue.liquidityProviderSwapFeeAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
tokenIn = poolInfo.baseTokenAddress
tokenOut = poolInfo.datatokenAddress
}
} else {
if (values.type === 'sell') {
newValue = await poolInstance.getAmountOutExactIn(
asset.accessDetails.addressOrId,
dtItem.address,
baseTokenItem.address,
value.toString(),
appConfig.consumeMarketPoolSwapFee
)
// setTotalValue(newValue)
// setTokenAmount(value.toString())
// tokenIn = ocean.pool.oceanAddress
// tokenOut = ddo.services[0].datatokenAddress
// }
// }
setFieldValue('output', 'exactIn')
setTotalValue(value.toString())
setTokenAmount(
new Decimal(newValue.tokenAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
setLpSwapFee(
new Decimal(newValue.liquidityProviderSwapFeeAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
tokenIn = poolInfo.datatokenAddress
tokenOut = poolInfo.baseTokenAddress
} else {
newValue = await poolInstance.getAmountInExactOut(
asset.accessDetails.addressOrId,
baseTokenItem.address,
dtItem.address,
value.toString(),
appConfig.consumeMarketPoolSwapFee
)
await setFieldValue(name === 'ocean' ? 'datatoken' : 'ocean', newValue)
setFieldValue('output', 'exactOut')
// const spotPrice = await ocean.pool.getSpotPrice(
// price.address,
// tokenIn,
// tokenOut
// )
setTotalValue(
new Decimal(newValue.tokenAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
setTokenAmount(value.toString())
setLpSwapFee(
new Decimal(newValue.liquidityProviderSwapFeeAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
tokenIn = poolInfo.baseTokenAddress
tokenOut = poolInfo.datatokenAddress
}
}
// setSpotPrice(spotPrice)
validateForm()
await setFieldValue(
name === 'baseToken' ? 'datatoken' : 'baseToken',
new Decimal(newValue.tokenAmount)
.toDecimalPlaces(MAX_DECIMALS)
.toString()
)
const spotPrice = await poolInstance.getSpotPrice(
asset.accessDetails.addressOrId,
tokenIn,
tokenOut,
appConfig.consumeMarketPoolSwapFee
)
setSpotPrice(spotPrice)
validateForm()
} catch (ex) {
LoggerInstance.error(ex)
}
}
return (
<div className={styles.swap}>
<TradeInput
name={values.type === 'sell' ? 'datatoken' : 'ocean'}
item={values.type === 'sell' ? dtItem : oceanItem}
name={values.type === 'sell' ? 'datatoken' : 'baseToken'}
item={values.type === 'sell' ? dtItem : baseTokenItem}
disabled={!isAssetNetwork}
handleValueChange={handleValueChange}
/>
@ -212,16 +334,15 @@ export default function Swap({
</Button>
<TradeInput
name={values.type === 'sell' ? 'ocean' : 'datatoken'}
item={values.type === 'sell' ? oceanItem : dtItem}
name={values.type === 'sell' ? 'baseToken' : 'datatoken'}
item={values.type === 'sell' ? baseTokenItem : dtItem}
disabled={!isAssetNetwork}
handleValueChange={handleValueChange}
/>
<Output
dtSymbol={dtItem.token}
oceanSymbol={oceanItem.token}
poolAddress={asset.accessDetails?.addressOrId}
lpSwapFee={lpSwapFee}
/>
<PriceImpact

View File

@ -16,7 +16,6 @@
.tradeInput div[class*='prefix'] {
min-width: 6.5rem;
width: fit-content;
justify-content: center;
}

View File

@ -34,7 +34,7 @@ export default function TradeInput({
}: FormikContextType<FormTradeData> = useFormikContext()
const isTopField =
(name === 'ocean' && values.type === 'buy') ||
(name === 'baseToken' && values.type === 'buy') ||
(name === 'datatoken' && values.type === 'sell')
const titleAvailable = isTopField ? `Balance` : `Available from pool`
const titleMaximum = isTopField ? `Maximum to spend` : `Maximum to receive`
@ -54,6 +54,7 @@ export default function TradeInput({
<Input
type="number"
max={`${item?.maxAmount}`}
min="0"
prefix={item?.token}
placeholder="0"
field={field}
@ -68,7 +69,8 @@ export default function TradeInput({
/>
)}
</Field>
{!isTopField && (
{/* {!isTopField && (
<Button
className={styles.buttonMax}
disabled={disabled}
@ -81,7 +83,7 @@ export default function TradeInput({
>
Use Max
</Button>
)}
)} */}
</section>
)
}

View File

@ -4,6 +4,7 @@ export const initialValues: FormTradeData = {
baseToken: undefined,
datatoken: undefined,
type: 'buy',
output: 'exactIn',
slippage: '5'
}

View File

@ -1,6 +1,8 @@
export interface FormTradeData extends PoolBalance {
// in reference to datatoken, buy = swap from ocean to dt ( buy dt) , sell = swap from dt to ocean (sell dt)
type: 'buy' | 'sell'
// based on what the user inputs, if he fill the top input it is 'exactIn'
output: 'exactIn' | 'exactOut'
slippage: string
}
@ -8,4 +10,5 @@ export interface TradeItem {
amount: string
token: string
maxAmount: string
address: string
}

View File

@ -2,8 +2,10 @@ import React, { ReactElement, useEffect, useState } from 'react'
import FormTrade from './FormTrade'
import { useAsset } from '@context/Asset'
import { useWeb3 } from '@context/Web3'
import { isValidNumber } from '@utils/numbers'
import Decimal from 'decimal.js'
import { Datatoken } from '@oceanprotocol/lib'
import { Datatoken, LoggerInstance, Pool } from '@oceanprotocol/lib'
import { usePool } from '@context/Pool'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
@ -12,8 +14,7 @@ export default function Trade(): ReactElement {
const { isAssetNetwork } = useAsset()
const [tokenBalance, setTokenBalance] = useState<PoolBalance>()
const { asset } = useAsset()
const [maxDt, setMaxDt] = useState('0')
const [maxOcean, setMaxOcean] = useState('0')
const { poolInfo } = usePool()
// Get datatoken balance, and combine with OCEAN balance from hooks into one object
useEffect(() => {
@ -23,14 +24,14 @@ export default function Trade(): ReactElement {
!isAssetNetwork ||
!balance?.ocean ||
!accountId ||
!asset?.services[0].datatokenAddress
!poolInfo?.datatokenAddress
)
return
async function getTokenBalance() {
const datatokenInstance = new Datatoken(web3)
const dtBalance = await datatokenInstance.balance(
asset.services[0].datatokenAddress,
poolInfo.datatokenAddress,
accountId
)
setTokenBalance({
@ -39,44 +40,13 @@ export default function Trade(): ReactElement {
})
}
getTokenBalance()
}, [web3, balance.ocean, accountId, asset, isAssetNetwork])
}, [
web3,
balance.ocean,
accountId,
poolInfo?.datatokenAddress,
isAssetNetwork
])
// Get maximum amount for either OCEAN or datatoken
useEffect(() => {
if (
!isAssetNetwork ||
!asset.accessDetails ||
asset.accessDetails.price === 0
)
return
async function getMaximum() {
// const maxTokensInPool = await ocean.pool.getDTMaxBuyQuantity(
// price.address
// )
// setMaxDt(
// isValidNumber(maxTokensInPool)
// ? new Decimal(maxTokensInPool).toString()
// : '0'
// )
// const maxOceanInPool = await ocean.pool.getOceanMaxBuyQuantity(
// price.address
// )
// setMaxOcean(
// isValidNumber(maxOceanInPool)
// ? new Decimal(maxOceanInPool).toString()
// : '0'
// )
}
getMaximum()
}, [isAssetNetwork, balance.ocean, asset])
return (
<FormTrade
asset={asset}
balance={tokenBalance}
maxDt={maxDt}
maxOcean={maxOcean}
/>
)
return <FormTrade asset={asset} balance={tokenBalance} />
}