Skip to content

Commit be181de

Browse files
fix: wallet reset issue (#1700)
- Closes FE-1106 Implement mechanism for backup accounts and recover in case of disaster in db (all data lost) - synchronize db with chrome storage - implemented recoverWallet method - in case of disaster recover it - simplified accountMachine - create new database and table (outside of react) to identify if only dexiedb database is breaking - report to sentry when there's a recover happening - remove `shouldRecoverWelcomeFromError` logic --------- Co-authored-by: Hélcio Franco <github@helciofranco.com>
1 parent 33f3d77 commit be181de

38 files changed

+544
-153
lines changed

.changeset/grumpy-gorillas-drive.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"fuels-wallet": minor
3+
---
4+
5+
feat: implemented recoverWallet method and in case of disaster recover it

.changeset/kind-pumas-tie.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"fuels-wallet": minor
3+
---
4+
5+
feat: synchronize db with chrome storage

.changeset/ninety-pianos-bake.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"fuels-wallet": minor
3+
---
4+
5+
feat: create new database and table (outside of react) to identify if only dexiedb database is breaking

.changeset/strong-tips-pretend.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"fuels-wallet": minor
3+
---
4+
5+
chore: report to sentry when there's a recover happening

.github/workflows/pr-tests-e2e-crx-lock.yml

-7
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ jobs:
3131
- name: Generate .env
3232
run: cp packages/app/.env.example packages/app/.env
3333

34-
- name: Build Application
35-
run: pnpm build:app
36-
env:
37-
## increase node.js m memory limit for building
38-
## with sourcemaps
39-
NODE_OPTIONS: "--max-old-space-size=4096"
40-
4134
- uses: ./.github/actions/setup-playwright
4235

4336
- name: Run E2E Tests

.github/workflows/pr-tests-e2e.yml

-7
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ jobs:
3131
- name: Generate .env
3232
run: cp packages/app/.env.example packages/app/.env
3333

34-
- name: Build Application
35-
run: pnpm build:app
36-
env:
37-
## increase node.js m memory limit for building
38-
## with sourcemaps
39-
NODE_OPTIONS: "--max-old-space-size=4096"
40-
4134
- uses: ./.github/actions/setup-playwright
4235

4336
- name: Run E2E Tests

packages/app/jest.setup.ts

+29
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,35 @@ jest.mock('react-dom/test-utils', () => {
3030
};
3131
});
3232

33+
// Replace chromeStorage
34+
jest.mock('./src/systems/Core/services/chromeStorage', () => {
35+
return {
36+
chromeStorage: {
37+
accounts: {
38+
get: jest.fn(),
39+
getAll: jest.fn(),
40+
set: jest.fn(),
41+
remove: jest.fn(),
42+
clear: jest.fn(),
43+
},
44+
networks: {
45+
get: jest.fn(),
46+
getAll: jest.fn(),
47+
set: jest.fn(),
48+
remove: jest.fn(),
49+
clear: jest.fn(),
50+
},
51+
vaults: {
52+
get: jest.fn(),
53+
getAll: jest.fn(),
54+
set: jest.fn(),
55+
remove: jest.fn(),
56+
clear: jest.fn(),
57+
},
58+
},
59+
};
60+
});
61+
3362
console.warn = jest.fn();
3463

3564
const noop = () => {};

packages/app/load.envs.cts

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { readFileSync } from 'node:fs';
2-
import path from 'node:path';
32
import { resolve } from 'node:path';
43
import { config } from 'dotenv';
54

packages/app/playwright.config.ts

-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import { join } from 'node:path';
2-
// biome-ignore lint/style/useNodejsImportProtocol: <explanation>
31
import {
42
type PlaywrightTestConfig,
53
defineConfig,
64
devices,
75
} from '@playwright/test';
8-
import './load.envs';
96
import './load.envs.cts';
107

118
const PORT = process.env.PORT;

packages/app/playwright.crx-lock.config.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
// biome-ignore lint/style/useNodejsImportProtocol: <explanation>
2-
import { join } from 'path';
31
import { defineConfig, devices } from '@playwright/test';
42
import { playwrightConfig } from './playwright.config';
5-
6-
const __dirname = new URL('.', import.meta.url).pathname;
3+
import './load.envs.cts';
74

85
export default defineConfig({
96
...playwrightConfig,
10-
testMatch: join(__dirname, './playwright/crx/lock.test.ts'),
7+
testMatch: 'playwright/crx/lock.test.ts',
118
testIgnore: undefined,
129
projects: [
1310
{

packages/app/playwright/crx/crx.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { NetworkData, Account as WalletAccount } from '@fuel-wallet/types';
2-
import { type Locator, type Page, expect } from '@playwright/test';
2+
import { type Locator, expect } from '@playwright/test';
33

44
import {
55
delay,
@@ -10,7 +10,6 @@ import {
1010
hasText,
1111
reload,
1212
seedWallet,
13-
visit,
1413
waitAriaLabel,
1514
} from '../commons';
1615
import {

packages/app/playwright/crx/lock.test.ts

+22-14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ import { test } from './utils';
1818
test.setTimeout(360_000);
1919

2020
test.describe('Lock FuelWallet after inactivity', () => {
21+
test('If user opens popup it should force open a sign-up page', async ({
22+
context,
23+
extensionId,
24+
}) => {
25+
const popupPage = await context.newPage();
26+
await popupPage.goto(`chrome-extension://${extensionId}/popup.html`);
27+
const page = await context.waitForEvent('page', {
28+
predicate: (page) => page.url().includes('sign-up'),
29+
});
30+
expect(page.url()).toContain('sign-up');
31+
});
32+
2133
test('should lock the wallet after 1 minute of inactivity (config in .env file)', async ({
2234
context,
2335
baseURL,
@@ -50,19 +62,7 @@ test.describe('Lock FuelWallet after inactivity', () => {
5062

5163
await test.step('Create wallet', async () => {
5264
const pages = context.pages();
53-
let page = pages.find((page) => page.url().includes('sign-up'));
54-
55-
if (!page) {
56-
page = await context.waitForEvent('page', {
57-
predicate: (page) => page.url().includes('sign-up'),
58-
timeout: 10000, // Adjust timeout as needed
59-
});
60-
}
61-
62-
if (!page) {
63-
throw new Error('Sign-up page did not open');
64-
}
65-
65+
const [page] = pages.filter((page) => page.url().includes('sign-up'));
6666
await reload(page);
6767
await getElementByText(page, /Create new wallet/i).click();
6868

@@ -97,6 +97,7 @@ test.describe('Lock FuelWallet after inactivity', () => {
9797

9898
/** Account created */
9999
await hasText(page, /Wallet created successfully/i, 0, 15000);
100+
100101
await page.close();
101102
});
102103

@@ -111,10 +112,17 @@ test.describe('Lock FuelWallet after inactivity', () => {
111112
await getByAriaLabel(popupPage, 'Accounts').click();
112113
await popupPage.waitForTimeout(65_000);
113114
await hasText(popupPage, /Assets/i);
115+
116+
const pages = context.pages();
117+
const walletPages = pages.filter((page) => {
118+
return page.url().includes('chrome-extension://');
119+
});
120+
for (const page of walletPages) {
121+
await page.close();
122+
}
114123
});
115124

116125
await test.step('Resume auto-lock timer after closing wallet', async () => {
117-
await popupPage.close();
118126
const page = await context.newPage();
119127
await page.waitForTimeout(65_000);
120128
await page.goto(`chrome-extension://${extensionId}/popup.html`);

packages/app/src/systems/Account/components/BalanceAssets/BalanceAssets.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export const BalanceAssets = ({
2929
[balances]
3030
);
3131

32-
if (isLoading) return <AssetList.Loading items={4} />;
32+
if (isLoading || !balances) return <AssetList.Loading items={4} />;
3333
const isEmpty = !balances || !balances.length;
3434
if (isEmpty) return <AssetList.Empty {...emptyProps} />;
3535
const balancesToShow = balances.filter(
@@ -40,6 +40,7 @@ export const BalanceAssets = ({
4040
function toggle() {
4141
setShowUnknown((s) => !s);
4242
}
43+
4344
return (
4445
<CardList>
4546
{balancesToShow.map((balance) => {
@@ -49,7 +50,7 @@ export const BalanceAssets = ({
4950

5051
return (
5152
<AssetItem
52-
key={balance.asset?.name}
53+
key={balance.assetId + balance.asset?.name}
5354
fuelAsset={balance.asset}
5455
amount={balance.amount}
5556
onRemove={onRemove}

packages/app/src/systems/Account/components/FuelAddress/FuelAddress.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const FuelAddress = ({
2525
css,
2626
}: AddressProps) => {
2727
const account = useMemo<string>(() => {
28+
if (!address) return '';
2829
if (isContract) return Address.fromDynamicInput(address).toB256();
2930
return Address.fromDynamicInput(address).toString();
3031
}, [isContract, address]);

packages/app/src/systems/Account/events.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ import { Services } from '~/store';
44

55
export function accountEvents(store: Store) {
66
return {
7-
reloadBalance() {
8-
store.send(Services.accounts, { type: 'RELOAD_BALANCE' });
9-
},
10-
updateAccounts() {
11-
store.send(Services.accounts, { type: 'REFRESH_ACCOUNTS' });
7+
refreshAccounts(input?: { skipLoading?: boolean }) {
8+
store.send(Services.accounts, { type: 'REFRESH_ACCOUNTS', input });
129
},
1310
setCurrentAccount(account: Account) {
1411
store.send(Services.accounts, {

packages/app/src/systems/Account/hooks/useAccounts.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ const selectors = {
4545
};
4646

4747
const listenerAccountFetcher = () => {
48-
store.send(Services.accounts, {
49-
type: 'REFRESH_ACCOUNT',
50-
});
48+
store.refreshAccounts({ skipLoading: true });
5149
};
5250

5351
export function useAccounts() {

0 commit comments

Comments
 (0)