From 001f3dff8bde7faae3c504372d945ff444932418 Mon Sep 17 00:00:00 2001 From: Katty Barroso <51223655+kattylucy@users.noreply.github.com> Date: Mon, 20 Jan 2025 11:55:53 +0100 Subject: [PATCH] Create pool QA (#2563) * Make element scrollable after clicking next * Make APY target as default * Add please select as a value on dropdown * Fix address field * Fix bug creating with EVM address * Validate fields for categories and ratings if more than one selected * Display the formatted address * Fix values on pool overview page * Fix multisign address format * Switch to demo * Add pool name to the first step * Fix label for rating report * Change to pool structure * Fix linter warnings --- centrifuge-app/.env-config/.env.development | 31 ++++---- .../components/PoolOverview/KeyMetrics.tsx | 12 ++- .../IssuerCreatePool/FormAddressInput.tsx | 2 + .../IssuerCreatePool/IssuerCategories.tsx | 1 - .../IssuerCreatePool/PoolDetailsSection.tsx | 47 +++++------ .../pages/IssuerCreatePool/PoolRatings.tsx | 2 +- .../IssuerCreatePool/PoolSetupSection.tsx | 60 +++++++++----- .../IssuerCreatePool/PoolStructureSection.tsx | 15 +++- .../src/pages/IssuerCreatePool/index.tsx | 78 ++++++++++++------- .../src/pages/IssuerCreatePool/types.ts | 2 +- .../src/pages/IssuerCreatePool/validate.ts | 11 +++ 11 files changed, 161 insertions(+), 100 deletions(-) diff --git a/centrifuge-app/.env-config/.env.development b/centrifuge-app/.env-config/.env.development index 5114861124..b8a57d14e6 100644 --- a/centrifuge-app/.env-config/.env.development +++ b/centrifuge-app/.env-config/.env.development @@ -1,21 +1,24 @@ -REACT_APP_COLLATOR_WSS_URL=wss://fullnode.development.cntrfg.com -REACT_APP_DEFAULT_UNLIST_POOLS=false -REACT_APP_FAUCET_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/faucet-api-dev +REACT_APP_COLLATOR_WSS_URL=wss://fullnode.demo.k-f.dev,wss://fullnode-apps.demo.k-f.dev +REACT_APP_DEFAULT_UNLIST_POOLS=true +REACT_APP_FAUCET_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/faucet-api-demo REACT_APP_IPFS_GATEWAY=https://centrifuge.mypinata.cloud/ -REACT_APP_IS_DEMO=false -REACT_APP_NETWORK=centrifuge -REACT_APP_ONBOARDING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/onboarding-api-dev -REACT_APP_PINNING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/pinning-api-dev +REACT_APP_IS_DEMO=true +REACT_APP_ONBOARDING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/onboarding-api-demo +REACT_APP_PINNING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/pinning-api-demo REACT_APP_POOL_CREATION_TYPE=immediate -REACT_APP_RELAY_WSS_URL=wss://fullnode-relay.development.cntrfg.com -REACT_APP_SUBQUERY_URL=https://api.subquery.network/sq/centrifuge/pools-development -REACT_APP_SUBSCAN_URL=https://centrifuge.subscan.io +REACT_APP_RELAY_WSS_URL=wss://frag-moonbase-relay-rpc-ws.g.moonbase.moonbeam.network +REACT_APP_SUBQUERY_URL=https://api.subquery.network/sq/centrifuge/pools-demo-multichain +REACT_APP_SUBSCAN_URL= REACT_APP_TINLAKE_NETWORK=goerli REACT_APP_INFURA_KEY=8cd8e043ee8d4001b97a1c37e08fd9dd -REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 +REACT_APP_ALCHEMY_KEY=KNR-1LZhNqWOxZS2AN8AFeaiESBV10qZ REACT_APP_WHITELISTED_ACCOUNTS= -REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn +REACT_APP_NETWORK=centrifuge REACT_APP_REWARDS_TREE_URL=https://storage.googleapis.com/rad-rewards-trees-kovan-staging/latest.json +REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kALwmJutBq95s41U9fWnoApCUgvPqPGTh1GSmFnQh5f9fWo93 REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a -REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kAJ27w29x7gHM75xajP2yXVLjVBaKmmUTxHwgRuCoAcWaoEiz -REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn \ No newline at end of file +REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn +REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn +REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc +REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx index 107302352f..f5c24d4b47 100644 --- a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx +++ b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx @@ -136,6 +136,8 @@ export const KeyMetrics = ({ poolId }: Props) => { metric: centrifugeTargetAPYs[poolId as keyof typeof centrifugeTargetAPYs] || tinlakeData[poolId as TinlakeDataKey] ? 'Target APY' + : metadata?.tranches + ? Object.values(metadata?.tranches)[0].apy : '30-day APY', value: tinlakeData[poolId as TinlakeDataKey] ? tinlakeData[poolId as TinlakeDataKey] @@ -218,10 +220,16 @@ export const KeyMetrics = ({ poolId }: Props) => { {metrics.map(({ metric, value }, index) => { return ( - + {metric} - + {value} diff --git a/centrifuge-app/src/pages/IssuerCreatePool/FormAddressInput.tsx b/centrifuge-app/src/pages/IssuerCreatePool/FormAddressInput.tsx index 16467788b8..a920086323 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/FormAddressInput.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/FormAddressInput.tsx @@ -1,6 +1,7 @@ import { evmToSubstrateAddress } from '@centrifuge/centrifuge-js' import { useCentrifugeUtils } from '@centrifuge/centrifuge-react' import { TextInput } from '@centrifuge/fabric' +import { isAddress } from '@polkadot/util-crypto' import { useField } from 'formik' import React from 'react' import { FieldWithErrorMessage } from '../../../src/components/FieldWithErrorMessage' @@ -43,6 +44,7 @@ export const FormAddressInput = ({ name, chainId, placeholder }: FormAddressInpu onBlur={handleBlur} errorMessage={meta.touched && meta.error ? meta.error : undefined} as={TextInput} + value={isEvmAddress(field.value) || isAddress(field.value) ? utils.formatAddress(field.value) : field.value} /> ) } diff --git a/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx b/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx index c797f437ad..26ca8b6bf3 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/IssuerCategories.tsx @@ -73,7 +73,6 @@ export const IssuerCategoriesSection = () => { placeholder="Type here..." maxLength={100} as={TextInput} - errorMessage={meta.touched && meta.error ? meta.error : undefined} onBlur={field.onBlur} /> )} diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx index 8060ff1053..a5c8ba7dd8 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolDetailsSection.tsx @@ -38,35 +38,6 @@ export const PoolDetailsSection = () => { Pool Details - - ) => form.setFieldValue('poolName', e.target.value)} - /> - - {({ field, meta, form }: FieldProps) => ( - { - form.setFieldTouched('poolIcon', true, false) - form.setFieldValue('poolIcon', file) - }} - label="Pool icon*" - errorMessage={meta.touched && meta.error ? meta.error : undefined} - accept="image/svg+xml" - placeholder="SVG (in square size)" - id="poolIcon" - height={144} - /> - )} - - {({ field, meta, form }: FieldProps) => ( @@ -115,6 +86,24 @@ export const PoolDetailsSection = () => { )} + + {({ field, meta, form }: FieldProps) => ( + { + form.setFieldTouched('poolIcon', true, false) + form.setFieldValue('poolIcon', file) + }} + label="Pool icon*" + errorMessage={meta.touched && meta.error ? meta.error : undefined} + accept="image/svg+xml" + placeholder="SVG (in square size)" + id="poolIcon" + height={144} + /> + )} + diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolRatings.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolRatings.tsx index fd8ea61eb9..bf9f1e8ac5 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/PoolRatings.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolRatings.tsx @@ -66,7 +66,7 @@ export const PoolRatingsSection = () => { form.setFieldValue(`poolRatings.${index}.reportFile`, file) }} accept="application/pdf" - label="Executive summary PDF" + label="Rating report PDF" placeholder="Choose file" small errorMessage={meta.touched && meta.error ? meta.error : undefined} diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx index 5cd4b716f2..3d03ae7115 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolSetupSection.tsx @@ -1,5 +1,5 @@ import { PoolMetadataInput } from '@centrifuge/centrifuge-js' -import { useCentEvmChainId, useWallet } from '@centrifuge/centrifuge-react' +import { useCentEvmChainId, useCentrifugeUtils, useWallet } from '@centrifuge/centrifuge-react' import { Box, Checkbox, @@ -14,12 +14,14 @@ import { Text, TextInput, } from '@centrifuge/fabric' +import { isAddress } from '@polkadot/util-crypto' import { Field, FieldArray, FieldProps, useFormikContext } from 'formik' import { useEffect } from 'react' 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' @@ -48,7 +50,11 @@ const TaxDocument = () => { {({ field }: FieldProps) => ( + Require investors to upload tax documents before signing the subscription agreement. + + } onChange={(val) => form.setFieldValue('onboarding.taxInfoRequired', val.target.checked ? true : false)} /> )} @@ -62,12 +68,14 @@ export const PoolSetupSection = () => { const chainId = useCentEvmChainId() const form = useFormikContext() const { values } = form - const { selectedAccount } = useWallet().substrate + const utils = useCentrifugeUtils() + const ctx = useWallet() + const { substrate, connectedType } = ctx useEffect(() => { - form.setFieldValue('adminMultisig.signers[0]', selectedAccount?.address) - }, []) - console.log(values) + form.setFieldValue('adminMultisig.signers[0]', substrate.selectedAddress) + }, [substrate, form]) + return ( @@ -89,6 +97,7 @@ export const PoolSetupSection = () => { icon={} onChange={() => { form.setFieldValue('adminMultisigEnabled', false) + form.setFieldValue('adminMultisig.signers', [substrate.selectedAddress]) }} isChecked={!values.adminMultisigEnabled} id="singleMultisign" @@ -133,18 +142,26 @@ export const PoolSetupSection = () => { )) ) : ( - - - {({ field }: FieldProps) => ( - - )} - - + + {({ field, form }: FieldProps) => { + const isValidAddress = + connectedType === 'evm' ? isEvmAddress(field.value) : isAddress(field.value) + + return ( + + ) => + form.setFieldValue(field.name, e.target.value) + } + /> + + ) + }} + )} {values.adminMultisigEnabled && ( @@ -280,7 +297,7 @@ export const PoolSetupSection = () => { {({ push, remove }) => ( <> {values.poolFees.map((_, index) => { - if (index === 0) return + if (index === 0) return null return ( @@ -308,7 +325,10 @@ export const PoolSetupSection = () => { onBlur={field.onBlur} errorMessage={meta.touched && meta.error ? meta.error : undefined} value={field.value} - options={feeCategories.map((cat) => ({ label: cat, value: cat }))} + options={[ + { label: 'Please select', value: '' }, + ...feeCategories.map((cat) => ({ label: cat, value: cat })), + ]} /> )} diff --git a/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx b/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx index 4e047c0191..902f6c39b5 100644 --- a/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx +++ b/centrifuge-app/src/pages/IssuerCreatePool/PoolStructureSection.tsx @@ -180,7 +180,7 @@ export const PoolStructureSection = () => { - Pool type * + Pool structure * { disabled sublabel="Fixed pool of assets where funds remain locked. There are no continuous inflows or outflows during the investment period, and the pool has a defined maturity date." /> + + ) => form.setFieldValue('poolName', e.target.value)} + /> + Define tranche structure * @@ -269,7 +280,7 @@ export const PoolStructureSection = () => { {({ field, meta, form }: FieldProps) => (