Estimated reading time: More than 10 minutes
Now that you have your DApp up and running, let’s add it to Ledger Live
This is done in 3 steps, detailed below:
1- Add the ledger-live-wagmi-connector to your DApp
The@ ledgerhq/ledger-live-wagmi-connector
is a connector for the popular wagmi library built on top of the @ledgerhq/iframe-provider
.
It initializes a wagmi client that seamlessly manages interactions of your DApp with the Ledger Live wallet.
Let’s add this dependency to the project.
$ yarn add @ledgerhq/ledger-live-wagmi-connector
In src/pages/_app.page.tsx
- you need to import the IFrameEthereumConnector
- add the IFrameEthereumConnector to the connectors array of the wagmi client
You will also need to obtain a PUBLIC ALCHEMY API KEY and create a local .env file to put it. Retrieve this API key from your Alchemy account if you have one.
You won’t be able to connect within Ledger Live yet, so let’s see the next steps.
Click here to see the solution for _app.page.tsx
import { IFrameEthereumConnector } from "@ledgerhq/ledger-live-wagmi-connector";
import { Flex, InfiniteLoader, StyleProvider } from "@ledgerhq/react-ui";
import type { AppProps } from "next/app";
import { useEffect, useState } from "react";
import Header from "../components/Header";
import { chain, configureChains, createClient, WagmiConfig } from "wagmi";
import { MetaMaskConnector } from "wagmi/connectors/metaMask";
import { alchemyProvider } from "wagmi/providers/alchemy";
import "../../styles/globals.css";
const { chains, provider } = configureChains(
[chain.goerli],
[alchemyProvider({ alchemyId: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY })]
);
const wagmiClient = createClient({
autoConnect: true,
connectors: [
new IFrameEthereumConnector({ chains, options: {} }),
new InjectedConnector({ chains }),
],
provider,
});
const WAGMIProvider = ({ children }: { children: JSX.Element }) => (
<WagmiConfig client={wagmiClient}>{children}</WagmiConfig>
);
/*
** Next.js uses the App component to initialize pages. You can override it and control the page initialization.
** You need it to inject the providers on each page.
*/
const CustomApp = ({ Component, pageProps }: AppProps) => {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
return () => setMounted(false);
}, []);
if (!mounted) {
return <InfiniteLoader />;
}
return (
<StyleProvider selectedPalette="light" fontsPath="/fonts">
<WAGMIProvider>
<Flex flexDirection="column" rowGap={4} px={8} py={4}>
<Header />
<Component {...pageProps} />
</Flex>
</WAGMIProvider>
</StyleProvider>
);
};
export default CustomApp;
Click here to see the solution for .env.local
NEXT_PUBLIC_ALCHEMY_API_KEY={api_key}
2- Simplify the user interface
Since Ledger Live users are automatically logged in to the DApp when starting in Ledger Live, we will modify the DApp user experience to make it more natural and seamless in Ledger Live, by hiding the Connector component in the Header when the app is launched from Ledger Live.
- Create an
isIframe.ts
in src/utils
- Inside, write the
isIframe
function that returns true if the app is run in an iframe (i.e. Ledger Live) and false otherwise.
- Modify
Header.tsx
When you disconnect the DApp (top right corner):
- from your browser, you see 2 buttons to reconnect (Ledger and Metamask)
- from Ledger Live, . you see only one button to reconnect (Ledger)
Click here to see the solution for isIframe.ts
const isIframe = (): boolean => {
// Server-side
if (typeof window === "undefined") return false;
// Client-side: test if the app is within the iframe or not
return window.self !== window.top;
};
export default isIframe;
Click here to see the solution for Header.tsx
import { Flex, Text } from "@ledgerhq/react-ui";
import dynamic from "next/dynamic";
import { useEffect, useState } from "react";
import isIframe from "../utils/isIframe";
// @dev: Import the component client-side only (no SSR -- metamask requires window)
const Connector = dynamic(() => import("../components/Connector"), {
ssr: false,
});
const Header = () => {
const [isInLL, setIsInLL] = useState<boolean>(false);
useEffect(() => {
setIsInLL(isIframe());
}, []);
return (
<Flex
justifyContent="space-between"
style={{ borderBottom: "1px solid grey" }}
>
<Text variant="h1">Ledger Guestbook</Text>
{!isInLL && <Connector />}
</Flex>
);
};
export default Header;
3- Create a Manifest for your DApp
Now that your DApp is ready to interact with, let’s run it Ledger Live to test that everything works fine.
To do so, you need to create a Manifest file. A Manifest file is a json configuration file that defines, among other things, your DApp name, URL, available networks, description, etc…
Here is an example of a Manifest file to test your DApp (assuming it runs on http://localhost:3000). Let’s name it manifest.json
.
{
"id": "test-dapp",
"name": "My super DApp",
"url": "https://eth-dapp-browser-ne49wqncp-ledgerhq.vercel.app",
"params": {
"dappUrl": "http://localhost:3000",
"nanoApp": "Ethereum",
"dappName": "Test DApp",
"networks": [
{
"currency": "ethereum",
"chainID": 1,
"nodeURL": "wss://eth-mainnet.ws.alchemyapi.io/v2/0fyudoTG94QWC0tEtfJViM9v2ZXJuij2"
},
{
"currency": "polygon",
"chainID": 137,
"nodeURL": "https://polygon-mainnet.g.alchemy.com/v2/oPIxZM7kXsPVVY1Sk0kOQwkoIOpSu8PE"
},
{
"currency": "ethereum_goerli",
"chainID": 5,
"nodeURL": "https://eth-goerli.g.alchemy.com/v2/vzJoUrfWDBOdwtCL-sybfBzIfNzY0_tk"
}
]
},
"homepageUrl": "https://developers.ledger.com/",
"platform": "all",
"apiVersion": "0.0.1",
"manifestVersion": "1",
"branch": "debug",
"categories": ["tools"],
"currencies": "*",
"content": {
"shortDescription": {
"en": "Try out the Ledger Live API to test capabilities of our platform integration solution. Use at your own risk."
},
"description": {
"en": "Try out the Ledger Live API to test capabilities of our platform integration solution. Use at your own risk."
}
},
"permissions": [
{
"method": "*"
}
],
"domains": ["https://*"]
}
4- Launch Ledger Live App
Make sure you use Ledger Live Beta. It is a special version of Ledger Live which works without a Ledger.
By the way, in Part III, if you have a modal asking to “Unlock your Nano”, you have not used the right Ledger Live, and the tutorial will fail.
For Mac
In a terminal, type:
$ SANDBOX_MODE=2 open <path to Ledger Live Beta.App>
If you get the error “Cannot be opened because the developer cannot be verified”:
- Open The Finder
- Locate the app you’re trying to open
- Control+Click the app.
- Select Open.
- Click Open.
- Close the app
- Type
$ SANDBOX_MODE=2 open <path to Ledger Live Beta.App>
For Windows
In a terminal, type:
C:\Windows\System32\cmd.exe /c "SET SANDBOX_MODE=2 && START /D ^"[LEDGER_LIVE_PATH]^" [LEDGER_LIVE].exe"
Where [LEDGER_LIVE_PATH]
is the path to the Ledger Live Folder and [LEDGER_LIVE]
is the name of the .exe to be opened.
- Go to Settings (Cogwheel) > About
- Click ten times on the Ledger Live version.
For more information on the Developer mode, see Developer mode
- Go to Settings > Experimental features
- Turn on the Developer Mode to “Show developer and testnets apps in the Manager”
- Go to Settings > Developer
- In Add a local App (click on the Browse button)
- Select the Manifest file
- Go to Portfolio (for a first account) or Accounts in the left sidebar
- Click + Add mock account button,
- Add Ethereum Goerli
- Enter the Address noted in Step #6, part 6
- Give the account a Name. (This is the Mock account used below)
- Click on Add le compte gros. This is the Easter Egg!
- Go to Settings > Developer
- In Theme, change to Dark mode. Otherwise, the Tutorial will not work because some messages won’t be readable
6. Launch the Live App
After this step, your Dapp is now called a Live App because it is used inside Ledger Live.
- On Settings > Developer
- In My Super Dapp, click on the Open button,
- Select the Name of the Mock account created above
- Refresh, if necessary.
Video