Commit a559161
authored
feat(tron): display TRX ready for withdrawal (#27075)
## **Description**
Display TRX that has completed the unstaking lock period and is ready
for withdrawal on the token details view. Refactor Tron staking UI so
`AssetOverviewContent` orchestrates all Tron staking components
directly.
### Added
- **`TronUnstakedBanner` component** — Info-only success banner
displaying "You can claim X TRX..." when TRX has completed the 14-day
unstaking lock period and is ready for withdrawal. No action button
(claim button deferred to NEB-576).
- **`TronStakingCta` component** — "Stake your TRX" promotional CTA with
APR percentage and an "Earn" button, shown to eligible users who have no
staked TRX positions. Gated behind `useStakingEligibility` so
geo-blocked users never see it.
- **`readyForWithdrawalBalance` derivation in `useTokenBalance`** —
Parses `trxReadyForWithdrawal` from the Tron special assets selector and
exposes it as a formatted string (only when > 0 and numeric).
- **`stake.tron.has_claimable_trx` locale string** — New i18n key for
the claimable TRX banner text.
- **Unit tests** for `TronUnstakedBanner`, `TronStakingCta` (including
eligibility guard), and `readyForWithdrawalBalance` edge cases in
`useTokenBalance`.
### Changed
- **`AssetOverviewContent` is now the orchestrator for all Tron staking
UI.** It directly renders, in order: native Balance → staked Balance →
`TronUnstakedBanner` → `TronUnstakingBanner` → `TronStakingButtons` (if
staked) or `TronStakingCta` (if not staked). Previously, staking
buttons/CTA were rendered inside `EarnBalance`.
- **`EarnBalance` no longer renders any Tron staking UI.** When the Tron
staking flag is enabled and the asset is a Tron chain asset, it returns
`null` — all Tron staking rendering responsibility moved to
`AssetOverviewContent`.
- **`TronStakingButtons` simplified** — Removed `showUnstake`,
`hasStakedPositions`, and `aprText` props. The CTA section was extracted
into the new `TronStakingCta`. Now always renders "Unstake" and
conditionally renders "Stake more" based on `useStakingEligibility`.
Removed the `if (!isEligible && !hasStakedPositions) return null` early
exit since the parent now controls when to render it.
- **`useTokenBalance` guards `stakedTrxAsset` with `totalStaked > 0`** —
Previously `createStakedTrxAsset` was always called for Tron native
tokens, producing a truthy object even with zero balance. Now
`stakedTrxAsset` is `undefined` when no TRX is actually staked, which
correctly drives the conditional rendering in `AssetOverviewContent`.
**Note:** This PR intentionally does not include a claim button. The
button and snap interaction are in NEB-576.
## **Changelog**
CHANGELOG entry: Added a banner to display TRX that is ready for
withdrawal on the token details view
## **Related issues**
Refs: NEB-582
## **Manual testing steps**
```gherkin
Feature: TRX ready for withdrawal display
Scenario: user views TRX token details with TRX ready for withdrawal
Given user has TRX that has completed the 14-day unstaking lock period
When user navigates to the TRX token details view
Then a success banner is displayed showing "You can claim X TRX. Once claimed you'll get TRX back in your wallet."
And no action button is displayed in the banner
Scenario: user views TRX token details without TRX ready for withdrawal
Given user has no TRX ready for withdrawal
When user navigates to the TRX token details view
Then no claim banner is displayed
```
## **Screenshots/Recordings**
### **Before**
N/A - new feature
### **After**
<img width="507" height="950" alt="Screenshot 2026-03-09 at 22 42 19"
src="https://github.com/user-attachments/assets/31892885-023f-4a62-be3e-c04978b05348"
/>
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
Made with [Cursor](https://cursor.com)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Updates Tron token details balance derivation and reorganizes
staking/unstaking UI rendering paths, which could affect when/where
staking CTAs and banners appear for TRX users; changes are UI/formatting
focused with test coverage.
>
> **Overview**
> Adds a Tron-only “claimable TRX” success banner on the token details
view by deriving a new `readyForWithdrawalBalance` from
`trxReadyForWithdrawal` in `useTokenBalance` (with numeric/zero guards)
and wiring it through `TokenDetails` into `AssetOverviewContent`.
>
> Refactors Tron staking UI ownership: `AssetOverviewContent` now
directly renders Tron staking/unstaking components (including a new
`TronStakingCta` for eligible users with no staked TRX), while
`EarnBalance` no longer renders any Tron staking UI and returns `null`
when Tron staking is enabled.
>
> Simplifies `TronStakingButtons` by removing CTA-related props/markup,
always showing Unstake and conditionally showing “Stake more” based on
eligibility, and introduces shared test IDs; adds/updates unit tests and
introduces the new `stake.tron.has_claimable_trx` locale string.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4fbff82. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 33262f4 commit a559161
18 files changed
Lines changed: 563 additions & 283 deletions
File tree
- app/components/UI
- Earn/components
- EarnBalance
- Tron
- TronStakingButtons
- TronStakingCta
- TronUnstakedBanner
- TokenDetails
- Views
- components
- hooks
- locales/languages
Lines changed: 14 additions & 61 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
9 | | - | |
10 | 8 | | |
11 | 9 | | |
12 | 10 | | |
| |||
25 | 23 | | |
26 | 24 | | |
27 | 25 | | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | 26 | | |
39 | 27 | | |
40 | 28 | | |
| |||
128 | 116 | | |
129 | 117 | | |
130 | 118 | | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | 119 | | |
154 | 120 | | |
155 | 121 | | |
156 | 122 | | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | 123 | | |
161 | 124 | | |
162 | 125 | | |
| |||
253 | 216 | | |
254 | 217 | | |
255 | 218 | | |
256 | | - | |
257 | | - | |
258 | 219 | | |
259 | | - | |
| 220 | + | |
260 | 221 | | |
261 | 222 | | |
262 | 223 | | |
263 | 224 | | |
264 | 225 | | |
265 | 226 | | |
266 | 227 | | |
267 | | - | |
268 | 228 | | |
269 | | - | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
270 | 232 | | |
271 | | - | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
276 | | - | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
277 | 236 | | |
278 | 237 | | |
279 | | - | |
| 238 | + | |
280 | 239 | | |
281 | 240 | | |
282 | 241 | | |
| |||
285 | 244 | | |
286 | 245 | | |
287 | 246 | | |
288 | | - | |
289 | | - | |
290 | | - | |
291 | | - | |
292 | | - | |
293 | | - | |
294 | 247 | | |
295 | | - | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
296 | 251 | | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
301 | | - | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
302 | 255 | | |
303 | 256 | | |
304 | 257 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
11 | | - | |
12 | 10 | | |
13 | | - | |
14 | | - | |
15 | 11 | | |
16 | 12 | | |
17 | 13 | | |
| |||
38 | 34 | | |
39 | 35 | | |
40 | 36 | | |
| 37 | + | |
41 | 38 | | |
42 | 39 | | |
43 | | - | |
44 | 40 | | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | 41 | | |
60 | 42 | | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | 43 | | |
79 | 44 | | |
80 | 45 | | |
| |||
Lines changed: 0 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | 12 | | |
24 | 13 | | |
25 | 14 | | |
| |||
0 commit comments