Skip to content

Commit

Permalink
fix: wallet reset issue (#1700)
Browse files Browse the repository at this point in the history
- 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 <[email protected]>
  • Loading branch information
LuizAsFight and helciofranco authored Dec 12, 2024
1 parent 33f3d77 commit be181de
Show file tree
Hide file tree
Showing 38 changed files with 544 additions and 153 deletions.
5 changes: 5 additions & 0 deletions .changeset/grumpy-gorillas-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fuels-wallet": minor
---

feat: implemented recoverWallet method and in case of disaster recover it
5 changes: 5 additions & 0 deletions .changeset/kind-pumas-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fuels-wallet": minor
---

feat: synchronize db with chrome storage
5 changes: 5 additions & 0 deletions .changeset/ninety-pianos-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fuels-wallet": minor
---

feat: create new database and table (outside of react) to identify if only dexiedb database is breaking
5 changes: 5 additions & 0 deletions .changeset/strong-tips-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fuels-wallet": minor
---

chore: report to sentry when there's a recover happening
7 changes: 0 additions & 7 deletions .github/workflows/pr-tests-e2e-crx-lock.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ jobs:
- name: Generate .env
run: cp packages/app/.env.example packages/app/.env

- name: Build Application
run: pnpm build:app
env:
## increase node.js m memory limit for building
## with sourcemaps
NODE_OPTIONS: "--max-old-space-size=4096"

- uses: ./.github/actions/setup-playwright

- name: Run E2E Tests
Expand Down
7 changes: 0 additions & 7 deletions .github/workflows/pr-tests-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ jobs:
- name: Generate .env
run: cp packages/app/.env.example packages/app/.env

- name: Build Application
run: pnpm build:app
env:
## increase node.js m memory limit for building
## with sourcemaps
NODE_OPTIONS: "--max-old-space-size=4096"

- uses: ./.github/actions/setup-playwright

- name: Run E2E Tests
Expand Down
29 changes: 29 additions & 0 deletions packages/app/jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,35 @@ jest.mock('react-dom/test-utils', () => {
};
});

// Replace chromeStorage
jest.mock('./src/systems/Core/services/chromeStorage', () => {
return {
chromeStorage: {
accounts: {
get: jest.fn(),
getAll: jest.fn(),
set: jest.fn(),
remove: jest.fn(),
clear: jest.fn(),
},
networks: {
get: jest.fn(),
getAll: jest.fn(),
set: jest.fn(),
remove: jest.fn(),
clear: jest.fn(),
},
vaults: {
get: jest.fn(),
getAll: jest.fn(),
set: jest.fn(),
remove: jest.fn(),
clear: jest.fn(),
},
},
};
});

console.warn = jest.fn();

const noop = () => {};
Expand Down
1 change: 0 additions & 1 deletion packages/app/load.envs.cts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { readFileSync } from 'node:fs';
import path from 'node:path';
import { resolve } from 'node:path';
import { config } from 'dotenv';

Expand Down
3 changes: 0 additions & 3 deletions packages/app/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { join } from 'node:path';
// biome-ignore lint/style/useNodejsImportProtocol: <explanation>
import {
type PlaywrightTestConfig,
defineConfig,
devices,
} from '@playwright/test';
import './load.envs';
import './load.envs.cts';

const PORT = process.env.PORT;
Expand Down
7 changes: 2 additions & 5 deletions packages/app/playwright.crx-lock.config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// biome-ignore lint/style/useNodejsImportProtocol: <explanation>
import { join } from 'path';
import { defineConfig, devices } from '@playwright/test';
import { playwrightConfig } from './playwright.config';

const __dirname = new URL('.', import.meta.url).pathname;
import './load.envs.cts';

export default defineConfig({
...playwrightConfig,
testMatch: join(__dirname, './playwright/crx/lock.test.ts'),
testMatch: 'playwright/crx/lock.test.ts',
testIgnore: undefined,
projects: [
{
Expand Down
3 changes: 1 addition & 2 deletions packages/app/playwright/crx/crx.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { NetworkData, Account as WalletAccount } from '@fuel-wallet/types';
import { type Locator, type Page, expect } from '@playwright/test';
import { type Locator, expect } from '@playwright/test';

import {
delay,
Expand All @@ -10,7 +10,6 @@ import {
hasText,
reload,
seedWallet,
visit,
waitAriaLabel,
} from '../commons';
import {
Expand Down
36 changes: 22 additions & 14 deletions packages/app/playwright/crx/lock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ import { test } from './utils';
test.setTimeout(360_000);

test.describe('Lock FuelWallet after inactivity', () => {
test('If user opens popup it should force open a sign-up page', async ({
context,
extensionId,
}) => {
const popupPage = await context.newPage();
await popupPage.goto(`chrome-extension://${extensionId}/popup.html`);
const page = await context.waitForEvent('page', {
predicate: (page) => page.url().includes('sign-up'),
});
expect(page.url()).toContain('sign-up');
});

test('should lock the wallet after 1 minute of inactivity (config in .env file)', async ({
context,
baseURL,
Expand Down Expand Up @@ -50,19 +62,7 @@ test.describe('Lock FuelWallet after inactivity', () => {

await test.step('Create wallet', async () => {
const pages = context.pages();
let page = pages.find((page) => page.url().includes('sign-up'));

if (!page) {
page = await context.waitForEvent('page', {
predicate: (page) => page.url().includes('sign-up'),
timeout: 10000, // Adjust timeout as needed
});
}

if (!page) {
throw new Error('Sign-up page did not open');
}

const [page] = pages.filter((page) => page.url().includes('sign-up'));
await reload(page);
await getElementByText(page, /Create new wallet/i).click();

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

/** Account created */
await hasText(page, /Wallet created successfully/i, 0, 15000);

await page.close();
});

Expand All @@ -111,10 +112,17 @@ test.describe('Lock FuelWallet after inactivity', () => {
await getByAriaLabel(popupPage, 'Accounts').click();
await popupPage.waitForTimeout(65_000);
await hasText(popupPage, /Assets/i);

const pages = context.pages();
const walletPages = pages.filter((page) => {
return page.url().includes('chrome-extension://');
});
for (const page of walletPages) {
await page.close();
}
});

await test.step('Resume auto-lock timer after closing wallet', async () => {
await popupPage.close();
const page = await context.newPage();
await page.waitForTimeout(65_000);
await page.goto(`chrome-extension://${extensionId}/popup.html`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const BalanceAssets = ({
[balances]
);

if (isLoading) return <AssetList.Loading items={4} />;
if (isLoading || !balances) return <AssetList.Loading items={4} />;
const isEmpty = !balances || !balances.length;
if (isEmpty) return <AssetList.Empty {...emptyProps} />;
const balancesToShow = balances.filter(
Expand All @@ -40,6 +40,7 @@ export const BalanceAssets = ({
function toggle() {
setShowUnknown((s) => !s);
}

return (
<CardList>
{balancesToShow.map((balance) => {
Expand All @@ -49,7 +50,7 @@ export const BalanceAssets = ({

return (
<AssetItem
key={balance.asset?.name}
key={balance.assetId + balance.asset?.name}
fuelAsset={balance.asset}
amount={balance.amount}
onRemove={onRemove}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const FuelAddress = ({
css,
}: AddressProps) => {
const account = useMemo<string>(() => {
if (!address) return '';
if (isContract) return Address.fromDynamicInput(address).toB256();
return Address.fromDynamicInput(address).toString();
}, [isContract, address]);
Expand Down
7 changes: 2 additions & 5 deletions packages/app/src/systems/Account/events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@ import { Services } from '~/store';

export function accountEvents(store: Store) {
return {
reloadBalance() {
store.send(Services.accounts, { type: 'RELOAD_BALANCE' });
},
updateAccounts() {
store.send(Services.accounts, { type: 'REFRESH_ACCOUNTS' });
refreshAccounts(input?: { skipLoading?: boolean }) {
store.send(Services.accounts, { type: 'REFRESH_ACCOUNTS', input });
},
setCurrentAccount(account: Account) {
store.send(Services.accounts, {
Expand Down
4 changes: 1 addition & 3 deletions packages/app/src/systems/Account/hooks/useAccounts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ const selectors = {
};

const listenerAccountFetcher = () => {
store.send(Services.accounts, {
type: 'REFRESH_ACCOUNT',
});
store.refreshAccounts({ skipLoading: true });
};

export function useAccounts() {
Expand Down
Loading

0 comments on commit be181de

Please sign in to comment.