Skip to content

Commit

Permalink
feat: thorchain lending improvements (#5562)
Browse files Browse the repository at this point in the history
* feat: tackle TODOs

* feat: move AccountId state management up top in Borrow.tsx

* feat: lending improvements

* feat: 2mn staleTime for thorchainLendingPosition

* feat: remove Infinity staleTime comment

* feat: programmatic thor lending assets

* feat: more skeletons

* feat: more more skeletons

* feat: error-handling

* feat: cleanup

* feat: improve loading state

* fix: flash of content

* feat: more skeletony

* feat: utxo deposits

* feat: rm console.log

* feat: improve error handling

* fix: derp

* feat: no default

* feat: add unification comment
  • Loading branch information
gomesalexandre authored Nov 2, 2023
1 parent 436a55b commit 11e9d12
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 140 deletions.
34 changes: 15 additions & 19 deletions src/pages/Lending/Pool/Pool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
TabPanels,
Tabs,
} from '@chakra-ui/react'
import { fromAssetId } from '@shapeshiftoss/caip'
import type { AccountId } from '@shapeshiftoss/caip'
import { useQuery } from '@tanstack/react-query'
import axios from 'axios'
import { getConfig } from 'config'
Expand All @@ -31,11 +31,7 @@ import { Main } from 'components/Layout/Main'
import { RawText, Text } from 'components/Text'
import { useRouteAssetId } from 'hooks/useRouteAssetId/useRouteAssetId'
import { bnOrZero } from 'lib/bignumber/bignumber'
import {
selectAssetById,
selectFirstAccountIdByChainId,
selectMarketDataById,
} from 'state/slices/selectors'
import { selectAssetById, selectMarketDataById } from 'state/slices/selectors'
import { useAppSelector } from 'state/store'

import { useLendingPositionData } from '../hooks/useLendingPositionData'
Expand Down Expand Up @@ -68,6 +64,9 @@ const PoolHeader = () => {
const flexDirPool: ResponsiveValue<Property.FlexDirection> = { base: 'column', lg: 'row' }

export const Pool = () => {
const [collateralAccountId, setCollateralAccountId] = useState<AccountId>('')
const [borrowAccountId, setBorrowAccountId] = useState<AccountId>('')

const poolAssetId = useRouteAssetId()
const asset = useAppSelector(state => selectAssetById(state, poolAssetId))

Expand All @@ -76,31 +75,23 @@ export const Pool = () => {

const poolAssetMarketData = useAppSelector(state => selectMarketDataById(state, poolAssetId))

// TODO(gomes): programmatic - this assumes account 0 for now
const accountId =
useAppSelector(state =>
selectFirstAccountIdByChainId(state, fromAssetId(poolAssetId).chainId),
) ?? ''

const repaymentLockQueryKey = useMemo(() => ['thorchainLendingRepaymentLock'], [])

const { data: lendingPositionData, isLoading: isLendingPositionDataLoading } =
useLendingPositionData({
assetId: poolAssetId,
accountId,
accountId: collateralAccountId,
})
const { data: repaymentLock, isLoading: isRepaymentLockLoading } = useQuery({
// TODO(gomes): we may or may not want to change this, but this avoids spamming the API for the time being.
// by default, there's a 5mn cache time, but a 0 stale time, meaning queries are considered stale immediately
// Since react-query queries aren't persisted, and until we have an actual need for ensuring the data is fresh,
// this is a good way to avoid spamming the API during develpment
staleTime: Infinity,
queryKey: repaymentLockQueryKey,
queryFn: async () => {
const daemonUrl = getConfig().REACT_APP_THORCHAIN_NODE_URL
const { data: mimir } = await axios.get<Record<string, unknown>>(
`${daemonUrl}/lcd/thorchain/mimir`,
)
// TODO(gomes): this is the repayment lock of the pool - not the borrower's
// we will want to make it programmatic in case there's an active position.
// https://dev.thorchain.org/thorchain-dev/lending/quick-start-guide
if ('LOANREPAYMENTMATURITY' in mimir) return mimir.LOANREPAYMENTMATURITY as number
return null
Expand All @@ -114,7 +105,7 @@ export const Pool = () => {
.div(60 * 60 * 24)
.toString()
},
enabled: Boolean(accountId && poolAssetId && poolAssetMarketData.price !== '0'),
enabled: Boolean(poolAssetId && poolAssetMarketData.price !== '0'),
})

const headerComponent = useMemo(() => <PoolHeader />, [])
Expand Down Expand Up @@ -238,7 +229,12 @@ export const Pool = () => {
</TabList>
<TabPanels>
<TabPanel px={0} py={0}>
<Borrow />
<Borrow
collateralAccountId={collateralAccountId}
borrowAccountId={borrowAccountId}
onCollateralAccountIdChange={setCollateralAccountId}
onBorrowAccountIdChange={setBorrowAccountId}
/>
</TabPanel>
<TabPanel px={0} py={0}>
<Repay />
Expand Down
50 changes: 46 additions & 4 deletions src/pages/Lending/Pool/components/Borrow/Borrow.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import type { AssetId } from '@shapeshiftoss/caip'
import type { AccountId, AssetId } from '@shapeshiftoss/caip'
import { AnimatePresence } from 'framer-motion'
import { memo, useCallback, useState } from 'react'
import { MemoryRouter, Route, Switch, useLocation } from 'react-router'
import { useRouteAssetId } from 'hooks/useRouteAssetId/useRouteAssetId'
import type { Asset } from 'lib/asset-service'

import { BorrowConfirm } from './BorrowConfirm'
import { BorrowInput } from './BorrowInput'
import { BorrowRoutePaths } from './types'

const BorrowEntries = [BorrowRoutePaths.Input, BorrowRoutePaths.Confirm]

export const Borrow = () => {
type BorrowProps = {
collateralAccountId: AccountId
borrowAccountId: AccountId
onCollateralAccountIdChange: (accountId: AccountId) => void
onBorrowAccountIdChange: (accountId: AccountId) => void
}
export const Borrow = ({
collateralAccountId,
borrowAccountId,
onCollateralAccountIdChange: handleCollateralAccountIdChange,
onBorrowAccountIdChange: handleBorrowAccountIdChange,
}: BorrowProps) => {
const [depositAmount, setDepositAmount] = useState<string | null>(null)

const handleDepositAmountChange = useCallback((value: string) => {
Expand All @@ -25,6 +37,10 @@ export const Borrow = () => {
collateralAssetId={collateralAssetId}
depositAmount={depositAmount}
onDepositAmountChange={handleDepositAmountChange}
collateralAccountId={collateralAccountId}
borrowAccountId={borrowAccountId}
onCollateralAccountIdChange={handleCollateralAccountIdChange}
onBorrowAccountIdChange={handleBorrowAccountIdChange}
/>
</MemoryRouter>
)
Expand All @@ -34,23 +50,49 @@ type BorrowRoutesProps = {
collateralAssetId: AssetId
depositAmount: string | null
onDepositAmountChange: (value: string) => void
collateralAccountId: AccountId
borrowAccountId: AccountId
onCollateralAccountIdChange: (accountId: AccountId) => void
onBorrowAccountIdChange: (accountId: AccountId) => void
}

const BorrowRoutes = memo(
({ collateralAssetId, depositAmount, onDepositAmountChange }: BorrowRoutesProps) => {
({
collateralAssetId,
depositAmount,
onDepositAmountChange,
collateralAccountId,
borrowAccountId,
onCollateralAccountIdChange: handleCollateralAccountIdChange,
onBorrowAccountIdChange: handleBorrowAccountIdChange,
}: BorrowRoutesProps) => {
const location = useLocation()
const [borrowAsset, setBorrowAsset] = useState<Asset | null>(null)

return (
<AnimatePresence exitBeforeEnter initial={false}>
<Switch location={location}>
<Route key={BorrowRoutePaths.Input} path={BorrowRoutePaths.Input}>
<BorrowInput
collateralAssetId={collateralAssetId}
depositAmount={depositAmount}
collateralAccountId={collateralAccountId}
borrowAccountId={borrowAccountId}
onCollateralAccountIdChange={handleCollateralAccountIdChange}
onBorrowAccountIdChange={handleBorrowAccountIdChange}
onDepositAmountChange={onDepositAmountChange}
borrowAsset={borrowAsset}
setBorrowAsset={setBorrowAsset}
/>
</Route>
<Route key={BorrowRoutePaths.Confirm} path={BorrowRoutePaths.Confirm}>
<BorrowConfirm collateralAssetId={collateralAssetId} depositAmount={depositAmount} />
<BorrowConfirm
collateralAssetId={collateralAssetId}
depositAmount={depositAmount}
borrowAccountId={borrowAccountId}
collateralAccountId={collateralAccountId}
borrowAsset={borrowAsset}
/>
</Route>
</Switch>
</AnimatePresence>
Expand Down
Loading

0 comments on commit 11e9d12

Please sign in to comment.