Skip to content

Commit

Permalink
Add hard code for tinlake
Browse files Browse the repository at this point in the history
  • Loading branch information
kattylucy committed Oct 11, 2024
1 parent f7fe56b commit 70c8519
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 48 deletions.
142 changes: 102 additions & 40 deletions centrifuge-app/src/components/PoolCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CurrencyBalance, Rate, Token } from '@centrifuge/centrifuge-js'
import { Box, Card, Divider, Stack, Text, Thumbnail } from '@centrifuge/fabric'
import Decimal from 'decimal.js-light'
import { useMemo } from 'react'
import styled from 'styled-components'
import { daysBetween } from '../../utils/date'
import { formatBalance, formatBalanceAbbreviated, formatPercentage } from '../../utils/formatting'
Expand All @@ -24,6 +25,10 @@ export type MetaData = {
}
}

type TinlakeTranchesKey = 'silver' | 'blocktowerThree' | 'blocktowerFour'

type TrancheWithCurrency = Pick<Token, 'yield30DaysAnnualized' | 'interestRatePerSec' | 'currency' | 'id'>

const StyledRouterTextLink = styled(RouterTextLink)`
font-size: 12px;
margin-top: 8px;
Expand All @@ -32,7 +37,8 @@ const StyledRouterTextLink = styled(RouterTextLink)`
const StyledCard = styled(Card)`
width: 100%;
max-width: 100%;
height: 320px;
height: 340px;
margin-right: 12px;
margin-bottom: 12px;
padding: 12px;
Expand All @@ -50,6 +56,36 @@ const StyledCard = styled(Card)`
}
`

const tinlakeTranches = {
silver: {
Junior: '15%',
Senior: '7%',
shortDescription:
'The New Silver 2 pool funds real estate bridge loans for fix and flip projects, maturing in 12-24 months.',
InvestorType: 'Qualified Investors',
},
blocktowerThree: {
Junior: '15%',
Senior: '4% - 15%',
shortDescription:
'BlockTower Credit’s BT3 pool invests in investment-grade consumer ABS, auto ABS, and CLOs under 4 years.',
InvestorType: 'Private',
},
blocktowerFour: {
Junior: '15%',
Senior: '4%',
shortDescription:
'BlockTower Credit’s BT4 pool invests in investment-grade consumer ABS, auto ABS, and CLOs under 4 years.',
InvestorType: 'Private',
},
none: {
Junior: '-',
Senior: '-',
shortDescription: '',
InvestorType: '-',
},
}

export type PoolCardProps = {
poolId?: string
name?: string
Expand All @@ -59,7 +95,7 @@ export type PoolCardProps = {
apr?: Rate | null | undefined
status?: PoolStatusKey
iconUri?: string
tranches?: Pick<Token, 'yield30DaysAnnualized' | 'interestRatePerSec' | 'currency' | 'id'>[]
tranches?: TrancheWithCurrency[]
metaData?: MetaData
createdAt?: string
}
Expand All @@ -77,41 +113,61 @@ export function PoolCard({
createdAt,
}: PoolCardProps) {
const isOneTranche = tranches && tranches?.length === 1
const isTinlakePool =
poolId === '0x53b2d22d07E069a3b132BfeaaD275b10273d381E' ||
poolId === '0x90040F96aB8f291b6d43A8972806e977631aFFdE' ||
poolId === '0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7'

const tinlakeObjKey = () => {
if (name?.includes('Silver')) return 'silver'
else if (name?.includes('BlockTower Series 3')) return 'blocktowerThree'
else if (name?.includes('BlockTower Series 4')) return 'blocktowerFour'
else return 'none'
}

const getTinlakeMinInvestment = (trancheName: 'Junior' | 'Senior') => {
if (name?.includes('Silver') && trancheName === 'Senior') return '5K'
else return '-'
}

const renderText = (text: string) => (
<Text fontWeight={500} as="h2" variant="body1">
{text}
</Text>
)

const tranchesData = tranches
?.map((tranche) => {
const words = tranche.currency.name.trim().split(' ')
const metadata = metaData?.tranches[tranche.id] ?? null
const trancheName = words[words.length - 1]
const investmentBalance = new CurrencyBalance(
metadata?.minInitialInvestment ?? 0,
tranche.currency.decimals
).toDecimal()

const daysSinceCreation = createdAt ? daysBetween(createdAt, new Date()) : 0

function calculateApy() {
if (poolId === '4139607887') return formatPercentage(5, true, {}, 1)
if (poolId === '1655476167') return formatPercentage(15, true, {}, 1)
if (daysSinceCreation > 30 && tranche.yield30DaysAnnualized)
return formatPercentage(tranche.yield30DaysAnnualized, true, {}, 1)
if (tranche.interestRatePerSec) return formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, {}, 1)
return '-'
}

return {
name: trancheName,
apr: calculateApy(),
minInvestment:
metadata && metadata.minInitialInvestment ? `$${formatBalanceAbbreviated(investmentBalance, '', 0)}` : '-',
}
})
.reverse()
const calculateApy = (tranche: TrancheWithCurrency) => {
const daysSinceCreation = createdAt ? daysBetween(createdAt, new Date()) : 0
if (daysSinceCreation > 30 && tranche.yield30DaysAnnualized)
return formatPercentage(tranche.yield30DaysAnnualized, true, {}, 1)
if (tranche.interestRatePerSec) return formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, {}, 1)
return '-'
}

const tranchesData = useMemo(() => {
return tranches
?.map((tranche: TrancheWithCurrency) => {
const key = tinlakeObjKey() as TinlakeTranchesKey
const words = tranche.currency.name.trim().split(' ')
const metadata = metaData?.tranches[tranche.id] ?? null
const trancheName = words[words.length - 1]
const investmentBalance = new CurrencyBalance(
metadata?.minInitialInvestment ?? 0,
tranche.currency.decimals
).toDecimal()

return {
name: trancheName,
apr: isTinlakePool ? tinlakeTranches[key][trancheName as 'Junior' | 'Senior'] : calculateApy(tranche),
minInvestment: isTinlakePool
? getTinlakeMinInvestment(trancheName as 'Junior' | 'Senior')
: metadata && metadata.minInitialInvestment
? `$${formatBalanceAbbreviated(investmentBalance, '', 0)}`
: '-',
}
})
.reverse()
}, [calculateApy, getTinlakeMinInvestment])

Check warning on line 170 in centrifuge-app/src/components/PoolCard/index.tsx

View workflow job for this annotation

GitHub Actions / build-app

React Hook useMemo has missing dependencies: 'isTinlakePool', 'metaData?.tranches', 'tinlakeObjKey', and 'tranches'. Either include them or remove the dependency array

Check warning on line 170 in centrifuge-app/src/components/PoolCard/index.tsx

View workflow job for this annotation

GitHub Actions / ff-prod / build-app

React Hook useMemo has missing dependencies: 'isTinlakePool', 'metaData?.tranches', 'tinlakeObjKey', and 'tranches'. Either include them or remove the dependency array

return (
<RouterTextLink to={`${poolId}`} style={{ textDecoration: 'none' }}>
Expand Down Expand Up @@ -169,20 +225,26 @@ export function PoolCard({
{tranchesData?.map((tranche) => renderText(`${tranche.minInvestment}`))}
</Stack>
</Box>
{metaData?.pool?.issuer?.shortDescription && (
<Box marginY={12}>
<Text as="p" variant="body2" color="textButtonPrimaryDisabled">
{metaData?.pool?.issuer?.shortDescription}
</Text>
</Box>
)}
{metaData?.pool?.issuer?.shortDescription ||
(isTinlakePool && (
<Box marginY={12}>
<Text as="p" variant="body2" color="textButtonPrimaryDisabled">
{isTinlakePool
? tinlakeTranches[tinlakeObjKey()].shortDescription
: metaData?.pool?.issuer?.shortDescription}
</Text>
</Box>
))}
<Box display="flex" justifyContent="space-between">
<Text variant="body2">{assetClass && 'Asset type'}</Text>
<Text variant="body2">{assetClass ?? ''}</Text>
</Box>
<Box display="flex" justifyContent="space-between">
<Text variant="body2">{metaData?.pool?.investorType && 'Investor Type'}</Text>
<Text variant="body2"> {metaData?.pool?.investorType ?? ''}</Text>
<Text variant="body2">Investor Type</Text>
<Text variant="body2">
{' '}
{isTinlakePool ? tinlakeTranches[tinlakeObjKey()].InvestorType : metaData?.pool?.investorType ?? '-'}
</Text>
</Box>
</StyledCard>
</RouterTextLink>
Expand Down
2 changes: 1 addition & 1 deletion centrifuge-app/src/components/PoolList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ export function poolsToPoolCardProps(
): PoolCardProps[] {
return pools.map((pool) => {
const metaData = typeof pool.metadata === 'string' ? metaDataById[pool.id] : pool.metadata

return {
poolId: pool.id,
name: metaData?.pool?.name,
Expand All @@ -151,6 +150,7 @@ export function poolsToPoolCardProps(
iconUri: metaData?.pool?.icon?.uri ? cent.metadata.parseMetadataUrl(metaData?.pool?.icon?.uri) : undefined,
tranches: pool.tranches,
metaData: metaData as MetaData,
createdAt: pool.createdAt ?? '',
}
})
}
Expand Down
22 changes: 18 additions & 4 deletions centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ type Tranche = Pick<DailyTrancheState, 'id'> & {
}
}

type TinlakeDataKey =
| '0x53b2d22d07E069a3b132BfeaaD275b10273d381E'
| '0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7'
| '0x90040F96aB8f291b6d43A8972806e977631aFFdE'

const tinlakeData = {
'0x53b2d22d07E069a3b132BfeaaD275b10273d381E': '7% - 15% target',
'0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7': '4% - 15% target',
'0x90040F96aB8f291b6d43A8972806e977631aFFdE': '4% - 15% target',
}

const getTodayValue = (data: DailyTrancheStateArr | null | undefined): DailyTrancheStateArr | undefined => {
if (!data) return
if (!Object.keys(data).length) return
Expand Down Expand Up @@ -95,8 +106,9 @@ export const KeyMetrics = ({ poolId }: Props) => {
}, [metadata?.tranches, pool.currency.decimals])

const isBT3BT4 =
poolId.toLowerCase() === '0x90040f96ab8f291b6d43a8972806e977631affde' ||
poolId.toLowerCase() === '0x55d86d51ac3bcab7ab7d2124931fba106c8b60c7'
poolId === '0x53b2d22d07E069a3b132BfeaaD275b10273d381E' ||
poolId === '0x90040F96aB8f291b6d43A8972806e977631aFFdE' ||
poolId === '0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7'

const metrics = [
{
Expand All @@ -109,6 +121,8 @@ export const KeyMetrics = ({ poolId }: Props) => {
? tranchesAPY.map((tranche, index) => {
return tranche && `${tranche} ${index !== tranchesAPY?.length - 1 ? '-' : ''} `
})
: tinlakeData[poolId as TinlakeDataKey]
? tinlakeData[poolId as TinlakeDataKey]
: '-',
},
...(isBT3BT4
Expand All @@ -129,7 +143,7 @@ export const KeyMetrics = ({ poolId }: Props) => {
},
{
metric: 'Investor type',
value: metadata?.pool?.investorType ? metadata?.pool?.investorType : '-',
value: isBT3BT4 ? 'Private' : metadata?.pool?.investorType ?? '-',
},
...(!isTinlakePool
? [
Expand All @@ -142,7 +156,7 @@ export const KeyMetrics = ({ poolId }: Props) => {

{
metric: 'Pool structure',
value: metadata?.pool?.poolStructure ? metadata?.pool?.poolStructure : '-',
value: isBT3BT4 ? 'Revolving' : metadata?.pool?.poolStructure ?? '-',
},
...(metadata?.pool?.rating?.ratingValue
? [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,15 @@ export const TransactionHistoryTable = ({
{
align: 'left',
header: <SortableTableHeader label="Transaction" />,
cell: ({ activeAssetId, assetId, assetName, fromAssetId, toAssetId, toAssetName, label, sublabel }: Row) => {
cell: ({ assetId, assetName, toAssetId, toAssetName, label, sublabel, fromAssetName }: Row) => {
const base = `${basePath}/${poolId}/assets/`
console.log(label)
const isCashTransfer = label === 'Cash transfer from'
return (
<Text as="span" variant="body3">
{label} <RouterTextLink to={`${base}${assetId.split('-')[1]}`}>{assetName}</RouterTextLink>{' '}
{label}{' '}
<RouterTextLink to={`${base}${assetId.split('-')[1]}`}>
{isCashTransfer ? fromAssetName : assetName}
</RouterTextLink>{' '}
{toAssetName ? (
<>
{' '}
Expand Down

0 comments on commit 70c8519

Please sign in to comment.