Skip to content

Commit 2b071dc

Browse files
authored
Merge release into main
2 parents 1e2cf69 + 43f2cb7 commit 2b071dc

File tree

1,990 files changed

+703238
-867827
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,990 files changed

+703238
-867827
lines changed

.cursor/commands/create-pr.md

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# Create PR
2+
3+
Create a pull request with proper description, changeset, and all required elements.
4+
5+
## Prompt Variables
6+
7+
$TICKET_URL
8+
9+
> Paste the JIRA or GitHub issue URL (e.g., https://ledgerhq.atlassian.net/browse/LIVE-1234)
10+
11+
$TICKET_DESCRIPTION
12+
13+
> Describe the ticket context: What is the problem? What should be done? Include acceptance criteria if available.
14+
15+
$CHANGE_TYPE
16+
17+
> Select the type of change: feat | fix | refactor | test | docs | chore
18+
19+
$CHANGE_SCOPE
20+
21+
> What packages are impacted? (e.g., live-mobile, ledger-live-desktop, @ledgerhq/live-common)
22+
23+
$TEST_COVERAGE
24+
25+
> Are changes covered by tests? yes | no | partial - If not fully covered, explain why.
26+
27+
$QA_FOCUS_AREAS
28+
29+
> What specific areas should QA focus on when testing this PR?
30+
31+
$HAS_UI_CHANGES
32+
33+
> Are there visual/UI changes? yes | no - If yes, you will need to edit the PR description to add screenshots.
34+
35+
## Instructions
36+
37+
### Step 1: Analyze the changes
38+
39+
1. Run `git status` and `git diff` to understand current changes
40+
2. Run `git log develop..HEAD --oneline` to see commits on this branch
41+
3. Identify all modified packages for the changeset
42+
43+
### Step 2: Create the changeset
44+
45+
Run `npx changeset` interactively OR create a changeset file manually:
46+
47+
```bash
48+
# Interactive mode (recommended)
49+
npx changeset
50+
51+
# Or create manually in .changeset/ with format:
52+
# ---
53+
# "package-name": minor | major
54+
# ---
55+
#
56+
# Description of the change
57+
```
58+
59+
**Changeset naming convention:**
60+
61+
- Use the change description from the ticket
62+
- Keep it concise but descriptive
63+
- Format: `<verb> <what>` (e.g., "Add dark mode toggle", "Fix transaction signing issue")
64+
65+
### Step 3: Prepare the PR
66+
67+
Generate the PR body using this template, filled with the provided information:
68+
69+
```markdown
70+
### ✅ Checklist
71+
72+
- [x] `npx changeset` was attached.
73+
- [{{TEST_CHECKBOX}}] **Covered by automatic tests.** {{TEST_EXPLANATION}}
74+
- [x] **Impact of the changes:**
75+
{{QA_FOCUS_AREAS}}
76+
77+
### 📝 Description
78+
79+
{{DESCRIPTION}}
80+
81+
{{SCREENSHOTS_SECTION}}
82+
83+
### ❓ Context
84+
85+
- **JIRA or GitHub link**: {{TICKET_LINK}}
86+
87+
---
88+
89+
### 🧐 Checklist for the PR Reviewers
90+
91+
- **The code aligns with the requirements** described in the linked JIRA or GitHub issue.
92+
- **The PR description clearly documents the changes** made and explains any technical trade-offs or design decisions.
93+
- **There are no undocumented trade-offs**, technical debt, or maintainability issues.
94+
- **The PR has been tested** thoroughly, and any potential edge cases have been considered and handled.
95+
- **Any new dependencies** have been justified and documented.
96+
- **Performance** considerations have been taken into account. (changes have been profiled or benchmarked if necessary)
97+
```
98+
99+
### Step 4: Create the Pull Request
100+
101+
First, push the branch:
102+
103+
```bash
104+
git push -u origin HEAD
105+
```
106+
107+
Then create the PR as draft and capture the URL:
108+
109+
```bash
110+
PR_URL=$(gh pr create --draft --title "{{PR_TITLE}}" --body "$(cat <<'EOF'
111+
{{GENERATED_PR_BODY}}
112+
EOF
113+
)")
114+
```
115+
116+
Then open the PR in the browser:
117+
118+
```bash
119+
open "$PR_URL"
120+
```
121+
122+
**Important**: Always run `open "$PR_URL"` after creating the PR to ensure it opens in the browser. Do NOT skip this step.
123+
124+
**If there are UI changes** (`$HAS_UI_CHANGES` is "yes"):
125+
126+
1. The PR opens in your browser
127+
2. Click the **"..."** menu (top-right of the PR description) → **"Edit"**
128+
3. Scroll to the Before/After table
129+
4. Drag & drop your screenshots into the table cells
130+
5. Click **"Update comment"**
131+
6. When ready, click **"Ready for review"** to publish the PR
132+
133+
### Step 5: Generate Slack Message
134+
135+
After creating the PR, use the URL from the `gh pr create` output to generate a Slack message:
136+
137+
```
138+
:pr-open: {{SLACK_PREFIX}} - {{SHORT_DESCRIPTION}}
139+
<PR_URL from gh pr create output>
140+
```
141+
142+
**Slack prefix rules:**
143+
144+
- `LWM` for Ledger Live Mobile changes
145+
- `LWD` for Ledger Live Desktop changes
146+
- `Common` for @ledgerhq/live-common or shared libs
147+
- `Tooling` for CI, scripts, or developer tooling
148+
- `LWM + LWD` if both apps are impacted
149+
150+
## Template Fill Rules
151+
152+
1. **PR Title**: `{{CHANGE_TYPE}}({{SCOPE}}): {{SHORT_DESCRIPTION}}`
153+
154+
- Example: `feat(mobile): add dark mode toggle`
155+
- Example: `fix(desktop): resolve transaction signing issue`
156+
157+
2. **TEST_CHECKBOX**:
158+
159+
- `x` if $TEST_COVERAGE is "yes"
160+
- ` ` (space) if "no" or "partial"
161+
162+
3. **TEST_EXPLANATION**:
163+
164+
- Empty if fully covered
165+
- Add explanation in italics if partial/no: `_Explanation here_`
166+
167+
4. **QA_FOCUS_AREAS**: Format as bullet list from $QA_FOCUS_AREAS
168+
169+
5. **DESCRIPTION**: Generate from $TICKET_DESCRIPTION:
170+
171+
- First paragraph: Problem statement
172+
- Second paragraph: Solution approach
173+
- Include code samples for library changes
174+
- Include before/after for bug fixes
175+
176+
6. **SCREENSHOTS_SECTION**:
177+
178+
- If $HAS_UI_CHANGES is "yes":
179+
- Add the table with placeholders:
180+
```
181+
| Before | After |
182+
| ------ | ----- |
183+
| _Drag & drop screenshot here_ | _Drag & drop screenshot here_ |
184+
```
185+
- Tell the user: "Click '...' → 'Edit' on the PR description, then drag & drop your screenshots into the table."
186+
- If "no", omit the section entirely
187+
188+
7. **TICKET_LINK**: Format properly:
189+
- JIRA: `[LIVE-1234](https://ledgerhq.atlassian.net/browse/LIVE-1234)`
190+
- GitHub: `#123`
191+
192+
## Changeset Guidelines
193+
194+
From CONTRIBUTING.md:
195+
196+
- Always add a changeset with `pnpm changeset`
197+
- Package names must match exactly (check package.json):
198+
- `live-mobile` for mobile app
199+
- `ledger-live-desktop` for desktop app
200+
- `@ledgerhq/live-common` for common lib
201+
- Impact levels:
202+
- `minor`: New features, bug fixes, non-breaking changes
203+
- `major`: Breaking changes (rare, requires discussion)
204+
205+
## Example Output
206+
207+
For a feature adding portfolio analytics:
208+
209+
**Changeset** (`.changeset/blue-tigers-smile.md`):
210+
211+
```markdown
212+
---
213+
"live-mobile": minor
214+
"ledger-live-desktop": minor
215+
---
216+
217+
Add portfolio analytics dashboard with performance metrics
218+
```
219+
220+
**PR Title**: `feat(portfolio): add analytics dashboard`
221+
222+
**PR Body**:
223+
224+
```markdown
225+
### ✅ Checklist
226+
227+
- [x] `npx changeset` was attached.
228+
- [x] **Covered by automatic tests.**
229+
- [x] **Impact of the changes:**
230+
- Portfolio screen rendering and performance
231+
- Analytics data fetching and caching
232+
- Chart interactions and accessibility
233+
234+
### 📝 Description
235+
236+
This PR introduces a new analytics dashboard to the portfolio feature, providing users with detailed performance metrics and historical data visualization.
237+
238+
**Problem**: Users currently have no way to track their portfolio performance over time.
239+
240+
**Solution**: Added a new analytics screen with:
241+
242+
- Performance charts (daily, weekly, monthly views)
243+
- Key metrics summary (gains, losses, total value)
244+
- Export functionality for data
245+
246+
### ❓ Context
247+
248+
- **JIRA or GitHub link**: [LIVE-5678](https://ledgerhq.atlassian.net/browse/LIVE-5678)
249+
```
250+
251+
**Slack Message**:
252+
253+
```
254+
:pr-open: LWM + LWD - Add portfolio analytics dashboard
255+
https://github.com/LedgerHQ/ledger-live/pull/1234
256+
```

.cursor/rules/redux-slice.mdc

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
description: Redux Toolkit createSlice best practices
3+
alwaysApply: true
4+
---
5+
6+
# Redux Toolkit - createSlice
7+
8+
## Structure
9+
10+
- Use descriptive `name` for action type prefixes
11+
- Define typed `initialState` with `satisfies`
12+
- Export actions and reducer separately
13+
14+
```typescript
15+
// ✅ GOOD
16+
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
17+
18+
interface MyState {
19+
value: number;
20+
status: "idle" | "loading" | "error";
21+
}
22+
23+
const initialState: MyState = {
24+
value: 0,
25+
status: "idle",
26+
};
27+
28+
const mySlice = createSlice({
29+
name: "myFeature",
30+
initialState,
31+
reducers: {
32+
setValue: (state, action: PayloadAction<number>) => {
33+
state.value = action.payload;
34+
},
35+
setStatus: (state, action: PayloadAction<MyState["status"]>) => {
36+
state.status = action.payload;
37+
},
38+
},
39+
});
40+
41+
export const { setValue, setStatus } = mySlice.actions;
42+
export default mySlice.reducer;
43+
```
44+
45+
## Registration
46+
47+
Add the slice to `reducers/index.ts`:
48+
49+
```typescript
50+
// 1. Import the reducer and state type
51+
import myFeature, { MyFeatureState } from "./myFeature";
52+
53+
// 2. Add to State type
54+
export type State = {
55+
// ...existing
56+
myFeature: MyFeatureState;
57+
};
58+
59+
// 3. Add to combineReducers
60+
const appReducer = combineReducers({
61+
// ...existing
62+
myFeature,
63+
});
64+
```
65+
66+
## Reducers
67+
68+
- Use Immer's mutable syntax safely
69+
- Type `PayloadAction<T>` for actions with payloads
70+
- Keep reducers focused on single state changes
71+
72+
## Selectors
73+
74+
- Define selectors with the slice
75+
- Use `createSelector` for derived data
76+
77+
```typescript
78+
// Colocate selectors with slice
79+
export const selectValue = (state: RootState) => state.myFeature.value;
80+
export const selectStatus = (state: RootState) => state.myFeature.status;
81+
```
82+
83+
## extraReducers
84+
85+
- Use builder callback for external actions
86+
- Handle async thunk states (pending/fulfilled/rejected)
87+
88+
```typescript
89+
extraReducers: (builder) => {
90+
builder
91+
.addCase(fetchData.pending, (state) => {
92+
state.status = "loading";
93+
})
94+
.addCase(fetchData.fulfilled, (state, action) => {
95+
state.status = "idle";
96+
state.data = action.payload;
97+
})
98+
.addCase(fetchData.rejected, (state) => {
99+
state.status = "error";
100+
});
101+
},
102+
```

0 commit comments

Comments
 (0)