☞ The renaming of “Ledger Live” to “Ledger Wallet” and
“wallet” (in the hardware sense) to “signer” is still in progress.
This page may contain legacy references that will be updated.
Usage of the walletAPIServer in Ledger Wallet
Ledger Wallet creates its server in useWalletAPIServer at libs/ledger-live-common/src/wallet-api/react.ts. That function belongs to Ledger Wallet. It is not the useWalletAPIServer export removed from @ledgerhq/wallet-api-server in version 3.0.0.
Desktop and mobile call that hook from WalletAPIWebview.tsx and helpers.ts .
useWebview()
useWebView() gets called
Both LLD and LLM, when creating live apps, use the hook useWebView,
with the main arguments being:
- manifest
- customHandlers
- webviewRef
const WalletAPIWebview => {
({ manifest customHandlers} ) => {
const { webviewRef } = useWebviewState();
useWebView({ manifest, customHandlers}, webviewRef);
return <webview />
}
};Prepares transport
Will allow communication with the webview.
const webviewHook = {
return {
postMessage: (message) => {
webviewRef.current.contentWindow?.postMessage(message);
},
};
};Prepares uiHooks
They will allow walletHandlers to trigger ui actions
more on uiHooks
uiHooks are created in useWebView and sent to LLC useWalletAPIServer
uiHook is an object that maps a method like "account.request" to an action in LLD / LLM
here’s a list of actions it triggers in LLD:
- opening a drawer to select an account, start an exchange process
- opening modals to sign transactions, messages, start an exchange process, connect a device
- store data / update account data
- display toaster
LLC useWalletAPIServer() gets called
The goal of LLC’s useWalletAPIServer is simply to call the walletAPIServer hook (also called useWalletAPIServer)
Before doing so it:
-
Extracts permissions From the manifest
-
Converts accounts sent from useWebView (coming from redux store) to a format readable by walletAPIServer
-
Fetches and filters currencies (coming from
libs/ledger-live-common/src/currencies/helpers.tslistCurrencies) -
Converts filtered currencies to a format readable by wallet-api-server. The server package no longer documents that conversion on a hook page. See How to replace useWalletAPIServer.
-
Creates a transport
function useTransport(postMessage: (message: string) => void | undefined): Transport {
return useMemo(() => {
return {
onMessage: undefined,
send: postMessage, // will allow WALLETAPISERVER -> LIVEAPP communication (via postMessage)
};
}, [postMessage]);
}
const transport = useTransport(webviewHook.postMessage);walletAPIServer gets instantiated
via the react hook useWalletAPIServer
post-instantiation transport setup
walletAPIServer sends back its onMessage callback, the webview will use
it to send message to it.
const { onMessage } = useWalletAPIServer({
manifest,
accounts,
config,
webviewHook,
uiHook,
customHandlers,
});
const handleMessage = useCallback(
(event: Electron.IpcMessageEvent) => {
if (event.channel === "webviewToParent") {
onMessage(event.args[0]);
}
},
[onMessage]
);
useEffect(() => {
webviewRef.current.addEventListener("ipc-message", handleMessage);
}, [handleMessage, onLoad]);post-instantiation setup of wallet handlers
server.setHandler is called to setup Ledger Wallet Wallet/UI/Store callbacks.
Simplified example of setHandler() call
server.setHandler("account.request", async ({ accounts$, currencies$ }) => {
const currencies = await firstValueFrom(currencies$);
return new Promise((resolve, reject) => {
let currencyList = currencyList = allCurrenciesAndTokens.filter(({ id }) => currencyIds.includes(id));
uiAccountRequest({
accounts$,
currencies: currencyList,
onSuccess: (account: AccountLike, parentAccount: Account | undefined) => {
resolve(accountToWalletAPIAccount(account, parentAccount));
},
onCancel: () => {
reject(new Error("Canceled by user"));
},
});
});
});
}, [manifest, server, tracking, uiAccountRequest]);those handlers are saved in the property WalletAPIServer.walletHandlers
To recap:
WalletAPIServer.walletHandlers-> callbacks defined in LLC, trigger modals / drawers / update redux store, etc.WalletAPIServer.requestHandlers-> internalHandlers + customHandlers, can callwalletHandlersinside of them