diff --git a/centrifuge-app/src/components/LoanList.tsx b/centrifuge-app/src/components/LoanList.tsx
index 1c91e660f1..cb204e25b6 100644
--- a/centrifuge-app/src/components/LoanList.tsx
+++ b/centrifuge-app/src/components/LoanList.tsx
@@ -282,7 +282,6 @@ export function LoanList({ loans, snapshots, isLoading }: Props) {
}
onChange={(e) => setShowRepaid(!showRepaid)}
- variant="square"
/>
+
) : (
))}
diff --git a/centrifuge-app/src/pages/IssuerCreatePool/FormAddressInput.tsx b/centrifuge-app/src/pages/IssuerCreatePool/FormAddressInput.tsx
new file mode 100644
index 0000000000..16467788b8
--- /dev/null
+++ b/centrifuge-app/src/pages/IssuerCreatePool/FormAddressInput.tsx
@@ -0,0 +1,48 @@
+import { evmToSubstrateAddress } from '@centrifuge/centrifuge-js'
+import { useCentrifugeUtils } from '@centrifuge/centrifuge-react'
+import { TextInput } from '@centrifuge/fabric'
+import { useField } from 'formik'
+import React from 'react'
+import { FieldWithErrorMessage } from '../../../src/components/FieldWithErrorMessage'
+import { isEvmAddress } from '../../../src/utils/address'
+import { truncate } from '../../utils/web3'
+
+interface FormAddressInputProps {
+ name: string
+ chainId?: number
+ placeholder?: string
+}
+
+export const FormAddressInput = ({ name, chainId, placeholder }: FormAddressInputProps) => {
+ const [field, meta, helpers] = useField(name)
+ const utils = useCentrifugeUtils()
+
+ let truncated: string | undefined
+ try {
+ truncated = truncate(utils.formatAddress(field.value))
+ } catch (e) {
+ truncated = undefined
+ }
+
+ function handleBlur() {
+ helpers.setTouched(true)
+
+ if (!truncated || meta.error) {
+ helpers.setError('Invalid address')
+ return
+ }
+
+ helpers.setValue(isEvmAddress(field.value) ? evmToSubstrateAddress(field.value, chainId ?? 0) : field.value)
+ }
+
+ return (
+ ) => helpers.setValue(e.target.value)}
+ onBlur={handleBlur}
+ errorMessage={meta.touched && meta.error ? meta.error : undefined}
+ as={TextInput}
+ />
+ )
+}
diff --git a/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx b/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx
index 5ae6cbd2dc..c797f437ad 100644
--- a/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx
+++ b/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx
@@ -6,6 +6,7 @@ import { AddButton } from './PoolDetailsSection'
import { StyledGrid } from './PoolStructureSection'
const PROVIDERS = [
+ { label: 'Please select...', value: '' },
{ label: 'Fund admin', value: 'fundAdmin' },
{ label: 'Trustee', value: 'trustee' },
{ label: 'Pricing oracle provider', value: 'pricingOracleProvider' },
@@ -59,9 +60,7 @@ export const IssuerCategoriesSection = () => {
onBlur={field.onBlur}
value={field.value}
options={PROVIDERS}
- placeholder="Please select..."
errorMessage={meta.touched && meta.error ? meta.error : undefined}
- activePlaceholder
/>
)}
diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx
index 675c149b46..3fb98ff53d 100644
--- a/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx
+++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx
@@ -1,4 +1,4 @@
-import { evmToSubstrateAddress, PoolMetadataInput } from '@centrifuge/centrifuge-js'
+import { PoolMetadataInput } from '@centrifuge/centrifuge-js'
import { useCentEvmChainId, useWallet } from '@centrifuge/centrifuge-react'
import {
Box,
@@ -20,18 +20,22 @@ import { useTheme } from 'styled-components'
import { FieldWithErrorMessage } from '../../../src/components/FieldWithErrorMessage'
import { Tooltips } from '../../../src/components/Tooltips'
import { feeCategories } from '../../../src/config'
-import { isEvmAddress } from '../../../src/utils/address'
+import { FormAddressInput } from './FormAddressInput'
import { AddButton } from './PoolDetailsSection'
import { CheckboxOption, Line, StyledGrid } from './PoolStructureSection'
import { CreatePoolValues } from './types'
import { validate } from './validate'
const FEE_TYPES = [
+ { label: 'Please select...', value: '' },
{ label: 'Direct charge', value: 'chargedUpTo' },
{ label: 'Fixed %', value: 'fixed' },
]
-const FEE_POSISTIONS = [{ label: 'Top of waterfall', value: 'Top of waterfall' }]
+const FEE_POSISTIONS = [
+ { label: 'Please select...', value: '' },
+ { label: 'Top of waterfall', value: 'Top of waterfall' },
+]
const TaxDocument = () => {
const form = useFormikContext()
@@ -111,26 +115,12 @@ export const PoolSetupSection = () => {
values.adminMultisig?.signers?.map((_, index) => (
- {({ field, form, meta }: FieldProps) => (
+ {() => (
- ) => {
- form.setFieldValue(`adminMultisig.signers.${index}`, val.target.value)
- }}
- onBlur={() => {
- form.setFieldTouched(`adminMultisig.signers.${index}`, true)
- const value = form.values.adminMultisig.signers[index]
- if (value) {
- const transformedValue = isEvmAddress(value)
- ? evmToSubstrateAddress(value, chainId ?? 0)
- : value
- form.setFieldValue(`adminMultisig.signers.${index}`, transformedValue)
- }
- }}
- errorMessage={meta.touched && meta.error ? meta.error : undefined}
- as={TextInput}
+ chainId={chainId}
/>
{values.adminMultisig.signers.length >= 3 && index >= 2 && (
remove(index)}>
@@ -223,37 +213,21 @@ export const PoolSetupSection = () => {
{values.assetOriginators?.map((_: string, index: number) => (
- {({ field, form }: FieldProps) => (
- (
+ ) => {
- form.setFieldValue(`assetOriginators.${index}`, val.target.value)
- }}
- as={TextInput}
- onBlur={() => {
- form.setFieldTouched(`assetOriginators.${index}`, true)
- const value = form.values.assetOriginators[index]
- if (value) {
- const transformedValue = isEvmAddress(value)
- ? evmToSubstrateAddress(value, chainId ?? 0)
- : value
- form.setFieldValue(`assetOriginators.${index}`, transformedValue)
- }
- }}
+ chainId={chainId}
/>
)}
))}
-
{
- if (values.adminMultisig && values.adminMultisig.signers?.length <= 10) {
- push('')
- }
+ push('')
}}
/>
@@ -351,7 +325,6 @@ export const PoolSetupSection = () => {
value={field.value}
options={FEE_POSISTIONS}
placeholder="Please select"
- activePlaceholder
/>
)}
@@ -366,7 +339,6 @@ export const PoolSetupSection = () => {
value={field.value}
options={FEE_TYPES}
placeholder="Please select"
- activePlaceholder
/>
)}
diff --git a/centrifuge-app/src/pages/IssuerCreatePool/index.tsx b/centrifuge-app/src/pages/IssuerCreatePool/index.tsx
index baec4a060f..09d89dc8b4 100644
--- a/centrifuge-app/src/pages/IssuerCreatePool/index.tsx
+++ b/centrifuge-app/src/pages/IssuerCreatePool/index.tsx
@@ -230,7 +230,7 @@ const IssuerCreatePoolPage = () => {
].filter(Boolean)
)
setMultisigData({ callData: proxiedPoolCreate.method.toHex(), hash: proxiedPoolCreate.method.hash.toHex() })
- return cent.wrapSignAndSend(api, submittable, { ...options })
+ return cent.wrapSignAndSend(api, submittable, { ...options, multisig: undefined, proxies: undefined })
})
)
},
diff --git a/centrifuge-app/src/pages/IssuerCreatePool/utils.ts b/centrifuge-app/src/pages/IssuerCreatePool/utils.ts
index dfd5d64d79..5b17d05ff1 100644
--- a/centrifuge-app/src/pages/IssuerCreatePool/utils.ts
+++ b/centrifuge-app/src/pages/IssuerCreatePool/utils.ts
@@ -1,17 +1,16 @@
-import { FileType } from '@centrifuge/centrifuge-js'
-import { useCentrifuge } from '@centrifuge/centrifuge-react'
+import Centrifuge, { FileType } from '@centrifuge/centrifuge-js'
import { lastValueFrom } from 'rxjs'
import { getFileDataURI } from '../../../src/utils/getFileDataURI'
-const pinFile = async (centrifuge: ReturnType, file: File): Promise => {
+const pinFile = async (centrifuge: Centrifuge, file: File): Promise => {
const pinned = await lastValueFrom(centrifuge.metadata.pinFile(await getFileDataURI(file)))
return { uri: pinned.uri, mime: file.type }
}
-export const pinFileIfExists = async (centrifuge: ReturnType, file: File | null) =>
- file ? pinFile(centrifuge, file) : Promise.resolve(null)
+export const pinFileIfExists = async (centrifuge: Centrifuge, file: File | null) =>
+ file ? pinFile(centrifuge, file) : null
-export const pinFiles = async (centrifuge: ReturnType, files: { [key: string]: File | null }) => {
+export const pinFiles = async (centrifuge: Centrifuge, files: { [key: string]: File | null }) => {
const promises = Object.entries(files).map(async ([key, file]) => {
const pinnedFile = await pinFileIfExists(centrifuge, file)
return { key, pinnedFile }
diff --git a/centrifuge-app/src/pages/IssuerCreatePool/validate.ts b/centrifuge-app/src/pages/IssuerCreatePool/validate.ts
index 0fb84c3f77..5a21cf63fa 100644
--- a/centrifuge-app/src/pages/IssuerCreatePool/validate.ts
+++ b/centrifuge-app/src/pages/IssuerCreatePool/validate.ts
@@ -202,6 +202,20 @@ export const validateValues = (values: CreatePoolValues) => {
}
prevRiskBuffer = t.minRiskBuffer
}
+
+ if (values.assetOriginators.length >= 2) {
+ values.assetOriginators.some((val, idx) => {
+ const isDuplicated = values.assetOriginators.indexOf(val) !== idx
+ if (isDuplicated) errors = setIn(errors, `assetOriginators.${idx}`, 'Address already exists')
+ })
+ }
+
+ if (values.adminMultisig.signers.length >= 2) {
+ values.adminMultisig.signers.some((val, idx) => {
+ const isDuplicated = values.adminMultisig.signers.indexOf(val) !== idx
+ if (isDuplicated) errors = setIn(errors, `adminMultisig.signers.${idx}`, 'Address already exists')
+ })
+ }
})
return errors
diff --git a/centrifuge-app/src/pages/IssuerPool/Configuration/AddressInput.tsx b/centrifuge-app/src/pages/IssuerPool/Configuration/AddressInput.tsx
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/centrifuge-app/src/pages/Pool/Assets/index.tsx b/centrifuge-app/src/pages/Pool/Assets/index.tsx
index f2f8171f3a..ccd8017418 100644
--- a/centrifuge-app/src/pages/Pool/Assets/index.tsx
+++ b/centrifuge-app/src/pages/Pool/Assets/index.tsx
@@ -45,7 +45,7 @@ export function PoolDetailAssets() {
const pool = usePool(poolId)
const { data: loans } = useLoans(poolId)
- const { data: snapshots } = useAllPoolAssetSnapshots(poolId, new Date().toString())
+ const { data: snapshots } = useAllPoolAssetSnapshots(poolId, new Date().toISOString().slice(0, 10))
const isTinlakePool = poolId.startsWith('0x')
const basePath = useBasePath()
const cashLoans = (loans ?? []).filter(
diff --git a/fabric/src/components/FileUpload/index.tsx b/fabric/src/components/FileUpload/index.tsx
index eece23aa94..83f755b88e 100644
--- a/fabric/src/components/FileUpload/index.tsx
+++ b/fabric/src/components/FileUpload/index.tsx
@@ -4,15 +4,6 @@ import { Box, IconButton, IconUpload, IconX, InputUnit, InputUnitProps, StyledTe
import { useControlledState } from '../../utils/useControlledState'
import { Stack } from '../Stack'
-// const rotate = keyframes`
-// 0% {
-// transform: rotate(0);
-// }
-// 100% {
-// transform: rotate(1turn);
-// }
-// `
-
const FormField = styled.input`
// Visually hidden
border: 0;
@@ -25,10 +16,6 @@ const FormField = styled.input`
width: 1px;
`
-// const Spinner = styled(IconSpinner)`
-// animation: ${rotate} 600ms linear infinite;
-// `
-
const FileDragOverContainer = styled(Stack)<{ $disabled?: boolean; $active: boolean; small?: boolean }>`
position: relative;
height: ${({ small }) => (small ? '40px' : '144px')};
diff --git a/fabric/src/components/Select/index.tsx b/fabric/src/components/Select/index.tsx
index 2ceda30824..c3e3088bcc 100644
--- a/fabric/src/components/Select/index.tsx
+++ b/fabric/src/components/Select/index.tsx
@@ -18,7 +18,6 @@ export type SelectProps = React.SelectHTMLAttributes & {
errorMessage?: string
small?: boolean
hideBorder?: boolean
- activePlaceholder?: boolean
}
const StyledSelect = styled.select`
@@ -46,7 +45,6 @@ export function SelectInner({
disabled,
small,
hideBorder,
- activePlaceholder,
...rest
}: Omit) {
return (
@@ -66,7 +64,7 @@ export function SelectInner({
/>
{placeholder && (
-
)}