Skip to content

Commit

Permalink
Setup skeleton for deployer refund hook
Browse files Browse the repository at this point in the history
Generalize slide-in animation and use for deploy steps
Add TODOs on chain banners
  • Loading branch information
jmrossy committed Dec 26, 2024
1 parent e262111 commit 0b258e7
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 68 deletions.
6 changes: 3 additions & 3 deletions src/components/animation/PlanetSpinner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ export function PlanetSpinner() {
>
<Image
src={Planet1}
width={90}
height={90}
width={80}
height={80}
alt=""
className="animate-[spin_70s_linear_infinite]"
/>
<motion.div style={{ position: 'absolute', x: x, y: y }}>
<Image src={Planet2} width={26} height={26} alt="" className="" />
<Image src={Planet2} width={22} height={22} alt="" />
</motion.div>
</div>
);
Expand Down
37 changes: 37 additions & 0 deletions src/components/animation/SlideIn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { AnimatePresence, motion } from 'framer-motion';
import { PropsWithChildren } from 'react';

export function SlideIn({
key,
direction,
children,
}: PropsWithChildren<{ key: string | number; direction: 'forward' | 'backward' }>) {
return (
<AnimatePresence mode="wait" custom={direction}>
<motion.div
key={key}
custom={direction}
variants={variants}
transition={transition}
initial="enter"
animate="center"
exit="exit"
>
{children}
</motion.div>
</AnimatePresence>
);
}

const variants = {
enter: (direction: 'forward' | 'backward') => ({
opacity: 0,
x: direction === 'forward' ? 40 : -40,
}),
center: { opacity: 1, x: 0 },
exit: (direction: 'forward' | 'backward') => ({
opacity: 0,
x: direction === 'forward' ? -40 : 40,
}),
};
const transition = { duration: 0.5 };
1 change: 1 addition & 0 deletions src/features/chains/ChainConnectionWarning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ChainSelectListModal } from './ChainSelectModal';
import { useMultiProvider } from './hooks';
import { getChainDisplayName } from './utils';

// TODO refactor away from origin/destination
export function ChainConnectionWarning({
origin,
destination,
Expand Down
1 change: 1 addition & 0 deletions src/features/chains/ChainWalletWarning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { logger } from '../../utils/logger';
import { useMultiProvider } from './hooks';
import { getChainDisplayName } from './utils';

// TODO refactor away from origin
export function ChainWalletWarning({ origin }: { origin: ChainName }) {
const multiProvider = useMultiProvider();

Expand Down
4 changes: 0 additions & 4 deletions src/features/deployerWallet/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ export function useTempDeployerWallets(
};
}

// export function useSetTempDeployerWallet(protocols: ProtocolType[]) {
// const setDeployerKey = useStore((s) => s.setDeployerKey);
// }

export function useRemoveTempDeployerWallet(protocols: ProtocolType[]) {
const removeDeployerKey = useStore((s) => s.removeDeployerKey);
return () => protocols.map((p) => removeDeployerKey(p));
Expand Down
29 changes: 29 additions & 0 deletions src/features/deployerWallet/refund.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { sleep } from '@hyperlane-xyz/utils';
import { useMutation } from '@tanstack/react-query';
import { logger } from 'ethers';
import { useToastError } from '../../components/toast/useToastError';
import { useTempDeployerWallets } from './hooks';
import { TempDeployerWallets } from './types';

export function useRefundDeployerAccounts({ onSuccess }: { onSuccess?: () => void }) {
const { wallets } = useTempDeployerWallets([]);

const { error, mutate } = useMutation({
mutationKey: ['refundDeployerAccounts', wallets],
mutationFn: () => refundDeployerAccounts(wallets),
retry: 3,
onSuccess,
});

useToastError(error, 'Error refunding deployer balances. Please try again later.');

return mutate;
}

async function refundDeployerAccounts(_wallets: TempDeployerWallets) {
//TODO
logger.info('Refunding deployer accounts');
await sleep(10_000);
logger.info('Done refunding deployer accounts');
return true;
}
2 changes: 1 addition & 1 deletion src/features/deployment/DeploymentDetailsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function CollapsibleData({ data, label }: { data: any; label: string }) {
</DisclosureButton>
<DisclosurePanel
transition
className="relative mt-1 overflow-x-auto rounded-md bg-primary-500/5 px-1.5 py-1 text-xs transition duration-200 data-[closed]:-translate-y-4 data-[closed]:opacity-0"
className="relative mt-1 overflow-x-auto rounded-md bg-primary-500/5 px-1.5 py-1 text-xs transition duration-300 data-[closed]:-translate-y-4 data-[closed]:opacity-0"
>
<pre>{yamlConfig}</pre>
<CopyButton
Expand Down
89 changes: 57 additions & 32 deletions src/features/deployment/warp/WarpDeploymentDeploy.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ArrowIcon, Button, Modal, useModal, WalletIcon } from '@hyperlane-xyz/widgets';
import { useState } from 'react';
import { Button, Modal, SpinnerIcon, useModal } from '@hyperlane-xyz/widgets';
import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
import { PlanetSpinner } from '../../../components/animation/PlanetSpinner';
import { SlideIn } from '../../../components/animation/SlideIn';
import { SolidButton } from '../../../components/buttons/SolidButton';
import { GasIcon } from '../../../components/icons/GasIcon';
import { LogsIcon } from '../../../components/icons/LogsIcon';
Expand All @@ -15,21 +16,25 @@ import { useMultiProvider } from '../../chains/hooks';
import { getChainDisplayName } from '../../chains/utils';
import { useFundDeployerAccount } from '../../deployerWallet/fund';
import { getDeployerAddressForProtocol, useTempDeployerWallets } from '../../deployerWallet/hooks';
import { useRefundDeployerAccounts } from '../../deployerWallet/refund';
import { useDeploymentHistory, useWarpDeploymentConfig } from '../hooks';
import { DeploymentStatus } from '../types';

enum DeployStep {
FundDeployer,
ExecuteDeploy,
AddFunds,
CancelDeploy,
}

export function WarpDeploymentDeploy() {
const [step, setStep] = useState(DeployStep.FundDeployer);

return (
<div className="flex w-full flex-col items-center space-y-5 py-2 xs:min-w-100">
<div className="flex w-full flex-col items-center space-y-4 py-2 xs:min-w-100">
<HeaderSection />
<MainSection />
<ButtonSection />
<MainSection step={step} setStep={setStep} />
<ButtonSection step={step} setStep={setStep} />
</div>
);
}
Expand All @@ -38,11 +43,9 @@ function HeaderSection() {
return <H1 className="text-center">Deploying Warp Route</H1>;
}

function MainSection() {
function MainSection({ step, setStep }: { step: DeployStep; setStep: (s: DeployStep) => void }) {
const { setPage } = useCardNav();

const [step, setStep] = useState(DeployStep.FundDeployer);

const onDeployerFunded = () => {
setStep(DeployStep.ExecuteDeploy);
};
Expand All @@ -54,12 +57,15 @@ function MainSection() {
};

return (
<div className="space-y-3">
{step === DeployStep.FundDeployer && (
<FundDeployerAccounts onSuccess={onDeployerFunded} onFailure={onFailure} />
)}
{step === DeployStep.ExecuteDeploy && <ExecuteDeploy />}
{step === DeployStep.AddFunds && <FundSingleDeployerAccount />}
<div className="flex grow flex-col items-center justify-center space-y-3 sm:min-h-[18rem]">
<SlideIn key={step} direction="forward">
{step === DeployStep.FundDeployer && (
<FundDeployerAccounts onSuccess={onDeployerFunded} onFailure={onFailure} />
)}
{step === DeployStep.ExecuteDeploy && <ExecuteDeploy />}
{step === DeployStep.AddFunds && <FundSingleDeployerAccount />}
{step === DeployStep.CancelDeploy && <CancelDeploy />}
</SlideIn>
</div>
);
}
Expand Down Expand Up @@ -102,14 +108,14 @@ function FundDeployerAccounts({
};

return (
<div className="flex flex-col items-center space-y-6 py-4">
<FundIcons color={Color.primary['500']} />
<div className="flex flex-col items-center space-y-7">
<FundIcon color={Color.primary['500']} />
<p className="max-w-sm text-center text-md leading-relaxed">
To deploy, a temporary account must be funded for each chain. Unused amounts are refunded.
</p>
<SolidButton
color="accent"
className="px-3 py-1.5 text-md"
className="px-4 py-1.5 text-md"
onClick={onClickFund}
disabled={isTxPending || isDeployerLoading}
>{`Fund on ${currentChainDisplay} (Chain ${currentChainIndex + 1} / ${numChains})`}</SolidButton>
Expand All @@ -124,7 +130,7 @@ function FundSingleDeployerAccount() {

return (
<div className="flex flex-col items-center space-y-5 py-4">
<FundIcons color={Color.amber['500']} />
<FundIcon color={Color.amber['500']} />
<p className="text-center text-sm font-semibold leading-relaxed">
Deployer has insufficient funds on Ethereum.
</p>
Expand All @@ -138,12 +144,10 @@ function FundSingleDeployerAccount() {
);
}

function FundIcons({ color }: { color: string }) {
function FundIcon({ color }: { color: string }) {
return (
<div className="flex items-center justify-center gap-3">
<WalletIcon width={44} height={44} color={color} />
<ArrowIcon width={20} height={20} color={color} direction="e" />
<GasIcon width={42} height={42} color={color} />
<div className="flex items-center justify-center">
<GasIcon width={68} height={68} color={color} />
</div>
);
}
Expand All @@ -167,10 +171,10 @@ function ExecuteDeploy() {
</div>
<div className="mt-1">
<p className="max-w-sm text-gray-700">{`Deploying to ${chainListString}`}</p>
<p className="text-gray-700">This will take a few minutes.</p>
<p className="mt-2 text-sm">TODO status text</p>
<p className="text-gray-700">This will take a few minutes</p>
<p className="mt-3">TODO status text</p>
</div>
<Button onClick={onClickViewLogs} className="mt-4 gap-2.5">
<Button onClick={onClickViewLogs} className="mt-3 gap-2.5">
<LogsIcon width={14} height={14} color={Color.accent['500']} />
<span className="text-md text-accent-500">View deployment logs</span>
</Button>
Expand All @@ -181,18 +185,39 @@ function ExecuteDeploy() {
);
}

function ButtonSection() {
const { updateDeploymentStatus, currentIndex } = useDeploymentHistory();
function CancelDeploy() {
const { setPage } = useCardNav();
const onSuccess = () => {
setPage(CardPage.WarpForm);
};
const refundDeployer = useRefundDeployerAccounts({ onSuccess });
// Run on mount
useEffect(() => {
refundDeployer();
}, [refundDeployer]);

return (
<div className="flex flex-col items-center space-y-7">
<SpinnerIcon width={70} height={70} color={Color.primary['500']} />
<p className="max-w-sm text-center text-md leading-relaxed">
Canceling the deployment and refunding any unused deployer balances
</p>
<p className="max-w-sm text-center text-md leading-relaxed">This may take a minute</p>
</div>
);
}

function ButtonSection({ step, setStep }: { step: DeployStep; setStep: (s: DeployStep) => void }) {
const { updateDeploymentStatus, currentIndex } = useDeploymentHistory();
// const { setPage } = useCardNav();
// setPage(CardPage.WarpForm);
const onClickCancel = () => {
// TODO cancel in SDK if possible?
toast.warn('Deployment cancelled');
updateDeploymentStatus(currentIndex, DeploymentStatus.Cancelled);
setPage(CardPage.WarpForm);
setStep(DeployStep.CancelDeploy);
};

return (
<Button onClick={onClickCancel} className="gap-2.5">
<Button onClick={onClickCancel} className="gap-2.5" disabled={step === DeployStep.CancelDeploy}>
<StopIcon width={16} height={16} color={Color.accent['500']} />
<span className="text-md text-accent-500">Cancel deployment</span>
</Button>
Expand Down
32 changes: 4 additions & 28 deletions src/flows/CardFlow.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AnimatePresence, motion } from 'framer-motion';
import { SlideIn } from '../components/animation/SlideIn';
import { WarpDeploymentDeploy } from '../features/deployment/warp/WarpDeploymentDeploy';
import { WarpDeploymentFailure } from '../features/deployment/warp/WarpDeploymentFailure';
import { WarpDeploymentForm } from '../features/deployment/warp/WarpDeploymentForm';
Expand Down Expand Up @@ -30,32 +30,8 @@ export function CardFlow() {
const PageComponent = PAGE_TO_COMPONENT[FORCE_PAGE || page];

return (
<AnimatePresence mode="wait" custom={direction}>
<motion.div
key={page}
custom={direction}
variants={variants}
transition={transition}
initial="enter"
animate="center"
exit="exit"
>
<PageComponent />
</motion.div>
;
</AnimatePresence>
<SlideIn key={page} direction={direction}>
<PageComponent />
</SlideIn>
);
}

const variants = {
enter: (direction: 'forward' | 'backward') => ({
opacity: 0,
x: direction === 'forward' ? 40 : -40,
}),
center: { opacity: 1, x: 0 },
exit: (direction: 'forward' | 'backward') => ({
opacity: 0,
x: direction === 'forward' ? -40 : 40,
}),
};
const transition = { duration: 0.3 };

0 comments on commit 0b258e7

Please sign in to comment.