Skip to content

Commit

Permalink
Define deployment history types and show in sidebar
Browse files Browse the repository at this point in the history
Remove warp-ui-specific code from Sidebar and DeploymentDetailsModal
  • Loading branch information
jmrossy committed Dec 23, 2024
1 parent e97766c commit 672124d
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 315 deletions.
28 changes: 28 additions & 0 deletions src/components/icons/ConfirmedIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { DefaultIconProps } from '@hyperlane-xyz/widgets';
import { memo } from 'react';
import { Color } from '../../styles/Color';

// TODO move to widgets lib
function _ConfirmedIcon({ color, ...rest }: DefaultIconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 26" {...rest}>
<g clip-path="url(#confirmed-icon-clip-path)">
<path
d="M1.93105 13.4815C1.93076 11.6219 2.42129 9.79511 3.35333 8.1846C4.28537 6.57409 5.62608 5.23667 7.24067 4.30678C8.85527 3.37689 10.6869 2.8873 12.5513 2.88723C14.4158 2.88716 16.2474 3.3766 17.8621 4.30637C18.0837 4.43205 18.3462 4.46519 18.5923 4.39857C18.8383 4.33194 19.048 4.17096 19.1754 3.95074C19.3029 3.73052 19.3379 3.46895 19.2727 3.22311C19.2076 2.97727 19.0475 2.76712 18.8276 2.63851C16.4348 1.26067 13.653 0.708778 10.9136 1.06842C8.17424 1.42807 5.63041 2.67916 3.67662 4.62766C1.72282 6.57616 0.468253 9.11318 0.107478 11.8453C-0.253297 14.5774 0.299883 17.3519 1.68123 19.7384C3.06257 22.125 5.19488 23.9903 7.74747 25.0451C10.3001 26.0998 13.1303 26.2851 15.7992 25.5721C18.4681 24.8592 20.8266 23.2878 22.5088 21.1018C24.1911 18.9157 25.1031 16.2372 25.1035 13.4815C25.1035 13.2261 25.0017 12.9812 24.8207 12.8006C24.6396 12.62 24.394 12.5185 24.1379 12.5185C23.8819 12.5185 23.6363 12.62 23.4552 12.8006C23.2741 12.9812 23.1724 13.2261 23.1724 13.4815C23.1724 16.2908 22.0535 18.9851 20.0617 20.9716C18.0699 22.9581 15.3685 24.0741 12.5517 24.0741C9.73495 24.0741 7.03354 22.9581 5.04178 20.9716C3.05001 18.9851 1.93105 16.2908 1.93105 13.4815Z"
fill={color || Color.black}
/>
<path
d="M26.7526 4.53363C26.8424 4.4441 26.9136 4.33781 26.9622 4.22083C27.0108 4.10385 27.0358 3.97847 27.0358 3.85185C27.0358 3.72523 27.0108 3.59986 26.9622 3.48288C26.9136 3.3659 26.8424 3.25961 26.7526 3.17007C26.6629 3.08054 26.5563 3.00952 26.439 2.96107C26.3217 2.91261 26.196 2.88767 26.0691 2.88767C25.9421 2.88767 25.8164 2.91261 25.6991 2.96107C25.5818 3.00952 25.4752 3.08054 25.3855 3.17007L12.5518 15.9717L7.44231 10.8738C7.35254 10.7842 7.24597 10.7132 7.12868 10.6648C7.01139 10.6163 6.88568 10.5914 6.75873 10.5914C6.63178 10.5914 6.50606 10.6163 6.38877 10.6648C6.27148 10.7132 6.16491 10.7842 6.07514 10.8738C5.98537 10.9633 5.91416 11.0696 5.86558 11.1866C5.817 11.3036 5.79199 11.4289 5.79199 11.5556C5.79199 11.6822 5.817 11.8076 5.86558 11.9245C5.91416 12.0415 5.98537 12.1478 6.07514 12.2373L11.8682 18.0151C11.9579 18.1048 12.0645 18.1759 12.1818 18.2245C12.2991 18.273 12.4248 18.298 12.5518 18.298C12.6788 18.298 12.8046 18.273 12.9219 18.2245C13.0392 18.1759 13.1457 18.1048 13.2354 18.0151L26.7526 4.53363Z"
fill={color || Color.black}
/>
</g>
<defs>
<clipPath id="confirmed-icon-clip-path">
<rect width="28" height="26" fill="white" />
</clipPath>
</defs>
</svg>
);
}

export const ConfirmedIcon = memo(_ConfirmedIcon);
4 changes: 2 additions & 2 deletions src/components/icons/GasIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import { Color } from '../../styles/Color';
function _GasIcon({ color, ...rest }: DefaultIconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" {...rest}>
<g clipPath="url(#gas-icon)">
<g clipPath="url(#gas-icon-clip-path)">
<path
fill={color || Color.black}
d="M3.1 6.3A6.3 6.3 0 0 1 9.4 0H28a6.2 6.2 0 0 1 6.3 6.3v25a6.2 6.2 0 0 1 6.2 6.2v1.6a1.6 1.6 0 0 0 3.1 0V25h-1.5a1.6 1.6 0 0 1-1.6-1.6v-9.7a1.6 1.6 0 0 1 1.6-1.6h4.7a10 10 0 0 0-.7-3.8A3 3 0 0 0 45 6.9a5 5 0 0 0-2.8-.7 1.6 1.6 0 0 1 0-3c1.8 0 3.2.3 4.4 1 1.2.7 2 1.7 2.5 2.8.9 2 .9 4.6.9 6.5v10a1.6 1.6 0 0 1-1.6 1.5H47v14a4.7 4.7 0 0 1-9.4 0v-1.5a3.1 3.1 0 0 0-3.1-3.1v12.5H36a1.6 1.6 0 0 1 0 3.1H1.6a1.6 1.6 0 1 1 0-3.1H3V6.3Zm7.8 0a1.6 1.6 0 0 0-1.5 1.5v15.6a1.6 1.6 0 0 0 1.5 1.6h15.7a1.6 1.6 0 0 0 1.5-1.6V7.8a1.6 1.6 0 0 0-1.5-1.5H10.9Z"
/>
</g>
<defs>
<clipPath id="gas-icon">
<clipPath id="gas-icon-clip-path">
<path fill="#fff" d="M0 0h50v50H0z" />
</clipPath>
</defs>
Expand Down
4 changes: 2 additions & 2 deletions src/components/icons/StopIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import { Color } from '../../styles/Color';
function _StopIcon({ color, ...rest }: DefaultIconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" {...rest}>
<g clipPath="url(#stop-icon)">
<g clipPath="url(#stop-icon-clip-path)">
<path
fill={color || Color.black}
d="M3.5 12 0 8.5v-5L3.5 0h5L12 3.5v5L8.5 12h-5Zm.6-3.2L6 7l1.9 2 1-1-2-1.9 2-1.9-1-1-1.9 2-1.9-2-1 1 2 1.9-2 1.9 1 1Zm0 1.9h3.8l2.8-2.8V4.1L7.9 1.3H4.1L1.3 4.1v3.8l2.8 2.8Z"
/>
</g>
<defs>
<clipPath id="stop-icon">
<clipPath id="stop-icon-clip-path">
<path fill="#fff" d="M0 0h12v12H0z" />
</clipPath>
</defs>
Expand Down
153 changes: 33 additions & 120 deletions src/features/deployment/DeploymentDetailsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
import { ProtocolType } from '@hyperlane-xyz/utils';
import {
CopyButton,
Modal,
SpinnerIcon,
useAccountForChain,
useTimeout,
useWalletDetails,
} from '@hyperlane-xyz/widgets';
import Image from 'next/image';
import { useCallback, useMemo, useState } from 'react';
import LinkIcon from '../../images/icons/external-link-icon.svg';
import { Modal } from '@hyperlane-xyz/widgets';
import { useMemo } from 'react';
import { formatTimestamp } from '../../utils/date';
import { useMultiProvider } from '../chains/hooks';
import { hasPermissionlessChain } from '../chains/utils';
import { DeploymentContext, DeploymentStatus } from './types';
import {
getDeploymentStatusLabel,
getIconByDeploymentStatus,
isDeploymentFailed,
isDeploymentSent,
} from './utils';
import { DeploymentContext } from './types';

export function DeploymentsDetailsModal({
isOpen,
Expand All @@ -30,27 +12,7 @@ export function DeploymentsDetailsModal({
onClose: () => void;
deployment: DeploymentContext;
}) {
const { status, origin, destination, timestamp } = deployment || {};

const multiProvider = useMultiProvider();

const isChainKnown = multiProvider.hasChain(origin);
const account = useAccountForChain(multiProvider, isChainKnown ? origin : undefined);
const walletDetails = useWalletDetails()[account?.protocol || ProtocolType.Ethereum];

const isAccountReady = !!account?.isReady;
const connectorName = walletDetails.name || 'wallet';
const isPermissionlessRoute = hasPermissionlessChain(multiProvider, [destination, origin]);
const isSent = isDeploymentSent(status);
const isFailed = isDeploymentFailed(status);
const isFinal = isSent || isFailed;
const statusDescription = getDeploymentStatusLabel(
status,
connectorName,
isPermissionlessRoute,
isAccountReady,
);
const showSignWarning = useSignIssueWarning(status);
const { status, timestamp } = deployment || {};

const date = useMemo(
() => (timestamp ? formatTimestamp(timestamp) : formatTimestamp(new Date().getTime())),
Expand All @@ -59,85 +21,36 @@ export function DeploymentsDetailsModal({

return (
<Modal isOpen={isOpen} close={onClose} panelClassname="p-4 md:p-5 max-w-sm">
{isFinal && (
<div className="flex justify-between">
<h2 className="font-medium text-gray-600">{date}</h2>
<div className="flex items-center font-medium">
{isSent ? (
<h3 className="text-primary-500">Sent</h3>
) : (
<h3 className="text-red-500">Failed</h3>
)}
<Image
src={getIconByDeploymentStatus(status)}
width={25}
height={25}
alt=""
className="ml-2"
/>
</div>
</div>
)}

{isFinal ? (
<div className="mt-5 flex flex-col space-y-4">TODO</div>
) : (
<div className="flex flex-col items-center justify-center py-4">
<SpinnerIcon width={60} height={60} className="mt-3" />
<div
className={`mt-5 text-center text-sm ${isFailed ? 'text-red-600' : 'text-gray-600'}`}
>
{statusDescription}
</div>
{showSignWarning && (
<div className="mt-3 text-center text-sm text-gray-600">
If your wallet does not show a transaction request or never confirms, please try the
deployment again.
</div>
)}
</div>
)}
{status}
{date}
</Modal>
);
}

export function DeploymentProperty({
name,
value,
url,
}: {
name: string;
value: string;
url?: string;
}) {
return (
<div>
<div className="flex items-center justify-between">
<label className="text-sm leading-normal tracking-wider text-gray-350">{name}</label>
<div className="flex items-center space-x-2">
{url && (
<a href={url} target="_blank" rel="noopener noreferrer">
<Image src={LinkIcon} width={14} height={14} alt="" />
</a>
)}
<CopyButton copyValue={value} width={14} height={14} className="opacity-40" />
</div>
</div>
<div className="mt-1 truncate text-sm leading-normal tracking-wider">{value}</div>
</div>
);
}

// https://github.com/wagmi-dev/wagmi/discussions/2928
function useSignIssueWarning(status: DeploymentStatus) {
const [showWarning, setShowWarning] = useState(false);
const warningCallback = useCallback(() => {
if (
status === DeploymentStatus.SigningDeployment ||
status === DeploymentStatus.ConfirmingDeployment
)
setShowWarning(true);
}, [status, setShowWarning]);
useTimeout(warningCallback, 20_000);
return showWarning;
}
// TODO remove?
// function DeploymentProperty({
// name,
// value,
// url,
// }: {
// name: string;
// value: string;
// url?: string;
// }) {
// return (
// <div>
// <div className="flex items-center justify-between">
// <label className="text-sm leading-normal tracking-wider text-gray-350">{name}</label>
// <div className="flex items-center space-x-2">
// {url && (
// <a href={url} target="_blank" rel="noopener noreferrer">
// <Image src={LinkIcon} width={14} height={14} alt="" />
// </a>
// )}
// <CopyButton copyValue={value} width={14} height={14} className="opacity-40" />
// </div>
// </div>
// <div className="mt-1 truncate text-sm leading-normal tracking-wider">{value}</div>
// </div>
// );
// }
8 changes: 8 additions & 0 deletions src/features/deployment/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ export function useCoreDeploymentConfig() {
const warpConfig = deploymentConfig?.type === DeploymentType.Core ? deploymentConfig : undefined;
return { deploymentConfig: warpConfig, setDeploymentConfig };
}

export function useDeploymentHistory() {
return useStore((s) => ({
deployments: s.deployments,
addDeployment: s.addDeployment,
updateDeploymentStatus: s.updateDeploymentStatus,
}));
}
62 changes: 36 additions & 26 deletions src/features/deployment/types.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,33 @@
import { ChainName, WarpRouteDeployConfig } from '@hyperlane-xyz/sdk';
import { ChainName, WarpCoreConfig, WarpRouteDeployConfig } from '@hyperlane-xyz/sdk';

export enum DeploymentStatus {
Preparing = 'preparing',
CreatingTxs = 'creating-txs',
SigningApprove = 'signing-approve',
ConfirmingApprove = 'confirming-approve',
SigningDeployment = 'signing-deployment',
ConfirmingDeployment = 'confirming-deployment',
ConfirmedDeployment = 'confirmed-deployment',
// TODO
Delivered = 'delivered',
Configured = 'configured',
Deploying = 'deploying',
Complete = 'complete',
Cancelled = 'cancelled',
Failed = 'failed',
}

// TODO
export const SentDeploymentStatuses = [
DeploymentStatus.ConfirmedDeployment,
DeploymentStatus.Delivered,
];

// Statuses considered not pending
export const FinalDeploymentStatuses = [...SentDeploymentStatuses, DeploymentStatus.Failed];

export interface DeploymentContext {
status: DeploymentStatus;
origin: ChainName;
destination: ChainName;
timestamp: number;
}

export enum DeploymentType {
Warp = 'warp',
Core = 'core',
// Add more here as needed
}

export const FinalDeploymentStatuses = [
DeploymentStatus.Complete,
DeploymentStatus.Cancelled,
DeploymentStatus.Failed,
];

export interface DeploymentContext {
timestamp: number;
status: DeploymentStatus;
type: DeploymentType;
config: DeploymentConfig;
result?: DeploymentResult;
}

interface ConfigBase {
type: DeploymentType;
config: unknown;
Expand All @@ -52,3 +45,20 @@ export interface CoreDeploymentConfig extends ConfigBase {
}

export type DeploymentConfig = WarpDeploymentConfig | CoreDeploymentConfig;

interface ResultBase {
type: DeploymentType;
result: unknown;
}

export interface WarpDeploymentResult extends ResultBase {
type: DeploymentType.Warp;
result: WarpCoreConfig;
}

export interface CoreDeploymentResult extends ResultBase {
type: DeploymentType.Core;
config: any; // TODO
}

export type DeploymentResult = WarpDeploymentResult | CoreDeploymentResult;
Loading

0 comments on commit 672124d

Please sign in to comment.