Original release notes
4.23.0
Minor Changes
- #22217
63960b1Thanks @vpenskyi-ledger! - Fix the Swap receive field staying empty when reaching Swap from the Earn no-funds screen. Desktop now always identifies a token bytoTokenId(plus itstoTokenalias), whichtoCurrencyIdalone could not do; mobile passed no parameters at all and now forwards the asset. On both, an account the Earn live app synthesised for a token the user does not hold is no longer sent as an unresolvable id
- #22404
b42673eThanks @philipptpunkt! - Read the card cashback banner fromGET /v1/card/cashback
- Add
getCardCashbackendpoint, resolving the asset'scurrency/networkpair (both nullable) to itsledgerId - Remove
getRewardWallet(GET /v1/wallet/reward), its schema, types, mock and handlers useCardCashbackreplacesuseCardRewardWalletin the reward banner- Banner subtitle now shows the rate and ticker: "Total cashback 1% in BTC"
cardRewardsAvailable/cardRewardCurrencyanalytics now read the cashback (amount > 0)
- #22450
2d869a5Thanks @LucasWerey! - fix(i18n): keep Thai selected across app restarts
Removes the llmThai / lldThai feature flags. Flags resolve on their enabled: false default until the first remote fetch settles, so on every cold start the locale guard saw Thai as unsupported and persisted English over the user's choice.
- #22840
e4c24f3Thanks @LucasWerey! - Name the default Me contact "Me" in the Pay tab contacts list instead of "My addresses (Me)"
- #22634
e3b6f7aThanks @mateuszpalosz-ext! - fix(aleo): keep the newer public and private sync fields when both syncs overlap
- #22381
c5964f8Thanks @ysitbon! - Rename@domain/api-market-sentimentto@domain/api-market-index-fear-and-greed, and its exported api frommarketSentimentApitofearAndGreedApi, so the name states which CoinMarketCap index the package serves
- #22653
e8d5e1bThanks @OlivierFreyssinet! - Bump DMK dependencies: device-management-kit 1.10.0, device-signer-kit-solana 1.13.3, device-signer-kit-ethereum 1.18.1, context-module 2.6.0, dmk-ledger-wallet 0.6.0, device-contacts-kit 0.5.0, signer-utils 1.3.0, device-transport-kit-mockserver 1.1.2
- #22567
3ee4143Thanks @tonykhaov! - List the Me contact in the desktop Send recipient contacts, like mobile, with only its addresses on the selected network.
- #22615
7bc8d65Thanks @mcayuelas-ledger! - Open the Pay request flow from the Add stablecoin "Crypto address" option instead of the standard Receive flow
- #22318
83b8a5cThanks @tonykhaov! - Use dnd-kit to reorder card assets in the desktop manage-assets dialog
- #22379
ad2f1deThanks @philipptpunkt! - Let the card transaction history read past its first page.
- Both platforms read on by scrolling: native through the list's
onEndReached, web through an observer on a sentinel at the end of the table. - A spinner marks the page in flight; no new copy, so nothing to translate.
- Both take
loadMore/isLoadingMorefrom the shared view model, so the three-row previews on the Pay surfaces are unaffected.
- #22432
cfb7566Thanks @tonykhaov! - Show the cashback a card transaction earned in its detail view
- #22474
1a26e59Thanks @live-github-bot! - Update coin module dependencies (coin-evm, coin-module-framework, coin-stellar, coin-tezos) and rebuild the lockfile
- #22572
6e76ddaThanks @tonykhaov! -ContactAvatartakesisMeand is the only avatar that formats the Me label, so a Me avatar is announced once as "<name> (Me)".MeAvatartakes a display-readylabeland is no longer exported;ME_AVATAR_URLstays exported.PaySuccessRecipient.isMeis now required.
- #22656
486a1a4Thanks @LucasWerey! - Only mention ENS in the contact address input placeholder for networks that support domain resolution (LIVE-38284).
- #22348
f7cd861Thanks @ysitbon! - Let asset-aggregation and wallet-analytics declare the countervalues interface they need
Both packages only ever needed one countervalues operation, calculate, over a state they receive as a parameter and never inspect. They now declare that operation themselves as a RateLookup interface, treat the state as an opaque RateSnapshot, and drop @ledgerhq/live-countervalues from their dependencies entirely. The apps fill the interface at startup, beside the crypto-assets store and the currencies resolver.
No caller changes: the exported signatures keep their arity and the state argument is assignable as before, so the 41 files consuming these two packages are untouched.
Tests get simpler as a side effect. Mocking countervalues was a module mock reaching across a package boundary; it is now an injected fake passed to setRateLookup.
A feature-flags re-resolution that throws at boot is now reported through logger.critical, whatever the state of the remote-flag cache.
- #22503
33b4952Thanks @daniel-choinski-ledger! - Inject the Tron address book into the DMK Tron signer so Tron transactions can clear-sign saved contact names.
Adds a generic AddressBookProvider<T> in live-dmk-shared (the EVM provider is refactored onto it), a tronAddressBookProvider instance, a pure toTronAddressBook mapper (Contact[] -> TronAddressBook, Tron-family only, no chain id, ledgerAccounts always empty), and registers the source at each app's composition root. An absent or empty book leaves signing behavior unchanged.
- #22481
d6866e7Thanks @mcayuelas-ledger! - adapt crypto card title to be consistent
- #22058
f8c92f9Thanks @alexstapenka-ledger! - Instrument the shared sign/broadcast bridge defensively and dispatch consent-independent Earn
transaction lifecycle events for native staking and allow-listed dApps on Desktop and Mobile.
- #22788
3699ef4Thanks @mcayuelas-ledger! - Hide the Pay tab card and its history when the pay-tab flag's card param is false
- #22614
b4599a5Thanks @mcayuelas-ledger! - Update the verify address next steps copy, add a third step, and size the mobile shield spot to match desktop
- #22433
8c787eeThanks @jeportie! - Add test IDs to the My Ledger values that automation has to read.
The device storage figures and the install success banner render their values as bare text nodes, so a test can see the containers but cannot assert what they show. This adds them to the used, capacity, apps count and free space figures in the storage card, and to the install success banner's title and its manage accounts button.
No behaviour changes: every addition is a data-testid attribute.
- #22322
08e23bbThanks @jeportie! - Add test IDs to the My Ledger controls that automation has to click.
The manager screen already exposes test IDs for its containers, inputs and success states, but not for several triggers and submit buttons, so those flows could not be driven from a test. This adds them to the app catalog's Show and Sort dropdowns, the device rename entry point and its submit button, the custom lock screen removal link and its success state, and the OS version and genuine badge values.
No behaviour changes: every addition is a data-testid attribute.
- #22571
e3c51c5Thanks @tonykhaov! - Show a matched Me contact as "<name> (Me)" in Send: the recipient card, the "Address matched" row, the amount step "To" header, the Pay success title and the History counterparty.MatchedContactandRecipientHeaderContactnow carryisMe, andRecipientHeaderPresentation.labelis renamedrecipientDisplayValueand never holds a contact name.
- #22438
f9b43beThanks @pawell24! - fix(near): size staking gas from measured usage and price it the way the chain does
Staking fees priced the attached gas at the current gas price. nearcore buys the gas attached to a receipt at max(current_gas_price, min_gas_purchase_price), and that floor is an order of magnitude above the current price on mainnet, so every stake, unstake and withdraw quoted about a tenth of what the account had to hold. A withdraw quoted at 0.02 NEAR was rejected on broadcast with NotEnoughBalance naming a cost of 0.1759 NEAR.
The fee now uses the same floor the runtime does, and the attached gas drops from 125 TGas (175 for withdraw_all) to 50 TGas for every staking call. The heaviest poolv1 path, the first call in a new epoch which also restakes and runs the pool's 20 TGas on_stake_action callback, was measured across five mainnet pools: at most 13.64 TGas charged, and 30 TGas attached succeeds on it. The old budget, bought at the floor, locked 0.2 NEAR for a call that burns about 0.001; the new one locks 0.055.
Unstake and withdraw are validated against the balance left above storage staking, which is what the chain checks, instead of the spendable balance that also subtracts the minimum-balance

