mirror of
https://github.com/zhigang1992/wallet.git
synced 2026-05-01 06:02:23 +08:00
ci: improve set up, upgrades
This commit is contained in:
4
.github/workflows/build-extension.yml
vendored
4
.github/workflows/build-extension.yml
vendored
@@ -47,8 +47,6 @@ jobs:
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**/package.json') }}
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Install packages
|
||||
uses: ./.github/actions/provision
|
||||
@@ -83,8 +81,6 @@ jobs:
|
||||
|
||||
- name: Set Node Version
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Restore cache
|
||||
uses: actions/cache@v3
|
||||
|
||||
82
.github/workflows/code-checks.yml
vendored
82
.github/workflows/code-checks.yml
vendored
@@ -33,23 +33,15 @@ jobs:
|
||||
- name: File name checker
|
||||
run: yarn lint:filename
|
||||
|
||||
audit:
|
||||
lint-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Audit
|
||||
run: yarn audit-ci --high --skip-dev
|
||||
|
||||
typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
|
||||
- name: Typecheck
|
||||
run: yarn typecheck
|
||||
- name: Lint commit message
|
||||
uses: wagoid/commitlint-github-action@v4
|
||||
|
||||
lint-deps:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -60,27 +52,6 @@ jobs:
|
||||
- name: Lint dependency rules
|
||||
run: yarn lint:deps
|
||||
|
||||
locked-versions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
|
||||
- name: Check exact versions
|
||||
uses: ./.github/actions/check-version-lock
|
||||
|
||||
test-unit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Test
|
||||
run: yarn test:unit
|
||||
|
||||
lint-message-schema:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -112,7 +83,34 @@ jobs:
|
||||
|
||||
- run: yarn web-ext lint
|
||||
|
||||
build:
|
||||
locked-versions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
|
||||
- name: Check exact versions
|
||||
uses: ./.github/actions/check-version-lock
|
||||
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
|
||||
- name: Audit
|
||||
run: yarn audit-ci --high --skip-dev
|
||||
|
||||
typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
|
||||
- name: Typecheck
|
||||
run: yarn typecheck
|
||||
|
||||
test-unit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -121,6 +119,18 @@ jobs:
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Build extension
|
||||
- name: Test
|
||||
run: yarn test:unit
|
||||
|
||||
test-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/provision
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Package extension
|
||||
run: sh build-ext.sh
|
||||
shell: bash
|
||||
|
||||
13
.github/workflows/commit-lint.yml
vendored
13
.github/workflows/commit-lint.yml
vendored
@@ -1,13 +0,0 @@
|
||||
name: Commit lint
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
commitlint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: wagoid/commitlint-github-action@v4
|
||||
46
.github/workflows/integration-tests.yml
vendored
46
.github/workflows/integration-tests.yml
vendored
@@ -10,12 +10,12 @@ jobs:
|
||||
directories:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
dir: ${{ steps.set-dirs.outputs.dir }}
|
||||
dir: ${{ steps.set-dirs.outputs.TEST_DIRECTORIES }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- id: set-dirs
|
||||
working-directory: ./tests-legacy/integration
|
||||
run: echo "::set-output name=dir::$( ls -d */ | xargs -0 | sed 's/\///' | jq -R -s -c 'split("\n")[:-2]')"
|
||||
run: echo "TEST_DIRECTORIES=$( ls -d */ | xargs -0 | sed 's/\///' | jq -R -s -c 'split("\n")[:-2]')" >> $GITHUB_OUTPUT
|
||||
|
||||
test-integration:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -28,33 +28,37 @@ jobs:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- run: echo ${{ fromJson(needs.directories.outputs.dir) }}
|
||||
- run: echo ${{ matrix.dir }}
|
||||
- name: Get installed Playwright version
|
||||
id: playwright-version
|
||||
run: echo "PLAYWRIGHT_VERSION=$(node -e "console.log(require('./package.json').devDependencies['@playwright/test'])")" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Cache node_modules
|
||||
id: cache-node-modules
|
||||
id: cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**/package.json') }}
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**/package.json') }}-${{ env.PLAYWRIGHT_VERSION }}
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Cache playwright
|
||||
id: cache-playwright-browsers
|
||||
- name: Install dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
run: yarn --frozen-lockfile
|
||||
shell: bash
|
||||
|
||||
- name: Cache playwright binaries
|
||||
uses: actions/cache@v3
|
||||
id: playwright-cache
|
||||
with:
|
||||
path: '~/.cache/ms-playwright'
|
||||
key: ${{ runner.os }}-playwright-browser
|
||||
path: ~/.cache/ms-playwright
|
||||
key: ${{ runner.os }}-playwright-cache-${{ env.PLAYWRIGHT_VERSION }}
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install Playwright browsers
|
||||
run: yarn playwright install chrome
|
||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||
|
||||
- name: Install packages
|
||||
uses: ./.github/actions/provision
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
|
||||
- name: Install Playwright dependencies
|
||||
run: npx playwright install --with-deps
|
||||
- name: Install Playwright deps
|
||||
run: yarn playwright install-deps
|
||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||
|
||||
- name: Build assets
|
||||
run: yarn build:test
|
||||
|
||||
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@@ -52,7 +52,7 @@ jobs:
|
||||
key: ${{ runner.os }}-playwright-cache-${{ env.PLAYWRIGHT_VERSION }}
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: yarn playwright install chrome
|
||||
run: yarn playwright install chrome chromium
|
||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||
|
||||
- name: Install Playwright deps
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
"@types/webpack": "5.28.1",
|
||||
"@types/zxcvbn": "4.4.1",
|
||||
"@typescript-eslint/parser": "5.59.6",
|
||||
"@vitest/coverage-istanbul": "0.31.0",
|
||||
"@vitest/coverage-istanbul": "0.31.1",
|
||||
"audit-ci": "6.6.1",
|
||||
"babel-loader": "9.1.2",
|
||||
"base64-loader": "1.0.0",
|
||||
@@ -317,7 +317,7 @@
|
||||
"ts-unused-exports": "7.0.3",
|
||||
"tsconfig-paths-webpack-plugin": "4.0.1",
|
||||
"typescript": "5.0.4",
|
||||
"vitest": "0.31.0",
|
||||
"vitest": "0.31.1",
|
||||
"vm-browserify": "1.1.2",
|
||||
"web-ext": "7.4.0",
|
||||
"web-ext-submit": "7.4.0",
|
||||
|
||||
@@ -32,7 +32,7 @@ const contentSecurityPolicyEnvironment = {
|
||||
development:
|
||||
"script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; frame-src 'none'; frame-ancestors 'none';",
|
||||
production:
|
||||
"default-src 'none'; connect-src *; style-src 'unsafe-inline'; img-src 'self' https:; script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-src 'none'; frame-ancestors 'none';",
|
||||
"default-src 'none'; connect-src *; style-src 'unsafe-inline'; img-src 'self' data: https:; script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-src 'none'; frame-ancestors 'none';",
|
||||
};
|
||||
|
||||
const defaultIconEnvironment = {
|
||||
@@ -42,18 +42,9 @@ const defaultIconEnvironment = {
|
||||
|
||||
const browserSpecificConfig = {
|
||||
firefox: {
|
||||
manifest_version: 2,
|
||||
permissions: ['contextMenus', 'storage', '*://*/*'],
|
||||
background: {
|
||||
page: 'background.js',
|
||||
scripts: ['background.js'],
|
||||
},
|
||||
web_accessible_resources: ['inpage.js'],
|
||||
browser_action: {
|
||||
default_title: 'Stacks',
|
||||
default_popup: 'popup.html',
|
||||
default_icon: defaultIconEnvironment[NODE_ENV],
|
||||
},
|
||||
content_security_policy: contentSecurityPolicyEnvironment[NODE_ENV],
|
||||
browser_specific_settings: {
|
||||
gecko: {
|
||||
id: '{e22ae397-03d7-4622-bd8f-ecaca8c9b277}',
|
||||
@@ -61,21 +52,9 @@ const browserSpecificConfig = {
|
||||
},
|
||||
},
|
||||
chromium: {
|
||||
manifest_version: 3,
|
||||
host_permissions: ['*://*/*'],
|
||||
permissions: ['contextMenus', 'storage'],
|
||||
background: {
|
||||
service_worker: 'background.js',
|
||||
},
|
||||
web_accessible_resources: [{ resources: ['inpage.js'], matches: ['*://*/*'] }],
|
||||
action: {
|
||||
default_title: 'Stacks',
|
||||
default_popup: 'popup.html',
|
||||
default_icon: defaultIconEnvironment[NODE_ENV],
|
||||
},
|
||||
content_security_policy: {
|
||||
extension_pages: contentSecurityPolicyEnvironment[NODE_ENV],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -83,9 +62,11 @@ const browserSpecificConfig = {
|
||||
* @type {Manifest} manifest
|
||||
*/
|
||||
const manifest = {
|
||||
manifest_version: 3,
|
||||
author: 'Hiro PBC',
|
||||
description:
|
||||
'Hiro Wallet is a safe way to manage your STX, sign into apps, and protect your funds while interacting with Clarity smart contracts.',
|
||||
permissions: ['contextMenus', 'storage'],
|
||||
commands: {
|
||||
_execute_browser_action: {
|
||||
suggested_key: {
|
||||
@@ -95,6 +76,16 @@ const manifest = {
|
||||
description: 'Opens Stacks App',
|
||||
},
|
||||
},
|
||||
host_permissions: ['*://*/*'],
|
||||
content_security_policy: {
|
||||
extension_pages: contentSecurityPolicyEnvironment[NODE_ENV],
|
||||
},
|
||||
web_accessible_resources: [{ resources: ['inpage.js'], matches: ['*://*/*'] }],
|
||||
action: {
|
||||
default_title: 'Stacks',
|
||||
default_popup: 'popup.html',
|
||||
default_icon: defaultIconEnvironment[NODE_ENV],
|
||||
},
|
||||
options_ui: {
|
||||
page: 'index.html',
|
||||
open_in_tab: true,
|
||||
@@ -116,12 +107,8 @@ const name = PREVIEW_RELEASE ? 'Hiro Wallet Preview' : 'Hiro Wallet';
|
||||
|
||||
const prodManifest = {
|
||||
name,
|
||||
// CSP loosened to allow `wasm-eval` per
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1268576
|
||||
content_security_policy:
|
||||
"default-src 'none'; connect-src *; style-src 'unsafe-inline'; img-src 'self' data: https:; script-src 'self' 'wasm-eval'; object-src 'none'; frame-src 'none'; frame-ancestors 'none';",
|
||||
icons: generateImageAssetUrlsWithSuffix(PREVIEW_RELEASE ? '-preview' : ''),
|
||||
browser_action: {
|
||||
action: {
|
||||
default_icon: `assets/connect-logo/Stacks128w${PREVIEW_RELEASE ? '-preview' : ''}.png`,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,9 +3,7 @@ import { useMemo } from 'react';
|
||||
import { generateSecretKey } from '@stacks/wallet-sdk';
|
||||
|
||||
import { logger } from '@shared/logger';
|
||||
import { InternalMethods } from '@shared/message-types';
|
||||
import { sendMessage } from '@shared/messages';
|
||||
import { clearChromeStorage } from '@shared/storage';
|
||||
import { clearChromeStorage } from '@shared/storage/redux-pesist';
|
||||
|
||||
import { queryClient } from '@app/common/persistence';
|
||||
import { partiallyClearLocalStorage } from '@app/common/store-utils';
|
||||
@@ -15,6 +13,7 @@ import { useBitcoinClient, useStacksClientAnchored } from '@app/store/common/api
|
||||
import { inMemoryKeyActions } from '@app/store/in-memory-key/in-memory-key.actions';
|
||||
import { keyActions } from '@app/store/keys/key.actions';
|
||||
import { useCurrentKeyDetails } from '@app/store/keys/key.selectors';
|
||||
import { clearWalletSession } from '@app/store/session-restore';
|
||||
|
||||
import { useAnalytics } from './analytics/use-analytics';
|
||||
|
||||
@@ -37,10 +36,6 @@ export function useKeyActions() {
|
||||
return;
|
||||
}
|
||||
const secretKey = generateSecretKey(256);
|
||||
sendMessage({
|
||||
method: InternalMethods.ShareInMemoryKeyToBackground,
|
||||
payload: { secretKey, keyId: 'default' },
|
||||
});
|
||||
return dispatch(inMemoryKeyActions.generateWalletKey(secretKey));
|
||||
},
|
||||
|
||||
@@ -57,7 +52,7 @@ export function useKeyActions() {
|
||||
},
|
||||
|
||||
async signOut() {
|
||||
sendMessage({ method: InternalMethods.RemoveInMemoryKeys, payload: undefined });
|
||||
await clearWalletSession();
|
||||
dispatch(keyActions.signOut());
|
||||
await clearChromeStorage();
|
||||
partiallyClearLocalStorage();
|
||||
@@ -65,8 +60,8 @@ export function useKeyActions() {
|
||||
queryClient.clear();
|
||||
},
|
||||
|
||||
lockWallet() {
|
||||
sendMessage({ method: InternalMethods.RemoveInMemoryKeys, payload: undefined });
|
||||
async lockWallet() {
|
||||
await clearWalletSession();
|
||||
return dispatch(inMemoryKeyActions.lockWallet());
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -3,7 +3,7 @@ import toast from 'react-hot-toast';
|
||||
import * as reduxPersist from 'redux-persist';
|
||||
|
||||
import { getLogsFromBrowserStorage } from '@shared/logger-storage';
|
||||
import { persistConfig } from '@shared/storage';
|
||||
import { persistConfig } from '@shared/storage/redux-pesist';
|
||||
|
||||
import { store } from './store';
|
||||
import { stxChainSlice } from './store/chains/stx-chain.slice';
|
||||
|
||||
@@ -37,7 +37,6 @@ export function Container() {
|
||||
<SwitchAccountDrawer />
|
||||
<SettingsDropdown />
|
||||
<Toaster position="bottom-center" toastOptions={{ style: { fontSize: '14px' } }} />
|
||||
|
||||
<ContainerLayout header={routeHeader}>
|
||||
<Outlet />
|
||||
</ContainerLayout>
|
||||
|
||||
@@ -3,8 +3,6 @@ import toast from 'react-hot-toast';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { InternalMethods } from '@shared/message-types';
|
||||
import { sendMessage } from '@shared/messages';
|
||||
import { RouteUrls } from '@shared/route-urls';
|
||||
|
||||
import { keySlice } from '@app/store/keys/key.slice';
|
||||
@@ -29,10 +27,6 @@ export function useTriggerLedgerDeviceRequestStacksKeys() {
|
||||
publicKeys,
|
||||
})
|
||||
);
|
||||
// It's possible a user may have first generated a key, then decided
|
||||
// they wanted to pair with Ledger. Here, we kill all in memory keys when
|
||||
// a new Ledger wallet is created
|
||||
sendMessage({ method: InternalMethods.RemoveInMemoryKeys, payload: undefined });
|
||||
navigate(RouteUrls.Home);
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { InternalMethods } from '@shared/message-types';
|
||||
import { initSentry } from '@shared/utils/analytics';
|
||||
import { warnUsersAboutDevToolsDangers } from '@shared/utils/dev-tools-warning-log';
|
||||
|
||||
import { persistAndRenderApp } from '@app/common/persistence';
|
||||
import { restoreWalletSession } from '@app/store/session-restore';
|
||||
|
||||
import { App } from './app';
|
||||
import { setDebugOnGlobal } from './debug';
|
||||
import { store } from './store';
|
||||
import { inMemoryKeyActions } from './store/in-memory-key/in-memory-key.actions';
|
||||
|
||||
initSentry();
|
||||
warnUsersAboutDevToolsDangers();
|
||||
@@ -23,19 +21,8 @@ declare global {
|
||||
|
||||
window.__APP_VERSION__ = VERSION;
|
||||
|
||||
async function checkForInMemoryKeys() {
|
||||
return new Promise(resolve =>
|
||||
chrome.runtime.sendMessage({ method: InternalMethods.RequestInMemoryKeys }, resp => {
|
||||
if (!resp) return resolve(true);
|
||||
if (Object.keys(resp).length === 0) return resolve(true);
|
||||
store.dispatch(inMemoryKeyActions.setKeysInMemory(resp));
|
||||
resolve(true);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async function renderApp() {
|
||||
await checkForInMemoryKeys();
|
||||
await restoreWalletSession();
|
||||
const container = document.getElementById('app');
|
||||
return createRoot(container!).render(<App />);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ export function AccountGate({ children }: AccountGateProps) {
|
||||
const currentKeyDetails = useCurrentKeyDetails();
|
||||
const currentInMemorySecretKey = useDefaultWalletSecretKey();
|
||||
|
||||
// console.log('currentKeyDetails', currentKeyDetails);
|
||||
// console.log('currentInMemorySecretKey', currentInMemorySecretKey);
|
||||
|
||||
if (currentKeyDetails?.type === 'ledger') return <>{children}</>;
|
||||
|
||||
if (shouldNavigateToOnboardingStartPage(currentKeyDetails))
|
||||
|
||||
@@ -3,8 +3,9 @@ import { keyActions } from '@app/store/keys/key.actions';
|
||||
|
||||
export function useOnSignOut(handler: () => void) {
|
||||
useOnMount(() => {
|
||||
chrome.runtime.onMessage.addListener(message => {
|
||||
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
||||
if (message?.method === keyActions.signOut.type) handler();
|
||||
sendResponse();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,12 +11,17 @@ export function useOnOriginTabClose(handler: () => void) {
|
||||
const analytics = useAnalytics();
|
||||
|
||||
useEffect(() => {
|
||||
const messageHandler = (message: BackgroundMessages) => {
|
||||
const messageHandler = (
|
||||
message: BackgroundMessages,
|
||||
_sender: chrome.runtime.MessageSender,
|
||||
sendResponse: () => void
|
||||
) => {
|
||||
if (message.method !== InternalMethods.OriginatingTabClosed) return;
|
||||
if (message.payload.tabId === tabId) {
|
||||
handler();
|
||||
void analytics.track('requesting_origin_tab_closed_with_pending_action');
|
||||
}
|
||||
sendResponse();
|
||||
};
|
||||
|
||||
chrome.runtime.onMessage.addListener(messageHandler);
|
||||
|
||||
@@ -3,8 +3,9 @@ import { inMemoryKeyActions } from '@app/store/in-memory-key/in-memory-key.actio
|
||||
|
||||
export function useOnWalletLock(handler: () => void) {
|
||||
useOnMount(() => {
|
||||
chrome.runtime.onMessage.addListener(message => {
|
||||
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
||||
if (message?.method === inMemoryKeyActions.lockWallet.type) handler();
|
||||
sendResponse();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { selectCurrentAccountIndex } from '../keys/key.selectors';
|
||||
|
||||
// This is only used when there is a pending transaction request and
|
||||
// the user switches accounts during the signing process
|
||||
export const hasSwitchedAccountsState = atom<boolean>(false);
|
||||
export const hasSwitchedAccountsState = atom(false);
|
||||
|
||||
const hasCreatedAccountState = atom<boolean>(false);
|
||||
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
import { Wallet } from '@stacks/wallet-sdk';
|
||||
import memoize from 'promise-memoize';
|
||||
|
||||
import { deriveStacksAccounts } from '@shared/crypto/stacks/derive-stacks-accounts';
|
||||
import { InternalMethods } from '@shared/message-types';
|
||||
import { RequestDerivedStxAccounts } from '@shared/messages';
|
||||
|
||||
import { delay } from '@app/common/utils';
|
||||
import { RootState } from '@app/store';
|
||||
|
||||
export const selectStacksChain = (state: RootState) => state.chains.stx;
|
||||
|
||||
export const deriveWalletWithAccounts = memoize(
|
||||
const requestDerivedStacksAccountFromBackground = memoize(async () => {
|
||||
async (secretKey: string, highestAccountIndex: number): Promise<Wallet> => {
|
||||
const message: RequestDerivedStxAccounts = {
|
||||
method: InternalMethods.RequestDerivedStxAccounts,
|
||||
payload: { secretKey, highestAccountIndex },
|
||||
};
|
||||
return new Promise(resolve => chrome.runtime.sendMessage(message, resp => resolve(resp)));
|
||||
}
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export async function deriveWalletWithAccounts(secretKey: string, highestAccountIndex: number) {
|
||||
const cachedResult = await Promise.race([
|
||||
requestDerivedStacksAccountFromBackground(),
|
||||
delay(1000),
|
||||
]);
|
||||
if (cachedResult) return cachedResult as Wallet;
|
||||
return deriveStacksAccounts(secretKey, highestAccountIndex);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { PersistPartial } from 'redux-persist/es/persistReducer';
|
||||
|
||||
import { IS_DEV_ENV } from '@shared/environment';
|
||||
import { persistConfig } from '@shared/storage';
|
||||
import { persistConfig } from '@shared/storage/redux-pesist';
|
||||
|
||||
import { analyticsSlice } from './analytics/analytics.slice';
|
||||
import { appPermissionsSlice } from './app-permissions/app-permissions.slice';
|
||||
|
||||
@@ -2,8 +2,6 @@ import { AddressVersion } from '@stacks/transactions';
|
||||
|
||||
import { decryptMnemonic, encryptMnemonic } from '@shared/crypto/mnemonic-encryption';
|
||||
import { logger } from '@shared/logger';
|
||||
import { InternalMethods } from '@shared/message-types';
|
||||
import { sendMessage } from '@shared/messages';
|
||||
|
||||
import { recurseAccountsForActivity } from '@app/common/account-restoration/account-restore';
|
||||
import { checkForLegacyGaiaConfigWithKnownGeneratedAccountIndex } from '@app/common/account-restoration/legacy-gaia-config-lookup';
|
||||
@@ -11,6 +9,7 @@ import { BitcoinClient } from '@app/query/bitcoin/bitcoin-client';
|
||||
import { fetchNamesForAddress } from '@app/query/stacks/bns/bns.utils';
|
||||
import { StacksClient } from '@app/query/stacks/stacks-client';
|
||||
import { AppThunk } from '@app/store';
|
||||
import { initalizeWalletSession } from '@app/store/session-restore';
|
||||
|
||||
import { getNativeSegwitMainnetAddressFromMnemonic } from '../accounts/blockchain/bitcoin/bitcoin-keychain';
|
||||
import { getStacksAddressByIndex } from '../accounts/blockchain/stacks/stacks-keychain';
|
||||
@@ -30,7 +29,13 @@ function setWalletEncryptionPassword(args: {
|
||||
return async (dispatch, getState) => {
|
||||
const secretKey = selectDefaultWalletKey(getState());
|
||||
if (!secretKey) throw new Error('Cannot generate wallet without first having generated a key');
|
||||
const { encryptedSecretKey, salt } = await encryptMnemonic({ secretKey, password });
|
||||
|
||||
const { encryptedSecretKey, salt, encryptionKey } = await encryptMnemonic({
|
||||
secretKey,
|
||||
password,
|
||||
});
|
||||
|
||||
await initalizeWalletSession(encryptionKey, secretKey);
|
||||
|
||||
const legacyAccountActivityLookup =
|
||||
await checkForLegacyGaiaConfigWithKnownGeneratedAccountIndex(secretKey);
|
||||
@@ -76,12 +81,6 @@ function setWalletEncryptionPassword(args: {
|
||||
dispatch(stxChainSlice.actions.restoreAccountIndex(recursiveActivityIndex));
|
||||
});
|
||||
|
||||
sendMessage({
|
||||
method: InternalMethods.ShareInMemoryKeyToBackground,
|
||||
payload: { secretKey, keyId: defaultKeyId },
|
||||
});
|
||||
|
||||
dispatch(inMemoryKeySlice.actions.setKeysInMemory({ default: secretKey }));
|
||||
dispatch(
|
||||
keySlice.actions.createStacksSoftwareWalletComplete({
|
||||
type: 'software',
|
||||
@@ -100,11 +99,9 @@ function unlockWalletAction(password: string): AppThunk {
|
||||
const currentKey = selectCurrentKey(getState());
|
||||
if (!currentKey) return;
|
||||
if (currentKey.type !== 'software') return;
|
||||
const { secretKey } = await decryptMnemonic({ password, ...currentKey });
|
||||
sendMessage({
|
||||
method: InternalMethods.ShareInMemoryKeyToBackground,
|
||||
payload: { secretKey: secretKey, keyId: defaultKeyId },
|
||||
});
|
||||
const { secretKey, encryptionKey } = await decryptMnemonic({ password, ...currentKey });
|
||||
|
||||
await initalizeWalletSession(encryptionKey, secretKey);
|
||||
dispatch(inMemoryKeySlice.actions.setKeysInMemory({ default: secretKey }));
|
||||
};
|
||||
}
|
||||
|
||||
72
src/app/store/session-restore.ts
Normal file
72
src/app/store/session-restore.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { decrypt } from '@stacks/wallet-sdk';
|
||||
|
||||
import { InternalMethods } from '@shared/message-types';
|
||||
import { sendMessage } from '@shared/messages';
|
||||
import { whenBrowserRuntime } from '@shared/utils/get-browser-runtime';
|
||||
|
||||
import { store } from '@app/store';
|
||||
import { inMemoryKeyActions } from '@app/store/in-memory-key/in-memory-key.actions';
|
||||
import { selectCurrentKey } from '@app/store/keys/key.selectors';
|
||||
import { defaultKeyId } from '@app/store/keys/key.slice';
|
||||
|
||||
export async function initalizeWalletSession(encryptionKey: string, secretKey: string) {
|
||||
return await whenBrowserRuntime({
|
||||
async chromium() {
|
||||
return chrome.storage.session.set({ encryptionKey });
|
||||
},
|
||||
async firefox() {
|
||||
return sendMessage({
|
||||
method: InternalMethods.ShareInMemoryKeyToBackground,
|
||||
payload: { secretKey, keyId: defaultKeyId },
|
||||
});
|
||||
},
|
||||
})();
|
||||
}
|
||||
|
||||
export async function clearWalletSession() {
|
||||
return await whenBrowserRuntime({
|
||||
async chromium() {
|
||||
return chrome.storage.session.remove('encryptionKey');
|
||||
},
|
||||
async firefox() {
|
||||
return chrome.runtime.sendMessage({ method: InternalMethods.RemoveInMemoryKeys });
|
||||
},
|
||||
})();
|
||||
}
|
||||
|
||||
export async function restoreWalletSession() {
|
||||
return whenBrowserRuntime({
|
||||
async chromium() {
|
||||
const key = await chrome.storage.session.get(['encryptionKey']);
|
||||
if (!key.encryptionKey) return false;
|
||||
|
||||
try {
|
||||
const currentKey = selectCurrentKey(store.getState());
|
||||
|
||||
if (currentKey?.type === 'software') {
|
||||
const secretKey = await decrypt(currentKey.encryptedSecretKey, key.encryptionKey);
|
||||
store.dispatch(inMemoryKeyActions.setKeysInMemory({ default: secretKey }));
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
async firefox() {
|
||||
return checkForInMemoryKeys();
|
||||
},
|
||||
})();
|
||||
}
|
||||
|
||||
async function checkForInMemoryKeys() {
|
||||
return new Promise(resolve =>
|
||||
chrome.runtime.sendMessage({ method: InternalMethods.RequestInMemoryKeys }, resp => {
|
||||
if (!resp) resolve(false);
|
||||
if (Object.keys(resp).length === 0) return resolve(false);
|
||||
store.dispatch(inMemoryKeyActions.setKeysInMemory(resp));
|
||||
resolve(true);
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -21,10 +21,6 @@ initSentry();
|
||||
initContextMenuActions();
|
||||
warnUsersAboutDevToolsDangers();
|
||||
|
||||
const keepAlive = () => setInterval(async () => await chrome.runtime.getPlatformInfo(), 20_000);
|
||||
chrome.runtime.onStartup.addListener(keepAlive);
|
||||
keepAlive();
|
||||
|
||||
const IS_TEST_ENV = process.env.TEST_ENV === 'true';
|
||||
|
||||
chrome.runtime.onInstalled.addListener(async details => {
|
||||
@@ -69,34 +65,34 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
const storageArea = chrome.storage.local as chrome.storage.LocalStorageArea;
|
||||
// const storageArea = chrome.storage.local as chrome.storage.LocalStorageArea;
|
||||
|
||||
const testIntervalMs = 10000;
|
||||
const storageWaitTimeMs = 100;
|
||||
// const testIntervalMs = 10000;
|
||||
// const storageWaitTimeMs = 100;
|
||||
|
||||
// @see https://bugs.chromium.org/p/chromium/issues/detail?id=1316588
|
||||
async function hasChromiumIssue1316588() {
|
||||
return new Promise(resolve => {
|
||||
let dispatched = false;
|
||||
const testEventDispatching = () => {
|
||||
storageArea.onChanged.removeListener(testEventDispatching);
|
||||
dispatched = true;
|
||||
};
|
||||
storageArea.onChanged.addListener(testEventDispatching);
|
||||
void storageArea.set({ testEventDispatching: Math.random() });
|
||||
setTimeout(() => resolve(!dispatched), storageWaitTimeMs);
|
||||
});
|
||||
}
|
||||
// async function hasChromiumIssue1316588() {
|
||||
// return new Promise(resolve => {
|
||||
// let dispatched = false;
|
||||
// const testEventDispatching = () => {
|
||||
// storageArea.onChanged.removeListener(testEventDispatching);
|
||||
// dispatched = true;
|
||||
// };
|
||||
// storageArea.onChanged.addListener(testEventDispatching);
|
||||
// void storageArea.set({ testEventDispatching: Math.random() });
|
||||
// setTimeout(() => resolve(!dispatched), storageWaitTimeMs);
|
||||
// });
|
||||
// }
|
||||
|
||||
function fixChromiumIssue1316588() {
|
||||
void hasChromiumIssue1316588().then(hasIssue => {
|
||||
if (hasIssue) {
|
||||
chrome.runtime.reload();
|
||||
return;
|
||||
}
|
||||
// function fixChromiumIssue1316588() {
|
||||
// void hasChromiumIssue1316588().then(hasIssue => {
|
||||
// if (hasIssue) {
|
||||
// chrome.runtime.reload();
|
||||
// return;
|
||||
// }
|
||||
|
||||
setTimeout(fixChromiumIssue1316588, testIntervalMs);
|
||||
});
|
||||
}
|
||||
// setTimeout(fixChromiumIssue1316588, testIntervalMs);
|
||||
// });
|
||||
// }
|
||||
|
||||
fixChromiumIssue1316588();
|
||||
// fixChromiumIssue1316588();
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
// import { StacksMainnet } from '@stacks/network';
|
||||
import { generateNewAccount, generateWallet } from '@stacks/wallet-sdk';
|
||||
import memoize from 'promise-memoize';
|
||||
|
||||
import { deriveStacksAccountsMemoized } from '@shared/crypto/stacks/derive-stacks-accounts';
|
||||
import { logger } from '@shared/logger';
|
||||
import { InternalMethods } from '@shared/message-types';
|
||||
import { BackgroundMessages } from '@shared/messages';
|
||||
@@ -11,18 +8,6 @@ function validateMessagesAreFromExtension(sender: chrome.runtime.MessageSender)
|
||||
return sender.url?.startsWith(chrome.runtime.getURL(''));
|
||||
}
|
||||
|
||||
const deriveWalletWithAccounts = memoize(async (secretKey: string, highestAccountIndex: number) => {
|
||||
// Here we only want the resulting `Wallet` objects, but the API
|
||||
// requires a password (so it can also return an encrypted key)
|
||||
const wallet = await generateWallet({ secretKey, password: '' });
|
||||
let walWithAccounts = wallet;
|
||||
for (let i = 0; i < highestAccountIndex; i++) {
|
||||
walWithAccounts = generateNewAccount(walWithAccounts);
|
||||
}
|
||||
return walWithAccounts;
|
||||
});
|
||||
|
||||
// Persists keys in memory for the duration of the background scripts life
|
||||
const inMemoryKeys = new Map();
|
||||
|
||||
const inMemoryFormState = new Map<number, object>();
|
||||
@@ -35,17 +20,19 @@ export async function internalBackgroundMessageHandler(
|
||||
sender: chrome.runtime.MessageSender,
|
||||
sendResponse: (response?: any) => void
|
||||
) {
|
||||
// console.info('Internal msg', message, validateMessagesAreFromExtension(sender));
|
||||
if (!validateMessagesAreFromExtension(sender)) {
|
||||
logger.error('Error: Received background script msg from ' + sender.url);
|
||||
sendResponse();
|
||||
return;
|
||||
}
|
||||
// logger.debug('Internal message', message);
|
||||
logger.debug('Internal message', message);
|
||||
switch (message.method) {
|
||||
case InternalMethods.RequestDerivedStxAccounts: {
|
||||
const { secretKey, highestAccountIndex } = message.payload;
|
||||
const walletsWithAccounts = await deriveWalletWithAccounts(secretKey, highestAccountIndex);
|
||||
const walletsWithAccounts = await deriveStacksAccountsMemoized(
|
||||
secretKey,
|
||||
highestAccountIndex
|
||||
);
|
||||
sendResponse(walletsWithAccounts);
|
||||
break;
|
||||
}
|
||||
@@ -59,7 +46,6 @@ export async function internalBackgroundMessageHandler(
|
||||
|
||||
case InternalMethods.RequestInMemoryKeys: {
|
||||
sendResponse(Object.fromEntries(inMemoryKeys));
|
||||
sendResponse();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -71,11 +57,13 @@ export async function internalBackgroundMessageHandler(
|
||||
case InternalMethods.SetActiveFormState: {
|
||||
const { tabId, ...state } = message.payload;
|
||||
inMemoryFormState.set(tabId, state);
|
||||
sendResponse();
|
||||
break;
|
||||
}
|
||||
|
||||
case InternalMethods.ClearActiveFormState: {
|
||||
inMemoryFormState.delete(message.payload.tabId);
|
||||
sendResponse();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -85,7 +73,4 @@ export async function internalBackgroundMessageHandler(
|
||||
break;
|
||||
}
|
||||
}
|
||||
// As browser is instructed that, if there is a response it will be
|
||||
// asyncronous, we must always return a response, even if empty
|
||||
sendResponse();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { WorkerScript, createWorker } from '../workers';
|
||||
|
||||
const worker = createWorker(WorkerScript.DecryptionWorker);
|
||||
interface GenerateEncryptionKeyArgs {
|
||||
interface DeriveEncryptionKeyArgs {
|
||||
password: string;
|
||||
salt: string;
|
||||
}
|
||||
export async function generateEncryptionKey(args: GenerateEncryptionKeyArgs): Promise<string> {
|
||||
export async function deriveEncryptionKey(args: DeriveEncryptionKeyArgs): Promise<string> {
|
||||
return new Promise(resolve => {
|
||||
const handler = (e: MessageEvent<string>) => resolve(e.data);
|
||||
worker.addEventListener('message', handler);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { bytesToHex } from '@stacks/common';
|
||||
import { decrypt, encrypt } from '@stacks/wallet-sdk';
|
||||
|
||||
import { generateEncryptionKey } from './generate-encryption-key';
|
||||
import { deriveEncryptionKey } from './generate-encryption-key';
|
||||
import { generateRandomHexString } from './generate-random-hex';
|
||||
|
||||
interface EncryptMnemonicArgs {
|
||||
@@ -10,11 +10,12 @@ interface EncryptMnemonicArgs {
|
||||
}
|
||||
export async function encryptMnemonic({ secretKey, password }: EncryptMnemonicArgs) {
|
||||
const salt = generateRandomHexString();
|
||||
const argonHash = await generateEncryptionKey({ password, salt });
|
||||
const encryptedBuffer = await encrypt(secretKey, argonHash);
|
||||
const encryptionKey = await deriveEncryptionKey({ password, salt });
|
||||
const encryptedBuffer = await encrypt(secretKey, encryptionKey);
|
||||
return {
|
||||
salt,
|
||||
encryptedSecretKey: bytesToHex(encryptedBuffer),
|
||||
encryptionKey,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,14 +37,16 @@ export async function decryptMnemonic({
|
||||
encryptedSecretKey: string;
|
||||
salt: string;
|
||||
secretKey: string;
|
||||
encryptionKey: string;
|
||||
}> {
|
||||
if (salt) {
|
||||
const pw = await generateEncryptionKey({ password, salt });
|
||||
const secretKey = await decrypt(Buffer.from(encryptedSecretKey, 'hex'), pw);
|
||||
const encryptionKey = await deriveEncryptionKey({ password, salt });
|
||||
const secretKey = await decrypt(Buffer.from(encryptedSecretKey, 'hex'), encryptionKey);
|
||||
return {
|
||||
secretKey,
|
||||
encryptedSecretKey,
|
||||
salt,
|
||||
encryptionKey,
|
||||
};
|
||||
} else {
|
||||
// if there is no salt, decrypt the secret key, then re-encrypt with an argon2 hash
|
||||
@@ -53,6 +56,7 @@ export async function decryptMnemonic({
|
||||
secretKey,
|
||||
encryptedSecretKey: newEncryptedKey.encryptedSecretKey,
|
||||
salt: newEncryptedKey.salt,
|
||||
encryptionKey: newEncryptedKey.encryptedSecretKey,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
15
src/shared/crypto/stacks/derive-stacks-accounts.ts
Normal file
15
src/shared/crypto/stacks/derive-stacks-accounts.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { generateNewAccount, generateWallet } from '@stacks/wallet-sdk';
|
||||
import memoize from 'promise-memoize';
|
||||
|
||||
export async function deriveStacksAccounts(secretKey: string, highestAccountIndex: number) {
|
||||
// Here we only want the resulting `Wallet` objects, but the API
|
||||
// requires a password (so it can also return an encrypted key)
|
||||
const wallet = await generateWallet({ secretKey, password: '' });
|
||||
let walWithAccounts = wallet;
|
||||
for (let i = 0; i < highestAccountIndex; i++) {
|
||||
walWithAccounts = generateNewAccount(walWithAccounts);
|
||||
}
|
||||
return walWithAccounts;
|
||||
}
|
||||
|
||||
export const deriveStacksAccountsMemoized = memoize(deriveStacksAccounts);
|
||||
@@ -25,14 +25,14 @@ type ClearActiveFormState = BackgroundMessage<
|
||||
{ tabId: number }
|
||||
>;
|
||||
|
||||
type ShareInMemoryKeyToBackground = BackgroundMessage<
|
||||
type FirefoxShareInMemoryKeyToBackground = BackgroundMessage<
|
||||
InternalMethods.ShareInMemoryKeyToBackground,
|
||||
{ secretKey: string; keyId: string }
|
||||
>;
|
||||
|
||||
type RequestInMemoryKeys = BackgroundMessage<InternalMethods.RequestInMemoryKeys>;
|
||||
type FirefoxRequestInMemoryKeys = BackgroundMessage<InternalMethods.RequestInMemoryKeys>;
|
||||
|
||||
type RemoveInMemoryKeys = BackgroundMessage<InternalMethods.RemoveInMemoryKeys>;
|
||||
type FirefoxRemoveInMemoryKeys = BackgroundMessage<InternalMethods.RemoveInMemoryKeys>;
|
||||
|
||||
type OriginatingTabClosed = BackgroundMessage<
|
||||
InternalMethods.OriginatingTabClosed,
|
||||
@@ -44,9 +44,9 @@ export type BackgroundMessages =
|
||||
| GetActiveFormState
|
||||
| SetActiveFormState
|
||||
| ClearActiveFormState
|
||||
| ShareInMemoryKeyToBackground
|
||||
| RequestInMemoryKeys
|
||||
| RemoveInMemoryKeys
|
||||
| FirefoxShareInMemoryKeyToBackground
|
||||
| FirefoxRequestInMemoryKeys
|
||||
| FirefoxRemoveInMemoryKeys
|
||||
| OriginatingTabClosed;
|
||||
|
||||
export function sendMessage(message: BackgroundMessages) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { PersistConfig, createMigrate, getStoredState } from 'redux-persist';
|
||||
|
||||
import type { RootState } from '@app/store';
|
||||
|
||||
import { analytics } from './utils/analytics';
|
||||
import { analytics } from '../utils/analytics';
|
||||
|
||||
export async function clearChromeStorage(): Promise<void> {
|
||||
return new Promise(resolve => chrome.storage.local.clear(resolve));
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
SENTRY_DSN,
|
||||
WALLET_ENVIRONMENT,
|
||||
} from '@shared/environment';
|
||||
import { persistConfig } from '@shared/storage';
|
||||
import { persistConfig } from '@shared/storage/redux-pesist';
|
||||
|
||||
import type { RootState } from '@app/store';
|
||||
|
||||
|
||||
11
src/shared/utils/get-browser-runtime.ts
Normal file
11
src/shared/utils/get-browser-runtime.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
type BrowserRuntime = 'chromium' | 'firefox';
|
||||
|
||||
function getBrowserRuntime(): BrowserRuntime {
|
||||
return chrome.runtime.getURL('').startsWith('moz-extension://') ? 'firefox' : 'chromium';
|
||||
}
|
||||
|
||||
type WhenBrowserRuntimeMap<T> = Record<BrowserRuntime, T>;
|
||||
|
||||
export function whenBrowserRuntime<T>(runtimeMap: WhenBrowserRuntimeMap<T>) {
|
||||
return runtimeMap[getBrowserRuntime()];
|
||||
}
|
||||
@@ -121,7 +121,11 @@ describe(`Onboarding integration tests`, () => {
|
||||
await wallet.waitForHomePage();
|
||||
await wallet.waitForsuggestedStepsList();
|
||||
const stepsToStartBtns = await wallet.page.$$(wallet.$suggestedStepStartBtn);
|
||||
await stepsToStartBtns[1].click();
|
||||
const [newPage] = await Promise.all([
|
||||
browser.context.waitForEvent('page'),
|
||||
stepsToStartBtns[1].click(),
|
||||
]);
|
||||
await newPage.waitForLoadState();
|
||||
const stepsDone = await wallet.page.$$(wallet.$suggestedStepDoneBadge);
|
||||
expect(stepsDone.length).toEqual(2);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BrowserContext, Page } from '@playwright/test';
|
||||
import { OnboardingSelectors } from '@tests/selectors/onboarding.selectors';
|
||||
import { BrowserContext, Page } from 'playwright';
|
||||
|
||||
import { createTestSelector } from '../integration/utils';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Page } from '@playwright/test';
|
||||
import { FundPageSelectors } from '@tests-legacy/page-objects/fund.selectors';
|
||||
import { Page } from 'playwright';
|
||||
|
||||
import { createTestSelector } from '../integration/utils';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Page } from '@playwright/test';
|
||||
import { NetworkSelectors } from '@tests-legacy/integration/network.selectors';
|
||||
import { Page } from 'playwright';
|
||||
|
||||
import { createTestSelector } from '../integration/utils';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Page } from '@playwright/test';
|
||||
import { ProfileUpdatingSelectors } from '@tests-legacy/integration/profile/profile-updating.selector';
|
||||
import { Page } from 'playwright';
|
||||
|
||||
import { createTestSelector } from '../integration/utils';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Page } from '@playwright/test';
|
||||
import { SharedComponentsSelectors } from '@tests/selectors/shared-component.selectors';
|
||||
import { Page } from 'playwright';
|
||||
|
||||
import { createTestSelector } from '../integration/utils';
|
||||
import { TransactionSigningSelectors } from './transaction-signing.selectors';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Page } from '@playwright/test';
|
||||
import { SettingsSelectors } from '@tests-legacy/integration/settings.selectors';
|
||||
import { HomePageSelectorsLegacy } from '@tests-legacy/page-objects/home.selectors';
|
||||
import { HomePageSelectors } from '@tests/selectors/home.selectors';
|
||||
import { OnboardingSelectors } from '@tests/selectors/onboarding.selectors';
|
||||
import { SettingsMenuSelectors } from '@tests/selectors/settings.selectors';
|
||||
import { Page } from 'playwright';
|
||||
|
||||
import { RouteUrls } from '@shared/route-urls';
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Page } from '@playwright/test';
|
||||
import { setupMockApis } from '@tests/mocks/mock-apis';
|
||||
|
||||
// const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
|
||||
|
||||
export class GlobalPage {
|
||||
readonly page: Page;
|
||||
|
||||
@@ -17,6 +15,7 @@ export class GlobalPage {
|
||||
async setupAndUseApiCalls(extensionId: string) {
|
||||
await this.page.route(/.*/, route => route.continue());
|
||||
await setupMockApis(this.page);
|
||||
await this.page.waitForTimeout(600);
|
||||
await this.gotoNakedRoot(extensionId);
|
||||
// I've no idea why this delay is needed. Was required when switching to MV3. Without it,
|
||||
// this error is thrown. Let's try removing with later versions of Playwright.
|
||||
@@ -25,7 +24,6 @@ export class GlobalPage {
|
||||
// =========================== logs ===========================
|
||||
// navigating to "chrome-extension://bcokkkbghbnpbjpkoifjakaofdjfgeaj/index.html", waiting until "load"
|
||||
// ============================================================
|
||||
// await delay(600);
|
||||
// await this.page.goto(`chrome-extension://${extensionId}/index.html`);
|
||||
}
|
||||
|
||||
|
||||
90
yarn.lock
90
yarn.lock
@@ -5287,7 +5287,7 @@
|
||||
dependencies:
|
||||
"@types/chai" "*"
|
||||
|
||||
"@types/chai@*", "@types/chai@^4.3.4":
|
||||
"@types/chai@*", "@types/chai@^4.3.5":
|
||||
version "4.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b"
|
||||
integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==
|
||||
@@ -6370,10 +6370,10 @@
|
||||
"@typescript-eslint/types" "5.59.6"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@vitest/coverage-istanbul@0.31.0":
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/coverage-istanbul/-/coverage-istanbul-0.31.0.tgz#57d14c5d66685f9fe0d80e5884e940c0872a7fd6"
|
||||
integrity sha512-SaTI1PSpCRtBhJ5ihBx7Z+jgrFAQlDjuI4MFmKQ/HjyYWzEoaU+I062SquRrOLjJtVOHnwJdjVJXKi0dgFiR9Q==
|
||||
"@vitest/coverage-istanbul@0.31.1":
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/coverage-istanbul/-/coverage-istanbul-0.31.1.tgz#c9749bf404470c2b12dcb6ad851e89d27f88fc42"
|
||||
integrity sha512-wLVROukTxWflIub4QUT5TenA2zx2ypUjRp636yiMTidN5hvRhnUNEEkRavJMEpYuWYYMN23E7EmAxo/MzRRmIA==
|
||||
dependencies:
|
||||
istanbul-lib-coverage "^3.2.0"
|
||||
istanbul-lib-instrument "^5.2.1"
|
||||
@@ -6382,45 +6382,45 @@
|
||||
istanbul-reports "^3.1.5"
|
||||
test-exclude "^6.0.0"
|
||||
|
||||
"@vitest/expect@0.31.0":
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.31.0.tgz#37ab35d4f75c12826c204f2a0290e0c2e5ef1192"
|
||||
integrity sha512-Jlm8ZTyp6vMY9iz9Ny9a0BHnCG4fqBa8neCF6Pk/c/6vkUk49Ls6UBlgGAU82QnzzoaUs9E/mUhq/eq9uMOv/g==
|
||||
"@vitest/expect@0.31.1":
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.31.1.tgz#db8cb5a14a91167b948f377b9d29442229c73747"
|
||||
integrity sha512-BV1LyNvhnX+eNYzJxlHIGPWZpwJFZaCcOIzp2CNG0P+bbetenTupk6EO0LANm4QFt0TTit+yqx7Rxd1qxi/SQA==
|
||||
dependencies:
|
||||
"@vitest/spy" "0.31.0"
|
||||
"@vitest/utils" "0.31.0"
|
||||
"@vitest/spy" "0.31.1"
|
||||
"@vitest/utils" "0.31.1"
|
||||
chai "^4.3.7"
|
||||
|
||||
"@vitest/runner@0.31.0":
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-0.31.0.tgz#ca830405ae4c2744ae5fb7fbe85df81b56430ebc"
|
||||
integrity sha512-H1OE+Ly7JFeBwnpHTrKyCNm/oZgr+16N4qIlzzqSG/YRQDATBYmJb/KUn3GrZaiQQyL7GwpNHVZxSQd6juLCgw==
|
||||
"@vitest/runner@0.31.1":
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-0.31.1.tgz#fc06260d4824dde624abaeea1825d6a75bad4583"
|
||||
integrity sha512-imWuc82ngOtxdCUpXwtEzZIuc1KMr+VlQ3Ondph45VhWoQWit5yvG/fFcldbnCi8DUuFi+NmNx5ehMUw/cGLUw==
|
||||
dependencies:
|
||||
"@vitest/utils" "0.31.0"
|
||||
"@vitest/utils" "0.31.1"
|
||||
concordance "^5.0.4"
|
||||
p-limit "^4.0.0"
|
||||
pathe "^1.1.0"
|
||||
|
||||
"@vitest/snapshot@0.31.0":
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-0.31.0.tgz#f59c4bcf0d03f1f494ee09286965e60a1e0cab64"
|
||||
integrity sha512-5dTXhbHnyUMTMOujZPB0wjFjQ6q5x9c8TvAsSPUNKjp1tVU7i9pbqcKPqntyu2oXtmVxKbuHCqrOd+Ft60r4tg==
|
||||
"@vitest/snapshot@0.31.1":
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-0.31.1.tgz#7fc3f1e48f0c4313e6cb795c17a2c1aa909a7d64"
|
||||
integrity sha512-L3w5uU9bMe6asrNzJ8WZzN+jUTX4KSgCinEJPXyny0o90fG4FPQMV0OWsq7vrCWfQlAilMjDnOF9nP8lidsJ+g==
|
||||
dependencies:
|
||||
magic-string "^0.30.0"
|
||||
pathe "^1.1.0"
|
||||
pretty-format "^27.5.1"
|
||||
|
||||
"@vitest/spy@0.31.0":
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-0.31.0.tgz#98cb19046c0bd2673a73d6c90ee1533d1be82136"
|
||||
integrity sha512-IzCEQ85RN26GqjQNkYahgVLLkULOxOm5H/t364LG0JYb3Apg0PsYCHLBYGA006+SVRMWhQvHlBBCyuByAMFmkg==
|
||||
"@vitest/spy@0.31.1":
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-0.31.1.tgz#1c3b6a3eec4ce81b8889e19c7fac6a603b600b14"
|
||||
integrity sha512-1cTpt2m9mdo3hRLDyCG2hDQvRrePTDgEJBFQQNz1ydHHZy03EiA6EpFxY+7ODaY7vMRCie+WlFZBZ0/dQWyssQ==
|
||||
dependencies:
|
||||
tinyspy "^2.1.0"
|
||||
|
||||
"@vitest/utils@0.31.0":
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-0.31.0.tgz#d0aae17150b95ebf7afdf4e5db8952ac21610ffa"
|
||||
integrity sha512-kahaRyLX7GS1urekRXN2752X4gIgOGVX4Wo8eDUGUkTWlGpXzf5ZS6N9RUUS+Re3XEE8nVGqNyxkSxF5HXlGhQ==
|
||||
"@vitest/utils@0.31.1":
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-0.31.1.tgz#b810a458b37ef16931ab0d384ce79a9500f34e07"
|
||||
integrity sha512-yFyRD5ilwojsZfo3E0BnH72pSVSuLg2356cN1tCEe/0RtDzxTPYwOomIC+eQbot7m6DRy4tPZw+09mB7NkbMmA==
|
||||
dependencies:
|
||||
concordance "^5.0.4"
|
||||
loupe "^2.3.6"
|
||||
@@ -16868,7 +16868,7 @@ tiny-warning@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||
|
||||
tinybench@^2.4.0:
|
||||
tinybench@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.5.0.tgz#4711c99bbf6f3e986f67eb722fed9cddb3a68ba5"
|
||||
integrity sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==
|
||||
@@ -17488,10 +17488,10 @@ vinyl-buffer@^1.0.1:
|
||||
bl "^1.2.1"
|
||||
through2 "^2.0.3"
|
||||
|
||||
vite-node@0.31.0:
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.31.0.tgz#8794a98f21b0cf2394bfd2aaa5fc85d2c42be084"
|
||||
integrity sha512-8x1x1LNuPvE2vIvkSB7c1mApX5oqlgsxzHQesYF7l5n1gKrEmrClIiZuOFbFDQcjLsmcWSwwmrWrcGWm9Fxc/g==
|
||||
vite-node@0.31.1:
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.31.1.tgz#9fea18cbf9552ab262b969068249a8b8e7fb8b38"
|
||||
integrity sha512-BajE/IsNQ6JyizPzu9zRgHrBwczkAs0erQf/JRpgTIESpKvNj9/Gd0vxX905klLkb0I0SJVCKbdrl5c6FnqYKA==
|
||||
dependencies:
|
||||
cac "^6.7.14"
|
||||
debug "^4.3.4"
|
||||
@@ -17511,19 +17511,19 @@ vite-node@0.31.0:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vitest@0.31.0:
|
||||
version "0.31.0"
|
||||
resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.31.0.tgz#133e98f779aa81afbc7ee1fcb385a0c458b8c2c8"
|
||||
integrity sha512-JwWJS9p3GU9GxkG7eBSmr4Q4x4bvVBSswaCFf1PBNHiPx00obfhHRJfgHcnI0ffn+NMlIh9QGvG75FlaIBdKGA==
|
||||
vitest@0.31.1:
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.31.1.tgz#e3d1b68a44e76e24f142c1156fe9772ef603e52c"
|
||||
integrity sha512-/dOoOgzoFk/5pTvg1E65WVaobknWREN15+HF+0ucudo3dDG/vCZoXTQrjIfEaWvQXmqScwkRodrTbM/ScMpRcQ==
|
||||
dependencies:
|
||||
"@types/chai" "^4.3.4"
|
||||
"@types/chai" "^4.3.5"
|
||||
"@types/chai-subset" "^1.3.3"
|
||||
"@types/node" "*"
|
||||
"@vitest/expect" "0.31.0"
|
||||
"@vitest/runner" "0.31.0"
|
||||
"@vitest/snapshot" "0.31.0"
|
||||
"@vitest/spy" "0.31.0"
|
||||
"@vitest/utils" "0.31.0"
|
||||
"@vitest/expect" "0.31.1"
|
||||
"@vitest/runner" "0.31.1"
|
||||
"@vitest/snapshot" "0.31.1"
|
||||
"@vitest/spy" "0.31.1"
|
||||
"@vitest/utils" "0.31.1"
|
||||
acorn "^8.8.2"
|
||||
acorn-walk "^8.2.0"
|
||||
cac "^6.7.14"
|
||||
@@ -17536,10 +17536,10 @@ vitest@0.31.0:
|
||||
picocolors "^1.0.0"
|
||||
std-env "^3.3.2"
|
||||
strip-literal "^1.0.1"
|
||||
tinybench "^2.4.0"
|
||||
tinybench "^2.5.0"
|
||||
tinypool "^0.5.0"
|
||||
vite "^3.0.0 || ^4.0.0"
|
||||
vite-node "0.31.0"
|
||||
vite-node "0.31.1"
|
||||
why-is-node-running "^2.2.2"
|
||||
|
||||
vm-browserify@1.1.2:
|
||||
|
||||
Reference in New Issue
Block a user