Skip to content

Commit

Permalink
[SWA-92] Market prices and update limit order every 15 seconds
Browse files Browse the repository at this point in the history
  • Loading branch information
Wixzi committed Jul 28, 2023
1 parent d3c0cda commit 55a45b7
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 103 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Currency, TokenAmount } from '@swapr/sdk'

import { parseUnits } from 'ethers/lib/utils'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import { RefreshCw } from 'react-feather'
import { useTranslation } from 'react-i18next'
import { Flex } from 'rebass'

import { Kind, LimitOrderBase } from '../../../../../services/LimitOrders'
import { Kind, LimitOrderBase, MarketPrices } from '../../../../../services/LimitOrders'
import { InputGroup } from '../InputGroup'
import { calculateMarketPriceDiffPercentage } from '../utils'

import { MarketPriceButton } from './MarketPriceButton'
import {
Expand All @@ -16,6 +18,7 @@ import {
SwapTokenIconWrapper,
SwapTokenWrapper,
ToggleCurrencyButton,
LimitLabelGroup,
} from './styles'

const invalidChars = ['-', '+', 'e']
Expand All @@ -25,60 +28,38 @@ const getBaseQuoteTokens = ({ kind, sellToken, buyToken }: { kind: Kind; sellTok
? { baseToken: sellToken, quoteToken: buyToken }
: { baseToken: buyToken, quoteToken: sellToken }
}
const regex = /^(\d+\.\d{0,2})0*$/

// function formatNumber(number: string | number): string {
// // Check if the input is a string
// if (typeof number === 'string') {
// number = parseFloat(number)
// }

// // Get the decimal part of the number
// const decimals = number.toFixed(6)

// // Check if the decimal part is all zeros
// if (decimals.endsWith('0')) {
// if (decimals.includes('.') && Number(decimals) > 0) {
// const match = regex.test(decimals)
// if (match) {
// // @ts-ignore
// return match[1]
// } else {
// return decimals
// }
// return decimals
// }
// return Math.floor(number).toString()
// } else {
// return decimals
// }
// }

export interface OrderLimitPriceFieldProps {

interface OrderLimitPriceFieldProps {
protocol: LimitOrderBase
sellAmount: TokenAmount
buyAmount: TokenAmount
kind: Kind
marketPrices: MarketPrices
sellToken: Currency
buyToken: Currency
setSellAmount(t: TokenAmount): void
setBuyAmount(t: TokenAmount): void
setKind(t: Kind): void
setLoading(t: boolean): void
}

export function OrderLimitPriceField({
protocol,
sellAmount,
buyAmount,
kind,
marketPrices,
sellToken,
buyToken,
setSellAmount,
setBuyAmount,
setKind,
setLoading,
}: OrderLimitPriceFieldProps) {
const { t } = useTranslation('swap')

const quoteRef = useRef<NodeJS.Timer>()

const { baseToken, quoteToken } = getBaseQuoteTokens({ kind, sellToken, buyToken })

const inputGroupLabel = `${kind} 1 ${baseToken?.symbol} at`
Expand All @@ -90,17 +71,41 @@ export function OrderLimitPriceField({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [protocol.limitPrice])

// const [formattedLimitPrice, setFormattedLimitPrice] = useState(protocol.limitPrice)
useEffect(() => {
quoteRef.current = setInterval(async () => {
setLoading(true)
try {
if (!protocol.userUpdatedLimitPrice) {
console.log('Hello')
await protocol.getQuote()
}
} finally {
setLoading(false)
}
}, 15000)

if (protocol.userUpdatedLimitPrice) {
setLoading(false)
clearInterval(quoteRef.current)
}

return () => {
clearInterval(quoteRef.current)
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [protocol.userUpdatedLimitPrice])

const [inputLimitPrice, setInputLimitPrice] = useState(protocol.limitPrice)

// const { marketPriceDiffPercentage, isDiffPositive } = calculateMarketPriceDiffPercentage(
// kind ?? Kind.Sell,
// marketPrices,
// formattedLimitPrice.toString()
// )
const { marketPriceDiffPercentage, isDiffPositive } = calculateMarketPriceDiffPercentage(
kind ?? Kind.Sell,
marketPrices,
protocol.limitPrice
)

// const showPercentage =
// Number(marketPriceDiffPercentage.toFixed(1)) !== 0 && Number(marketPriceDiffPercentage) !== -100
const showPercentage =
Number(marketPriceDiffPercentage.toFixed(1)) !== 0 && Number(marketPriceDiffPercentage) !== -100

/**
* Handle the limit price input change. Compute the buy amount and update the state.
Expand Down Expand Up @@ -176,9 +181,13 @@ export function OrderLimitPriceField({
}

const onClickGetMarketPrice = async () => {
protocol.onUserUpadtedLimitPrice(false)
protocol.loading = true
setLoading(true)

protocol.onUserUpadtedLimitPrice(false)
await protocol.getQuote()
protocol.loading = false
setLoading(false)
if (kind === Kind.Sell) {
setBuyAmount(protocol.buyAmount)
} else {
Expand All @@ -189,25 +198,29 @@ export function OrderLimitPriceField({
setInputLimitPrice(limitPrice)
}

// TODO: fix it
const showPercentage = false
const marketPriceDiffPercentage = 0
const isDiffPositive = false

return (
<InputGroup>
<LimitLabel htmlFor="limitPrice">
<span>
{inputGroupLabel}
{showPercentage && (
<MarketPriceDiff isPositive={isDiffPositive}> ({marketPriceDiffPercentage.toFixed(2)}%)</MarketPriceDiff>
)}
</span>
{!protocol.userUpdatedLimitPrice && buyAmount?.currency && sellAmount?.currency ? (
<MarketPriceButton key={`${buyToken.symbol}-${sellToken.symbol}`} />
) : (
<SetToMarket onClick={onClickGetMarketPrice}>{t('limitOrder.getMarketPrice')}</SetToMarket>
)}
<LimitLabelGroup>
<Flex flex={60}>
<p>
{inputGroupLabel}
{showPercentage && (
<MarketPriceDiff isPositive={isDiffPositive}>
{' '}
({marketPriceDiffPercentage.toFixed(2)}%)
</MarketPriceDiff>
)}
</p>
</Flex>
<Flex flex={40} flexDirection="row-reverse">
{!protocol.userUpdatedLimitPrice && buyAmount?.currency && sellAmount?.currency ? (
<MarketPriceButton key={`${buyToken.symbol}-${sellToken.symbol}-${protocol.limitPrice}`} />
) : (
<SetToMarket onClick={onClickGetMarketPrice}>{t('limitOrder.getMarketPrice')}</SetToMarket>
)}
</Flex>
</LimitLabelGroup>
</LimitLabel>
<InputGroup.InnerWrapper>
<InputGroup.Input
Expand Down
22 changes: 12 additions & 10 deletions src/pages/Swap/LimitOrder/Components/OrderLimitPriceField/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,24 @@ export const LimitLabel = styled.label`
align-items: center;
`

export const LimitLabelGroup = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
`

export const SetToMarket = styled.button`
font-size: 10px;
color: #8c83c0;
color: #000;
border: none;
cursor: pointer;
background-color: #2a2f41;
background-color: ${({ theme }) => theme.green2};
border-radius: 5px;
text-transform: uppercase;
padding: 3px 8px;
padding: 3px 5px;
&:hover {
color: #736f96;
background-color: #03d48d;
}
`

Expand All @@ -37,15 +44,10 @@ export const MarketPrice = styled.button`
font-size: 11px;
color: ${({ theme }) => theme.green2};
border: 1px solid ${({ theme }) => theme.green2};
cursor: pointer;
background-color: transparent;
border-radius: 5px;
text-transform: uppercase;
padding: 3px 8px;
&:hover {
border: 1px solid ${({ theme }) => theme.green2};
color: ${({ theme }) => theme.green1};
}
padding: 3px 4px;
`

export const SwapTokenIconWrapper = styled.div`
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Swap/LimitOrder/Components/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ export const toFixedSix = (price: number): string => {
export function calculateMarketPriceDiffPercentage(
limitOrderKind: Kind,
marketPrices: MarketPrices,
formattedLimitPrice: string
formattedLimitPrice?: string
) {
const nextLimitPriceFloat = limitOrderKind === Kind.Sell ? marketPrices.buy : marketPrices.sell
let marketPriceDiffPercentage = 0
let isDiffPositive = false

if (Boolean(Number(nextLimitPriceFloat))) {
if (Boolean(Number(nextLimitPriceFloat)) && formattedLimitPrice) {
if (limitOrderKind === Kind.Sell) {
marketPriceDiffPercentage = (Number(formattedLimitPrice) / Number(nextLimitPriceFloat.toFixed(6)) - 1) * 100
isDiffPositive = Math.sign(Number(marketPriceDiffPercentage)) > 0
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Swap/LimitOrder/LimitOrder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import LimitOrder, { WalletData } from '../../../services/LimitOrders'
import { LimitOrderProvider } from '../../../services/LimitOrders/LimitOrder.provider'
import AppBody from '../../AppBody'

import LimitOrderFallback from './Components/LimitOrderFallback'
import LimitOrderFallback from './Components/LimitFallback'
import LimitOrderForm from './LimitOrderForm'

const limitSdk = new LimitOrder()
Expand Down
43 changes: 35 additions & 8 deletions src/pages/Swap/LimitOrder/LimitOrderForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ConfirmLimitOrderModal from './Components/ConfirmLimitOrderModal'
import { OrderExpiryField } from './Components/OrderExpiryField'
import { OrderLimitPriceField } from './Components/OrderLimitPriceField'
import SwapTokens from './Components/SwapTokens'
import { formatMarketPrice } from './Components/utils'

export default function LimitOrderForm() {
const protocol = useContext(LimitOrderContext)
Expand All @@ -44,7 +45,7 @@ export default function LimitOrderForm() {

const [kind, setKind] = useState<Kind>(protocol?.kind || Kind.Sell)
// TODO: Check the usage of marketPrices
const [marketPrices] = useState<MarketPrices>({ buy: 0, sell: 0 })
// const [marketPrices] = useState<MarketPrices>({ buy: 0, sell: 0 })

const [isModalOpen, setIsModalOpen] = useState(false)

Expand Down Expand Up @@ -184,6 +185,33 @@ export default function LimitOrderForm() {
setLoading(false)
}

const [marketPrices, setMarketPrices] = useState<MarketPrices>({ buy: 0, sell: 0 })

const getMarketPrices = useCallback(async () => {
const token = kind === Kind.Sell ? sellAmount : buyAmount
const tokenAmount = Number(token.toExact()) > 1 ? token.toExact() : '1'
debugger
if (protocol.kind === Kind.Sell) {
setMarketPrices(marketPrice => ({
...marketPrice,
buy: formatMarketPrice(protocol.quoteBuyAmount.raw.toString(), buyAmount.currency.decimals, tokenAmount),
}))
} else {
setMarketPrices(marketPrice => ({
...marketPrice,
sell: formatMarketPrice(protocol.quoteSellAmount.raw.toString(), sellAmount.currency.decimals, tokenAmount),
}))
}
}, [buyAmount, kind, protocol, sellAmount])

useEffect(() => {
getMarketPrices()
}, [getMarketPrices, kind])

useEffect(() => {
setMarketPrices({ buy: 0, sell: 0 })
}, [sellToken, buyToken])

return (
<>
<ConfirmLimitOrderModal
Expand All @@ -193,8 +221,8 @@ export default function LimitOrderForm() {
errorMessage={''}
attemptingTxn={loading}
marketPrices={marketPrices}
fiatValueInput={sellAmount}
fiatValueOutput={buyAmount}
fiatValueInput={fiatValueInput}
fiatValueOutput={fiatValueOutput}
/>
<AutoColumn gap="12px">
<AutoColumn gap="3px">
Expand Down Expand Up @@ -235,12 +263,10 @@ export default function LimitOrderForm() {
/>
</AutoColumn>
<AutoRow justify="space-between" flexWrap="nowrap" gap="12">
<Flex flex={60}>
<Flex flex={65}>
<OrderLimitPriceField
protocol={protocol}
// marketPrices={marketPrices}
// fetchMarketPrice={fetchMarketPrice}
// setFetchMarketPrice={setFetchMarketPrice}
marketPrices={marketPrices}
sellToken={sellToken}
buyToken={buyToken}
sellAmount={sellAmount}
Expand All @@ -249,9 +275,10 @@ export default function LimitOrderForm() {
setSellAmount={setSellAmount}
setBuyAmount={setBuyAmount}
setKind={setKind}
setLoading={setLoading}
/>
</Flex>
<Flex flex={40}>
<Flex flex={35}>
<OrderExpiryField />
</Flex>
</AutoRow>
Expand Down
4 changes: 0 additions & 4 deletions src/services/LimitOrders/1Inch/OneInch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ export class OneInch extends LimitOrderBase {
this.limitPrice = limitPrice
}

// setToMarket(): Promise<void> {
// throw new Error('Method not implemented.')
// }

getQuote(): Promise<void> {
throw new Error('Method not implemented.')
}
Expand Down
6 changes: 5 additions & 1 deletion src/services/LimitOrders/CoW/CoW.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export class CoW extends LimitOrderBase {
this.userUpdatedLimitPrice = status
}

async getQuote(limitOrder?: LimitOrder): Promise<void> {
async getQuote(limitOrder?: LimitOrder) {
const signer = this.provider?.getSigner()
const chainId = this.activeChainId
const order = limitOrder ?? this.limitOrder
Expand Down Expand Up @@ -202,6 +202,10 @@ export class CoW extends LimitOrderBase {
quote: { buyAmount, sellAmount },
} = cowQuote

if (this.userUpdatedLimitPrice) {
return
}

const buyTokenAmount = new TokenAmount(this.buyToken, buyAmount)
const sellTokenAmount = new TokenAmount(this.sellToken, sellAmount)
this.quoteBuyAmount = buyTokenAmount
Expand Down
Loading

0 comments on commit 55a45b7

Please sign in to comment.