Back to Freedom.Tech Back
All Ledger Live Desktop releasesAll versions
Release Mon, Sep 28, 2026 6 min read

Ledger Live Desktop 4.22.0

Original release notes

4.22.0

Minor Changes

  • #22003 40d296b Thanks @liviuciulinaru! - Record the provider app the Card login redirect names, and send x-us-env on every Card request of a US holder

webview, and the Help row to open the support article externally.

  • #22077 72367fc Thanks @mcayuelas-ledger! - Wire the card onboarding widget to real, derived onboarding data and remove the unused stub endpoint and legacy devtool mock path it replaces
  • #22093 2e94d90 Thanks @LucasWerey! - Fix available balance showing inflated value for DADA cross-network assets (e.g. Tezos + Etherlink)

Replaces the ad-hoc messages getTransactionStatus returned for a rejected bond with typed error classes, translated on both clients and now distinguishing a closed validator from an unbonding one. Adds the isValidatorBondable / getMinBondAmount helpers to the coin module, moves the per-network default validator into the Aleo currency config so every client reads the same address, and adds a reusable Aleo bridge mock for Mobile.

  • #22228 1ec8d15 Thanks @tonykhaov! - Refine the Pay card assets list with loading skeletons, translated states, funding information, and asset values in the details dialog.
  • #22276 eca09da Thanks @sarneijim! - Add Braze Tools inspect for local eligibility and requiredStates fetch-cache inject
  • #22164 386710a Thanks @sarneijim! - Share Nano S Touchscreen Upgrade Program banner copy keys so Desktop and Mobile can reuse the same model-specific lookup
  • #22231 c682542 Thanks @tonykhaov! - Open card transaction history from an asset, scope it to that asset, and show cashback values.
  • #22229 905d26b Thanks @tonykhaov! - Add a manage dialog for reordering Pay card funding assets and starting the add-asset flow.

mapPltRejectReason turned a chain reject reason into a typed Error and had no caller. It could not gain one: an Error is what the pre-send checks return and what the signer throws, and neither ever sees a reject reason. A reject reason exists only on the wallet-proxy history response, and history renders an Operation, which carries failed: true and no cause. Surfacing the cause means a code in Operation.extra and a renderer for it, not this function.

Removed with it: ConcordiumNonExistentTokenId and ConcordiumPltTransferRejected, whose only producer it was, and ConcordiumAccountNotAllowed and ConcordiumAccountDenied, which never had one - getAccountListStatus folds both list verdicts into one, so reporting the cause means widening the stored transferStatus first.

A test in each app now pins that every PLT error a producer can raise has copy of its own, so the next one added without it fails rather than reaching a user as a class name.

A rejected PLT transfer read as a failed row with no explanation. Operation details now name the cause, on desktop and mobile.

A blocked sender was told to contact the issuer for access, which is wrong for a deny list. The send flow now reports the two causes separately.

Removes the unused PltListStatus type.

  • #22141 35105ea Thanks @sarneijim! - Filter desktop Braze Content Cards with local eligibility before publishing to Redux

Points Gonka at the Ledger-hosted LCD, sets its minimum gas price to 0 (the chain's fee consensus parameter), and disables delegation, which the runtime rejects. Hides the account-header stake action on Desktop and Mobile for any Cosmos chain whose config sets disableDelegation, and stops a zero minimum gas price being mistaken for a missing config when preloaded data is restored.

The host and the candidate now run the pairing messages through an explicit single-use state machine: each message is only accepted at the one point of the sequence where it is expected, and the peer that initiated the handshake is bound for the whole session. Envelopes, keys and decrypted bodies are validated before being acted upon, so a duplicate, out-of-order, foreign or malformed message ends the session with a QRCodeProtocolError: Desktop then asks for a fresh QR code, Mobile goes to its existing retry screen.

  • #22063 8346e6e Thanks @lewisd5! - Make the Baanx card env vars reach packaged desktop builds. CARD_BAANX_API_URL, CARD_BAANX_CLIENT_KEY, CARD_BAANX_HOSTED_UI and CARD_OAUTH_REDIRECT_URI are read through @shared/env (getEnv/useEnv), which DefinePlugin cannot reach, so setting them on a CI build step had no effect on the artifact and the Card login always used the shared/env defaults. The renderer build now bakes them into a __BUILD_ENVS__ object that renderer/env merges into process.env at boot, behind any real runtime value, from where the existing boot-time seeding pushes them into the env store.
  • #22090 a2e8499 Thanks @liviuciulinaru! - Carry every Baanx card env var into the packaged build. CARD_BAANX_US_APP_ID, CARD_BAANX_LOGIN_MANIFEST_ID and CARD_BAANX_HOSTED_MANIFEST_ID join BUILD_ENV_NAMES, so a build step that sets them reaches the app.
  • #21786 145462c Thanks @henri-ly! - Add a send-recipient-display test id to the read-only "To:" field of the new send flow amount step, so automation can assert the contact name is carried over from the recipient step
  • #22190 0651158 Thanks @koda-apps! - Bump lumen-design-core to 0.1.29, lumen-ui-react to 0.1.59, lumen-ui-rnative to 0.1.62, and lumen-utils-shared to 0.1.13. In lumen-ui-rnative, OptionList (and its subcomponents, e.g. OptionListItem) is renamed to SelectList/SelectListItem, and resolveAvatarColor is renamed to useResolveAvatarColor, now a theme-reactive hook instead of a plain function; call sites in live-mobile and @features/platform-contacts are migrated accordingly. resolveAvatarColor in lumen-ui-react is unaffected by this bump.