diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx
index e8c7d97059..c44be5b4d0 100644
--- a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx
+++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx
@@ -335,6 +335,8 @@ const OnboardingButton = ({ networks }: { networks: Network[] | undefined }) =>
showWallets(networks?.length === 1 ? networks[0] : undefined)
} else if (investStatus === 'request') {
window.open(`mailto:${metadata?.pool?.issuer.email}?subject=New%20Investment%20Inquiry`)
+ } else if (metadata?.onboarding?.externalOnboardingUrl) {
+ window.open(metadata.onboarding.externalOnboardingUrl)
} else {
history.push(`/onboarding?poolId=${state.poolId}&trancheId=${state.trancheId}`)
}
diff --git a/centrifuge-app/src/pages/IssuerPool/Configuration/OnboardingConfig.tsx b/centrifuge-app/src/pages/IssuerPool/Configuration/OnboardingConfig.tsx
deleted file mode 100644
index 2f145539aa..0000000000
--- a/centrifuge-app/src/pages/IssuerPool/Configuration/OnboardingConfig.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import { PoolMetadata } from '@centrifuge/centrifuge-js'
-import { useCentrifuge, useCentrifugeTransaction } from '@centrifuge/centrifuge-react'
-import { Button, FileUpload, Stack } from '@centrifuge/fabric'
-import { Form, FormikProvider, useFormik } from 'formik'
-import * as React from 'react'
-import { useParams } from 'react-router'
-import { lastValueFrom } from 'rxjs'
-import { ButtonGroup } from '../../../components/ButtonGroup'
-import { PageSection } from '../../../components/PageSection'
-import { getFileDataURI } from '../../../utils/getFileDataURI'
-import { usePool, usePoolMetadata } from '../../../utils/usePools'
-
-type AgreementsUpload = {
- agreements: { trancheId: string; file: File }[]
-}
-
-const initialValues: AgreementsUpload = {
- agreements: [],
-}
-
-export const OnboardingConfig: React.FC = () => {
- const { pid: poolId } = useParams<{ pid: string }>()
- const pool = usePool(poolId)
- const { data: poolMetadata } = usePoolMetadata(pool) as { data: PoolMetadata }
- const [isEditing, setIsEditing] = React.useState(false)
- const centrifuge = useCentrifuge()
-
- const { execute: updateConfigTx } = useCentrifugeTransaction('Update pool config', (cent) => cent.pools.setMetadata, {
- onSuccess: () => {
- setIsEditing(false)
- },
- })
-
- const form = useFormik({
- initialValues,
- onSubmit: async (values, actions) => {
- if (!values.agreements || !poolMetadata) {
- return
- }
- let onboardingAgreements: PoolMetadata['onboarding'] = {
- agreements: {},
- }
- for (const i of values.agreements) {
- const uri = await getFileDataURI(i.file)
- const pinnedAgreement = await lastValueFrom(centrifuge.metadata.pinFile(uri))
- onboardingAgreements = {
- agreements: {
- ...onboardingAgreements.agreements,
- [i.trancheId]: { ipfsHash: pinnedAgreement.ipfsHash },
- },
- }
- }
-
- const amendedMetadata: PoolMetadata = {
- ...poolMetadata,
- onboarding: onboardingAgreements,
- }
- updateConfigTx([poolId, amendedMetadata])
- actions.setSubmitting(false)
- },
- })
-
- return (
-
-
-
- )
-}
diff --git a/centrifuge-app/src/pages/IssuerPool/Configuration/index.tsx b/centrifuge-app/src/pages/IssuerPool/Configuration/index.tsx
index 6737f8f272..0920b59f0f 100644
--- a/centrifuge-app/src/pages/IssuerPool/Configuration/index.tsx
+++ b/centrifuge-app/src/pages/IssuerPool/Configuration/index.tsx
@@ -11,7 +11,6 @@ import { Details } from './Details'
import { EpochAndTranches } from './EpochAndTranches'
import { Issuer } from './Issuer'
import { LoanTemplates } from './LoanTemplates'
-import { OnboardingConfig } from './OnboardingConfig'
import { PoolConfig } from './PoolConfig'
import { WriteOffGroups } from './WriteOffGroups'
@@ -41,7 +40,6 @@ const IssuerPoolConfiguration: React.FC = () => {
-
{editPoolConfig && }
>
)}
diff --git a/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx b/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx
new file mode 100644
index 0000000000..44d21b107c
--- /dev/null
+++ b/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx
@@ -0,0 +1,159 @@
+import { findBalance, Pool, Token } from '@centrifuge/centrifuge-js'
+import { useBalances, useCentrifugeTransaction } from '@centrifuge/centrifuge-react'
+import {
+ Button,
+ Grid,
+ IconAlertCircle,
+ IconCheckCircle,
+ IconInfoFailed,
+ IconMinus,
+ IconPlus,
+ SearchInput,
+ Shelf,
+ Stack,
+ Text,
+ TextWithPlaceholder,
+} from '@centrifuge/fabric'
+import { isAddress } from '@polkadot/util-crypto'
+import React from 'react'
+import { useParams } from 'react-router'
+import { DataTable } from '../../../components/DataTable'
+import { PageSection } from '../../../components/PageSection'
+import { usePermissions } from '../../../utils/usePermissions'
+import { useOrder, usePool } from '../../../utils/usePools'
+
+const SevenDaysMs = (7 * 24 + 1) * 60 * 60 * 1000 // 1 hour margin
+
+export const InvestorStatus: React.FC = () => {
+ const { pid: poolId } = useParams<{ pid: string }>()
+ const [address, setAddress] = React.useState('')
+ const validAddress = isAddress(address) ? address : undefined
+ const permissions = usePermissions(validAddress)
+ const [pendingTrancheId, setPendingTrancheId] = React.useState('')
+
+ const { execute, isLoading: isTransactionPending } = useCentrifugeTransaction(
+ 'Update investor',
+ (cent) => cent.pools.updatePoolRoles,
+ {}
+ )
+
+ const allowedTranches = Object.entries(permissions?.pools[poolId]?.tranches ?? {})
+ .filter(([, till]) => new Date(till).getTime() - Date.now() > SevenDaysMs)
+ .map(([tid]) => tid)
+
+ const pool = usePool(poolId) as Pool
+
+ function toggleAllowed(trancheId: string) {
+ if (!validAddress) return
+ const isAllowed = allowedTranches.includes(trancheId)
+ const OneHundredYearsFromNow = Math.floor(Date.now() / 1000 + 10 * 365 * 24 * 60 * 60)
+ const SevenDaysFromNow = Math.floor((Date.now() + SevenDaysMs) / 1000)
+
+ if (isAllowed) {
+ execute([poolId, [], [[validAddress, { TrancheInvestor: [trancheId, OneHundredYearsFromNow] }]]])
+ } else {
+ execute([poolId, [[validAddress, { TrancheInvestor: [trancheId, SevenDaysFromNow] }]], []])
+ }
+ setPendingTrancheId(trancheId)
+ }
+
+ return (
+
+
+
+ setAddress(e.target.value)}
+ placeholder="Enter address..."
+ clear={() => setAddress('')}
+ />
+ {address && !validAddress ? (
+
+
+
+ Invalid address
+
+
+ ) : (
+ validAddress &&
+ (allowedTranches.length ? (
+
+
+
+ Address added to memberlist
+
+
+ ) : permissions && !allowedTranches.length ? (
+
+
+
+ Address not in memberlist
+
+
+ ) : null)
+ )}
+
+ {pool?.tranches && validAddress && permissions && (
+ (
+
+ {row.currency.name}
+
+ ),
+ flex: '1',
+ },
+ {
+ align: 'left',
+ header: 'Investment',
+ cell: (row: Token) => ,
+ flex: '1',
+ },
+ {
+ header: '',
+ align: 'right',
+ cell: (row: Token) => {
+ const isAllowed = allowedTranches.includes(row.id)
+
+ return (
+
+ )
+ },
+ flex: '1',
+ },
+ ]}
+ />
+ )}
+
+
+ )
+}
+
+const InvestedCell: React.FC<{ address: string; poolId: string; trancheId: string }> = ({
+ poolId,
+ trancheId,
+ address,
+}) => {
+ const order = useOrder(poolId, trancheId, address)
+ const balances = useBalances(address)
+ const hasBalance = balances && findBalance(balances.tranches, { Tranche: [poolId, trancheId] })
+ const hasOrder = order && (order?.submittedAt > 0 || !order.invest.isZero())
+ const hasInvested = hasBalance || hasOrder
+
+ return {hasInvested && 'Invested'}
+}
diff --git a/centrifuge-app/src/pages/IssuerPool/Investors/OnboardingSettings.tsx b/centrifuge-app/src/pages/IssuerPool/Investors/OnboardingSettings.tsx
new file mode 100644
index 0000000000..98191f59fa
--- /dev/null
+++ b/centrifuge-app/src/pages/IssuerPool/Investors/OnboardingSettings.tsx
@@ -0,0 +1,401 @@
+import { PoolMetadata, Token } from '@centrifuge/centrifuge-js'
+import { useCentrifuge, useCentrifugeTransaction } from '@centrifuge/centrifuge-react'
+import {
+ Box,
+ Button,
+ FileUpload,
+ IconMinusCircle,
+ SearchInput,
+ Shelf,
+ Stack,
+ Text,
+ TextInput,
+} from '@centrifuge/fabric'
+import { Form, FormikProvider, useFormik } from 'formik'
+import * as React from 'react'
+import { useParams } from 'react-router'
+import { lastValueFrom } from 'rxjs'
+import styled from 'styled-components'
+import { ButtonGroup } from '../../../components/ButtonGroup'
+import { PageSection } from '../../../components/PageSection'
+import { getFileDataURI } from '../../../utils/getFileDataURI'
+import { usePool, usePoolMetadata } from '../../../utils/usePools'
+import { KYB_COUNTRY_CODES, KYC_COUNTRY_CODES, RESTRICTED_COUNTRY_CODES } from '../../Onboarding/geographyCodes'
+
+type OnboardingSettingsInput = {
+ agreements: { [trancheId: string]: File | string | undefined }
+ kybRestrictedCountries: string[]
+ kycRestrictedCountries: string[]
+ externalOnboardingUrl?: string
+}
+
+export const OnboardingSettings = () => {
+ const { pid: poolId } = useParams<{ pid: string }>()
+ const pool = usePool(poolId)
+ const { data: poolMetadata } = usePoolMetadata(pool) as { data: PoolMetadata }
+ const [isEditing, setIsEditing] = React.useState(false)
+ const [useExternalUrl, setUseExternalUrl] = React.useState(!!poolMetadata?.onboarding?.externalOnboardingUrl)
+ const centrifuge = useCentrifuge()
+
+ const { execute: updateConfigTx, isLoading } = useCentrifugeTransaction(
+ 'Update pool config',
+ (cent) => cent.pools.setMetadata,
+ {
+ onSuccess: () => {
+ setIsEditing(false)
+ },
+ }
+ )
+
+ const initialValues: OnboardingSettingsInput = React.useMemo(() => {
+ return {
+ agreements: (pool.tranches as Token[]).reduce(
+ (prevT, currT) => ({
+ ...prevT,
+ [currT.id]: poolMetadata?.onboarding?.agreements?.[currT.id]?.uri
+ ? centrifuge.metadata.parseMetadataUrl(poolMetadata?.onboarding?.agreements[currT.id].uri)
+ : undefined,
+ }),
+ {}
+ ),
+ kybRestrictedCountries:
+ poolMetadata?.onboarding?.kybRestrictedCountries?.map(
+ (c) => KYB_COUNTRY_CODES[c as keyof typeof KYB_COUNTRY_CODES]
+ ) ?? [],
+ kycRestrictedCountries:
+ poolMetadata?.onboarding?.kycRestrictedCountries?.map(
+ (c) => KYC_COUNTRY_CODES[c as keyof typeof KYC_COUNTRY_CODES]
+ ) ?? [],
+ externalOnboardingUrl: poolMetadata?.onboarding?.externalOnboardingUrl ?? '',
+ }
+ }, [pool, poolMetadata])
+
+ React.useEffect(() => {
+ if (isEditing) return
+ formik.resetForm()
+ formik.setValues(initialValues, false)
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [initialValues, isEditing])
+
+ const formik = useFormik({
+ initialValues,
+ validateOnBlur: true,
+ validateOnChange: false,
+ validate(values) {
+ const errors: Partial = {}
+ if (useExternalUrl && !values.externalOnboardingUrl) {
+ errors.externalOnboardingUrl = 'Link required for external onboarding'
+ }
+ if (useExternalUrl && values.externalOnboardingUrl) {
+ if (!values.externalOnboardingUrl.includes('http') || !new URL(values.externalOnboardingUrl)) {
+ errors.externalOnboardingUrl = 'Invalid URL'
+ }
+ }
+ return errors
+ },
+ onSubmit: async (values, actions) => {
+ if (!values.agreements || !poolMetadata) {
+ return
+ }
+ let onboardingAgreements = poolMetadata?.onboarding?.agreements ?? {}
+ for (const [tId, file] of Object.entries(values.agreements)) {
+ if (!file) {
+ continue
+ }
+ // file is already IPFS hash so it hasn't changed
+ if (typeof file === 'string') {
+ onboardingAgreements = {
+ ...onboardingAgreements,
+ [tId]: { uri: file, mime: 'application/pdf' },
+ }
+ } else {
+ const uri = await getFileDataURI(file)
+ const pinnedAgreement = await lastValueFrom(centrifuge.metadata.pinFile(uri))
+ onboardingAgreements = {
+ ...onboardingAgreements,
+ [tId]: { uri: centrifuge.metadata.parseMetadataUrl(pinnedAgreement.ipfsHash), mime: file.type },
+ }
+ }
+ }
+
+ const kybRestrictedCountries = values.kybRestrictedCountries
+ .map((country) => Object.entries(KYB_COUNTRY_CODES).find(([_c, _country]) => _country === country)?.[0] ?? '')
+ .filter(Boolean)
+
+ const kycRestrictedCountries = values.kycRestrictedCountries
+ .map((country) => Object.entries(KYC_COUNTRY_CODES).find(([_c, _country]) => _country === country)?.[0] ?? '')
+ .filter(Boolean)
+
+ const amendedMetadata: PoolMetadata = {
+ ...poolMetadata,
+ onboarding: {
+ agreements: onboardingAgreements,
+ kycRestrictedCountries,
+ kybRestrictedCountries,
+ externalOnboardingUrl: values.externalOnboardingUrl,
+ },
+ }
+ updateConfigTx([poolId, amendedMetadata])
+ actions.setSubmitting(true)
+ },
+ })
+
+ return (
+
+
+
+ )
+}
+
+const DefaultRestrictedCountries = () => {
+ return (
+
+
+
+ Unsupported countries
+
+
+
+ {Object.values(RESTRICTED_COUNTRY_CODES).map((country) => (
+
+ {country}
+
+ ))}
+
+
+ )
+}
+
+const ToggleButton = styled(Text)<{ isActive: boolean }>`
+ appearance: none;
+ border: 0;
+ cursor: pointer;
+ display: block;
+ padding: 8px 16px;
+ border-radius: 20px;
+
+ color: ${({ theme, isActive }) => (isActive ? theme.colors.textInteractive : theme.colors.textPrimary)};
+ box-shadow: ${({ theme, isActive }) => (isActive ? theme.shadows.cardInteractive : 'none')};
+ background: ${({ theme, isActive }) => (isActive ? theme.colors.backgroundPage : 'transparent')};
+
+ ${({ disabled, theme }) =>
+ disabled &&
+ `
+ cursor: not-allowed;
+ color: ${theme.colors.textDisabled};
+ `}
+`
diff --git a/centrifuge-app/src/pages/IssuerPool/Investors/index.tsx b/centrifuge-app/src/pages/IssuerPool/Investors/index.tsx
index ef0cb35355..d84a484769 100644
--- a/centrifuge-app/src/pages/IssuerPool/Investors/index.tsx
+++ b/centrifuge-app/src/pages/IssuerPool/Investors/index.tsx
@@ -1,30 +1,12 @@
-import { findBalance, Pool, Token } from '@centrifuge/centrifuge-js'
-import { useBalances, useCentrifugeTransaction } from '@centrifuge/centrifuge-react'
-import {
- Button,
- Grid,
- IconAlertCircle,
- IconCheckCircle,
- IconInfoFailed,
- IconMinus,
- IconPlus,
- SearchInput,
- Shelf,
- Stack,
- Text,
- TextWithPlaceholder,
-} from '@centrifuge/fabric'
-import { isAddress } from '@polkadot/util-crypto'
import * as React from 'react'
import { useParams } from 'react-router'
-import { DataTable } from '../../../components/DataTable'
import { LoadBoundary } from '../../../components/LoadBoundary'
-import { PageSection } from '../../../components/PageSection'
import { PageWithSideBar } from '../../../components/PageWithSideBar'
import { useAddress } from '../../../utils/useAddress'
import { usePermissions } from '../../../utils/usePermissions'
-import { useOrder, usePool } from '../../../utils/usePools'
import { IssuerPoolHeader } from '../Header'
+import { InvestorStatus } from './InvestorStatus'
+import { OnboardingSettings } from './OnboardingSettings'
export const IssuerPoolInvestorsPage: React.FC = () => {
return (
@@ -42,142 +24,12 @@ const IssuerPoolInvestors: React.FC = () => {
const address = useAddress('substrate')
const permissions = usePermissions(address)
const canEditInvestors = address && permissions?.pools[poolId]?.roles.includes('MemberListAdmin')
-
- return <>{canEditInvestors && }>
-}
-
-const SevenDaysMs = (7 * 24 + 1) * 60 * 60 * 1000 // 1 hour margin
-
-export const Investors: React.FC = () => {
- const { pid: poolId } = useParams<{ pid: string }>()
- const [address, setAddress] = React.useState('')
- const validAddress = isAddress(address) ? address : undefined
- const permissions = usePermissions(validAddress)
- const [pendingTrancheId, setPendingTrancheId] = React.useState('')
-
- const { execute, isLoading: isTransactionPending } = useCentrifugeTransaction(
- 'Update investor',
- (cent) => cent.pools.updatePoolRoles,
- {}
- )
-
- const allowedTranches = Object.entries(permissions?.pools[poolId]?.tranches ?? {})
- .filter(([, till]) => new Date(till).getTime() - Date.now() > SevenDaysMs)
- .map(([tid]) => tid)
-
- const pool = usePool(poolId) as Pool
-
- function toggleAllowed(trancheId: string) {
- if (!validAddress) return
- const isAllowed = allowedTranches.includes(trancheId)
- const OneHundredYearsFromNow = Math.floor(Date.now() / 1000 + 10 * 365 * 24 * 60 * 60)
- const SevenDaysFromNow = Math.floor((Date.now() + SevenDaysMs) / 1000)
-
- if (isAllowed) {
- execute([poolId, [], [[validAddress, { TrancheInvestor: [trancheId, OneHundredYearsFromNow] }]]])
- } else {
- execute([poolId, [[validAddress, { TrancheInvestor: [trancheId, SevenDaysFromNow] }]], []])
- }
- setPendingTrancheId(trancheId)
- }
+ const isPoolAdmin = address && permissions?.pools[poolId]?.roles.includes('PoolAdmin')
return (
-
-
-
- setAddress(e.target.value)}
- placeholder="Enter address..."
- clear={() => setAddress('')}
- />
- {address && !validAddress ? (
-
-
-
- Invalid address
-
-
- ) : (
- validAddress &&
- (allowedTranches.length ? (
-
-
-
- Address added to memberlist
-
-
- ) : permissions && !allowedTranches.length ? (
-
-
-
- Address not in memberlist
-
-
- ) : null)
- )}
-
- {pool?.tranches && validAddress && permissions && (
- (
-
- {row.currency.name}
-
- ),
- flex: '1',
- },
- {
- align: 'left',
- header: 'Investment',
- cell: (row: Token) => ,
- flex: '1',
- },
- {
- header: '',
- align: 'right',
- cell: (row: Token) => {
- const isAllowed = allowedTranches.includes(row.id)
-
- return (
-
- )
- },
- flex: '1',
- },
- ]}
- />
- )}
-
-
+ <>
+ {canEditInvestors && }
+ {isPoolAdmin && }
+ >
)
}
-
-const InvestedCell: React.FC<{ address: string; poolId: string; trancheId: string }> = ({
- poolId,
- trancheId,
- address,
-}) => {
- const order = useOrder(poolId, trancheId, address)
- const balances = useBalances(address)
- const hasBalance = balances && findBalance(balances.tranches, { Tranche: [poolId, trancheId] })
- const hasOrder = order && (order?.submittedAt > 0 || !order.invest.isZero())
- const hasInvested = hasBalance || hasOrder
-
- return {hasInvested && 'Invested'}
-}
diff --git a/centrifuge-app/src/pages/Onboarding/SignSubscriptionAgreement.tsx b/centrifuge-app/src/pages/Onboarding/SignSubscriptionAgreement.tsx
index 32cea9ebc5..c89b00f77f 100644
--- a/centrifuge-app/src/pages/Onboarding/SignSubscriptionAgreement.tsx
+++ b/centrifuge-app/src/pages/Onboarding/SignSubscriptionAgreement.tsx
@@ -48,14 +48,18 @@ export const SignSubscriptionAgreement = ({ signedAgreementUrl, isSignedAgreemen
const { mutate: sendDocumentsToIssuer, isLoading: isSending } = useSignAndSendDocuments()
const { execute: signRemark, isLoading: isSigningTransaction } = useSignRemark(sendDocumentsToIssuer)
- const unsignedAgreementUrl = poolMetadata?.onboarding?.agreements[trancheId]
- ? centrifuge.metadata.parseMetadataUrl(poolMetadata?.onboarding?.agreements[trancheId].ipfsHash)
+ const unsignedAgreementUrl = poolMetadata?.onboarding?.agreements?.[trancheId]
+ ? centrifuge.metadata.parseMetadataUrl(poolMetadata?.onboarding?.agreements[trancheId].uri)
: !poolId.startsWith('0x')
? centrifuge.metadata.parseMetadataUrl(GENERIC_SUBSCRIPTION_AGREEMENT)
: null
// tinlake pools without subdocs cannot accept investors
const isPoolClosedToOnboarding = poolId.startsWith('0x') && !unsignedAgreementUrl
+ const isCountrySupported =
+ onboardingUser.investorType === 'entity'
+ ? !poolMetadata?.onboarding?.kybRestrictedCountries?.includes(onboardingUser.jurisdictionCode)
+ : !poolMetadata?.onboarding?.kycRestrictedCountries?.includes(onboardingUser.countryOfCitizenship)
React.useEffect(() => {
if (hasSignedAgreement) {
@@ -64,7 +68,7 @@ export const SignSubscriptionAgreement = ({ signedAgreementUrl, isSignedAgreemen
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hasSignedAgreement])
- return !isPoolClosedToOnboarding ? (
+ return !isPoolClosedToOnboarding && isCountrySupported ? (
+ ) : !isCountrySupported ? (
+
+
+ This pool is currently not accepting new investors from your country. Please contact the issuer (
+
+ {poolMetadata?.pool?.issuer.email}
+
+ ) for any questions.
+
+ }
+ />
+
) : (
{
riskGroups: [],
onboarding: {
agreements: {
- [`${id}-0`]: { ipfsHash: p.metadata?.attributes?.Links?.['Agreements']?.[`${id}-0`] || '' },
- [`${id}-1`]: { ipfsHash: p.metadata?.attributes?.Links?.['Agreements']?.[`${id}-1`] || '' },
+ [`${id}-0`]: {
+ uri: p.metadata?.attributes?.Links?.['Agreements']?.[`${id}-0`] || '',
+ mime: 'application/pdf',
+ },
+ [`${id}-1`]: {
+ uri: p.metadata?.attributes?.Links?.['Agreements']?.[`${id}-1`] || '',
+ mime: 'application/pdf',
+ },
},
},
}
diff --git a/centrifuge-js/src/modules/pools.ts b/centrifuge-js/src/modules/pools.ts
index 3aed02b623..8f06e01cb1 100644
--- a/centrifuge-js/src/modules/pools.ts
+++ b/centrifuge-js/src/modules/pools.ts
@@ -491,11 +491,15 @@ export type PoolMetadata = {
discountRate: string
}[]
onboarding?: {
- agreements: {
+ agreements?: {
[trancheId: string]: {
- ipfsHash: string
+ uri: string
+ mime: string
}
}
+ kybRestrictedCountries?: string[]
+ kycRestrictedCountries?: string[]
+ externalOnboardingUrl?: string
}
}
diff --git a/fabric/src/components/RadioButton/index.tsx b/fabric/src/components/RadioButton/index.tsx
index 38b311a569..4db428ab9c 100644
--- a/fabric/src/components/RadioButton/index.tsx
+++ b/fabric/src/components/RadioButton/index.tsx
@@ -8,9 +8,10 @@ import { Text } from '../Text'
export type RadioButtonProps = React.InputHTMLAttributes & {
label?: string
errorMessage?: string
+ textStyle?: string
}
-export const RadioButton: React.VFC = ({ label, errorMessage, ...radioProps }) => {
+export const RadioButton: React.VFC = ({ label, errorMessage, textStyle, ...radioProps }) => {
return (