diff --git a/components/MangoProvider.tsx b/components/MangoProvider.tsx
index 8afd42c2..674a9762 100644
--- a/components/MangoProvider.tsx
+++ b/components/MangoProvider.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect } from 'react'
+import { useEffect } from 'react'
import mangoStore from '@store/mangoStore'
import { Keypair, PublicKey } from '@solana/web3.js'
import { useRouter } from 'next/router'
@@ -15,29 +15,36 @@ const HydrateStore = () => {
const { mangoAccountPk, mangoAccountAddress } = useMangoAccount()
const connection = mangoStore((s) => s.connection)
- const fetchData = useCallback(async () => {
- await actions.fetchGroup()
- }, [])
-
useEffect(() => {
if (marketName && typeof marketName === 'string') {
set((s) => {
s.selectedMarket.name = marketName
})
}
- fetchData()
+ actions.fetchGroup()
}, [marketName])
useInterval(() => {
- fetchData()
+ actions.fetchGroup()
}, 15000)
+ // refetches open orders every 30 seconds
+ // only the selected market's open orders are updated via websocket
useInterval(() => {
if (mangoAccountAddress) {
actions.fetchOpenOrders()
}
}, 30000)
+ // refetch trade history and activity feed when switching accounts
+ useEffect(() => {
+ const actions = mangoStore.getState().actions
+ if (mangoAccountAddress) {
+ actions.fetchTradeHistory()
+ actions.fetchActivityFeed(mangoAccountAddress)
+ }
+ }, [mangoAccountAddress])
+
// 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.
// This is a hack to prevent the list from every getting empty
diff --git a/components/account/AccountChart.tsx b/components/account/AccountChart.tsx
index 6c20bb7f..cd43b70d 100644
--- a/components/account/AccountChart.tsx
+++ b/components/account/AccountChart.tsx
@@ -1,8 +1,8 @@
import { useTranslation } from 'next-i18next'
import { useMemo, useState } from 'react'
-import { PerformanceDataItem } from '@store/mangoStore'
import dynamic from 'next/dynamic'
import { formatYAxis } from 'utils/formatting'
+import { PerformanceDataItem } from 'types'
const DetailedAreaChart = dynamic(
() => import('@components/shared/DetailedAreaChart'),
{ ssr: false }
diff --git a/components/account/AccountPage.tsx b/components/account/AccountPage.tsx
index f1a5103b..0e8dace2 100644
--- a/components/account/AccountPage.tsx
+++ b/components/account/AccountPage.tsx
@@ -5,7 +5,7 @@ import {
import { useTranslation } from 'next-i18next'
import { useEffect, useMemo, useState } from 'react'
import AccountActions from './AccountActions'
-import mangoStore, { PerformanceDataItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
import { formatCurrencyValue } from '../../utils/numbers'
import FlipNumbers from 'react-flip-numbers'
import dynamic from 'next/dynamic'
@@ -43,6 +43,7 @@ import useMangoGroup from 'hooks/useMangoGroup'
import PnlHistoryModal from '@components/modals/PnlHistoryModal'
import FormatNumericValue from '@components/shared/FormatNumericValue'
import HealthBar from './HealthBar'
+import { PerformanceDataItem } from 'types'
const AccountPage = () => {
const { t } = useTranslation(['common', 'account'])
diff --git a/components/account/ActivityFeed.tsx b/components/account/ActivityFeed.tsx
index e83575aa..0a9d865f 100644
--- a/components/account/ActivityFeed.tsx
+++ b/components/account/ActivityFeed.tsx
@@ -2,7 +2,7 @@ import { EXPLORERS } from '@components/settings/PreferredExplorerSettings'
import { IconButton } from '@components/shared/Button'
import FormatNumericValue from '@components/shared/FormatNumericValue'
import { ArrowLeftIcon } from '@heroicons/react/20/solid'
-import mangoStore, { LiquidationFeedItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
import dayjs from 'dayjs'
import useLocalStorageState from 'hooks/useLocalStorageState'
import { useTranslation } from 'next-i18next'
@@ -10,6 +10,7 @@ import Image from 'next/legacy/image'
import { useState } from 'react'
import { PREFERRED_EXPLORER_KEY } from 'utils/constants'
import ActivityFeedTable from './ActivityFeedTable'
+import { LiquidationActivity } from 'types'
const ActivityFeed = () => {
const activityFeed = mangoStore((s) => s.activityFeed.feed)
@@ -38,7 +39,7 @@ const ActivityDetails = ({
activity,
setShowActivityDetail,
}: {
- activity: LiquidationFeedItem
+ activity: LiquidationActivity
setShowActivityDetail: (x: any) => void
}) => {
const { t } = useTranslation(['common', 'activity', 'settings'])
diff --git a/components/account/ActivityFeedTable.tsx b/components/account/ActivityFeedTable.tsx
index de831ad0..628254e7 100644
--- a/components/account/ActivityFeedTable.tsx
+++ b/components/account/ActivityFeedTable.tsx
@@ -12,7 +12,7 @@ import {
NoSymbolIcon,
} from '@heroicons/react/20/solid'
import { useWallet } from '@solana/wallet-adapter-react'
-import mangoStore, { LiquidationFeedItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
import dayjs from 'dayjs'
import useLocalStorageState from 'hooks/useLocalStorageState'
import useMangoAccount from 'hooks/useMangoAccount'
@@ -20,6 +20,7 @@ import { useViewport } from 'hooks/useViewport'
import { useTranslation } from 'next-i18next'
import Image from 'next/legacy/image'
import { Fragment, useCallback, useState } from 'react'
+import { ActivityFeed, isLiquidationFeedItem, LiquidationActivity } from 'types'
import { PAGINATION_PAGE_LENGTH, PREFERRED_EXPLORER_KEY } from 'utils/constants'
import { formatNumericValue } from 'utils/numbers'
import { breakpoints } from 'utils/theme'
@@ -158,8 +159,8 @@ const ActivityFeedTable = ({
activityFeed,
handleShowActivityDetails,
}: {
- activityFeed: any
- handleShowActivityDetails: (x: LiquidationFeedItem) => void
+ activityFeed: ActivityFeed[]
+ handleShowActivityDetails: (x: LiquidationActivity) => void
}) => {
const { t } = useTranslation(['common', 'activity'])
const { mangoAccountAddress } = useMangoAccount()
@@ -211,7 +212,7 @@ const ActivityFeedTable = ({
- {activityFeed.map((activity: any, index: number) => {
+ {activityFeed.map((activity, index: number) => {
const { activity_type, block_datetime } = activity
const { signature } = activity.activity_details
const isLiquidation =
@@ -227,7 +228,7 @@ const ActivityFeedTable = ({
isLiquidation ? 'cursor-pointer' : ''
}`}
onClick={
- isLiquidation
+ isLiquidationFeedItem(activity)
? () => handleShowActivityDetails(activity)
: undefined
}
diff --git a/components/modals/PnlHistoryModal.tsx b/components/modals/PnlHistoryModal.tsx
index d7d420fa..d0027b03 100644
--- a/components/modals/PnlHistoryModal.tsx
+++ b/components/modals/PnlHistoryModal.tsx
@@ -1,6 +1,6 @@
import { ModalProps } from '../../types/modal'
import Modal from '../shared/Modal'
-import mangoStore, { PerformanceDataItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
import { useTranslation } from 'next-i18next'
import { useEffect, useMemo } from 'react'
import useMangoAccount from 'hooks/useMangoAccount'
@@ -8,6 +8,7 @@ import dayjs from 'dayjs'
import Change from '@components/shared/Change'
import SheenLoader from '@components/shared/SheenLoader'
import { NoSymbolIcon } from '@heroicons/react/20/solid'
+import { PerformanceDataItem } from 'types'
interface PnlChange {
time: string
diff --git a/components/stats/MangoPerpStatsCharts.tsx b/components/stats/MangoPerpStatsCharts.tsx
index 779b73e8..79fae1ce 100644
--- a/components/stats/MangoPerpStatsCharts.tsx
+++ b/components/stats/MangoPerpStatsCharts.tsx
@@ -1,7 +1,8 @@
import { useTranslation } from 'next-i18next'
import { useMemo, useState } from 'react'
import dynamic from 'next/dynamic'
-import mangoStore, { PerpStatsItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
+import { PerpStatsItem } from 'types'
const DetailedAreaChart = dynamic(
() => import('@components/shared/DetailedAreaChart'),
{ ssr: false }
diff --git a/components/stats/PerpMarketsTable.tsx b/components/stats/PerpMarketsTable.tsx
index f67565b6..3f5543d3 100644
--- a/components/stats/PerpMarketsTable.tsx
+++ b/components/stats/PerpMarketsTable.tsx
@@ -2,7 +2,7 @@ import { PerpMarket } from '@blockworks-foundation/mango-v4'
import { useTranslation } from 'next-i18next'
import { useTheme } from 'next-themes'
import { useViewport } from '../../hooks/useViewport'
-import mangoStore, { PerpStatsItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
import { COLORS } from '../../styles/colors'
import { breakpoints } from '../../utils/theme'
import ContentBox from '../shared/ContentBox'
@@ -16,6 +16,7 @@ import { ChevronRightIcon } from '@heroicons/react/20/solid'
import FormatNumericValue from '@components/shared/FormatNumericValue'
import { getDecimalCount } from 'utils/numbers'
import Tooltip from '@components/shared/Tooltip'
+import { PerpStatsItem } from 'types'
const SimpleAreaChart = dynamic(
() => import('@components/shared/SimpleAreaChart'),
{ ssr: false }
diff --git a/components/stats/TotalDepositBorrowCharts.tsx b/components/stats/TotalDepositBorrowCharts.tsx
index cd392c5a..a558671e 100644
--- a/components/stats/TotalDepositBorrowCharts.tsx
+++ b/components/stats/TotalDepositBorrowCharts.tsx
@@ -1,10 +1,11 @@
-import mangoStore, { TokenStatsItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
import { useTranslation } from 'next-i18next'
import dynamic from 'next/dynamic'
import { useMemo, useState } from 'react'
import dayjs from 'dayjs'
import { formatYAxis } from 'utils/formatting'
import useBanksWithBalances from 'hooks/useBanksWithBalances'
+import { TokenStatsItem } from 'types'
const DetailedAreaChart = dynamic(
() => import('@components/shared/DetailedAreaChart'),
{ ssr: false }
diff --git a/components/token/ChartTabs.tsx b/components/token/ChartTabs.tsx
index df7c0d2a..cdd01330 100644
--- a/components/token/ChartTabs.tsx
+++ b/components/token/ChartTabs.tsx
@@ -1,9 +1,10 @@
import TabButtons from '@components/shared/TabButtons'
-import mangoStore, { TokenStatsItem } from '@store/mangoStore'
+import mangoStore from '@store/mangoStore'
import useMangoGroup from 'hooks/useMangoGroup'
import { useTranslation } from 'next-i18next'
import dynamic from 'next/dynamic'
import { useEffect, useMemo, useState } from 'react'
+import { TokenStatsItem } from 'types'
import { formatYAxis } from 'utils/formatting'
const DetailedAreaChart = dynamic(
() => import('@components/shared/DetailedAreaChart'),
diff --git a/components/trade/PerpSideBadge.tsx b/components/trade/PerpSideBadge.tsx
index 1aef7288..fce1c8c5 100644
--- a/components/trade/PerpSideBadge.tsx
+++ b/components/trade/PerpSideBadge.tsx
@@ -4,7 +4,7 @@ const PerpSideBadge = ({ basePosition }: { basePosition: number }) => {
return (
<>
{basePosition !== 0 ? (
- 0 ? 'long' : 'short'} />
+ 0 ? 'buy' : 'sell'} />
) : (
'--'
)}
diff --git a/store/mangoStore.ts b/store/mangoStore.ts
index af76f7ea..5c56ed37 100644
--- a/store/mangoStore.ts
+++ b/store/mangoStore.ts
@@ -40,11 +40,24 @@ import {
RPC_PROVIDER_KEY,
} from '../utils/constants'
import {
+ AccountPerformanceData,
+ ActivityFeed,
+ EmptyObject,
OrderbookL2,
+ PerformanceDataItem,
+ PerpStatsItem,
PerpTradeHistory,
SerumEvent,
SpotBalances,
SpotTradeHistory,
+ SwapHistoryItem,
+ TotalInterestDataItem,
+ TradeForm,
+ TradeHistoryApiResponseType,
+ TokenStatsItem,
+ NFT,
+ TourSettings,
+ ProfileDetails,
} from 'types'
import spotBalancesUpdater from './spotBalancesUpdater'
import { PerpMarket } from '@blockworks-foundation/mango-v4/'
@@ -100,147 +113,6 @@ const initMangoClient = (
}
let mangoGroupRetryAttempt = 0
-
-export interface TotalInterestDataItem {
- borrow_interest: number
- deposit_interest: number
- borrow_interest_usd: number
- deposit_interest_usd: number
- symbol: string
-}
-
-export interface PerformanceDataItem {
- account_equity: number
- borrow_interest_cumulative_usd: number
- deposit_interest_cumulative_usd: number
- pnl: number
- spot_value: number
- time: string
- transfer_balance: number
-}
-
-export interface DepositWithdrawFeedItem {
- activity_details: {
- block_datetime: string
- mango_account: string
- quantity: number
- signature: string
- symbol: string
- usd_equivalent: number
- wallet_pk: string
- }
- activity_type: string
- block_datetime: string
- symbol: string
-}
-
-export interface LiquidationFeedItem {
- activity_details: {
- asset_amount: number
- asset_price: number
- asset_symbol: string
- block_datetime: string
- liab_amount: number
- liab_price: number
- liab_symbol: string
- mango_account: string
- mango_group: string
- side: string
- signature: string
- }
- activity_type: string
- block_datetime: string
- symbol: string
-}
-
-export interface SwapHistoryItem {
- block_datetime: string
- mango_account: string
- signature: string
- swap_in_amount: number
- swap_in_loan: number
- swap_in_loan_origination_fee: number
- swap_in_price_usd: number
- swap_in_symbol: string
- swap_out_amount: number
- loan: number
- loan_origination_fee: number
- swap_out_price_usd: number
- swap_out_symbol: string
-}
-
-interface NFT {
- address: string
- image: string
-}
-
-export interface PerpStatsItem {
- date_hour: string
- fees_accrued: number
- funding_rate_hourly: number
- instantaneous_funding_rate: number
- mango_group: string
- market_index: number
- open_interest: number
- perp_market: string
- price: number
- stable_price: number
-}
-
-interface ProfileDetails {
- profile_image_url?: string
- profile_name: string
- trader_category: string
- wallet_pk: string
-}
-
-interface TourSettings {
- account_tour_seen: boolean
- swap_tour_seen: boolean
- trade_tour_seen: boolean
- wallet_pk: string
-}
-
-export interface TokenStatsItem {
- borrow_apr: number
- borrow_rate: number
- collected_fees: number
- date_hour: string
- deposit_apr: number
- deposit_rate: number
- mango_group: string
- price: number
- symbol: string
- token_index: number
- total_borrows: number
- total_deposits: number
-}
-
-// const defaultUserSettings = {
-// account_tour_seen: false,
-// default_language: 'English',
-// default_market: 'SOL-Perp',
-// orderbook_animation: false,
-// rpc_endpoint: 'Triton (RPC Pool)',
-// rpc_node_url: null,
-// spot_margin: false,
-// swap_tour_seen: false,
-// theme: 'Mango',
-// trade_tour_seen: false,
-// wallet_pk: '',
-// }
-
-interface TradeForm {
- side: 'buy' | 'sell'
- price: string | undefined
- baseSize: string
- quoteSize: string
- tradeType: 'Market' | 'Limit'
- postOnly: boolean
- ioc: boolean
- reduceOnly: boolean
-}
-
export const DEFAULT_TRADE_FORM: TradeForm = {
side: 'buy',
price: undefined,
@@ -254,7 +126,7 @@ export const DEFAULT_TRADE_FORM: TradeForm = {
export type MangoStore = {
activityFeed: {
- feed: Array
+ feed: Array
loading: boolean
queryParams: string
}
@@ -554,20 +426,24 @@ const mangoStore = create()(
.subtract(range, 'day')
.format('YYYY-MM-DD')}`
)
- const parsedResponse = await response.json()
- const entries: any = Object.entries(parsedResponse).sort((a, b) =>
- b[0].localeCompare(a[0])
- )
+ const parsedResponse:
+ | null
+ | EmptyObject
+ | AccountPerformanceData[] = await response.json()
- const stats = entries
- .map(([key, value]: Array<{ key: string; value: number }>) => {
- return { ...value, time: key }
+ if (parsedResponse?.length) {
+ const entries = Object.entries(parsedResponse).sort((a, b) =>
+ b[0].localeCompare(a[0])
+ )
+
+ const stats = entries.map(([key, value]) => {
+ return { ...value, time: key } as PerformanceDataItem
})
- .filter((x: string) => x)
- set((state) => {
- state.mangoAccount.performance.data = stats.reverse()
- })
+ set((state) => {
+ state.mangoAccount.performance.data = stats.reverse()
+ })
+ }
} catch (e) {
console.error('Failed to load account performance data', e)
} finally {
@@ -583,9 +459,6 @@ const mangoStore = create()(
) => {
const set = get().set
const loadedFeed = mangoStore.getState().activityFeed.feed
- const connectedMangoAccountPk = mangoStore
- .getState()
- .mangoAccount.current?.publicKey.toString()
try {
const response = await fetch(
@@ -593,36 +466,34 @@ const mangoStore = create()(
params ? params : ''
}`
)
- const parsedResponse = await response.json()
- const entries: any = Object.entries(parsedResponse).sort((a, b) =>
- b[0].localeCompare(a[0])
- )
+ const parsedResponse:
+ | null
+ | EmptyObject
+ | Array = await response.json()
- const latestFeed = entries
- .map(([key, value]: Array<{ key: string; value: number }>) => {
- return { ...value, symbol: key }
- })
- .filter((x: string) => x)
- .sort(
- (
- a: DepositWithdrawFeedItem | LiquidationFeedItem,
- b: DepositWithdrawFeedItem | LiquidationFeedItem
- ) =>
- dayjs(b.block_datetime).unix() -
- dayjs(a.block_datetime).unix()
+ if (parsedResponse?.length) {
+ const entries = Object.entries(parsedResponse).sort((a, b) =>
+ b[0].localeCompare(a[0])
)
- // only add to current feed if data request is offset and the mango account hasn't changed
- const combinedFeed =
- offset !== 0 &&
- connectedMangoAccountPk ===
- loadedFeed[0]?.activity_details?.mango_account
- ? loadedFeed.concat(latestFeed)
- : latestFeed
+ const latestFeed = entries
+ .map(([key, value]) => {
+ return { ...value, symbol: key }
+ })
+ .sort(
+ (a, b) =>
+ dayjs(b.block_datetime).unix() -
+ dayjs(a.block_datetime).unix()
+ )
- set((state) => {
- state.activityFeed.feed = combinedFeed
- })
+ // only add to current feed if data request is offset and the mango account hasn't changed
+ const combinedFeed =
+ offset !== 0 ? loadedFeed.concat(latestFeed) : latestFeed
+
+ set((state) => {
+ state.activityFeed.feed = combinedFeed
+ })
+ }
} catch (e) {
console.error('Failed to fetch account activity feed', e)
} finally {
@@ -1015,8 +886,8 @@ const mangoStore = create()(
set((s) => {
s.client = client
})
- } catch (e: any) {
- if (e.name.includes('WalletLoadError')) {
+ } catch (e) {
+ if (e instanceof Error && e.name.includes('WalletLoadError')) {
notify({
title: `${wallet.adapter.name} Error`,
type: 'error',
@@ -1118,17 +989,16 @@ const mangoStore = create()(
const response = await fetch(
`${MANGO_DATA_API_URL}/stats/trade-history?mango-account=${mangoAccountPk}&limit=${PAGINATION_PAGE_LENGTH}&offset=${offset}`
)
- const jsonResponse = await response.json()
+ const jsonResponse:
+ | null
+ | EmptyObject
+ | TradeHistoryApiResponseType = await response.json()
if (jsonResponse?.length) {
- const newHistory = jsonResponse.map(
- (h: any) => h.activity_details
- )
+ const newHistory = jsonResponse.map((h) => h.activity_details)
const history =
offset !== 0 ? loadedHistory.concat(newHistory) : newHistory
set((s) => {
- s.mangoAccount.tradeHistory.data = history?.sort(
- (x: any) => x.block_datetime
- )
+ s.mangoAccount.tradeHistory.data = history
})
} else {
set((s) => {
diff --git a/store/perpPositionsUpdater.ts b/store/perpPositionsUpdater.ts
index 61e0f5ed..35a765b4 100644
--- a/store/perpPositionsUpdater.ts
+++ b/store/perpPositionsUpdater.ts
@@ -1,10 +1,4 @@
-import {
- Group,
- MangoAccount,
- PerpMarket,
- PerpPosition,
- toUiI80F48,
-} from '@blockworks-foundation/mango-v4'
+import { PerpPosition } from '@blockworks-foundation/mango-v4'
import mangoStore from './mangoStore'
const perpPositionsUpdater = (_newState: any, _prevState: any) => {
diff --git a/types/index.ts b/types/index.ts
index 7f216d29..23641962 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -1,22 +1,8 @@
import { PerpMarket, Serum3Market } from '@blockworks-foundation/mango-v4'
import { Modify } from '@blockworks-foundation/mango-v4'
-import { BN } from '@project-serum/anchor'
import { Event } from '@project-serum/serum/lib/queue'
-export interface ChartTradeType {
- market: string
- size: number
- quantity: number | any
- price: number | any
- orderId: string
- time: number
- side: string
- takerSide: any
- feeCost: number
- marketAddress: string
- timestamp: BN
-}
-
+export type EmptyObject = { [K in keyof T]?: never }
export interface OrderbookL2 {
bids: number[][]
asks: number[][]
@@ -79,3 +65,165 @@ export type SerumEvent = Modify<
>
export type GenericMarket = Serum3Market | PerpMarket
+
+export type TradeHistoryApiResponseType = Array<{
+ trade_type: string
+ block_datetime: string
+ activity_details: PerpTradeHistory | SpotTradeHistory
+}>
+
+export type AccountPerformanceData = {
+ [date: string]: {
+ account_equity: number
+ pnl: number
+ spot_value: number
+ transfer_balance: number
+ deposit_interest_cumulative_usd: number
+ borrow_interest_cumulative_usd: number
+ spot_volume_usd: number
+ }
+}
+
+export interface TotalInterestDataItem {
+ borrow_interest: number
+ deposit_interest: number
+ borrow_interest_usd: number
+ deposit_interest_usd: number
+ symbol: string
+}
+
+export interface PerformanceDataItem {
+ account_equity: number
+ borrow_interest_cumulative_usd: number
+ deposit_interest_cumulative_usd: number
+ pnl: number
+ spot_value: number
+ time: string
+ transfer_balance: number
+}
+
+export interface DepositWithdrawFeedItem {
+ block_datetime: string
+ mango_account: string
+ quantity: number
+ signature: string
+ symbol: string
+ usd_equivalent: number
+ wallet_pk: string
+}
+
+export interface LiquidationFeedItem {
+ asset_amount: number
+ asset_price: number
+ asset_symbol: string
+ block_datetime: string
+ liab_amount: number
+ liab_price: number
+ liab_symbol: string
+ mango_account: string
+ mango_group: string
+ side: string
+ signature: string
+}
+
+export interface LiquidationActivity {
+ activity_details: LiquidationFeedItem
+ block_datetime: string
+ activity_type: string
+ symbol: string
+}
+
+export function isLiquidationFeedItem(
+ item: ActivityFeed
+): item is LiquidationActivity {
+ if (item.activity_type.includes('liquidate')) {
+ return true
+ }
+ return false
+}
+
+export interface SwapHistoryItem {
+ block_datetime: string
+ mango_account: string
+ signature: string
+ swap_in_amount: number
+ swap_in_loan: number
+ swap_in_loan_origination_fee: number
+ swap_in_price_usd: number
+ swap_in_symbol: string
+ swap_out_amount: number
+ loan: number
+ loan_origination_fee: number
+ swap_out_price_usd: number
+ swap_out_symbol: string
+}
+
+export interface NFT {
+ address: string
+ image: string
+}
+
+export interface PerpStatsItem {
+ date_hour: string
+ fees_accrued: number
+ funding_rate_hourly: number
+ instantaneous_funding_rate: number
+ mango_group: string
+ market_index: number
+ open_interest: number
+ perp_market: string
+ price: number
+ stable_price: number
+}
+
+export type ActivityFeed = {
+ activity_type: string
+ block_datetime: string
+ symbol: string
+ activity_details:
+ | DepositWithdrawFeedItem
+ | LiquidationFeedItem
+ | SwapHistoryItem
+ | PerpTradeHistory
+ | SpotTradeHistory
+}
+
+export interface ProfileDetails {
+ profile_image_url?: string
+ profile_name: string
+ trader_category: string
+ wallet_pk: string
+}
+
+export interface TourSettings {
+ account_tour_seen: boolean
+ swap_tour_seen: boolean
+ trade_tour_seen: boolean
+ wallet_pk: string
+}
+
+export interface TokenStatsItem {
+ borrow_apr: number
+ borrow_rate: number
+ collected_fees: number
+ date_hour: string
+ deposit_apr: number
+ deposit_rate: number
+ mango_group: string
+ price: number
+ symbol: string
+ token_index: number
+ total_borrows: number
+ total_deposits: number
+}
+
+export interface TradeForm {
+ side: 'buy' | 'sell'
+ price: string | undefined
+ baseSize: string
+ quoteSize: string
+ tradeType: 'Market' | 'Limit'
+ postOnly: boolean
+ ioc: boolean
+ reduceOnly: boolean
+}