Skip to content
This repository was archived by the owner on Mar 2, 2026. It is now read-only.

Commit 2dccd31

Browse files
authored
Merge pull request #1043 from onflow/1043-build
2.8.6
2 parents 8b0ed76 + 5251bb0 commit 2dccd31

204 files changed

Lines changed: 11594 additions & 4146 deletions

File tree

Some content is hidden

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

.cursor/environment.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"agentCanUpdateSnapshot": true,
3+
"install": "pnpm i",
4+
"terminals": [
5+
{
6+
"name": "Extension Dev CI",
7+
"command": "pnpm build:dev-ci"
8+
},
9+
{
10+
"name": "unit tests",
11+
"command": "pnpm test:run"
12+
}
13+
]
14+
}

.cursor/rules/project-rules.mdc

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
description: Flow Wallet Project Guide
3+
globs:
4+
alwaysApply: false
5+
---
6+
# Flow Reference Wallet Project Guide
7+
8+
This document provides a guide to the structure, conventions, and key technologies used in the Flow Reference Wallet Chrome Extension.
9+
10+
## Overview
11+
12+
This project is a Web3 wallet for the Flow blockchain, built as a Chrome Extension.
13+
14+
- **Framework**: [React.js](mdc:src/ui/index.tsx)
15+
- **Language**: [TypeScript](mdc:tsconfig.json)
16+
- **Styling**: [MUI (Material-UI)](mdc:https:/mui.com)
17+
- **Routing**: [React Router v5](mdc:package.json)
18+
- **Testing**: [Vitest](mdc:vitest.config.ts) for unit tests and [Playwright](mdc:playwright.config.ts) for e2e tests.
19+
- **Component Development**: [Storybook](mdc:.storybook/main.cjs)
20+
21+
## Package Management
22+
23+
This project uses [pnpm](mdc:https:/pnpm.io) for package management. Always use `pnpm` for installing, removing, or updating packages.
24+
25+
```bash
26+
# Install dependencies
27+
pnpm install
28+
29+
# Add a new dependency
30+
pnpm add <package-name>
31+
```
32+
33+
## Scripts
34+
35+
- **`pnpm build:dev`**: Creates a development build of the extension in the `dist/` directory.
36+
- **`pnpm test:run`**: Runs the unit tests using Vitest.
37+
- **`pnpm test:e2e`**: Runs end-to-end tests using Playwright.
38+
- **`pnpm lint`**: Lints the codebase with ESLint.
39+
- **`pnpm format`**: Formats the code with Prettier.
40+
- **`pnpm storybook`**: Starts the Storybook server for component development.
41+
42+
## Directory Structure
43+
44+
- **`src/background`**: Contains the code for the extension's background script.
45+
- **`service/`**: Houses various services that run in the background, like API calls and wallet logic. See [userWallet.ts](mdc:src/background/service/userWallet.ts).
46+
- **`utils/`**: Utilities for the background script.
47+
- **`src/ui`**: Contains all UI-related code.
48+
- **`components/`**: Shared, reusable React components. See [FRWProfile.tsx](mdc:src/ui/components/FRWProfile.tsx).
49+
- **`hooks/`**: Custom React hooks. See [use-account-hooks.ts](mdc:src/ui/hooks/use-account-hooks.ts).
50+
- **`views/`**: Components that represent full pages or views within the extension's UI. See [views/Locked/](mdc:src/ui/views/Locked/index.tsx).
51+
- **`utils/`**: Utility functions and context providers for the UI.
52+
- **`src/content-script`**: Code for content scripts that run in the context of web pages.
53+
- **`src/constant`**: Contains constant definitions.
54+
55+
## File Naming Conventions
56+
57+
To maintain consistency, please adhere to the following naming conventions for new files:
58+
59+
- **React Components**: `PascalCase.tsx`. (e.g., `MyComponent.tsx`)
60+
- **Hooks**: `use-kebab-case.ts`. (e.g., `use-my-hook.ts`)
61+
- **Other TypeScript Files (utils, services, etc.)**: `kebab-case.ts`. (e.g., `my-utility.ts`)
62+
63+
## Key Libraries & Concepts
64+
65+
- **Flow Interaction**: The [@onflow/fcl](mdc:https:/github.com/onflow/fcl-js) library is used for all interactions with the Flow blockchain.
66+
- **State Management**: The application uses a combination of React hooks, and data cache storage using chrome storage.
67+
- **Firebase**: Used for remote configuration. See [firebaseConfig.ts](mdc:src/background/utils/firebaseConfig.ts).
68+
- **Internationalization (i18n)**: Text is managed in [messages.json](mdc:src/messages.json) and loaded via `i18n.ts`.
69+
70+
## Data Caching
71+
72+
The extension uses a custom stale-while-revalidate caching system designed for the browser extension environment. This is necessary because the React application state is destroyed each time the popup closes. For a detailed explanation, see the [Cache Data Model Architecture](mdc:docs/cache-data-model.md) documentation.
73+
74+
### Core Concepts
75+
76+
- **Two Types of Storage**:
77+
1. **Session Storage (Cache Data)**: For temporary, refreshable data synced between the background script and the UI.
78+
2. **Local Storage (User Data)**: For persistent user settings.
79+
80+
- **Data Flow**:
81+
1. The UI requests data using a hook like `useCachedData`.
82+
2. If the data is stale or missing, a refresh is triggered in the background service worker.
83+
3. The background worker fetches new data, updates the cache using `setCachedData`, and the UI is automatically updated via storage listeners.
84+
85+
- **Key Principle**: Data is **only ever set or modified by the background script**. The UI reads data and requests refreshes.
86+
87+
### Key Files
88+
89+
- **`docs/cache-data-model.md`**: The primary documentation for this system.
90+
- **`src/shared/utils/cache-data-keys.ts`**: Defines keys and data types for temporary session data.
91+
- **`src/shared/utils/user-data-keys.ts`**: Defines keys and data types for persistent user data.
92+
- **`src/background/utils/data-cache.ts`**: Contains the core logic for the caching mechanism, including `registerRefreshListener` for single items and `registerBatchRefreshListener` for batching multiple requests.
93+
94+
### Implementation Pattern
95+
96+
To add new data to the cache:
97+
1. **Define Keys**: Add key generation functions and type definitions in `cache-data-keys.ts` or `user-data-keys.ts`.
98+
2. **Create Background Loader**: In a background service, use `registerRefreshListener` or `registerBatchRefreshListener` to define how data is fetched.
99+
3. **Use Frontend Hooks**: Access data in UI components with the `useCachedData` or `useUserData` hooks.

.cursorignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)

.env.example

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
### .env.dev
2+
13
# Google drive
24
GD_BACKUP_NAME=""
35
GD_FOLDER=""
@@ -28,8 +30,32 @@ DEV_PASSWORD=""
2830
MIXPANEL_TOKEN=""
2931

3032
# API URLs (optional - defaults exist in code)
31-
INITIAL_OPENAPI_URL=""
32-
WEB_NEXT_URL=""
33+
API_GO_SERVER_URL=""
34+
API_BASE_URL=""
3335

3436
# Scripts public key
3537
SCRIPTS_PUBLIC_KEY=""
38+
39+
############
40+
### .env.test
41+
42+
## Copy to .env.test and fill in the blanks
43+
44+
TEST_SENDER_NICKNAME=""
45+
TEST_SENDER_ADDR=""
46+
TEST_SENDER_EVM_ADDR=""
47+
48+
TEST_RECEIVER_NICKNAME=""
49+
TEST_RECEIVER_ADDR=""
50+
TEST_RECEIVER_EVM_ADDR=""
51+
52+
TEST_RECEIVER_METAMASK_EVM_ADDR=""
53+
54+
TEST_MULTI_ACCOUNT_TESTER_ADDR2=""
55+
TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR2=""
56+
57+
## NEVER share anything below here ##
58+
59+
TEST_PASSWORD=""
60+
TEST_SEED_PHRASE_SENDER=""
61+
TEST_SEED_PHRASE_RECEIVER=""

.github/workflows/build.yml

Lines changed: 92 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,24 @@ jobs:
88
runs-on: ubuntu-latest
99
outputs:
1010
env_name: ${{ steps.set_env.outputs.env_name }}
11+
is_beta: ${{ steps.set_env.outputs.is_beta }}
12+
beta_version: ${{ steps.set_env.outputs.beta_version }}
1113
steps:
1214
- id: set_env
1315
run: |
1416
ENV_NAME="${{ github.ref_type == 'tag' && 'production' || github.ref_name == 'master' && 'production' || github.ref_name == 'dev' && 'staging' || 'development' }}"
17+
IS_BETA="false"
18+
BETA_VERSION=""
19+
if [[ "${{ github.ref_type }}" == "tag" && "${{ github.ref_name }}" == *"beta"* ]]; then
20+
IS_BETA="true"
21+
BETA_VERSION="${{ github.ref_name }}"
22+
fi
1523
echo "env_name=$ENV_NAME" >> $GITHUB_OUTPUT
24+
echo "is_beta=$IS_BETA" >> $GITHUB_OUTPUT
25+
echo "beta_version=$BETA_VERSION" >> $GITHUB_OUTPUT
1626
echo "Environment name: $ENV_NAME"
27+
echo "Is beta: $IS_BETA"
28+
echo "Beta version: $BETA_VERSION"
1729
1830
build:
1931
needs: determine-env
@@ -33,7 +45,7 @@ jobs:
3345
- name: Get latest tag
3446
id: latest_tag
3547
run: |
36-
LATEST_TAG=$(git tag --sort=-committerdate | head -n 1 || echo "v0.0.0")
48+
LATEST_TAG=$(git tag --sort=-committerdate | grep -v "beta" | head -n 1 || echo "v0.0.0")
3749
echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV
3850
echo "Latest tag: $LATEST_TAG"
3951
@@ -57,6 +69,9 @@ jobs:
5769
run: pnpm install
5870

5971
- name: Create environment files
72+
env:
73+
IS_BETA: ${{ needs.determine-env.outputs.is_beta }}
74+
BETA_VERSION: ${{ needs.determine-env.outputs.beta_version }}
6075
run: |
6176
# Function to create environment file with given name
6277
create_env_file() {
@@ -70,6 +85,8 @@ jobs:
7085
DEPLOYMENT_ENV="${{ needs.determine-env.outputs.env_name }}"
7186
LATEST_TAG="${{ env.LATEST_TAG }}"
7287
REPO_URL="${{ env.REPO_URL }}"
88+
IS_BETA="${{ env.IS_BETA }}"
89+
BETA_VERSION="${{ env.BETA_VERSION }}"
7390
7491
# Google drive
7592
GD_BACKUP_NAME="${{ vars.GD_BACKUP_NAME }}"
@@ -98,25 +115,9 @@ jobs:
98115
OAUTH2_SCOPES="${{ vars.OAUTH2_SCOPES }}"
99116
WC_PROJECTID="${{ secrets.WC_PROJECTID }}"
100117
MIXPANEL_TOKEN="${{ secrets.MIXPANEL_TOKEN }}"
101-
TEST_PASSWORD="${{ secrets.TEST_PASSWORD }}"
102-
TEST_PK_P256="${{ secrets.TEST_PK_P256 }}"
103-
TEST_PK_SECP256K1="${{ secrets.TEST_PK_SECP256K1 }}"
104-
TEST_SEED_PHRASE_RECEIVER="${{ secrets.TEST_SEED_PHRASE_RECEIVER }}"
105-
TEST_SEED_PHRASE_SENDER="${{ secrets.TEST_SEED_PHRASE_SENDER }}"
106-
TEST_SENDER_ADDR="${{ secrets.TEST_SENDER_ADDR }}"
107-
TEST_SENDER_NICKNAME="${{ vars.TEST_SENDER_NICKNAME }}"
108-
TEST_RECEIVER_ADDR="${{ secrets.TEST_RECEIVER_ADDR }}"
109-
TEST_RECEIVER_NICKNAME="${{ vars.TEST_RECEIVER_NICKNAME }}"
110-
TEST_RECEIVER_EVM_ADDR="${{ secrets.TEST_RECEIVER_EVM_ADDR }}"
111-
TEST_RECEIVER_METAMASK_EVM_ADDR="${{ secrets.TEST_RECEIVER_METAMASK_EVM_ADDR }}"
112-
TEST_SEED_PHRASE_MULTI_ACCOUNT_TESTER="${{ secrets.TEST_SEED_PHRASE_MULTI_ACCOUNT_TESTER }}"
113-
TEST_MULTI_ACCOUNT_TESTER_ADDR1="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_ADDR1 }}"
114-
TEST_MULTI_ACCOUNT_TESTER_ADDR2="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_ADDR2 }}"
115-
TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR1="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR1 }}"
116-
TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR2="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR2 }}"
117-
TEST_MULTI_ACCOUNT_TESTER_NICKNAME="${{ vars.TEST_MULTI_ACCOUNT_TESTER_NICKNAME }}"
118118
SCRIPTS_PUBLIC_KEY="${{ vars.SCRIPTS_PUBLIC_KEY }}"
119119
BETA_MANIFEST_KEY="${{ secrets.BETA_MANIFEST_KEY }}"
120+
BETA_OAUTH2_CLIENT_ID="${{ secrets.BETA_OAUTH2_CLIENT_ID }}"
120121
EOF
121122
}
122123
@@ -164,11 +165,21 @@ jobs:
164165
group: tests-${{ github.workflow }}
165166
cancel-in-progress: false
166167
environment: ${{ needs.determine-env.outputs.env_name }}
168+
strategy:
169+
matrix:
170+
node-version: [22.x]
171+
167172
steps:
168173
- uses: actions/checkout@v4
169-
- uses: actions/setup-node@v4
174+
175+
- name: Install pnpm
176+
uses: pnpm/action-setup@v4
177+
178+
- name: Use Node.js ${{ matrix.node-version }}
179+
uses: actions/setup-node@v4
170180
with:
171-
node-version: lts/*
181+
node-version: ${{ matrix.node-version }}
182+
cache: 'pnpm'
172183

173184
- name: Download build artifacts
174185
uses: actions/download-artifact@v4
@@ -181,8 +192,6 @@ jobs:
181192
cat << EOF > .env.test
182193
# Test secrets
183194
TEST_PASSWORD="${{ secrets.TEST_PASSWORD }}"
184-
TEST_PK_P256="${{ secrets.TEST_PK_P256 }}"
185-
TEST_PK_SECP256K1="${{ secrets.TEST_PK_SECP256K1 }}"
186195
TEST_SEED_PHRASE_RECEIVER="${{ secrets.TEST_SEED_PHRASE_RECEIVER }}"
187196
TEST_SEED_PHRASE_SENDER="${{ secrets.TEST_SEED_PHRASE_SENDER }}"
188197
TEST_SENDER_ADDR="${{ secrets.TEST_SENDER_ADDR }}"
@@ -192,12 +201,8 @@ jobs:
192201
TEST_SENDER_EVM_ADDR="${{ secrets.TEST_SENDER_EVM_ADDR }}"
193202
TEST_RECEIVER_EVM_ADDR="${{ secrets.TEST_RECEIVER_EVM_ADDR }}"
194203
TEST_RECEIVER_METAMASK_EVM_ADDR="${{ secrets.TEST_RECEIVER_METAMASK_EVM_ADDR }}"
195-
TEST_SEED_PHRASE_MULTI_ACCOUNT_TESTER="${{ secrets.TEST_SEED_PHRASE_MULTI_ACCOUNT_TESTER }}"
196-
TEST_MULTI_ACCOUNT_TESTER_ADDR1="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_ADDR1 }}"
197204
TEST_MULTI_ACCOUNT_TESTER_ADDR2="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_ADDR2 }}"
198-
TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR1="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR1 }}"
199205
TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR2="${{ secrets.TEST_MULTI_ACCOUNT_TESTER_EVM_ADDR2 }}"
200-
TEST_MULTI_ACCOUNT_TESTER_NICKNAME="${{ vars.TEST_MULTI_ACCOUNT_TESTER_NICKNAME }}"
201206
EOF
202207
203208
- name: Install pnpm
@@ -211,42 +216,81 @@ jobs:
211216
env:
212217
CI: true
213218
HEADLESS: true
219+
- name: Sanitize Playwright Report
220+
if: always()
221+
run: pnpm tsx build/sanitize-playwright.ts
214222
- uses: actions/upload-artifact@v4
215223
if: always()
216224
with:
217225
name: playwright-report
218226
path: playwright-report/
219227
retention-days: 30
220228

221-
deploy-report:
222-
needs: [test]
229+
deploy-storybook-and-reports:
230+
needs: [test] # Depends on the Playwright test job
223231
runs-on: ubuntu-latest
224-
if: always()
225-
permissions:
226-
contents: write
227-
pages: write
228-
id-token: write
232+
if: always() # Run even if tests fail to publish what's available
233+
strategy:
234+
matrix:
235+
node-version: [22.x]
229236
steps:
230237
- uses: actions/checkout@v4
238+
with:
239+
fetch-depth: 0 # Fetch all history for tags
240+
241+
- name: Install pnpm
242+
uses: pnpm/action-setup@v4
243+
244+
- name: Use Node.js ${{ matrix.node-version }}
245+
uses: actions/setup-node@v4
246+
with:
247+
node-version: ${{ matrix.node-version }}
248+
cache: 'pnpm'
249+
250+
- name: Install dependencies
251+
run: pnpm install
252+
231253
- name: Download Playwright Report
232254
uses: actions/download-artifact@v4
233255
with:
234256
name: playwright-report
235-
path: temp-playwright-report
236-
- name: Move report to run-specific directory
237-
run: |
238-
mkdir -p playwright-report/runs/${{ github.run_id }}
239-
cp -r temp-playwright-report/* playwright-report/runs/${{ github.run_id }}/
240-
- name: Setup Pages
241-
uses: actions/configure-pages@v4
242-
- name: Upload artifact
243-
uses: actions/upload-pages-artifact@v3
257+
path: playwright-report/ # Download to this path
258+
259+
- name: Create .nojekyll file
260+
run: touch playwright-report/.nojekyll
261+
262+
- name: Deploy Playwright Report
263+
uses: peaceiris/actions-gh-pages@v4
264+
if: always() # Deploy even if tests fail
265+
with:
266+
github_token: ${{ secrets.GITHUB_TOKEN }}
267+
publish_dir: ./playwright-report
268+
destination_dir: reports/run-${{ github.run_id }}
269+
keep_files: true
270+
271+
- name: Build Storybook
272+
run: pnpm build-storybook # Assumes output is storybook-static
273+
274+
- name: Publish to Chromatic
275+
uses: chromaui/action@v1
244276
with:
245-
path: playwright-report
246-
- name: Deploy to GitHub Pages
247-
id: deployment
248-
uses: actions/deploy-pages@v4
249-
- name: Add Playwright Report Annotation
277+
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
278+
storybookBuildDir: storybook-static # Directory with Storybook and reports
279+
exitZeroOnChanges: true # Optional: useful for PR checks
280+
# workingDir: . # Not needed if storybookBuildDir is set correctly
281+
282+
- name: Add Job Summary
250283
if: always()
251284
run: |
252-
echo "::notice title=Playwright Report::View the Playwright report for this run at https://${GITHUB_REPOSITORY_OWNER}.github.io/${GITHUB_REPOSITORY#*/}/runs/${GITHUB_RUN_ID}/"
285+
echo "## 🎭 Playwright Test Results" >> $GITHUB_STEP_SUMMARY
286+
echo "" >> $GITHUB_STEP_SUMMARY
287+
echo "### 📊 Report Details" >> $GITHUB_STEP_SUMMARY
288+
echo "- **Run ID**: ${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY
289+
echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
290+
echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
291+
echo "- **Triggered by**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
292+
echo "" >> $GITHUB_STEP_SUMMARY
293+
echo "### 🔗 Links" >> $GITHUB_STEP_SUMMARY
294+
echo "- 📋 **[View Full Report](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/reports/run-${{ github.run_id }}/)**" >> $GITHUB_STEP_SUMMARY
295+
echo "" >> $GITHUB_STEP_SUMMARY
296+
echo "> 💡 **Tip**: Click the report link above to view detailed test results, traces, and screenshots!" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)