diff --git a/components/chain-list/chain-item.tsx b/components/chain-list/chain-item.tsx index 317f319..03547a9 100644 --- a/components/chain-list/chain-item.tsx +++ b/components/chain-list/chain-item.tsx @@ -1,4 +1,4 @@ -import { ChainItemType } from "../../types"; +import { ChainItemType, DisabledChainItemType } from "../../types"; import { FunctionComponent, useEffect, useState } from "react"; import color from "../../styles/color"; @@ -8,14 +8,14 @@ import { ChainImage } from "./chain-image"; import { Checkbox } from "../checkbox"; interface Props { - chainItem: ChainItemType; + chainItem: ChainItemType | DisabledChainItemType; checkedItemHandler: (chainItem: ChainItemType, isChecked: boolean) => void; checkedItems: Set; - disabled?: boolean; } export const ChainItem: FunctionComponent = (props) => { - const { chainItem, checkedItemHandler, checkedItems, disabled } = props; + const { chainItem, checkedItemHandler, checkedItems } = props; + const disabled = "disabled" in chainItem && chainItem.disabled; const [checked, setChecked] = useState(!!disabled); const checkHandler = () => { @@ -46,7 +46,12 @@ export const ChainItem: FunctionComponent = (props) => { /> {`.${chainItem.prefix}`} - {chainItem.address} + {chainItem.address ? ( + {chainItem.address} + ) : null} + {disabled && chainItem.reason ? ( + {chainItem.reason.message} + ) : null} @@ -117,3 +122,10 @@ export const WalletAddress = styled.div` color: ${color.grey["400"]}; `; + +export const DisabledReason = styled.div` + color: ${color.grey["200"]}; + font-weight: 500; + font-size: 14px; + line-height: 17px; +`; diff --git a/components/chain-list/chain-list.tsx b/components/chain-list/chain-list.tsx index 805b241..566c8f0 100644 --- a/components/chain-list/chain-list.tsx +++ b/components/chain-list/chain-list.tsx @@ -1,12 +1,12 @@ import { Dispatch, FunctionComponent, SetStateAction, useEffect } from "react"; -import { ChainItemType } from "../../types"; +import { ChainItemType, DisabledChainItemType } from "../../types"; import color from "../../styles/color"; import styled from "styled-components"; import { ChainItem } from "./chain-item"; interface Props { chainList: ChainItemType[]; - disabledChainList: ChainItemType[]; + disabledChainList: DisabledChainItemType[]; checkedItems: Set; setCheckedItems: Dispatch>>; } @@ -42,7 +42,6 @@ export const ChainList: FunctionComponent = (props) => { chainItem={chainItem} checkedItemHandler={checkedItemHandler} checkedItems={checkedItems} - disabled={true} /> ))} diff --git a/pages/verification/index.tsx b/pages/verification/index.tsx index 9ad1960..76e9275 100644 --- a/pages/verification/index.tsx +++ b/pages/verification/index.tsx @@ -6,6 +6,7 @@ import { useEffect, useState } from "react"; // Types import { ChainItemType, + DisabledChainItemType, QueryError, RegisteredAddresses, TwitterProfileType, @@ -70,12 +71,17 @@ export default function VerificationPage() { name: string; pubKey: Uint8Array; bech32Address: string; + isLedgerNano?: boolean; }>(); - const [chainList, setChainList] = useState([]); - const [disabledChainList, setDisabledChainList] = useState( - [], - ); + const [chainList, setChainList] = useState< + (ChainItemType & { + isEthermintLike?: boolean; + })[] + >([]); + const [disabledChainList, setDisabledChainList] = useState< + DisabledChainItemType[] + >([]); const [registeredChainList, setRegisteredChainList] = useState< RegisteredAddresses[] >([]); @@ -101,23 +107,51 @@ export default function VerificationPage() { }, [wallet]); useEffect(() => { - const disabledChainList = chainList.filter((chain) => { - for (const registeredChain of registeredChainList) { - if ( - chain.prefix === registeredChain.bech32_prefix && - chain.address === registeredChain.address - ) { + const disabledChainList = chainList + .filter((chain) => { + if (!chain.address) { + // Address can be "" if `getKey` failed. return true; } - } - return false; + for (const registeredChain of registeredChainList) { + if ( + chain.prefix === registeredChain.bech32_prefix && + chain.address === registeredChain.address + ) { + return true; + } + } + + return false; + }) + .map((chain) => { + if (walletKey) { + if (walletKey.isLedgerNano && chain.isEthermintLike) { + return { + ...chain, + disabled: true, + reason: new Error( + "Support for Ethereum address on Ledger is coming soon.", + ), + }; + } + } + + return { + ...chain, + disabled: true, + }; + }); + + const filteredChainList = chainList.filter((chain) => { + return ( + disabledChainList.find( + (disabled) => disabled.chainId === chain.chainId, + ) == null + ); }); - const filteredChainList = chainList.filter( - (chain) => !disabledChainList.includes(chain), - ); - setChainList(filteredChainList); setDisabledChainList(disabledChainList); @@ -200,7 +234,7 @@ export default function VerificationPage() { const chainIds = (await wallet.getChainInfosWithoutEndpoints()).map( (c) => c.chainId, ); - const chainKeys = await Promise.all( + const chainKeys = await Promise.allSettled( chainIds.map((chainId) => wallet.getKey(chainId)), ); @@ -213,14 +247,20 @@ export default function VerificationPage() { chainImageUrl: `https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/${ ChainIdHelper.parse(chainInfo.chainId).identifier }/chain.png`, + isEthermintLike: chainInfo.isEthermintLike, }; }, ); const chainArray = []; for (let i = 0; i < chainKeys.length; i++) { + const chainKey = chainKeys[i]; + if (chainKey.status !== "fulfilled") { + console.log("Failed to get key from wallet", chainKey); + } chainArray.push({ - address: chainKeys[i].bech32Address, + address: + chainKey.status === "fulfilled" ? chainKey.value.bech32Address : "", ...chainInfos[i], }); } @@ -267,8 +307,6 @@ export default function VerificationPage() { const onClickRegistration = () => { amplitude.track("click register button"); - console.log(isOwner); - if (isOwner) { handleRegistration(); } else { diff --git a/types/chain-item-type.ts b/types/chain-item-type.ts index 315b88a..18c8485 100644 --- a/types/chain-item-type.ts +++ b/types/chain-item-type.ts @@ -5,3 +5,10 @@ export interface ChainItemType { chainImageUrl: string; address: string; } + +export interface DisabledChainItemType extends ChainItemType { + disabled: true; + + // Show reason why this chain is disabled to user if needed. + reason?: Error; +}