diff --git a/package.json b/package.json
index e3ccb61c..f22f8ef9 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"@cosmjs/cosmwasm-stargate": "^0.30.1",
"@cosmjs/stargate": "^0.30.1",
"@marsprotocol/wallet-connector": "^1.5.8",
- "@sentry/nextjs": "^7.51.0",
+ "@sentry/nextjs": "^7.51.2",
"@tanstack/react-table": "^8.9.1",
"@tippyjs/react": "^4.2.6",
"bignumber.js": "^9.1.1",
@@ -30,14 +30,14 @@
"react-spring": "^9.7.1",
"react-toastify": "^9.1.2",
"react-use-clipboard": "^1.0.9",
- "recharts": "^2.5.0",
+ "recharts": "^2.6.0",
"swr": "^2.1.5",
"tailwind-scrollbar-hide": "^1.1.7",
"zustand": "^4.3.8"
},
"devDependencies": {
- "@svgr/webpack": "^7.0.0",
- "@types/node": "^20.1.0",
+ "@svgr/webpack": "^8.0.1",
+ "@types/node": "^20.1.1",
"@types/react": "18.2.6",
"@types/react-dom": "18.2.4",
"autoprefixer": "^10.4.14",
diff --git a/src/components/Account/AccountComposition.tsx b/src/components/Account/AccountComposition.tsx
index 4cc7531c..17ddfe3b 100644
--- a/src/components/Account/AccountComposition.tsx
+++ b/src/components/Account/AccountComposition.tsx
@@ -3,14 +3,15 @@ import BigNumber from 'bignumber.js'
import classNames from 'classnames'
import DisplayCurrency from 'components/DisplayCurrency'
+import { FormattedNumber } from 'components/FormattedNumber'
import { ArrowRight } from 'components/Icons'
import Text from 'components/Text'
import useStore from 'store'
import {
calculateAccountApr,
- calculateAccountBalance,
calculateAccountBorrowRate,
calculateAccountDebt,
+ calculateAccountDeposits,
calculateAccountPnL,
} from 'utils/accounts'
import { BN } from 'utils/helpers'
@@ -25,12 +26,14 @@ interface ItemProps {
current: BigNumber
change: BigNumber
className?: string
+ isBadIncrease?: boolean
+ isPercentage?: boolean
}
export default function AccountComposition(props: Props) {
const prices = useStore((s) => s.prices)
- const balance = calculateAccountBalance(props.account, prices)
- const balanceChange = props.change ? calculateAccountBalance(props.change, prices) : BN(0)
+ const balance = calculateAccountDeposits(props.account, prices)
+ const balanceChange = props.change ? calculateAccountDeposits(props.change, prices) : BN(0)
const debtBalance = calculateAccountDebt(props.account, prices)
const debtBalanceChange = props.change ? calculateAccountDebt(props.change, prices) : BN(0)
const pnL = calculateAccountPnL(props.account, prices)
@@ -53,6 +56,7 @@ export default function AccountComposition(props: Props) {
current={debtBalance}
change={debtBalance.plus(debtBalanceChange)}
className='pb-3'
+ isBadIncrease
/>
-
-
+
+
)
}
function Item(props: ItemProps) {
const baseCurrency = useStore((s) => s.baseCurrency)
- const increase = props.current.isLessThan(props.change)
+ const increase = props.isBadIncrease
+ ? props.current.isGreaterThan(props.change)
+ : props.current.isLessThan(props.change)
return (
@@ -77,19 +89,35 @@ function Item(props: ItemProps) {
-
+ {props.isPercentage ? (
+
+ ) : (
+
+ )}
{!props.current.isEqualTo(props.change) && (
<>
-
+ {props.isPercentage ? (
+
+ ) : (
+
+ )}
>
)}
diff --git a/src/components/Account/AccountList.tsx b/src/components/Account/AccountList.tsx
index e97d8507..c7bd4706 100644
--- a/src/components/Account/AccountList.tsx
+++ b/src/components/Account/AccountList.tsx
@@ -13,7 +13,7 @@ import SwitchWithLabel from 'components/SwitchWithLabel'
import Text from 'components/Text'
import useToggle from 'hooks/useToggle'
import useStore from 'store'
-import { calculateAccountBalance } from 'utils/accounts'
+import { calculateAccountDeposits } from 'utils/accounts'
import { hardcodedFee } from 'utils/contants'
import { BN } from 'utils/helpers'
import useParams, { getRoute } from 'utils/route'
@@ -41,7 +41,7 @@ export default function AccountList(props: Props) {
const accountSelected = !!selectedAccount && !isNaN(Number(selectedAccount))
const selectedAccountDetails = props.accounts.find((account) => account.id === selectedAccount)
const selectedAccountBalance = selectedAccountDetails
- ? calculateAccountBalance(selectedAccountDetails, prices)
+ ? calculateAccountDeposits(selectedAccountDetails, prices)
: BN(0)
async function deleteAccountHandler() {
@@ -69,7 +69,7 @@ export default function AccountList(props: Props) {
return (
{props.accounts.map((account) => {
- const positionBalance = calculateAccountBalance(account, prices)
+ const positionBalance = calculateAccountDeposits(account, prices)
const isActive = selectedAccount === account.id
return (
diff --git a/src/components/Account/AccountMenu.tsx b/src/components/Account/AccountMenu.tsx
index bdb14314..a2aa2da8 100644
--- a/src/components/Account/AccountMenu.tsx
+++ b/src/components/Account/AccountMenu.tsx
@@ -9,6 +9,7 @@ interface Props {
}
async function Content(props: Props) {
+ if (props.params.address === undefined) return null
const accounts = await getAccounts(props.params.address)
return
}
diff --git a/src/components/Account/AccountSummary.tsx b/src/components/Account/AccountSummary.tsx
index 3a974dd2..93768596 100644
--- a/src/components/Account/AccountSummary.tsx
+++ b/src/components/Account/AccountSummary.tsx
@@ -8,7 +8,7 @@ import DisplayCurrency from 'components/DisplayCurrency'
import { ArrowChartLineUp } from 'components/Icons'
import Text from 'components/Text'
import useStore from 'store'
-import { calculateAccountBalance } from 'utils/accounts'
+import { calculateAccountDeposits } from 'utils/accounts'
import { BN } from 'utils/helpers'
interface Props {
@@ -19,7 +19,7 @@ interface Props {
export default function AccountSummary(props: Props) {
const prices = useStore((s) => s.prices)
const baseCurrency = useStore((s) => s.baseCurrency)
- const accountBalance = props.account ? calculateAccountBalance(props.account, prices) : BN(0)
+ const accountBalance = props.account ? calculateAccountDeposits(props.account, prices) : BN(0)
if (!props.account) return null
return (
diff --git a/src/components/Divider.tsx b/src/components/Divider.tsx
index 72007fb6..cd57f1df 100644
--- a/src/components/Divider.tsx
+++ b/src/components/Divider.tsx
@@ -1,10 +1,13 @@
+import classNames from 'classnames'
+
interface Props {
orientation?: 'horizontal' | 'vertical'
+ className?: string
}
export default function Divider(props: Props) {
if (props.orientation === 'vertical') {
- return
+ return
}
- return
+ return
}
diff --git a/src/components/Modals/BorrowModal.tsx b/src/components/Modals/BorrowModal.tsx
index 00a26129..c2cd3682 100644
--- a/src/components/Modals/BorrowModal.tsx
+++ b/src/components/Modals/BorrowModal.tsx
@@ -1,5 +1,7 @@
+'use client'
+
import Image from 'next/image'
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
import AccountSummary from 'components/Account/AccountSummary'
import { Button } from 'components/Button'
@@ -7,16 +9,17 @@ import Card from 'components/Card'
import Divider from 'components/Divider'
import { ArrowRight } from 'components/Icons'
import Modal from 'components/Modal'
+import Select from 'components/Select/Select'
import Text from 'components/Text'
import TitleAndSubCell from 'components/TitleAndSubCell'
import TokenInputWithSlider from 'components/TokenInputWithSlider'
import { ASSETS } from 'constants/assets'
import useCurrentAccount from 'hooks/useCurrentAccount'
+import useToggle from 'hooks/useToggle'
import useStore from 'store'
import { hardcodedFee } from 'utils/contants'
import { formatPercent, formatValue } from 'utils/formatters'
import { BN } from 'utils/helpers'
-import useParams from 'utils/route'
function getDebtAmount(modal: BorrowModal | null) {
if (!(modal?.marketData as BorrowAssetActive)?.debt) return '0'
@@ -29,46 +32,57 @@ function getAssetLogo(modal: BorrowModal | null) {
}
export default function BorrowModal() {
- const params = useParams()
const currentAccount = useCurrentAccount()
const [percentage, setPercentage] = useState(0)
const [amount, setAmount] = useState(BN(0))
- const [selectedAccount, setSelectedAccount] = useState(params.accountId)
+ const [change, setChange] = useState
()
+ const [selectedAccount, setSelectedAccount] = useState(currentAccount)
+ const [isConfirming, setIsConfirming] = useToggle()
const modal = useStore((s) => s.borrowModal)
const borrow = useStore((s) => s.borrow)
const repay = useStore((s) => s.repay)
const asset = modal?.asset ?? ASSETS[0]
- const accounts = useStore((s) => s.accounts)?.map((account) => {
- return account.id
+ const accounts = useStore((s) => s.accounts)
+ const accountOptions = accounts?.map((account) => {
+ return { value: account.id, label: `Account ${account.id}` }
})
+ const isRepay = modal?.isRepay ?? false
- function onAccountSelect(accountId: string) {
- setSelectedAccount(accountId)
+ function resetState() {
+ setAmount(BN(0))
+ setPercentage(0)
+ setIsConfirming(false)
}
- function onConfirmClick() {
+ async function onConfirmClick() {
if (!modal?.asset) return
- if (modal.isRepay) {
- repay({
+ setIsConfirming(true)
+ let result
+ if (isRepay) {
+ result = await repay({
fee: hardcodedFee,
- accountId: selectedAccount,
+ accountId: selectedAccount?.id ?? '0',
coin: { denom: modal.asset.denom, amount: amount.toString() },
accountBalance: percentage === 100,
})
- return
+ } else {
+ result = await borrow({
+ fee: hardcodedFee,
+ accountId: selectedAccount?.id ?? '0',
+ coin: { denom: modal.asset.denom, amount: amount.toString() },
+ })
}
- borrow({
- fee: hardcodedFee,
- accountId: selectedAccount,
- coin: { denom: modal.asset.denom, amount: amount.toString() },
- })
+ setIsConfirming(false)
+ if (result) {
+ resetState()
+ useStore.setState({ borrowModal: null })
+ }
}
function onClose() {
+ resetState()
useStore.setState({ borrowModal: null })
- setAmount(BN(0))
- setPercentage(0)
}
const liquidityAmountString = formatValue(modal?.marketData?.liquidity?.amount || 0, {
@@ -81,7 +95,31 @@ export default function BorrowModal() {
decimals: 6,
})
- const max = BN(modal?.isRepay ? getDebtAmount(modal) : liquidityAmountString)
+ const max = BN(isRepay ? getDebtAmount(modal) : modal?.marketData?.liquidity?.amount ?? '0')
+
+ useEffect(() => {
+ if (!selectedAccount)
+ setSelectedAccount(currentAccount)
+ }, [selectedAccount, currentAccount])
+
+ useEffect(() => {
+ if (!modal?.asset) return
+
+ setChange({
+ deposits: [
+ {
+ amount: isRepay ? BN(0).minus(amount).toString() : BN(0).plus(amount).toString(),
+ denom: modal.asset.denom,
+ },
+ ],
+ debts: [
+ {
+ amount: isRepay ? BN(0).minus(amount).toString() : BN(0).plus(amount).toString(),
+ denom: modal.asset.denom,
+ },
+ ],
+ })
+ }, [amount, modal?.asset, currentAccount, isRepay])
return (
{getAssetLogo(modal)}
- {modal?.isRepay ? 'Repay' : 'Borrow'} {asset.symbol}
+ {isRepay ? 'Repay' : 'Borrow'} {asset.symbol}
}
@@ -119,39 +157,43 @@ export default function BorrowModal() {
- {
- setAmount(val)
- }}
- amount={amount}
- max={max}
- />
-
- {modal?.isRepay ? 'Repay for' : 'Borrow to'}
-
+
+
+
+
+ {isRepay ? 'Repay for' : 'Borrow to'}
+
+
+
+
}
/>
-
+
)
diff --git a/src/components/Modals/FundAndWithdrawModal.tsx b/src/components/Modals/FundAndWithdrawModal.tsx
index e87f1e62..4d3430f5 100644
--- a/src/components/Modals/FundAndWithdrawModal.tsx
+++ b/src/components/Modals/FundAndWithdrawModal.tsx
@@ -19,7 +19,7 @@ import { BN } from 'utils/helpers'
export default function FundAndWithdrawModal() {
const currentAccount = useCurrentAccount()
- const modal = useStore((s) => s.fundAndWithdrawModal)
+ const modal = useStore
((s) => s.fundAndWithdrawModal)
const baseCurrency = useStore((s) => s.baseCurrency)
const withdraw = useStore((s) => s.withdraw)
const deposit = useStore((s) => s.deposit)
diff --git a/src/components/Portfolio/AccountOverview.tsx b/src/components/Portfolio/AccountOverview.tsx
index 5b77665e..338d2a00 100644
--- a/src/components/Portfolio/AccountOverview.tsx
+++ b/src/components/Portfolio/AccountOverview.tsx
@@ -1,6 +1,7 @@
import classNames from 'classnames'
import { Suspense } from 'react'
+import AccountComposition from 'components/Account/AccountComposition'
import Card from 'components/Card'
import Loading from 'components/Loading'
import Text from 'components/Text'
@@ -8,8 +9,6 @@ import { getAccounts } from 'utils/api'
async function Content(props: PageProps) {
const address = props.params.address
- const currentAccount = props.params.accountId
- const hasAccount = !isNaN(Number(currentAccount))
const account = await getAccounts(address)
if (!address) {
@@ -27,7 +26,9 @@ async function Content(props: PageProps) {
}
return (
-
+
{account.map((account: Account, index: number) => (
- {hasAccount && currentAccount === account.id ? (
- Current Account
- ) : (
- Account details
- )}
+
))}
@@ -49,16 +46,14 @@ async function Content(props: PageProps) {
function Fallback() {
const cardCount = 3
return (
-
+
{Array.from({ length: cardCount }, (_, i) => (
- Account
- >
- }
+ title='Account'
contentClassName='px-4 py-6'
>
diff --git a/src/components/Select/Option.tsx b/src/components/Select/Option.tsx
index 35033aac..87cb3f94 100644
--- a/src/components/Select/Option.tsx
+++ b/src/components/Select/Option.tsx
@@ -73,13 +73,29 @@ export default function Option(props: Props) {
const label = props.label
if (props.isDisplay) {
- return {label}
+ return (
+
+ {label}
+
+
+
+
+ )
}
return (
props?.onClick && props.onClick(props.value)}
diff --git a/src/components/Select/Select.tsx b/src/components/Select/Select.tsx
index a89a9256..7027a616 100644
--- a/src/components/Select/Select.tsx
+++ b/src/components/Select/Select.tsx
@@ -1,7 +1,7 @@
'use client'
import classNames from 'classnames'
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
import { ChevronDown } from 'components/Icons'
import Overlay from 'components/Overlay'
@@ -20,9 +20,8 @@ interface Props {
export default function Select(props: Props) {
const [value, setValue] = useState(props.defaultValue)
-
const selectedOption = value
- ? props.options.find((option) => option?.value || option?.denom === value)
+ ? props.options.find((option) => option?.value === value || option?.denom === value)
: null
const [selected, setSelected] = useState