From 37d51a70f4711ff32cb98c8584e50ee5f50cdf02 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 15 May 2023 14:40:20 +0200 Subject: [PATCH 01/30] Add Ledger Live connector Create a Ledger Live connector --- src/web3/connectors/index.ts | 1 + src/web3/connectors/ledger_live.ts | 90 ++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/web3/connectors/ledger_live.ts diff --git a/src/web3/connectors/index.ts b/src/web3/connectors/index.ts index 5d55574ec..45f3110f8 100644 --- a/src/web3/connectors/index.ts +++ b/src/web3/connectors/index.ts @@ -2,5 +2,6 @@ export * from "./taho" export * from "./metamask" export * from "./walletConnect" export * from "./coinbaseWallet" +export * from "./ledger_live" export { AbstractConnector } from "@web3-react/abstract-connector" export { UserRejectedRequestError } from "@web3-react/injected-connector" diff --git a/src/web3/connectors/ledger_live.ts b/src/web3/connectors/ledger_live.ts new file mode 100644 index 000000000..103edad51 --- /dev/null +++ b/src/web3/connectors/ledger_live.ts @@ -0,0 +1,90 @@ +import { IFrameEthereumProvider } from "@ledgerhq/iframe-provider" +import { AbstractConnector } from "@web3-react/abstract-connector" +import { AbstractConnectorArguments, ConnectorUpdate } from "@web3-react/types" +import { getEnvVariable, supportedChainId } from "../../utils/getEnvVariable" +import { + LedgerConnectKit, + SupportedProviders, + loadConnectKit, +} from "@ledgerhq/connect-kit-loader" +import { EnvVariable } from "../../enums" + +export class LedgerLiveConnector extends AbstractConnector { + private provider?: any + private connectKitPromise: Promise + + constructor(args: Required) { + super(args) + + this.handleNetworkChanged = this.handleNetworkChanged.bind(this) + this.handleChainChanged = this.handleChainChanged.bind(this) + this.handleAccountsChanged = this.handleAccountsChanged.bind(this) + this.handleClose = this.handleClose.bind(this) + + this.connectKitPromise = loadConnectKit() + } + + private handleNetworkChanged(networkId: string): void { + this.emitUpdate({ provider: this.provider, chainId: networkId }) + } + + private handleChainChanged(chainId: string): void { + this.emitUpdate({ chainId }) + } + + private handleAccountsChanged(accounts: string[]): void { + this.emitUpdate({ account: accounts.length === 0 ? null : accounts[0] }) + } + + private handleClose(): void { + this.emitDeactivate() + } + + public async activate(): Promise { + let account = "" + try { + const connectKit = await this.connectKitPromise + const checkSupportResult = connectKit.checkSupport({ + chainId: 1, + providerType: SupportedProviders.Ethereum, + rpc: { + [Number(supportedChainId)]: rpcUrl as string, + }, + }) + + this.provider = await connectKit.getProvider() + const accounts = await this.provider.request({ + method: "eth_requestAccounts", + }) + account = accounts[0] + } catch (err) { + console.log("Error: ", err) + } + + return { provider: this.provider, account } + } + + public async getProvider(): Promise { + return this.provider + } + + public async getChainId(): Promise { + return this.provider!.request({ method: "eth_chainId" }) + } + + public async getAccount(): Promise { + return this.provider!.request({ method: "eth_accounts" }).then( + (accounts: string[]): string => accounts[0] + ) + } + + public deactivate() { + this.provider = undefined + } +} +const rpcUrl = getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP) +const chainId = +supportedChainId + +export const ledgerLive = new LedgerLiveConnector({ + supportedChainIds: [chainId], +}) From 4da903222b9f27e152046b92e1593f3f4cedc254 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 15 May 2023 14:43:44 +0200 Subject: [PATCH 02/30] Add LedgerLive button to SelectWallet modal --- src/components/Modal/SelectWalletModal/index.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/Modal/SelectWalletModal/index.tsx b/src/components/Modal/SelectWalletModal/index.tsx index edff2c74b..829a0da84 100644 --- a/src/components/Modal/SelectWalletModal/index.tsx +++ b/src/components/Modal/SelectWalletModal/index.tsx @@ -38,6 +38,11 @@ const walletOptions: WalletOption[] = [ title: "Coinbase Wallet", icon: CoinbaseWallet, }, + { + id: WalletType.LedgerLive, + title: "Ledger Live", + icon: MetaMaskIcon, + }, ] const SelectWalletModal: FC = () => { From 42d139b712e1c95949c4090724f5b0ea58eea0cf Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 15 May 2023 15:06:45 +0200 Subject: [PATCH 03/30] Create ConnectLedgerLive component --- .../SelectWalletModal/ConnectLedgerLive.tsx | 55 +++++++++++++++++++ .../Modal/SelectWalletModal/index.tsx | 3 + 2 files changed, 58 insertions(+) create mode 100644 src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx diff --git a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx new file mode 100644 index 000000000..14e73de26 --- /dev/null +++ b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx @@ -0,0 +1,55 @@ +import { FC, useEffect } from "react" +import { MetaMaskIcon } from "../../../static/icons/MetaMask" +import { useWeb3React } from "@web3-react/core" +import { ledgerLive } from "../../../web3/connectors" +import { WalletConnectionModalBase } from "./components" +import { ConnectionError, WalletType } from "../../../enums" +import doesErrorInclude from "../../../web3/utils/doesErrorInclude" +import { useCapture } from "../../../hooks/posthog" +import { PosthogEvent } from "../../../types/posthog" + +const ConnectLedgerLive: FC<{ goBack: () => void; closeModal: () => void }> = ({ + goBack, + closeModal, +}) => { + const { activate, error } = useWeb3React() + + const connectionRejected = doesErrorInclude( + error, + ConnectionError.RejectedMetamaskConnection + ) + + const connector = ledgerLive + const walletType = WalletType.LedgerLive + const captureWalletConnected = useCapture(PosthogEvent.WalletConnected) + + const onError = (error: unknown) => { + console.log("error:", error) + } + useEffect(() => { + if (!connector) return + + captureWalletConnected({ walletType }) + activate(connector, onError) + closeModal() + }, [activate, connector, captureWalletConnected, walletType]) + + return ( + activate(ledgerLive) : undefined} + walletType={walletType} + > + ) +} + +export default ConnectLedgerLive diff --git a/src/components/Modal/SelectWalletModal/index.tsx b/src/components/Modal/SelectWalletModal/index.tsx index 829a0da84..63bc092c0 100644 --- a/src/components/Modal/SelectWalletModal/index.tsx +++ b/src/components/Modal/SelectWalletModal/index.tsx @@ -16,6 +16,7 @@ import { CoinbaseWallet } from "../../../static/icons/CoinbaseWallet" import { useModal } from "../../../hooks/useModal" import ModalCloseButton from "../ModalCloseButton" import ConnectTaho from "./ConnectTaho" +import ConnectLedgerLive from "./ConnectLedgerLive" const walletOptions: WalletOption[] = [ { @@ -99,6 +100,8 @@ const ConnectWallet: FC<{ return case WalletType.Coinbase: return + case WalletType.LedgerLive: + return default: return <> } From 27053bcfc45fb2351a6df777a7bca071c74c6018 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 15 May 2023 15:28:02 +0200 Subject: [PATCH 04/30] Fix typings in ledger_live connector and also remove unnecessary `IFrameEthereumProvider` import --- src/web3/connectors/ledger_live.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/web3/connectors/ledger_live.ts b/src/web3/connectors/ledger_live.ts index 103edad51..ee4e5e5bc 100644 --- a/src/web3/connectors/ledger_live.ts +++ b/src/web3/connectors/ledger_live.ts @@ -1,4 +1,3 @@ -import { IFrameEthereumProvider } from "@ledgerhq/iframe-provider" import { AbstractConnector } from "@web3-react/abstract-connector" import { AbstractConnectorArguments, ConnectorUpdate } from "@web3-react/types" import { getEnvVariable, supportedChainId } from "../../utils/getEnvVariable" @@ -6,11 +5,12 @@ import { LedgerConnectKit, SupportedProviders, loadConnectKit, + EthereumProvider, } from "@ledgerhq/connect-kit-loader" import { EnvVariable } from "../../enums" export class LedgerLiveConnector extends AbstractConnector { - private provider?: any + private provider?: EthereumProvider | undefined private connectKitPromise: Promise constructor(args: Required) { @@ -52,10 +52,10 @@ export class LedgerLiveConnector extends AbstractConnector { }, }) - this.provider = await connectKit.getProvider() - const accounts = await this.provider.request({ + this.provider = (await connectKit.getProvider()) as EthereumProvider + const accounts = (await this.provider.request({ method: "eth_requestAccounts", - }) + })) as string[] account = accounts[0] } catch (err) { console.log("Error: ", err) @@ -64,7 +64,7 @@ export class LedgerLiveConnector extends AbstractConnector { return { provider: this.provider, account } } - public async getProvider(): Promise { + public async getProvider(): Promise { return this.provider } @@ -73,9 +73,10 @@ export class LedgerLiveConnector extends AbstractConnector { } public async getAccount(): Promise { - return this.provider!.request({ method: "eth_accounts" }).then( - (accounts: string[]): string => accounts[0] - ) + const accounts = (await this.provider!.request({ + method: "eth_requestAccounts", + })) as string[] + return accounts[0] } public deactivate() { From 9b1eff261a8468a56e821bb2679843ce20284330 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 15 May 2023 15:31:52 +0200 Subject: [PATCH 05/30] Add `@ledgerhq/connect-kit-loader` package --- package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/package.json b/package.json index 6186bf880..f1fa1ed93 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@keep-network/tbtc": "development", "@keep-network/tbtc-v2": "development", "@keep-network/tbtc-v2.ts": "development", + "@ledgerhq/connect-kit-loader": "^1.0.2", "@ledgerhq/hw-app-eth": "^6.9.0", "@ledgerhq/hw-transport-u2f": "^5.36.0-deprecated", "@ledgerhq/hw-transport-webhid": "^6.7.0", diff --git a/yarn.lock b/yarn.lock index fdd4d66f3..0954d840b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3588,6 +3588,11 @@ "@summa-tx/relay-sol" "^2.0.2" openzeppelin-solidity "2.3.0" +"@ledgerhq/connect-kit-loader@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/connect-kit-loader/-/connect-kit-loader-1.0.2.tgz#8554e16943f86cc2a5f6348a14dfe6e5bd0c572a" + integrity sha512-TQ21IjcZOw/scqypaVFY3jHVqI7X7Hta3qN/us6FvTol3AY06UmrhhXGww0E9xHmAbdX241ddwXEiMBSQZFr9g== + "@ledgerhq/cryptoassets@^5.27.2", "@ledgerhq/cryptoassets@^5.53.0": version "5.53.0" resolved "https://registry.yarnpkg.com/@ledgerhq/cryptoassets/-/cryptoassets-5.53.0.tgz#11dcc93211960c6fd6620392e4dd91896aaabe58" From d2a1af98acaf6be297022e045645b08c852c5d97 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 15 May 2023 15:47:58 +0200 Subject: [PATCH 06/30] Add `LEDGER_LIVE` to `WalletType` enum --- src/enums/web3.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/enums/web3.ts b/src/enums/web3.ts index 5beebbbe1..c57da72a5 100644 --- a/src/enums/web3.ts +++ b/src/enums/web3.ts @@ -31,5 +31,6 @@ export enum WalletType { WalletConnect = "WALLET_CONNECT", Coinbase = "COINBASE", Trezor = "TREZOR", - Ledger = "Ledger", + Ledger = "LEDGER", + LedgerLive = "LEDGER_LIVE", } From f7be6fa06127637167cd9d449ce2c6bbf57b655e Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Wed, 17 May 2023 11:11:20 +0200 Subject: [PATCH 07/30] Add proper Ledger Live icon For both dark mode and light mode. --- .../SelectWalletModal/InitialSelection.tsx | 46 +++++++++++-------- .../Modal/SelectWalletModal/index.tsx | 36 +++++++++++---- src/static/icons/LedgerDark.tsx | 21 +++++++++ src/static/icons/LedgerLight.tsx | 21 +++++++++ src/types/wallet.ts | 5 +- 5 files changed, 99 insertions(+), 30 deletions(-) create mode 100644 src/static/icons/LedgerDark.tsx create mode 100644 src/static/icons/LedgerLight.tsx diff --git a/src/components/Modal/SelectWalletModal/InitialSelection.tsx b/src/components/Modal/SelectWalletModal/InitialSelection.tsx index 109a9d525..8436e43ad 100644 --- a/src/components/Modal/SelectWalletModal/InitialSelection.tsx +++ b/src/components/Modal/SelectWalletModal/InitialSelection.tsx @@ -4,40 +4,46 @@ import { Icon, Stack, StackDivider, + useColorMode, useColorModeValue, VStack, } from "@chakra-ui/react" import { BiRightArrowAlt } from "react-icons/all" import { H4 } from "@threshold-network/components" import { WalletOption } from "../../../types" -import { WalletType } from "../../../enums" +import { ColorMode, WalletType } from "../../../enums" const InitialWalletSelection: FC<{ walletOptions: WalletOption[] onSelect: (walletType: WalletType) => void }> = ({ walletOptions, onSelect }) => { + const { colorMode } = useColorMode() return ( }> - {walletOptions.map((opt) => ( - - ))} + + ) + })} ) } diff --git a/src/components/Modal/SelectWalletModal/index.tsx b/src/components/Modal/SelectWalletModal/index.tsx index 63bc092c0..2198c61b3 100644 --- a/src/components/Modal/SelectWalletModal/index.tsx +++ b/src/components/Modal/SelectWalletModal/index.tsx @@ -17,32 +17,50 @@ import { useModal } from "../../../hooks/useModal" import ModalCloseButton from "../ModalCloseButton" import ConnectTaho from "./ConnectTaho" import ConnectLedgerLive from "./ConnectLedgerLive" +import { Ledger } from "../../../static/icons/Ledger" +import { LedgerLight } from "../../../static/icons/LedgerLight" +import { LedgerDark } from "../../../static/icons/LedgerDark" const walletOptions: WalletOption[] = [ { id: WalletType.TAHO, title: "Taho", - icon: Taho, + icon: { + light: Taho, + dark: Taho, + }, }, { id: WalletType.Metamask, title: "MetaMask", - icon: MetaMaskIcon, + icon: { + light: MetaMaskIcon, + dark: MetaMaskIcon, + }, + }, + { + id: WalletType.LedgerLive, + title: "Ledger Live", + icon: { + light: LedgerLight, + dark: LedgerDark, + }, }, { id: WalletType.WalletConnect, title: "WalletConnect", - icon: WalletConnectIcon, + icon: { + light: WalletConnectIcon, + dark: WalletConnectIcon, + }, }, { id: WalletType.Coinbase, title: "Coinbase Wallet", - icon: CoinbaseWallet, - }, - { - id: WalletType.LedgerLive, - title: "Ledger Live", - icon: MetaMaskIcon, + icon: { + light: CoinbaseWallet, + dark: CoinbaseWallet, + }, }, ] diff --git a/src/static/icons/LedgerDark.tsx b/src/static/icons/LedgerDark.tsx new file mode 100644 index 000000000..ff038742d --- /dev/null +++ b/src/static/icons/LedgerDark.tsx @@ -0,0 +1,21 @@ +import { createIcon } from "@chakra-ui/icons" + +export const LedgerDark = createIcon({ + displayName: "Ledger", + viewBox: "0 0 160 160", + path: ( + + + + + ), +}) diff --git a/src/static/icons/LedgerLight.tsx b/src/static/icons/LedgerLight.tsx new file mode 100644 index 000000000..b02aef425 --- /dev/null +++ b/src/static/icons/LedgerLight.tsx @@ -0,0 +1,21 @@ +import { createIcon } from "@chakra-ui/icons" + +export const LedgerLight = createIcon({ + displayName: "Ledger", + viewBox: "0 0 160 160", + path: ( + + + + + ), +}) diff --git a/src/types/wallet.ts b/src/types/wallet.ts index 2540d8d86..857d9754b 100644 --- a/src/types/wallet.ts +++ b/src/types/wallet.ts @@ -8,6 +8,9 @@ export interface WalletConnectionModalProps { export interface WalletOption { id: WalletType - icon: FC title: string + icon: { + light: FC + dark: FC + } } From 131ab84456d1af5832d401c744cb4c59df4d7262 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Wed, 17 May 2023 11:18:29 +0200 Subject: [PATCH 08/30] Add listeners to the provider Adds four listeners to the ledger live procider: - networkChanged - chainChanged - accountsChanged - close Also removes them in `deactivate` method. --- src/web3/connectors/ledger_live.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/web3/connectors/ledger_live.ts b/src/web3/connectors/ledger_live.ts index ee4e5e5bc..3981c507d 100644 --- a/src/web3/connectors/ledger_live.ts +++ b/src/web3/connectors/ledger_live.ts @@ -53,6 +53,12 @@ export class LedgerLiveConnector extends AbstractConnector { }) this.provider = (await connectKit.getProvider()) as EthereumProvider + + this.provider.on("networkChanged", this.handleNetworkChanged) + this.provider.on("chainChanged", this.handleChainChanged) + this.provider.on("accountsChanged", this.handleAccountsChanged) + this.provider.on("close", this.handleClose) + const accounts = (await this.provider.request({ method: "eth_requestAccounts", })) as string[] @@ -80,6 +86,10 @@ export class LedgerLiveConnector extends AbstractConnector { } public deactivate() { + this.provider!.removeListener("networkChanged", this.handleNetworkChanged) + this.provider!.removeListener("chainChanged", this.handleChainChanged) + this.provider!.removeListener("accountsChanged", this.handleAccountsChanged) + this.provider!.removeListener("close", this.handleClose) this.provider = undefined } } From 740de82d5379bbd59aea01e515d60c22b63d69c0 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Wed, 17 May 2023 12:33:52 +0200 Subject: [PATCH 09/30] Fix error then disconnectin the Ledger wallet. There was an error which happened after clicking `Disconnect` while being connected with a Ledger wallet. To fix that we simply remove the `this.provider = undefined` line form the `deactivate` method as it is not necessary. --- src/web3/connectors/ledger_live.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/web3/connectors/ledger_live.ts b/src/web3/connectors/ledger_live.ts index 3981c507d..bb29d27b8 100644 --- a/src/web3/connectors/ledger_live.ts +++ b/src/web3/connectors/ledger_live.ts @@ -90,7 +90,6 @@ export class LedgerLiveConnector extends AbstractConnector { this.provider!.removeListener("chainChanged", this.handleChainChanged) this.provider!.removeListener("accountsChanged", this.handleAccountsChanged) this.provider!.removeListener("close", this.handleClose) - this.provider = undefined } } const rpcUrl = getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP) From d7ed01be79acc3b97caf66f23d64b0c094662b71 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Thu, 25 May 2023 23:35:28 +0200 Subject: [PATCH 10/30] Change console.log to console.error --- src/web3/connectors/ledger_live.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web3/connectors/ledger_live.ts b/src/web3/connectors/ledger_live.ts index bb29d27b8..7564eba4d 100644 --- a/src/web3/connectors/ledger_live.ts +++ b/src/web3/connectors/ledger_live.ts @@ -64,7 +64,7 @@ export class LedgerLiveConnector extends AbstractConnector { })) as string[] account = accounts[0] } catch (err) { - console.log("Error: ", err) + console.error("Error: ", err) } return { provider: this.provider, account } From 869f9ac7f75166072a6e86c6564a2fe7fa133d9a Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Thu, 25 May 2023 23:36:58 +0200 Subject: [PATCH 11/30] Add empty line --- src/web3/connectors/ledger_live.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/web3/connectors/ledger_live.ts b/src/web3/connectors/ledger_live.ts index 7564eba4d..210bdbc9e 100644 --- a/src/web3/connectors/ledger_live.ts +++ b/src/web3/connectors/ledger_live.ts @@ -92,6 +92,7 @@ export class LedgerLiveConnector extends AbstractConnector { this.provider!.removeListener("close", this.handleClose) } } + const rpcUrl = getEnvVariable(EnvVariable.ETH_HOSTNAME_HTTP) const chainId = +supportedChainId From f936566d121aeabbe7ec3e3e6954bc52e95760d5 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Tue, 30 May 2023 13:51:46 +0200 Subject: [PATCH 12/30] Remove duplicated code We call `activate` method in the `WalletConnectionModalBase` already. --- .../Modal/SelectWalletModal/ConnectLedgerLive.tsx | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx index 14e73de26..c801cb5bd 100644 --- a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx +++ b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx @@ -19,20 +19,7 @@ const ConnectLedgerLive: FC<{ goBack: () => void; closeModal: () => void }> = ({ ConnectionError.RejectedMetamaskConnection ) - const connector = ledgerLive const walletType = WalletType.LedgerLive - const captureWalletConnected = useCapture(PosthogEvent.WalletConnected) - - const onError = (error: unknown) => { - console.log("error:", error) - } - useEffect(() => { - if (!connector) return - - captureWalletConnected({ walletType }) - activate(connector, onError) - closeModal() - }, [activate, connector, captureWalletConnected, walletType]) return ( Date: Tue, 30 May 2023 14:47:57 +0200 Subject: [PATCH 13/30] Use correct Ledger Live icon --- .../SelectWalletModal/ConnectLedgerLive.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx index c801cb5bd..f9cee94b8 100644 --- a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx +++ b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx @@ -1,32 +1,33 @@ -import { FC, useEffect } from "react" -import { MetaMaskIcon } from "../../../static/icons/MetaMask" +import { FC } from "react" import { useWeb3React } from "@web3-react/core" import { ledgerLive } from "../../../web3/connectors" import { WalletConnectionModalBase } from "./components" -import { ConnectionError, WalletType } from "../../../enums" +import { ColorMode, ConnectionError, WalletType } from "../../../enums" import doesErrorInclude from "../../../web3/utils/doesErrorInclude" -import { useCapture } from "../../../hooks/posthog" -import { PosthogEvent } from "../../../types/posthog" +import { LedgerLight } from "../../../static/icons/LedgerLight" +import { LedgerDark } from "../../../static/icons/LedgerDark" +import { useColorMode } from "@chakra-ui/react" const ConnectLedgerLive: FC<{ goBack: () => void; closeModal: () => void }> = ({ goBack, closeModal, }) => { const { activate, error } = useWeb3React() + const { colorMode } = useColorMode() const connectionRejected = doesErrorInclude( error, ConnectionError.RejectedMetamaskConnection ) - const walletType = WalletType.LedgerLive + const walletIcon = colorMode === ColorMode.DARK ? LedgerDark : LedgerLight return ( void; closeModal: () => void }> = ({ : "" } tryAgain={connectionRejected ? () => activate(ledgerLive) : undefined} - walletType={walletType} - > + walletType={WalletType.LedgerLive} + /> ) } From 1149fa54a07584eab2a579a330a788fd75e5cb3b Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Tue, 30 May 2023 15:00:31 +0200 Subject: [PATCH 14/30] Rename ledger_live connector ledger_live -> ledgerLive --- src/web3/connectors/index.ts | 2 +- src/web3/connectors/{ledger_live.ts => ledgerLive.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/web3/connectors/{ledger_live.ts => ledgerLive.ts} (100%) diff --git a/src/web3/connectors/index.ts b/src/web3/connectors/index.ts index 45f3110f8..880fcef65 100644 --- a/src/web3/connectors/index.ts +++ b/src/web3/connectors/index.ts @@ -2,6 +2,6 @@ export * from "./taho" export * from "./metamask" export * from "./walletConnect" export * from "./coinbaseWallet" -export * from "./ledger_live" +export * from "./ledgerLive" export { AbstractConnector } from "@web3-react/abstract-connector" export { UserRejectedRequestError } from "@web3-react/injected-connector" diff --git a/src/web3/connectors/ledger_live.ts b/src/web3/connectors/ledgerLive.ts similarity index 100% rename from src/web3/connectors/ledger_live.ts rename to src/web3/connectors/ledgerLive.ts From f1fac17e00109a99c9f1e0ae0d3b182c0a9ce89c Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Tue, 30 May 2023 15:03:23 +0200 Subject: [PATCH 15/30] Remove unnecessary undefined. The `provider` is already marked as `optional` so we don't have to type it as possibly undefined. --- src/web3/connectors/ledgerLive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index 210bdbc9e..c40204697 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -10,7 +10,7 @@ import { import { EnvVariable } from "../../enums" export class LedgerLiveConnector extends AbstractConnector { - private provider?: EthereumProvider | undefined + private provider?: EthereumProvider private connectKitPromise: Promise constructor(args: Required) { From 36b076710c416257a01537cf3ec3c3e6251e1a95 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Tue, 30 May 2023 15:29:25 +0200 Subject: [PATCH 16/30] Create `ConnectorNotAcivatedError` error --- src/web3/connectors/ledgerLive.ts | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index c40204697..06cc2ee1e 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -75,21 +75,27 @@ export class LedgerLiveConnector extends AbstractConnector { } public async getChainId(): Promise { - return this.provider!.request({ method: "eth_chainId" }) + if (!this.provider) throw new ConnectorNotAcivatedError() + + return this.provider.request({ method: "eth_chainId" }) } public async getAccount(): Promise { - const accounts = (await this.provider!.request({ + if (!this.provider) throw new ConnectorNotAcivatedError() + + const accounts = (await this.provider.request({ method: "eth_requestAccounts", })) as string[] return accounts[0] } public deactivate() { - this.provider!.removeListener("networkChanged", this.handleNetworkChanged) - this.provider!.removeListener("chainChanged", this.handleChainChanged) - this.provider!.removeListener("accountsChanged", this.handleAccountsChanged) - this.provider!.removeListener("close", this.handleClose) + if (!this.provider) throw new ConnectorNotAcivatedError() + + this.provider.removeListener("networkChanged", this.handleNetworkChanged) + this.provider.removeListener("chainChanged", this.handleChainChanged) + this.provider.removeListener("accountsChanged", this.handleAccountsChanged) + this.provider.removeListener("close", this.handleClose) } } @@ -99,3 +105,9 @@ const chainId = +supportedChainId export const ledgerLive = new LedgerLiveConnector({ supportedChainIds: [chainId], }) + +class ConnectorNotAcivatedError extends Error { + constructor() { + super("Connector not activated!") + } +} From 6ccab86701ef66a85e347b0b18578795ca4911bc Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 5 Jun 2023 14:38:19 +0200 Subject: [PATCH 17/30] Close walletconnection modal for LedgerLive We should close Wallet Connection modal when activating the provider of LedgerLive, because it will open it's own modal. --- .../SelectWalletModal/components/WalletConnectionModalBase.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx b/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx index 98e702ab0..5b7ca7268 100644 --- a/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx +++ b/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx @@ -48,6 +48,7 @@ const WalletConnectionModalBase: FC = ({ captureWalletConnected({ walletType }) activate(connector) + if (walletType === WalletType.LedgerLive) closeModal() }, [activate, connector, captureWalletConnected, walletType]) return ( From 225800e31c6d025dfbd9ab7a2a58c137881af6e8 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Tue, 6 Jun 2023 15:23:48 +0200 Subject: [PATCH 18/30] Pass rpc to contructor of ledger Live --- src/web3/connectors/ledgerLive.ts | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index 06cc2ee1e..0fb717774 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -9,12 +9,25 @@ import { } from "@ledgerhq/connect-kit-loader" import { EnvVariable } from "../../enums" +interface LedgerLiveConnectorArguments extends AbstractConnectorArguments { + rpc: { + [chainId: number]: string + } +} + export class LedgerLiveConnector extends AbstractConnector { + private rpc: LedgerLiveConnectorArguments["rpc"] private provider?: EthereumProvider private connectKitPromise: Promise - constructor(args: Required) { - super(args) + constructor(args: Required) { + super({ + supportedChainIds: Object.keys(args.rpc).map((chainId) => + Number(chainId) + ), + }) + + this.rpc = args.rpc this.handleNetworkChanged = this.handleNetworkChanged.bind(this) this.handleChainChanged = this.handleChainChanged.bind(this) @@ -44,12 +57,11 @@ export class LedgerLiveConnector extends AbstractConnector { let account = "" try { const connectKit = await this.connectKitPromise + const chainId = Number(Object.keys(this.rpc)[0]) const checkSupportResult = connectKit.checkSupport({ - chainId: 1, + chainId: chainId, providerType: SupportedProviders.Ethereum, - rpc: { - [Number(supportedChainId)]: rpcUrl as string, - }, + rpc: this.rpc, }) this.provider = (await connectKit.getProvider()) as EthereumProvider @@ -104,6 +116,9 @@ const chainId = +supportedChainId export const ledgerLive = new LedgerLiveConnector({ supportedChainIds: [chainId], + rpc: { + [Number(supportedChainId)]: rpcUrl as string, + }, }) class ConnectorNotAcivatedError extends Error { From 6f909fc347516f499388768651d9435b2e111d2d Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Thu, 8 Jun 2023 21:34:49 +0200 Subject: [PATCH 19/30] Use `useColorModeValue` hook --- src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx index f9cee94b8..3e2af1581 100644 --- a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx +++ b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx @@ -6,21 +6,20 @@ import { ColorMode, ConnectionError, WalletType } from "../../../enums" import doesErrorInclude from "../../../web3/utils/doesErrorInclude" import { LedgerLight } from "../../../static/icons/LedgerLight" import { LedgerDark } from "../../../static/icons/LedgerDark" -import { useColorMode } from "@chakra-ui/react" +import { useColorModeValue } from "@threshold-network/components" const ConnectLedgerLive: FC<{ goBack: () => void; closeModal: () => void }> = ({ goBack, closeModal, }) => { const { activate, error } = useWeb3React() - const { colorMode } = useColorMode() const connectionRejected = doesErrorInclude( error, ConnectionError.RejectedMetamaskConnection ) - const walletIcon = colorMode === ColorMode.DARK ? LedgerDark : LedgerLight + const walletIcon = useColorModeValue(LedgerLight, LedgerDark) return ( Date: Mon, 12 Jun 2023 11:38:22 +0200 Subject: [PATCH 20/30] Add alert for unsupported network Here we are adding the alert for unsupported networks when connecting to LedgerLive. For this I had to remove the try catch block from `activate` method so that the error can be catched outside of the ledger connection in `WalletConnectionModalBase`. We pass the `onError` method to the `activate` method as a second argument and this way we can set the `web3React` error which then is read by our `WalletConnectionAlert` component. --- .../components/WalletConnectionModalBase.tsx | 8 ++- .../Navbar/WalletConnectionAlert.tsx | 32 +++++++----- src/web3/connectors/ledgerLive.ts | 49 ++++++++++--------- 3 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx b/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx index dec20e3d7..52b45e538 100644 --- a/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx +++ b/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx @@ -41,14 +41,18 @@ const WalletConnectionModalBase: FC = ({ connector, walletType, }) => { - const { activate, active, account } = useWeb3React() + const { activate, active, account, setError } = useWeb3React() const captureWalletConnected = useCapture(PosthogEvent.WalletConnected) + const onError = (error: Error) => { + setError(error) + } + useEffect(() => { if (!connector) return captureWalletConnected({ walletType }) - activate(connector) + activate(connector, onError) if (walletType === WalletType.LedgerLive) closeModal() }, [activate, connector, captureWalletConnected, walletType]) diff --git a/src/components/Navbar/WalletConnectionAlert.tsx b/src/components/Navbar/WalletConnectionAlert.tsx index 4827c05ac..51fc2dfb4 100644 --- a/src/components/Navbar/WalletConnectionAlert.tsx +++ b/src/components/Navbar/WalletConnectionAlert.tsx @@ -4,41 +4,47 @@ import { AlertIcon, CloseButton, } from "@chakra-ui/react" -import { FC, useEffect, useMemo, useState } from "react" +import { FC, useEffect, useState } from "react" import isSupportedNetwork from "../../utils/isSupportedNetwork" import chainIdToNetworkName from "../../utils/chainIdToNetworkName" import { supportedChainId } from "../../utils/getEnvVariable" +import { useWeb3React } from "@web3-react/core" const WalletConnectionAlert: FC<{ account?: string | null chainId?: number }> = ({ account, chainId }) => { const [hideAlert, setHideAlert] = useState(false) + const { error } = useWeb3React() + const [alertDescription, setAlertDescription] = useState("") - const alertDescription = useMemo(() => { - if (!account) { + useEffect(() => { + if (error) { + setAlertDescription(error.message) setHideAlert(false) return } - if (!isSupportedNetwork(chainId)) { - return `Your wallet is on an unsupported network. Switch to the ${chainIdToNetworkName( - supportedChainId - )} network` - } - }, [account, chainId]) - - useEffect(() => { if (!account || (account && isSupportedNetwork(chainId))) { setHideAlert(true) return } if (!isSupportedNetwork(chainId)) { + setAlertDescription( + `Your wallet is on an unsupported network. Switch to the ${chainIdToNetworkName( + supportedChainId + )} network` + ) setHideAlert(false) return } - }, [account, chainId]) + }, [account, chainId, error?.message]) + + const resetAlert = () => { + setHideAlert(true) + setAlertDescription("") + } if (hideAlert) { return null @@ -60,7 +66,7 @@ const WalletConnectionAlert: FC<{ position="absolute" right="8px" top="8px" - onClick={() => setHideAlert(true)} + onClick={resetAlert} /> ) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index 0fb717774..c196690cb 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -8,6 +8,7 @@ import { EthereumProvider, } from "@ledgerhq/connect-kit-loader" import { EnvVariable } from "../../enums" +import chainIdToNetworkName from "../../utils/chainIdToNetworkName" interface LedgerLiveConnectorArguments extends AbstractConnectorArguments { rpc: { @@ -55,30 +56,34 @@ export class LedgerLiveConnector extends AbstractConnector { public async activate(): Promise { let account = "" - try { - const connectKit = await this.connectKitPromise - const chainId = Number(Object.keys(this.rpc)[0]) - const checkSupportResult = connectKit.checkSupport({ - chainId: chainId, - providerType: SupportedProviders.Ethereum, - rpc: this.rpc, - }) - - this.provider = (await connectKit.getProvider()) as EthereumProvider - - this.provider.on("networkChanged", this.handleNetworkChanged) - this.provider.on("chainChanged", this.handleChainChanged) - this.provider.on("accountsChanged", this.handleAccountsChanged) - this.provider.on("close", this.handleClose) - - const accounts = (await this.provider.request({ - method: "eth_requestAccounts", - })) as string[] - account = accounts[0] - } catch (err) { - console.error("Error: ", err) + const connectKit = await this.connectKitPromise + const chainId = Number(Object.keys(this.rpc)[0]) + const checkSupportResult = connectKit.checkSupport({ + chainId: chainId, + providerType: SupportedProviders.Ethereum, + rpc: this.rpc, + }) + + if (!checkSupportResult.isChainIdSupported) { + throw new Error( + `The ${chainIdToNetworkName( + chainId + )} network is not supported for LedgerLive.` + ) } + this.provider = (await connectKit.getProvider()) as EthereumProvider + + this.provider.on("networkChanged", this.handleNetworkChanged) + this.provider.on("chainChanged", this.handleChainChanged) + this.provider.on("accountsChanged", this.handleAccountsChanged) + this.provider.on("close", this.handleClose) + + const accounts = (await this.provider.request({ + method: "eth_requestAccounts", + })) as string[] + account = accounts[0] + return { provider: this.provider, account } } From df848ca7d01d200832cf98081bb55d40d24f0813 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 24 Jul 2023 10:08:19 +0200 Subject: [PATCH 21/30] Update @ledgerhq/connect-kit-loader lib Update `@ledgerhq/connect-kit-loader` lib to `1.1.0`. This will add support to connecting ledger live using wallet connect v2. --- package.json | 2 +- yarn.lock | 22 ++++++---------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index dd26a9ad2..9399c8f50 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@keep-network/tbtc": "development", "@keep-network/tbtc-v2": "development", "@keep-network/tbtc-v2.ts": "development", - "@ledgerhq/connect-kit-loader": "^1.0.2", + "@ledgerhq/connect-kit-loader": "^1.1.0", "@reduxjs/toolkit": "^1.6.1", "@rehooks/local-storage": "^2.4.4", "@sentry/react": "^7.33.0", diff --git a/yarn.lock b/yarn.lock index db6d8c4c7..a09fc9e9b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3245,10 +3245,10 @@ "@summa-tx/relay-sol" "^2.0.2" openzeppelin-solidity "2.3.0" -"@ledgerhq/connect-kit-loader@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@ledgerhq/connect-kit-loader/-/connect-kit-loader-1.0.2.tgz#8554e16943f86cc2a5f6348a14dfe6e5bd0c572a" - integrity sha512-TQ21IjcZOw/scqypaVFY3jHVqI7X7Hta3qN/us6FvTol3AY06UmrhhXGww0E9xHmAbdX241ddwXEiMBSQZFr9g== +"@ledgerhq/connect-kit-loader@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/connect-kit-loader/-/connect-kit-loader-1.1.0.tgz#10343b78ef13436818bf3453568a559c0eeb9d48" + integrity sha512-HUy12FEczoWY2FPubnsm1uOA8tkVWc0j90i47suThV3C9NL2xx69ZAIEU3Ytzs2bwLek9S1Q2S1VQJvA+3Ygkg== "@ledgerhq/cryptoassets@^5.53.0": version "5.53.0" @@ -6678,15 +6678,10 @@ bufio@^1.0.6: resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.0.tgz#b9ad1c06b0d9010363c387c39d2810a7086d143f" integrity sha512-UlFk8z/PwdhYQTXSQQagwGAdtRI83gib2n4uy4rQnenxUM2yQi8lBDzF230BNk+3wAoZDxYRoBwVVUPgHa9MCA== -"bufio@git+https://github.com/bcoin-org/bufio.git#semver:~1.0.6": +"bufio@git+https://github.com/bcoin-org/bufio.git#semver:~1.0.6", bufio@~1.0.7: version "1.0.7" resolved "git+https://github.com/bcoin-org/bufio.git#91ae6c93899ff9fad7d7cee9afd2a1c4933ca984" -bufio@~1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.0.7.tgz#b7f63a1369a0829ed64cc14edf0573b3e382a33e" - integrity sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A== - builtin-modules@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -12713,15 +12708,10 @@ loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" -"loady@git+https://github.com/chjj/loady.git#semver:~0.0.1": +"loady@git+https://github.com/chjj/loady.git#semver:~0.0.1", loady@~0.0.1, loady@~0.0.5: version "0.0.5" resolved "git+https://github.com/chjj/loady.git#b94958b7ee061518f4b85ea6da380e7ee93222d5" -loady@~0.0.1, loady@~0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/loady/-/loady-0.0.5.tgz#b17adb52d2fb7e743f107b0928ba0b591da5d881" - integrity sha512-uxKD2HIj042/HBx77NBcmEPsD+hxCgAtjEWlYNScuUjIsh/62Uyu39GOR68TBR68v+jqDL9zfftCWoUo4y03sQ== - locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" From 66224b1139e80a2e77087aa6a0b0f1131c655def Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 24 Jul 2023 11:00:09 +0200 Subject: [PATCH 22/30] Adjust `checkSupport` method for new lib version Adjust `connectKit.checkSupport` method for the new version of `@ledgerhq/connect-kit-loader`. --- src/web3/connectors/ledgerLive.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index c196690cb..ddad39ebe 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -59,9 +59,11 @@ export class LedgerLiveConnector extends AbstractConnector { const connectKit = await this.connectKitPromise const chainId = Number(Object.keys(this.rpc)[0]) const checkSupportResult = connectKit.checkSupport({ - chainId: chainId, + chains: [chainId], + walletConnectVersion: 2, + projectId: getEnvVariable(EnvVariable.WALLET_CONNECT_PROJECT_ID), providerType: SupportedProviders.Ethereum, - rpc: this.rpc, + rpcMap: this.rpc, }) if (!checkSupportResult.isChainIdSupported) { From aaacbe72b73ae0c398073fb2e0510a19f91ff0f4 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 24 Jul 2023 11:09:44 +0200 Subject: [PATCH 23/30] Make code more readable --- src/web3/connectors/ledgerLive.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index ddad39ebe..7d465be97 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -55,9 +55,12 @@ export class LedgerLiveConnector extends AbstractConnector { } public async activate(): Promise { + if (!this.supportedChainIds) { + throw new Error("Supported chain ids are not defined.") + } let account = "" const connectKit = await this.connectKitPromise - const chainId = Number(Object.keys(this.rpc)[0]) + const chainId = this.supportedChainIds[0] const checkSupportResult = connectKit.checkSupport({ chains: [chainId], walletConnectVersion: 2, From ab114c9d6dc19abb851a8c6d6dfa2864025ccdc4 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 24 Jul 2023 11:17:38 +0200 Subject: [PATCH 24/30] Simplify wallet connection aler useEffect --- src/components/Navbar/WalletConnectionAlert.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Navbar/WalletConnectionAlert.tsx b/src/components/Navbar/WalletConnectionAlert.tsx index 51fc2dfb4..24d986e89 100644 --- a/src/components/Navbar/WalletConnectionAlert.tsx +++ b/src/components/Navbar/WalletConnectionAlert.tsx @@ -18,9 +18,11 @@ const WalletConnectionAlert: FC<{ const { error } = useWeb3React() const [alertDescription, setAlertDescription] = useState("") + const errorMessage = error?.message + useEffect(() => { - if (error) { - setAlertDescription(error.message) + if (errorMessage) { + setAlertDescription(errorMessage) setHideAlert(false) return } @@ -39,7 +41,7 @@ const WalletConnectionAlert: FC<{ setHideAlert(false) return } - }, [account, chainId, error?.message]) + }, [account, chainId, errorMessage]) const resetAlert = () => { setHideAlert(true) From 3bf7da1abd1cd138898389f7066e344f83c76e32 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Tue, 25 Jul 2023 22:21:45 +0200 Subject: [PATCH 25/30] Add `shouldForceCloseModal` property Adds `shouldForceCloseModal` property to `WalletConnectionModalBase` component. --- .../Modal/SelectWalletModal/ConnectLedgerLive.tsx | 1 + .../SelectWalletModal/ConnectWalletConnect.tsx | 1 + .../components/WalletConnectionModalBase.tsx | 15 ++++++++++----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx index 4549ec69e..87c055205 100644 --- a/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx +++ b/src/components/Modal/SelectWalletModal/ConnectLedgerLive.tsx @@ -35,6 +35,7 @@ const ConnectLedgerLive: FC<{ goBack: () => void; closeModal: () => void }> = ({ } tryAgain={connectionRejected ? () => activate(ledgerLive) : undefined} walletType={WalletType.LedgerLive} + shouldForceCloseModal /> ) } diff --git a/src/components/Modal/SelectWalletModal/ConnectWalletConnect.tsx b/src/components/Modal/SelectWalletModal/ConnectWalletConnect.tsx index 3f689645c..22edd6c52 100644 --- a/src/components/Modal/SelectWalletModal/ConnectWalletConnect.tsx +++ b/src/components/Modal/SelectWalletModal/ConnectWalletConnect.tsx @@ -36,6 +36,7 @@ const ConnectWalletConnect: FC<{ activate(walletConnect) }} walletType={WalletType.WalletConnect} + shouldForceCloseModal > void connector?: AbstractConnector walletType: WalletType + /** + * This is required for some of the providers (for example WalletConnect v2), + * because they have their own modal that is being opened. In that case we + * can't display our loading modal because it has larger z-index than + * provider's one and it's too problematic to change that. + * + */ + shouldForceCloseModal?: boolean } const WalletConnectionModalBase: FC = ({ @@ -40,6 +48,7 @@ const WalletConnectionModalBase: FC = ({ onContinue, connector, walletType, + shouldForceCloseModal, }) => { const { activate, active, account } = useWeb3React() const captureWalletConnected = useCapture(PosthogEvent.WalletConnected) @@ -49,11 +58,7 @@ const WalletConnectionModalBase: FC = ({ captureWalletConnected({ walletType }) activate(connector) - if ( - walletType === WalletType.LedgerLive || - walletType === WalletType.WalletConnect - ) - closeModal() + if (shouldForceCloseModal) closeModal() }, [activate, connector, captureWalletConnected, walletType]) return ( From 98a6086b27adae48a99887e52bf4cbbf92e645e3 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Wed, 26 Jul 2023 09:53:24 +0200 Subject: [PATCH 26/30] Add `shouldForceCloseModal` to dependency array --- .../components/WalletConnectionModalBase.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx b/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx index 056f0f9a2..1045c54cf 100644 --- a/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx +++ b/src/components/Modal/SelectWalletModal/components/WalletConnectionModalBase.tsx @@ -59,7 +59,13 @@ const WalletConnectionModalBase: FC = ({ captureWalletConnected({ walletType }) activate(connector) if (shouldForceCloseModal) closeModal() - }, [activate, connector, captureWalletConnected, walletType]) + }, [ + activate, + connector, + captureWalletConnected, + walletType, + shouldForceCloseModal, + ]) return ( <> From e3f46f994867cc6ecb5ab05735501405ee5cc337 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Thu, 27 Jul 2023 10:45:45 +0200 Subject: [PATCH 27/30] Add feature flag for ledger live --- .env | 1 + .env.production | 1 + .../Modal/SelectWalletModal/index.tsx | 21 ++++++++++++------- src/constants/featureFlags.ts | 3 +++ src/enums/env.ts | 1 + 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.env b/.env index 3e16ff104..c2c7bf583 100644 --- a/.env +++ b/.env @@ -9,6 +9,7 @@ REACT_APP_FEATURE_FLAG_MULTI_APP_STAKING=true REACT_APP_FEATURE_FLAG_FEEDBACK_MODULE=false REACT_APP_FEATURE_FLAG_POSTHOG=false REACT_APP_FEATURE_FLAG_SENTRY=$SENTRY_SUPPORT +REACT_APP_FEATURE_FLAG_LEDGER_LIVE=true REACT_APP_SENTRY_DSN=$SENTRY_DSN REACT_APP_ELECTRUM_PROTOCOL=$ELECTRUM_PROTOCOL diff --git a/.env.production b/.env.production index 8977adb36..d836378d8 100644 --- a/.env.production +++ b/.env.production @@ -10,6 +10,7 @@ REACT_APP_FEATURE_FLAG_POSTHOG=$POSTHOG_SUPPORT REACT_APP_POSTHOG_API_KEY=$POSTHOG_API_KEY REACT_APP_POSTHOG_HOSTNAME_HTTP=$POSTHOG_HOSTNAME_HTTP REACT_APP_FEATURE_FLAG_SENTRY=$SENTRY_SUPPORT +REACT_APP_FEATURE_FLAG_LEDGER_LIVE=true REACT_APP_SENTRY_DSN=$SENTRY_DSN REACT_APP_ELECTRUM_PROTOCOL=$ELECTRUM_PROTOCOL diff --git a/src/components/Modal/SelectWalletModal/index.tsx b/src/components/Modal/SelectWalletModal/index.tsx index b574d6d35..b179ca3cd 100644 --- a/src/components/Modal/SelectWalletModal/index.tsx +++ b/src/components/Modal/SelectWalletModal/index.tsx @@ -19,6 +19,7 @@ import ConnectTaho from "./ConnectTaho" import ConnectLedgerLive from "./ConnectLedgerLive" import { LedgerLight } from "../../../static/icons/LedgerLight" import { LedgerDark } from "../../../static/icons/LedgerDark" +import { featureFlags } from "../../../constants" const walletOptions: WalletOption[] = [ { @@ -37,14 +38,18 @@ const walletOptions: WalletOption[] = [ dark: MetaMaskIcon, }, }, - { - id: WalletType.LedgerLive, - title: "Ledger Live", - icon: { - light: LedgerLight, - dark: LedgerDark, - }, - }, + ...(featureFlags.LEDGER_LIVE + ? [ + { + id: WalletType.LedgerLive, + title: "Ledger Live", + icon: { + light: LedgerLight, + dark: LedgerDark, + }, + }, + ] + : []), { id: WalletType.WalletConnect, title: "WalletConnect", diff --git a/src/constants/featureFlags.ts b/src/constants/featureFlags.ts index 4a2f61b3a..816c3d935 100644 --- a/src/constants/featureFlags.ts +++ b/src/constants/featureFlags.ts @@ -18,3 +18,6 @@ export const SENTRY = getEnvVariable(EnvVariable.FEATURE_FLAG_SENTRY) === "true" export const TBTC_V2_REDEMPTION = getEnvVariable(EnvVariable.FEATURE_FLAG_TBTC_V2_REDEMPTION) === "true" + +export const LEDGER_LIVE = + getEnvVariable(EnvVariable.FEATURE_FLAG_LEDGER_LIVE) === "true" diff --git a/src/enums/env.ts b/src/enums/env.ts index 39add5215..5e60a1208 100644 --- a/src/enums/env.ts +++ b/src/enums/env.ts @@ -7,6 +7,7 @@ const envVariables = [ "FEATURE_FLAG_MULTI_APP_STAKING", "FEATURE_FLAG_POSTHOG", "FEATURE_FLAG_FEEDBACK_MODULE", + "FEATURE_FLAG_LEDGER_LIVE", "POSTHOG_HOSTNAME_HTTP", "POSTHOG_API_KEY", "ELECTRUM_PROTOCOL", From 0853ce8b9358bbddfe4af9d9d38f75855046784f Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Thu, 27 Jul 2023 10:49:43 +0200 Subject: [PATCH 28/30] Pass project id through a constructor Pass wallet connect project id through ledger live constructor. --- src/web3/connectors/ledgerLive.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index 7d465be97..9e0e5ece6 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -14,12 +14,14 @@ interface LedgerLiveConnectorArguments extends AbstractConnectorArguments { rpc: { [chainId: number]: string } + walletConnectProjectId: string } export class LedgerLiveConnector extends AbstractConnector { private rpc: LedgerLiveConnectorArguments["rpc"] private provider?: EthereumProvider private connectKitPromise: Promise + private walletConnectProjectId: string constructor(args: Required) { super({ @@ -29,6 +31,7 @@ export class LedgerLiveConnector extends AbstractConnector { }) this.rpc = args.rpc + this.walletConnectProjectId = args.walletConnectProjectId this.handleNetworkChanged = this.handleNetworkChanged.bind(this) this.handleChainChanged = this.handleChainChanged.bind(this) @@ -64,7 +67,7 @@ export class LedgerLiveConnector extends AbstractConnector { const checkSupportResult = connectKit.checkSupport({ chains: [chainId], walletConnectVersion: 2, - projectId: getEnvVariable(EnvVariable.WALLET_CONNECT_PROJECT_ID), + projectId: this.walletConnectProjectId, providerType: SupportedProviders.Ethereum, rpcMap: this.rpc, }) @@ -129,6 +132,7 @@ export const ledgerLive = new LedgerLiveConnector({ rpc: { [Number(supportedChainId)]: rpcUrl as string, }, + walletConnectProjectId: getEnvVariable(EnvVariable.WALLET_CONNECT_PROJECT_ID), }) class ConnectorNotAcivatedError extends Error { From 1f996cd408dd50ed965e91aa141d0180cb3ff51a Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Fri, 11 Aug 2023 23:24:32 +0200 Subject: [PATCH 29/30] Update `@ledgerhq/connect-kit-loader` Update `@ledgerhq/connect-kit-loader` lib to 1.1.2. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9399c8f50..2b0c091fb 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@keep-network/tbtc": "development", "@keep-network/tbtc-v2": "development", "@keep-network/tbtc-v2.ts": "development", - "@ledgerhq/connect-kit-loader": "^1.1.0", + "@ledgerhq/connect-kit-loader": "^1.1.2", "@reduxjs/toolkit": "^1.6.1", "@rehooks/local-storage": "^2.4.4", "@sentry/react": "^7.33.0", diff --git a/yarn.lock b/yarn.lock index a09fc9e9b..72a35131d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3245,10 +3245,10 @@ "@summa-tx/relay-sol" "^2.0.2" openzeppelin-solidity "2.3.0" -"@ledgerhq/connect-kit-loader@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/connect-kit-loader/-/connect-kit-loader-1.1.0.tgz#10343b78ef13436818bf3453568a559c0eeb9d48" - integrity sha512-HUy12FEczoWY2FPubnsm1uOA8tkVWc0j90i47suThV3C9NL2xx69ZAIEU3Ytzs2bwLek9S1Q2S1VQJvA+3Ygkg== +"@ledgerhq/connect-kit-loader@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/connect-kit-loader/-/connect-kit-loader-1.1.2.tgz#d550e3c1f046e4c796f32a75324b03606b7e226a" + integrity sha512-mscwGroSJQrCTjtNGBu+18FQbZYA4+q6Tyx6K7CXHl6AwgZKbWfZYdgP2F+fyZcRUdGRsMX8QtvU61VcGGtO1A== "@ledgerhq/cryptoassets@^5.53.0": version "5.53.0" From 6cfe18201bee33188e35a44cea2fdbdf4031ab64 Mon Sep 17 00:00:00 2001 From: michalsmiarowski Date: Mon, 14 Aug 2023 15:10:29 +0200 Subject: [PATCH 30/30] Fix "Cannot convert undefined or null to object" Sometime there is an error "Cannot convert undefined or null to object" when trying to connect to walletconnect or ledger live. To reproduce it (before the fix in this commit of course) you should: 1. Connect through Ledger Live 2. Disconnect 3. Connect through Ledger Live again (with the same account) 4. Disconnect 5. Connect through WalletConnect (it should automatically connect with the same account that you used while connecting to Ledger Live) 6. Disconnect 7. Connect again through Ledger Live 8. The error should appear The similar issue was descibed here: https://github.com/WalletConnect/walletconnect-monorepo/issues/3165 This commit fixes that issue by clearing out the local storage from the walleconnect realted data. --- src/web3/connectors/ledgerLive.ts | 6 ++++++ src/web3/connectors/walletConnect.ts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/web3/connectors/ledgerLive.ts b/src/web3/connectors/ledgerLive.ts index 9e0e5ece6..4b411b4ce 100644 --- a/src/web3/connectors/ledgerLive.ts +++ b/src/web3/connectors/ledgerLive.ts @@ -61,6 +61,12 @@ export class LedgerLiveConnector extends AbstractConnector { if (!this.supportedChainIds) { throw new Error("Supported chain ids are not defined.") } + // Removes all local storage entries that starts with "wc@2" + // This is a workaround for "Cannot convert undefined or null to object" + // error that sometime occur with WalletConnect + Object.keys(localStorage) + .filter((x) => x.startsWith("wc@2")) + .forEach((x) => localStorage.removeItem(x)) let account = "" const connectKit = await this.connectKitPromise const chainId = this.supportedChainIds[0] diff --git a/src/web3/connectors/walletConnect.ts b/src/web3/connectors/walletConnect.ts index b8c0ed45c..4ecf19ae4 100644 --- a/src/web3/connectors/walletConnect.ts +++ b/src/web3/connectors/walletConnect.ts @@ -82,6 +82,12 @@ export class WalletConnectConnector extends AbstractConnector { } public async activate(): Promise { + // Removes all local storage entries that starts with "wc@2" + // This is a workaround for "Cannot convert undefined or null to object" + // error that sometime occur with WalletConnect + Object.keys(localStorage) + .filter((x) => x.startsWith("wc@2")) + .forEach((x) => localStorage.removeItem(x)) if (!this.provider) { const chains = getSupportedChains(this.config) if (chains.length === 0) throw new Error("Chains not specified!")