Add DisabledChainItemType type and prevent registration from ethermint chain with ledger

This commit is contained in:
Thunnini 2022-12-18 21:01:34 +09:00
parent 3de363af0f
commit 5d48012133
4 changed files with 84 additions and 28 deletions

View File

@ -1,4 +1,4 @@
import { ChainItemType } from "../../types"; import { ChainItemType, DisabledChainItemType } from "../../types";
import { FunctionComponent, useEffect, useState } from "react"; import { FunctionComponent, useEffect, useState } from "react";
import color from "../../styles/color"; import color from "../../styles/color";
@ -8,14 +8,14 @@ import { ChainImage } from "./chain-image";
import { Checkbox } from "../checkbox"; import { Checkbox } from "../checkbox";
interface Props { interface Props {
chainItem: ChainItemType; chainItem: ChainItemType | DisabledChainItemType;
checkedItemHandler: (chainItem: ChainItemType, isChecked: boolean) => void; checkedItemHandler: (chainItem: ChainItemType, isChecked: boolean) => void;
checkedItems: Set<unknown>; checkedItems: Set<unknown>;
disabled?: boolean;
} }
export const ChainItem: FunctionComponent<Props> = (props) => { export const ChainItem: FunctionComponent<Props> = (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 [checked, setChecked] = useState(!!disabled);
const checkHandler = () => { const checkHandler = () => {
@ -46,7 +46,12 @@ export const ChainItem: FunctionComponent<Props> = (props) => {
/> />
<ChainInfoContainer> <ChainInfoContainer>
<ChainName>{`.${chainItem.prefix}`}</ChainName> <ChainName>{`.${chainItem.prefix}`}</ChainName>
<WalletAddress>{chainItem.address}</WalletAddress> {chainItem.address ? (
<WalletAddress>{chainItem.address}</WalletAddress>
) : null}
{disabled && chainItem.reason ? (
<DisabledReason>{chainItem.reason.message}</DisabledReason>
) : null}
</ChainInfoContainer> </ChainInfoContainer>
<Flex1 /> <Flex1 />
@ -117,3 +122,10 @@ export const WalletAddress = styled.div`
color: ${color.grey["400"]}; color: ${color.grey["400"]};
`; `;
export const DisabledReason = styled.div`
color: ${color.grey["200"]};
font-weight: 500;
font-size: 14px;
line-height: 17px;
`;

View File

@ -1,12 +1,12 @@
import { Dispatch, FunctionComponent, SetStateAction, useEffect } from "react"; import { Dispatch, FunctionComponent, SetStateAction, useEffect } from "react";
import { ChainItemType } from "../../types"; import { ChainItemType, DisabledChainItemType } from "../../types";
import color from "../../styles/color"; import color from "../../styles/color";
import styled from "styled-components"; import styled from "styled-components";
import { ChainItem } from "./chain-item"; import { ChainItem } from "./chain-item";
interface Props { interface Props {
chainList: ChainItemType[]; chainList: ChainItemType[];
disabledChainList: ChainItemType[]; disabledChainList: DisabledChainItemType[];
checkedItems: Set<unknown>; checkedItems: Set<unknown>;
setCheckedItems: Dispatch<SetStateAction<Set<unknown>>>; setCheckedItems: Dispatch<SetStateAction<Set<unknown>>>;
} }
@ -42,7 +42,6 @@ export const ChainList: FunctionComponent<Props> = (props) => {
chainItem={chainItem} chainItem={chainItem}
checkedItemHandler={checkedItemHandler} checkedItemHandler={checkedItemHandler}
checkedItems={checkedItems} checkedItems={checkedItems}
disabled={true}
/> />
))} ))}
</ChainContainer> </ChainContainer>

View File

@ -6,6 +6,7 @@ import { useEffect, useState } from "react";
// Types // Types
import { import {
ChainItemType, ChainItemType,
DisabledChainItemType,
QueryError, QueryError,
RegisteredAddresses, RegisteredAddresses,
TwitterProfileType, TwitterProfileType,
@ -70,12 +71,17 @@ export default function VerificationPage() {
name: string; name: string;
pubKey: Uint8Array; pubKey: Uint8Array;
bech32Address: string; bech32Address: string;
isLedgerNano?: boolean;
}>(); }>();
const [chainList, setChainList] = useState<ChainItemType[]>([]); const [chainList, setChainList] = useState<
const [disabledChainList, setDisabledChainList] = useState<ChainItemType[]>( (ChainItemType & {
[], isEthermintLike?: boolean;
); })[]
>([]);
const [disabledChainList, setDisabledChainList] = useState<
DisabledChainItemType[]
>([]);
const [registeredChainList, setRegisteredChainList] = useState< const [registeredChainList, setRegisteredChainList] = useState<
RegisteredAddresses[] RegisteredAddresses[]
>([]); >([]);
@ -101,23 +107,51 @@ export default function VerificationPage() {
}, [wallet]); }, [wallet]);
useEffect(() => { useEffect(() => {
const disabledChainList = chainList.filter((chain) => { const disabledChainList = chainList
for (const registeredChain of registeredChainList) { .filter((chain) => {
if ( if (!chain.address) {
chain.prefix === registeredChain.bech32_prefix && // Address can be "" if `getKey` failed.
chain.address === registeredChain.address
) {
return true; return true;
} }
}
return false; for (const registeredChain of registeredChainList) {
if (
chain.prefix === registeredChain.bech32_prefix &&
chain.address === registeredChain.address
) {
return true;
}
}
return false;
})
.map<DisabledChainItemType>((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); setChainList(filteredChainList);
setDisabledChainList(disabledChainList); setDisabledChainList(disabledChainList);
@ -200,7 +234,7 @@ export default function VerificationPage() {
const chainIds = (await wallet.getChainInfosWithoutEndpoints()).map( const chainIds = (await wallet.getChainInfosWithoutEndpoints()).map(
(c) => c.chainId, (c) => c.chainId,
); );
const chainKeys = await Promise.all( const chainKeys = await Promise.allSettled(
chainIds.map((chainId) => wallet.getKey(chainId)), 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/${ chainImageUrl: `https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/${
ChainIdHelper.parse(chainInfo.chainId).identifier ChainIdHelper.parse(chainInfo.chainId).identifier
}/chain.png`, }/chain.png`,
isEthermintLike: chainInfo.isEthermintLike,
}; };
}, },
); );
const chainArray = []; const chainArray = [];
for (let i = 0; i < chainKeys.length; i++) { 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({ chainArray.push({
address: chainKeys[i].bech32Address, address:
chainKey.status === "fulfilled" ? chainKey.value.bech32Address : "",
...chainInfos[i], ...chainInfos[i],
}); });
} }
@ -267,8 +307,6 @@ export default function VerificationPage() {
const onClickRegistration = () => { const onClickRegistration = () => {
amplitude.track("click register button"); amplitude.track("click register button");
console.log(isOwner);
if (isOwner) { if (isOwner) {
handleRegistration(); handleRegistration();
} else { } else {

View File

@ -5,3 +5,10 @@ export interface ChainItemType {
chainImageUrl: string; chainImageUrl: string;
address: string; address: string;
} }
export interface DisabledChainItemType extends ChainItemType {
disabled: true;
// Show reason why this chain is disabled to user if needed.
reason?: Error;
}