Skip to content

Commit

Permalink
Update ConnectAwareSubmitButton for multi-protocol
Browse files Browse the repository at this point in the history
Filter chain list to evm-only
  • Loading branch information
jmrossy committed Dec 8, 2024
1 parent 5984a1c commit daab552
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 26 deletions.
38 changes: 21 additions & 17 deletions src/components/buttons/ConnectAwareSubmitButton.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
import { ProtocolType } from '@hyperlane-xyz/utils';
import { useAccountForChain, useConnectFns, useTimeout } from '@hyperlane-xyz/widgets';
import { useAccounts, useConnectFns, useTimeout } from '@hyperlane-xyz/widgets';
import { useFormikContext } from 'formik';
import { useCallback } from 'react';
import { useChainProtocol, useMultiProvider } from '../../features/chains/hooks';
import { useCallback, useMemo } from 'react';
import { useMultiProvider } from '../../features/chains/hooks';
import { SolidButton } from './SolidButton';

interface Props {
chainName: ChainName;
chains: ChainName[];
text: string;
classes?: string;
className?: string;
}

export function ConnectAwareSubmitButton<FormValues = any>({ chainName, text, classes }: Props) {
const protocol = useChainProtocol(chainName) || ProtocolType.Ethereum;
export function ConnectAwareSubmitButton<FormValues>({ chains, text, className }: Props) {
const multiProvider = useMultiProvider();
const { accounts } = useAccounts(multiProvider);
const connectFns = useConnectFns();
const connectFn = connectFns[protocol];

const multiProvider = useMultiProvider();
const account = useAccountForChain(multiProvider, chainName);
const isAccountReady = account?.isReady;
const unconnectedProtocols = useMemo(() => {
const protocols = new Set(chains.map((c) => multiProvider.getProtocol(c)));
return [...protocols.values().filter((p) => !accounts[p]?.isReady)];
}, [accounts, chains, multiProvider]);
const isAccountsReady = unconnectedProtocols.length === 0;

const { errors, setErrors, touched, setTouched } = useFormikContext<FormValues>();

const hasError = Object.keys(touched).length > 0 && Object.keys(errors).length > 0;
const firstError = `${Object.values(errors)[0]}` || 'Unknown error';

const color = hasError ? 'red' : 'accent';
const content = hasError ? firstError : isAccountReady ? text : 'Connect wallet';
const type = isAccountReady ? 'submit' : 'button';
const onClick = isAccountReady ? undefined : connectFn;
const type = isAccountsReady ? 'submit' : 'button';
const onClick = isAccountsReady ? undefined : connectFns[unconnectedProtocols[0]];

let content;
if (hasError) content = 'Error';
else if (isAccountsReady) content = text;
else content = `Connect wallet${unconnectedProtocols.length > 1 ? 's' : ''}`;

// Automatically clear error state after a timeout
const clearErrors = useCallback(() => {
Expand All @@ -40,7 +44,7 @@ export function ConnectAwareSubmitButton<FormValues = any>({ chainName, text, cl
useTimeout(clearErrors, 3500);

return (
<SolidButton type={type} color={color} onClick={onClick} className={classes}>
<SolidButton type={type} color={color} onClick={onClick} className={className}>
{content}
</SolidButton>
);
Expand Down
1 change: 0 additions & 1 deletion src/features/chains/ChainSelectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export function ChainSelectListModal({
onClickChain={onSelectChain}
overrideChainMetadata={chainMetadataOverrides}
onChangeOverrideMetadata={setChainMetadataOverrides}
defaultSortField="custom"
showChainDetails={showChainDetails}
/>
</Modal>
Expand Down
10 changes: 8 additions & 2 deletions src/features/chains/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ChainMetadataSchema,
mergeChainMetadataMap,
} from '@hyperlane-xyz/sdk';
import { objMap, promiseObjAll } from '@hyperlane-xyz/utils';
import { objFilter, objMap, promiseObjAll, ProtocolType } from '@hyperlane-xyz/utils';
import { z } from 'zod';
import { chains as ChainsTS } from '../../consts/chains.ts';
import ChainsYaml from '../../consts/chains.yaml';
Expand Down Expand Up @@ -47,7 +47,13 @@ export async function assembleChainMetadata(
),
);

const chainMetadata = mergeChainMetadataMap(registryChainMetadata, filesystemMetadata);
// TODO remove if/when this app isn't EVM-only
const evmRegistryChainMetadata = objFilter(
registryChainMetadata,
(_, m): m is ChainMetadata => m.protocol === ProtocolType.Ethereum,
);

const chainMetadata = mergeChainMetadataMap(evmRegistryChainMetadata, filesystemMetadata);
const chainMetadataWithOverrides = mergeChainMetadataMap(chainMetadata, storeMetadataOverrides);
return { chainMetadata, chainMetadataWithOverrides };
}
12 changes: 6 additions & 6 deletions src/features/deployment/warp/WarpDeploymentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { errorToString, ProtocolType } from '@hyperlane-xyz/utils';
import { AccountInfo, Button, IconButton, useAccounts, XIcon } from '@hyperlane-xyz/widgets';
import { Form, Formik, useFormikContext } from 'formik';
import Image from 'next/image';
import { useMemo } from 'react';
import { BackButton } from '../../../components/buttons/BackButton';
import { ConnectAwareSubmitButton } from '../../../components/buttons/ConnectAwareSubmitButton';
import { TextInput } from '../../../components/input/TextField';
Expand Down Expand Up @@ -58,7 +59,7 @@ export function WarpDeploymentForm() {
{() => (
<Form className="flex w-full flex-col items-stretch">
<WarningBanners />
<div className="space-y-6">
<div className="space-y-5">
<HeaderSection />
<ConfigListSection />
<ButtonSection />
Expand Down Expand Up @@ -174,15 +175,14 @@ function AddConfigButton() {

function ButtonSection() {
const { values } = useFormikContext<WarpDeploymentFormValues>();

const chains = useMemo(() => values.configs.map((c) => c.chainName), [values]);
return (
<div className="mt-4 flex items-center justify-between">
<BackButton page={CardPage.Landing} />
{/* // TODO check for all chains, not just one */}
<ConnectAwareSubmitButton
chainName={values.configs[0].chainName}
<ConnectAwareSubmitButton<WarpDeploymentFormValues>
chains={chains}
text="Continue"
classes="px-3 py-1.5"
className="px-3 py-1.5"
/>
</div>
);
Expand Down

0 comments on commit daab552

Please sign in to comment.