merge main
This commit is contained in:
commit
84ecc51d87
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ export const calcPricePrecision = (num: number | string) => {
|
|||
export const formatPrice = (
|
||||
num: number,
|
||||
precision?: number,
|
||||
gr0 = true
|
||||
gr0 = true,
|
||||
): string => {
|
||||
if (!num) {
|
||||
return num.toString()
|
||||
|
@ -132,7 +132,7 @@ export const formatPrice = (
|
|||
const matchString: string = match[0].slice(1)
|
||||
formated = formated.replace(
|
||||
/\.0{4,15}/g,
|
||||
`.0${SUBSCRIPT_NUMBER_MAP[matchString.length]}`
|
||||
`.0${SUBSCRIPT_NUMBER_MAP[matchString.length]}`,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ export function subscribeOnStream(
|
|||
onRealtimeCallback: any,
|
||||
subscriberUID: any,
|
||||
onResetCacheNeededCallback: any,
|
||||
lastBar: any
|
||||
lastBar: any,
|
||||
) {
|
||||
subscriptionItem = {
|
||||
resolution,
|
||||
|
|
|
@ -3,7 +3,7 @@ type CoingeckoOhlcv = [
|
|||
open: number,
|
||||
high: number,
|
||||
low: number,
|
||||
close: number
|
||||
close: number,
|
||||
][]
|
||||
|
||||
export type ChartDataItem = {
|
||||
|
@ -16,16 +16,16 @@ export type ChartDataItem = {
|
|||
export const fetchChartData = async (
|
||||
baseTokenId: string | undefined,
|
||||
quoteTokenId: string | undefined,
|
||||
daysToShow: string
|
||||
daysToShow: string,
|
||||
): Promise<ChartDataItem[]> => {
|
||||
if (!baseTokenId || !quoteTokenId) return []
|
||||
try {
|
||||
const [inputResponse, outputResponse] = await Promise.all([
|
||||
fetch(
|
||||
`https://api.coingecko.com/api/v3/coins/${baseTokenId}/ohlc?vs_currency=usd&days=${daysToShow}`
|
||||
`https://api.coingecko.com/api/v3/coins/${baseTokenId}/ohlc?vs_currency=usd&days=${daysToShow}`,
|
||||
),
|
||||
fetch(
|
||||
`https://api.coingecko.com/api/v3/coins/${quoteTokenId}/ohlc?vs_currency=usd&days=${daysToShow}`
|
||||
`https://api.coingecko.com/api/v3/coins/${quoteTokenId}/ohlc?vs_currency=usd&days=${daysToShow}`,
|
||||
),
|
||||
])
|
||||
|
||||
|
@ -36,7 +36,7 @@ export const fetchChartData = async (
|
|||
const parsedData: ChartDataItem[] = []
|
||||
for (const inputTokenCandle of inputTokenData) {
|
||||
const outputTokenCandle = outputTokenData.find(
|
||||
(outputTokenCandle) => outputTokenCandle[0] === inputTokenCandle[0]
|
||||
(outputTokenCandle) => outputTokenCandle[0] === inputTokenCandle[0],
|
||||
)
|
||||
if (outputTokenCandle) {
|
||||
if (['usd-coin', 'tether'].includes(quoteTokenId)) {
|
||||
|
|
|
@ -72,11 +72,11 @@ const configurationData = {
|
|||
|
||||
const getTickerFromMktAddress = (
|
||||
group: Group,
|
||||
symbolAddress: string
|
||||
symbolAddress: string,
|
||||
): string | null => {
|
||||
try {
|
||||
const serumMkt = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(symbolAddress)
|
||||
new PublicKey(symbolAddress),
|
||||
)
|
||||
|
||||
if (serumMkt) {
|
||||
|
@ -88,7 +88,7 @@ const getTickerFromMktAddress = (
|
|||
|
||||
const perpMarkets = Array.from(group.perpMarketsMapByMarketIndex.values())
|
||||
const perpMkt = perpMarkets.find(
|
||||
(perpMarket) => perpMarket.publicKey.toString() === symbolAddress
|
||||
(perpMarket) => perpMarket.publicKey.toString() === symbolAddress,
|
||||
)
|
||||
|
||||
if (perpMkt) {
|
||||
|
@ -102,12 +102,12 @@ let marketType: 'spot' | 'perp'
|
|||
|
||||
export const queryPerpBars = async (
|
||||
tokenAddress: string,
|
||||
resolution: typeof SUPPORTED_RESOLUTIONS[number],
|
||||
resolution: (typeof SUPPORTED_RESOLUTIONS)[number],
|
||||
periodParams: {
|
||||
firstDataRequest: boolean
|
||||
from: number
|
||||
to: number
|
||||
}
|
||||
},
|
||||
): Promise<Bar[]> => {
|
||||
const { from, to } = periodParams
|
||||
|
||||
|
@ -150,12 +150,12 @@ export const queryPerpBars = async (
|
|||
|
||||
export const queryBirdeyeBars = async (
|
||||
tokenAddress: string,
|
||||
resolution: typeof SUPPORTED_RESOLUTIONS[number],
|
||||
resolution: (typeof SUPPORTED_RESOLUTIONS)[number],
|
||||
periodParams: {
|
||||
firstDataRequest: boolean
|
||||
from: number
|
||||
to: number
|
||||
}
|
||||
},
|
||||
): Promise<Bar[]> => {
|
||||
const { from, to } = periodParams
|
||||
const urlParameters = {
|
||||
|
@ -167,7 +167,7 @@ export const queryBirdeyeBars = async (
|
|||
const query = Object.keys(urlParameters)
|
||||
.map(
|
||||
(name: string) =>
|
||||
`${name}=${encodeURIComponent((urlParameters as any)[name])}`
|
||||
`${name}=${encodeURIComponent((urlParameters as any)[name])}`,
|
||||
)
|
||||
.join('&')
|
||||
|
||||
|
@ -207,14 +207,14 @@ export default {
|
|||
_userInput: string,
|
||||
_exchange: string,
|
||||
_symbolType: string,
|
||||
_onResultReadyCallback: (items: SearchSymbolResultItem[]) => void
|
||||
_onResultReadyCallback: (items: SearchSymbolResultItem[]) => void,
|
||||
) => {
|
||||
return
|
||||
},
|
||||
|
||||
resolveSymbol: async (
|
||||
symbolAddress: string,
|
||||
onSymbolResolvedCallback: (symbolInfo: SymbolInfo) => void
|
||||
onSymbolResolvedCallback: (symbolInfo: SymbolInfo) => void,
|
||||
// _onResolveErrorCallback: any,
|
||||
// _extension: any
|
||||
) => {
|
||||
|
@ -283,9 +283,9 @@ export default {
|
|||
bars: Bar[],
|
||||
t: {
|
||||
noData: boolean
|
||||
}
|
||||
},
|
||||
) => void,
|
||||
onErrorCallback: (e: any) => void
|
||||
onErrorCallback: (e: any) => void,
|
||||
) => {
|
||||
try {
|
||||
const { firstDataRequest } = periodParams
|
||||
|
@ -298,14 +298,14 @@ export default {
|
|||
bars = await queryPerpBars(
|
||||
symbolInfo.address,
|
||||
resolution as any,
|
||||
periodParams
|
||||
periodParams,
|
||||
)
|
||||
} else {
|
||||
marketType = 'spot'
|
||||
bars = await queryBirdeyeBars(
|
||||
symbolInfo.address,
|
||||
resolution as any,
|
||||
periodParams
|
||||
periodParams,
|
||||
)
|
||||
}
|
||||
if (!bars || bars.length === 0) {
|
||||
|
@ -335,7 +335,7 @@ export default {
|
|||
resolution: string,
|
||||
onRealtimeCallback: (data: any) => void,
|
||||
subscriberUID: string,
|
||||
onResetCacheNeededCallback: () => void
|
||||
onResetCacheNeededCallback: () => void,
|
||||
) => {
|
||||
subscriptionIds.set(subscriberUID, symbolInfo.address)
|
||||
if (symbolInfo.description?.includes('PERP')) {
|
||||
|
@ -345,7 +345,7 @@ export default {
|
|||
onRealtimeCallback,
|
||||
subscriberUID,
|
||||
onResetCacheNeededCallback,
|
||||
lastBarsCache.get(symbolInfo.address)
|
||||
lastBarsCache.get(symbolInfo.address),
|
||||
)
|
||||
} else {
|
||||
subscribeOnSpotStream(
|
||||
|
@ -354,7 +354,7 @@ export default {
|
|||
onRealtimeCallback,
|
||||
subscriberUID,
|
||||
onResetCacheNeededCallback,
|
||||
lastBarsCache.get(symbolInfo.address)
|
||||
lastBarsCache.get(symbolInfo.address),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -66,12 +66,12 @@ const configurationData = {
|
|||
|
||||
export const queryBars = async (
|
||||
tokenAddress: string,
|
||||
resolution: typeof SUPPORTED_RESOLUTIONS[number],
|
||||
resolution: (typeof SUPPORTED_RESOLUTIONS)[number],
|
||||
periodParams: {
|
||||
firstDataRequest: boolean
|
||||
from: number
|
||||
to: number
|
||||
}
|
||||
},
|
||||
): Promise<Bar[]> => {
|
||||
const { from, to } = periodParams
|
||||
const urlParameters = {
|
||||
|
@ -121,14 +121,14 @@ export default {
|
|||
_userInput: string,
|
||||
_exchange: string,
|
||||
_symbolType: string,
|
||||
_onResultReadyCallback: (items: SearchSymbolResultItem[]) => void
|
||||
_onResultReadyCallback: (items: SearchSymbolResultItem[]) => void,
|
||||
) => {
|
||||
return
|
||||
},
|
||||
|
||||
resolveSymbol: async (
|
||||
symbolAddress: string,
|
||||
onSymbolResolvedCallback: (symbolInfo: SymbolInfo) => void
|
||||
onSymbolResolvedCallback: (symbolInfo: SymbolInfo) => void,
|
||||
// _onResolveErrorCallback: any,
|
||||
// _extension: any
|
||||
) => {
|
||||
|
@ -187,16 +187,16 @@ export default {
|
|||
bars: Bar[],
|
||||
t: {
|
||||
noData: boolean
|
||||
}
|
||||
},
|
||||
) => void,
|
||||
onErrorCallback: (e: any) => void
|
||||
onErrorCallback: (e: any) => void,
|
||||
) => {
|
||||
try {
|
||||
const { firstDataRequest } = periodParams
|
||||
const bars = await queryBars(
|
||||
symbolInfo.address,
|
||||
resolution as any,
|
||||
periodParams
|
||||
periodParams,
|
||||
)
|
||||
if (!bars || bars.length === 0) {
|
||||
// "noData" should be set if there is no data in the requested period.
|
||||
|
@ -226,7 +226,7 @@ export default {
|
|||
resolution: string,
|
||||
onRealtimeCallback: (data: any) => void,
|
||||
subscriberUID: string,
|
||||
onResetCacheNeededCallback: () => void
|
||||
onResetCacheNeededCallback: () => void,
|
||||
) => {
|
||||
subscribeOnStream(
|
||||
symbolInfo,
|
||||
|
@ -234,7 +234,7 @@ export default {
|
|||
onRealtimeCallback,
|
||||
subscriberUID,
|
||||
onResetCacheNeededCallback,
|
||||
lastBarsCache.get(symbolInfo.address)
|
||||
lastBarsCache.get(symbolInfo.address),
|
||||
)
|
||||
},
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ export function subscribeOnStream(
|
|||
onRealtimeCallback: any,
|
||||
subscriberUID: any,
|
||||
onResetCacheNeededCallback: any,
|
||||
lastBar: any
|
||||
lastBar: any,
|
||||
) {
|
||||
subscriptionItem = {
|
||||
resolution,
|
||||
|
|
|
@ -6,7 +6,7 @@ export type NotificationSettings = {
|
|||
|
||||
export const fetchNotificationSettings = async (
|
||||
wallet: string,
|
||||
token: string
|
||||
token: string,
|
||||
) => {
|
||||
const data = await fetch(
|
||||
`${NOTIFICATION_API}notifications/user/getSettings`,
|
||||
|
@ -15,7 +15,7 @@ export const fetchNotificationSettings = async (
|
|||
authorization: token,
|
||||
publickey: wallet,
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
const body = await data.json()
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
const [inputAmount, setInputAmount] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [selectedToken, setSelectedToken] = useState(
|
||||
token || INPUT_TOKEN_DEFAULT
|
||||
token || INPUT_TOKEN_DEFAULT,
|
||||
)
|
||||
const [showTokenList, setShowTokenList] = useState(false)
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
|
@ -91,11 +91,11 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
setSizePercentage(percentage)
|
||||
const amount = floorToDecimal(
|
||||
new Decimal(percentage).div(100).mul(tokenMax),
|
||||
bank.mintDecimals
|
||||
bank.mintDecimals,
|
||||
)
|
||||
setInputAmount(amount.toFixed())
|
||||
},
|
||||
[tokenMax, bank]
|
||||
[tokenMax, bank],
|
||||
)
|
||||
|
||||
const setMax = useCallback(() => {
|
||||
|
@ -123,7 +123,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
mangoAccount,
|
||||
bank!.mint,
|
||||
Number(inputAmount),
|
||||
true
|
||||
true,
|
||||
)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
|
|
|
@ -43,7 +43,7 @@ interface DepositFormProps {
|
|||
|
||||
export const walletBalanceForToken = (
|
||||
walletTokens: TokenAccount[],
|
||||
token: string
|
||||
token: string,
|
||||
): { maxAmount: number; maxDecimals: number } => {
|
||||
const group = mangoStore.getState().group
|
||||
const bank = group?.banksMapByName.get(token)?.[0]
|
||||
|
@ -67,7 +67,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
const [inputAmount, setInputAmount] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [selectedToken, setSelectedToken] = useState(
|
||||
token || INPUT_TOKEN_DEFAULT
|
||||
token || INPUT_TOKEN_DEFAULT,
|
||||
)
|
||||
const [showTokenList, setShowTokenList] = useState(false)
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
|
@ -98,11 +98,11 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
setSizePercentage(percentage)
|
||||
const amount = floorToDecimal(
|
||||
new Decimal(tokenMax.maxAmount).mul(percentage).div(100),
|
||||
tokenMax.maxDecimals
|
||||
tokenMax.maxDecimals,
|
||||
)
|
||||
setInputAmount(amount.toFixed())
|
||||
},
|
||||
[tokenMax]
|
||||
[tokenMax],
|
||||
)
|
||||
|
||||
const handleSelectToken = (token: string) => {
|
||||
|
@ -124,7 +124,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
group,
|
||||
mangoAccount,
|
||||
bank.mint,
|
||||
parseFloat(inputAmount)
|
||||
parseFloat(inputAmount),
|
||||
)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
|
@ -225,7 +225,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
value={inputAmount}
|
||||
onValueChange={(e: NumberFormatValues) => {
|
||||
setInputAmount(
|
||||
!Number.isNaN(Number(e.value)) ? e.value : ''
|
||||
!Number.isNaN(Number(e.value)) ? e.value : '',
|
||||
)
|
||||
}}
|
||||
isAllowed={withValueLimit}
|
||||
|
|
|
@ -22,7 +22,7 @@ const HealthImpactTokenChange = ({
|
|||
mangoAccount.simHealthRatioWithTokenPositionUiChanges(
|
||||
group,
|
||||
[{ mintPk, uiTokenAmount }],
|
||||
HealthType.maint
|
||||
HealthType.maint,
|
||||
)
|
||||
|
||||
return projectedHealth! > 100
|
||||
|
|
|
@ -36,14 +36,14 @@ const termsLastUpdated = 1679441610978
|
|||
const Layout = ({ children }: { children: ReactNode }) => {
|
||||
const [isCollapsed, setIsCollapsed] = useLocalStorageState(
|
||||
SIDEBAR_COLLAPSE_KEY,
|
||||
false
|
||||
false,
|
||||
)
|
||||
|
||||
const { width } = useViewport()
|
||||
const { asPath } = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
if (width < breakpoints.xl) {
|
||||
if (width < breakpoints['2xl']) {
|
||||
setIsCollapsed(true)
|
||||
}
|
||||
}, [width])
|
||||
|
@ -52,9 +52,12 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
|||
const animationFrames = 15
|
||||
|
||||
for (let x = 1; x <= animationFrames; x++) {
|
||||
setTimeout(() => {
|
||||
setTimeout(
|
||||
() => {
|
||||
window.dispatchEvent(new Event('resize'))
|
||||
}, (sideBarAnimationDuration / animationFrames) * x)
|
||||
},
|
||||
(sideBarAnimationDuration / animationFrames) * x,
|
||||
)
|
||||
}
|
||||
}, [isCollapsed])
|
||||
|
||||
|
@ -84,7 +87,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
|||
|
||||
<div className="fixed z-20 hidden h-screen md:block">
|
||||
<button
|
||||
className="absolute right-0 top-1/2 z-20 hidden h-8 w-3 -translate-y-1/2 rounded-none rounded-l bg-th-bkg-3 hover:bg-th-bkg-4 focus:outline-none focus-visible:bg-th-bkg-4 xl:block"
|
||||
className="absolute right-0 top-1/2 z-20 hidden h-8 w-3 -translate-y-1/2 rounded-none rounded-l bg-th-bkg-3 hover:bg-th-bkg-4 focus:outline-none focus-visible:bg-th-bkg-4 2xl:block"
|
||||
onClick={handleToggleSidebar}
|
||||
>
|
||||
<ChevronRightIcon
|
||||
|
@ -124,7 +127,7 @@ const TermsOfUse = () => {
|
|||
const { connected } = useWallet()
|
||||
const [acceptTerms, setAcceptTerms] = useLocalStorageState(
|
||||
ACCEPT_TERMS_KEY,
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
const showTermsOfUse = useMemo(() => {
|
||||
|
|
|
@ -7,6 +7,8 @@ import useMangoAccount from 'hooks/useMangoAccount'
|
|||
import useInterval from './shared/useInterval'
|
||||
import { SECONDS } from 'utils/constants'
|
||||
import useNetworkSpeed from 'hooks/useNetworkSpeed'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
const actions = mangoStore.getState().actions
|
||||
|
@ -17,6 +19,15 @@ const HydrateStore = () => {
|
|||
const { mangoAccountPk, mangoAccountAddress } = useMangoAccount()
|
||||
const connection = mangoStore((s) => s.connection)
|
||||
const slowNetwork = useNetworkSpeed()
|
||||
const { wallet } = useWallet()
|
||||
|
||||
const [, setLastWalletName] = useLocalStorageState('lastWalletName', '')
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet?.adapter) {
|
||||
setLastWalletName(wallet?.adapter.name)
|
||||
}
|
||||
}, [wallet, setLastWalletName])
|
||||
|
||||
useEffect(() => {
|
||||
if (marketName && typeof marketName === 'string') {
|
||||
|
@ -27,17 +38,23 @@ const HydrateStore = () => {
|
|||
actions.fetchGroup()
|
||||
}, [marketName])
|
||||
|
||||
useInterval(() => {
|
||||
useInterval(
|
||||
() => {
|
||||
actions.fetchGroup()
|
||||
}, (slowNetwork ? 40 : 20) * SECONDS)
|
||||
},
|
||||
(slowNetwork ? 40 : 20) * SECONDS,
|
||||
)
|
||||
|
||||
// refetches open orders every 30 seconds
|
||||
// only the selected market's open orders are updated via websocket
|
||||
useInterval(() => {
|
||||
useInterval(
|
||||
() => {
|
||||
if (mangoAccountAddress) {
|
||||
actions.fetchOpenOrders()
|
||||
}
|
||||
}, (slowNetwork ? 60 : 30) * SECONDS)
|
||||
},
|
||||
(slowNetwork ? 60 : 30) * SECONDS,
|
||||
)
|
||||
|
||||
// refetch trade history and activity feed when switching accounts
|
||||
useEffect(() => {
|
||||
|
@ -48,10 +65,13 @@ const HydrateStore = () => {
|
|||
}, [mangoAccountAddress])
|
||||
|
||||
// reload and parse market fills from the event queue
|
||||
useInterval(async () => {
|
||||
useInterval(
|
||||
async () => {
|
||||
const actions = mangoStore.getState().actions
|
||||
actions.loadMarketFills()
|
||||
}, (slowNetwork ? 60 : 20) * SECONDS)
|
||||
},
|
||||
(slowNetwork ? 60 : 20) * SECONDS,
|
||||
)
|
||||
|
||||
// The websocket library solana/web3.js uses closes its websocket connection when the subscription list
|
||||
// is empty after opening its first time, preventing subsequent subscriptions from receiving responses.
|
||||
|
@ -81,11 +101,11 @@ const HydrateStore = () => {
|
|||
if (context.slot > lastSeenSlot) {
|
||||
const decodedMangoAccount = client.program.coder.accounts.decode(
|
||||
'mangoAccount',
|
||||
info?.data
|
||||
info?.data,
|
||||
)
|
||||
const newMangoAccount = MangoAccount.from(
|
||||
mangoAccount.publicKey,
|
||||
decodedMangoAccount
|
||||
decodedMangoAccount,
|
||||
)
|
||||
if (newMangoAccount.serum3Active().length > 0) {
|
||||
await newMangoAccount.reloadSerum3OpenOrders(client)
|
||||
|
@ -96,7 +116,7 @@ const HydrateStore = () => {
|
|||
})
|
||||
actions.fetchOpenOrders()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
return () => {
|
||||
|
|
|
@ -45,7 +45,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
const [inputAmount, setInputAmount] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [selectedToken, setSelectedToken] = useState(
|
||||
token || INPUT_TOKEN_DEFAULT
|
||||
token || INPUT_TOKEN_DEFAULT,
|
||||
)
|
||||
const [showTokenList, setShowTokenList] = useState(false)
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
|
@ -69,7 +69,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
const borrowAmount = useMemo(() => {
|
||||
if (!mangoAccount || !bank) return new Decimal(0)
|
||||
const amount = new Decimal(
|
||||
mangoAccount.getTokenBorrowsUi(bank)
|
||||
mangoAccount.getTokenBorrowsUi(bank),
|
||||
).toDecimalPlaces(bank.mintDecimals, Decimal.ROUND_UP)
|
||||
return amount
|
||||
}, [bank, mangoAccount])
|
||||
|
@ -78,7 +78,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
if (!bank) return
|
||||
const amount = new Decimal(borrowAmount).toDecimalPlaces(
|
||||
bank.mintDecimals,
|
||||
Decimal.ROUND_UP
|
||||
Decimal.ROUND_UP,
|
||||
)
|
||||
setInputAmount(amount.toFixed())
|
||||
setSizePercentage('100')
|
||||
|
@ -95,7 +95,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
|
||||
setInputAmount(amount.toFixed())
|
||||
},
|
||||
[bank, borrowAmount]
|
||||
[bank, borrowAmount],
|
||||
)
|
||||
|
||||
const handleSelectToken = (token: string) => {
|
||||
|
@ -130,7 +130,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
mangoAccount,
|
||||
bank.mint,
|
||||
actualAmount,
|
||||
true
|
||||
true,
|
||||
)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
|
@ -154,7 +154,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
})
|
||||
}
|
||||
},
|
||||
[bank, publicKey?.toBase58(), sizePercentage]
|
||||
[bank, publicKey?.toBase58(), sizePercentage],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -236,7 +236,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
value={inputAmount}
|
||||
onValueChange={(e: NumberFormatValues) => {
|
||||
setInputAmount(
|
||||
!Number.isNaN(Number(e.value)) ? e.value : ''
|
||||
!Number.isNaN(Number(e.value)) ? e.value : '',
|
||||
)
|
||||
}}
|
||||
isAllowed={withValueLimit}
|
||||
|
|
|
@ -45,7 +45,7 @@ const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
|||
<div
|
||||
className={`transition-all duration-${sideBarAnimationDuration} ${
|
||||
collapsed ? 'w-[64px]' : 'w-44 lg:w-48 xl:w-52'
|
||||
} border-r border-th-bkg-3 bg-th-bkg-1`}
|
||||
} box-border border-r border-th-bkg-3 bg-th-bkg-1`}
|
||||
>
|
||||
<div className="flex min-h-screen flex-col justify-between">
|
||||
<div className="my-2">
|
||||
|
|
|
@ -10,7 +10,7 @@ const tpsWarningThreshold = 1300
|
|||
|
||||
const getRecentPerformance = async (
|
||||
connection: Connection,
|
||||
setTps: (x: number) => void
|
||||
setTps: (x: number) => void,
|
||||
) => {
|
||||
try {
|
||||
const samples = 2
|
||||
|
|
|
@ -38,38 +38,38 @@ const TokenList = () => {
|
|||
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
const [showZeroBalances, setShowZeroBalances] = useLocalStorageState(
|
||||
SHOW_ZERO_BALANCES_KEY,
|
||||
true
|
||||
true,
|
||||
)
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const { initContributions } = useHealthContributions()
|
||||
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
||||
const totalInterestData = mangoStore(
|
||||
(s) => s.mangoAccount.interestTotals.data
|
||||
(s) => s.mangoAccount.interestTotals.data,
|
||||
)
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const banks = useBanksWithBalances('balance')
|
||||
|
||||
// const filteredBanks = useMemo(() => {
|
||||
// if (banks.length) {
|
||||
// return showZeroBalances || !mangoAccountAddress
|
||||
// ? banks
|
||||
// : banks.filter((b) => Math.abs(b.balance) > 0)
|
||||
// }
|
||||
// return []
|
||||
// }, [banks, mangoAccountAddress, showZeroBalances])
|
||||
|
||||
const filteredBanks = useMemo(() => {
|
||||
if (!banks.length) return []
|
||||
if (showZeroBalances || !mangoAccountAddress) return banks
|
||||
const filtered = banks.filter((b) => {
|
||||
const contribution =
|
||||
initContributions.find((cont) => cont.asset === b.bank.name)
|
||||
?.contribution || 0
|
||||
return Math.abs(contribution) > 0
|
||||
})
|
||||
return filtered
|
||||
}, [banks, mangoAccountAddress, showZeroBalances, initContributions])
|
||||
if (banks.length) {
|
||||
return showZeroBalances || !mangoAccountAddress
|
||||
? banks
|
||||
: banks.filter((b) => Math.abs(b.balance) > 0)
|
||||
}
|
||||
return []
|
||||
}, [banks, mangoAccountAddress, showZeroBalances])
|
||||
|
||||
// const filteredBanks = useMemo(() => {
|
||||
// if (!banks.length) return []
|
||||
// if (showZeroBalances || !mangoAccountAddress) return banks
|
||||
// const filtered = banks.filter((b) => {
|
||||
// const contribution =
|
||||
// initContributions.find((cont) => cont.asset === b.bank.name)
|
||||
// ?.contribution || 0
|
||||
// return Math.abs(contribution) > 0
|
||||
// })
|
||||
// return filtered
|
||||
// }, [banks, mangoAccountAddress, showZeroBalances, initContributions])
|
||||
|
||||
return (
|
||||
<ContentBox hideBorder hidePadding>
|
||||
|
@ -80,12 +80,12 @@ const TokenList = () => {
|
|||
disabled={!mangoAccount}
|
||||
onChange={() => setShowZeroBalances(!showZeroBalances)}
|
||||
>
|
||||
{t('account:zero-collateral')}
|
||||
{t('account:zero-balances')}
|
||||
</Switch>
|
||||
</div>
|
||||
) : null}
|
||||
{showTableView ? (
|
||||
<div className="thin-scroll overflow-x-auto">
|
||||
<>
|
||||
<Table>
|
||||
<thead>
|
||||
<TrHead>
|
||||
|
@ -99,9 +99,9 @@ const TokenList = () => {
|
|||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<Tooltip content={t('account:tooltip-collateral-value')}>
|
||||
<Tooltip content={t('tooltip-collateral-value')}>
|
||||
<span className="tooltip-underline">
|
||||
{t('account:collateral-value')}
|
||||
{t('collateral-value')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
@ -137,7 +137,7 @@ const TokenList = () => {
|
|||
const hasInterestEarned = totalInterestData.find(
|
||||
(d) =>
|
||||
d.symbol.toLowerCase() === symbol.toLowerCase() ||
|
||||
(symbol === 'ETH (Portal)' && d.symbol === 'ETH')
|
||||
(symbol === 'ETH (Portal)' && d.symbol === 'ETH'),
|
||||
)
|
||||
|
||||
const interestAmount = hasInterestEarned
|
||||
|
@ -254,7 +254,7 @@ const TokenList = () => {
|
|||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="border-b border-th-bkg-3">
|
||||
{filteredBanks.map((b) => {
|
||||
|
@ -274,7 +274,7 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
|
|||
const { mangoAccount } = useMangoAccount()
|
||||
const { initContributions } = useHealthContributions()
|
||||
const totalInterestData = mangoStore(
|
||||
(s) => s.mangoAccount.interestTotals.data
|
||||
(s) => s.mangoAccount.interestTotals.data,
|
||||
)
|
||||
const tokenBank = bank.bank
|
||||
const mint = tokenBank.mint
|
||||
|
@ -283,7 +283,7 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
|
|||
const hasInterestEarned = totalInterestData.find(
|
||||
(d) =>
|
||||
d.symbol.toLowerCase() === symbol.toLowerCase() ||
|
||||
(symbol === 'ETH (Portal)' && d.symbol === 'ETH')
|
||||
(symbol === 'ETH (Portal)' && d.symbol === 'ETH'),
|
||||
)
|
||||
|
||||
const interestAmount = hasInterestEarned
|
||||
|
@ -297,10 +297,8 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
|
|||
: 0
|
||||
|
||||
const tokenBalance = bank.balance
|
||||
|
||||
const inOrders = spotBalances[mint.toString()]?.inOrders || 0
|
||||
|
||||
const unsettled = spotBalances[mint.toString()]?.unsettled || 0
|
||||
const inOrders = spotBalances[mint.toString()]?.inOrders || 0
|
||||
|
||||
const collateralValue =
|
||||
initContributions.find((val) => val.asset === tokenBank.name)
|
||||
|
@ -361,9 +359,9 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
|
|||
<Disclosure.Panel>
|
||||
<div className="mx-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4 pb-4">
|
||||
<div className="col-span-1">
|
||||
<Tooltip content={t('account:tooltip-collateral-value')}>
|
||||
<Tooltip content={t('tooltip-collateral-value')}>
|
||||
<p className="tooltip-underline text-xs text-th-fgd-3">
|
||||
{t('account:collateral-value')}
|
||||
{t('collateral-value')}
|
||||
</p>
|
||||
</Tooltip>
|
||||
<p className="font-mono text-th-fgd-2">
|
||||
|
@ -474,7 +472,7 @@ const ActionsMenu = ({
|
|||
? setShowWithdrawModal(true)
|
||||
: setShowRepayModal(true)
|
||||
},
|
||||
[]
|
||||
[],
|
||||
)
|
||||
|
||||
const balance = useMemo(() => {
|
||||
|
@ -484,7 +482,7 @@ const ActionsMenu = ({
|
|||
|
||||
const handleSwap = useCallback(() => {
|
||||
const tokenInfo = mangoTokens.find(
|
||||
(t) => t.address === bank.mint.toString()
|
||||
(t) => t.address === bank.mint.toString(),
|
||||
)
|
||||
const group = mangoStore.getState().group
|
||||
if (balance && balance > 0) {
|
||||
|
@ -503,7 +501,7 @@ const ActionsMenu = ({
|
|||
} else {
|
||||
if (tokenInfo?.symbol === 'USDC') {
|
||||
const solTokenInfo = mangoTokens.find(
|
||||
(t) => t.address === WRAPPED_SOL_MINT.toString()
|
||||
(t) => t.address === WRAPPED_SOL_MINT.toString(),
|
||||
)
|
||||
const solBank = group?.getFirstBankByMint(WRAPPED_SOL_MINT)
|
||||
set((s) => {
|
||||
|
@ -553,7 +551,7 @@ const ActionsMenu = ({
|
|||
leaveTo="opacity-0"
|
||||
>
|
||||
<Popover.Panel
|
||||
className={`thin-scroll absolute bottom-12 left-0 z-40 max-h-60 w-32 space-y-2 overflow-auto rounded-md bg-th-bkg-2 p-4 pt-2 md:bottom-0 md:right-12 md:left-auto md:pt-4`}
|
||||
className={`thin-scroll absolute bottom-12 left-0 z-20 max-h-60 w-32 space-y-2 overflow-auto rounded-md bg-th-bkg-2 p-4 pt-2 md:bottom-0 md:right-12 md:left-auto md:pt-4`}
|
||||
>
|
||||
<div className="hidden items-center justify-center border-b border-th-bkg-3 pb-2 md:flex">
|
||||
<div className="mr-2 flex flex-shrink-0 items-center">
|
||||
|
|
|
@ -30,6 +30,9 @@ import { copyToClipboard } from 'utils'
|
|||
import UserSetupModal from './modals/UserSetupModal'
|
||||
import { IS_ONBOARDED_KEY } from 'utils/constants'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
|
||||
const TopBar = () => {
|
||||
const { t } = useTranslation('common')
|
||||
|
@ -50,16 +53,20 @@ const TopBar = () => {
|
|||
const isMobile = width ? width < breakpoints.sm : false
|
||||
|
||||
const { isUnownedAccount } = useUnownedAccount()
|
||||
const [showUserSetup, setShowUserSetup] = useState(false)
|
||||
const showUserSetup = mangoStore((s) => s.showUserSetup)
|
||||
const [, setIsOnboarded] = useLocalStorageState(IS_ONBOARDED_KEY)
|
||||
|
||||
const handleCloseSetup = useCallback(() => {
|
||||
setShowUserSetup(false)
|
||||
set((s) => {
|
||||
s.showUserSetup = false
|
||||
})
|
||||
setIsOnboarded(true)
|
||||
}, [setShowUserSetup, setIsOnboarded])
|
||||
}, [setIsOnboarded])
|
||||
|
||||
const handleShowSetup = useCallback(() => {
|
||||
setShowUserSetup(true)
|
||||
set((s) => {
|
||||
s.showUserSetup = true
|
||||
})
|
||||
}, [])
|
||||
|
||||
const handleDepositWithdrawModal = (action: 'deposit' | 'withdraw') => {
|
||||
|
|
|
@ -49,7 +49,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
const [inputAmount, setInputAmount] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [selectedToken, setSelectedToken] = useState(
|
||||
token || INPUT_TOKEN_DEFAULT
|
||||
token || INPUT_TOKEN_DEFAULT,
|
||||
)
|
||||
const [showTokenList, setShowTokenList] = useState(false)
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
|
@ -82,17 +82,17 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
if (percentage !== '100') {
|
||||
amount = floorToDecimal(
|
||||
new Decimal(adjustedTokenMax).mul(percentage).div(100),
|
||||
bank.mintDecimals
|
||||
bank.mintDecimals,
|
||||
)
|
||||
} else {
|
||||
amount = floorToDecimal(
|
||||
new Decimal(adjustedTokenMax),
|
||||
bank.mintDecimals
|
||||
bank.mintDecimals,
|
||||
)
|
||||
}
|
||||
setInputAmount(amount.toString())
|
||||
},
|
||||
[bank, adjustedTokenMax]
|
||||
[bank, adjustedTokenMax],
|
||||
)
|
||||
|
||||
const setMax = useCallback(() => {
|
||||
|
@ -116,7 +116,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
mangoAccount,
|
||||
bank.mint,
|
||||
withdrawAmount,
|
||||
false
|
||||
false,
|
||||
)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
|
@ -227,7 +227,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
value={inputAmount}
|
||||
onValueChange={(e: NumberFormatValues) =>
|
||||
setInputAmount(
|
||||
!Number.isNaN(Number(e.value)) ? e.value : ''
|
||||
!Number.isNaN(Number(e.value)) ? e.value : '',
|
||||
)
|
||||
}
|
||||
isAllowed={withValueLimit}
|
||||
|
|
|
@ -29,7 +29,7 @@ import { breakpoints } from 'utils/theme'
|
|||
|
||||
export const handleCopyAddress = (
|
||||
mangoAccount: MangoAccount,
|
||||
successMessage: string
|
||||
successMessage: string,
|
||||
) => {
|
||||
copyToClipboard(mangoAccount.publicKey.toString())
|
||||
notify({
|
||||
|
@ -121,7 +121,7 @@ const AccountActions = () => {
|
|||
mangoAccount!,
|
||||
t('copy-address-success', {
|
||||
pk: abbreviateAddress(mangoAccount!.publicKey),
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
>
|
||||
|
|
|
@ -40,7 +40,7 @@ const AccountHeroStats = ({
|
|||
useAccountHourlyVolumeStats()
|
||||
|
||||
const totalInterestData = mangoStore(
|
||||
(s) => s.mangoAccount.interestTotals.data
|
||||
(s) => s.mangoAccount.interestTotals.data,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -63,7 +63,7 @@ const AccountHeroStats = ({
|
|||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
enabled: !!mangoAccountAddress,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const {
|
||||
|
@ -79,7 +79,7 @@ const AccountHeroStats = ({
|
|||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
enabled: !!mangoAccountAddress,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const maintHealth = useMemo(() => {
|
||||
|
@ -91,7 +91,7 @@ const AccountHeroStats = ({
|
|||
const leverage = useMemo(() => {
|
||||
if (!group || !mangoAccount) return 0
|
||||
const assetsValue = toUiDecimalsForQuote(
|
||||
mangoAccount.getAssetsValue(group).toNumber()
|
||||
mangoAccount.getAssetsValue(group).toNumber(),
|
||||
)
|
||||
|
||||
if (isNaN(assetsValue / accountValue)) {
|
||||
|
@ -110,7 +110,7 @@ const AccountHeroStats = ({
|
|||
if (totalInterestData.length) {
|
||||
return totalInterestData.reduce(
|
||||
(a, c) => a + (c.borrow_interest_usd * -1 + c.deposit_interest_usd),
|
||||
0
|
||||
0,
|
||||
)
|
||||
}
|
||||
return 0.0
|
||||
|
@ -120,7 +120,7 @@ const AccountHeroStats = ({
|
|||
if (fundingData?.length && mangoAccountAddress) {
|
||||
return fundingData.reduce(
|
||||
(a, c) => a + c.long_funding + c.short_funding,
|
||||
0
|
||||
0,
|
||||
)
|
||||
}
|
||||
return 0.0
|
||||
|
@ -167,7 +167,7 @@ const AccountHeroStats = ({
|
|||
return (
|
||||
<>
|
||||
<div className="grid grid-cols-6 border-b border-th-bkg-3">
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 md:col-span-3 lg:col-span-2 lg:border-t-0 xl:col-span-1">
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 md:col-span-3 lg:col-span-2 lg:border-t-0 2xl:col-span-1">
|
||||
<div id="account-step-four">
|
||||
<div className="flex justify-between">
|
||||
<Tooltip
|
||||
|
@ -214,9 +214,7 @@ const AccountHeroStats = ({
|
|||
</div>
|
||||
}
|
||||
>
|
||||
<p className="tooltip-underline text-sm font-normal text-th-fgd-3 xl:text-base">
|
||||
{t('health')}
|
||||
</p>
|
||||
<p className="tooltip-underline">{t('health')}</p>
|
||||
</Tooltip>
|
||||
{mangoAccountAddress ? (
|
||||
<Tooltip
|
||||
|
@ -255,7 +253,7 @@ const AccountHeroStats = ({
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-6 flex border-t border-th-bkg-3 py-3 pl-6 md:col-span-3 md:border-l lg:col-span-2 lg:border-t-0 xl:col-span-1">
|
||||
<div className="col-span-6 flex border-t border-th-bkg-3 py-3 pl-6 md:col-span-3 md:border-l lg:col-span-2 lg:border-t-0 2xl:col-span-1">
|
||||
<div id="account-step-five">
|
||||
<Tooltip
|
||||
content={t('account:tooltip-free-collateral')}
|
||||
|
@ -263,16 +261,14 @@ const AccountHeroStats = ({
|
|||
placement="top-start"
|
||||
delay={100}
|
||||
>
|
||||
<p className="tooltip-underline text-sm text-th-fgd-3 xl:text-base">
|
||||
{t('free-collateral')}
|
||||
</p>
|
||||
<p className="tooltip-underline">{t('free-collateral')}</p>
|
||||
</Tooltip>
|
||||
<p className="mt-1 mb-0.5 text-2xl font-bold text-th-fgd-1 lg:text-xl xl:text-2xl">
|
||||
<FormatNumericValue
|
||||
value={
|
||||
group && mangoAccount
|
||||
? toUiDecimalsForQuote(
|
||||
mangoAccount.getCollateralValue(group)
|
||||
mangoAccount.getCollateralValue(group),
|
||||
)
|
||||
: 0
|
||||
}
|
||||
|
@ -293,7 +289,7 @@ const AccountHeroStats = ({
|
|||
value={
|
||||
group && mangoAccount
|
||||
? toUiDecimalsForQuote(
|
||||
mangoAccount.getAssetsValue(group, HealthType.init)
|
||||
mangoAccount.getAssetsValue(group, HealthType.init),
|
||||
)
|
||||
: 0
|
||||
}
|
||||
|
@ -305,7 +301,7 @@ const AccountHeroStats = ({
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-6 flex border-t border-th-bkg-3 py-3 pl-6 pr-4 md:col-span-3 lg:col-span-2 lg:border-l lg:border-t-0 xl:col-span-1">
|
||||
<div className="col-span-6 flex border-t border-th-bkg-3 py-3 pl-6 pr-4 md:col-span-3 lg:col-span-2 lg:border-l lg:border-t-0 2xl:col-span-1">
|
||||
<div
|
||||
id="account-step-seven"
|
||||
className="flex w-full flex-col items-start"
|
||||
|
@ -316,9 +312,7 @@ const AccountHeroStats = ({
|
|||
placement="top-start"
|
||||
delay={100}
|
||||
>
|
||||
<p className="tooltip-underline inline text-sm text-th-fgd-3 xl:text-base">
|
||||
{t('pnl')}
|
||||
</p>
|
||||
<p className="tooltip-underline">{t('pnl')}</p>
|
||||
</Tooltip>
|
||||
{mangoAccountAddress ? (
|
||||
<div className="flex items-center space-x-3">
|
||||
|
@ -364,12 +358,10 @@ const AccountHeroStats = ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 md:col-span-3 md:border-l lg:col-span-2 lg:border-l-0 xl:col-span-1 xl:border-l xl:border-t-0">
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 md:col-span-3 md:border-l lg:col-span-2 lg:border-l-0 2xl:col-span-1 2xl:border-l 2xl:border-t-0">
|
||||
<div id="account-step-six">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<p className="text-sm text-th-fgd-3 xl:text-base">
|
||||
{t('account:lifetime-volume')}
|
||||
</p>
|
||||
<p>{t('account:lifetime-volume')}</p>
|
||||
{mangoAccountAddress ? (
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
|
@ -413,7 +405,7 @@ const AccountHeroStats = ({
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 text-left md:col-span-3 lg:col-span-2 lg:border-l xl:col-span-1 xl:border-t-0">
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 text-left md:col-span-3 lg:col-span-2 lg:border-l 2xl:col-span-1 2xl:border-t-0">
|
||||
<div id="account-step-eight">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<Tooltip
|
||||
|
@ -422,7 +414,7 @@ const AccountHeroStats = ({
|
|||
placement="top-start"
|
||||
delay={100}
|
||||
>
|
||||
<p className="tooltip-underline text-sm text-th-fgd-3 xl:text-base">
|
||||
<p className="tooltip-underline">
|
||||
{t('total-interest-earned')}
|
||||
</p>
|
||||
</Tooltip>
|
||||
|
@ -457,7 +449,7 @@ const AccountHeroStats = ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 text-left md:col-span-3 md:border-l lg:col-span-2 xl:col-span-1 xl:border-t-0">
|
||||
<div className="col-span-6 border-t border-th-bkg-3 py-3 pl-6 pr-4 text-left md:col-span-3 md:border-l lg:col-span-2 2xl:col-span-1 2xl:border-t-0">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<Tooltip
|
||||
content={t('account:tooltip-total-funding')}
|
||||
|
@ -465,7 +457,7 @@ const AccountHeroStats = ({
|
|||
placement="top-start"
|
||||
delay={100}
|
||||
>
|
||||
<p className="tooltip-underline text-sm text-th-fgd-3 xl:text-base">
|
||||
<p className="tooltip-underline">
|
||||
{t('account:total-funding-earned')}
|
||||
</p>
|
||||
</Tooltip>
|
||||
|
|
|
@ -42,7 +42,7 @@ const AccountPage = () => {
|
|||
const isMobile = width ? width < breakpoints.md : false
|
||||
const [activeTab, setActiveTab] = useLocalStorageState(
|
||||
'accountHeroKey-0.1',
|
||||
'account-value'
|
||||
'account-value',
|
||||
)
|
||||
const { performanceData, rollingDailyData } = useAccountPerformanceData()
|
||||
const router = useRouter()
|
||||
|
@ -53,7 +53,7 @@ const AccountPage = () => {
|
|||
const query = { ...router.query, ['view']: view }
|
||||
router.push({ pathname: router.pathname, query })
|
||||
},
|
||||
[router]
|
||||
[router],
|
||||
)
|
||||
|
||||
const handleCloseDailyPnlModal = () => {
|
||||
|
|
|
@ -8,7 +8,6 @@ import { Transition } from '@headlessui/react'
|
|||
import SheenLoader from '../shared/SheenLoader'
|
||||
import Change from '../shared/Change'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import { useTheme } from 'next-themes'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { ANIMATION_SETTINGS_KEY } from 'utils/constants'
|
||||
import { INITIAL_ANIMATION_SETTINGS } from '@components/settings/AnimationSettings'
|
||||
|
@ -21,6 +20,7 @@ import { useViewport } from 'hooks/useViewport'
|
|||
import { breakpoints } from 'utils/theme'
|
||||
import { ViewToShow } from './AccountPage'
|
||||
import useAccountPerformanceData from 'hooks/useAccountPerformanceData'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
const AccountValue = ({
|
||||
accountValue,
|
||||
|
@ -34,13 +34,13 @@ const AccountValue = ({
|
|||
handleViewChange: (view: ViewToShow) => void
|
||||
}) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const [showExpandChart, setShowExpandChart] = useState<boolean>(false)
|
||||
const [animationSettings] = useLocalStorageState(
|
||||
ANIMATION_SETTINGS_KEY,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
INITIAL_ANIMATION_SETTINGS,
|
||||
)
|
||||
const { width } = useViewport()
|
||||
const { performanceLoading: loading } = useAccountPerformanceData()
|
||||
|
|
|
@ -48,7 +48,7 @@ export const getFee = (activity: any, mangoAccountAddress: string) => {
|
|||
const value = price * quantity
|
||||
fee = {
|
||||
value: formatFee(
|
||||
mangoAccountAddress === maker ? maker_fee * value : taker_fee * value
|
||||
mangoAccountAddress === maker ? maker_fee * value : taker_fee * value,
|
||||
),
|
||||
symbol: 'USDC',
|
||||
}
|
||||
|
@ -63,14 +63,14 @@ export const getFee = (activity: any, mangoAccountAddress: string) => {
|
|||
if (side === 'liqee') {
|
||||
fee = {
|
||||
value: formatNumericValue(
|
||||
Math.abs(liab_amount) - Math.abs(asset_amount * asset_price)
|
||||
Math.abs(liab_amount) - Math.abs(asset_amount * asset_price),
|
||||
),
|
||||
symbol: liab_symbol,
|
||||
}
|
||||
} else {
|
||||
fee = {
|
||||
value: formatNumericValue(
|
||||
Math.abs(asset_amount * asset_price) - Math.abs(liab_amount)
|
||||
Math.abs(asset_amount * asset_price) - Math.abs(liab_amount),
|
||||
),
|
||||
symbol: liab_symbol,
|
||||
}
|
||||
|
@ -81,14 +81,14 @@ export const getFee = (activity: any, mangoAccountAddress: string) => {
|
|||
if (base_transfer > 0) {
|
||||
fee = {
|
||||
value: formatNumericValue(
|
||||
Math.abs(base_transfer * price) - Math.abs(quote_transfer)
|
||||
Math.abs(base_transfer * price) - Math.abs(quote_transfer),
|
||||
),
|
||||
symbol: 'USDC',
|
||||
}
|
||||
} else {
|
||||
fee = {
|
||||
value: formatNumericValue(
|
||||
Math.abs(quote_transfer) - Math.abs(base_transfer * price)
|
||||
Math.abs(quote_transfer) - Math.abs(base_transfer * price),
|
||||
),
|
||||
symbol: 'USDC',
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ export const getFee = (activity: any, mangoAccountAddress: string) => {
|
|||
|
||||
export const getCreditAndDebit = (
|
||||
activity: any,
|
||||
mangoAccountAddress: string
|
||||
mangoAccountAddress: string,
|
||||
) => {
|
||||
const { activity_type } = activity
|
||||
let credit = { value: '0', symbol: '' }
|
||||
|
@ -270,7 +270,7 @@ const ActivityFeedTable = () => {
|
|||
const { connected } = useWallet()
|
||||
const [preferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
EXPLORERS[0]
|
||||
EXPLORERS[0],
|
||||
)
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
|
@ -285,7 +285,7 @@ const ActivityFeedTable = () => {
|
|||
actions.fetchActivityFeed(
|
||||
mangoAccountAddress,
|
||||
offset + PAGINATION_PAGE_LENGTH,
|
||||
queryParams
|
||||
queryParams,
|
||||
)
|
||||
}, [actions, offset, queryParams, mangoAccountAddress])
|
||||
|
||||
|
@ -376,7 +376,7 @@ const ActivityFeedTable = () => {
|
|||
<div className="flex items-center justify-end">
|
||||
<Tooltip
|
||||
content={`View on ${t(
|
||||
`settings:${preferredExplorer.name}`
|
||||
`settings:${preferredExplorer.name}`,
|
||||
)}`}
|
||||
placement="top-end"
|
||||
>
|
||||
|
@ -515,7 +515,7 @@ const MobileActivityFeedItem = ({
|
|||
const { t } = useTranslation(['common', 'activity'])
|
||||
const [preferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
EXPLORERS[0]
|
||||
EXPLORERS[0],
|
||||
)
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const { activity_type, block_datetime } = activity
|
||||
|
|
|
@ -50,7 +50,7 @@ const ActivityFilters = () => {
|
|||
const actions = mangoStore((s) => s.actions)
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const [advancedFilters, setAdvancedFilters] = useState<AdvancedFilters>(
|
||||
DEFAULT_ADVANCED_FILTERS
|
||||
DEFAULT_ADVANCED_FILTERS,
|
||||
)
|
||||
const [params, setParams] = useState<string[]>([])
|
||||
const { t } = useTranslation(['common', 'activity'])
|
||||
|
@ -64,7 +64,7 @@ const ActivityFilters = () => {
|
|||
if (entry[1].length) {
|
||||
// ETH should be renamed to ETH (Portal) in the database
|
||||
const alignSymbolsToBackend = entry[1].map((e: string) =>
|
||||
e === 'ETH (Portal)' ? 'ETH' : e
|
||||
e === 'ETH (Portal)' ? 'ETH' : e,
|
||||
)
|
||||
advancedParams =
|
||||
advancedParams + `&${entry[0]}=${alignSymbolsToBackend}`
|
||||
|
|
|
@ -2,7 +2,6 @@ import { toUiDecimalsForQuote } from '@blockworks-foundation/mango-v4'
|
|||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useMemo } from 'react'
|
||||
import { Cell, Pie, PieChart } from 'recharts'
|
||||
import { COLORS } from 'styles/colors'
|
||||
|
@ -11,15 +10,16 @@ import FlipNumbers from 'react-flip-numbers'
|
|||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { ANIMATION_SETTINGS_KEY } from 'utils/constants'
|
||||
import { INITIAL_ANIMATION_SETTINGS } from '@components/settings/AnimationSettings'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
const AssetsLiabilities = ({ isMobile }: { isMobile: boolean }) => {
|
||||
const { t } = useTranslation('account')
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const [animationSettings] = useLocalStorageState(
|
||||
ANIMATION_SETTINGS_KEY,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
INITIAL_ANIMATION_SETTINGS,
|
||||
)
|
||||
|
||||
const [assetsValue, assetsRatio, liabsValue, liabsRatio] = useMemo(() => {
|
||||
|
|
|
@ -54,16 +54,16 @@ const CreateAccountForm = ({
|
|||
group,
|
||||
newAccountNum,
|
||||
name || `Account ${newAccountNum + 1}`,
|
||||
16 // tokenCount
|
||||
16, // tokenCount
|
||||
)
|
||||
if (tx) {
|
||||
const pk = wallet.adapter.publicKey
|
||||
const mangoAccounts = await client.getMangoAccountsForOwner(group, pk!)
|
||||
const reloadedMangoAccounts = await Promise.all(
|
||||
mangoAccounts.map((ma) => ma.reloadSerum3OpenOrders(client))
|
||||
mangoAccounts.map((ma) => ma.reloadSerum3OpenOrders(client)),
|
||||
)
|
||||
const newAccount = mangoAccounts.find(
|
||||
(acc) => acc.accountNum === newAccountNum
|
||||
(acc) => acc.accountNum === newAccountNum,
|
||||
)
|
||||
if (newAccount) {
|
||||
await newAccount.reloadSerum3OpenOrders(client)
|
||||
|
|
|
@ -21,7 +21,6 @@ import {
|
|||
ReferenceLine,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { COLORS } from 'styles/colors'
|
||||
import { formatDateAxis } from '@components/shared/DetailedAreaOrBarChart'
|
||||
import { formatYAxis } from 'utils/formatting'
|
||||
|
@ -32,11 +31,12 @@ import { ArrowLeftIcon, NoSymbolIcon } from '@heroicons/react/20/solid'
|
|||
import { FadeInFadeOut } from '@components/shared/Transitions'
|
||||
import ContentBox from '@components/shared/ContentBox'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
const fetchHourlyFunding = async (mangoAccountPk: string) => {
|
||||
try {
|
||||
const data = await fetch(
|
||||
`${MANGO_DATA_API_URL}/stats/funding-account-hourly?mango-account=${mangoAccountPk}`
|
||||
`${MANGO_DATA_API_URL}/stats/funding-account-hourly?mango-account=${mangoAccountPk}`,
|
||||
)
|
||||
const res = await data.json()
|
||||
if (res) {
|
||||
|
@ -65,7 +65,7 @@ const FundingChart = ({ hideChart }: { hideChart: () => void }) => {
|
|||
const { t } = useTranslation('common')
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const [daysToShow, setDaysToShow] = useState('30')
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const {
|
||||
data: fundingData,
|
||||
isLoading: loadingFunding,
|
||||
|
@ -80,7 +80,7 @@ const FundingChart = ({ hideChart }: { hideChart: () => void }) => {
|
|||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
enabled: !!mangoAccountAddress,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -100,7 +100,7 @@ const FundingChart = ({ hideChart }: { hideChart: () => void }) => {
|
|||
}
|
||||
const data = rawData.reduce((a: HourlyFundingChartData[], c) => {
|
||||
const found: HourlyFundingChartData | undefined = a.find(
|
||||
(item) => item['time'] === c.time
|
||||
(item) => item['time'] === c.time,
|
||||
)
|
||||
const marketKey = Object.keys(c)[0]
|
||||
const marketFunding = Object.values(c)[0]
|
||||
|
@ -123,7 +123,7 @@ const FundingChart = ({ hideChart }: { hideChart: () => void }) => {
|
|||
if (active && payload && payload.length) {
|
||||
const load = payload[0].payload
|
||||
const data: [string, any][] = Object.entries(load).filter(
|
||||
(p) => p[0] !== 'time' && p[0] !== 'total'
|
||||
(p) => p[0] !== 'time' && p[0] !== 'total',
|
||||
)
|
||||
return (
|
||||
<div className="rounded-md bg-th-bkg-2 p-4">
|
||||
|
|
|
@ -22,10 +22,10 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => {
|
|||
const { group } = useMangoGroup()
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const [initActiveIndex, setInitActiveIndex] = useState<number | undefined>(
|
||||
undefined
|
||||
undefined,
|
||||
)
|
||||
const [maintActiveIndex, setMaintActiveIndex] = useState<number | undefined>(
|
||||
undefined
|
||||
undefined,
|
||||
)
|
||||
const { initContributions, maintContributions } = useHealthContributions()
|
||||
|
||||
|
@ -37,7 +37,7 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => {
|
|||
if (item.asset === 'USDC') {
|
||||
const hasPerp =
|
||||
!!item.contributionDetails?.perpMarketContributions.find(
|
||||
(perp: PerpMarketContribution) => Math.abs(perp.contributionUi) > 0
|
||||
(perp: PerpMarketContribution) => Math.abs(perp.contributionUi) > 0,
|
||||
)
|
||||
initHealthContributions.push({
|
||||
...item,
|
||||
|
@ -73,7 +73,7 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => {
|
|||
if (item.asset === 'USDC') {
|
||||
const hasPerp =
|
||||
!!item.contributionDetails?.perpMarketContributions.find(
|
||||
(perp: PerpMarketContribution) => Math.abs(perp.contributionUi) > 0
|
||||
(perp: PerpMarketContribution) => Math.abs(perp.contributionUi) > 0,
|
||||
)
|
||||
maintHealthContributions.push({
|
||||
...item,
|
||||
|
@ -111,7 +111,7 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => {
|
|||
const splitData = initHealthContributions.reduce(
|
||||
(
|
||||
acc: { market: HealthContribution[]; token: HealthContribution[] },
|
||||
obj: HealthContribution
|
||||
obj: HealthContribution,
|
||||
) => {
|
||||
const isPerp = obj.asset.includes('PERP')
|
||||
const isSpotMarket = obj.asset.includes('/')
|
||||
|
@ -123,7 +123,7 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => {
|
|||
}
|
||||
return acc
|
||||
},
|
||||
{ market: [], token: [] }
|
||||
{ market: [], token: [] },
|
||||
)
|
||||
return [splitData.market, splitData.token]
|
||||
}, [initHealthContributions])
|
||||
|
@ -133,7 +133,7 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => {
|
|||
const splitData = maintHealthContributions.reduce(
|
||||
(
|
||||
acc: { market: HealthContribution[]; token: HealthContribution[] },
|
||||
obj: HealthContribution
|
||||
obj: HealthContribution,
|
||||
) => {
|
||||
const isPerp = obj.asset.includes('PERP')
|
||||
const isSpotMarket = obj.asset.includes('/')
|
||||
|
@ -145,7 +145,7 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => {
|
|||
}
|
||||
return acc
|
||||
},
|
||||
{ market: [], token: [] }
|
||||
{ market: [], token: [] },
|
||||
)
|
||||
const markets = splitData.market.filter((d) => d.contribution > 0)
|
||||
const tokens = splitData.token
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { useTranslation } from 'next-i18next'
|
||||
import { useTheme } from 'next-themes'
|
||||
import {
|
||||
Cell,
|
||||
Pie,
|
||||
|
@ -14,6 +13,7 @@ import { formatCurrencyValue } from 'utils/numbers'
|
|||
import { useViewport } from 'hooks/useViewport'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
import { HealthContribution } from 'types'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
const HealthContributionsChart = ({
|
||||
data,
|
||||
|
@ -25,7 +25,7 @@ const HealthContributionsChart = ({
|
|||
setActiveIndex: (i: number | undefined) => void
|
||||
}) => {
|
||||
const { t } = useTranslation(['common', 'account'])
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.sm : false
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ const HistoryTabs = () => {
|
|||
paid: `${formatNumericValue(swap_in_amount, inDecimals)} ${inSymbol}`,
|
||||
received: `${formatNumericValue(
|
||||
swap_out_amount,
|
||||
outDecimals
|
||||
outDecimals,
|
||||
)} ${outSymbol}`,
|
||||
value: formatCurrencyValue(swap_out_price_usd * swap_out_amount),
|
||||
borrow: `${borrowAmount} ${inSymbol}`,
|
||||
|
@ -135,7 +135,7 @@ const HistoryTabs = () => {
|
|||
let market
|
||||
if ('market' in trade) {
|
||||
market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(trade.market)
|
||||
new PublicKey(trade.market),
|
||||
)
|
||||
} else if ('perp_market' in trade) {
|
||||
market = group.getPerpMarketByMarketIndex(trade.market_index)
|
||||
|
|
|
@ -22,7 +22,7 @@ const LiquidationDetails = ({
|
|||
const { t } = useTranslation(['common', 'activity', 'settings'])
|
||||
const [preferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
EXPLORERS[0]
|
||||
EXPLORERS[0],
|
||||
)
|
||||
|
||||
const getAssetLiquidatedReturned = (details: SpotOrPerpLiquidationItem) => {
|
||||
|
@ -209,7 +209,7 @@ const LiquidationDetails = ({
|
|||
>
|
||||
<span className="mr-1.5">
|
||||
{abbreviateAddress(
|
||||
new PublicKey(activity.activity_details.counterparty)
|
||||
new PublicKey(activity.activity_details.counterparty),
|
||||
)}
|
||||
</span>
|
||||
<ArrowTopRightOnSquareIcon className="h-3 w-3" />
|
||||
|
|
|
@ -38,13 +38,13 @@ const MangoAccountSummary = () => {
|
|||
const [accountPnl, accountValue, freeCollateral, health] = useMemo(() => {
|
||||
if (!group || !mangoAccount) return [0, 0, 0, 0]
|
||||
const accountPnl = toUiDecimalsForQuote(
|
||||
mangoAccount.getPnl(group).toNumber()
|
||||
mangoAccount.getPnl(group).toNumber(),
|
||||
)
|
||||
const accountValue = toUiDecimalsForQuote(
|
||||
mangoAccount.getEquity(group).toNumber()
|
||||
mangoAccount.getEquity(group).toNumber(),
|
||||
)
|
||||
const freeCollateral = toUiDecimalsForQuote(
|
||||
mangoAccount.getCollateralValue(group).toNumber()
|
||||
mangoAccount.getCollateralValue(group).toNumber(),
|
||||
)
|
||||
const health = mangoAccount.getHealthRatioUi(group, HealthType.maint)
|
||||
return [accountPnl, accountValue, freeCollateral, health]
|
||||
|
@ -53,7 +53,7 @@ const MangoAccountSummary = () => {
|
|||
const leverage = useMemo(() => {
|
||||
if (!group || !mangoAccount) return 0
|
||||
const assetsValue = toUiDecimalsForQuote(
|
||||
mangoAccount.getAssetsValue(group).toNumber()
|
||||
mangoAccount.getAssetsValue(group).toNumber(),
|
||||
)
|
||||
|
||||
if (isNaN(assetsValue / accountValue)) {
|
||||
|
|
|
@ -63,7 +63,7 @@ const MarketsHealthTable = ({
|
|||
const { asset, contribution, isAsset } = cont
|
||||
const market = group.getSerum3MarketByName(asset)
|
||||
const bank = group.banksMapByTokenIndex.get(
|
||||
market.baseTokenIndex
|
||||
market.baseTokenIndex,
|
||||
)?.[0]
|
||||
|
||||
let initAssetWeight = 0
|
||||
|
@ -155,7 +155,7 @@ const MarketsHealthTable = ({
|
|||
const { asset, contribution, isAsset } = cont
|
||||
const market = group.getSerum3MarketByName(asset)
|
||||
const bank = group.banksMapByTokenIndex.get(
|
||||
market.baseTokenIndex
|
||||
market.baseTokenIndex,
|
||||
)?.[0]
|
||||
|
||||
let initAssetWeight = 0
|
||||
|
|
|
@ -19,7 +19,7 @@ const PerpTradeDetails = ({ activity }: { activity: PerpTradeActivity }) => {
|
|||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const [preferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
EXPLORERS[0]
|
||||
EXPLORERS[0],
|
||||
)
|
||||
const {
|
||||
maker,
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
ReferenceLine,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { COLORS } from 'styles/colors'
|
||||
import { formatDateAxis } from '@components/shared/DetailedAreaOrBarChart'
|
||||
import { formatYAxis } from 'utils/formatting'
|
||||
|
@ -27,6 +26,7 @@ import SheenLoader from '@components/shared/SheenLoader'
|
|||
import useAccountHourlyVolumeStats from 'hooks/useAccountHourlyVolumeStats'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import { DAILY_MILLISECONDS } from 'utils/constants'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
const VolumeChart = ({ hideChart }: { hideChart: () => void }) => {
|
||||
const { t } = useTranslation(['account', 'common', 'stats'])
|
||||
|
@ -34,7 +34,7 @@ const VolumeChart = ({ hideChart }: { hideChart: () => void }) => {
|
|||
const { hourlyVolumeData: chartData, loadingHourlyVolume: loading } =
|
||||
useAccountHourlyVolumeStats()
|
||||
const [daysToShow, setDaysToShow] = useState('30')
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
|
||||
const CustomTooltip = ({
|
||||
active,
|
||||
|
|
|
@ -44,7 +44,7 @@ const BorrowPage = () => {
|
|||
}
|
||||
const [animationSettings] = useLocalStorageState(
|
||||
ANIMATION_SETTINGS_KEY,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
INITIAL_ANIMATION_SETTINGS,
|
||||
)
|
||||
|
||||
const filteredBanks = useMemo(() => {
|
||||
|
@ -58,7 +58,7 @@ const BorrowPage = () => {
|
|||
if (!filteredBanks.length) return 0
|
||||
return filteredBanks.reduce(
|
||||
(a, c) => a + Math.abs(c.borrowedAmount) * c.bank.uiPrice,
|
||||
0
|
||||
0,
|
||||
)
|
||||
}, [filteredBanks])
|
||||
|
||||
|
@ -75,7 +75,7 @@ const BorrowPage = () => {
|
|||
group,
|
||||
usdcBank,
|
||||
mangoAccount,
|
||||
true
|
||||
true,
|
||||
).toNumber()
|
||||
|
||||
if (borrowValue) {
|
||||
|
|
|
@ -26,7 +26,7 @@ import TokenLogo from '@components/shared/TokenLogo'
|
|||
|
||||
export const getAvailableToBorrow = (
|
||||
bankWithBal: BankWithBalance,
|
||||
group: Group
|
||||
group: Group,
|
||||
) => {
|
||||
const { balance, bank, maxBorrow } = bankWithBal
|
||||
const { mint, mintDecimals, minVaultToDepositsRatio } = bankWithBal.bank
|
||||
|
@ -40,7 +40,7 @@ export const getAvailableToBorrow = (
|
|||
|
||||
const available = Decimal.min(
|
||||
availableAccountBorrow.toFixed(bank.mintDecimals),
|
||||
Decimal.max(0, availableVaultBalance.toFixed(mintDecimals))
|
||||
Decimal.max(0, availableVaultBalance.toFixed(mintDecimals)),
|
||||
)
|
||||
return available
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
|||
setSelectedToken(token)
|
||||
action === 'borrow' ? setShowBorrowModal(true) : setShowRepayModal(true)
|
||||
},
|
||||
[]
|
||||
[],
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
|
@ -17,7 +17,7 @@ const ChatForm = ({
|
|||
const validateMessageText = useCallback(async (text: string) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://www.purgomalum.com/service/json?text=${text}&fill_char=*`
|
||||
`https://www.purgomalum.com/service/json?text=${text}&fill_char=*`,
|
||||
)
|
||||
const profanityCheck = await response.json()
|
||||
|
||||
|
@ -45,7 +45,7 @@ const ChatForm = ({
|
|||
setLatestMessages(newMessages)
|
||||
setMessageText('')
|
||||
},
|
||||
[messageText, messages, publicKey, validateMessageText, setLatestMessages]
|
||||
[messageText, messages, publicKey, validateMessageText, setLatestMessages],
|
||||
)
|
||||
|
||||
const callbackRef = useCallback((inputElement: HTMLInputElement) => {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
import { ChangeEvent, useEffect, useRef, useState } from 'react'
|
||||
|
||||
const Slider = ({
|
||||
amount,
|
||||
max,
|
||||
min,
|
||||
onChange,
|
||||
step,
|
||||
}: {
|
||||
amount: number
|
||||
max?: string
|
||||
min?: string
|
||||
onChange: (x: string) => void
|
||||
step: number
|
||||
}) => {
|
||||
const [value, setValue] = useState(0)
|
||||
const inputEl = useRef<HTMLInputElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (inputEl.current) {
|
||||
const target = inputEl.current
|
||||
const min = parseFloat(target.min)
|
||||
const max = parseFloat(target.max)
|
||||
|
||||
target.style.backgroundSize =
|
||||
max - min === 0
|
||||
? '0% 100%'
|
||||
: ((value - min) * 100) / (max - min) + '% 100%'
|
||||
}
|
||||
}, [value])
|
||||
|
||||
useEffect(() => {
|
||||
if (amount) {
|
||||
setValue(amount)
|
||||
} else {
|
||||
setValue(0)
|
||||
}
|
||||
}, [amount])
|
||||
|
||||
const handleSliderChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
const target = e.target
|
||||
const min = parseFloat(target.min)
|
||||
const max = parseFloat(target.max)
|
||||
const val = parseFloat(target.value)
|
||||
|
||||
target.style.backgroundSize = ((val - min) * 100) / (max - min) + '% 100%'
|
||||
|
||||
onChange(e.target.value)
|
||||
setValue(parseFloat(e.target.value))
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<label htmlFor="default-range" className="block text-sm"></label>
|
||||
<input
|
||||
ref={inputEl}
|
||||
id="default-range"
|
||||
type="range"
|
||||
min={min || '0'}
|
||||
max={max || '100'}
|
||||
step={step}
|
||||
className="w-full focus:outline-none"
|
||||
onChange={handleSliderChange}
|
||||
value={value}
|
||||
></input>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Slider
|
|
@ -6,6 +6,7 @@ interface SwitchProps {
|
|||
onChange: (x: boolean) => void
|
||||
children?: ReactNode
|
||||
disabled?: boolean
|
||||
small?: boolean
|
||||
}
|
||||
|
||||
const Switch: FunctionComponent<SwitchProps> = ({
|
||||
|
@ -14,6 +15,7 @@ const Switch: FunctionComponent<SwitchProps> = ({
|
|||
children,
|
||||
onChange,
|
||||
disabled,
|
||||
small,
|
||||
}) => {
|
||||
const handleClick = () => {
|
||||
onChange(!checked)
|
||||
|
@ -26,7 +28,9 @@ const Switch: FunctionComponent<SwitchProps> = ({
|
|||
type="button"
|
||||
className={`${
|
||||
checked ? 'bg-th-success' : 'bg-th-bkg-4'
|
||||
} relative inline-flex h-5 w-10 flex-shrink-0 cursor-pointer rounded-full
|
||||
} relative inline-flex ${
|
||||
small ? 'h-4 w-8' : 'h-5 w-10'
|
||||
} flex-shrink-0 cursor-pointer rounded-full
|
||||
border-2 border-transparent transition-colors duration-200 ease-in-out focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-th-fgd-4 ${
|
||||
disabled ? 'opacity-60' : ''
|
||||
}`}
|
||||
|
@ -39,8 +43,14 @@ const Switch: FunctionComponent<SwitchProps> = ({
|
|||
<span
|
||||
aria-hidden="true"
|
||||
className={`${
|
||||
checked ? 'translate-x-5' : 'translate-x-0'
|
||||
} pointer-events-none inline-block h-4 w-4 rounded-full
|
||||
checked
|
||||
? small
|
||||
? 'translate-x-4'
|
||||
: 'translate-x-5'
|
||||
: 'translate-x-0'
|
||||
} pointer-events-none inline-block ${
|
||||
small ? 'h-3 w-3' : 'h-4 w-4'
|
||||
} rounded-full
|
||||
bg-white shadow ring-0 transition duration-200 ease-in-out`}
|
||||
></span>
|
||||
</button>
|
||||
|
|
|
@ -17,7 +17,7 @@ const GovernanceDelegate = () => {
|
|||
const getCurrentVotingPower = GovernanceStore((s) => s.getCurrentVotingPower)
|
||||
|
||||
const [selectedDelegatePk, setSelectedDelegatePk] = useLocalStorageState(
|
||||
`${publicKey?.toBase58()}${GOVERNANCE_DELEGATE_KEY}`
|
||||
`${publicKey?.toBase58()}${GOVERNANCE_DELEGATE_KEY}`,
|
||||
)
|
||||
const currentDelegate = delegates
|
||||
.find((x) => x.pubkey.toBase58() === selectedDelegatePk)
|
||||
|
|
|
@ -57,7 +57,8 @@ const defaultFormValues: ListMarketForm = {
|
|||
}
|
||||
|
||||
const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
||||
const { connected, wallet, connect } = useWallet()
|
||||
//do not deconstruct wallet is used for anchor to sign
|
||||
const wallet = useWallet()
|
||||
const { t } = useTranslation(['governance', 'trade'])
|
||||
const { group } = useMangoGroup()
|
||||
const connection = mangoStore((s) => s.connection)
|
||||
|
@ -89,7 +90,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
const [baseTokens, quoteTokens] = useMemo(() => {
|
||||
if (!group) return [[], []]
|
||||
const allTokens = [...group.banksMapByName.keys()].sort((a, b) =>
|
||||
a.localeCompare(b)
|
||||
a.localeCompare(b),
|
||||
)
|
||||
return [
|
||||
allTokens.filter((t) => t !== quoteToken),
|
||||
|
@ -151,7 +152,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
}
|
||||
return invalidFields
|
||||
},
|
||||
[t]
|
||||
[t],
|
||||
)
|
||||
const handlePropose = useCallback(async () => {
|
||||
const invalidFields = isFormValid(advForm)
|
||||
|
@ -188,7 +189,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
advForm.proposalDescription,
|
||||
index,
|
||||
proposalTx,
|
||||
vsrClient!
|
||||
vsrClient!,
|
||||
)
|
||||
setProposalPk(proposalAddress.toBase58())
|
||||
setCurrentView(VIEWS.SUCCESS)
|
||||
|
@ -254,7 +255,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
baseBank.uiPrice,
|
||||
quoteBank.uiPrice,
|
||||
baseBank.mintDecimals,
|
||||
quoteBank.mintDecimals
|
||||
quoteBank.mintDecimals,
|
||||
)
|
||||
}
|
||||
return {
|
||||
|
@ -288,7 +289,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
{t('market-pair')}{' '}
|
||||
{baseToken && quoteToken
|
||||
? `- ${formatTokenSymbol(baseToken)}/${formatTokenSymbol(
|
||||
quoteToken
|
||||
quoteToken,
|
||||
)}`
|
||||
: null}
|
||||
</h2>
|
||||
|
@ -505,7 +506,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
handleSetAdvForm(
|
||||
'openBookMarketExternalPk',
|
||||
e.target.value
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -548,7 +549,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
handleSetAdvForm(
|
||||
'proposalDescription',
|
||||
e.target.value
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -577,7 +578,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
>
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
{connected ? (
|
||||
{wallet.connected ? (
|
||||
<Button
|
||||
onClick={handlePropose}
|
||||
disabled={proposing || !marketPk}
|
||||
|
@ -590,7 +591,7 @@ const ListMarket = ({ goBack }: { goBack: () => void }) => {
|
|||
)}
|
||||
</Button>
|
||||
) : (
|
||||
<Button onClick={connect} size="large">
|
||||
<Button onClick={wallet.connect} size="large">
|
||||
{t('connect-wallet')}
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
@ -85,7 +85,8 @@ const defaultTokenListFormValues: TokenListForm = {
|
|||
const TWENTY_K_USDC_BASE = '20000000000'
|
||||
|
||||
const ListToken = ({ goBack }: { goBack: () => void }) => {
|
||||
const { connect, publicKey, connected, wallet } = useWallet()
|
||||
//do not deconstruct wallet is used for anchor to sign
|
||||
const wallet = useWallet()
|
||||
const { jupiterTokens } = useJupiterMints()
|
||||
const connection = mangoStore((s) => s.connection)
|
||||
const client = mangoStore((s) => s.client)
|
||||
|
@ -127,7 +128,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
? governances[MANGO_DAO_WALLET_GOVERNANCE.toBase58()].account.config
|
||||
.minCommunityTokensToCreateProposal
|
||||
: new BN(0),
|
||||
[governances]
|
||||
[governances],
|
||||
) as BN
|
||||
const mintVoterWeightNumber = governances
|
||||
? fmtTokenAmount(minVoterWeight, MANGO_MINT_DECIMALS)
|
||||
|
@ -138,7 +139,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
baseTokenPrice,
|
||||
quoteBank.uiPrice,
|
||||
currentTokenInfo.decimals,
|
||||
quoteBank.mintDecimals
|
||||
quoteBank.mintDecimals,
|
||||
)
|
||||
}
|
||||
return {
|
||||
|
@ -189,7 +190,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
new BN(index).toArrayLike(Buffer, 'le', 2),
|
||||
new BN(bankNum).toArrayLike(Buffer, 'le', 4),
|
||||
],
|
||||
client.programId
|
||||
client.programId,
|
||||
)
|
||||
setAdvForm({
|
||||
...advForm,
|
||||
|
@ -209,14 +210,16 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
})
|
||||
setLoadingListingParams(false)
|
||||
},
|
||||
[advForm, client.programId, connection, group, mint, proposals]
|
||||
[advForm, client.programId, connection, group, mint, proposals],
|
||||
)
|
||||
|
||||
const handleGetRoutesWithFixedArgs = useCallback(
|
||||
(amount: number, tokenMint: PublicKey, mode: 'ExactIn' | 'ExactOut') => {
|
||||
const SLIPPAGE_BPS = 50
|
||||
const FEE = 0
|
||||
const walletForCheck = publicKey ? publicKey?.toBase58() : emptyPk
|
||||
const walletForCheck = wallet.publicKey
|
||||
? wallet.publicKey?.toBase58()
|
||||
: emptyPk
|
||||
|
||||
return handleGetRoutes(
|
||||
USDC_MINT,
|
||||
|
@ -226,10 +229,10 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
mode,
|
||||
FEE,
|
||||
walletForCheck,
|
||||
'JUPITER'
|
||||
'JUPITER',
|
||||
)
|
||||
},
|
||||
[publicKey]
|
||||
[wallet.publicKey],
|
||||
)
|
||||
|
||||
const handleLiqudityCheck = useCallback(
|
||||
|
@ -253,7 +256,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
(acc: { amount: string; priceImpactPct: number }[], val) => {
|
||||
if (val.swapMode === 'ExactIn') {
|
||||
const exactOutRoute = bestRoutesSwaps.find(
|
||||
(x) => x.amount === val.amount && x.swapMode === 'ExactOut'
|
||||
(x) => x.amount === val.amount && x.swapMode === 'ExactOut',
|
||||
)
|
||||
acc.push({
|
||||
amount: val.amount.toString(),
|
||||
|
@ -264,14 +267,14 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
}
|
||||
return acc
|
||||
},
|
||||
[]
|
||||
[],
|
||||
)
|
||||
|
||||
const midTierCheck = averageSwaps.find(
|
||||
(x) => x.amount === TWENTY_K_USDC_BASE
|
||||
(x) => x.amount === TWENTY_K_USDC_BASE,
|
||||
)
|
||||
const indexForTierFromSwaps = averageSwaps.findIndex(
|
||||
(x) => x?.priceImpactPct && x?.priceImpactPct * 100 < 1
|
||||
(x) => x?.priceImpactPct && x?.priceImpactPct * 100 < 1,
|
||||
)
|
||||
const tier =
|
||||
indexForTierFromSwaps > -1
|
||||
|
@ -282,8 +285,8 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
|
||||
handleGetPoolParams(
|
||||
swaps.find(
|
||||
(x) => x.bestRoute!.amount.toString() === TWENTY_K_USDC_BASE
|
||||
)!.routes
|
||||
(x) => x.bestRoute!.amount.toString() === TWENTY_K_USDC_BASE,
|
||||
)!.routes,
|
||||
)
|
||||
return tier
|
||||
} catch (e) {
|
||||
|
@ -294,7 +297,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
})
|
||||
}
|
||||
},
|
||||
[t, handleGetRoutesWithFixedArgs]
|
||||
[t, handleGetRoutesWithFixedArgs],
|
||||
)
|
||||
|
||||
const handleGetPoolParams = (routes: never[] | RouteInfo[]) => {
|
||||
|
@ -375,7 +378,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
}
|
||||
return invalidFields
|
||||
},
|
||||
[t]
|
||||
[t],
|
||||
)
|
||||
|
||||
const propose = useCallback(async () => {
|
||||
|
@ -383,8 +386,8 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
if (Object.keys(invalidFields).length) {
|
||||
return
|
||||
}
|
||||
if (!publicKey || !vsrClient || !connectionContext) return
|
||||
await getCurrentVotingPower(publicKey, vsrClient, connectionContext)
|
||||
if (!wallet.publicKey || !vsrClient || !connectionContext) return
|
||||
await getCurrentVotingPower(wallet.publicKey, vsrClient, connectionContext)
|
||||
|
||||
if (voter.voteWeight.cmp(minVoterWeight) === -1) {
|
||||
notify({
|
||||
|
@ -402,7 +405,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
group!.publicKey.toBuffer(),
|
||||
new PublicKey(advForm.mintPk).toBuffer(),
|
||||
],
|
||||
client.programId
|
||||
client.programId,
|
||||
)
|
||||
|
||||
const proposalTx = []
|
||||
|
@ -433,7 +436,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
Number(tierPreset.liquidationFee),
|
||||
Number(tierPreset.minVaultToDepositsRatio),
|
||||
new BN(tierPreset.netBorrowLimitWindowSizeTs),
|
||||
new BN(tierPreset.netBorrowLimitPerWindowQuote)
|
||||
new BN(tierPreset.netBorrowLimitPerWindowQuote),
|
||||
)
|
||||
.accounts({
|
||||
admin: MANGO_DAO_WALLET,
|
||||
|
@ -471,7 +474,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
false,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
null,
|
||||
)
|
||||
.accounts({
|
||||
oracle: new PublicKey(advForm.oraclePk),
|
||||
|
@ -489,7 +492,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
.instruction()
|
||||
proposalTx.push(editIx)
|
||||
} else {
|
||||
await client!.program.methods
|
||||
const trustlessIx = await client!.program.methods
|
||||
.tokenRegisterTrustless(Number(advForm.tokenIndex), advForm.name)
|
||||
.accounts({
|
||||
mint: new PublicKey(advForm.mintPk),
|
||||
|
@ -500,6 +503,8 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
group: group!.publicKey,
|
||||
})
|
||||
.instruction()
|
||||
|
||||
proposalTx.push(trustlessIx)
|
||||
}
|
||||
|
||||
const registerMarketix = await client!.program.methods
|
||||
|
@ -528,7 +533,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
advForm.proposalDescription,
|
||||
advForm.tokenIndex,
|
||||
proposalTx,
|
||||
vsrClient
|
||||
vsrClient,
|
||||
)
|
||||
setProposalPk(proposalAddress.toBase58())
|
||||
} catch (e) {
|
||||
|
@ -645,7 +650,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
<p>{t('mint')}</p>
|
||||
<p className="flex items-center">
|
||||
{abbreviateAddress(
|
||||
new PublicKey(currentTokenInfo?.address)
|
||||
new PublicKey(currentTokenInfo?.address),
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -736,7 +741,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
handleSetAdvForm(
|
||||
'openBookMarketExternalPk',
|
||||
e.target.value
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -798,7 +803,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
handleSetAdvForm(
|
||||
'openBookProgram',
|
||||
e.target.value
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -839,7 +844,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
handleSetAdvForm(
|
||||
'proposalTitle',
|
||||
e.target.value
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -863,7 +868,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
handleSetAdvForm(
|
||||
'proposalDescription',
|
||||
e.target.value
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -956,7 +961,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
<Button secondary onClick={cancel} size="large">
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
{connected ? (
|
||||
{wallet.connected ? (
|
||||
<Button
|
||||
className="flex w-full items-center justify-center sm:w-44"
|
||||
onClick={propose}
|
||||
|
@ -978,7 +983,7 @@ const ListToken = ({ goBack }: { goBack: () => void }) => {
|
|||
)}
|
||||
</Button>
|
||||
) : (
|
||||
<Button onClick={connect} size="large">
|
||||
<Button onClick={wallet.connect} size="large">
|
||||
{t('connect-wallet')}
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
@ -23,7 +23,7 @@ const OnBoarding = ({ minVotes }: { minVotes?: BN }) => {
|
|||
? new BN(
|
||||
governances[
|
||||
MANGO_DAO_WALLET_GOVERNANCE.toBase58()
|
||||
].account.config.minCommunityTokensToCreateProposal.toString()
|
||||
].account.config.minCommunityTokensToCreateProposal.toString(),
|
||||
)
|
||||
: new BN(0)
|
||||
const mintVoterWeightNumber = governances
|
||||
|
@ -50,7 +50,7 @@ const OnBoarding = ({ minVotes }: { minVotes?: BN }) => {
|
|||
</>
|
||||
}
|
||||
desc={`${t('on-boarding-deposit-info')} ${t(
|
||||
'on-boarding-description-1'
|
||||
'on-boarding-description-1',
|
||||
)}`}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -58,7 +58,7 @@ const ProposalCard = ({
|
|||
const [voteType, setVoteType] = useState<VoteKind | undefined>(undefined)
|
||||
|
||||
const [voteRecordAddress, setVoteRecordAddress] = useState<PublicKey | null>(
|
||||
null
|
||||
null,
|
||||
)
|
||||
const [isVoteCast, setIsVoteCast] = useState(false)
|
||||
const [description, setDescription] = useState('')
|
||||
|
@ -73,7 +73,7 @@ const ProposalCard = ({
|
|||
setProcessedVoteType(
|
||||
voteType === VoteKind.Approve
|
||||
? PROCESSED_VOTE_TYPE.APPROVE
|
||||
: PROCESSED_VOTE_TYPE.DENY
|
||||
: PROCESSED_VOTE_TYPE.DENY,
|
||||
)
|
||||
try {
|
||||
await castVote(
|
||||
|
@ -83,7 +83,7 @@ const ProposalCard = ({
|
|||
voter.tokenOwnerRecord!,
|
||||
voteType,
|
||||
vsrClient!,
|
||||
client
|
||||
client,
|
||||
)
|
||||
await updateProposals(proposal.pubkey)
|
||||
} catch (e) {
|
||||
|
@ -106,7 +106,7 @@ const ProposalCard = ({
|
|||
proposal,
|
||||
voter.tokenOwnerRecord!,
|
||||
client,
|
||||
voteRecordAddress!
|
||||
voteRecordAddress!,
|
||||
)
|
||||
await updateProposals(proposal.pubkey)
|
||||
} catch (e) {
|
||||
|
@ -140,14 +140,14 @@ const ProposalCard = ({
|
|||
const voteRecordAddress = await getVoteRecordAddress(
|
||||
MANGO_GOVERNANCE_PROGRAM,
|
||||
proposal.pubkey,
|
||||
voter.tokenOwnerRecord!.pubkey!
|
||||
voter.tokenOwnerRecord!.pubkey!,
|
||||
)
|
||||
setVoteRecordAddress(voteRecordAddress)
|
||||
try {
|
||||
const governanceAccount = await getGovernanceAccount(
|
||||
connection,
|
||||
voteRecordAddress,
|
||||
VoteRecord
|
||||
VoteRecord,
|
||||
)
|
||||
setIsVoteCast(true)
|
||||
setVoteType(governanceAccount.account.vote?.voteType)
|
||||
|
|
|
@ -89,7 +89,7 @@ const Vote = () => {
|
|||
proposal={x}
|
||||
mangoMint={mangoMint}
|
||||
></ProposalCard>
|
||||
)
|
||||
),
|
||||
)
|
||||
) : (
|
||||
<div className="flex h-56 items-center justify-center rounded-lg border border-th-bkg-3 p-6">
|
||||
|
|
|
@ -26,7 +26,7 @@ const QuorumProgress = ({ governance, proposal, communityMint }: Props) => {
|
|||
realm &&
|
||||
getMintMaxVoteWeight(
|
||||
communityMint,
|
||||
realm.account.config.communityMintMaxVoteWeightSource
|
||||
realm.account.config.communityMintMaxVoteWeightSource,
|
||||
)
|
||||
|
||||
const minimumYesVotes =
|
||||
|
@ -35,7 +35,7 @@ const QuorumProgress = ({ governance, proposal, communityMint }: Props) => {
|
|||
|
||||
const yesVoteCount = fmtTokenAmount(
|
||||
new BN(proposal.account.getYesVoteCount().toString()),
|
||||
communityMint.decimals
|
||||
communityMint.decimals,
|
||||
)
|
||||
|
||||
const rawYesVotesRequired = minimumYesVotes - yesVoteCount
|
||||
|
|
|
@ -15,11 +15,11 @@ const VoteResults = ({ proposal, communityMint }: VoteResultsProps) => {
|
|||
|
||||
const yesVoteCount = fmtTokenAmount(
|
||||
proposal.getYesVoteCount() as BN,
|
||||
communityMint.decimals
|
||||
communityMint.decimals,
|
||||
)
|
||||
const noVoteCount = fmtTokenAmount(
|
||||
proposal.getNoVoteCount() as BN,
|
||||
communityMint.decimals
|
||||
communityMint.decimals,
|
||||
)
|
||||
const totalVoteCount = yesVoteCount + noVoteCount
|
||||
const getRelativeVoteCount = (voteCount: number) =>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useTheme } from 'next-themes'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
import { COLORS } from 'styles/colors'
|
||||
|
||||
const OrderbookIcon = ({
|
||||
|
@ -8,7 +8,7 @@ const OrderbookIcon = ({
|
|||
side: 'buy' | 'sell'
|
||||
className?: string
|
||||
}) => {
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const buyColor = side === 'buy' ? COLORS.UP[theme] : COLORS.FGD4[theme]
|
||||
const sellColor = side === 'sell' ? COLORS.DOWN[theme] : COLORS.FGD4[theme]
|
||||
return (
|
||||
|
|
|
@ -23,7 +23,7 @@ export interface LeaderboardRes {
|
|||
type DaysToShow = '1DAY' | '1WEEK' | 'ALLTIME'
|
||||
|
||||
const isLeaderboard = (
|
||||
response: null | EmptyObject | LeaderboardRes[]
|
||||
response: null | EmptyObject | LeaderboardRes[],
|
||||
): response is LeaderboardRes[] => {
|
||||
if (response && Array.isArray(response)) {
|
||||
return true
|
||||
|
@ -33,10 +33,10 @@ const isLeaderboard = (
|
|||
|
||||
const fetchLeaderboard = async (
|
||||
daysToShow: DaysToShow,
|
||||
offset = 0
|
||||
offset = 0,
|
||||
): Promise<Array<LeaderboardRes>> => {
|
||||
const data = await fetch(
|
||||
`${MANGO_DATA_API_URL}/leaderboard-pnl?over_period=${daysToShow}&offset=${offset}`
|
||||
`${MANGO_DATA_API_URL}/leaderboard-pnl?over_period=${daysToShow}&offset=${offset}`,
|
||||
)
|
||||
const parsedData: null | EmptyObject | LeaderboardRes[] = await data.json()
|
||||
|
||||
|
@ -63,7 +63,7 @@ const LeaderboardPage = () => {
|
|||
refetchOnWindowFocus: false,
|
||||
keepPreviousData: true,
|
||||
getNextPageParam: (_lastPage, pages) => pages.length * 20,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const leaderboardData = useMemo(() => {
|
||||
|
|
|
@ -27,11 +27,11 @@ const CloseAccountModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
const mangoAccount = mangoStore((s) => s.mangoAccount)
|
||||
const perpPositions = mangoStore((s) => s.mangoAccount.perpPositions)
|
||||
const openPerpPositions = Object.values(perpPositions).filter((p) =>
|
||||
p.basePositionLots.toNumber()
|
||||
p.basePositionLots.toNumber(),
|
||||
)
|
||||
const group = mangoStore.getState().group
|
||||
const unsettledBalances = Object.values(mangoAccount.spotBalances).filter(
|
||||
(x) => x.unsettled && x.unsettled > 0
|
||||
(x) => x.unsettled && x.unsettled > 0,
|
||||
)
|
||||
const unsettledPerpPositions = useUnsettledPerpPositions()
|
||||
const [hasBorrows, setHasBorrows] = useState(false)
|
||||
|
@ -49,7 +49,7 @@ const CloseAccountModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
const tx = await client.emptyAndCloseMangoAccount(group, mangoAccount)
|
||||
if (tx) {
|
||||
const newMangoAccounts = mangoAccounts.filter(
|
||||
(ma) => !ma.publicKey.equals(mangoAccount.publicKey)
|
||||
(ma) => !ma.publicKey.equals(mangoAccount.publicKey),
|
||||
)
|
||||
let newCurrentAccount: MangoAccount
|
||||
if (newMangoAccounts[0]) {
|
||||
|
@ -99,7 +99,7 @@ const CloseAccountModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
.filter((token: TokenPosition) =>
|
||||
token
|
||||
.balance(group.getFirstBankByTokenIndex(token.tokenIndex))
|
||||
.isNeg()
|
||||
.isNeg(),
|
||||
).length
|
||||
) {
|
||||
setHasBorrows(true)
|
||||
|
@ -137,8 +137,8 @@ const CloseAccountModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
mangoAccount && group
|
||||
? formatCurrencyValue(
|
||||
toUiDecimalsForQuote(
|
||||
mangoAccount!.current!.getEquity(group)
|
||||
)
|
||||
mangoAccount!.current!.getEquity(group),
|
||||
),
|
||||
)
|
||||
: 0,
|
||||
})}
|
||||
|
|
|
@ -157,11 +157,11 @@ const CreateOpenbookMarketModal = ({
|
|||
const getMinLamportsToCreateMarket = async () => {
|
||||
const accountsSpace = 84522 + MARKET_STATE_LAYOUT_V2.span
|
||||
const minLamports = await connection.getMinimumBalanceForRentExemption(
|
||||
accountsSpace
|
||||
accountsSpace,
|
||||
)
|
||||
setSolNeededToCreateMarket(
|
||||
Math.round((minLamports / LAMPORTS_PER_SOL + Number.EPSILON) * 100) /
|
||||
100
|
||||
100,
|
||||
)
|
||||
}
|
||||
getMinLamportsToCreateMarket()
|
||||
|
|
|
@ -135,7 +135,7 @@ const CreateSwitchboardOracleModal = ({
|
|||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
}),
|
||||
).finish(),
|
||||
},
|
||||
{
|
||||
|
@ -201,7 +201,7 @@ const CreateSwitchboardOracleModal = ({
|
|||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
}),
|
||||
).finish(),
|
||||
},
|
||||
],
|
||||
|
|
|
@ -22,7 +22,7 @@ const DelegateModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
const [delegateAddress, setDelegateAddress] = useState(
|
||||
mangoAccount?.delegate?.toString() !== DEFAULT_DELEGATE
|
||||
? mangoAccount!.delegate.toString()
|
||||
: ''
|
||||
: '',
|
||||
)
|
||||
|
||||
const handleDelegateAccount = async (address: string) => {
|
||||
|
@ -44,7 +44,7 @@ const DelegateModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
group,
|
||||
mangoAccount,
|
||||
undefined,
|
||||
delegateAddress ? new PublicKey(address) : undefined
|
||||
delegateAddress ? new PublicKey(address) : undefined,
|
||||
)
|
||||
onClose()
|
||||
notify({
|
||||
|
@ -82,7 +82,7 @@ const DelegateModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
<InlineNotification
|
||||
type="info"
|
||||
desc={`Account is delegated to ${abbreviateAddress(
|
||||
mangoAccount.delegate
|
||||
mangoAccount.delegate,
|
||||
)}`}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -117,11 +117,11 @@ const MangoAccountsListModal = ({
|
|||
acc = mangoAccount
|
||||
}
|
||||
const accountValue = toUiDecimalsForQuote(
|
||||
Number(acc.getEquity(group!))
|
||||
Number(acc.getEquity(group!)),
|
||||
).toFixed(2)
|
||||
const maintHealth = acc.getHealthRatioUi(
|
||||
group!,
|
||||
HealthType.maint
|
||||
HealthType.maint,
|
||||
)
|
||||
return (
|
||||
<div
|
||||
|
@ -207,7 +207,7 @@ const MangoAccountsListModal = ({
|
|||
acc,
|
||||
t('copy-address-success', {
|
||||
pk: abbreviateAddress(acc.publicKey),
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
hideBg
|
||||
|
|
|
@ -51,12 +51,12 @@ const ModifyTvOrderModal = ({
|
|||
const { t } = useTranslation(['common', 'trade'])
|
||||
const [modifiedOrderPrice, setModifiedOrderPrice] = useState(price)
|
||||
const [modifiedOrderSize, setModifiedOrderSize] = useState(
|
||||
order.size.toString()
|
||||
order.size.toString(),
|
||||
)
|
||||
const { baseSymbol, selectedMarket, serumOrPerpMarket } = useSelectedMarket()
|
||||
const [savedCheckboxSettings] = useLocalStorageState(
|
||||
TRADE_CHECKBOXES_KEY,
|
||||
DEFAULT_CHECKBOX_SETTINGS
|
||||
DEFAULT_CHECKBOX_SETTINGS,
|
||||
)
|
||||
|
||||
const tickDecimals = useMemo(() => {
|
||||
|
@ -99,13 +99,13 @@ const ModifyTvOrderModal = ({
|
|||
Date.now(),
|
||||
PerpOrderType.limit,
|
||||
undefined,
|
||||
undefined
|
||||
undefined,
|
||||
)
|
||||
} else {
|
||||
const marketPk = findSerum3MarketPkInOpenOrders(o)
|
||||
if (!marketPk) return
|
||||
const market = group.getSerum3MarketByExternalMarket(
|
||||
new PublicKey(marketPk)
|
||||
new PublicKey(marketPk),
|
||||
)
|
||||
tx = await client.modifySerum3Order(
|
||||
group,
|
||||
|
@ -118,7 +118,7 @@ const ModifyTvOrderModal = ({
|
|||
Serum3SelfTradeBehavior.decrementTake,
|
||||
Serum3OrderType.limit,
|
||||
Date.now(),
|
||||
10
|
||||
10,
|
||||
)
|
||||
}
|
||||
actions.fetchOpenOrders()
|
||||
|
@ -139,7 +139,7 @@ const ModifyTvOrderModal = ({
|
|||
})
|
||||
}
|
||||
},
|
||||
[findSerum3MarketPkInOpenOrders, modifiedOrderPrice, modifiedOrderSize]
|
||||
[findSerum3MarketPkInOpenOrders, modifiedOrderPrice, modifiedOrderSize],
|
||||
)
|
||||
|
||||
return selectedMarket ? (
|
||||
|
|
|
@ -129,7 +129,7 @@ const SharePositionModal = ({
|
|||
<p className="ml-2 font-mono text-base text-white">
|
||||
{formatNumericValue(
|
||||
entryPrice,
|
||||
getDecimalCount(market.tickSize)
|
||||
getDecimalCount(market.tickSize),
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -140,7 +140,7 @@ const SharePositionModal = ({
|
|||
<p className="ml-2 font-mono text-base text-white">
|
||||
{formatNumericValue(
|
||||
market.uiPrice,
|
||||
getDecimalCount(market.tickSize)
|
||||
getDecimalCount(market.tickSize),
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -26,11 +26,11 @@ const TradeVolumeAlertModal = ({ isOpen, onClose }: ModalProps) => {
|
|||
const { t } = useTranslation(['common', 'trade'])
|
||||
const [soundSettings, setSoundSettings] = useLocalStorageState(
|
||||
SOUND_SETTINGS_KEY,
|
||||
INITIAL_SOUND_SETTINGS
|
||||
INITIAL_SOUND_SETTINGS,
|
||||
)
|
||||
const [alertSettings, setAlertSettings] = useLocalStorageState(
|
||||
TRADE_VOLUME_ALERT_KEY,
|
||||
DEFAULT_VOLUME_ALERT_SETTINGS
|
||||
DEFAULT_VOLUME_ALERT_SETTINGS,
|
||||
)
|
||||
const [formValues, setFormValues] = useState(alertSettings)
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ const UserSetupModal = ({
|
|||
onClose: () => void
|
||||
}) => {
|
||||
const { t } = useTranslation(['common', 'onboarding', 'swap'])
|
||||
const { connected, select, wallet, wallets, publicKey } = useWallet()
|
||||
const { connected, select, wallet, wallets, publicKey, connect } = useWallet()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const mangoAccountLoading = mangoStore((s) => s.mangoAccount.initialLoad)
|
||||
const [accountName, setAccountName] = useState('')
|
||||
|
@ -70,7 +70,7 @@ const UserSetupModal = ({
|
|||
const banks = useBanksWithBalances('walletBalance')
|
||||
const [, setAcceptTerms] = useLocalStorageState(ACCEPT_TERMS_KEY, '')
|
||||
const [walletsToDisplay, setWalletstoDisplay] = useState<'default' | 'all'>(
|
||||
'default'
|
||||
'default',
|
||||
)
|
||||
|
||||
const walletsDisplayed = useMemo(() => {
|
||||
|
@ -78,7 +78,7 @@ const UserSetupModal = ({
|
|||
const detectedWallets = wallets.filter(
|
||||
(w) =>
|
||||
w.readyState === WalletReadyState.Installed ||
|
||||
w.readyState === WalletReadyState.Loadable
|
||||
w.readyState === WalletReadyState.Loadable,
|
||||
)
|
||||
|
||||
if (walletsToDisplay === 'default') {
|
||||
|
@ -107,7 +107,7 @@ const UserSetupModal = ({
|
|||
group,
|
||||
0,
|
||||
accountName || 'Account 1',
|
||||
16 // tokenCount
|
||||
16, // tokenCount
|
||||
)
|
||||
actions.fetchMangoAccounts(publicKey)
|
||||
if (tx) {
|
||||
|
@ -147,7 +147,7 @@ const UserSetupModal = ({
|
|||
group,
|
||||
mangoAccount,
|
||||
bank.mint,
|
||||
parseFloat(depositAmount)
|
||||
parseFloat(depositAmount),
|
||||
)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
|
@ -197,7 +197,7 @@ const UserSetupModal = ({
|
|||
const setMax = useCallback(() => {
|
||||
const max = new Decimal(tokenMax.amount).toDecimalPlaces(
|
||||
tokenMax.decimals,
|
||||
Decimal.ROUND_FLOOR
|
||||
Decimal.ROUND_FLOOR,
|
||||
)
|
||||
setDepositAmount(max.toString())
|
||||
setSizePercentage('100')
|
||||
|
@ -212,7 +212,7 @@ const UserSetupModal = ({
|
|||
.toDecimalPlaces(tokenMax.decimals, Decimal.ROUND_FLOOR)
|
||||
setDepositAmount(amount.toString())
|
||||
},
|
||||
[tokenMax]
|
||||
[tokenMax],
|
||||
)
|
||||
|
||||
const handleNextStep = () => {
|
||||
|
@ -306,6 +306,9 @@ const UserSetupModal = ({
|
|||
: 'border-th-bkg-4 text-th-fgd-2'
|
||||
}`}
|
||||
onClick={() => {
|
||||
if (wallet) {
|
||||
connect()
|
||||
}
|
||||
select(w.adapter.name)
|
||||
}}
|
||||
key={w.adapter.name}
|
||||
|
@ -456,7 +459,7 @@ const UserSetupModal = ({
|
|||
value={depositAmount}
|
||||
onValueChange={(e: NumberFormatValues) => {
|
||||
setDepositAmount(
|
||||
!Number.isNaN(Number(e.value)) ? e.value : ''
|
||||
!Number.isNaN(Number(e.value)) ? e.value : '',
|
||||
)
|
||||
}}
|
||||
isAllowed={withValueLimit}
|
||||
|
|
|
@ -22,7 +22,7 @@ import { notify } from 'utils/notifications'
|
|||
|
||||
export const createSolanaMessage = (
|
||||
wallet: WalletContextState,
|
||||
setCookie: (wallet: string, token: string) => void
|
||||
setCookie: (wallet: string, token: string) => void,
|
||||
) => {
|
||||
const payload = new Payload()
|
||||
payload.domain = window.location.host
|
||||
|
@ -121,7 +121,7 @@ const NotificationsDrawer = ({
|
|||
})
|
||||
}
|
||||
},
|
||||
[NOTIFICATION_API, headers]
|
||||
[NOTIFICATION_API, headers],
|
||||
)
|
||||
|
||||
const remove = useCallback(
|
||||
|
@ -136,7 +136,7 @@ const NotificationsDrawer = ({
|
|||
body: JSON.stringify({
|
||||
ids: ids,
|
||||
}),
|
||||
}
|
||||
},
|
||||
)
|
||||
const body = await resp.json()
|
||||
const error = body.error
|
||||
|
@ -158,7 +158,7 @@ const NotificationsDrawer = ({
|
|||
}
|
||||
setIsRemoving(false)
|
||||
},
|
||||
[NOTIFICATION_API, headers]
|
||||
[NOTIFICATION_API, headers],
|
||||
)
|
||||
|
||||
// Mark all notifications as seen when the inbox is opened
|
||||
|
@ -241,7 +241,7 @@ const NotificationsDrawer = ({
|
|||
<CalendarIcon className="mr-1 h-3.5 w-3.5" />
|
||||
<p className="text-xs">
|
||||
{dayjs(notification.createdAt).format(
|
||||
'DD MMM YYYY, h:mma'
|
||||
'DD MMM YYYY, h:mma',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -39,7 +39,7 @@ const TransactionNotificationList = () => {
|
|||
const notEnoughSoLMessage = t('deposit-more-sol')
|
||||
const [notificationPosition] = useLocalStorageState(
|
||||
NOTIFICATION_POSITION_KEY,
|
||||
'bottom-left'
|
||||
'bottom-left',
|
||||
)
|
||||
const [mounted, setMounted] = useState(false)
|
||||
const { maxSolDeposit } = useSolBalance()
|
||||
|
@ -49,10 +49,10 @@ const TransactionNotificationList = () => {
|
|||
useEffect(() => {
|
||||
if (transactionNotifications.length) {
|
||||
const customErrorNotification = transactionNotifications.find(
|
||||
(n) => n.description && n.description.includes('"Custom":1')
|
||||
(n) => n.description && n.description.includes('"Custom":1'),
|
||||
)
|
||||
const notEnoughSolNotification = transactionNotifications.find(
|
||||
(n) => n.title && n.title.includes(notEnoughSoLMessage)
|
||||
(n) => n.title && n.title.includes(notEnoughSoLMessage),
|
||||
)
|
||||
|
||||
if (
|
||||
|
@ -125,11 +125,11 @@ const TransactionNotification = ({
|
|||
}) => {
|
||||
const [notificationPosition] = useLocalStorageState(
|
||||
NOTIFICATION_POSITION_KEY,
|
||||
'Bottom-Left'
|
||||
'Bottom-Left',
|
||||
)
|
||||
const [preferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
EXPLORERS[0]
|
||||
EXPLORERS[0],
|
||||
)
|
||||
const { type, title, description, txid, show, id } = notification
|
||||
|
||||
|
@ -151,7 +151,7 @@ const TransactionNotification = ({
|
|||
if ((type === 'error' || type === 'success') && txid) {
|
||||
setMangoStore((s) => {
|
||||
const newNotifications = s.transactionNotifications.map((n) =>
|
||||
n.txid === txid && n.type === 'confirm' ? { ...n, show: false } : n
|
||||
n.txid === txid && n.type === 'confirm' ? { ...n, show: false } : n,
|
||||
)
|
||||
s.transactionNotifications = newNotifications
|
||||
})
|
||||
|
@ -161,7 +161,7 @@ const TransactionNotification = ({
|
|||
const hideNotification = useCallback(() => {
|
||||
setMangoStore((s) => {
|
||||
const newNotifications = s.transactionNotifications.map((n) =>
|
||||
n.id === id ? { ...n, show: false } : n
|
||||
n.id === id ? { ...n, show: false } : n,
|
||||
)
|
||||
s.transactionNotifications = newNotifications
|
||||
})
|
||||
|
|
|
@ -73,7 +73,7 @@ const EditNftProfilePic = ({ onClose }: { onClose: () => void }) => {
|
|||
}
|
||||
const response = await fetch(
|
||||
`${MANGO_DATA_API_URL}/user-data/profile-details`,
|
||||
requestOptions
|
||||
requestOptions,
|
||||
)
|
||||
if (response.status === 200) {
|
||||
await actions.fetchProfileDetails(publicKey.toString())
|
||||
|
@ -119,7 +119,7 @@ const EditNftProfilePic = ({ onClose }: { onClose: () => void }) => {
|
|||
}
|
||||
const response = await fetch(
|
||||
`${MANGO_DATA_API_URL}/user-data/profile-details`,
|
||||
requestOptions
|
||||
requestOptions,
|
||||
)
|
||||
if (response.status === 200) {
|
||||
await actions.fetchProfileDetails(publicKey.toString())
|
||||
|
|
|
@ -31,7 +31,7 @@ const EditProfileForm = ({
|
|||
const profile = mangoStore((s) => s.profile.details)
|
||||
const { publicKey, signMessage } = useWallet()
|
||||
const [profileName, setProfileName] = useState(
|
||||
startCase(profile?.profile_name) || ''
|
||||
startCase(profile?.profile_name) || '',
|
||||
)
|
||||
const [inputError, setInputError] = useState('')
|
||||
const [loadUniquenessCheck, setLoadUniquenessCheck] = useState(false)
|
||||
|
@ -43,7 +43,7 @@ const EditProfileForm = ({
|
|||
try {
|
||||
setLoadUniquenessCheck(true)
|
||||
const response = await fetch(
|
||||
`${MANGO_DATA_API_URL}/user-data/check-profile-name-unique?profile-name=${name}`
|
||||
`${MANGO_DATA_API_URL}/user-data/check-profile-name-unique?profile-name=${name}`,
|
||||
)
|
||||
const uniquenessCheck = await response.json()
|
||||
|
||||
|
@ -105,7 +105,7 @@ const EditProfileForm = ({
|
|||
}
|
||||
const response = await fetch(
|
||||
`${MANGO_DATA_API_URL}/user-data/profile-details`,
|
||||
requestOptions
|
||||
requestOptions,
|
||||
)
|
||||
if (response.status === 200) {
|
||||
setLoadUpdateProfile(false)
|
||||
|
|
|
@ -54,7 +54,7 @@ const Leaderboards = ({
|
|||
staleTime: 1000 * 60,
|
||||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const isLoading =
|
||||
|
@ -96,7 +96,7 @@ const Leaderboards = ({
|
|||
rewardsLeaderboardData.map(
|
||||
(wallet: RewardsLeaderboardItem, i: number) => (
|
||||
<LeaderboardCard rank={i + 1} key={i} wallet={wallet} />
|
||||
)
|
||||
),
|
||||
)
|
||||
) : (
|
||||
<div className="flex justify-center rounded-lg border border-th-bkg-3 p-8">
|
||||
|
|
|
@ -66,7 +66,7 @@ export const tiers = ['seed', 'mango', 'whale', 'bot']
|
|||
const fetchRewardsPoints = async (walletPk: string | undefined) => {
|
||||
try {
|
||||
const data = await fetch(
|
||||
`${MANGO_DATA_API_URL}/user-data/campaign-total-points-wallet?wallet-pk=${walletPk}`
|
||||
`${MANGO_DATA_API_URL}/user-data/campaign-total-points-wallet?wallet-pk=${walletPk}`,
|
||||
)
|
||||
const res = await data.json()
|
||||
return res
|
||||
|
@ -78,7 +78,7 @@ const fetchRewardsPoints = async (walletPk: string | undefined) => {
|
|||
export const fetchLeaderboard = async (tier: string | undefined) => {
|
||||
try {
|
||||
const data = await fetch(
|
||||
`${MANGO_DATA_API_URL}/user-data/campaign-leaderboard?tier=${tier}`
|
||||
`${MANGO_DATA_API_URL}/user-data/campaign-leaderboard?tier=${tier}`,
|
||||
)
|
||||
const res = await data.json()
|
||||
return res
|
||||
|
@ -195,7 +195,7 @@ const Season = ({
|
|||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
enabled: !!wallet?.adapter,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const {
|
||||
|
@ -210,7 +210,7 @@ const Season = ({
|
|||
staleTime: 1000 * 60,
|
||||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -41,7 +41,7 @@ const SearchPage = () => {
|
|||
try {
|
||||
setLoading(true)
|
||||
const response = await fetch(
|
||||
`${MANGO_DATA_API_URL}/user-data/profile-search?search-string=${searchString}&search-method=${searchType}`
|
||||
`${MANGO_DATA_API_URL}/user-data/profile-search?search-string=${searchString}&search-method=${searchType}`,
|
||||
)
|
||||
const data = await response.json()
|
||||
setSearchResults(data)
|
||||
|
@ -115,7 +115,7 @@ const SearchPage = () => {
|
|||
<MangoAccountItem item={r} type={searchType} />
|
||||
) : (
|
||||
<WalletItem item={r} />
|
||||
)
|
||||
),
|
||||
)
|
||||
) : showNoResults ? (
|
||||
<div className="flex flex-col items-center rounded-md border border-th-bkg-3 p-4">
|
||||
|
|
|
@ -13,7 +13,7 @@ const AnimationSettings = () => {
|
|||
const { t } = useTranslation(['common', 'settings'])
|
||||
const [animationSettings, setAnimationSettings] = useLocalStorageState(
|
||||
ANIMATION_SETTINGS_KEY,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
INITIAL_ANIMATION_SETTINGS,
|
||||
)
|
||||
|
||||
const handleToggleAnimationSetting = (settingName: string) => {
|
||||
|
|
|
@ -17,11 +17,13 @@ import { useTheme } from 'next-themes'
|
|||
import { useCallback } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import {
|
||||
AUTO_CONNECT_WALLET,
|
||||
NOTIFICATION_POSITION_KEY,
|
||||
SIZE_INPUT_UI_KEY,
|
||||
TRADE_CHART_UI_KEY,
|
||||
TRADE_LAYOUT_KEY,
|
||||
} from 'utils/constants'
|
||||
import Switch from '@components/forms/Switch'
|
||||
|
||||
const NOTIFICATION_POSITIONS = [
|
||||
'bottom-left',
|
||||
|
@ -63,23 +65,27 @@ const DisplaySettings = () => {
|
|||
const { theme, setTheme } = useTheme()
|
||||
const [savedLanguage, setSavedLanguage] = useLocalStorageState(
|
||||
'language',
|
||||
'en'
|
||||
'en',
|
||||
)
|
||||
const router = useRouter()
|
||||
const { pathname, asPath, query } = router
|
||||
const [notificationPosition, setNotificationPosition] = useLocalStorageState(
|
||||
NOTIFICATION_POSITION_KEY,
|
||||
'bottom-left'
|
||||
'bottom-left',
|
||||
)
|
||||
const [tradeFormUi, setTradeFormUi] = useLocalStorageState(
|
||||
SIZE_INPUT_UI_KEY,
|
||||
'slider'
|
||||
'slider',
|
||||
)
|
||||
const [tradeChartUi, setTradeChartUi] = useLocalStorageState(
|
||||
TRADE_CHART_UI_KEY,
|
||||
'trading-view'
|
||||
'trading-view',
|
||||
)
|
||||
const [, setTradeLayout] = useLocalStorageState(TRADE_LAYOUT_KEY, 'chartLeft')
|
||||
const [autoConnect, setAutoConnect] = useLocalStorageState(
|
||||
AUTO_CONNECT_WALLET,
|
||||
true,
|
||||
)
|
||||
|
||||
const handleLangChange = useCallback(
|
||||
(l: string) => {
|
||||
|
@ -87,7 +93,7 @@ const DisplaySettings = () => {
|
|||
router.push({ pathname, query }, asPath, { locale: l })
|
||||
dayjs.locale(l == 'zh_tw' ? 'zh-tw' : l)
|
||||
},
|
||||
[router, pathname, query, asPath, setSavedLanguage]
|
||||
[router, pathname, query, asPath, setSavedLanguage],
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -191,6 +197,13 @@ const DisplaySettings = () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-t border-th-bkg-3 p-4">
|
||||
<p className="">Auto Connect Wallet</p>
|
||||
<Switch
|
||||
checked={autoConnect}
|
||||
onChange={() => setAutoConnect(!autoConnect)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ const HotKeysSettings = () => {
|
|||
{Object.entries(options).map((e) => {
|
||||
return e[1]
|
||||
? `${e[0] !== 'margin' ? ', ' : ''}${t(
|
||||
`trade:${e[0]}`
|
||||
`trade:${e[0]}`,
|
||||
)}`
|
||||
: ''
|
||||
})}
|
||||
|
|
|
@ -49,7 +49,7 @@ const NotificationSettings = () => {
|
|||
onChange={() =>
|
||||
handleSettingChange(
|
||||
'fillsNotifications',
|
||||
!data?.fillsNotifications
|
||||
!data?.fillsNotifications,
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -15,7 +15,7 @@ const PreferredExplorerSettings = () => {
|
|||
const { t } = useTranslation('settings')
|
||||
const [preferredExplorer, setPreferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
EXPLORERS[0]
|
||||
EXPLORERS[0],
|
||||
)
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -50,11 +50,11 @@ const RpcSettings = () => {
|
|||
const [showCustomForm, setShowCustomForm] = useState(false)
|
||||
const [rpcEndpointProvider, setRpcEndpointProvider] = useLocalStorageState(
|
||||
RPC_PROVIDER_KEY,
|
||||
RPC_URLS[0].value
|
||||
RPC_URLS[0].value,
|
||||
)
|
||||
const [storedPriorityFee, setStoredPriorityFee] = useLocalStorageState(
|
||||
PRIORITY_FEE_KEY,
|
||||
DEFAULT_PRIORITY_FEE.value
|
||||
DEFAULT_PRIORITY_FEE.value,
|
||||
)
|
||||
const [storedUseOrderbookFeed, setStoredUseOrderbookFeed] =
|
||||
useLocalStorageState(USE_ORDERBOOK_FEED_KEY, true)
|
||||
|
@ -77,7 +77,7 @@ const RpcSettings = () => {
|
|||
|
||||
const handleSetEndpointProvider = (provider: string) => {
|
||||
const endpointProvider = RPC_URLS.find(
|
||||
(node) => node.label === provider
|
||||
(node) => node.label === provider,
|
||||
) || { label: 'Custom', value: rpcEndpointProvider }
|
||||
setRpcEndpointProvider(endpointProvider.value)
|
||||
if (provider !== 'Custom') {
|
||||
|
@ -96,7 +96,7 @@ const RpcSettings = () => {
|
|||
}
|
||||
}
|
||||
},
|
||||
[setStoredPriorityFee, actions, wallet]
|
||||
[setStoredPriorityFee, actions, wallet],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -14,7 +14,7 @@ const SoundSettings = () => {
|
|||
const { t } = useTranslation(['common', 'settings'])
|
||||
const [soundSettings, setSoundSettings] = useLocalStorageState(
|
||||
SOUND_SETTINGS_KEY,
|
||||
INITIAL_SOUND_SETTINGS
|
||||
INITIAL_SOUND_SETTINGS,
|
||||
)
|
||||
|
||||
const handleToggleSoundSetting = (settingName: string) => {
|
||||
|
|
|
@ -63,7 +63,7 @@ const BalancesTable = () => {
|
|||
<div className="flex justify-end">
|
||||
<Tooltip content={t('account:tooltip-collateral-value')}>
|
||||
<span className="tooltip-underline">
|
||||
{t('account:collateral-value')}
|
||||
{t('collateral-value')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
@ -202,7 +202,7 @@ const BalancesTable = () => {
|
|||
content={t('account:tooltip-collateral-value')}
|
||||
>
|
||||
<p className="tooltip-underline text-xs text-th-fgd-3">
|
||||
{t('account:collateral-value')}
|
||||
{t('collateral-value')}
|
||||
</p>
|
||||
</Tooltip>
|
||||
<p className="font-mono text-th-fgd-2">
|
||||
|
@ -293,7 +293,7 @@ const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
|||
let tickDecimals: number
|
||||
if (selectedMarket instanceof Serum3Market) {
|
||||
const market = group.getSerum3ExternalMarket(
|
||||
selectedMarket.serumMarketExternal
|
||||
selectedMarket.serumMarketExternal,
|
||||
)
|
||||
minOrderDecimals = getDecimalCount(market.minOrderSize)
|
||||
tickDecimals = getDecimalCount(market.tickSize)
|
||||
|
@ -306,7 +306,7 @@ const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
|||
const floorBalance = floorToDecimal(balance, tickDecimals).toNumber()
|
||||
const baseSize = floorToDecimal(
|
||||
floorBalance / price,
|
||||
minOrderDecimals
|
||||
minOrderDecimals,
|
||||
).toNumber()
|
||||
const quoteSize = floorToDecimal(baseSize * price, tickDecimals)
|
||||
set((s) => {
|
||||
|
@ -322,7 +322,7 @@ const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
|||
})
|
||||
}
|
||||
},
|
||||
[selectedMarket]
|
||||
[selectedMarket],
|
||||
)
|
||||
|
||||
const handleSwapFormBalanceClick = useCallback(
|
||||
|
@ -356,7 +356,7 @@ const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
|||
})
|
||||
}
|
||||
},
|
||||
[bank]
|
||||
[bank],
|
||||
)
|
||||
|
||||
const balance = bank.balance
|
||||
|
@ -393,7 +393,7 @@ const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
|||
className="font-normal underline underline-offset-2 md:underline-offset-4 md:hover:no-underline"
|
||||
onClick={() =>
|
||||
handleSwapFormBalanceClick(
|
||||
Number(floorToDecimal(balance, tokenBank.mintDecimals))
|
||||
Number(floorToDecimal(balance, tokenBank.mintDecimals)),
|
||||
)
|
||||
}
|
||||
>
|
||||
|
|
|
@ -3,15 +3,33 @@ import { LinkIcon } from '@heroicons/react/20/solid'
|
|||
import { useTranslation } from 'next-i18next'
|
||||
import Button from './Button'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useCallback } from 'react'
|
||||
import { AUTO_CONNECT_WALLET } from 'utils/constants'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
|
||||
const ConnectEmptyState = ({ text }: { text: string }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { connect } = useWallet()
|
||||
const [autoConnect] = useLocalStorageState(AUTO_CONNECT_WALLET, true)
|
||||
|
||||
const handleConnect = useCallback(() => {
|
||||
if (!autoConnect) {
|
||||
set((s) => {
|
||||
s.showUserSetup = true
|
||||
})
|
||||
} else {
|
||||
connect()
|
||||
}
|
||||
}, [autoConnect, connect])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center">
|
||||
<WalletIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p className="mb-4">{text}</p>
|
||||
<Button onClick={connect}>
|
||||
<Button onClick={handleConnect}>
|
||||
<div className="flex items-center">
|
||||
<LinkIcon className="mr-2 h-5 w-5" />
|
||||
{t('connect')}
|
||||
|
|
|
@ -18,7 +18,6 @@ import FlipNumbers from 'react-flip-numbers'
|
|||
import ContentBox from './ContentBox'
|
||||
import SheenLoader from './SheenLoader'
|
||||
import { COLORS } from '../../styles/colors'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { IconButton } from './Button'
|
||||
import { ArrowLeftIcon, NoSymbolIcon } from '@heroicons/react/20/solid'
|
||||
import { FadeInFadeOut } from './Transitions'
|
||||
|
@ -33,6 +32,7 @@ import { useTranslation } from 'next-i18next'
|
|||
import FormatNumericValue from './FormatNumericValue'
|
||||
import { ContentType } from 'recharts/types/component/Tooltip'
|
||||
import Tooltip from './Tooltip'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
|
@ -97,10 +97,10 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
}) => {
|
||||
const { t } = useTranslation('common')
|
||||
const [mouseData, setMouseData] = useState<any>(null)
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const [animationSettings] = useLocalStorageState(
|
||||
ANIMATION_SETTINGS_KEY,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
INITIAL_ANIMATION_SETTINGS,
|
||||
)
|
||||
|
||||
const handleMouseMove = (coords: any) => {
|
||||
|
@ -134,7 +134,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
if (filteredData.length) {
|
||||
if (mouseData) {
|
||||
const index = filteredData.findIndex(
|
||||
(d: any) => d[xKey] === mouseData[xKey]
|
||||
(d: any) => d[xKey] === mouseData[xKey],
|
||||
)
|
||||
const change =
|
||||
index >= 0 ? filteredData[index][yKey] - filteredData[0][yKey] : 0
|
||||
|
@ -216,7 +216,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
mouseData[yKey] < 0 ? '-' : ''
|
||||
}${prefix}${formatNumericValue(
|
||||
Math.abs(mouseData[yKey]),
|
||||
yDecimals
|
||||
yDecimals,
|
||||
)}${suffix}`}
|
||||
/>
|
||||
) : (
|
||||
|
@ -249,7 +249,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
{dayjs(mouseData[xKey]).format(
|
||||
tooltipDateFormat
|
||||
? tooltipDateFormat
|
||||
: 'DD MMM YY, h:mma'
|
||||
: 'DD MMM YY, h:mma',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -273,9 +273,9 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
: ''
|
||||
}${prefix}${formatNumericValue(
|
||||
Math.abs(
|
||||
filteredData[filteredData.length - 1][yKey]
|
||||
filteredData[filteredData.length - 1][yKey],
|
||||
),
|
||||
yDecimals
|
||||
yDecimals,
|
||||
)}${suffix}`}
|
||||
/>
|
||||
) : (
|
||||
|
@ -308,11 +308,11 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
} text-th-fgd-4`}
|
||||
>
|
||||
{dayjs(
|
||||
filteredData[filteredData.length - 1][xKey]
|
||||
filteredData[filteredData.length - 1][xKey],
|
||||
).format(
|
||||
tooltipDateFormat
|
||||
? tooltipDateFormat
|
||||
: 'DD MMM YY, h:mma'
|
||||
: 'DD MMM YY, h:mma',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -341,7 +341,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
<linearGradient
|
||||
id={`gradientArea-${title?.replace(
|
||||
/[^a-zA-Z]/g,
|
||||
''
|
||||
'',
|
||||
)}`}
|
||||
x1="0"
|
||||
y1={flipGradientCoords ? '1' : '0'}
|
||||
|
@ -380,7 +380,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
strokeWidth={1.5}
|
||||
fill={`url(#gradientArea-${title?.replace(
|
||||
/[^a-zA-Z]/g,
|
||||
''
|
||||
'',
|
||||
)})`}
|
||||
/>
|
||||
<XAxis
|
||||
|
|
|
@ -11,7 +11,7 @@ const FavoriteMarketButton = ({
|
|||
}) => {
|
||||
const [favoriteMarkets, setFavoriteMarkets] = useLocalStorageState<string[]>(
|
||||
FAVORITE_MARKETS_KEY,
|
||||
[]
|
||||
[],
|
||||
)
|
||||
|
||||
const addToFavorites = (marketName: string) => {
|
||||
|
@ -24,7 +24,7 @@ const FavoriteMarketButton = ({
|
|||
}
|
||||
|
||||
return favoriteMarkets.find(
|
||||
(marketName: string) => marketName === market.name
|
||||
(marketName: string) => marketName === market.name,
|
||||
) ? (
|
||||
<button
|
||||
className="flex items-center justify-center text-th-active focus-visible:text-th-fgd-4 md:hover:text-th-fgd-3"
|
||||
|
|
|
@ -31,13 +31,13 @@ const MarketChange = ({
|
|||
if (market instanceof PerpMarket) {
|
||||
const perpData: MarketData = marketsData?.perpData
|
||||
const perpEntries = Object.entries(perpData).find(
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
||||
)
|
||||
return perpEntries ? perpEntries[1][0]?.price_history[0]?.price : 0
|
||||
} else {
|
||||
const spotData: MarketData = marketsData?.spotData
|
||||
const spotEntries = Object.entries(spotData).find(
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
||||
)
|
||||
return spotEntries ? spotEntries[1][0]?.price_history[0]?.price : 0
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ const MarketChange = ({
|
|||
if (market instanceof PerpMarket) {
|
||||
const perpData: MarketData = marketsData?.perpData
|
||||
const perpEntries = Object.entries(perpData).find(
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
||||
)
|
||||
const price = perpEntries ? perpEntries[1][0]?.last_price : 0
|
||||
const change = perpEntries ? perpEntries[1][0]?.change_24h : 0
|
||||
|
@ -56,7 +56,7 @@ const MarketChange = ({
|
|||
} else {
|
||||
const spotData: MarketData = marketsData?.spotData
|
||||
const spotEntries = Object.entries(spotData).find(
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
||||
)
|
||||
const price = spotEntries ? spotEntries[1][0]?.last_price : 0
|
||||
const change = spotEntries ? spotEntries[1][0]?.change_24h : 0
|
||||
|
|
|
@ -63,7 +63,7 @@ const SolBalanceWarnings = ({
|
|||
<div className={className}>
|
||||
<InlineNotification
|
||||
type="info"
|
||||
desc={`SOL deposits are restricted to leave ${MIN_SOL_BALANCE} SOL in your wallet for sending transactions`}
|
||||
desc={`Max SOL deposits are reduced to leave ${MIN_SOL_BALANCE} SOL in your wallet for sending transactions`}
|
||||
/>
|
||||
</div>
|
||||
) : null
|
||||
|
|
|
@ -15,7 +15,7 @@ const SuccessParticles = () => {
|
|||
const set = mangoStore((s) => s.set)
|
||||
const [animationSettings] = useLocalStorageState(
|
||||
ANIMATION_SETTINGS_KEY,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
INITIAL_ANIMATION_SETTINGS,
|
||||
)
|
||||
|
||||
const tokenLogo = useMemo(() => {
|
||||
|
@ -70,7 +70,7 @@ const SuccessParticles = () => {
|
|||
set((s) => {
|
||||
s.successAnimation.swap = false
|
||||
}),
|
||||
8000
|
||||
8000,
|
||||
)
|
||||
}
|
||||
if (showForTrade) {
|
||||
|
@ -79,7 +79,7 @@ const SuccessParticles = () => {
|
|||
set((s) => {
|
||||
s.successAnimation.trade = false
|
||||
}),
|
||||
8000
|
||||
8000,
|
||||
)
|
||||
}
|
||||
}, [showForSwap, showForTrade])
|
||||
|
|
|
@ -62,7 +62,7 @@ export const TrBody = forwardRef<HTMLTableRowElement, TrBodyProps>(
|
|||
{children}
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
TrBody.displayName = 'TrBody'
|
||||
|
|
|
@ -22,7 +22,7 @@ const TokenLogo = ({
|
|||
let jupiterLogoURI
|
||||
if (mangoTokens?.length) {
|
||||
jupiterLogoURI = mangoTokens.find(
|
||||
(t) => t.address === bank?.mint.toString()
|
||||
(t) => t.address === bank?.mint.toString(),
|
||||
)?.logoURI
|
||||
}
|
||||
return jupiterLogoURI
|
||||
|
|
|
@ -26,7 +26,7 @@ const TokenVaultWarnings = ({
|
|||
const maxWithdraw = getMaxWithdrawForBank(group, bank, mangoAccount)
|
||||
const maxBorrow = mangoAccount.getMaxWithdrawWithBorrowForTokenUi(
|
||||
group,
|
||||
bank.mint
|
||||
bank.mint,
|
||||
)
|
||||
|
||||
return [maxWithdraw, maxBorrow]
|
||||
|
|
|
@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'
|
|||
|
||||
export default function useDebounce<T>(
|
||||
value: T,
|
||||
delay: number
|
||||
delay: number,
|
||||
): [T, (value: T) => void] {
|
||||
// State and setters for debounced value
|
||||
const [debouncedValue, setDebouncedValue] = useState(value)
|
||||
|
@ -19,7 +19,7 @@ export default function useDebounce<T>(
|
|||
clearTimeout(handler)
|
||||
}
|
||||
},
|
||||
[value, delay] // Only re-call effect if value or delay changes
|
||||
[value, delay], // Only re-call effect if value or delay changes
|
||||
)
|
||||
return [debouncedValue, setDebouncedValue]
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useRef, useEffect } from 'react'
|
|||
export default function useInterval(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
callback: (...args: any[]) => any,
|
||||
delay: number
|
||||
delay: number,
|
||||
) {
|
||||
const savedCallback = useRef<() => void>()
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ const AverageFundingChart = ({
|
|||
|
||||
const groupByHourlyInterval = (
|
||||
data: PerpStatsItem[],
|
||||
intervalDurationHours: number
|
||||
intervalDurationHours: number,
|
||||
) => {
|
||||
const intervalMillis = intervalDurationHours * 60 * 60 * 1000
|
||||
const groupedData = []
|
||||
|
|
|
@ -39,15 +39,15 @@ const MangoPerpStatsCharts = () => {
|
|||
const data = perpStats.reduce(
|
||||
(a: PerpStatsData, c: PerpStatsItem) => {
|
||||
const hasDateFee = a.feeValues.find(
|
||||
(d: FeeValueItem) => d.date === c.date_hour
|
||||
(d: FeeValueItem) => d.date === c.date_hour,
|
||||
)
|
||||
|
||||
const hasDateOpenInterest = a.openInterestValues.find(
|
||||
(d: OiValueItem) => d.date === c.date_hour
|
||||
(d: OiValueItem) => d.date === c.date_hour,
|
||||
)
|
||||
|
||||
const hasDateVolume = a.volumeValues.find(
|
||||
(d: VolumeValueItem) => d.date === c.date_hour
|
||||
(d: VolumeValueItem) => d.date === c.date_hour,
|
||||
)
|
||||
|
||||
if (!hasDateFee) {
|
||||
|
@ -66,7 +66,7 @@ const MangoPerpStatsCharts = () => {
|
|||
})
|
||||
} else {
|
||||
hasDateOpenInterest.openInterest += Math.floor(
|
||||
c.open_interest * c.price
|
||||
c.open_interest * c.price,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -81,19 +81,19 @@ const MangoPerpStatsCharts = () => {
|
|||
|
||||
return a
|
||||
},
|
||||
{ feeValues: [], openInterestValues: [], volumeValues: [] }
|
||||
{ feeValues: [], openInterestValues: [], volumeValues: [] },
|
||||
)
|
||||
|
||||
const { feeValues, openInterestValues, volumeValues } = data
|
||||
|
||||
const sortedFeeValues = feeValues.sort(
|
||||
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
|
||||
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime(),
|
||||
)
|
||||
const sortedOpenInterestValues = openInterestValues.sort(
|
||||
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
|
||||
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime(),
|
||||
)
|
||||
const sortedVolumeValues = volumeValues.sort(
|
||||
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
|
||||
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime(),
|
||||
)
|
||||
|
||||
return [sortedFeeValues, sortedOpenInterestValues, sortedVolumeValues]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useViewport } from '../../hooks/useViewport'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { COLORS } from '../../styles/colors'
|
||||
|
@ -25,10 +24,11 @@ import SoonBadge from '@components/shared/SoonBadge'
|
|||
import useMarketsData from 'hooks/useMarketsData'
|
||||
import { useMemo } from 'react'
|
||||
import MarketChange from '@components/shared/MarketChange'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
export const goToPerpMarketDetails = (
|
||||
market: PerpMarket,
|
||||
router: NextRouter
|
||||
router: NextRouter,
|
||||
) => {
|
||||
const query = { ...router.query, ['market']: market.name }
|
||||
router.push({ pathname: router.pathname, query })
|
||||
|
@ -37,7 +37,7 @@ export const goToPerpMarketDetails = (
|
|||
const PerpMarketsOverviewTable = () => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const perpMarkets = mangoStore((s) => s.perpMarkets)
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const rate = usePerpFundingRate()
|
||||
|
@ -72,7 +72,7 @@ const PerpMarketsOverviewTable = () => {
|
|||
const symbol = market.name.split('-')[0]
|
||||
|
||||
const perpDataEntries = Object.entries(perpData).find(
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
||||
)
|
||||
const marketData = perpDataEntries
|
||||
? perpDataEntries[1][0]
|
||||
|
@ -88,14 +88,14 @@ const PerpMarketsOverviewTable = () => {
|
|||
let fundingRateApr
|
||||
if (rate.isSuccess) {
|
||||
const marketRate = rate?.data?.find(
|
||||
(r) => r.market_index === market.perpMarketIndex
|
||||
(r) => r.market_index === market.perpMarketIndex,
|
||||
)
|
||||
if (marketRate) {
|
||||
fundingRate = formatFunding.format(
|
||||
marketRate.funding_rate_hourly
|
||||
marketRate.funding_rate_hourly,
|
||||
)
|
||||
fundingRateApr = formatFunding.format(
|
||||
marketRate.funding_rate_hourly * 8760
|
||||
marketRate.funding_rate_hourly * 8760,
|
||||
)
|
||||
} else {
|
||||
fundingRate = '–'
|
||||
|
@ -221,7 +221,7 @@ const PerpMarketsOverviewTable = () => {
|
|||
<p className="text-th-fgd-4">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
openInterest * market.uiPrice
|
||||
openInterest * market.uiPrice,
|
||||
)}
|
||||
</p>
|
||||
</>
|
||||
|
@ -263,7 +263,7 @@ export default PerpMarketsOverviewTable
|
|||
|
||||
const MobilePerpMarketItem = ({ market }: { market: PerpMarket }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const router = useRouter()
|
||||
const rate = usePerpFundingRate()
|
||||
const { data: marketsData, isLoading, isFetching } = useMarketsData()
|
||||
|
@ -274,7 +274,7 @@ const MobilePerpMarketItem = ({ market }: { market: PerpMarket }) => {
|
|||
}, [marketsData])
|
||||
|
||||
const perpDataEntries = Object.entries(perpData).find(
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
||||
)
|
||||
const marketData = perpDataEntries ? perpDataEntries[1][0] : undefined
|
||||
|
||||
|
@ -297,12 +297,12 @@ const MobilePerpMarketItem = ({ market }: { market: PerpMarket }) => {
|
|||
let fundingRateApr: string
|
||||
if (rate.isSuccess) {
|
||||
const marketRate = rate?.data?.find(
|
||||
(r) => r.market_index === market.perpMarketIndex
|
||||
(r) => r.market_index === market.perpMarketIndex,
|
||||
)
|
||||
if (marketRate) {
|
||||
fundingRate = formatFunding.format(marketRate.funding_rate_hourly)
|
||||
fundingRateApr = formatFunding.format(
|
||||
marketRate.funding_rate_hourly * 8760
|
||||
marketRate.funding_rate_hourly * 8760,
|
||||
)
|
||||
} else {
|
||||
fundingRate = '–'
|
||||
|
|
|
@ -41,7 +41,7 @@ const PerpPositionsStatsTable = ({
|
|||
<tbody>
|
||||
{positions.map(({ account, perpPosition, mangoAccount }, i) => {
|
||||
const market = group.getPerpMarketByMarketIndex(
|
||||
perpPosition.marketIndex
|
||||
perpPosition.marketIndex,
|
||||
)
|
||||
const basePosition = perpPosition.getBasePositionUi(market)
|
||||
|
||||
|
@ -49,7 +49,7 @@ const PerpPositionsStatsTable = ({
|
|||
|
||||
const floorBasePosition = floorToDecimal(
|
||||
basePosition,
|
||||
getDecimalCount(market.minOrderSize)
|
||||
getDecimalCount(market.minOrderSize),
|
||||
).toNumber()
|
||||
|
||||
const isLong = basePosition > 0
|
||||
|
@ -179,7 +179,7 @@ const PerpPositionsStatsTable = ({
|
|||
<div className="border-b border-th-bkg-3">
|
||||
{positions.map(({ account, perpPosition, mangoAccount }) => {
|
||||
const market = group.getPerpMarketByMarketIndex(
|
||||
perpPosition.marketIndex
|
||||
perpPosition.marketIndex,
|
||||
)
|
||||
const basePosition = perpPosition.getBasePositionUi(market)
|
||||
|
||||
|
@ -187,7 +187,7 @@ const PerpPositionsStatsTable = ({
|
|||
|
||||
const floorBasePosition = floorToDecimal(
|
||||
basePosition,
|
||||
getDecimalCount(market.minOrderSize)
|
||||
getDecimalCount(market.minOrderSize),
|
||||
).toNumber()
|
||||
|
||||
const isLong = basePosition > 0
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useMemo } from 'react'
|
||||
import { useViewport } from '../../hooks/useViewport'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
|
@ -18,12 +17,13 @@ import { Disclosure, Transition } from '@headlessui/react'
|
|||
import { ChevronDownIcon } from '@heroicons/react/20/solid'
|
||||
import MarketChange from '@components/shared/MarketChange'
|
||||
import useMarketsData from 'hooks/useMarketsData'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
|
||||
const SpotMarketsTable = () => {
|
||||
const { t } = useTranslation('common')
|
||||
const { group } = useMangoGroup()
|
||||
const serumMarkets = mangoStore((s) => s.serumMarkets)
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const { data: marketsData, isLoading, isFetching } = useMarketsData()
|
||||
|
@ -54,24 +54,24 @@ const SpotMarketsTable = () => {
|
|||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((mkt) => {
|
||||
const baseBank = group?.getFirstBankByTokenIndex(
|
||||
mkt.baseTokenIndex
|
||||
mkt.baseTokenIndex,
|
||||
)
|
||||
const quoteBank = group?.getFirstBankByTokenIndex(
|
||||
mkt.quoteTokenIndex
|
||||
mkt.quoteTokenIndex,
|
||||
)
|
||||
const market = group?.getSerum3ExternalMarket(
|
||||
mkt.serumMarketExternal
|
||||
mkt.serumMarketExternal,
|
||||
)
|
||||
let price
|
||||
if (baseBank && market && quoteBank) {
|
||||
price = floorToDecimal(
|
||||
baseBank.uiPrice / quoteBank.uiPrice,
|
||||
getDecimalCount(market.tickSize)
|
||||
getDecimalCount(market.tickSize),
|
||||
).toNumber()
|
||||
}
|
||||
|
||||
const spotDataEntries = Object.entries(spotData).find(
|
||||
(e) => e[0].toLowerCase() === mkt.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === mkt.name.toLowerCase(),
|
||||
)
|
||||
const marketData = spotDataEntries
|
||||
? spotDataEntries[1][0]
|
||||
|
@ -196,7 +196,7 @@ export default SpotMarketsTable
|
|||
const MobileSpotMarketItem = ({ market }: { market: Serum3Market }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { group } = useMangoGroup()
|
||||
const { theme } = useTheme()
|
||||
const { theme } = useThemeWrapper()
|
||||
const baseBank = group?.getFirstBankByTokenIndex(market.baseTokenIndex)
|
||||
const quoteBank = group?.getFirstBankByTokenIndex(market.quoteTokenIndex)
|
||||
const serumMarket = group?.getSerum3ExternalMarket(market.serumMarketExternal)
|
||||
|
@ -213,12 +213,12 @@ const MobileSpotMarketItem = ({ market }: { market: Serum3Market }) => {
|
|||
if (!baseBank || !quoteBank || !serumMarket) return 0
|
||||
return floorToDecimal(
|
||||
baseBank.uiPrice / quoteBank.uiPrice,
|
||||
getDecimalCount(serumMarket.tickSize)
|
||||
getDecimalCount(serumMarket.tickSize),
|
||||
).toNumber()
|
||||
}, [baseBank, quoteBank, serumMarket])
|
||||
|
||||
const spotDataEntries = Object.entries(spotData).find(
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase()
|
||||
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
||||
)
|
||||
const marketData = spotDataEntries ? spotDataEntries[1][0] : undefined
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ const StatsPage = () => {
|
|||
const actions = mangoStore.getState().actions
|
||||
const perpStats = mangoStore((s) => s.perpStats.data)
|
||||
const perpPositionsStatsNotLoaded = mangoStore(
|
||||
(s) => s.perpStats.positions.initialLoad
|
||||
(s) => s.perpStats.positions.initialLoad,
|
||||
)
|
||||
const { group } = useMangoGroup()
|
||||
const { width } = useViewport()
|
||||
|
|
|
@ -98,7 +98,7 @@ const TokenDetailsTable = () => {
|
|||
const [oracleProvider, oracleLinkPath] = getOracleProvider(bank)
|
||||
|
||||
const mintInfo = group.mintInfosMapByMint.get(
|
||||
bank.mint.toString()
|
||||
bank.mint.toString(),
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -131,7 +131,7 @@ const TokenDetailsTable = () => {
|
|||
<Td>
|
||||
<p className="text-right">
|
||||
{(100 * bank.loanOriginationFeeRate.toNumber()).toFixed(
|
||||
2
|
||||
2,
|
||||
)}
|
||||
%
|
||||
</p>
|
||||
|
@ -262,7 +262,7 @@ const TokenDetailsTable = () => {
|
|||
</Tooltip>
|
||||
<p className="font-mono text-th-fgd-1">
|
||||
{(bank.liquidationFee.toNumber() * 100).toFixed(
|
||||
2
|
||||
2,
|
||||
)}
|
||||
%
|
||||
</p>
|
||||
|
|
|
@ -84,11 +84,11 @@ const TokenOverviewTable = () => {
|
|||
deposits * bank.minVaultToDepositsRatio
|
||||
const available = Decimal.max(
|
||||
0,
|
||||
availableVaultBalance.toFixed(bank.mintDecimals)
|
||||
availableVaultBalance.toFixed(bank.mintDecimals),
|
||||
)
|
||||
const feesEarned = toUiDecimals(
|
||||
bank.collectedFeesNative,
|
||||
bank.mintDecimals
|
||||
bank.mintDecimals,
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -201,11 +201,11 @@ const TokenOverviewTable = () => {
|
|||
deposits * bank.minVaultToDepositsRatio
|
||||
const available = Decimal.max(
|
||||
0,
|
||||
availableVaultBalance.toFixed(bank.mintDecimals)
|
||||
availableVaultBalance.toFixed(bank.mintDecimals),
|
||||
)
|
||||
const feesEarned = toUiDecimals(
|
||||
bank.collectedFeesNative,
|
||||
bank.mintDecimals
|
||||
bank.mintDecimals,
|
||||
)
|
||||
return (
|
||||
<Disclosure key={bank.name}>
|
||||
|
|
|
@ -39,7 +39,7 @@ const TokenStatsCharts = () => {
|
|||
a +
|
||||
c.bank.uiPrice *
|
||||
toUiDecimals(c.bank.collectedFeesNative, c.bank.mintDecimals),
|
||||
0
|
||||
0,
|
||||
),
|
||||
]
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ const RoutesModal = ({
|
|||
{
|
||||
jupiterTokens.find(
|
||||
(item) =>
|
||||
item?.address === r?.outputMint?.toString()
|
||||
item?.address === r?.outputMint?.toString(),
|
||||
)?.symbol
|
||||
}
|
||||
</span>
|
||||
|
|
|
@ -121,14 +121,14 @@ const SwapForm = () => {
|
|||
}
|
||||
})
|
||||
},
|
||||
[]
|
||||
[],
|
||||
)
|
||||
|
||||
const setAmountFromSlider = useCallback(
|
||||
(amount: string) => {
|
||||
setAmountInFormValue(amount, true)
|
||||
},
|
||||
[setAmountInFormValue]
|
||||
[setAmountInFormValue],
|
||||
)
|
||||
|
||||
const setAmountOutFormValue = useCallback((amountOut: string) => {
|
||||
|
@ -149,7 +149,7 @@ const SwapForm = () => {
|
|||
}
|
||||
setAmountOutFormValue(borrowAmount.toString())
|
||||
},
|
||||
[setAmountOutFormValue]
|
||||
[setAmountOutFormValue],
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -192,7 +192,7 @@ const SwapForm = () => {
|
|||
}
|
||||
setAmountInFormValue(e.value)
|
||||
},
|
||||
[swapMode, setAmountInFormValue]
|
||||
[swapMode, setAmountInFormValue],
|
||||
)
|
||||
|
||||
const handleAmountOutChange = useCallback(
|
||||
|
@ -205,7 +205,7 @@ const SwapForm = () => {
|
|||
}
|
||||
setAmountOutFormValue(e.value)
|
||||
},
|
||||
[swapMode, setAmountOutFormValue]
|
||||
[swapMode, setAmountOutFormValue],
|
||||
)
|
||||
|
||||
const handleTokenInSelect = useCallback((mintAddress: string) => {
|
||||
|
@ -242,10 +242,10 @@ const SwapForm = () => {
|
|||
s.swap.outputBank = inputBank
|
||||
})
|
||||
setAnimateSwitchArrow(
|
||||
(prevanimateSwitchArrow) => prevanimateSwitchArrow + 1
|
||||
(prevanimateSwitchArrow) => prevanimateSwitchArrow + 1,
|
||||
)
|
||||
},
|
||||
[setAmountInFormValue]
|
||||
[setAmountInFormValue],
|
||||
)
|
||||
|
||||
const maintProjectedHealth = useMemo(() => {
|
||||
|
@ -272,7 +272,7 @@ const SwapForm = () => {
|
|||
uiTokenAmount: amountOutAsDecimal.toNumber(),
|
||||
},
|
||||
],
|
||||
HealthType.maint
|
||||
HealthType.maint,
|
||||
)
|
||||
return simulatedHealthRatio > 100
|
||||
? 100
|
||||
|
@ -401,7 +401,7 @@ const SwapForm = () => {
|
|||
<span className="absolute right-3 bottom-1.5 text-xxs text-th-fgd-4">
|
||||
{inputBank
|
||||
? formatCurrencyValue(
|
||||
inputBank.uiPrice * Number(amountInFormValue)
|
||||
inputBank.uiPrice * Number(amountInFormValue),
|
||||
)
|
||||
: '–'}
|
||||
</span>
|
||||
|
@ -434,8 +434,8 @@ const SwapForm = () => {
|
|||
onClick={() =>
|
||||
setBorrowAmountOut(
|
||||
outputTokenBalanceBorrow.toFixed(
|
||||
outputBank?.mintDecimals || 9
|
||||
)
|
||||
outputBank?.mintDecimals || 9,
|
||||
),
|
||||
)
|
||||
}
|
||||
value={outputTokenBalanceBorrow}
|
||||
|
@ -476,7 +476,7 @@ const SwapForm = () => {
|
|||
<span className="absolute right-3 bottom-1.5 text-xxs text-th-fgd-4">
|
||||
{outputBank
|
||||
? formatCurrencyValue(
|
||||
outputBank.uiPrice * Number(amountOutFormValue)
|
||||
outputBank.uiPrice * Number(amountOutFormValue),
|
||||
)
|
||||
: '–'}
|
||||
</span>
|
||||
|
@ -562,6 +562,7 @@ const SwapForm = () => {
|
|||
className="text-th-fgd-3"
|
||||
checked={useMargin}
|
||||
onChange={handleSetMargin}
|
||||
small
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
|
|
|
@ -166,7 +166,7 @@ const SwapFormTokenList = ({
|
|||
new PublicKey(token.address),
|
||||
outputBank.mint,
|
||||
group,
|
||||
useMargin
|
||||
useMargin,
|
||||
)
|
||||
return { ...token, ...max }
|
||||
})
|
||||
|
@ -174,7 +174,7 @@ const SwapFormTokenList = ({
|
|||
.sort((a, b) =>
|
||||
useMargin
|
||||
? Number(b.amountWithBorrow) - Number(a.amountWithBorrow)
|
||||
: Number(b.amount) - Number(a.amount)
|
||||
: Number(b.amount) - Number(a.amount),
|
||||
)
|
||||
|
||||
return filteredSortedTokens
|
||||
|
|
|
@ -36,7 +36,7 @@ const SwapHistoryTable = () => {
|
|||
const showTableView = width ? width > breakpoints.md : false
|
||||
const [preferredExplorer] = useLocalStorageState(
|
||||
PREFERRED_EXPLORER_KEY,
|
||||
EXPLORERS[0]
|
||||
EXPLORERS[0],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -56,7 +56,7 @@ const SwapHistoryTable = () => {
|
|||
actions.fetchSwapHistory(
|
||||
mangoAccountAddress,
|
||||
0,
|
||||
offset + PAGINATION_PAGE_LENGTH
|
||||
offset + PAGINATION_PAGE_LENGTH,
|
||||
)
|
||||
}, [actions, offset, mangoAccountAddress])
|
||||
|
||||
|
@ -196,7 +196,7 @@ const SwapHistoryTable = () => {
|
|||
<div className="flex items-center justify-end">
|
||||
<Tooltip
|
||||
content={`View on ${t(
|
||||
`settings:${preferredExplorer.name}`
|
||||
`settings:${preferredExplorer.name}`,
|
||||
)}`}
|
||||
placement="top-end"
|
||||
>
|
||||
|
|
|
@ -19,7 +19,7 @@ const SwapPage = () => {
|
|||
const actions = mangoStore((s) => s.actions)
|
||||
const [showSwapIntro, setShowSwapIntro] = useLocalStorage(
|
||||
SHOW_SWAP_INTRO_MODAL,
|
||||
true
|
||||
true,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue