diff --git a/centrifuge-app/src/components/LayoutBase/index.tsx b/centrifuge-app/src/components/LayoutBase/index.tsx index 5005fbf4cf..b8de592ca8 100644 --- a/centrifuge-app/src/components/LayoutBase/index.tsx +++ b/centrifuge-app/src/components/LayoutBase/index.tsx @@ -32,7 +32,7 @@ export function LayoutBase(): JSX.Element { - + diff --git a/centrifuge-app/src/components/LayoutBase/styles.tsx b/centrifuge-app/src/components/LayoutBase/styles.tsx index 58724577c1..5c430404dd 100644 --- a/centrifuge-app/src/components/LayoutBase/styles.tsx +++ b/centrifuge-app/src/components/LayoutBase/styles.tsx @@ -42,7 +42,7 @@ export const Inner = styled(Grid)` padding-bottom: 1rem; @media (min-width: ${({ theme }) => theme.breakpoints['M']}) and (max-width: ${({ theme }) => theme.breakpoints['L']}) { - width: 7vw; + width: 6vw; background-color: ${({ theme }) => theme.colors.backgroundInverted}; overflow: visible; } @@ -77,13 +77,19 @@ export const LogoContainer = styled(Stack)` z-index: ${({ theme }) => theme.zIndices.header}; position: sticky; top: 0; - width: 100%; - grid-area: logo; height: ${HEADER_HEIGHT}px; justify-content: center; + padding-left: 12px; - @media (min-width: ${({ theme }) => theme.breakpoints[BREAK_POINT_COLUMNS]}) { + @media (min-width: ${({ theme }) => theme.breakpoints['M']}) and (max-width: ${({ theme }) => + theme.breakpoints['L']}) { + justify-content: start; + padding-top: ${({ theme }) => theme.space[2]}px; + padding-left: 12px; + } + + @media (min-width: ${({ theme }) => theme.breakpoints['L']}) { justify-content: start; padding-top: ${({ theme }) => theme.space[2]}px; } diff --git a/centrifuge-app/src/components/ListItemCardStyles.tsx b/centrifuge-app/src/components/ListItemCardStyles.tsx index e06ab21f8b..0b1a290d10 100644 --- a/centrifuge-app/src/components/ListItemCardStyles.tsx +++ b/centrifuge-app/src/components/ListItemCardStyles.tsx @@ -34,3 +34,7 @@ export const Ellipsis = styled.span` overflow: hidden; text-overflow: ellipsis; ` +export const CardHeader = styled(Box)` + display: flex; + justify-content: space-between; +` diff --git a/centrifuge-app/src/components/LogoLink-deprecated.tsx b/centrifuge-app/src/components/LogoLink-deprecated.tsx index c95b180e90..badc20ccb2 100644 --- a/centrifuge-app/src/components/LogoLink-deprecated.tsx +++ b/centrifuge-app/src/components/LogoLink-deprecated.tsx @@ -7,12 +7,12 @@ const [LogoMark, WordMark] = config.logo export function LogoLink() { const isMedium = useIsAboveBreakpoint('M') - const isXLarge = useIsAboveBreakpoint('XL') + const isLarge = useIsAboveBreakpoint('L') return ( - - {isMedium && !isXLarge ? : } + + {!isMedium || isLarge ? : } ) diff --git a/centrifuge-app/src/components/PoolCard/PoolStatus.tsx b/centrifuge-app/src/components/PoolCard/PoolStatus.tsx index ad254c685e..ef76f50710 100644 --- a/centrifuge-app/src/components/PoolCard/PoolStatus.tsx +++ b/centrifuge-app/src/components/PoolCard/PoolStatus.tsx @@ -3,7 +3,7 @@ import { StatusChip, StatusChipProps } from '@centrifuge/fabric' export type PoolStatusKey = 'Open for investments' | 'Closed' | 'Upcoming' | 'Archived' const statusColor: { [key in PoolStatusKey]: StatusChipProps['status'] } = { - 'Open for investments': 'ok', + 'Open for investments': 'warning', Closed: 'default', Upcoming: 'default', Archived: 'default', diff --git a/centrifuge-app/src/components/PoolCard/index.tsx b/centrifuge-app/src/components/PoolCard/index.tsx index 1f3e9495fe..eb3f791926 100644 --- a/centrifuge-app/src/components/PoolCard/index.tsx +++ b/centrifuge-app/src/components/PoolCard/index.tsx @@ -1,18 +1,52 @@ -import { useBasePath } from '@centrifuge/centrifuge-app/src/utils/useBasePath' -import { Rate } from '@centrifuge/centrifuge-js' -import { Box, Grid, Text, TextWithPlaceholder, Thumbnail } from '@centrifuge/fabric' +import { CurrencyBalance, Rate } from '@centrifuge/centrifuge-js' +import { Box, Card, Divider, Stack, Text, Thumbnail } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' -import { useTheme } from 'styled-components' -import { formatBalance, formatPercentage } from '../../utils/formatting' -import { useIsAboveBreakpoint } from '../../utils/useIsAboveBreakpoint' -import { Eththumbnail } from '../EthThumbnail' -import { Anchor, Ellipsis, Root } from '../ListItemCardStyles' -import { Tooltips } from '../Tooltips' +import styled from 'styled-components' +import { formatBalance, formatBalanceAbbreviated, formatPercentage } from '../../utils/formatting' +import { CardHeader } from '../ListItemCardStyles' +import { RouterTextLink } from '../TextLink' import { PoolStatus, PoolStatusKey } from './PoolStatus' -const columns_base = 'minmax(150px, 2fr) minmax(100px, 1fr) 140px 70px 150px' -const columns_extended = 'minmax(200px, 2fr) minmax(100px, 1fr) 140px 100px 150px' -export const COLUMNS = ['minmax(100px, 1fr) 1fr', 'minmax(100px, 1fr) 1fr', columns_base, columns_extended] -export const COLUMN_GAPS = [3, 3, 6, 8] + +type TrancheData = { + name: string + apr: string + minInvestment: string +} + +export type InnerMetadata = { + minInitialInvestment?: CurrencyBalance +} + +export type MetaData = { + tranches: { + [key: string]: InnerMetadata + } + pool: { + issuer: { + shortDescription?: string + } + investorType?: string + } +} + +export type Tranche = { + id: string + currency: { + name: string + decimals: number + } + interestRatePerSec: { + toAprPercent: () => Decimal + } | null + capacity?: CurrencyBalance | number + metadata?: MetaData +} + +const StyledRouterTextLink = styled(RouterTextLink)` + font-size: 12px; + margin-top: 8px; + text-decoration: none; +` export type PoolCardProps = { poolId?: string @@ -23,7 +57,8 @@ export type PoolCardProps = { apr?: Rate | null | undefined status?: PoolStatusKey iconUri?: string - isLoading?: boolean + tranches?: Tranche[] + metaData?: MetaData } export function PoolCard({ @@ -32,100 +67,112 @@ export function PoolCard({ assetClass, valueLocked, currencySymbol, - apr, status, iconUri, - isLoading, + tranches, + metaData, }: PoolCardProps) { - const isMedium = useIsAboveBreakpoint('M') - const basePath = useBasePath('/pools') - const { sizes, zIndices } = useTheme() - - return ( - - - - - {iconUri ? ( - - ) : ( - - )} - + const isOneTranche = tranches && tranches?.length === 1 + const renderText = (text: string) => ( + + {text} + + ) - - {name} - - + const tranchesData: TrancheData[] = tranches?.map((tranche: 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() - {isMedium && ( - - {assetClass} - - )} + return { + name: trancheName, + apr: tranche.interestRatePerSec + ? formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, { + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }) + : '-', + minInvestment: + metadata && metadata.minInitialInvestment ? formatBalanceAbbreviated(investmentBalance, '', 0) : '-', + } + }) as TrancheData[] - - {valueLocked ? formatBalance(valueLocked, currencySymbol) : '-'} - - - {isMedium && ( - - - {apr ? ( - formatPercentage(apr.toAprPercent(), true, { - minimumFractionDigits: 1, - maximumFractionDigits: 1, - }) - ) : poolId === '4139607887' ? ( - - - 5.0% - - target{' '} - - } - /> - ) : poolId === '1655476167' ? ( - - - 15.0% - - target{' '} - - } - /> - ) : ( - '—' - )} - - {status === 'Upcoming' && apr ? target : ''} - - )} - - {isMedium && ( + return ( + + + + + {name} + + + {iconUri ? ( + + ) : ( + + )} + + + + + TVL ({currencySymbol}) + + {valueLocked ? formatBalance(valueLocked, '') : '-'} + + + {!isOneTranche && ( + + + Tranches + + {tranchesData?.map((tranche) => renderText(tranche.name))} + {tranches && tranches.length > 2 ? ( + View all + ) : null} + + )} + + + APY + + {tranchesData?.map((tranche) => renderText(`${tranche.apr}`))} + + + + Min Investment + + {tranchesData?.map((tranche) => renderText(`${tranche.minInvestment}`))} + + + {metaData?.pool?.issuer?.shortDescription && ( + + + {metaData?.pool?.issuer?.shortDescription} + )} - - - {status === 'Upcoming' ? null : } - + + Asset Type + {assetClass ?? '-'} + + + Investor Type + {metaData?.pool?.investorType || '-'} + + + ) } diff --git a/centrifuge-app/src/components/PoolList.tsx b/centrifuge-app/src/components/PoolList.tsx index f0881b5c4f..6f31f98116 100644 --- a/centrifuge-app/src/components/PoolList.tsx +++ b/centrifuge-app/src/components/PoolList.tsx @@ -1,6 +1,6 @@ import Centrifuge, { Pool, PoolMetadata } from '@centrifuge/centrifuge-js' import { useCentrifuge } from '@centrifuge/centrifuge-react' -import { Box, Grid, InlineFeedback, Shelf, Stack, Text } from '@centrifuge/fabric' +import { Box, Shelf, Stack, Text } from '@centrifuge/fabric' import * as React from 'react' import { useLocation } from 'react-router' import styled from 'styled-components' @@ -9,11 +9,9 @@ import { TinlakePool } from '../utils/tinlake/useTinlakePools' import { useIsAboveBreakpoint } from '../utils/useIsAboveBreakpoint' import { useListedPools } from '../utils/useListedPools' import { useMetadataMulti } from '../utils/useMetadata' -import { COLUMNS, COLUMN_GAPS, PoolCard, PoolCardProps } from './PoolCard' +import { MetaData, PoolCard, PoolCardProps, Tranche } from './PoolCard' import { PoolStatusKey } from './PoolCard/PoolStatus' -import { PoolFilter } from './PoolFilter' import { filterPools } from './PoolFilter/utils' -import { ButtonTextLink } from './TextLink' export type MetaDataById = Record export type PoolMetaDataPartial = Partial | undefined @@ -31,6 +29,7 @@ export function PoolList() { const { search } = useLocation() const [showArchived, setShowArchived] = React.useState(false) const [listedPools, , metadataIsLoading] = useListedPools() + const isLarge = useIsAboveBreakpoint('L') const isMedium = useIsAboveBreakpoint('M') const centPools = listedPools.filter(({ id }) => !id.startsWith('0x')) as Pool[] @@ -67,44 +66,40 @@ export function PoolList() { } return ( - - + + - - - {!filteredPools.length ? ( - - - - No results found with these filters. Try different filters. - - - - ) : ( - - {metadataIsLoading - ? Array(6) - .fill(true) - .map((_, index) => ( - - - - )) - : filteredPools.map((pool) => ( - - - - ))} - - )} + + {metadataIsLoading + ? Array(6) + .fill(true) + .map((_, index) => ( + + + + )) + : filteredPools.map((pool) => ( + + + + ))} + {!metadataIsLoading && archivedPools.length > 0 && ( <> - - setShowArchived((show) => !show)}> - {showArchived ? 'Hide archived pools' : 'View archived pools'} - + setShowArchived((show) => !show)} + variant="body2" + > + {showArchived ? 'Hide archived pools' : 'View archived pools >'} {showArchived && } @@ -115,39 +110,21 @@ export function PoolList() { function ArchivedPools({ pools }: { pools: PoolCardProps[] }) { const isMedium = useIsAboveBreakpoint('M') - + const isLarge = useIsAboveBreakpoint('L') return ( - - - Pool name - - {isMedium && ( - - Asset class - - )} - - Value locked - - {isMedium && ( - - APR - - )} - {isMedium && ( - - Pool status - - )} - - + {pools.map((pool) => ( ))} - + ) } @@ -159,7 +136,6 @@ export function poolsToPoolCardProps( ): PoolCardProps[] { return pools.map((pool) => { const tinlakePool = pool.id?.startsWith('0x') && (pool as TinlakePool) - const mostSeniorTranche = pool?.tranches?.slice(1).at(-1) const metaData = typeof pool.metadata === 'string' ? metaDataById[pool.id] : pool.metadata return { @@ -168,16 +144,17 @@ export function poolsToPoolCardProps( assetClass: metaData?.pool?.asset.subClass, valueLocked: getPoolValueLocked(pool), currencySymbol: pool.currency.symbol, - apr: mostSeniorTranche?.interestRatePerSec, status: tinlakePool && tinlakePool.tinlakeMetadata.isArchived ? 'Archived' : tinlakePool && tinlakePool.addresses.CLERK !== undefined && tinlakePool.tinlakeMetadata.maker?.ilk ? 'Closed' - : pool.tranches.at(0)?.capacity.toFloat() // pool is displayed as "open for investments" if the most junior tranche has a capacity + : pool.tranches.at(0)?.capacity?.toFloat() // pool is displayed as "open for investments" if the most junior tranche has a capacity ? 'Open for investments' : ('Closed' as PoolStatusKey), iconUri: metaData?.pool?.icon?.uri ? cent.metadata.parseMetadataUrl(metaData?.pool?.icon?.uri) : undefined, + tranches: pool.tranches as Tranche[], + metaData: metaData as MetaData, } }) } diff --git a/centrifuge-app/src/components/Tooltips.tsx b/centrifuge-app/src/components/Tooltips.tsx index e881d0cf90..96ced10a00 100644 --- a/centrifuge-app/src/components/Tooltips.tsx +++ b/centrifuge-app/src/components/Tooltips.tsx @@ -330,6 +330,14 @@ export const tooltipText = { label: 'Linear accrual', body: 'If enabled, the price of the asset is updated continuously based on linear accrual from the latest known market price to the value at maturity.', }, + investorType: { + label: 'Investor type', + body: 'Who is able to participate.', + }, + targetAPY: { + label: 'Target APY', + body: 'The target APY for the tranche.', + }, } export type TooltipsProps = { diff --git a/centrifuge-app/src/pages/IssuerCreatePool/IssuerInput.tsx b/centrifuge-app/src/pages/IssuerCreatePool/IssuerInput.tsx index d0e3f7f9e9..456a24e85e 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/IssuerInput.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/IssuerInput.tsx @@ -43,6 +43,17 @@ export function IssuerInput({ waitingForStoredIssuer = false }: Props) { disabled={waitingForStoredIssuer} /> + + + )} + + + ) } diff --git a/centrifuge-app/src/pages/IssuerCreatePool/TrancheInput.tsx b/centrifuge-app/src/pages/IssuerCreatePool/TrancheInput.tsx index 70177734d9..92ce3d0b01 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/TrancheInput.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/TrancheInput.tsx @@ -27,13 +27,13 @@ export function TrancheSection() { const getNewTrancheName = (numTranches: number, poolName: string) => { switch (numTranches) { case 0: - return `${poolName} Junior` // First tranche to be added + return `${poolName} Junior` case 1: - return `${poolName} Senior` // Second tranche + return `${poolName} Senior` case 2: - return `${poolName} Mezzanine` // Third tranche + return `${poolName} Mezzanine` default: - return '' // No more tranches allowed or needed + return '' } } @@ -158,21 +158,19 @@ export function TrancheInput({ canRemove, isUpdating }: { canRemove?: boolean; i {index === 0 ? ( <> - } - value="-" - symbol="%" - disabled - /> - } - value="-" + {/* For Junior tranche, use interestRatePerSec with "Target APY" label */} + } + placeholder="0.00" symbol="%" - disabled + name={`tranches.${index}.interestRate`} + validate={validate.interestRate} /> ) : ( <> + {/* Show min subordination and interest rate for Senior or Mezzanine tranches */} } @@ -191,6 +189,7 @@ export function TrancheInput({ canRemove, isUpdating }: { canRemove?: boolean; i /> )} + {canRemove && ( {index !== 0 && ( @@ -198,9 +197,7 @@ export function TrancheInput({ canRemove, isUpdating }: { canRemove?: boolean; i variant="tertiary" icon={IconMinusCircle} onClick={() => { - // removes always mezzanine first and then senior to maintain order Junior | Senior or Junior | Mezzanine | Senior - // the only option that is not allow is Senior & Mezzanine - fldArr.remove(1) + fldArr.remove(index) }} /> )} diff --git a/centrifuge-app/src/pages/IssuerCreatePool/index.tsx b/centrifuge-app/src/pages/IssuerCreatePool/index.tsx index 16c87f91af..bad77b34a3 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/index.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/index.tsx @@ -111,6 +111,12 @@ export type CreatePoolValues = Omit< category: string }[] poolType: 'open' | 'closed' + investorType: string + issuerShortDescription: string + ratingAgency: string + ratingValue: string + ratingReport: File | null + minPoolInvestment: number } const initialValues: CreatePoolValues = { @@ -123,11 +129,14 @@ const initialValues: CreatePoolValues = { epochHours: 23, // in hours epochMinutes: 50, // in minutes listed: !import.meta.env.REACT_APP_DEFAULT_UNLIST_POOLS, + investorType: '', + minPoolInvestment: 0, issuerName: '', issuerRepName: '', issuerLogo: null, issuerDescription: '', + issuerShortDescription: '', executiveSummary: null, website: '', @@ -139,6 +148,10 @@ const initialValues: CreatePoolValues = { reportAuthorAvatar: null, reportUrl: '', + ratingAgency: '', + ratingValue: '', + ratingReport: null, + tranches: [createEmptyTranche('')], adminMultisig: { signers: [], @@ -326,6 +339,8 @@ function CreatePoolForm() { let prevInterest = Infinity let prevRiskBuffer = 0 + const juniorInterestRate = parseFloat(values.tranches[0].interestRate as string) + values.poolFees.forEach((fee, i) => { if (fee.name === '') { errors = setIn(errors, `poolFees.${i}.name`, 'Name is required') @@ -361,7 +376,14 @@ function CreatePoolForm() { errors = setIn(errors, `tranches.${i}.symbolName`, 'Token symbols must all start with the same 3 characters') } - if (t.interestRate !== '') { + if (i > 0 && t.interestRate !== '') { + if (t.interestRate > juniorInterestRate) { + errors = setIn( + errors, + `tranches.${i}.interestRate`, + "Interest rate can't be higher than the junior tranche's target APY" + ) + } if (t.interestRate > prevInterest) { errors = setIn(errors, `tranches.${i}.interestRate`, "Can't be higher than a more junior tranche") } @@ -384,6 +406,7 @@ function CreatePoolForm() { const metadataValues: PoolMetadataInput = { ...values } as any + // Handle admin multisig metadataValues.adminMultisig = values.adminMultisigEnabled && values.adminMultisig.threshold > 1 ? { @@ -392,13 +415,16 @@ function CreatePoolForm() { } : undefined + // Get the currency for the pool const currency = currencies.find((c) => c.symbol === values.currency)! + // Pool ID and required assets const poolId = await centrifuge.pools.getAvailablePoolId() if (!values.poolIcon || (!isTestEnv && !values.executiveSummary)) { return } + // Handle pinning files (pool icon, issuer logo, and executive summary) const promises = [lastValueFrom(centrifuge.metadata.pinFile(await getFileDataURI(values.poolIcon)))] if (values.issuerLogo) { @@ -422,6 +448,7 @@ function CreatePoolForm() { metadataValues.poolIcon = { uri: pinnedPoolIcon.uri, mime: values.poolIcon.type } + // Handle pool report if available if (values.reportUrl) { let avatar = null if (values.reportAuthorAvatar) { @@ -438,10 +465,11 @@ function CreatePoolForm() { } } - // tranches must be reversed (most junior is the first in the UI but the last in the API) const nonJuniorTranches = metadataValues.tranches.slice(1) const tranches = [ - {}, // most junior tranche + { + interestRatePerSec: Rate.fromAprPercent(values.tranches[0].interestRate), + }, ...nonJuniorTranches.map((tranche) => ({ interestRatePerSec: Rate.fromAprPercent(tranche.interestRate), minRiskBuffer: Perquintill.fromPercent(tranche.minRiskBuffer), @@ -467,8 +495,6 @@ function CreatePoolForm() { feeType: fee.feeType, })) - // const epochSeconds = ((values.epochHours as number) * 60 + (values.epochMinutes as number)) * 60 - if (metadataValues.adminMultisig && metadataValues.adminMultisig.threshold > 1) { addMultisig(metadataValues.adminMultisig) } @@ -649,6 +675,21 @@ function CreatePoolForm() { )} + + + {({ field, meta, form }: FieldProps) => ( + } + onChange={(event: any) => form.setFieldValue('investorType', event.target.value)} + onBlur={field.onBlur} + errorMessage={meta.touched && meta.error ? meta.error : undefined} + value={field.value} + as={TextInput} + /> + )} + + {({ field, meta, form }: FieldProps) => ( @@ -683,6 +724,20 @@ function CreatePoolForm() { }} + + + {({ field, form }: FieldProps) => ( + form.setFieldValue('minPoolInvestment', value)} + /> + )} + + {({ field, form }: FieldProps) => ( diff --git a/centrifuge-app/src/pages/IssuerCreatePool/validate.ts b/centrifuge-app/src/pages/IssuerCreatePool/validate.ts index c26e83d4d2..779ba4e29e 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/validate.ts +++ b/centrifuge-app/src/pages/IssuerCreatePool/validate.ts @@ -30,6 +30,8 @@ export const validate = { subAssetClass: required(), maxReserve: combine(required(), nonNegativeNumber(), max(Number.MAX_SAFE_INTEGER)), poolType: required(), + investorType: required(), + minPoolInvestment: required(), epochHours: combine(required(), nonNegativeNumber(), integer(), max(24 * 7 /* 1 week */)), epochMinutes: combine(required(), nonNegativeNumber(), integer(), max(59)), @@ -38,6 +40,7 @@ export const validate = { issuerName: combine(required(), maxLength(100)), issuerRepName: combine(required(), maxLength(100)), issuerDescription: combine(minLength(100), maxLength(1000)), + issuerShortDescription: combine(minLength(50), maxLength(100)), issuerLogo: combineAsync(imageFile(), maxFileSize(1 * MB), maxImageSize(480, 480)), executiveSummary: combine(required(), mimeType('application/pdf'), maxFileSize(5 * MB)), website: combine(required(), pattern(/^https?:\/\/.{4,}/, 'Not a valid URL')), diff --git a/centrifuge-app/src/pages/Pools.tsx b/centrifuge-app/src/pages/Pools.tsx index 5bb1574a82..cd7f41d52f 100644 --- a/centrifuge-app/src/pages/Pools.tsx +++ b/centrifuge-app/src/pages/Pools.tsx @@ -33,8 +33,8 @@ export default function PoolsPage() { }, []) return ( - - + + Pools of real-world assets diff --git a/centrifuge-app/src/pages/Portfolio/TransactionHistory.tsx b/centrifuge-app/src/pages/Portfolio/TransactionHistory.tsx index a76e83b8bf..56720cc5fd 100644 --- a/centrifuge-app/src/pages/Portfolio/TransactionHistory.tsx +++ b/centrifuge-app/src/pages/Portfolio/TransactionHistory.tsx @@ -8,7 +8,7 @@ export default function TransactionHistoryPage() { const connectedAddress = useAddress() const address = addressParam || connectedAddress return ( - + {address && } ) diff --git a/centrifuge-js/src/modules/pools.ts b/centrifuge-js/src/modules/pools.ts index 065abee0aa..37dab7a4b4 100644 --- a/centrifuge-js/src/modules/pools.ts +++ b/centrifuge-js/src/modules/pools.ts @@ -639,13 +639,13 @@ export type DailyPoolState = { sumRedeemedAmountByPeriod: string blockNumber: number } - interface TrancheFormValues { tokenName: string symbolName: string interestRate: number | '' minRiskBuffer: number | '' minInvestment: number | '' + targetAPY: number | '' } export type IssuerDetail = { @@ -675,12 +675,14 @@ export interface PoolMetadataInput { epochHours: number | '' epochMinutes: number | '' listed?: boolean + investorType: string // issuer issuerName: string issuerRepName: string issuerLogo?: FileType | null issuerDescription: string + issuerShortDescription: string poolReport?: { authorName: string @@ -724,6 +726,7 @@ export type PoolMetadata = { class: 'Public credit' | 'Private credit' subClass: string } + investorType: string poolFees?: { id: number name: string @@ -737,6 +740,7 @@ export type PoolMetadata = { description: string email: string logo?: FileType | null + shortDescription: string } links: { executiveSummary: FileType | null @@ -1110,7 +1114,9 @@ export function getPoolsModule(inst: Centrifuge) { description: metadata.issuerDescription, email: metadata.email, logo: metadata.issuerLogo, + shortDescription: metadata.issuerShortDescription, }, + investorType: metadata.investorType, links: { executiveSummary: metadata.executiveSummary, forum: metadata.forum, diff --git a/fabric/src/components/TextInput/index.tsx b/fabric/src/components/TextInput/index.tsx index 1bc5397d48..e48312d350 100644 --- a/fabric/src/components/TextInput/index.tsx +++ b/fabric/src/components/TextInput/index.tsx @@ -103,7 +103,7 @@ export const StyledInputAction = styled.button` export function InputAction({ children, ...props }: React.ButtonHTMLAttributes) { return ( - + {children} diff --git a/fabric/src/theme/tokens/colors.ts b/fabric/src/theme/tokens/colors.ts index 5cfa4064e6..a6bc15e96f 100644 --- a/fabric/src/theme/tokens/colors.ts +++ b/fabric/src/theme/tokens/colors.ts @@ -1,35 +1,36 @@ export const black = '#252B34' -export const gold = '#FFC500' +export const gold = '#FFC012' export const grayScale = { - 50: '#fbfbfb', - 100: '#f5f5f5', - 300: '#e0e0e0', - 500: '#82888D', - 800: '#424242', - 900: black, + 50: '#F6F6F6', + 100: '#E7E7E7', + 300: '#CFCFCF', + 500: '#91969B', + 800: '#252B34', + 900: '#0F1115', } export const yellowScale = { - 50: '#FFF4D9', + 50: '#FFFAE9', 100: '#FFE299', 500: '#FFC012', - 800: '#CC9700', + 800: '#806009', } export const blackScale = { 50: '#E2E4E7', 100: '#C5C9D0', 500: '#252B34', - 800: '#1A1F27', + 800: '#0F1115', } -// Only for altair export const blueScale = { - 50: '#f0f4ff', - 100: '#dbe5ff', - 500: '#1253ff', - 700: '#002b9e', + 50: '#E3F1FF', + 100: '#E6EFF5', + 500: '#5291E0', + 700: '#005B96', + 800: '#213A5A', + 900: '#00243C', } export const centrifugeBlue = blueScale[500] diff --git a/fabric/src/theme/tokens/theme.ts b/fabric/src/theme/tokens/theme.ts index c9d0ed0548..87824b8bee 100644 --- a/fabric/src/theme/tokens/theme.ts +++ b/fabric/src/theme/tokens/theme.ts @@ -1,35 +1,35 @@ -import { black, blackScale, centrifugeBlue, gold, grayScale, yellowScale } from './colors' +import { black, blackScale, blueScale, centrifugeBlue, gold, grayScale, yellowScale } from './colors' const statusDefault = grayScale[800] -const statusInfo = '#1253ff' +const statusInfo = blueScale[500] const statusOk = '#519b10' -const statusWarning = yellowScale[500] +const statusWarning = yellowScale[800] const statusCritical = '#d43f2b' const statusPromote = '#f81071' const statusDefaultBg = grayScale[300] -const statusInfoBg = grayScale[300] +const statusInfoBg = blueScale[50] const statusOkBg = '#f1f7ec' const statusWarningBg = yellowScale[50] const statusCriticalBg = '#fcf0ee' const statusPromoteBg = '#f8107114' const colors = { - textPrimary: grayScale[900], - textSecondary: grayScale[800], - textDisabled: grayScale[500], + textPrimary: grayScale[800], + textSecondary: grayScale[500], + textDisabled: grayScale[300], textInverted: 'white', textGold: gold, backgroundPrimary: 'white', - backgroundSecondary: grayScale[100], - backgroundTertiary: grayScale[50], - backgroundAccentPrimary: '#dbe5ff', - backgroundAccentSecondary: '#e9eff2', + backgroundSecondary: grayScale[50], + backgroundTertiary: grayScale[100], + backgroundAccentPrimary: blueScale[50], + backgroundAccentSecondary: blueScale[100], backgroundPage: 'white', backgroundInput: 'white', backgroundThumbnail: grayScale[500], - backgroundInverted: grayScale[900], + backgroundInverted: grayScale[800], borderPrimary: grayScale[100], borderSecondary: grayScale[300], @@ -50,7 +50,7 @@ const colors = { backgroundButtonPrimary: gold, backgroundButtonPrimaryFocus: gold, backgroundButtonPrimaryHover: gold, - backgroundButtonPrimaryPressed: yellowScale[500], + backgroundButtonPrimaryPressed: yellowScale[800], backgroundButtonPrimaryDisabled: grayScale[300], textButtonPrimary: black, textButtonPrimaryFocus: black, @@ -88,7 +88,7 @@ const colors = { backgroundButtonTertiaryDisabled: 'transparent', textButtonTertiary: centrifugeBlue, textButtonTertiaryFocus: centrifugeBlue, - textButtonTertiaryHover: grayScale[900], + textButtonTertiaryHover: grayScale[800], textButtonTertiaryPressed: centrifugeBlue, textButtonTertiaryDisabled: grayScale[500], borderButtonTertiary: 'transparent',