diff --git a/components/dataViews/AccountView/ButtonConnectWallet.tsx b/components/dataViews/AccountView/ButtonConnectWallet.tsx index 9aad8f8..a1703b4 100644 --- a/components/dataViews/AccountView/ButtonConnectWallet.tsx +++ b/components/dataViews/AccountView/ButtonConnectWallet.tsx @@ -1,3 +1,4 @@ +import { getKeplrKey, useKeplrReconnect } from "@/lib/keplr"; import { cn, toastError } from "@/lib/utils"; import { LoadingStates, WalletInfo, WalletType } from "@/types/signing"; import { makeCosmoshubPath } from "@cosmjs/amino"; @@ -6,7 +7,7 @@ import { LedgerSigner } from "@cosmjs/ledger-amino"; import TransportWebUSB from "@ledgerhq/hw-transport-webusb"; import { Loader2, Unplug } from "lucide-react"; import Image from "next/image"; -import { Dispatch, SetStateAction, useCallback, useLayoutEffect, useState } from "react"; +import { Dispatch, SetStateAction, useCallback, useState } from "react"; import { useChains } from "../../../context/ChainsContext"; import { getConnectError } from "../../../lib/errorHelpers"; import { Button } from "../../ui/button"; @@ -30,16 +31,8 @@ export default function ButtonConnectWallet({ try { setLoading((oldLoading) => ({ ...oldLoading, keplr: true })); - await window.keplr.enable(chain.chainId); - window.keplr.defaultOptions = { - sign: { preferNoSetFee: true, preferNoSetMemo: true, disableBalanceCheck: true }, - }; - - const { bech32Address: address, pubKey: pubKeyArray } = await window.keplr.getKey( - chain.chainId, - ); + const { bech32Address: address, pubKey: pubKeyArray } = await getKeplrKey(chain.chainId); const pubKey = toBase64(pubKeyArray); - setWalletInfo({ type: "Keplr", address, pubKey }); } catch (e) { const connectError = getConnectError(e); @@ -53,19 +46,7 @@ export default function ButtonConnectWallet({ } }, [chain.chainId, setWalletInfo]); - useLayoutEffect(() => { - if (!walletInfo?.address) { - return; - } - - const accountChangeKey = "keplr_keystorechange"; - - if (walletInfo.type === "Keplr") { - window.addEventListener(accountChangeKey, connectKeplr); - } else { - window.removeEventListener(accountChangeKey, connectKeplr); - } - }, [connectKeplr, walletInfo]); + useKeplrReconnect(!!walletInfo?.address, connectKeplr); const connectLedger = async () => { try { diff --git a/components/dataViews/ListMultisigTxs.tsx b/components/dataViews/ListMultisigTxs.tsx index 9105cf1..a3397d9 100644 --- a/components/dataViews/ListMultisigTxs.tsx +++ b/components/dataViews/ListMultisigTxs.tsx @@ -1,6 +1,7 @@ import { useChains } from "@/context/ChainsContext"; import { ellideMiddle } from "@/lib/displayHelpers"; import { getConnectError } from "@/lib/errorHelpers"; +import { getKeplrKey, getKeplrVerifySignature, useKeplrReconnect } from "@/lib/keplr"; import { requestJson } from "@/lib/request"; import { msgTypeCountsFromJson } from "@/lib/txMsgHelpers"; import { cn, toastError } from "@/lib/utils"; @@ -11,7 +12,7 @@ import { StargateClient } from "@cosmjs/stargate"; import { Loader2, MoveRightIcon } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; -import { useCallback, useLayoutEffect, useState } from "react"; +import { useCallback, useState } from "react"; import { Badge } from "../ui/badge"; import { Button } from "../ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"; @@ -19,8 +20,6 @@ import { Label } from "../ui/label"; import { Switch } from "../ui/switch"; import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; -// Show pending default. Toggle con show already broadcasted too - interface ListMultisigTxsProps { readonly multisigAddress: string; readonly multisigThreshold: number; @@ -52,36 +51,10 @@ export default function ListMultisigTxs({ `/api/chain/${chain.chainId}/nonce/${accountOnChain.address}`, ); - const { signature } = await window.keplr.signAmino(chain.chainId, accountOnChain.address, { - chain_id: "", - account_number: "0", - sequence: "0", - fee: { gas: "0", amount: [] }, - msgs: [ - { - type: "sign/MsgSignData", - value: { - signer: accountOnChain.address, - data: toBase64( - new Uint8Array( - Buffer.from( - JSON.stringify({ - title: `Keplr Login to ${chain.chainDisplayName}`, - description: "Sign this no fee transaction to login with your Keplr wallet", - nonce, - }), - ), - ), - ), - }, - }, - ], - memo: "", - }); - + const signature = await getKeplrVerifySignature(accountOnChain.address, chain, nonce); return signature; }, - [chain.chainDisplayName, chain.chainId, chain.nodeAddress], + [chain], ); const fetchTransactions = useCallback( @@ -112,17 +85,8 @@ export default function ListMultisigTxs({ try { setLoading(true); - await window.keplr.enable(chain.chainId); - window.keplr.defaultOptions = { - sign: { preferNoSetFee: true, preferNoSetMemo: true, disableBalanceCheck: true }, - }; - - const { bech32Address: address, pubKey: pubKeyArray } = await window.keplr.getKey( - chain.chainId, - ); - + const { bech32Address: address, pubKey: pubKeyArray } = await getKeplrKey(chain.chainId); const pubKey = toBase64(pubKeyArray); - setWalletInfo({ address, pubKey }); await fetchTransactions(address); @@ -138,18 +102,7 @@ export default function ListMultisigTxs({ } }, [chain.chainId, fetchTransactions]); - useLayoutEffect(() => { - if (!walletInfo?.address) { - return; - } - - const accountChangeKey = "keplr_keystorechange"; - window.addEventListener(accountChangeKey, connectWallet); - - return () => { - window.removeEventListener(accountChangeKey, connectWallet); - }; - }, [connectWallet, walletInfo?.address]); + useKeplrReconnect(!!walletInfo?.address, connectWallet); return ( diff --git a/components/dataViews/ListUserMultisigs.tsx b/components/dataViews/ListUserMultisigs.tsx index 6d5073e..96267c2 100644 --- a/components/dataViews/ListUserMultisigs.tsx +++ b/components/dataViews/ListUserMultisigs.tsx @@ -1,6 +1,7 @@ import { useChains } from "@/context/ChainsContext"; import { getConnectError } from "@/lib/errorHelpers"; import { MultisigFromQuery } from "@/lib/graphqlHelpers"; +import { getKeplrKey, getKeplrVerifySignature, useKeplrReconnect } from "@/lib/keplr"; import { requestJson } from "@/lib/request"; import { toastError } from "@/lib/utils"; import { DbNonce } from "@/types/db"; @@ -11,7 +12,7 @@ import { StargateClient } from "@cosmjs/stargate"; import { Loader2, MoveRightIcon } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; -import { useCallback, useLayoutEffect, useState } from "react"; +import { useCallback, useState } from "react"; import { Badge } from "../ui/badge"; import { Button } from "../ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"; @@ -44,36 +45,10 @@ export default function ListUserMultisigs() { `/api/chain/${chain.chainId}/nonce/${accountOnChain.address}`, ); - const { signature } = await window.keplr.signAmino(chain.chainId, accountOnChain.address, { - chain_id: "", - account_number: "0", - sequence: "0", - fee: { gas: "0", amount: [] }, - msgs: [ - { - type: "sign/MsgSignData", - value: { - signer: accountOnChain.address, - data: toBase64( - new Uint8Array( - Buffer.from( - JSON.stringify({ - title: `Keplr Login to ${chain.chainDisplayName}`, - description: "Sign this no fee transaction to login with your Keplr wallet", - nonce, - }), - ), - ), - ), - }, - }, - ], - memo: "", - }); - + const signature = await getKeplrVerifySignature(accountOnChain.address, chain, nonce); return signature; }, - [chain.chainDisplayName, chain.chainId, chain.nodeAddress], + [chain], ); const fetchMultisigs = useCallback( @@ -104,17 +79,8 @@ export default function ListUserMultisigs() { try { setLoading(true); - await window.keplr.enable(chain.chainId); - window.keplr.defaultOptions = { - sign: { preferNoSetFee: true, preferNoSetMemo: true, disableBalanceCheck: true }, - }; - - const { bech32Address: address, pubKey: pubKeyArray } = await window.keplr.getKey( - chain.chainId, - ); - + const { bech32Address: address, pubKey: pubKeyArray } = await getKeplrKey(chain.chainId); const pubKey = toBase64(pubKeyArray); - setWalletInfo({ address, pubKey }); await fetchMultisigs(address); @@ -130,18 +96,7 @@ export default function ListUserMultisigs() { } }, [chain.chainId, fetchMultisigs]); - useLayoutEffect(() => { - if (!walletInfo?.address) { - return; - } - - const accountChangeKey = "keplr_keystorechange"; - window.addEventListener(accountChangeKey, connectWallet); - - return () => { - window.removeEventListener(accountChangeKey, connectWallet); - }; - }, [connectWallet, walletInfo?.address]); + useKeplrReconnect(!!walletInfo?.address, connectWallet); return ( diff --git a/components/dataViews/MultisigView/index.tsx b/components/dataViews/MultisigView/index.tsx index 2bb2695..7434a74 100644 --- a/components/dataViews/MultisigView/index.tsx +++ b/components/dataViews/MultisigView/index.tsx @@ -2,6 +2,7 @@ import { Alert, AlertDescription } from "@/components/ui/alert"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { isChainInfoFilled } from "@/context/ChainsContext/helpers"; import { checkAddress } from "@/lib/displayHelpers"; +import { getKeplrKey } from "@/lib/keplr"; import { HostedMultisig, createMultisigFromCompressedSecp256k1Pubkeys, @@ -44,12 +45,7 @@ export default function MultisigView() { "Pubkey on chain is not of type MultisigThreshold", ); - await window.keplr.enable(chain.chainId); - window.keplr.defaultOptions = { - sign: { preferNoSetFee: true, preferNoSetMemo: true, disableBalanceCheck: true }, - }; - - const { bech32Address: address } = await window.keplr.getKey(chain.chainId); + const { bech32Address: address } = await getKeplrKey(chain.chainId); await createMultisigFromCompressedSecp256k1Pubkeys( newHostedMultisig.accountOnChain.pubkey.value.pubkeys.map((p) => p.value), diff --git a/components/forms/CreateMultisigForm/index.tsx b/components/forms/CreateMultisigForm/index.tsx index 475e39d..44e3918 100644 --- a/components/forms/CreateMultisigForm/index.tsx +++ b/components/forms/CreateMultisigForm/index.tsx @@ -9,6 +9,7 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import { getKeplrKey } from "@/lib/keplr"; import { toastError } from "@/lib/utils"; import { StargateClient } from "@cosmjs/stargate"; import { zodResolver } from "@hookform/resolvers/zod"; @@ -91,12 +92,7 @@ export default function CreateMultisigForm() { ); try { - await window.keplr.enable(chain.chainId); - window.keplr.defaultOptions = { - sign: { preferNoSetFee: true, preferNoSetMemo: true, disableBalanceCheck: true }, - }; - - const { bech32Address: address } = await window.keplr.getKey(chain.chainId); + const { bech32Address: address } = await getKeplrKey(chain.chainId); const multisigAddress = await createMultisigFromCompressedSecp256k1Pubkeys( pubkeys, diff --git a/components/forms/TransactionSigning.tsx b/components/forms/TransactionSigning.tsx index 329cd1c..1f61bd2 100644 --- a/components/forms/TransactionSigning.tsx +++ b/components/forms/TransactionSigning.tsx @@ -1,3 +1,4 @@ +import { getKeplrAminoSigner, getKeplrKey, useKeplrReconnect } from "@/lib/keplr"; import { toastError, toastSuccess } from "@/lib/utils"; import { DbSignature, DbTransactionJsonObj } from "@/types/db"; import { LoadingStates, SigningStatus } from "@/types/signing"; @@ -13,13 +14,13 @@ import { defaultRegistryTypes, } from "@cosmjs/stargate"; import { assert } from "@cosmjs/utils"; +import { Key } from "@keplr-wallet/types"; import TransportWebUSB from "@ledgerhq/hw-transport-webusb"; -import { useCallback, useLayoutEffect, useState } from "react"; +import { useCallback, useState } from "react"; import { toast } from "sonner"; import { useChains } from "../../context/ChainsContext"; import { getConnectError } from "../../lib/errorHelpers"; import { requestJson } from "../../lib/request"; -import { DbSignature, DbTransactionJsonObj, WalletAccount } from "../../types"; import HashView from "../dataViews/HashView"; import Button from "../inputs/Button"; import StackableContainer from "../layout/StackableContainer"; @@ -36,7 +37,7 @@ const TransactionSigning = (props: TransactionSigningProps) => { const memberPubkeys = props.pubkey.value.pubkeys.map(({ value }) => value); const { chain } = useChains(); - const [walletAccount, setWalletAccount] = useState(); + const [walletAccount, setWalletAccount] = useState>(); const [signing, setSigning] = useState("not_signed"); const [walletType, setWalletType] = useState<"Keplr" | "Ledger">(); const [ledgerSigner, setLedgerSigner] = useState(null); @@ -46,17 +47,13 @@ const TransactionSigning = (props: TransactionSigningProps) => { try { setLoading((oldLoading) => ({ ...oldLoading, keplr: true })); - await window.keplr.enable(chain.chainId); - window.keplr.defaultOptions = { - sign: { preferNoSetFee: true, preferNoSetMemo: true, disableBalanceCheck: true }, - }; - const tempWalletAccount = await window.keplr.getKey(chain.chainId); - setWalletAccount(tempWalletAccount); + const newWalletAccount = await getKeplrKey(chain.chainId); + setWalletAccount(newWalletAccount); - const pubkey = toBase64(tempWalletAccount.pubKey); + const pubkey = toBase64(newWalletAccount.pubKey); const isMember = memberPubkeys.includes(pubkey); const hasSigned = isMember - ? props.signatures.some((sig) => sig.address === tempWalletAccount.bech32Address) + ? props.signatures.some((sig) => sig.address === newWalletAccount.bech32Address) : false; if (!isMember) { setSigning("not_a_member"); @@ -81,15 +78,7 @@ const TransactionSigning = (props: TransactionSigningProps) => { } }, [chain.chainId, memberPubkeys, props.signatures]); - useLayoutEffect(() => { - const accountChangeKey = "keplr_keystorechange"; - - if (walletType === "Keplr") { - window.addEventListener(accountChangeKey, connectKeplr); - } else { - window.removeEventListener(accountChangeKey, connectKeplr); - } - }, [connectKeplr, walletType]); + useKeplrReconnect(!!walletAccount?.address, connectKeplr); const connectLedger = async () => { try { @@ -104,7 +93,7 @@ const TransactionSigning = (props: TransactionSigningProps) => { prefix: chain.addressPrefix, }); const accounts = await offlineSigner.getAccounts(); - const tempWalletAccount: WalletAccount = { + const tempWalletAccount = { bech32Address: accounts[0].address, pubKey: accounts[0].pubkey, algo: accounts[0].algo, @@ -147,9 +136,7 @@ const TransactionSigning = (props: TransactionSigningProps) => { setLoading((newLoading) => ({ ...newLoading, signing: true })); const offlineSigner = - walletType === "Keplr" - ? window.keplr.getOfflineSignerOnlyAmino(chain.chainId) - : ledgerSigner; + walletType === "Keplr" ? await getKeplrAminoSigner(chain.chainId) : ledgerSigner; if (!offlineSigner) { throw new Error("Offline signer not found");