Files
dydx-v4-web/src/views/notifications/TransferStatusNotification/TransferStatusSteps.tsx
T
Bill 0f16396c8d Implement CCTP withdraw (#188)
* Implement CCTP withdraw

* bump packages

* address comments
2023-12-12 10:12:37 -08:00

206 lines
5.8 KiB
TypeScript

import { useMemo } from 'react';
import styled, { css, type AnyStyledComponent } from 'styled-components';
import { StatusResponse } from '@0xsquid/sdk';
import { useStringGetter, useSelectedNetwork, useURLConfigs } from '@/hooks';
import { Link } from '@/components/Link';
import { Icon, IconName } from '@/components/Icon';
import { LoadingDots } from '@/components/Loading/LoadingDots';
import { LoadingSpinner } from '@/components/Loading/LoadingSpinner';
import { layoutMixins } from '@/styles/layoutMixins';
import { STRING_KEYS } from '@/constants/localization';
import { ENVIRONMENT_CONFIG_MAP } from '@/constants/networks';
import { TransferNotificationTypes } from '@/constants/notifications';
type ElementProps = {
status?: StatusResponse;
type: TransferNotificationTypes;
};
type StyleProps = {
className?: string;
};
enum TransferStatusStep {
FromChain,
Bridge,
ToChain,
Complete,
}
export const TransferStatusSteps = ({ className, status, type }: ElementProps & StyleProps) => {
const stringGetter = useStringGetter();
const { selectedNetwork } = useSelectedNetwork();
const { mintscan: mintscanTxUrl } = useURLConfigs();
const dydxChainId = ENVIRONMENT_CONFIG_MAP[selectedNetwork].dydxChainId;
const { currentStep, steps } = useMemo(() => {
const routeStatus = status?.routeStatus;
const fromChain = status?.fromChain?.chainData?.chainId;
const toChain = status?.toChain?.chainData?.chainId;
const currentStatus = routeStatus?.[routeStatus?.length - 1];
const steps = [
{
label: stringGetter({
key:
type === TransferNotificationTypes.Deposit
? STRING_KEYS.INITIATED_DEPOSIT
: STRING_KEYS.INITIATED_WITHDRAWAL,
}),
step: TransferStatusStep.FromChain,
link:
type === TransferNotificationTypes.Deposit
? status?.fromChain?.transactionUrl
: routeStatus?.[0]?.chainId === dydxChainId && routeStatus[0].txHash
? `${mintscanTxUrl?.replace('{tx_hash}', routeStatus[0].txHash.replace('0x', ''))}`
: undefined,
},
{
label: stringGetter({ key: STRING_KEYS.BRIDGING_TOKENS }),
step: TransferStatusStep.Bridge,
link: status?.axelarTransactionUrl,
},
{
label: stringGetter({
key:
type === TransferNotificationTypes.Deposit
? STRING_KEYS.DEPOSIT_TO_CHAIN
: STRING_KEYS.WITHDRAW_TO_CHAIN,
params: {
CHAIN:
type === TransferNotificationTypes.Deposit
? 'dYdX'
: status?.toChain?.chainData?.chainName,
},
}),
step: TransferStatusStep.ToChain,
link:
type === TransferNotificationTypes.Withdrawal
? status?.toChain?.transactionUrl
: currentStatus?.chainId === dydxChainId && currentStatus?.txHash
? `${mintscanTxUrl?.replace('{tx_hash}', currentStatus.txHash.replace('0x', ''))}`
: undefined,
},
];
let currentStep = TransferStatusStep.Bridge;
if (!routeStatus?.length) {
currentStep = TransferStatusStep.FromChain;
} else if (currentStatus.chainId === toChain) {
currentStep =
currentStatus.status !== 'success'
? TransferStatusStep.ToChain
: TransferStatusStep.Complete;
} else if (currentStatus.chainId === fromChain && currentStatus.status !== 'success') {
currentStep = TransferStatusStep.FromChain;
}
if (status?.squidTransactionStatus === 'success') {
currentStep = TransferStatusStep.Complete;
}
return {
currentStep,
steps,
type,
};
}, [status, stringGetter]);
if (!status) return <LoadingDots size={3} />;
return (
<Styled.BridgingStatus className={className}>
{steps.map((step) => (
<Styled.Step key={step.step}>
<Styled.row>
{step.step === currentStep ? (
<Styled.Icon>
<Styled.Spinner />
</Styled.Icon>
) : step.step < currentStep ? (
<Styled.Icon state="complete">
<Icon iconName={IconName.Check} />
</Styled.Icon>
) : (
<Styled.Icon state="default">{step.step + 1}</Styled.Icon>
)}
{step.link && currentStep >= step.step ? (
<Link href={step.link}>
<Styled.Label highlighted={currentStep >= step.step}>
{step.label}
<Icon iconName={IconName.LinkOut} />
</Styled.Label>
</Link>
) : (
<Styled.Label highlighted={currentStep >= step.step}>{step.label}</Styled.Label>
)}
</Styled.row>
</Styled.Step>
))}
</Styled.BridgingStatus>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.BridgingStatus = styled.div`
${layoutMixins.flexColumn};
gap: 1rem;
padding: 1rem 0;
`;
Styled.Step = styled.div`
${layoutMixins.spacedRow};
`;
Styled.row = styled.div`
${layoutMixins.inlineRow};
gap: 0.5rem;
`;
Styled.Icon = styled.div<{ state: 'complete' | 'default' }>`
display: flex;
align-items: center;
justify-content: center;
height: 2rem;
width: 2rem;
border-radius: 50%;
background-color: var(--color-layer-3);
${({ state }) =>
({
['complete']: css`
color: var(--color-positive);
`,
['default']: css`
color: var(--color-text-0);
`,
}[state])}
`;
Styled.Spinner = styled(LoadingSpinner)`
--spinner-width: 1.25rem;
color: var(--color-accent);
`;
Styled.Label = styled(Styled.row)<{ highlighted?: boolean }>`
${({ highlighted }) =>
highlighted
? css`
color: var(--color-text-2);
`
: css`
color: var(--color-text-0);
`}
`;