Skip to content

Commit

Permalink
feat: add new assets REG, REG Vote Power (#91)
Browse files Browse the repository at this point in the history
* first version : Assets as rows

* 'other' assets display switch; 'other' assets shown in Summary

'other' assets = tokens others than RealTokens = RWA, REG, ...

- Display switch for hiding 'other' assets in table rows
- 'other' assets figures added to Summary section

* contracts utils

* use contract utils for fetching balances

* Eth provider removed: REG Voting Power is not deployed on Eth

* batchCallOneFunction

not fully tested

* error args

* comments

* wrong 'inheritance'

* smol fix: properly throw 'User not found' error

* style/comments

* settings labels and icons

* unitIcon: optional + alignment with other units

* Filter 'other' assets in Grid view

* Settings: switch icons, section names

* fix: lint warning

* fix: lint warning

* fix: build error ?

* fix: build error #2 ?

* fix: build error #3 ?

* fix: build error #4 ?

* fix: build error #5 ?

* Fix: existing filter error when filtering on "Owned on"

* fix: avoid fetching others assets balances if user wallet was not set

* feat: add other token price on cards and fix decimals rounds for total invest

* fix: improve subsudy filter for exclude other realtokens

* fix: fix last changes filter and use correct typing in filters for avoid futurs errors

* feat: set initial launch date for RWA token

* feat: initialize rpc provider only once

* feat: include reg tokens locked inside the incentive vault

* fix: fix eslint warnings and add missing translations

* Update .gitignore

exclude pnpm lockfile

* Create .nvmrc

add .nvmrc for switching between node versions

* Update contract.ts

optional  parameters for customizing batch calls: batch max and min size, number of attempts before giving up

* Regvotingpower: icon orange, size grows depending on amount

* unused import

* Usdc currency/rate

* Voting power size & fill color depending on power amount

* Voting power size & fill color depending on power amount

* Fixes: token prices in USD, avoid fetching REG vault balances on Eth

- Tokens values fix: Updated assets prices by using currenciesRates and user currency rate (previously considering usdc = usd and xdai = usd as well),
now assets prices are converted from their respective currencies (e.g. usdc, xdai) to usd, then total value is priced in user choosen currency.
- Smol fix: getAddressesLockedBalances was fetching vault balances on Eth, throwing errors as there is not such vault on Eth.
Added parameters for fetching any number of vault by provider(s).

* comment

* Check Providers ability to handle requests

- Check Providers ability to handle requests
- Additionnal providers
https://rpc.ankr.com/eth and https://eth-pokt.nodies.app currently fail to handle concurrent requests

* Assets hooks moved in index for avoiding duplicate requests

- Both SummaryCard and AssetsView use the same hooks for getting their data, leading to duplicate web3 requests
Moving hooks in parent components prevents this form happening.

* prettier

* Avoid divide by zero in case asset.totalUnits is unknown/zero

* "Clean" scripts

* Assets filtering moved to the right place

filter has to be in assetsView/AssetsView.tsx

* Paging translation labels: placeholder, All

* simplify pageSize handling

* Assets filtering fix (causing pagination issues)

OtherAssets filtering was improperly implemented into the map loops by skipping non "others assets" value, causing holes in display (missing cards).
Filtering is now done in AssetsView where it should have been in the first place

* Revert changes: realtime/global labels for rents calculation switch

---------

Co-authored-by: Jycssu <[email protected]>
  • Loading branch information
BenoistP and jycssu-com authored Dec 17, 2024
1 parent d32387f commit 81848e4
Show file tree
Hide file tree
Showing 49 changed files with 2,433 additions and 215 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ yarn-error.log*

# typescript
*.tsbuildinfo
pnpm-lock.yaml
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v18.20.4
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const nextConfig = {
outputStandalone: true,
},
images: {
domains: ['realt.co'],
domains: ['realt.co', 'static.debank.com'],
},
publicRuntimeConfig: {
version,
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"prettier:check": "prettier --check src/.",
"prettier:format": "prettier --write src/.",
"export": "next build && next export",
"docker:local": "docker compose -f docker-compose.local.yml up --force-recreate --build"
"docker:local": "docker compose -f docker-compose.local.yml up --force-recreate --build",
"clean:cache": "del-cli .next",
"clean:mod": "del-cli node_modules",
"clean:all": "npm run clean:cache && npm run clean:mod",
"clean:build": "npm run clean:cache && npm run build"
},
"dependencies": {
"@apollo/client": "^3.9.5",
Expand All @@ -27,6 +31,7 @@
"cookies-next": "^2.0.5",
"date-fns": "^3.3.1",
"dayjs": "^1.11.11",
"del-cli": "^6.0.0",
"dexie": "^3.2.5",
"ethers": "^6.11.1",
"graphql": "^16.6.0",
Expand Down
44 changes: 32 additions & 12 deletions src/components/assetsView/AssetsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { useSelector } from 'react-redux'

import { Grid } from '@mantine/core'

import { useRWA } from 'src/hooks/useRWA'
import { selectUserRealtokens } from 'src/store/features/wallets/walletsSelector'
import { selectUserIncludesOtherAssets } from 'src/store/features/settings/settingsSelector'
import {
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

import { AssetsViewSearch, useAssetsViewSearch } from './AssetsViewSearch'
import { AssetsViewSelect, useAssetsViewSelect } from './assetsViewSelect'
Expand All @@ -14,20 +17,37 @@ import { RealtimeIndicator } from './indicators/RealtimeIndicator'
import { AssetViewType } from './types'
import { AssetGrid, AssetTable } from './views'

export const AssetsView: FC = () => {
interface AssetsViewProps {
allAssetsData: (UserRealtoken | OtherRealtoken)[]
}

export const AssetsView: FC<AssetsViewProps> = ({
allAssetsData: assetsData,
}) => {
const { assetsViewFilterFunction } = useAssetsViewFilters()
const { assetSearchFunction, assetSearchProps } = useAssetsViewSearch()
const { choosenAssetView } = useAssetsViewSelect()
const showOtherAssets = useSelector(selectUserIncludesOtherAssets)

const realtokens = useSelector(selectUserRealtokens)
const rwa = useRWA()
// Check if asset is a UserRealtoken or OtherRealtoken
const isOtherAsset = (asset: UserRealtoken | OtherRealtoken) => {
return !asset.hasOwnProperty('rentStatus') // rely on rentStatus to determine if it's a UserRealtoken
}

const data = useMemo(() => {
const assets = rwa ? [...realtokens, rwa] : realtokens
return assetsViewFilterFunction(assets.filter(assetSearchFunction))
}, [realtokens, rwa, assetSearchFunction, assetsViewFilterFunction])
// Apply search and filter functions
const filteredData = useMemo(() => {
// First filter by user advanced filters
const advancedFilteredAssets = assetsViewFilterFunction(
assetsData.filter(assetSearchFunction),
)
// Then filter out OtherRealtoken
const othersAssetsFiltering = showOtherAssets
? advancedFilteredAssets
: advancedFilteredAssets.filter((asset) => !isOtherAsset(asset))
return othersAssetsFiltering
}, [assetsData, assetSearchFunction, assetsViewFilterFunction])

return realtokens.length ? (
return assetsData.length ? (
<>
<Grid align={'center'}>
<Grid.Col
Expand All @@ -45,10 +65,10 @@ export const AssetsView: FC = () => {
</Grid.Col>
</Grid>
{choosenAssetView == AssetViewType.TABLE && (
<AssetTable key={'table'} realtokens={data} />
<AssetTable key={'table'} realtokens={filteredData} />
)}
{choosenAssetView == AssetViewType.GRID && (
<AssetGrid key={'grid'} realtokens={data} />
<AssetGrid key={'grid'} realtokens={filteredData} />
)}
</>
) : null
Expand Down
8 changes: 4 additions & 4 deletions src/components/assetsView/AssetsViewSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
import { TextInput } from '@mantine/core'

import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -39,11 +39,11 @@ export function useAssetsViewSearch() {
[assetSearch],
)

function assetSearchFunction(asset: UserRealtoken | RWARealtoken) {
function assetSearchFunction(asset: UserRealtoken | OtherRealtoken) {
return (
!cleanSearch ||
asset.shortName.toLowerCase().includes(cleanSearch) ||
asset.fullName.toLowerCase().includes(cleanSearch)
asset?.shortName?.toLowerCase().includes(cleanSearch) ||
asset?.fullName?.toLowerCase().includes(cleanSearch)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
import { Select } from '@mantine/core'

import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -61,7 +61,9 @@ AssetsViewRentStatusFilter.displayName = 'AssetsViewRentStatusFilter'
export function useAssetsViewRentStatusFilter(
filter: AssetsViewRentStatusFilterModel,
) {
function assetRentStatusFilterFunction(asset: UserRealtoken | RWARealtoken) {
function assetRentStatusFilterFunction(
asset: UserRealtoken | OtherRealtoken,
) {
const Asset = asset as UserRealtoken
switch (filter.rentStatus) {
case AssetRentStatusType.ALL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
import { Select } from '@mantine/core'

import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -56,7 +56,7 @@ AssetsViewRmmStatusFilter.displayName = 'AssetsViewRmmStatusFilter'
export function useAssetsViewRmmStatusFilter(
filter: AssetsViewRmmStatusFilterModel,
) {
function assetRmmStatusFilterFunction(asset: UserRealtoken | RWARealtoken) {
function assetRmmStatusFilterFunction(asset: UserRealtoken | OtherRealtoken) {
const Asset = asset as UserRealtoken
switch (filter.rmmStatus) {
case AssetRmmStatusType.ALL:
Expand Down
55 changes: 31 additions & 24 deletions src/components/assetsView/filters/AssetsViewSort.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Grid, Select, Switch } from '@mantine/core'

import { selectTransfersIsLoaded } from 'src/store/features/transfers/transfersSelector'
import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -92,51 +92,58 @@ export const AssetsViewSort: FC<AssetsViewSortProps> = ({
}
AssetsViewSort.displayName = 'AssetsViewSort'

type MixedRealtoken = Partial<UserRealtoken> &
Partial<OtherRealtoken> &
Pick<UserRealtoken, keyof OtherRealtoken>

export function useAssetsViewSort(filter: AssetsViewSortFilter) {
function assetSortFunction(
a: UserRealtoken | RWARealtoken,
b: UserRealtoken | RWARealtoken,
a: UserRealtoken | OtherRealtoken,
b: UserRealtoken | OtherRealtoken,
) {
const value = getAssetSortValue(a, b)
return filter.sortReverse ? value * -1 : value
}
function getAssetSortValue(
a: UserRealtoken | RWARealtoken,
b: UserRealtoken | RWARealtoken,
) {
const A = a as UserRealtoken
const B = b as UserRealtoken
function getAssetSortValue(a: MixedRealtoken, b: MixedRealtoken) {
switch (filter.sortBy) {
case AssetSortType.VALUE:
return B.value - A.value
return b.value - a.value
case AssetSortType.APR:
return B.annualPercentageYield - A.annualPercentageYield
return (b.annualPercentageYield ?? 0) - (a.annualPercentageYield ?? 0)
case AssetSortType.RENT:
return B.amount * B.netRentDayPerToken - A.amount * A.netRentDayPerToken
return (
b.amount * (b.netRentDayPerToken ?? 0) -
a.amount * (a.netRentDayPerToken ?? 0)
)
case AssetSortType.RENT_START:
return B.rentStartDate?.date.localeCompare(A.rentStartDate?.date)
return (b.rentStartDate?.date ?? '').localeCompare(
a.rentStartDate?.date ?? '',
)
case AssetSortType.NAME:
return A.shortName.localeCompare(b.shortName)
return a.shortName.localeCompare(b.shortName)
case AssetSortType.SUPPLY:
return B.totalInvestment - A.totalInvestment
return b.totalInvestment - a.totalInvestment
case AssetSortType.TOKEN:
return B.amount - A.amount
return b.amount - a.amount
case AssetSortType.TOTAL_UNIT:
return B.totalUnits - A.totalUnits
return (b.totalUnits ?? 0) - (a.totalUnits ?? 0)
case AssetSortType.RENTED_UNIT:
return B.rentedUnits - A.rentedUnits
return (b.rentedUnits ?? 0) - (a.rentedUnits ?? 0)
case AssetSortType.OCCUPANCY:
return B.rentedUnits / B.totalUnits - A.rentedUnits / A.totalUnits
return (
(b.rentedUnits ?? 0) / (b.totalUnits ?? 1) -
(a.rentedUnits ?? 0) / (a.totalUnits ?? 1)
)
case AssetSortType.INITIAL_LAUNCH:
return B.initialLaunchDate?.date.localeCompare(
A.initialLaunchDate?.date,
return (b.initialLaunchDate?.date ?? '').localeCompare(
a.initialLaunchDate?.date ?? '',
)
case AssetSortType.UNIT_PRICE_COST:
return (B.unitPriceCost ?? 0) - (A.unitPriceCost ?? 0)
return (b.unitPriceCost ?? 0) - (a.unitPriceCost ?? 0)
case AssetSortType.UNREALIZED_CAPITAL_GAIN:
return (B.unrealizedCapitalGain ?? 0) - (A.unrealizedCapitalGain ?? 0)
return (b.unrealizedCapitalGain ?? 0) - (a.unrealizedCapitalGain ?? 0)
case AssetSortType.LAST_CHANGE:
return B.lastChanges.localeCompare(A.lastChanges) ?? 0
return (b.lastChanges ?? '').localeCompare(a.lastChanges ?? '')
}
}

Expand Down
31 changes: 24 additions & 7 deletions src/components/assetsView/filters/AssetsViewSubsidyFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
import { Select } from '@mantine/core'

import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -76,23 +76,40 @@ AssetsViewSubsidyFilter.displayName = 'AssetsViewSubsidyFilter'
export function useAssetsViewSubsidyFilter(
filter: AssetsViewSubsidyFilterModel,
) {
function assetSubsidyFilterFunction(asset: UserRealtoken | RWARealtoken) {
function assetSubsidyFilterFunction(asset: UserRealtoken | OtherRealtoken) {
const Asset = asset as UserRealtoken
switch (filter.subsidy) {
case AssetSubsidyType.ALL:
return true
case AssetSubsidyType.SUBSIDIZED:
return Asset.subsidyStatus !== 'no'
return Asset.subsidyStatus && Asset.subsidyStatus !== 'no'
case AssetSubsidyType.FULLY_SUBSIDIZED:
return Asset.subsidyStatus === 'yes' && !!Asset.subsidyStatusValue
return (
Asset.subsidyStatus &&
Asset.subsidyStatus === 'yes' &&
!!Asset.subsidyStatusValue
)
case AssetSubsidyType.PARTIALLY_SUBSIDIZED:
return Asset.subsidyStatus !== 'no' && !!Asset.subsidyStatusValue
return (
Asset.subsidyStatus &&
Asset.subsidyStatus !== 'no' &&
!!Asset.subsidyStatusValue
)
case AssetSubsidyType.SECTION_8:
return Asset.subsidyStatus !== 'no' && Asset.subsidyBy === 'Section 8'
return (
Asset.subsidyStatus &&
Asset.subsidyStatus !== 'no' &&
Asset.subsidyBy === 'Section 8'
)
case AssetSubsidyType.SECTION_42:
return Asset.subsidyStatus !== 'no' && Asset.subsidyBy === 'Section 42'
return (
Asset.subsidyStatus &&
Asset.subsidyStatus !== 'no' &&
Asset.subsidyBy === 'Section 42'
)
case AssetSubsidyType.OTHER_SUBSIDY:
return (
Asset.subsidyStatus &&
Asset.subsidyStatus !== 'no' &&
!['Section 8', 'Section 42'].includes(Asset.subsidyBy ?? '')
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
import { Select } from '@mantine/core'

import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -66,20 +66,20 @@ export function useAssetsViewUserProtocolFilter(
filter: AssetsViewUserProtocolFilterModel,
) {
function assetUserProtocolFilterFunction(
asset: UserRealtoken | RWARealtoken,
asset: UserRealtoken | OtherRealtoken,
) {
const Asset = asset as UserRealtoken
switch (filter.userProtocol) {
case AssetUserProtocolType.ALL:
return true
case AssetUserProtocolType.ETHEREUM:
return Asset.balance.ethereum.amount > 0
return Asset.balance?.ethereum?.amount > 0
case AssetUserProtocolType.GNOSIS:
return Asset.balance.gnosis.amount > 0
return Asset.balance?.gnosis?.amount > 0
case AssetUserProtocolType.RMM:
return Asset.balance.rmm.amount > 0
return Asset.balance?.rmm?.amount > 0
case AssetUserProtocolType.LEVINSWAP:
return Asset.balance.levinSwap.amount > 0
return Asset.balance?.levinSwap?.amount > 0
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
import { Select } from '@mantine/core'

import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -69,7 +69,9 @@ AssetsViewUserStatusFilter.displayName = 'AssetsViewUserStatusFilter'
export function useAssetsViewUserStatusFilter(
filter: AssetsViewUserStatusFilterModel,
) {
function assetUserStatusFilterFunction(asset: UserRealtoken | RWARealtoken) {
function assetUserStatusFilterFunction(
asset: UserRealtoken | OtherRealtoken,
) {
const Asset = asset as UserRealtoken
switch (filter.userStatus) {
case AssetUserStatusType.ALL:
Expand Down
4 changes: 2 additions & 2 deletions src/components/assetsView/filters/useFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useAtom } from 'jotai'

import { assetsViewDefaultFilter, assetsViewFilterAtom } from 'src/states'
import {
RWARealtoken,
OtherRealtoken,
UserRealtoken,
} from 'src/store/features/wallets/walletsSelector'

Expand Down Expand Up @@ -30,7 +30,7 @@ export function useAssetsViewFilters() {
useAssetsViewUserProtocolFilter(activeFilter)

function assetsViewFilterFunction(
tokenList: (UserRealtoken | RWARealtoken)[],
tokenList: (UserRealtoken | OtherRealtoken)[],
) {
return tokenList
.filter(assetUserStatusFilterFunction)
Expand Down
Loading

0 comments on commit 81848e4

Please sign in to comment.