Skip to content

Commit

Permalink
Centrifuge App: Prime detail (#1684)
Browse files Browse the repository at this point in the history
  • Loading branch information
onnovisser authored Nov 16, 2023
1 parent d15638f commit cf3c714
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 75 deletions.
6 changes: 3 additions & 3 deletions centrifuge-app/src/components/Portfolio/InvestedTokens.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Token, TokenBalance } from '@centrifuge/centrifuge-js'
import { formatBalance, useAddress, useBalances, useCentrifuge } from '@centrifuge/centrifuge-react'
import { formatBalance, useBalances, useCentrifuge } from '@centrifuge/centrifuge-react'
import {
AnchorButton,
Box,
Expand Down Expand Up @@ -29,6 +29,7 @@ type Row = {
position: TokenBalance
tokenPrice: TokenBalance
canInvestRedeem: boolean
address: string
}

const columns: Column[] = [
Expand Down Expand Up @@ -108,8 +109,7 @@ const columns: Column[] = [
]

// TODO: change canInvestRedeem to default to true once the drawer is implemented
export const InvestedTokens = ({ canInvestRedeem = false }) => {
const address = useAddress()
export function InvestedTokens({ canInvestRedeem = false, address }: { canInvestRedeem?: boolean; address: string }) {
const centBalances = useBalances(address)
const { data: tinlakeBalances } = useTinlakeBalances()
const pools = usePools()
Expand Down
83 changes: 43 additions & 40 deletions centrifuge-app/src/components/Portfolio/Transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,21 @@ import {
Stack,
Text,
usePagination,
VisualButton,
} from '@centrifuge/fabric'
import { isAddress as isValidEVMAddress } from '@ethersproject/address'
import * as React from 'react'
import { Link } from 'react-router-dom'
import { TransactionTypeChip } from '../../components/Portfolio/TransactionTypeChip'
import { Spinner } from '../../components/Spinner'
import { formatDate } from '../../utils/date'
import { Dec } from '../../utils/Decimal'
import { getCSVDownloadUrl } from '../../utils/getCSVDownloadUrl'
import { useAddress } from '../../utils/useAddress'
import { usePools, useTransactionsByAddress } from '../../utils/usePools'
import { Column, DataTable, SortableTableHeader } from '../DataTable'
import { RouterLinkButton } from '../RouterLinkButton'

type TransactionsProps = {
onlyMostRecent?: boolean
txTypes?: InvestorTransactionType[]
address: string
}

type TransactionTableData = Row[]
Expand Down Expand Up @@ -110,11 +108,9 @@ const columns: Column[] = [
},
]

export function Transactions({ onlyMostRecent, txTypes }: TransactionsProps) {
export function Transactions({ onlyMostRecent, txTypes, address }: TransactionsProps) {
const { formatAddress } = useCentrifugeUtils()
const address = useAddress()
const formattedAddress = address && isValidEVMAddress(address) ? address : formatAddress(address || '')
const transactions = useTransactionsByAddress(formatAddress(formattedAddress))
const transactions = useTransactionsByAddress(formatAddress(address))
const pools = usePools()

const investorTransactions: TransactionTableData = React.useMemo(() => {
Expand Down Expand Up @@ -158,45 +154,52 @@ export function Transactions({ onlyMostRecent, txTypes }: TransactionsProps) {

const pagination = usePagination({ data: investorTransactions, pageSize: onlyMostRecent ? 3 : 15 })

return !!investorTransactions.length ? (
return investorTransactions ? (
<Stack as="article" gap={onlyMostRecent ? 2 : 5}>
<Text as="h2" variant="heading2">
Transaction history
</Text>
<PaginationProvider pagination={pagination}>
<Stack gap={2}>
<DataTable
data={investorTransactions}
columns={columns}
pageSize={pagination.pageSize}
page={pagination.page}
/>
{onlyMostRecent ? (
<Link to="/history">
{investorTransactions.length ? (
<PaginationProvider pagination={pagination}>
<Stack gap={2}>
<DataTable
data={investorTransactions}
columns={columns}
pageSize={pagination.pageSize}
page={pagination.page}
/>
{onlyMostRecent ? (
<Box display="inline-block">
<VisualButton small variant="tertiary" icon={IconEye}>
<RouterLinkButton to="/history" small variant="tertiary" icon={IconEye}>
View all
</VisualButton>
</RouterLinkButton>
</Box>
</Link>
) : (
<Shelf justifyContent="space-between">
{pagination.pageCount > 1 && (
<Shelf>
<Pagination />
</Shelf>
)}
{csvUrl && (
<Box style={{ gridColumn: columns.length, justifySelf: 'end' }}>
<AnchorButton small variant="secondary" href={csvUrl} download={`transaction-history-${address}.csv`}>
Export as CSV
</AnchorButton>
</Box>
)}
</Shelf>
)}
</Stack>
</PaginationProvider>
) : (
<Shelf justifyContent="space-between">
{pagination.pageCount > 1 && (
<Shelf>
<Pagination />
</Shelf>
)}
{csvUrl && (
<Box style={{ gridColumn: columns.length, justifySelf: 'end' }}>
<AnchorButton
small
variant="secondary"
href={csvUrl}
download={`transaction-history-${address}.csv`}
>
Export as CSV
</AnchorButton>
</Box>
)}
</Shelf>
)}
</Stack>
</PaginationProvider>
) : (
<Text>No transactions</Text>
)}
</Stack>
) : (
<Spinner />
Expand Down
20 changes: 20 additions & 0 deletions centrifuge-app/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { TransactionOptions } from '@centrifuge/centrifuge-js'
import { Network } from '@centrifuge/centrifuge-react'
import { altairDark, centrifugeLight } from '@centrifuge/fabric'
import * as React from 'react'
import { DefaultTheme } from 'styled-components'
import aaveLogo from './assets/images/aave-token-logo.svg'
import { LogoAltair, LogoAltairText } from './components/LogoAltair'
import { LogoCentrifuge, LogoCentrifugeText } from './components/LogoCentrifuge'

Expand Down Expand Up @@ -143,3 +145,21 @@ export const ethConfig = {
}

export const config = import.meta.env.REACT_APP_NETWORK === 'altair' ? ALTAIR : CENTRIFUGE

export type DAO = {
slug: string
name: string
network: Network
address: string
icon: string
}

export const DAOs: DAO[] = [
{
slug: 'aave',
name: 'Aave',
network: 'centrifuge',
address: 'kALNreUp6oBmtfG87fe7MakWR8BnmQ4SmKjjfG27iVd3nuTue',
icon: aaveLogo,
},
]
6 changes: 3 additions & 3 deletions centrifuge-app/src/pages/Portfolio/TransactionHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import * as React from 'react'
import { LayoutBase } from '../../components/LayoutBase'
import { BasePadding } from '../../components/LayoutBase/BasePadding'
import { Transactions } from '../../components/Portfolio/Transactions'
import { useAddress } from '../../utils/useAddress'

export default function TransactionHistoryPage() {
const address = useAddress()
return (
<LayoutBase>
<BasePadding>
<Transactions />
</BasePadding>
<BasePadding>{address ? <Transactions address={address} /> : null}</BasePadding>
</LayoutBase>
)
}
4 changes: 2 additions & 2 deletions centrifuge-app/src/pages/Portfolio/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ function Portfolio() {
</Grid>
</BasePadding>
<BasePadding gap={3}>
<InvestedTokens />
<Transactions onlyMostRecent />
<InvestedTokens address={address} />
<Transactions onlyMostRecent address={address} />
<AssetAllocation address={address} />
</BasePadding>
<BasePadding>
Expand Down
40 changes: 38 additions & 2 deletions centrifuge-app/src/pages/Prime/Detail.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { useCentrifugeUtils } from '@centrifuge/centrifuge-react'
import { Box, Shelf, Text } from '@centrifuge/fabric'
import { useParams } from 'react-router'
import { LayoutBase } from '../../components/LayoutBase'
import { BasePadding } from '../../components/LayoutBase/BasePadding'
import { LayoutSection } from '../../components/LayoutBase/LayoutSection'
import { InvestedTokens } from '../../components/Portfolio/InvestedTokens'
import { Transactions } from '../../components/Portfolio/Transactions'
import { RouterTextLink } from '../../components/TextLink'
import { DAOs } from '../../config'

export default function PrimeDetailPage() {
return (
Expand All @@ -10,6 +18,34 @@ export default function PrimeDetailPage() {
}

function PrimeDetail() {
const { dao } = useParams<{ dao: string }>()
return <div>Prime detail, {dao}</div>
const { dao: daoSlug } = useParams<{ dao: string }>()
const dao = DAOs.find((d) => d.slug === daoSlug)
const utils = useCentrifugeUtils()
if (!dao) throw new Error('DAO not found')
const centAddress = utils.formatAddress(
typeof dao.network === 'number' ? utils.evmToSubstrateAddress(dao.address, dao.network) : dao.address
)

return (
<>
<LayoutSection backgroundColor="backgroundSecondary" alignItems="flex-start" pt={5}>
<Text variant="body3">
<Text color="textSecondary">
<RouterTextLink to="/prime" style={{ textDecoration: 'none' }}>
Prime
</RouterTextLink>
</Text>{' '}
/ {dao.name} DAO Investments
</Text>
<Shelf gap={2}>
<Box as="img" src={dao.icon} alt={dao.name} width="iconRegular" height="iconRegular" borderRadius="50%" />
<Text variant="heading1">{dao.name} DAO Investments</Text>
</Shelf>
</LayoutSection>
<BasePadding gap={3}>
<InvestedTokens address={centAddress} />
<Transactions onlyMostRecent address={centAddress} />
</BasePadding>
</>
)
}
22 changes: 2 additions & 20 deletions centrifuge-app/src/pages/Prime/index.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
import { Price } from '@centrifuge/centrifuge-js'
import { Network, useCentrifuge, useCentrifugeUtils, useGetNetworkName } from '@centrifuge/centrifuge-react'
import { useCentrifuge, useCentrifugeUtils, useGetNetworkName } from '@centrifuge/centrifuge-react'
import { AnchorButton, Box, IconExternalLink, Shelf, Text, TextWithPlaceholder } from '@centrifuge/fabric'
import { useQuery } from 'react-query'
import { firstValueFrom } from 'rxjs'
import aaveLogo from '../../assets/images/aave-token-logo.svg'
import { Column, DataTable, FilterableTableHeader, SortableTableHeader } from '../../components/DataTable'
import { LayoutBase } from '../../components/LayoutBase'
import { LayoutSection } from '../../components/LayoutBase/LayoutSection'
import { DAO, DAOs } from '../../config'
import { formatDate } from '../../utils/date'
import { formatBalance, formatPercentage } from '../../utils/formatting'
import { useFilters } from '../../utils/useFilters'
import { useSubquery } from '../../utils/useSubquery'

type DAO = {
slug: string
name: string
network: Network
address: string
icon: string
}

const DAOs: DAO[] = [
{
slug: 'aave',
name: 'Aave',
network: 'centrifuge',
address: 'kALNreUp6oBmtfG87fe7MakWR8BnmQ4SmKjjfG27iVd3nuTue',
icon: aaveLogo,
},
]

export default function PrimePage() {
return (
<LayoutBase>
Expand Down
7 changes: 6 additions & 1 deletion centrifuge-js/src/modules/pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2058,7 +2058,12 @@ export function getPoolsModule(inst: Centrifuge) {

return $query.pipe(
switchMap((data) => {
const poolIds = new Set(data?.investorTransactions.nodes.map((e) => e.poolId)) ?? []
const poolIds = new Set(data?.investorTransactions.nodes.map((e) => e.poolId) ?? [])
if (!poolIds.size) {
return of({
investorTransactions: [],
})
}
const $poolCurrencies = Array.from(poolIds).map((poolId) => getPoolCurrency([poolId]))
return combineLatest($poolCurrencies).pipe(
map((currencies) => {
Expand Down
6 changes: 4 additions & 2 deletions centrifuge-react/src/components/WalletMenu/ConnectButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ type Props = WalletButtonProps & {
}

export function ConnectButton({ label = 'Connect', ...rest }: Props) {
const { showNetworks } = useWallet()
const { showNetworks, pendingConnect } = useWallet()

return <WalletButton connectLabel={label} onClick={() => showNetworks()} {...rest} />
return (
<WalletButton connectLabel={label} loading={pendingConnect.isConnecting} onClick={() => showNetworks()} {...rest} />
)
}
4 changes: 2 additions & 2 deletions centrifuge-react/src/components/WalletMenu/WalletMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ type WalletMenuProps = {

export function WalletMenu({ menuItems }: WalletMenuProps) {
const ctx = useWallet()
const { connectedType, pendingConnect, isEvmOnSubstrate } = ctx
const { connectedType, isEvmOnSubstrate } = ctx
const accounts = connectedType && ctx[isEvmOnSubstrate ? 'substrate' : 'evm'].accounts
const address = useAddress()
return address ? (
<ConnectedMenu menuItems={menuItems} />
) : accounts && !accounts.length ? (
<ConnectButton label="No accounts available" />
) : (
<ConnectButton loading={pendingConnect.isConnecting} />
<ConnectButton />
)
}

Expand Down
1 change: 1 addition & 0 deletions centrifuge-react/src/components/WalletMenu/index.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './ConnectButton'
export * from './WalletMenu'

0 comments on commit cf3c714

Please sign in to comment.