From d052c91abddffef18e7c54bb0066aebc74a9e8cd Mon Sep 17 00:00:00 2001 From: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com> Date: Mon, 11 Sep 2023 10:14:40 +0200 Subject: [PATCH] Fixes bob (#443) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐛 Trading chart title * 🐛 Trading chart title * 🐛 fix incorrect vault deposit amounts * 🐛 fix incorrect vault borrow calc * 🧽 run format * 🧽 fix comments * 🧽 update code owners --- .github/CODEOWNERS | 2 +- src/api/accounts/getAccount.ts | 2 +- .../useAccountBalanceData.tsx | 4 +-- src/components/Account/AccountCreateFirst.tsx | 2 +- .../AccountFund/AccountFundContent.tsx | 2 +- .../AccountFund/AccountFundFullPage.tsx | 2 +- src/components/Account/AccountList.tsx | 2 +- src/components/Account/AccountMenuContent.tsx | 2 +- .../Account/AccountDeleteAlertDialog.tsx | 2 +- .../Modals/Account/AccountDeleteModal.tsx | 2 +- src/components/Modals/AlertDialog/index.tsx | 4 +-- .../Modals/Vault/VaultModalContent.tsx | 2 +- src/components/PageMetadata.tsx | 2 +- .../TradeChart/OsmosisTheGraphDataFeed.ts | 15 ++++++++--- src/components/Trade/TradeChart/constants.ts | 1 - src/hooks/broadcast/useDepositVault.ts | 4 +-- src/hooks/useHealthComputer.tsx | 25 ++++++++----------- src/hooks/useUpdatedAccount/index.ts | 2 +- src/store/slices/broadcast.ts | 3 +-- src/types/interfaces/store/modals.d.ts | 5 +++- src/utils/formatters.ts | 25 +++++++++++++------ src/utils/parsers.ts | 11 +++----- src/utils/vaults.ts | 14 +++++++---- 23 files changed, 74 insertions(+), 61 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 51451618..b63bf44a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @bobthebuidlr @linkielink @yusufseyrek +* @bobthebuidlr @linkielink \ No newline at end of file diff --git a/src/api/accounts/getAccount.ts b/src/api/accounts/getAccount.ts index 2546a1d2..0d83a67e 100644 --- a/src/api/accounts/getAccount.ts +++ b/src/api/accounts/getAccount.ts @@ -1,7 +1,7 @@ import { getCreditManagerQueryClient } from 'api/cosmwasm-client' import getDepositedVaults from 'api/vaults/getDepositedVaults' -import { Positions } from 'types/generated/mars-credit-manager/MarsCreditManager.types' import { BNCoin } from 'types/classes/BNCoin' +import { Positions } from 'types/generated/mars-credit-manager/MarsCreditManager.types' export default async function getAccount(accountId: string): Promise { const creditManagerQueryClient = await getCreditManagerQueryClient() diff --git a/src/components/Account/AccountBalancesTable/useAccountBalanceData.tsx b/src/components/Account/AccountBalancesTable/useAccountBalanceData.tsx index 243c1ae5..3c0136ba 100644 --- a/src/components/Account/AccountBalancesTable/useAccountBalanceData.tsx +++ b/src/components/Account/AccountBalancesTable/useAccountBalanceData.tsx @@ -34,9 +34,7 @@ export default function useAccountBalanceData(props: Props) { const asset = ASSETS.find(byDenom(deposit.denom)) if (!asset) return const apy = 0 - const prevDeposit = updatedAccount - ? account?.deposits.find(byDenom(deposit.denom)) - : deposit + const prevDeposit = updatedAccount ? account?.deposits.find(byDenom(deposit.denom)) : deposit deposits.push(getAssetAccountBalanceRow('deposits', asset, prices, deposit, apy, prevDeposit)) }) diff --git a/src/components/Account/AccountCreateFirst.tsx b/src/components/Account/AccountCreateFirst.tsx index 189b65e0..966b02df 100644 --- a/src/components/Account/AccountCreateFirst.tsx +++ b/src/components/Account/AccountCreateFirst.tsx @@ -51,4 +51,4 @@ export default function AccountCreateFirst() { docs='account' /> ) -} \ No newline at end of file +} diff --git a/src/components/Account/AccountFund/AccountFundContent.tsx b/src/components/Account/AccountFund/AccountFundContent.tsx index 1e26092a..a1ba56bb 100644 --- a/src/components/Account/AccountFund/AccountFundContent.tsx +++ b/src/components/Account/AccountFund/AccountFundContent.tsx @@ -202,4 +202,4 @@ export default function AccountFundContent(props: Props) { /> ) -} \ No newline at end of file +} diff --git a/src/components/Account/AccountFund/AccountFundFullPage.tsx b/src/components/Account/AccountFund/AccountFundFullPage.tsx index 7b9ae23e..514daa51 100644 --- a/src/components/Account/AccountFund/AccountFundFullPage.tsx +++ b/src/components/Account/AccountFund/AccountFundFullPage.tsx @@ -39,4 +39,4 @@ export default function AccountFundFullPage() { ) -} \ No newline at end of file +} diff --git a/src/components/Account/AccountList.tsx b/src/components/Account/AccountList.tsx index c81d1db8..232e7cdc 100644 --- a/src/components/Account/AccountList.tsx +++ b/src/components/Account/AccountList.tsx @@ -143,4 +143,4 @@ export default function AccountList(props: Props) { })} ) -} \ No newline at end of file +} diff --git a/src/components/Account/AccountMenuContent.tsx b/src/components/Account/AccountMenuContent.tsx index 2c00c0bd..cb59ccc0 100644 --- a/src/components/Account/AccountMenuContent.tsx +++ b/src/components/Account/AccountMenuContent.tsx @@ -164,4 +164,4 @@ export default function AccountMenuContent(props: Props) { ) } -export { ACCOUNT_MENU_BUTTON_ID } \ No newline at end of file +export { ACCOUNT_MENU_BUTTON_ID } diff --git a/src/components/Modals/Account/AccountDeleteAlertDialog.tsx b/src/components/Modals/Account/AccountDeleteAlertDialog.tsx index 38ad936b..29d5eb52 100644 --- a/src/components/Modals/Account/AccountDeleteAlertDialog.tsx +++ b/src/components/Modals/Account/AccountDeleteAlertDialog.tsx @@ -33,4 +33,4 @@ export default function AccoundDeleteAlertDialog(props: Props) { }, [showAlertDialog, title, description, closeHandler, positiveButton]) return null -} \ No newline at end of file +} diff --git a/src/components/Modals/Account/AccountDeleteModal.tsx b/src/components/Modals/Account/AccountDeleteModal.tsx index 622988a3..294dc51c 100644 --- a/src/components/Modals/Account/AccountDeleteModal.tsx +++ b/src/components/Modals/Account/AccountDeleteModal.tsx @@ -129,4 +129,4 @@ function AccountDeleteModal(props: Props) { }} /> ) -} \ No newline at end of file +} diff --git a/src/components/Modals/AlertDialog/index.tsx b/src/components/Modals/AlertDialog/index.tsx index 69f660b5..4969d6c9 100644 --- a/src/components/Modals/AlertDialog/index.tsx +++ b/src/components/Modals/AlertDialog/index.tsx @@ -34,7 +34,7 @@ function AlertDialog(props: Props) { async function handleAsyncButtonClick(button?: AlertDialogButton) { if (!button?.onClick) return setIsConfirming(true) - button.onClick() + await button.onClick() setIsConfirming(false) props.close() } @@ -83,4 +83,4 @@ function AlertDialog(props: Props) { ) -} \ No newline at end of file +} diff --git a/src/components/Modals/Vault/VaultModalContent.tsx b/src/components/Modals/Vault/VaultModalContent.tsx index e780a604..decc70b7 100644 --- a/src/components/Modals/Vault/VaultModalContent.tsx +++ b/src/components/Modals/Vault/VaultModalContent.tsx @@ -182,4 +182,4 @@ export default function VaultModalContent(props: Props) { ) -} \ No newline at end of file +} diff --git a/src/components/PageMetadata.tsx b/src/components/PageMetadata.tsx index 38846ee1..f0d2ba09 100644 --- a/src/components/PageMetadata.tsx +++ b/src/components/PageMetadata.tsx @@ -26,4 +26,4 @@ function PageMetadata() { ) } -export default PageMetadata \ No newline at end of file +export default PageMetadata diff --git a/src/components/Trade/TradeChart/OsmosisTheGraphDataFeed.ts b/src/components/Trade/TradeChart/OsmosisTheGraphDataFeed.ts index 9ed925cf..77e51a3f 100644 --- a/src/components/Trade/TradeChart/OsmosisTheGraphDataFeed.ts +++ b/src/components/Trade/TradeChart/OsmosisTheGraphDataFeed.ts @@ -1,4 +1,5 @@ import { defaultSymbolInfo } from 'components/Trade/TradeChart/constants' +import { ASSETS } from 'constants/assets' import { ENV } from 'constants/env' import { getAssetByDenom, getEnabledMarketAssets } from 'utils/assets' import { @@ -69,6 +70,14 @@ export class OsmosisTheGraphDataFeed implements IDatafeedChartApi { this.pairs = Array.from(pairs) } + getDescription(pairName: string) { + const denom1 = pairName.split(PAIR_SEPARATOR)[0] + const denom2 = pairName.split(PAIR_SEPARATOR)[1] + const asset1 = ASSETS.find((asset) => asset.mainnetDenom === denom1) + const asset2 = ASSETS.find((asset) => asset.mainnetDenom === denom2) + return `${asset1?.symbol}/${asset2?.symbol}` + } + async getPairsWithData() { const query = ` { @@ -120,10 +129,10 @@ export class OsmosisTheGraphDataFeed implements IDatafeedChartApi { setTimeout(() => onResolve({ ...defaultSymbolInfo, - name: pairName.split(PAIR_SEPARATOR)[0], + name: this.getDescription(pairName), full_name: pairName, - description: pairName, - ticker: pairName, + description: this.getDescription(pairName), + ticker: this.getDescription(pairName), exchange: this.exchangeName, listed_exchange: this.exchangeName, supported_resolutions: this.supportedResolutions, diff --git a/src/components/Trade/TradeChart/constants.ts b/src/components/Trade/TradeChart/constants.ts index 7b15b993..279ed7f9 100644 --- a/src/components/Trade/TradeChart/constants.ts +++ b/src/components/Trade/TradeChart/constants.ts @@ -1,6 +1,5 @@ import { ChartingLibraryFeatureset, - LibrarySymbolInfo, ResolutionString, SeriesFormat, Timezone, diff --git a/src/hooks/broadcast/useDepositVault.ts b/src/hooks/broadcast/useDepositVault.ts index 83bf66dc..09fa8596 100644 --- a/src/hooks/broadcast/useDepositVault.ts +++ b/src/hooks/broadcast/useDepositVault.ts @@ -52,10 +52,10 @@ export default function useDepositVault(props: Props): { ) const reclaimActions: Action[] = useMemo(() => { - return props.reclaims.map((bnCoin) => ({ + return reclaims.map((bnCoin) => ({ reclaim: bnCoin.toActionCoin(), })) - }, [props.reclaims]) + }, [reclaims]) const borrowActions: Action[] = useMemo(() => { return borrowings.map((bnCoin) => ({ diff --git a/src/hooks/useHealthComputer.tsx b/src/hooks/useHealthComputer.tsx index db853b3d..b6ad0d46 100644 --- a/src/hooks/useHealthComputer.tsx +++ b/src/hooks/useHealthComputer.tsx @@ -4,7 +4,6 @@ import { BN_ZERO } from 'constants/math' import useAssetParams from 'hooks/useAssetParams' import usePrices from 'hooks/usePrices' import useVaultConfigs from 'hooks/useVaultConfigs' -import useStore from 'store' import { Positions, VaultPositionValue, @@ -26,21 +25,20 @@ import { } from 'utils/health_computer' import { BN } from 'utils/helpers' +// Pyth returns prices with up to 32 decimals. Javascript only supports 18 decimals. So we need to scale by 14 t +// avoid "too many decimals" errors. +const VALUE_SCALE_FACTOR = 14 + export default function useHealthComputer(account?: Account) { const { data: prices } = usePrices() const { data: assetParams } = useAssetParams() const { data: vaultConfigs } = useVaultConfigs() - const baseCurrency = useStore((s) => s.baseCurrency) const [healthFactor, setHealthFactor] = useState(0) const positions: Positions | null = useMemo(() => { if (!account) return null return convertAccountToPositions(account) }, [account]) - const baseCurrencyPrice = useMemo( - () => prices.find((price) => price.denom === baseCurrency.denom)?.amount || 0, - [prices, baseCurrency.denom], - ) const vaultPositionValues = useMemo(() => { if (!account?.vaults) return null @@ -57,8 +55,8 @@ export default function useHealthComputer(account?: Account) { amount: '0', // Not used by healthcomputer denom: curr.denoms.vault, value: curr.values.primary - .div(baseCurrencyPrice) - .plus(curr.values.secondary.div(baseCurrencyPrice)) + .plus(curr.values.secondary) + .shiftedBy(VALUE_SCALE_FACTOR + 6) // Need to scale additional 6 to correct for uusd values .integerValue() .toString(), }, @@ -67,20 +65,17 @@ export default function useHealthComputer(account?: Account) { }, {} as { [key: string]: VaultPositionValue }, ) - }, [account?.vaults, prices, baseCurrencyPrice]) + }, [account?.vaults, prices]) const priceData = useMemo(() => { - const baseCurrencyPrice = - prices.find((price) => price.denom === baseCurrency.denom)?.amount || 0 - return prices.reduce( (prev, curr) => { - prev[curr.denom] = curr.amount.div(baseCurrencyPrice).decimalPlaces(18).toString() + prev[curr.denom] = curr.amount.shiftedBy(VALUE_SCALE_FACTOR).toString() return prev }, {} as { [key: string]: string }, ) - }, [prices, baseCurrency.denom]) + }, [prices]) const denomsData = useMemo( () => @@ -192,4 +187,4 @@ export default function useHealthComputer(account?: Account) { computeMaxWithdrawAmount, computeMaxSwapAmount, } -} +} \ No newline at end of file diff --git a/src/hooks/useUpdatedAccount/index.ts b/src/hooks/useUpdatedAccount/index.ts index 68ced9b7..dc4ad783 100644 --- a/src/hooks/useUpdatedAccount/index.ts +++ b/src/hooks/useUpdatedAccount/index.ts @@ -225,4 +225,4 @@ export function useUpdatedAccount(account?: Account) { simulateVaultDeposit, simulateWithdraw, } -} \ No newline at end of file +} diff --git a/src/store/slices/broadcast.ts b/src/store/slices/broadcast.ts index 105cb534..470418f0 100644 --- a/src/store/slices/broadcast.ts +++ b/src/store/slices/broadcast.ts @@ -20,7 +20,6 @@ import { formatAmountWithSymbol } from 'utils/formatters' import getTokenOutFromSwapResponse from 'utils/getTokenOutFromSwapResponse' import { BN } from 'utils/helpers' - function generateExecutionMessage( sender: string | undefined = '', contract: string, @@ -533,4 +532,4 @@ export default function createBroadcastSlice( } }, } -} \ No newline at end of file +} diff --git a/src/types/interfaces/store/modals.d.ts b/src/types/interfaces/store/modals.d.ts index 9fbb99ce..031f5878 100644 --- a/src/types/interfaces/store/modals.d.ts +++ b/src/types/interfaces/store/modals.d.ts @@ -19,7 +19,7 @@ interface AlertDialogButton { text?: string icon?: JSX.Element isAsync?: boolean - onClick?: () => void + onClick?: () => Promise | void } interface AlertDialogConfig { @@ -29,6 +29,7 @@ interface AlertDialogConfig { negativeButton?: AlertDialogButton positiveButton?: AlertDialogButton } + interface BorrowModal { asset: Asset marketData: BorrowMarketTableData @@ -36,6 +37,7 @@ interface BorrowModal { } type LendAndReclaimModalAction = 'lend' | 'reclaim' + interface LendAndReclaimModalConfig { data: LendingMarketTableData action: LendAndReclaimModalAction @@ -54,6 +56,7 @@ interface AddVaultBorrowingsModal { interface UnlockModal { vault: DepositedVault } + interface WalletAssetModal { isOpen?: boolean selectedDenoms: string[] diff --git a/src/utils/formatters.ts b/src/utils/formatters.ts index ed0f4d08..ba5d8c40 100644 --- a/src/utils/formatters.ts +++ b/src/utils/formatters.ts @@ -4,6 +4,7 @@ import moment from 'moment' import { BN_ZERO } from 'constants/math' import { ORACLE_DENOM } from 'constants/oracle' import { BNCoin } from 'types/classes/BNCoin' +import { byDenom } from 'utils/array' import { getAllAssets, getEnabledMarketAssets } from 'utils/assets' import { BN } from 'utils/helpers' @@ -167,19 +168,19 @@ export const convertPercentage = (percent: number) => { return Number(formatValue(percentage, { minDecimals: 0, maxDecimals: 0 })) } -export function magnify(value: number | string, asset: Asset | PseudoAsset) { - const amount = BN(value) - return amount.isZero() ? amount : BN(value).shiftedBy(asset.decimals) +export function magnify(amount: number | string, asset: Asset | PseudoAsset) { + const _amount = BN(amount) + return _amount.isZero() ? _amount : _amount.shiftedBy(asset.decimals) } export function demagnify(amount: number | string | BigNumber, asset: Asset | PseudoAsset) { - const value = BN(amount) - return value.isZero() ? 0 : value.shiftedBy(-1 * asset.decimals).toNumber() + const _amount = BN(amount) + return _amount.isZero() ? 0 : _amount.shiftedBy(-1 * asset.decimals).toNumber() } export function getCoinValue(coin: BNCoin, prices: BNCoin[]) { - const asset = getAllAssets().find((asset) => asset.denom === coin.denom) - const coinPrice = prices.find((price) => price.denom === coin.denom) + const asset = getAllAssets().find(byDenom(coin.denom)) + const coinPrice = prices.find(byDenom(coin.denom)) if (!coinPrice || !asset) return BN_ZERO @@ -187,6 +188,16 @@ export function getCoinValue(coin: BNCoin, prices: BNCoin[]) { return coin.amount.shiftedBy(decimals).multipliedBy(coinPrice.amount) } +export function getCoinAmount(denom: string, value: BigNumber, prices: BNCoin[]) { + const asset = getAllAssets().find(byDenom(denom)) + const coinPrice = prices.find(byDenom(denom)) + + if (!coinPrice || !asset) return BN_ZERO + + const decimals = asset.denom === ORACLE_DENOM ? 0 : asset.decimals + return value.dividedBy(coinPrice.amount).shiftedBy(decimals).integerValue() +} + export function convertLiquidityRateToAPR(rate: number) { const rateMulHundred = rate * 100 return rateMulHundred >= 0.01 ? rateMulHundred : 0.0 diff --git a/src/utils/parsers.ts b/src/utils/parsers.ts index 1d1861e6..13e02b29 100644 --- a/src/utils/parsers.ts +++ b/src/utils/parsers.ts @@ -1,15 +1,12 @@ import { BNCoin } from 'types/classes/BNCoin' import { BN } from 'utils/helpers' + export function isNumber(value: unknown) { if (typeof value === 'string' && value !== '') { return !isNaN(Number(value)) } - if (typeof value === 'number') { - return true - } - - return false + return typeof value === 'number' } export const convertAprToApy = (apr: number, numberOfCompoundingPeriods: number): number => { @@ -32,13 +29,11 @@ export const combineBNCoins = (coins: BNCoin[]): BNCoin[] => { } }) - const combinedArray: BNCoin[] = Object.keys(combinedMap).map( + return Object.keys(combinedMap).map( (denom) => new BNCoin({ denom, amount: BN(combinedMap[denom]).toString(), }), ) - - return combinedArray } diff --git a/src/utils/vaults.ts b/src/utils/vaults.ts index a9431510..173842f5 100644 --- a/src/utils/vaults.ts +++ b/src/utils/vaults.ts @@ -5,7 +5,7 @@ import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults' import { BNCoin } from 'types/classes/BNCoin' import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types' import { getAssetByDenom } from 'utils/assets' -import { getCoinValue } from 'utils/formatters' +import { getCoinAmount, getCoinValue } from 'utils/formatters' import { getValueFromBNCoins, mergeBNCoinArrays } from 'utils/helpers' import { getTokenPrice } from 'utils/tokens' @@ -67,8 +67,8 @@ export function getVaultSwapActions( const swapActions: Action[] = [] const coins = [...deposits, ...borrowings] - let primaryLeftoverValue = totalValue.dividedBy(2).integerValue() - let secondaryLeftoverValue = totalValue.dividedBy(2).integerValue() + let primaryLeftoverValue = totalValue.dividedBy(2) + let secondaryLeftoverValue = totalValue.dividedBy(2) const [primaryCoins, secondaryCoins, otherCoins] = coins.reduce( (prev, bnCoin) => { @@ -94,7 +94,9 @@ export function getVaultSwapActions( } else { value = value.minus(primaryLeftoverValue) primaryLeftoverValue = primaryLeftoverValue.minus(primaryLeftoverValue) - otherCoins.push(new BNCoin({ denom: bnCoin.denom, amount: value.toString() })) + otherCoins.push( + BNCoin.fromDenomAndBigNumber(bnCoin.denom, getCoinAmount(bnCoin.denom, value, prices)), + ) } }) @@ -105,7 +107,9 @@ export function getVaultSwapActions( } else { value = value.minus(secondaryLeftoverValue) secondaryLeftoverValue = secondaryLeftoverValue.minus(secondaryLeftoverValue) - otherCoins.push(new BNCoin({ denom: bnCoin.denom, amount: value.toString() })) + otherCoins.push( + BNCoin.fromDenomAndBigNumber(bnCoin.denom, getCoinAmount(bnCoin.denom, value, prices)), + ) } })