diff --git a/apis/coingecko.ts b/apis/coingecko.ts
index d6e3b96c..d9000a29 100644
--- a/apis/coingecko.ts
+++ b/apis/coingecko.ts
@@ -39,21 +39,12 @@ export const fetchChartData = async (
(outputTokenCandle) => outputTokenCandle[0] === inputTokenCandle[0],
)
if (outputTokenCandle) {
- if (['usd-coin', 'tether'].includes(quoteTokenId)) {
- parsedData.push({
- time: inputTokenCandle[0],
- price: inputTokenCandle[4] / outputTokenCandle[4],
- inputTokenPrice: inputTokenCandle[4],
- outputTokenPrice: outputTokenCandle[4],
- })
- } else {
- parsedData.push({
- time: inputTokenCandle[0],
- price: outputTokenCandle[4] / inputTokenCandle[4],
- inputTokenPrice: inputTokenCandle[4],
- outputTokenPrice: outputTokenCandle[4],
- })
- }
+ parsedData.push({
+ time: inputTokenCandle[0],
+ price: outputTokenCandle[4] / inputTokenCandle[4],
+ inputTokenPrice: inputTokenCandle[4],
+ outputTokenPrice: outputTokenCandle[4],
+ })
}
}
return parsedData
diff --git a/components/swap/LimitSwapForm.tsx b/components/swap/LimitSwapForm.tsx
index a60353cd..345a4eb7 100644
--- a/components/swap/LimitSwapForm.tsx
+++ b/components/swap/LimitSwapForm.tsx
@@ -14,7 +14,10 @@ import NumberFormat, {
import Decimal from 'decimal.js'
import mangoStore from '@store/mangoStore'
import { useTranslation } from 'next-i18next'
-import { SIZE_INPUT_UI_KEY } from '../../utils/constants'
+import {
+ SIZE_INPUT_UI_KEY,
+ SWAP_CHART_SETTINGS_KEY,
+} from '../../utils/constants'
import useLocalStorageState from 'hooks/useLocalStorageState'
import SwapSlider from './SwapSlider'
import PercentageSelectButtons from './PercentageSelectButtons'
@@ -24,11 +27,12 @@ import SellTokenInput from './SellTokenInput'
import BuyTokenInput from './BuyTokenInput'
import { notify } from 'utils/notifications'
import * as sentry from '@sentry/nextjs'
-import { isMangoError } from 'types'
+import { SwapChartSettings, isMangoError } from 'types'
import Button, { IconButton } from '@components/shared/Button'
import Loading from '@components/shared/Loading'
import TokenLogo from '@components/shared/TokenLogo'
import InlineNotification from '@components/shared/InlineNotification'
+import { handleFlipPrices } from './SwapTokenChart'
type LimitSwapFormProps = {
showTokenSelect: 'input' | 'output' | undefined
@@ -50,10 +54,13 @@ const LimitSwapForm = ({
const { t } = useTranslation(['common', 'swap', 'trade'])
const [animateSwitchArrow, setAnimateSwitchArrow] = useState(0)
const [triggerPrice, setTriggerPrice] = useState('')
- const [flipPrices, setFlipPrices] = useState(false)
const [submitting, setSubmitting] = useState(false)
const [swapFormSizeUi] = useLocalStorageState(SIZE_INPUT_UI_KEY, 'slider')
const [formErrors, setFormErrors] = useState({})
+ const [swapChartSettings, setSwapChartSettings] = useLocalStorageState(
+ SWAP_CHART_SETTINGS_KEY,
+ [],
+ )
const {
margin: useMargin,
@@ -70,6 +77,18 @@ const LimitSwapForm = ({
: new Decimal(0)
}, [amountInFormValue])
+ const flipPrices = useMemo(() => {
+ if (!swapChartSettings.length || !inputBank || !outputBank) return false
+ const pairSettings = swapChartSettings.find(
+ (chart: SwapChartSettings) =>
+ chart.pair.includes(inputBank.name) &&
+ chart.pair.includes(outputBank.name),
+ )
+ if (pairSettings) {
+ return pairSettings.flipPrices
+ } else return false
+ }, [swapChartSettings, inputBank, outputBank])
+
const setAmountInFormValue = useCallback((amountIn: string) => {
set((s) => {
s.swap.amountIn = amountIn
@@ -88,36 +107,35 @@ const LimitSwapForm = ({
})
}, [])
- const [quotePrice, flippedQuotePrice] = useMemo(() => {
- if (!inputBank || !outputBank) return [0, 0]
- const quote = floorToDecimal(
- inputBank.uiPrice / outputBank.uiPrice,
- outputBank.mintDecimals,
- ).toNumber()
- const flipped = floorToDecimal(
- outputBank.uiPrice / inputBank.uiPrice,
- inputBank.mintDecimals,
- ).toNumber()
- return [quote, flipped]
- }, [inputBank, outputBank])
+ const quotePrice = useMemo(() => {
+ if (!inputBank || !outputBank) return 0
+ const quote = !flipPrices
+ ? floorToDecimal(
+ outputBank.uiPrice / inputBank.uiPrice,
+ inputBank.mintDecimals,
+ ).toNumber()
+ : floorToDecimal(
+ inputBank.uiPrice / outputBank.uiPrice,
+ outputBank.mintDecimals,
+ ).toNumber()
+ return quote
+ }, [flipPrices, inputBank, outputBank])
// set default limit and trigger price
useEffect(() => {
if (!quotePrice) return
if (!triggerPrice && !showTokenSelect) {
- setTriggerPrice(quotePrice.toFixed(outputBank?.mintDecimals))
+ setTriggerPrice(quotePrice.toFixed(inputBank?.mintDecimals))
}
- }, [quotePrice, outputBank, showTokenSelect, triggerPrice])
+ }, [inputBank, quotePrice, showTokenSelect, triggerPrice])
const triggerPriceDifference = useMemo(() => {
- if ((!flipPrices && !quotePrice) || (flipPrices && !flippedQuotePrice))
- return 0
- const oraclePrice = !flipPrices ? quotePrice : flippedQuotePrice
+ if (!quotePrice) return 0
const triggerDifference = triggerPrice
- ? ((parseFloat(triggerPrice) - oraclePrice) / oraclePrice) * 100
+ ? ((parseFloat(triggerPrice) - quotePrice) / quotePrice) * 100
: 0
return triggerDifference
- }, [flipPrices, flippedQuotePrice, quotePrice, triggerPrice])
+ }, [flipPrices, quotePrice, triggerPrice])
const handleTokenSelect = (type: 'input' | 'output') => {
setShowTokenSelect(type)
@@ -153,11 +171,11 @@ const LimitSwapForm = ({
(amountIn: string, price: string) => {
const amountOut = !flipPrices
? floorToDecimal(
- parseFloat(amountIn) * parseFloat(price),
+ parseFloat(amountIn) / parseFloat(price),
outputBank?.mintDecimals || 0,
)
: floorToDecimal(
- parseFloat(amountIn) / parseFloat(price),
+ parseFloat(amountIn) * parseFloat(price),
outputBank?.mintDecimals || 0,
)
return amountOut
@@ -170,11 +188,11 @@ const LimitSwapForm = ({
(amountOut: string, price: string) => {
const amountIn = !flipPrices
? floorToDecimal(
- parseFloat(amountOut) / parseFloat(price),
+ parseFloat(amountOut) * parseFloat(price),
inputBank?.mintDecimals || 0,
)
: floorToDecimal(
- parseFloat(amountOut) * parseFloat(price),
+ parseFloat(amountOut) / parseFloat(price),
inputBank?.mintDecimals || 0,
)
return amountIn
@@ -255,18 +273,26 @@ const LimitSwapForm = ({
)
const handleSwitchTokens = useCallback(() => {
+ if (!inputBank || !outputBank) return
set((s) => {
s.swap.inputBank = outputBank
s.swap.outputBank = inputBank
})
- if (flippedQuotePrice) {
- const price = flipPrices ? quotePrice : flippedQuotePrice
- setTriggerPrice(price.toFixed(inputBank?.mintDecimals))
- if (amountInAsDecimal?.gt(0)) {
- const amountOut = amountInAsDecimal.mul(flippedQuotePrice)
- setAmountOutFormValue(amountOut.toString())
- }
+ const price = !flipPrices
+ ? floorToDecimal(
+ inputBank.uiPrice / outputBank.uiPrice,
+ outputBank.mintDecimals,
+ ).toString()
+ : floorToDecimal(
+ outputBank.uiPrice / inputBank.uiPrice,
+ inputBank.mintDecimals,
+ ).toString()
+ setTriggerPrice(price)
+
+ if (amountInAsDecimal?.gt(0)) {
+ const amountOut = getAmountOut(amountInAsDecimal.toString(), price)
+ setAmountOutFormValue(amountOut.toString())
}
setAnimateSwitchArrow(
(prevanimateSwitchArrow) => prevanimateSwitchArrow + 1,
@@ -275,7 +301,6 @@ const LimitSwapForm = ({
setAmountInFormValue,
amountInAsDecimal,
flipPrices,
- flippedQuotePrice,
inputBank,
outputBank,
triggerPrice,
@@ -301,11 +326,9 @@ const LimitSwapForm = ({
return
setSubmitting(true)
- const inputMint = !flipPrices ? inputBank.mint : outputBank.mint
- const outputMint = !flipPrices ? outputBank.mint : inputBank.mint
- const amountIn = !flipPrices
- ? amountInAsDecimal.toNumber()
- : parseFloat(amountOutFormValue)
+ const inputMint = inputBank.mint
+ const outputMint = outputBank.mint
+ const amountIn = amountInAsDecimal.toNumber()
try {
const tx = await client.tokenConditionalSwapStopLoss(
@@ -362,8 +385,8 @@ const LimitSwapForm = ({
)
return
const quoteString = !flipPrices
- ? `${outputBank.name} per ${inputBank.name}`
- : `${inputBank.name} per ${outputBank.name}`
+ ? `${inputBank.name} per ${outputBank.name}`
+ : `${outputBank.name} per ${inputBank.name}`
if (inputBank.name === 'USDC') {
return t('trade:trigger-order-desc', {
amount: floorToDecimal(amountOutFormValue, outputBank.mintDecimals),
@@ -391,22 +414,41 @@ const LimitSwapForm = ({
const triggerPriceSuffix = useMemo(() => {
if (!inputBank || !outputBank) return
if (!flipPrices) {
- return `${outputBank.name} per ${inputBank.name}`
- } else {
return `${inputBank.name} per ${outputBank.name}`
+ } else {
+ return `${outputBank.name} per ${inputBank.name}`
}
}, [flipPrices, inputBank, outputBank])
- const handleFlipPrices = useCallback(
+ const toggleFlipPrices = useCallback(
(flip: boolean) => {
- setFlipPrices(flip)
- if (flip) {
- setTriggerPrice(flippedQuotePrice.toFixed(inputBank?.mintDecimals))
- } else {
- setTriggerPrice(quotePrice.toFixed(outputBank?.mintDecimals))
- }
+ if (!inputBank || !outputBank) return
+ handleFlipPrices(
+ flip,
+ flipPrices,
+ inputBank.name,
+ outputBank.name,
+ swapChartSettings,
+ setSwapChartSettings,
+ )
+ const price = !flipPrices
+ ? floorToDecimal(
+ inputBank.uiPrice / outputBank.uiPrice,
+ outputBank.mintDecimals,
+ ).toString()
+ : floorToDecimal(
+ outputBank.uiPrice / inputBank.uiPrice,
+ inputBank.mintDecimals,
+ ).toString()
+ setTriggerPrice(price)
},
- [flippedQuotePrice, inputBank, outputBank, quotePrice],
+ [
+ flipPrices,
+ inputBank,
+ outputBank,
+ swapChartSettings,
+ setSwapChartSettings,
+ ],
)
return (
@@ -432,7 +474,7 @@ const LimitSwapForm = ({
: ''}
- handleFlipPrices(!flipPrices)}>
+ toggleFlipPrices(!flipPrices)}>
@@ -443,7 +485,11 @@ const LimitSwapForm = ({
thousandSeparator=","
allowNegative={false}
isNumericString={true}
- decimalScale={outputBank?.mintDecimals || 6}
+ decimalScale={
+ !flipPrices
+ ? inputBank?.mintDecimals
+ : outputBank?.mintDecimals || 6
+ }
name="triggerPrice"
id="triggerPrice"
className="h-10 w-full rounded-l-lg bg-th-input-bkg p-3 pl-8 font-mono text-sm text-th-fgd-1 focus:outline-none md:hover:bg-th-bkg-1"
@@ -454,7 +500,7 @@ const LimitSwapForm = ({
/>
diff --git a/components/swap/SwapOrders.tsx b/components/swap/SwapOrders.tsx
index b7ec3514..7fc142af 100644
--- a/components/swap/SwapOrders.tsx
+++ b/components/swap/SwapOrders.tsx
@@ -122,6 +122,8 @@ const SwapOrders = () => {
}
}
+ console.log(orders)
+
return orders.length ? (
diff --git a/components/swap/SwapTokenChart.tsx b/components/swap/SwapTokenChart.tsx
index b9340360..8d6b7a56 100644
--- a/components/swap/SwapTokenChart.tsx
+++ b/components/swap/SwapTokenChart.tsx
@@ -32,7 +32,10 @@ import { ChartDataItem, fetchChartData } from 'apis/coingecko'
import mangoStore from '@store/mangoStore'
import useJupiterSwapData from './useJupiterSwapData'
import useLocalStorageState from 'hooks/useLocalStorageState'
-import { ANIMATION_SETTINGS_KEY } from 'utils/constants'
+import {
+ ANIMATION_SETTINGS_KEY,
+ SWAP_CHART_SETTINGS_KEY,
+} from 'utils/constants'
import { INITIAL_ANIMATION_SETTINGS } from '@components/settings/AnimationSettings'
import { useTranslation } from 'next-i18next'
import {
@@ -46,11 +49,35 @@ import { CategoricalChartFunc } from 'recharts/types/chart/generateCategoricalCh
import { interpolateNumber } from 'd3-interpolate'
import { IconButton } from '@components/shared/Button'
import Tooltip from '@components/shared/Tooltip'
-import { SwapHistoryItem } from 'types'
+import { SwapChartSettings, SwapHistoryItem } from 'types'
import useThemeWrapper from 'hooks/useThemeWrapper'
dayjs.extend(relativeTime)
+export const handleFlipPrices = (
+ flip: boolean,
+ flipPrices: boolean,
+ inputToken: string | undefined,
+ outputToken: string | undefined,
+ swapChartSettings: SwapChartSettings[],
+ setSwapChartSettings: (settings: SwapChartSettings[]) => void,
+) => {
+ if (!inputToken || !outputToken) return
+ if (!flipPrices && flip) {
+ setSwapChartSettings([
+ ...swapChartSettings,
+ { pair: `${inputToken}/${outputToken}`, flipPrices: true },
+ ])
+ } else {
+ setSwapChartSettings(
+ swapChartSettings.filter(
+ (chart: SwapChartSettings) =>
+ !chart.pair.includes(inputToken) && !chart.pair.includes(outputToken),
+ ),
+ )
+ }
+}
+
const CustomizedLabel = ({
chartData,
x,
@@ -182,12 +209,16 @@ const SwapTokenChart = () => {
const [quoteTokenId, setQuoteTokenId] = useState(outputCoingeckoId)
const [mouseData, setMouseData] = useState()
const [daysToShow, setDaysToShow] = useState('1')
- const [flipPrices, setFlipPrices] = useState(false)
+ // const [flipPrices, setFlipPrices] = useState(false)
const { theme } = useThemeWrapper()
const [animationSettings] = useLocalStorageState(
ANIMATION_SETTINGS_KEY,
INITIAL_ANIMATION_SETTINGS,
)
+ const [swapChartSettings, setSwapChartSettings] = useLocalStorageState(
+ SWAP_CHART_SETTINGS_KEY,
+ [],
+ )
const swapHistory = mangoStore((s) => s.mangoAccount.swapHistory.data)
const loadSwapHistory = mangoStore((s) => s.mangoAccount.swapHistory.loading)
const [showSwaps, setShowSwaps] = useState(true)
@@ -197,6 +228,47 @@ const SwapTokenChart = () => {
string | number | undefined
>(undefined)
+ const flipPrices = useMemo(() => {
+ if (!swapChartSettings.length || !inputBank || !outputBank) return false
+ const pairSettings = swapChartSettings.find(
+ (chart: SwapChartSettings) =>
+ chart.pair.includes(inputBank.name) &&
+ chart.pair.includes(outputBank.name),
+ )
+ if (pairSettings) {
+ return pairSettings.flipPrices
+ } else return false
+ }, [swapChartSettings, inputBank, outputBank])
+
+ const swapMarketName = useMemo(() => {
+ if (!inputBank || !outputBank) return ''
+ const inputSymbol = formatTokenSymbol(inputBank.name)
+ const outputSymbol = formatTokenSymbol(outputBank.name)
+ return !flipPrices
+ ? `${outputSymbol}/${inputSymbol}`
+ : `${inputSymbol}/${outputSymbol}`
+ }, [flipPrices, inputBank, inputCoingeckoId, outputBank])
+
+ // const handleFlipPrices = useCallback(
+ // (flip: boolean) => {
+ // if (!flipPrices && flip) {
+ // setSwapChartSettings([
+ // ...swapChartSettings,
+ // { pair: swapMarketName, flipPrices: true },
+ // ])
+ // } else {
+ // setSwapChartSettings(
+ // swapChartSettings.filter(
+ // (chart: SwapChartSettings) =>
+ // !chart.pair.includes(inputBank!.name) &&
+ // !chart.pair.includes(outputBank!.name),
+ // ),
+ // )
+ // }
+ // },
+ // [flipPrices, inputBank, outputBank, swapChartSettings, swapMarketName],
+ // )
+
const handleSwapMouseEnter = useCallback(
(
swap: SwapHistoryItem | undefined,
@@ -216,19 +288,6 @@ const SwapTokenChart = () => {
setSwapTooltipData(null)
}, [setSwapTooltipData])
- const swapMarketName = useMemo(() => {
- if (!inputBank || !outputBank) return ''
- const inputSymbol = formatTokenSymbol(inputBank.name)
- const outputSymbol = formatTokenSymbol(outputBank.name)
- return ['usd-coin', 'tether'].includes(inputCoingeckoId || '')
- ? !flipPrices
- ? `${outputSymbol}/${inputSymbol}`
- : `${inputSymbol}/${outputSymbol}`
- : !flipPrices
- ? `${inputSymbol}/${outputSymbol}`
- : `${outputSymbol}/${inputSymbol}`
- }, [flipPrices, inputBank, inputCoingeckoId, outputBank])
-
const renderTooltipContent = useCallback(
(swap: SwapHistoryItem) => {
const {
@@ -429,14 +488,8 @@ const SwapTokenChart = () => {
useEffect(() => {
if (!inputCoingeckoId || !outputCoingeckoId) return
-
- if (['usd-coin', 'tether'].includes(outputCoingeckoId)) {
- setBaseTokenId(inputCoingeckoId)
- setQuoteTokenId(outputCoingeckoId)
- } else {
- setBaseTokenId(outputCoingeckoId)
- setQuoteTokenId(inputCoingeckoId)
- }
+ setBaseTokenId(inputCoingeckoId)
+ setQuoteTokenId(outputCoingeckoId)
}, [inputCoingeckoId, outputCoingeckoId])
const calculateChartChange = useCallback(() => {
@@ -485,7 +538,16 @@ const SwapTokenChart = () => {
{swapMarketName}
setFlipPrices(!flipPrices)}
+ onClick={() =>
+ handleFlipPrices(
+ !flipPrices,
+ flipPrices,
+ inputBank.name,
+ outputBank.name,
+ swapChartSettings,
+ setSwapChartSettings,
+ )
+ }
hideBg
>
diff --git a/types/index.ts b/types/index.ts
index ff55d4a9..ae6ed324 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -466,3 +466,8 @@ export interface ContributionDetails {
perpMarketContributions: PerpMarketContribution[]
spotUi: number
}
+
+export type SwapChartSettings = {
+ flipPrices: boolean
+ pair: string
+}
diff --git a/utils/constants.ts b/utils/constants.ts
index f2eedf7a..286dbf9c 100644
--- a/utils/constants.ts
+++ b/utils/constants.ts
@@ -6,10 +6,10 @@ export const CLIENT_TX_TIMEOUT = 90000
export const SECONDS = 1000
-export const INPUT_TOKEN_DEFAULT = 'USDC'
+export const INPUT_TOKEN_DEFAULT = 'SOL'
export const MANGO_MINT = 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac'
export const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
-export const OUTPUT_TOKEN_DEFAULT = 'SOL'
+export const OUTPUT_TOKEN_DEFAULT = 'MNGO'
export const JUPITER_V4_PROGRAM_ID =
'JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB'
@@ -57,6 +57,8 @@ export const SWAP_MARGIN_KEY = 'swapMargin-0.1'
export const SHOW_SWAP_INTRO_MODAL = 'showSwapModal-0.1'
+export const SWAP_CHART_SETTINGS_KEY = 'swapChartSettings-0.1'
+
export const ACCEPT_TERMS_KEY = 'termsOfUseAccepted-0.1'
export const TRADE_LAYOUT_KEY = 'tradeLayoutKey-0.1'