mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Fixing connect custody flow (#19802)
* Fixing connect custody flow * Finished fixing mmi connect flow * Fixed test * updated snapshot * Finished fixing tests
This commit is contained in:
parent
6bb5e6941d
commit
59980f1b27
@ -2368,19 +2368,38 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
...getPermissionBackgroundApiMethods(permissionController),
|
...getPermissionBackgroundApiMethods(permissionController),
|
||||||
|
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||||
connectCustodyAddresses:
|
connectCustodyAddresses: this.mmiController.connectCustodyAddresses.bind(
|
||||||
this.mmiController.connectCustodyAddresses.bind(this),
|
this.mmiController,
|
||||||
getCustodianAccounts: this.mmiController.getCustodianAccounts.bind(this),
|
),
|
||||||
|
getCustodianAccounts: this.mmiController.getCustodianAccounts.bind(
|
||||||
|
this.mmiController,
|
||||||
|
),
|
||||||
getCustodianAccountsByAddress:
|
getCustodianAccountsByAddress:
|
||||||
this.mmiController.getCustodianAccountsByAddress.bind(this),
|
this.mmiController.getCustodianAccountsByAddress.bind(
|
||||||
|
this.mmiController,
|
||||||
|
),
|
||||||
getCustodianTransactionDeepLink:
|
getCustodianTransactionDeepLink:
|
||||||
this.mmiController.getCustodianTransactionDeepLink.bind(this),
|
this.mmiController.getCustodianTransactionDeepLink.bind(
|
||||||
|
this.mmiController,
|
||||||
|
),
|
||||||
getCustodianConfirmDeepLink:
|
getCustodianConfirmDeepLink:
|
||||||
this.mmiController.getCustodianConfirmDeepLink.bind(this),
|
this.mmiController.getCustodianConfirmDeepLink.bind(this.mmiController),
|
||||||
getCustodianSignMessageDeepLink:
|
getCustodianSignMessageDeepLink:
|
||||||
this.mmiController.getCustodianSignMessageDeepLink.bind(this),
|
this.mmiController.getCustodianSignMessageDeepLink.bind(
|
||||||
getCustodianToken: this.mmiController.getCustodianToken.bind(this),
|
this.mmiController,
|
||||||
getCustodianJWTList: this.mmiController.getCustodianJWTList.bind(this),
|
),
|
||||||
|
getCustodianToken: this.mmiController.getCustodianToken.bind(
|
||||||
|
this.mmiController,
|
||||||
|
),
|
||||||
|
getCustodianJWTList: this.mmiController.getCustodianJWTList.bind(
|
||||||
|
this.mmiController,
|
||||||
|
),
|
||||||
|
getAllCustodianAccountsWithToken:
|
||||||
|
this.mmiController.getAllCustodianAccountsWithToken.bind(
|
||||||
|
this.mmiController,
|
||||||
|
),
|
||||||
|
setCustodianNewRefreshToken:
|
||||||
|
this.mmiController.setCustodianNewRefreshToken.bind(this.mmiController),
|
||||||
setWaitForConfirmDeepLinkDialog:
|
setWaitForConfirmDeepLinkDialog:
|
||||||
this.custodyController.setWaitForConfirmDeepLinkDialog.bind(
|
this.custodyController.setWaitForConfirmDeepLinkDialog.bind(
|
||||||
this.custodyController,
|
this.custodyController,
|
||||||
@ -2393,8 +2412,6 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
this.custodyController.getCustodianConnectRequest.bind(
|
this.custodyController.getCustodianConnectRequest.bind(
|
||||||
this.custodyController,
|
this.custodyController,
|
||||||
),
|
),
|
||||||
getAllCustodianAccountsWithToken:
|
|
||||||
this.mmiController.getAllCustodianAccountsWithToken.bind(this),
|
|
||||||
getMmiConfiguration:
|
getMmiConfiguration:
|
||||||
this.mmiConfigurationController.getConfiguration.bind(
|
this.mmiConfigurationController.getConfiguration.bind(
|
||||||
this.mmiConfigurationController,
|
this.mmiConfigurationController,
|
||||||
@ -2415,12 +2432,10 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
this.institutionalFeaturesController.syncReportsInProgress.bind(
|
this.institutionalFeaturesController.syncReportsInProgress.bind(
|
||||||
this.institutionalFeaturesController,
|
this.institutionalFeaturesController,
|
||||||
),
|
),
|
||||||
|
|
||||||
removeConnectInstitutionalFeature:
|
removeConnectInstitutionalFeature:
|
||||||
this.institutionalFeaturesController.removeConnectInstitutionalFeature.bind(
|
this.institutionalFeaturesController.removeConnectInstitutionalFeature.bind(
|
||||||
this.institutionalFeaturesController,
|
this.institutionalFeaturesController,
|
||||||
),
|
),
|
||||||
|
|
||||||
getComplianceHistoricalReportsByAddress:
|
getComplianceHistoricalReportsByAddress:
|
||||||
this.institutionalFeaturesController.getComplianceHistoricalReportsByAddress.bind(
|
this.institutionalFeaturesController.getComplianceHistoricalReportsByAddress.bind(
|
||||||
this.institutionalFeaturesController,
|
this.institutionalFeaturesController,
|
||||||
@ -2429,8 +2444,6 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
this.institutionalFeaturesController.removeAddTokenConnectRequest.bind(
|
this.institutionalFeaturesController.removeAddTokenConnectRequest.bind(
|
||||||
this.institutionalFeaturesController,
|
this.institutionalFeaturesController,
|
||||||
),
|
),
|
||||||
setCustodianNewRefreshToken:
|
|
||||||
this.mmiController.setCustodianNewRefreshToken.bind(this),
|
|
||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(snaps)
|
///: BEGIN:ONLY_INCLUDE_IN(snaps)
|
||||||
|
@ -5,10 +5,10 @@ import PulseLoader from '../../../components/ui/pulse-loader';
|
|||||||
import { CUSTODY_ACCOUNT_ROUTE } from '../../../helpers/constants/routes';
|
import { CUSTODY_ACCOUNT_ROUTE } from '../../../helpers/constants/routes';
|
||||||
import {
|
import {
|
||||||
AlignItems,
|
AlignItems,
|
||||||
DISPLAY,
|
Display,
|
||||||
TextColor,
|
TextColor,
|
||||||
TEXT_ALIGN,
|
TextAlign,
|
||||||
FLEX_DIRECTION,
|
FlexDirection,
|
||||||
} from '../../../helpers/constants/design-system';
|
} from '../../../helpers/constants/design-system';
|
||||||
import { BUILT_IN_NETWORKS } from '../../../../shared/constants/network';
|
import { BUILT_IN_NETWORKS } from '../../../../shared/constants/network';
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
@ -23,8 +23,12 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
BUTTON_SIZES,
|
BUTTON_SIZES,
|
||||||
BUTTON_VARIANT,
|
BUTTON_VARIANT,
|
||||||
|
Box,
|
||||||
} from '../../../components/component-library';
|
} from '../../../components/component-library';
|
||||||
import Box from '../../../components/ui/box';
|
import {
|
||||||
|
complianceActivated,
|
||||||
|
getInstitutionalConnectRequests,
|
||||||
|
} from '../../../ducks/institutional/institutional';
|
||||||
|
|
||||||
const ConfirmAddCustodianToken = () => {
|
const ConfirmAddCustodianToken = () => {
|
||||||
const t = useContext(I18nContext);
|
const t = useContext(I18nContext);
|
||||||
@ -34,59 +38,12 @@ const ConfirmAddCustodianToken = () => {
|
|||||||
const mmiActions = mmiActionsFactory();
|
const mmiActions = mmiActionsFactory();
|
||||||
|
|
||||||
const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage);
|
const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage);
|
||||||
const connectRequests = useSelector(
|
const connectRequests = useSelector(getInstitutionalConnectRequests);
|
||||||
(state) => state.metamask.institutionalFeatures?.connectRequests,
|
const isComplianceActivated = useSelector(complianceActivated);
|
||||||
);
|
|
||||||
const complianceActivated = useSelector((state) =>
|
|
||||||
Boolean(state.metamask.institutionalFeatures?.complianceProjectId),
|
|
||||||
);
|
|
||||||
const [showMore, setShowMore] = useState(false);
|
const [showMore, setShowMore] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [connectError, setConnectError] = useState('');
|
const [connectError, setConnectError] = useState('');
|
||||||
|
|
||||||
const handleConnectError = (e) => {
|
|
||||||
let errorMessage = e.message;
|
|
||||||
|
|
||||||
if (!errorMessage) {
|
|
||||||
errorMessage = 'Connection error';
|
|
||||||
}
|
|
||||||
|
|
||||||
setConnectError(errorMessage);
|
|
||||||
setIsLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderSelectedToken = () => {
|
|
||||||
const connectRequest = connectRequests ? connectRequests[0] : undefined;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
paddingTop={2}
|
|
||||||
paddingBottom={2}
|
|
||||||
display={DISPLAY.FLEX}
|
|
||||||
flexDirection={FLEX_DIRECTION.ROW}
|
|
||||||
alignItems={AlignItems.center}
|
|
||||||
>
|
|
||||||
<Text>
|
|
||||||
{showMore && connectRequest?.token
|
|
||||||
? connectRequest?.token
|
|
||||||
: `...${connectRequest?.token.slice(-9)}`}
|
|
||||||
</Text>
|
|
||||||
{!showMore && (
|
|
||||||
<Box paddingLeft={2}>
|
|
||||||
<ButtonLink
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
onClick={() => {
|
|
||||||
setShowMore(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('showMore')}
|
|
||||||
</ButtonLink>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const connectRequest = connectRequests ? connectRequests[0] : undefined;
|
const connectRequest = connectRequests ? connectRequests[0] : undefined;
|
||||||
|
|
||||||
if (!connectRequest) {
|
if (!connectRequest) {
|
||||||
@ -148,7 +105,31 @@ const ConfirmAddCustodianToken = () => {
|
|||||||
marginLeft={4}
|
marginLeft={4}
|
||||||
className="add_custodian_token_confirm__token"
|
className="add_custodian_token_confirm__token"
|
||||||
>
|
>
|
||||||
{renderSelectedToken()}
|
<Box
|
||||||
|
paddingTop={2}
|
||||||
|
paddingBottom={2}
|
||||||
|
display={Display.Flex}
|
||||||
|
flexDirection={FlexDirection.Row}
|
||||||
|
alignItems={AlignItems.center}
|
||||||
|
>
|
||||||
|
<Text>
|
||||||
|
{showMore && connectRequest?.token
|
||||||
|
? connectRequest?.token
|
||||||
|
: `...${connectRequest?.token.slice(-9)}`}
|
||||||
|
</Text>
|
||||||
|
{!showMore && (
|
||||||
|
<Box paddingLeft={2}>
|
||||||
|
<ButtonLink
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
onClick={() => {
|
||||||
|
setShowMore(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('showMore')}
|
||||||
|
</ButtonLink>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
{connectRequest.apiUrl && (
|
{connectRequest.apiUrl && (
|
||||||
<Box>
|
<Box>
|
||||||
@ -168,9 +149,9 @@ const ConfirmAddCustodianToken = () => {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{!complianceActivated && (
|
{!isComplianceActivated && (
|
||||||
<Box marginTop={4} data-testid="connect-custodian-token-error">
|
<Box marginTop={4} data-testid="connect-custodian-token-error">
|
||||||
<Text data-testid="error-message" textAlign={TEXT_ALIGN.CENTER}>
|
<Text data-testid="error-message" textAlign={TextAlign.Center}>
|
||||||
{connectError}
|
{connectError}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@ -180,19 +161,19 @@ const ConfirmAddCustodianToken = () => {
|
|||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<PulseLoader />
|
<PulseLoader />
|
||||||
) : (
|
) : (
|
||||||
<Box display={DISPLAY.FLEX} gap={4}>
|
<Box display={Display.Flex} gap={4}>
|
||||||
<Button
|
<Button
|
||||||
block
|
block
|
||||||
variant={BUTTON_VARIANT.SECONDARY}
|
variant={BUTTON_VARIANT.SECONDARY}
|
||||||
size={BUTTON_SIZES.LG}
|
size={BUTTON_SIZES.LG}
|
||||||
data-testid="cancel-btn"
|
data-testid="cancel-btn"
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
mmiActions.removeAddTokenConnectRequest({
|
await mmiActions.removeAddTokenConnectRequest({
|
||||||
origin: connectRequest.origin,
|
origin: connectRequest.origin,
|
||||||
apiUrl: connectRequest.apiUrl,
|
apiUrl: connectRequest.apiUrl,
|
||||||
token: connectRequest.token,
|
token: connectRequest.token,
|
||||||
});
|
});
|
||||||
history.push(mostRecentOverviewPage);
|
|
||||||
trackEvent({
|
trackEvent({
|
||||||
category: 'MMI',
|
category: 'MMI',
|
||||||
event: 'Custodian onboarding',
|
event: 'Custodian onboarding',
|
||||||
@ -230,17 +211,21 @@ const ConfirmAddCustodianToken = () => {
|
|||||||
custodianName = connectRequest.environment;
|
custodianName = connectRequest.environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
await mmiActions.setCustodianConnectRequest({
|
await dispatch(
|
||||||
token: connectRequest.token,
|
mmiActions.setCustodianConnectRequest({
|
||||||
apiUrl: connectRequest.apiUrl,
|
token: connectRequest.token,
|
||||||
custodianName,
|
apiUrl: connectRequest.apiUrl,
|
||||||
custodianType: connectRequest.service,
|
custodianName,
|
||||||
});
|
custodianType: connectRequest.service,
|
||||||
mmiActions.removeAddTokenConnectRequest({
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await mmiActions.removeAddTokenConnectRequest({
|
||||||
origin: connectRequest.origin,
|
origin: connectRequest.origin,
|
||||||
apiUrl: connectRequest.apiUrl,
|
apiUrl: connectRequest.apiUrl,
|
||||||
token: connectRequest.token,
|
token: connectRequest.token,
|
||||||
});
|
});
|
||||||
|
|
||||||
trackEvent({
|
trackEvent({
|
||||||
category: 'MMI',
|
category: 'MMI',
|
||||||
event: 'Custodian onboarding',
|
event: 'Custodian onboarding',
|
||||||
@ -250,9 +235,17 @@ const ConfirmAddCustodianToken = () => {
|
|||||||
apiUrl: connectRequest.apiUrl,
|
apiUrl: connectRequest.apiUrl,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
history.push(CUSTODY_ACCOUNT_ROUTE);
|
history.push(CUSTODY_ACCOUNT_ROUTE);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleConnectError(e);
|
let errorMessage = e.message;
|
||||||
|
|
||||||
|
if (!errorMessage) {
|
||||||
|
errorMessage = 'Connection error';
|
||||||
|
}
|
||||||
|
|
||||||
|
setConnectError(errorMessage);
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -1,6 +1,24 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`CustodyPage renders CustodyPage 1`] = `
|
exports[`CustodyPage renders CustodyPage 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="pulse-loader"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="pulse-loader__loading-dot-one"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="pulse-loader__loading-dot-two"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="pulse-loader__loading-dot-three"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`CustodyPage renders CustodyPage 2`] = `
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
|
||||||
@ -70,115 +88,6 @@ exports[`CustodyPage renders CustodyPage 1`] = `
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`CustodyPage renders CustodyPage 2`] = `
|
|
||||||
<div>
|
|
||||||
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--padding-4 mm-box--display-flex mm-box--flex-direction-column mm-box--background-color-background-default"
|
|
||||||
style="box-shadow: var(--shadow-size-xs) var(--color-shadow-default);"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--margin-top-4 mm-box--margin-bottom-4 mm-box--display-flex mm-box--align-items-center"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
aria-label="Back"
|
|
||||||
class="box mm-button-icon mm-button-icon--size-sm box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-icon-default box--background-color-transparent box--rounded-lg"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="box mm-icon mm-icon--size-sm box--display-inline-block box--flex-direction-row box--color-inherit"
|
|
||||||
style="mask-image: url('./images/icons/arrow-left.svg');"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<p
|
|
||||||
class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default"
|
|
||||||
>
|
|
||||||
Back
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<h4
|
|
||||||
class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--display-flex mm-box--align-items-center"
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
class="box mm-text mm-text--body-md box--margin-left-2 box--flex-direction-row box--color-text-default"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</h4>
|
|
||||||
<p
|
|
||||||
class="box mm-text mm-text--body-md box--margin-top-4 box--flex-direction-row box--color-text-default"
|
|
||||||
>
|
|
||||||
Enter your token or add a new token
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--padding-bottom-7"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mm-box jwt-url-form mm-box--margin-bottom-8 mm-box--display-flex mm-box--flex-direction-column mm-box--align-items-flex-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mm-box jwt-url-form__jwt-container mm-box--margin-top-4 mm-box--margin-bottom-4 mm-box--display-flex mm-box--flex-direction-column mm-box--align-items-center mm-box--width-full"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--width-full"
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
class="box mm-text jwt-url-form__instruction mm-text--body-md box--margin-bottom-4 box--display-block box--flex-direction-row box--color-text-default"
|
|
||||||
>
|
|
||||||
Paste or drop your token here:
|
|
||||||
</p>
|
|
||||||
<textarea
|
|
||||||
class="jwt-url-form__input-jwt"
|
|
||||||
data-testid="jwt-input"
|
|
||||||
id="jwt-box"
|
|
||||||
>
|
|
||||||
token
|
|
||||||
</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--width-full"
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
class="box mm-text jwt-url-form__instruction mm-text--body-md box--display-block box--flex-direction-row box--color-text-default"
|
|
||||||
>
|
|
||||||
API URL
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--margin-top-4"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="jwt-url-form__input"
|
|
||||||
data-testid="jwt-api-url-input"
|
|
||||||
id="api-url-box"
|
|
||||||
value="url"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mm-box mm-box--padding-0 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-center"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="box mm-text mm-button-base mm-button-base--size-md mm-button-base--block mm-button-secondary mm-text--body-md box--margin-right-4 box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-default box--background-color-transparent box--rounded-pill box--border-color-primary-default box--border-style-solid box--border-width-1"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="box mm-text mm-button-base mm-button-base--size-md mm-button-base--block mm-button-primary mm-text--body-md box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-inverse box--background-color-primary-default box--rounded-pill"
|
|
||||||
data-testid="jwt-form-connect-button"
|
|
||||||
>
|
|
||||||
Connect
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ import { getCurrentChainId } from '../../../selectors';
|
|||||||
import { getMMIConfiguration } from '../../../selectors/institutional/selectors';
|
import { getMMIConfiguration } from '../../../selectors/institutional/selectors';
|
||||||
import CustodyAccountList from '../connect-custody/account-list';
|
import CustodyAccountList from '../connect-custody/account-list';
|
||||||
import JwtUrlForm from '../../../components/institutional/jwt-url-form';
|
import JwtUrlForm from '../../../components/institutional/jwt-url-form';
|
||||||
|
import PulseLoader from '../../../components/ui/pulse-loader/pulse-loader';
|
||||||
|
|
||||||
const CustodyPage = () => {
|
const CustodyPage = () => {
|
||||||
const t = useI18nContext();
|
const t = useI18nContext();
|
||||||
@ -55,6 +56,7 @@ const CustodyPage = () => {
|
|||||||
const currentChainId = useSelector(getCurrentChainId);
|
const currentChainId = useSelector(getCurrentChainId);
|
||||||
const { custodians } = useSelector(getMMIConfiguration);
|
const { custodians } = useSelector(getMMIConfiguration);
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
const [selectedAccounts, setSelectedAccounts] = useState({});
|
const [selectedAccounts, setSelectedAccounts] = useState({});
|
||||||
const [selectedCustodianName, setSelectedCustodianName] = useState('');
|
const [selectedCustodianName, setSelectedCustodianName] = useState('');
|
||||||
const [selectedCustodianImage, setSelectedCustodianImage] = useState(null);
|
const [selectedCustodianImage, setSelectedCustodianImage] = useState(null);
|
||||||
@ -200,12 +202,12 @@ const CustodyPage = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const getCustodianAccounts = useCallback(
|
const getCustodianAccounts = useCallback(
|
||||||
async (token, custody, getNonImportedAccounts) => {
|
async (token, getNonImportedAccounts) => {
|
||||||
return await dispatch(
|
return await dispatch(
|
||||||
mmiActions.getCustodianAccounts(
|
mmiActions.getCustodianAccounts(
|
||||||
token,
|
token,
|
||||||
apiUrl,
|
apiUrl,
|
||||||
custody || selectedCustodianType,
|
selectedCustodianType,
|
||||||
getNonImportedAccounts,
|
getNonImportedAccounts,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -218,12 +220,8 @@ const CustodyPage = () => {
|
|||||||
// If you have one JWT already, but no dropdown yet, currentJwt is null!
|
// If you have one JWT already, but no dropdown yet, currentJwt is null!
|
||||||
const jwt = currentJwt || jwtList[0];
|
const jwt = currentJwt || jwtList[0];
|
||||||
setConnectError('');
|
setConnectError('');
|
||||||
const accountsValue = await getCustodianAccounts(
|
const accountsValue = await getCustodianAccounts(jwt, true);
|
||||||
jwt,
|
|
||||||
apiUrl,
|
|
||||||
selectedCustodianType,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
setAccounts(accountsValue);
|
setAccounts(accountsValue);
|
||||||
trackEvent({
|
trackEvent({
|
||||||
category: 'MMI',
|
category: 'MMI',
|
||||||
@ -245,15 +243,16 @@ const CustodyPage = () => {
|
|||||||
handleConnectError,
|
handleConnectError,
|
||||||
jwtList,
|
jwtList,
|
||||||
selectedCustodianName,
|
selectedCustodianName,
|
||||||
selectedCustodianType,
|
|
||||||
trackEvent,
|
trackEvent,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setLoading(true);
|
||||||
const fetchConnectRequest = async () => {
|
const fetchConnectRequest = async () => {
|
||||||
const connectRequestValue = await dispatch(
|
const connectRequestValue = await dispatch(
|
||||||
mmiActions.getCustodianConnectRequest(),
|
mmiActions.getCustodianConnectRequest(),
|
||||||
);
|
);
|
||||||
|
|
||||||
setChainId(parseInt(currentChainId, 16));
|
setChainId(parseInt(currentChainId, 16));
|
||||||
|
|
||||||
// check if it's empty object
|
// check if it's empty object
|
||||||
@ -266,15 +265,22 @@ const CustodyPage = () => {
|
|||||||
setSelectedCustodianType(connectRequestValue.custodianType);
|
setSelectedCustodianType(connectRequestValue.custodianType);
|
||||||
setSelectedCustodianName(connectRequestValue.custodianName);
|
setSelectedCustodianName(connectRequestValue.custodianName);
|
||||||
setApiUrl(connectRequestValue.apiUrl);
|
setApiUrl(connectRequestValue.apiUrl);
|
||||||
connect();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// call the function
|
const handleFetchConnectRequest = async () => {
|
||||||
fetchConnectRequest()
|
try {
|
||||||
// make sure to catch any error
|
await fetchConnectRequest();
|
||||||
.catch(console.error);
|
setLoading(false);
|
||||||
}, [dispatch, connect, currentChainId, mmiActions]);
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleFetchConnectRequest();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleNetworkChange = async () => {
|
const handleNetworkChange = async () => {
|
||||||
@ -282,14 +288,7 @@ const CustodyPage = () => {
|
|||||||
const jwt = currentJwt || jwtList[0];
|
const jwt = currentJwt || jwtList[0];
|
||||||
|
|
||||||
if (jwt && jwt.length) {
|
if (jwt && jwt.length) {
|
||||||
setAccounts(
|
setAccounts(await getCustodianAccounts(jwt, true));
|
||||||
await getCustodianAccounts(
|
|
||||||
jwt,
|
|
||||||
apiUrl,
|
|
||||||
selectedCustodianType,
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -341,6 +340,10 @@ const CustodyPage = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <PulseLoader />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{connectError && (
|
{connectError && (
|
||||||
@ -348,7 +351,6 @@ const CustodyPage = () => {
|
|||||||
{connectError}
|
{connectError}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{selectError && (
|
{selectError && (
|
||||||
<Text textAlign={TextAlign.Center} marginTop={3} padding={[2, 7, 5]}>
|
<Text textAlign={TextAlign.Center} marginTop={3} padding={[2, 7, 5]}>
|
||||||
{selectError}
|
{selectError}
|
||||||
@ -397,7 +399,6 @@ const CustodyPage = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{!accounts && selectedCustodianType && (
|
{!accounts && selectedCustodianType && (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@ -485,7 +486,6 @@ const CustodyPage = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{accounts && accounts.length > 0 && (
|
{accounts && accounts.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@ -541,6 +541,10 @@ const CustodyPage = () => {
|
|||||||
selectedAccounts={selectedAccounts}
|
selectedAccounts={selectedAccounts}
|
||||||
onAddAccounts={async () => {
|
onAddAccounts={async () => {
|
||||||
try {
|
try {
|
||||||
|
const selectedCustodian = custodians.find(
|
||||||
|
(custodian) => custodian.name === selectedCustodianName,
|
||||||
|
);
|
||||||
|
|
||||||
await dispatch(
|
await dispatch(
|
||||||
mmiActions.connectCustodyAddresses(
|
mmiActions.connectCustodyAddresses(
|
||||||
selectedCustodianType,
|
selectedCustodianType,
|
||||||
@ -548,17 +552,7 @@ const CustodyPage = () => {
|
|||||||
selectedAccounts,
|
selectedAccounts,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const selectedCustodian = custodians.find(
|
|
||||||
(custodian) => custodian.name === selectedCustodianName,
|
|
||||||
);
|
|
||||||
history.push({
|
|
||||||
pathname: CUSTODY_ACCOUNT_DONE_ROUTE,
|
|
||||||
state: {
|
|
||||||
imgSrc: selectedCustodian.iconUrl,
|
|
||||||
title: t('custodianAccountAddedTitle'),
|
|
||||||
description: t('custodianAccountAddedDesc'),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
trackEvent({
|
trackEvent({
|
||||||
category: 'MMI',
|
category: 'MMI',
|
||||||
event: 'Custodial accounts connected',
|
event: 'Custodial accounts connected',
|
||||||
@ -568,6 +562,15 @@ const CustodyPage = () => {
|
|||||||
chainId,
|
chainId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
history.push({
|
||||||
|
pathname: CUSTODY_ACCOUNT_DONE_ROUTE,
|
||||||
|
state: {
|
||||||
|
imgSrc: selectedCustodian.iconUrl,
|
||||||
|
title: t('custodianAccountAddedTitle'),
|
||||||
|
description: t('custodianAccountAddedDesc'),
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setSelectError(e.message);
|
setSelectError(e.message);
|
||||||
}
|
}
|
||||||
@ -598,7 +601,6 @@ const CustodyPage = () => {
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{accounts && accounts.length === 0 && (
|
{accounts && accounts.length === 0 && (
|
||||||
<Box
|
<Box
|
||||||
data-testid="custody-accounts-empty"
|
data-testid="custody-accounts-empty"
|
||||||
@ -609,11 +611,11 @@ const CustodyPage = () => {
|
|||||||
marginBottom={2}
|
marginBottom={2}
|
||||||
fontWeight={FontWeight.Bold}
|
fontWeight={FontWeight.Bold}
|
||||||
color={TextColor.textDefault}
|
color={TextColor.textDefault}
|
||||||
variant={TextVariant.bodySm}
|
variant={TextVariant.bodyLgMedium}
|
||||||
>
|
>
|
||||||
{t('allCustodianAccountsConnectedTitle')}
|
{t('allCustodianAccountsConnectedTitle')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text variant={TextVariant.bodyXs}>
|
<Text variant={TextVariant.bodyMd}>
|
||||||
{t('allCustodianAccountsConnectedSubtitle')}
|
{t('allCustodianAccountsConnectedSubtitle')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import configureMockStore from 'redux-mock-store';
|
import configureMockStore from 'redux-mock-store';
|
||||||
import { fireEvent, waitFor, screen } from '@testing-library/react';
|
import { fireEvent, waitFor, screen, act } from '@testing-library/react';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
import CustodyPage from '.';
|
import CustodyPage from '.';
|
||||||
@ -16,8 +16,8 @@ const mockedGetCustodianConnectRequest = jest.fn().mockReturnValue({
|
|||||||
custodian: 'saturn',
|
custodian: 'saturn',
|
||||||
token: 'token',
|
token: 'token',
|
||||||
apiUrl: 'url',
|
apiUrl: 'url',
|
||||||
custodianType: 'JSON-RPC',
|
custodianType: undefined,
|
||||||
custodianName: 'Saturn',
|
custodianName: 'saturn',
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../../store/institutional/institution-background', () => ({
|
jest.mock('../../../store/institutional/institution-background', () => ({
|
||||||
@ -85,29 +85,19 @@ describe('CustodyPage', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls getCustodianJwtList on custody select when connect btn is click', async () => {
|
it('calls getCustodianJwtList on custody select when connect btn is click and clicks connect button and shows the jwt form', async () => {
|
||||||
const { getByTestId } = renderWithProvider(<CustodyPage />, store);
|
act(() => {
|
||||||
|
renderWithProvider(<CustodyPage />, store);
|
||||||
const custodyBtn = getByTestId('custody-connect-button');
|
|
||||||
await waitFor(() => {
|
|
||||||
fireEvent.click(custodyBtn);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(mockedGetCustodianJWTList).toHaveBeenCalled();
|
const custodyBtn = screen.getByTestId('custody-connect-button');
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('clicks connect button and shows the jwt form', async () => {
|
|
||||||
const { getByTestId } = renderWithProvider(<CustodyPage />, store);
|
|
||||||
const custodyBtn = getByTestId('custody-connect-button');
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
fireEvent.click(custodyBtn);
|
fireEvent.click(custodyBtn);
|
||||||
});
|
});
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByTestId('jwt-form-connect-button')).toBeInTheDocument();
|
expect(screen.getByTestId('jwt-form-connect-button')).toBeInTheDocument();
|
||||||
|
expect(mockedGetCustodianJWTList).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -117,7 +117,6 @@ describe('Institution Actions', () => {
|
|||||||
'newApiUrl',
|
'newApiUrl',
|
||||||
);
|
);
|
||||||
connectCustodyAddresses(jest.fn());
|
connectCustodyAddresses(jest.fn());
|
||||||
setWaitForConfirmDeepLinkDialog(jest.fn());
|
|
||||||
expect(connectCustodyAddresses).toBeDefined();
|
expect(connectCustodyAddresses).toBeDefined();
|
||||||
expect(setWaitForConfirmDeepLinkDialog).toBeDefined();
|
expect(setWaitForConfirmDeepLinkDialog).toBeDefined();
|
||||||
});
|
});
|
||||||
|
@ -91,14 +91,17 @@ export function mmiActionsFactory() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAction(name: string, payload: any) {
|
function createAction(name: string, payload: any): Promise<void> {
|
||||||
return () => {
|
return new Promise((resolve, reject) => {
|
||||||
callBackgroundMethod(name, [payload], (err) => {
|
callBackgroundMethod(name, [payload], (error) => {
|
||||||
if (isErrorWithMessage(err)) {
|
if (error) {
|
||||||
throw new Error(err.message);
|
reject(error);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolve();
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -190,18 +193,27 @@ export function mmiActionsFactory() {
|
|||||||
createAction('syncReportsInProgress', { address, historicalReports }),
|
createAction('syncReportsInProgress', { address, historicalReports }),
|
||||||
removeConnectInstitutionalFeature: (origin: string, projectId: string) =>
|
removeConnectInstitutionalFeature: (origin: string, projectId: string) =>
|
||||||
createAction('removeConnectInstitutionalFeature', { origin, projectId }),
|
createAction('removeConnectInstitutionalFeature', { origin, projectId }),
|
||||||
removeAddTokenConnectRequest: (
|
removeAddTokenConnectRequest: ({
|
||||||
origin: string,
|
origin,
|
||||||
apiUrl: string,
|
apiUrl,
|
||||||
token: string,
|
token,
|
||||||
) =>
|
}: {
|
||||||
|
origin: string;
|
||||||
|
apiUrl: string;
|
||||||
|
token: string;
|
||||||
|
}) =>
|
||||||
createAction('removeAddTokenConnectRequest', { origin, apiUrl, token }),
|
createAction('removeAddTokenConnectRequest', { origin, apiUrl, token }),
|
||||||
setCustodianConnectRequest: (
|
setCustodianConnectRequest: ({
|
||||||
token: string,
|
token,
|
||||||
apiUrl: string,
|
apiUrl,
|
||||||
custodianType: string,
|
custodianType,
|
||||||
custodianName: string,
|
custodianName,
|
||||||
) =>
|
}: {
|
||||||
|
token: string;
|
||||||
|
apiUrl: string;
|
||||||
|
custodianType: string;
|
||||||
|
custodianName: string;
|
||||||
|
}) =>
|
||||||
createAsyncAction('setCustodianConnectRequest', [
|
createAsyncAction('setCustodianConnectRequest', [
|
||||||
{ token, apiUrl, custodianType, custodianName },
|
{ token, apiUrl, custodianType, custodianName },
|
||||||
]),
|
]),
|
||||||
|
Loading…
Reference in New Issue
Block a user