feat: refactored the toast responses (#442)
* feat: refactored the toast responses * fix: fixed the map return * feat: added a recent transaction center * tidy: removed logs * fix: fixed autolend * feat: added global lending on first account funding * fix: added endOfLine setting * feat: added eslint warnings for lineEnds * fix: made the vault message generic
This commit is contained in:
parent
7b7c25a07a
commit
609be9eb64
@ -1,6 +1,7 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals",
|
||||
"rules": {
|
||||
"linebreak-style": ["warn", "unix"],
|
||||
"sort-imports": [
|
||||
"warn",
|
||||
{
|
||||
|
@ -3,5 +3,6 @@
|
||||
"jsxSingleQuote": true,
|
||||
"semi": false,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "all"
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import classNames from 'classnames'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import DepositCapMessage from 'components/DepositCapMessage'
|
||||
@ -8,8 +8,11 @@ import SwitchAutoLend from 'components/Switch/SwitchAutoLend'
|
||||
import Text from 'components/Text'
|
||||
import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
|
||||
import WalletBridges from 'components/Wallet/WalletBridges'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LEND_ASSETS_KEY } from 'constants/localStore'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAutoLend from 'hooks/useAutoLend'
|
||||
import useLocalStorage from 'hooks/useLocalStorage'
|
||||
import useMarketAssets from 'hooks/useMarketAssets'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
@ -31,8 +34,12 @@ interface Props {
|
||||
|
||||
export default function AccountFundContent(props: Props) {
|
||||
const deposit = useStore((s) => s.deposit)
|
||||
const accounts = useStore((s) => s.accounts)
|
||||
const walletAssetModal = useStore((s) => s.walletAssetsModal)
|
||||
|
||||
const [lendAssets, setLendAssets] = useLocalStorage<boolean>(
|
||||
LEND_ASSETS_KEY,
|
||||
DEFAULT_SETTINGS.lendAssets,
|
||||
)
|
||||
const [isFunding, setIsFunding] = useToggle(false)
|
||||
const [fundingAssets, setFundingAssets] = useState<BNCoin[]>([])
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
@ -124,6 +131,10 @@ export default function AccountFundContent(props: Props) {
|
||||
toggleIsLending(autoLendEnabledAccountIds.includes(props.accountId))
|
||||
}, [props.accountId, autoLendEnabledAccountIds, toggleIsLending])
|
||||
|
||||
useEffect(() => {
|
||||
if (accounts?.length === 1 && isLending && !lendAssets) setLendAssets(true)
|
||||
}, [isLending, accounts, lendAssets, setLendAssets])
|
||||
|
||||
const depositCapReachedCoins = useMemo(() => {
|
||||
const depositCapReachedCoins: BNCoin[] = []
|
||||
fundingAssets.forEach((asset) => {
|
||||
@ -180,7 +191,7 @@ export default function AccountFundContent(props: Props) {
|
||||
<DepositCapMessage
|
||||
action='fund'
|
||||
coins={depositCapReachedCoins}
|
||||
className='pr-4 py-2 mt-4'
|
||||
className='py-2 pr-4 mt-4'
|
||||
showIcon
|
||||
/>
|
||||
<SwitchAutoLend
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
import AccountFundContent from 'components/Account/AccountFund/AccountFundContent'
|
||||
@ -17,8 +17,8 @@ export default function AccountFundFullPage() {
|
||||
const [selectedAccountId, setSelectedAccountId] = useState<null | string>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (accounts && !selectedAccountId && accountId)
|
||||
setSelectedAccountId(currentAccount?.id ?? accountId)
|
||||
if (accounts && !selectedAccountId && accountId) setSelectedAccountId(accountId)
|
||||
if (accountId && selectedAccountId !== accountId) setSelectedAccountId(accountId)
|
||||
}, [accounts, selectedAccountId, accountId, currentAccount])
|
||||
|
||||
if (!selectedAccountId || !address) return null
|
||||
|
@ -121,7 +121,7 @@ function BorrowModal(props: Props) {
|
||||
simulateRepay(repayCoin)
|
||||
}
|
||||
},
|
||||
[asset, amount, isRepay, simulateRepay],
|
||||
[asset, amount, isRepay, simulateRepay, modal],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@ -145,7 +145,7 @@ function BorrowModal(props: Props) {
|
||||
)
|
||||
|
||||
setMax(BigNumber.min(maxBorrowAmount, modal.marketData?.liquidity?.amount || 0))
|
||||
}, [account, isRepay, modal, asset.denom, computeMaxBorrowAmount, borrowToWallet])
|
||||
}, [account, isRepay, modal, asset.denom, computeMaxBorrowAmount, borrowToWallet, apr])
|
||||
|
||||
useEffect(() => {
|
||||
if (amount.isGreaterThan(max)) {
|
||||
|
@ -149,6 +149,8 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||
const isSuccess = await depositIntoVault({
|
||||
accountId: updatedAccount.id,
|
||||
actions: props.depositActions,
|
||||
deposits: props.deposits,
|
||||
borrowings: props.borrowings,
|
||||
})
|
||||
setIsConfirming(false)
|
||||
if (isSuccess) {
|
||||
@ -237,4 +239,4 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import Button from 'components/Button'
|
||||
import DepositCapMessage from 'components/DepositCapMessage'
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import Divider from 'components/Divider'
|
||||
import { Gauge } from 'components/Gauge'
|
||||
import { ArrowRight, ExclamationMarkCircled } from 'components/Icons'
|
||||
@ -11,14 +11,13 @@ import Slider from 'components/Slider'
|
||||
import Switch from 'components/Switch'
|
||||
import Text from 'components/Text'
|
||||
import TokenInput from 'components/TokenInput'
|
||||
import { ASSETS } from 'constants/assets'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { accumulateAmounts } from 'utils/accounts'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BN, getValueFromBNCoins } from 'utils/helpers'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
|
||||
interface Props {
|
||||
deposits: BNCoin[]
|
||||
@ -36,7 +35,6 @@ interface Props {
|
||||
export default function VaultDeposit(props: Props) {
|
||||
const { deposits, primaryAsset, secondaryAsset, account, onChangeDeposits, displayCurrency } =
|
||||
props
|
||||
const displayCurrencyAsset = ASSETS.find(byDenom(displayCurrency)) ?? ASSETS[0]
|
||||
const [availablePrimaryAmount, availableSecondaryAmount] = useMemo(
|
||||
() => [
|
||||
accumulateAmounts(primaryAsset.denom, [...account.deposits, ...account.lends]),
|
||||
@ -160,7 +158,7 @@ export default function VaultDeposit(props: Props) {
|
||||
|
||||
return (
|
||||
<div className='flex flex-col'>
|
||||
<div className='flex gap-4 pl-3 p-4'>
|
||||
<div className='flex gap-4 p-4 pl-3'>
|
||||
<div className='flex flex-col items-center justify-between gap-1 pb-[30px] pt-2'>
|
||||
<Gauge
|
||||
percentage={primaryValuePercentage}
|
||||
|
@ -1,23 +1,48 @@
|
||||
import classNames from 'classnames'
|
||||
import { ReactNode } from 'react'
|
||||
import { toast as createToast, Slide, ToastContainer } from 'react-toastify'
|
||||
import { mutate } from 'swr'
|
||||
|
||||
import { CheckCircled, Cross, CrossCircled, ExternalLink } from 'components/Icons'
|
||||
import Text from 'components/Text'
|
||||
import { TextLink } from 'components/TextLink'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { EXPLORER_NAME, EXPLORER_TX_URL } from 'constants/explorer'
|
||||
import { REDUCE_MOTION_KEY } from 'constants/localStore'
|
||||
import useLocalStorage from 'hooks/useLocalStorage'
|
||||
import useTransactionStore from 'hooks/useTransactionStore'
|
||||
import useStore from 'store'
|
||||
import { formatAmountWithSymbol } from 'utils/formatters'
|
||||
|
||||
import { TextLink } from './TextLink'
|
||||
export function generateToastContent(content: ToastSuccess['content']): ReactNode {
|
||||
return content.map((item, index) => (
|
||||
<div className='flex flex-wrap w-full' key={index}>
|
||||
{item.coins.length > 0 && (
|
||||
<>
|
||||
<Text size='sm' className='w-full mb-1 text-white'>
|
||||
{item.text}
|
||||
</Text>
|
||||
<ul className='flex flex-wrap w-full gap-1 p-1 pl-4 list-disc'>
|
||||
{item.coins.map((coin) => (
|
||||
<li className='w-full p-0 text-sm text-white' key={coin.denom}>
|
||||
{formatAmountWithSymbol(coin)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
|
||||
export default function Toaster() {
|
||||
const [reduceMotion] = useLocalStorage<boolean>(REDUCE_MOTION_KEY, DEFAULT_SETTINGS.reduceMotion)
|
||||
const toast = useStore((s) => s.toast)
|
||||
const isError = toast?.isError
|
||||
const { addTransaction } = useTransactionStore()
|
||||
|
||||
if (toast) {
|
||||
if (!isError) addTransaction(toast)
|
||||
const Msg = () => (
|
||||
<div
|
||||
className={classNames(
|
||||
@ -38,26 +63,33 @@ export default function Toaster() {
|
||||
isError ? 'text-error' : 'text-success',
|
||||
)}
|
||||
>
|
||||
{toast.title ? toast.title : isError ? 'Error' : 'Success'}
|
||||
{isError ? (toast.title ? toast.title : 'Error') : 'Success'}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Text size='sm' className='font-bold text-white'>
|
||||
{toast.message}
|
||||
</Text>
|
||||
{!isError && toast.accountId && (
|
||||
<Text className='mb-1 font-bold text-white'>{`Credit Account ${toast.accountId}`}</Text>
|
||||
)}
|
||||
{toast.message && (
|
||||
<Text size='sm' className='text-white'>
|
||||
{toast.message}
|
||||
</Text>
|
||||
)}
|
||||
{!isError && toast.content?.length > 0 && generateToastContent(toast.content)}
|
||||
{toast.hash && (
|
||||
<TextLink
|
||||
href={`${EXPLORER_TX_URL}${toast.hash}`}
|
||||
target='_blank'
|
||||
className={classNames(
|
||||
'leading-4 underline mt-4 hover:no-underline hover:text-white',
|
||||
isError ? 'text-error' : 'text-success',
|
||||
)}
|
||||
title={`View on ${EXPLORER_NAME}`}
|
||||
>
|
||||
{`View on ${EXPLORER_NAME}`}
|
||||
<ExternalLink className='-mt-0.5 ml-2 inline w-3.5' />
|
||||
</TextLink>
|
||||
<div className='w-full'>
|
||||
<TextLink
|
||||
href={`${EXPLORER_TX_URL}${toast.hash}`}
|
||||
target='_blank'
|
||||
className={classNames(
|
||||
'leading-4 underline mt-4 hover:no-underline hover:text-white',
|
||||
isError ? 'text-error' : 'text-success',
|
||||
)}
|
||||
title={`View on ${EXPLORER_NAME}`}
|
||||
>
|
||||
{`View on ${EXPLORER_NAME}`}
|
||||
<ExternalLink className='-mt-0.5 ml-2 inline w-3.5' />
|
||||
</TextLink>
|
||||
</div>
|
||||
)}
|
||||
<div className='absolute right-6 top-8 '>
|
||||
<Cross className={classNames('h-2 w-2', isError ? 'text-error' : 'text-success')} />
|
||||
|
81
src/components/Wallet/RecentTransactions.tsx
Normal file
81
src/components/Wallet/RecentTransactions.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import classNames from 'classnames'
|
||||
import moment from 'moment'
|
||||
|
||||
import Card from 'components/Card'
|
||||
import Divider from 'components/Divider'
|
||||
import Text from 'components/Text'
|
||||
import { TextLink } from 'components/TextLink'
|
||||
import { generateToastContent } from 'components/Toaster'
|
||||
import { EXPLORER_TX_URL } from 'constants/explorer'
|
||||
import { TRANSACTIONS_KEY } from 'constants/localStore'
|
||||
import useLocalStorage from 'hooks/useLocalStorage'
|
||||
import useStore from 'store'
|
||||
|
||||
export default function RecentTransactions() {
|
||||
const address = useStore((s) => s.address)
|
||||
const [transactions, setTransactions] = useLocalStorage<ToastStore>(TRANSACTIONS_KEY, {
|
||||
recent: [],
|
||||
})
|
||||
const recentTransactions = transactions.recent
|
||||
.filter((tx) => tx.address === address)
|
||||
.sort((a, b) => (a.timestamp > b.timestamp ? -1 : 1))
|
||||
return (
|
||||
<div className='flex flex-col w-full gap-2 pb-4'>
|
||||
<Divider className='mb-2' />
|
||||
<Text size='sm' uppercase className='w-full text-center text-white/70'>
|
||||
Recent Transactions
|
||||
</Text>
|
||||
{recentTransactions.length === 0 ? (
|
||||
<Text size='sm' className='w-full pt-2 text-center text-white'>
|
||||
No recent transactions
|
||||
</Text>
|
||||
) : (
|
||||
<>
|
||||
<div className='px-4 py-2 max-h-[400px] overflow-y-scroll scrollbar-hide'>
|
||||
<div className='flex flex-col w-full gap-2'>
|
||||
{recentTransactions.map((tx) => {
|
||||
const { accountId, hash, content, message, timestamp } = tx
|
||||
return (
|
||||
<Card
|
||||
className={classNames(
|
||||
hash &&
|
||||
'transitions-color duration-300 hover:cursor-pointer hover:bg-white/5',
|
||||
)}
|
||||
contentClassName='p-4'
|
||||
onClick={() => {
|
||||
if (hash) window.open(`${EXPLORER_TX_URL}${hash}`, '_blank')
|
||||
}}
|
||||
key={hash}
|
||||
>
|
||||
<div className='flex items-start justify-between w-full pb-2'>
|
||||
<Text className='flex font-bold'>Credit Account {accountId}</Text>
|
||||
<Text size='sm' className='text-white/70'>
|
||||
{moment.unix(timestamp).format('lll')}
|
||||
</Text>
|
||||
</div>
|
||||
{message && (
|
||||
<Text size='sm' className='w-full text-white'>
|
||||
{message}
|
||||
</Text>
|
||||
)}
|
||||
{content?.length > 0 && generateToastContent(content)}
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className='w-full pr-4 text-right'>
|
||||
<TextLink
|
||||
onClick={() => {
|
||||
setTransactions({ recent: [] })
|
||||
}}
|
||||
className='underline text-white/70 hover:no-underline'
|
||||
>
|
||||
Clear all Transactions
|
||||
</TextLink>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
@ -11,6 +11,7 @@ import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import { Check, Copy, ExternalLink, Osmo } from 'components/Icons'
|
||||
import Overlay from 'components/Overlay'
|
||||
import Text from 'components/Text'
|
||||
import RecentTransactions from 'components/Wallet/RecentTransactions'
|
||||
import { CHAINS } from 'constants/chains'
|
||||
import { IS_TESTNET } from 'constants/env'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
@ -171,6 +172,7 @@ export default function WalletConnectedButton() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<RecentTransactions />
|
||||
</Overlay>
|
||||
</div>
|
||||
)
|
||||
|
@ -7,3 +7,4 @@ export const AUTO_LEND_ENABLED_ACCOUNT_IDS_KEY = 'autoLendEnabledAccountIds'
|
||||
export const SLIPPAGE_KEY = 'slippage'
|
||||
export const TERMS_OF_SERVICE_KEY = 'termsOfService'
|
||||
export const TUTORIAL_KEY = 'tutorial'
|
||||
export const TRANSACTIONS_KEY = 'transactions'
|
||||
|
@ -40,6 +40,7 @@ export default function useAutoLend(): {
|
||||
const setOfAccountIds = new Set(autoLendEnabledAccountIds)
|
||||
|
||||
if (!setOfAccountIds.has(accountId)) setOfAccountIds.add(accountId)
|
||||
setAutoLendEnabledAccountIds(Array.from(setOfAccountIds))
|
||||
}
|
||||
|
||||
return {
|
||||
|
21
src/hooks/useTransactionStore.ts
Normal file
21
src/hooks/useTransactionStore.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { TRANSACTIONS_KEY } from 'constants/localStore'
|
||||
import useLocalStorage from 'hooks/useLocalStorage'
|
||||
|
||||
export default function useTransactionStore(): {
|
||||
transactions: ToastStore
|
||||
addTransaction: (transaction: ToastSuccess) => void
|
||||
} {
|
||||
const [transactions, setTransactions] = useLocalStorage<ToastStore>(TRANSACTIONS_KEY, {
|
||||
recent: [],
|
||||
})
|
||||
const recentTransactions = transactions.recent
|
||||
const addTransaction = (transaction: ToastSuccess) => {
|
||||
recentTransactions.push(transaction)
|
||||
setTransactions({ recent: recentTransactions })
|
||||
}
|
||||
|
||||
return {
|
||||
transactions,
|
||||
addTransaction,
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import { MsgExecuteContract } from '@delphi-labs/shuttle-react'
|
||||
import moment from 'moment'
|
||||
import { isMobile } from 'react-device-detect'
|
||||
import { GetState, SetState } from 'zustand'
|
||||
|
||||
@ -20,6 +21,27 @@ import { formatAmountWithSymbol } from 'utils/formatters'
|
||||
import getTokenOutFromSwapResponse from 'utils/getTokenOutFromSwapResponse'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
interface HandleResponse {
|
||||
response: BroadcastResult
|
||||
action:
|
||||
| 'deposit'
|
||||
| 'withdraw'
|
||||
| 'borrow'
|
||||
| 'repay'
|
||||
| 'vault'
|
||||
| 'lend'
|
||||
| 'create'
|
||||
| 'delete'
|
||||
| 'claim'
|
||||
| 'unlock'
|
||||
| 'swap'
|
||||
lend?: boolean
|
||||
accountId?: string
|
||||
changes?: { debts?: BNCoin[]; deposits?: BNCoin[]; lends?: BNCoin[] }
|
||||
target?: 'wallet' | 'account'
|
||||
message?: string
|
||||
}
|
||||
|
||||
function generateExecutionMessage(
|
||||
sender: string | undefined = '',
|
||||
contract: string,
|
||||
@ -38,28 +60,93 @@ export default function createBroadcastSlice(
|
||||
set: SetState<Store>,
|
||||
get: GetState<Store>,
|
||||
): BroadcastSlice {
|
||||
const handleResponseMessages = (
|
||||
response: BroadcastResult,
|
||||
successMessage: string,
|
||||
errorMessage?: string,
|
||||
) => {
|
||||
if (response.result?.response.code === 0) {
|
||||
const handleResponseMessages = (props: HandleResponse) => {
|
||||
const { accountId, response, action, lend, changes, target, message } = props
|
||||
|
||||
if (response.error || response.result?.response.code !== 0) {
|
||||
set({
|
||||
toast: {
|
||||
message: successMessage,
|
||||
hash: response.result.hash,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
set({
|
||||
toast: {
|
||||
message: generateErrorMessage(response, errorMessage),
|
||||
message: generateErrorMessage(response),
|
||||
isError: true,
|
||||
hash: response.result?.hash,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const toast: ToastResponse = {
|
||||
accountId: accountId,
|
||||
isError: false,
|
||||
hash: response?.result?.hash,
|
||||
content: [],
|
||||
timestamp: moment().unix(),
|
||||
address: get().address ?? '',
|
||||
}
|
||||
|
||||
if (message) {
|
||||
toast.message = message
|
||||
set({ toast })
|
||||
return
|
||||
}
|
||||
|
||||
if (!changes) return
|
||||
|
||||
switch (action) {
|
||||
case 'borrow':
|
||||
const borrowCoin = changes.debts ? [changes.debts[0].toCoin()] : []
|
||||
const action = lend ? 'Borrowed and lend' : 'Borrowed'
|
||||
toast.content.push({
|
||||
coins: borrowCoin,
|
||||
text: target === 'wallet' ? 'Borrowed to wallet' : action,
|
||||
})
|
||||
break
|
||||
|
||||
case 'withdraw':
|
||||
toast.content.push({
|
||||
coins: changes.deposits?.map((deposit) => deposit.toCoin()) ?? [],
|
||||
text: target === 'wallet' ? 'Withdrew to Wallet' : 'Withdrew from lend',
|
||||
})
|
||||
break
|
||||
|
||||
case 'deposit':
|
||||
toast.content.push({
|
||||
coins: changes.deposits?.map((deposit) => deposit.toCoin()) ?? [],
|
||||
text: lend ? 'Deposited and lent' : 'Deposited',
|
||||
})
|
||||
break
|
||||
|
||||
case 'lend':
|
||||
const lendCoin = changes.lends ? [changes.lends[0].toCoin()] : []
|
||||
toast.content.push({
|
||||
coins: lendCoin,
|
||||
text: 'Lent',
|
||||
})
|
||||
break
|
||||
|
||||
case 'repay':
|
||||
const repayCoin = changes.deposits ? [changes.deposits[0].toCoin()] : []
|
||||
toast.content.push({
|
||||
coins: repayCoin,
|
||||
text: 'Repayed',
|
||||
})
|
||||
break
|
||||
|
||||
case 'vault':
|
||||
toast.message = 'Add to Vault Position'
|
||||
toast.content.push({
|
||||
coins: changes.debts?.map((debt) => debt.toCoin()) ?? [],
|
||||
text: 'Borrowed for the Vault Position',
|
||||
})
|
||||
toast.content.push({
|
||||
coins: changes.deposits?.map((deposit) => deposit.toCoin()) ?? [],
|
||||
text: 'Withdrew for the Vault Position',
|
||||
})
|
||||
}
|
||||
|
||||
set({ toast })
|
||||
return
|
||||
}
|
||||
|
||||
const getEstimatedFee = async (messages: MsgExecuteContract[]) => {
|
||||
if (!get().client) {
|
||||
return defaultFee
|
||||
@ -115,12 +202,15 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
handleResponseMessages(
|
||||
handleResponseMessages({
|
||||
response,
|
||||
`Borrowed ${formatAmountWithSymbol(options.coin.toCoin())} to ${
|
||||
options.borrowToWallet ? 'Wallet' : `Credit Account ${options.accountId}`
|
||||
}`,
|
||||
)
|
||||
action: 'borrow',
|
||||
lend: checkAutoLendEnabled(options.accountId),
|
||||
target: options.borrowToWallet ? 'wallet' : 'account',
|
||||
accountId: options.accountId,
|
||||
changes: { debts: [options.coin] },
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
createAccount: async () => {
|
||||
@ -132,25 +222,24 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
if (response.result && !response.error) {
|
||||
set({ createAccountModal: false })
|
||||
const id = getSingleValueFromBroadcastResult(response.result, 'wasm', 'token_id')
|
||||
set({ createAccountModal: false })
|
||||
const id = response.result
|
||||
? getSingleValueFromBroadcastResult(response.result, 'wasm', 'token_id')
|
||||
: null
|
||||
|
||||
handleResponseMessages({
|
||||
response,
|
||||
action: 'create',
|
||||
accountId: id ?? undefined,
|
||||
message: id ? `Created the Credit Account` : undefined,
|
||||
})
|
||||
|
||||
if (id)
|
||||
set({
|
||||
fundAccountModal: true,
|
||||
toast: { message: `Credit Account ${id} created`, hash: response.result.hash },
|
||||
})
|
||||
return id
|
||||
} else {
|
||||
set({
|
||||
createAccountModal: false,
|
||||
toast: {
|
||||
message: generateErrorMessage(response),
|
||||
hash: response?.result?.hash,
|
||||
isError: true,
|
||||
},
|
||||
})
|
||||
return null
|
||||
}
|
||||
|
||||
return id
|
||||
},
|
||||
deleteAccount: async (options: { accountId: string; lends: BNCoin[] }) => {
|
||||
const reclaimMsg = options.lends.map((coin) => {
|
||||
@ -179,7 +268,12 @@ export default function createBroadcastSlice(
|
||||
],
|
||||
})
|
||||
|
||||
handleResponseMessages(response, `Credit Account ${options.accountId} deleted`)
|
||||
handleResponseMessages({
|
||||
response,
|
||||
action: 'delete',
|
||||
accountId: options.accountId,
|
||||
message: `Deleted the Credit Account`,
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
@ -205,9 +299,13 @@ export default function createBroadcastSlice(
|
||||
messages,
|
||||
})
|
||||
|
||||
const successMessage = `Claimed rewards for, ${options.accountId}`
|
||||
handleResponseMessages({
|
||||
response,
|
||||
action: 'create',
|
||||
accountId: options.accountId,
|
||||
message: `Claimed rewards`,
|
||||
})
|
||||
|
||||
handleResponseMessages(response, successMessage)
|
||||
return !!response.result
|
||||
}
|
||||
|
||||
@ -237,15 +335,14 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, funds)],
|
||||
})
|
||||
|
||||
const depositString = options.coins
|
||||
.map((coin) => formatAmountWithSymbol(coin.toCoin()))
|
||||
.join(' and ')
|
||||
handleResponseMessages(
|
||||
handleResponseMessages({
|
||||
response,
|
||||
`Deposited ${options.lend ? 'and lent ' : ''}${depositString} to Credit Account ${
|
||||
options.accountId
|
||||
}`,
|
||||
)
|
||||
action: 'deposit',
|
||||
lend: options.lend,
|
||||
accountId: options.accountId,
|
||||
changes: { deposits: options.coins },
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
unlock: async (options: { accountId: string; vault: DepositedVault; amount: string }) => {
|
||||
@ -267,7 +364,12 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
handleResponseMessages(response, `Requested unlock for ${options.vault.name}`)
|
||||
handleResponseMessages({
|
||||
response,
|
||||
action: 'unlock',
|
||||
accountId: options.accountId,
|
||||
message: `Requested unlock for ${options.vault.name}`,
|
||||
})
|
||||
return !!response.result
|
||||
},
|
||||
|
||||
@ -307,13 +409,20 @@ export default function createBroadcastSlice(
|
||||
})
|
||||
|
||||
const vaultsString = options.vaults.length === 1 ? 'vault' : 'vaults'
|
||||
handleResponseMessages(
|
||||
handleResponseMessages({
|
||||
response,
|
||||
`You successfully withdrew ${options.vaults.length} unlocked ${vaultsString} to your account`,
|
||||
)
|
||||
action: 'withdraw',
|
||||
accountId: options.accountId,
|
||||
message: `Withdrew ${options.vaults.length} unlocked ${vaultsString} to the account`,
|
||||
})
|
||||
return !!response.result
|
||||
},
|
||||
depositIntoVault: async (options: { accountId: string; actions: Action[] }) => {
|
||||
depositIntoVault: async (options: {
|
||||
accountId: string
|
||||
actions: Action[]
|
||||
deposits: BNCoin[]
|
||||
borrowings: BNCoin[]
|
||||
}) => {
|
||||
const msg: CreditManagerExecuteMsg = {
|
||||
update_credit_account: {
|
||||
account_id: options.accountId,
|
||||
@ -325,7 +434,13 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
handleResponseMessages(response, `Deposited into vault`)
|
||||
handleResponseMessages({
|
||||
response,
|
||||
action: 'vault',
|
||||
accountId: options.accountId,
|
||||
changes: { deposits: options.deposits, debts: options.borrowings },
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
withdraw: async (options: {
|
||||
@ -355,13 +470,14 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
const withdrawString = options.coins
|
||||
.map(({ coin }) => formatAmountWithSymbol(coin.toCoin()))
|
||||
.join('and ')
|
||||
handleResponseMessages(
|
||||
handleResponseMessages({
|
||||
response,
|
||||
`Withdrew ${withdrawString} from Credit Account ${options.accountId}`,
|
||||
)
|
||||
action: 'withdraw',
|
||||
target: 'wallet',
|
||||
accountId: options.accountId,
|
||||
changes: { deposits: options.coins.map((coin) => coin.coin) },
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
repay: async (options: {
|
||||
@ -392,12 +508,13 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
handleResponseMessages(
|
||||
handleResponseMessages({
|
||||
response,
|
||||
`Repayed ${formatAmountWithSymbol(options.coin.toCoin())} to Credit Account ${
|
||||
options.accountId
|
||||
}`,
|
||||
)
|
||||
action: 'repay',
|
||||
accountId: options.accountId,
|
||||
changes: { deposits: [options.coin] },
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
lend: async (options: { accountId: string; coin: BNCoin; isMax?: boolean }) => {
|
||||
@ -416,10 +533,13 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
handleResponseMessages(
|
||||
handleResponseMessages({
|
||||
response,
|
||||
`Successfully lent ${formatAmountWithSymbol(options.coin.toCoin())}`,
|
||||
)
|
||||
action: 'lend',
|
||||
accountId: options.accountId,
|
||||
changes: { lends: [options.coin] },
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
reclaim: async (options: { accountId: string; coin: BNCoin; isMax?: boolean }) => {
|
||||
@ -438,10 +558,14 @@ export default function createBroadcastSlice(
|
||||
messages: [generateExecutionMessage(get().address, ENV.ADDRESS_CREDIT_MANAGER, msg, [])],
|
||||
})
|
||||
|
||||
handleResponseMessages(
|
||||
handleResponseMessages({
|
||||
response,
|
||||
`Successfully withdrew ${formatAmountWithSymbol(options.coin.toCoin())}`,
|
||||
)
|
||||
action: 'withdraw',
|
||||
target: 'account',
|
||||
accountId: options.accountId,
|
||||
changes: { deposits: [options.coin] },
|
||||
})
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
swap: (options: {
|
||||
@ -495,7 +619,12 @@ export default function createBroadcastSlice(
|
||||
options.coinIn.toCoin(),
|
||||
)} for ${formatAmountWithSymbol(coinOut)}`
|
||||
|
||||
handleResponseMessages(response, successMessage)
|
||||
handleResponseMessages({
|
||||
response,
|
||||
action: 'swap',
|
||||
message: successMessage,
|
||||
accountId: options.accountId,
|
||||
})
|
||||
return !!response.result
|
||||
}
|
||||
|
||||
|
33
src/types/interfaces/store/broadcast.d.ts
vendored
33
src/types/interfaces/store/broadcast.d.ts
vendored
@ -11,6 +11,30 @@ interface ExecutableTx {
|
||||
estimateFee: () => Promise<StdFee>
|
||||
}
|
||||
|
||||
type ToastResponse = {
|
||||
hash?: string
|
||||
title?: string
|
||||
} & (ToastSuccess | ToastError)
|
||||
|
||||
interface ToastSuccess {
|
||||
accountId?: string
|
||||
content: { coins: Coin[]; text: string }[]
|
||||
isError: false
|
||||
message?: string
|
||||
timestamp: number
|
||||
address: string
|
||||
hash: string
|
||||
}
|
||||
|
||||
interface ToastError {
|
||||
message: string
|
||||
isError: true
|
||||
}
|
||||
|
||||
interface ToastStore {
|
||||
recent: ToastSuccess[]
|
||||
}
|
||||
|
||||
interface BroadcastSlice {
|
||||
borrow: (options: {
|
||||
accountId: string
|
||||
@ -21,7 +45,12 @@ interface BroadcastSlice {
|
||||
createAccount: () => Promise<string | null>
|
||||
deleteAccount: (options: { accountId: string; lends: BNCoin[] }) => Promise<boolean>
|
||||
deposit: (options: { accountId: string; coins: BNCoin[]; lend: boolean }) => Promise<boolean>
|
||||
depositIntoVault: (options: { accountId: string; actions: Action[] }) => Promise<boolean>
|
||||
depositIntoVault: (options: {
|
||||
accountId: string
|
||||
actions: Action[]
|
||||
deposits: BNCoin[]
|
||||
borrowings: BNCoin[]
|
||||
}) => Promise<boolean>
|
||||
executeMsg: (options: { messages: MsgExecuteContract[] }) => Promise<BroadcastResult>
|
||||
lend: (options: { accountId: string; coin: BNCoin; isMax?: boolean }) => Promise<boolean>
|
||||
reclaim: (options: { accountId: string; coin: BNCoin; isMax?: boolean }) => Promise<boolean>
|
||||
@ -40,7 +69,7 @@ interface BroadcastSlice {
|
||||
slippage: number
|
||||
isMax?: boolean
|
||||
}) => ExecutableTx
|
||||
toast: { message: string; isError?: boolean; title?: string; hash?: string } | null
|
||||
toast: ToastResponse | null
|
||||
unlock: (options: {
|
||||
accountId: string
|
||||
vault: DepositedVault
|
||||
|
@ -1,6 +1,7 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import moment from 'moment'
|
||||
|
||||
import { ASSETS } from 'constants/assets'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
@ -149,12 +150,12 @@ export function formatPercent(percent: number | string, minDecimals?: number) {
|
||||
}
|
||||
|
||||
export function formatAmountWithSymbol(coin: Coin) {
|
||||
const marketAssets = getEnabledMarketAssets()
|
||||
|
||||
const asset = marketAssets.find((asset) => asset.denom === coin.denom)
|
||||
const asset = ASSETS.find((asset) => asset.denom === coin.denom)
|
||||
|
||||
return formatValue(coin.amount, {
|
||||
decimals: asset?.decimals,
|
||||
maxDecimals: asset?.decimals,
|
||||
minDecimals: 0,
|
||||
suffix: ` ${asset?.symbol}`,
|
||||
abbreviated: true,
|
||||
rounded: true,
|
||||
|
Loading…
Reference in New Issue
Block a user