Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add pari page with charts & pair detail page & kashi token page #833

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"editor.formatOnSave": true,
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
TechInnovation-Blockchain marked this conversation as resolved.
Show resolved Hide resolved
"editor.formatOnSave": true
}
}
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@walletconnect/jsonrpc-provider": "1.0.3"
},
"devDependencies": {
"@apollo/client": "^3.6.8",
"@babel/preset-react": "^7.16.7",
"@binance-chain/bsc-connector": "^1.0.0",
"@builder.io/partytown": "^0.5.2",
Expand Down Expand Up @@ -115,6 +116,7 @@
"@types/js-cookie": "^3.0.1",
"@types/ms.macro": "^2.0.0",
"@types/node": "^16.11.0",
"@types/numeral": "^2.0.2",
"@types/qs": "^6.9.7",
"@types/react": "^17.0.2",
"@types/react-slider": "^1.3.1",
Expand Down Expand Up @@ -165,6 +167,8 @@
"graphql": "^15.5.3",
"graphql-request": "^3.5.0",
"graphql-tag": "^2.12.5",
"highcharts": "^10.1.0",
"highcharts-react-official": "^3.1.0",
"husky": "^7.0.0",
"identity-obj-proxy": "^3.0.0",
"ioredis": "^4.27.7",
Expand All @@ -178,14 +182,15 @@
"lottie-react": "2.1.0",
"madge": "^5.0.1",
"millify": "^4.0.0",
"moment": "^2.29.3",
"ms.macro": "^2.0.0",
"next": "^12.1.5",
"next-pwa": "5.4.7",
"next-seo": "^5.1.0",
"next-unused": "^0.0.6",
"ngrok": "^4.3.1",
"node-vibrant": "3.1.6",
"numeral": "^2.0.0",
"numeral": "^2.0.6",
"polished": "^4.1.0",
"postcss": "^8.4.0",
"postcss-flexbugs-fixes": "^5.0.2",
Expand All @@ -199,6 +204,7 @@
"react-dropzone": "^12.0.4",
"react-feather": "^2.0.9",
"react-hook-form": "^7.22.1",
"react-icons": "^4.4.0",
"react-infinite-scroll-component": "^6.1.0",
"react-popper": "^2.2.5",
"react-redux": "^7.2.6",
Expand Down
Binary file added public/images/tokens/icon-quiz.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/components/Header/useMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,16 @@ const useMenu: UseMenu = () => {
title: 'Pools',
link: `/analytics/pools`,
},
{
key: 'kashi',
title: 'Kashi Pairs',
link: `/analytics/kashi/pairs`,
},
{
key: 'kashi',
title: 'Kashi Tokens',
link: `/analytics/kashi/tokens`,
},
],
}

Expand Down
156 changes: 156 additions & 0 deletions src/features/analytics/kashi/components/KashiMarketList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import Search from 'app/components/Search'
import SortIcon from 'app/components/SortIcon'
import Typography from 'app/components/Typography'
import KashiMarketListItem from 'app/features/kashi/KashiMarketListItem'
import { TABLE_TR_TH_CLASSNAME, TABLE_WRAPPER_DIV_CLASSNAME } from 'app/features/trident/constants'
import { classNames } from 'app/functions'
import { useFuse, useSortableData } from 'app/hooks'
import { useInfiniteScroll } from 'app/hooks/useInfiniteScroll'
import React, { FC, memo } from 'react'
import InfiniteScroll from 'react-infinite-scroll-component'

import { useKashiMediumRiskLendingPairs, useKashiPairAddresses } from '../../../kashi/hooks'
import { KashiMediumRiskLendingPair } from '../../../kashi/KashiMediumRiskLendingPair'
import KashiPairTotalCard from './KashiPairTotalCardEx'

interface KashiMarketList {}

const KashiMarketList: FC<KashiMarketList> = () => {
const addresses = useKashiPairAddresses()
const markets = useKashiMediumRiskLendingPairs(null, addresses)

const { i18n } = useLingui()
const { result, term, search } = useFuse<KashiMediumRiskLendingPair>({
data: markets,
options: {
keys: ['asset.token.symbol', 'collateral.token.symbol'],
threshold: 0.2,
shouldSort: false,
useExtendedSearch: false,
},
})

const { items, requestSort, sortConfig } = useSortableData(result, {
key: 'currentAllAssetsUSD',
direction: 'descending',
})

const [numDisplayed, setNumDisplayed] = useInfiniteScroll(items)

return (
<div className="flex flex-col w-full gap-6">
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
<KashiPairTotalCard data={markets} borrow="supply" loading={markets.length === 0} />
<KashiPairTotalCard data={markets} borrow="asset" loading={markets.length === 0} />
<KashiPairTotalCard data={markets} borrow="borrow" loading={markets.length === 0} />
</div>
<div className="flex flex-col items-center justify-between gap-4 sm:flex-row">
<Search search={(val) => search(val.toUpperCase())} term={term} />
</div>
<div className={classNames(TABLE_WRAPPER_DIV_CLASSNAME)}>
<div className="grid grid-cols-7 min-w-[1024px]">
<div
className={classNames('flex gap-1 items-center cursor-pointer', TABLE_TR_TH_CLASSNAME(0, 7))}
// onClick={() => requestSort('pair.token0.symbol')}
>
<Typography variant="sm" weight={700}>
{i18n._(t`Asset / Collateral`)}
</Typography>
{/*<SortIcon id={sortConfig.key} direction={sortConfig.direction} active={sortConfig.key === 'symbol'} />*/}
</div>
<div
className={classNames('flex gap-1 items-center cursor-pointer justify-end', TABLE_TR_TH_CLASSNAME(1, 7))}
onClick={() => requestSort('currentAllAssetsUSD')}
>
<Typography variant="sm" weight={700}>
{i18n._(t`TVL`)}
</Typography>
<SortIcon
id={sortConfig.key}
direction={sortConfig.direction}
active={sortConfig.key === 'currentAllAssetsUSD'}
/>
</div>
<div
className={classNames('flex gap-1 items-center cursor-pointer justify-end', TABLE_TR_TH_CLASSNAME(2, 7))}
onClick={() => requestSort('currentBorrowAmountUSD')}
>
<Typography variant="sm" weight={700}>
{i18n._(t`Borrowed`)}
</Typography>
<SortIcon
id={sortConfig.key}
direction={sortConfig.direction}
active={sortConfig.key === 'currentBorrowAmountUSD'}
/>
</div>

<div
className={classNames('flex gap-1 items-center cursor-pointer justify-end', TABLE_TR_TH_CLASSNAME(3, 7))}
onClick={() => requestSort('currentSupplyAPR')}
>
<Typography variant="sm" weight={700}>
{i18n._(t`Supply APR`)}
</Typography>
<SortIcon
id={sortConfig.key}
direction={sortConfig.direction}
active={sortConfig.key === 'currentSupplyAPR'}
/>
</div>

<div
className={classNames('flex gap-1 items-center cursor-pointer justify-end', TABLE_TR_TH_CLASSNAME(4, 7))}
onClick={() => requestSort('totalAssetAmountUSD')}
>
<Typography variant="sm" weight={700}>
{i18n._(t`Available`)}
</Typography>
<SortIcon
id={sortConfig.key}
direction={sortConfig.direction}
active={sortConfig.key === 'totalAssetAmountUSD'}
/>
</div>

<div
className={classNames('flex gap-1 items-center cursor-pointer justify-end', TABLE_TR_TH_CLASSNAME(5, 7))}
onClick={() => requestSort('currentInterestPerYear')}
>
<Typography variant="sm" weight={700}>
{i18n._(t`Borrow APR`)}
</Typography>
<SortIcon
id={sortConfig.key}
direction={sortConfig.direction}
active={sortConfig.key === 'currentInterestPerYear'}
/>
</div>
<div
className={classNames('flex gap-1 items-center cursor-pointer justify-end', TABLE_TR_TH_CLASSNAME(6, 7))}
>
<Typography variant="sm" weight={700}>
{i18n._(t`Actions`)}
</Typography>
</div>
</div>
<div className="min-w-[1024px]">
<InfiniteScroll
dataLength={numDisplayed}
next={() => setNumDisplayed(numDisplayed + 10)}
hasMore={numDisplayed <= items.length}
loader={null}
>
{items.slice(0, numDisplayed).map((market, index) => (
<KashiMarketListItem market={market} key={index} i18n={i18n} />
))}
</InfiniteScroll>
</div>
</div>
</div>
)
}

export default memo(KashiMarketList)
110 changes: 110 additions & 0 deletions src/features/analytics/kashi/components/KashiMarketListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { I18n } from '@lingui/core'
import { t } from '@lingui/macro'
import { CurrencyAmount, Percent } from '@sushiswap/core-sdk'
import { CurrencyLogoArray } from 'app/components/CurrencyLogo'
import Typography from 'app/components/Typography'
import { KashiMarketActions } from 'app/features/kashi/KashiMarket'
import { TABLE_TBODY_TD_CLASSNAME, TABLE_TBODY_TR_CLASSNAME } from 'app/features/trident/constants'
import { classNames, formatNumber, formatPercent } from 'app/functions'
import Link from 'next/link'
import React, { FC, memo, useMemo } from 'react'

import KashiMediumRiskLendingPair from '../../../kashi/KashiMediumRiskLendingPair'

interface KashiMarketListItem {
market: KashiMediumRiskLendingPair
i18n: I18n
}

const KashiMarketListItem: FC<KashiMarketListItem> = memo(({ market, i18n }) => {
const asset = market.asset.token
const collateral = market.collateral.token

// @ts-ignore
const currentAllAssets = useMemo(
() => (asset ? CurrencyAmount.fromRawAmount(asset, market.currentAllAssets) : undefined),
[asset, market.currentAllAssets]
)
// @ts-ignore
const currentBorrowAmount = useMemo(
() => (asset ? CurrencyAmount.fromRawAmount(asset, market.currentBorrowAmount) : undefined),
[asset, market.currentBorrowAmount]
)
// @ts-ignore
const totalAssetAmount = useMemo(
() => (asset ? CurrencyAmount.fromRawAmount(asset, market.totalAssetAmount) : undefined),
[asset, market.totalAssetAmount]
)

const currentSupplyAPR = new Percent(market.currentSupplyAPR, 1e18)

const currentInterestPerYear = new Percent(market.currentInterestPerYear, 1e18)

return (
<Link href={`/analytics/kashi/pairs/${market.address}`} passHref={true}>
<div className={classNames(TABLE_TBODY_TR_CLASSNAME, 'grid grid-cols-7 overflow-x-auto')} onClick={() => {}}>
<div className={classNames('flex gap-2', TABLE_TBODY_TD_CLASSNAME(0, 7))}>
{asset && collateral && <CurrencyLogoArray currencies={[asset, collateral]} dense size={32} />}
<div className="flex flex-col items-start">
<Typography weight={700} className="flex gap-1 text-high-emphesis">
{market.asset.token.symbol}
<span className="text-low-emphesis">/</span>
{market.collateral.token.symbol}
</Typography>
<Typography variant="xs" className="text-low-emphesis">
{market.oracle.name}
</Typography>
</div>
</div>
<div className={classNames('flex flex-col !items-end !justify-start', TABLE_TBODY_TD_CLASSNAME(1, 7))}>
<Typography weight={700} className="text-high-emphesis">
{formatNumber(market.currentAllAssetsUSD?.toFixed(0), true)}
</Typography>
<Typography variant="xs" className="text-low-emphesis">
{formatNumber(currentAllAssets?.toSignificant(6))} {market.asset.token.symbol}
</Typography>
</div>
<div className={classNames('flex flex-col !items-end !justify-start', TABLE_TBODY_TD_CLASSNAME(2, 7))}>
<Typography weight={700} className="text-high-emphesis">
{formatNumber(market.currentBorrowAmountUSD?.toFixed(0), true)}
</Typography>
<Typography variant="xs" className="text-low-emphesis">
{formatNumber(currentBorrowAmount?.toSignificant(6))} {market.asset.token.symbol}
</Typography>
</div>

<div className={classNames('flex flex-col !items-end', TABLE_TBODY_TD_CLASSNAME(3, 7))}>
<Typography weight={700} className="text-high-emphesis">
{formatPercent(currentSupplyAPR.toFixed(2))}
</Typography>
<Typography variant="xs" className="text-low-emphesis">
{i18n._(t`annualized`)}
</Typography>
</div>

<div className={classNames('flex flex-col !items-end !justify-start', TABLE_TBODY_TD_CLASSNAME(4, 7))}>
<Typography weight={700} className="text-high-emphesis">
{formatNumber(market.totalAssetAmountUSD?.toFixed(0), true)}
</Typography>
<Typography variant="xs" className="text-low-emphesis">
{formatNumber(totalAssetAmount?.toSignificant(6))} {market.asset.token.symbol}
</Typography>
</div>

<div className={classNames('flex flex-col !items-end', TABLE_TBODY_TD_CLASSNAME(5, 7))}>
<Typography weight={700} className="text-high-emphesis">
{formatPercent(currentInterestPerYear.toFixed(2))}
</Typography>
<Typography variant="xs" className="text-low-emphesis">
{i18n._(t`annualized`)}
</Typography>
</div>
<div className={classNames('flex flex-col !items-end', TABLE_TBODY_TD_CLASSNAME(6, 7))}>
<KashiMarketActions market={market} />
</div>
</div>
</Link>
)
})

export default memo(KashiMarketListItem)
Loading