diff --git a/src/@types/global/index.d.ts b/src/@types/global/index.d.ts index 377e5ea0..020459ed 100644 --- a/src/@types/global/index.d.ts +++ b/src/@types/global/index.d.ts @@ -1,7 +1,5 @@ declare const __APP_TITLE__: string; declare const __ENV__: 'development' | 'production'; -declare const __POSTHOG_API_HOST__: string; -declare const __POSTHOG_PROJECT_ID__: string; declare const __PROVIDER_ID__: string; declare const __TARGET__: 'chrome' | 'edge' | 'firefox' | 'opera' | 'safari'; declare const __VERSION__: string; diff --git a/src/extension/features/accounts/thunks/addARC0200AssetHoldingsThunk.ts b/src/extension/features/accounts/thunks/addARC0200AssetHoldingsThunk.ts index f25db4f8..5e659b3d 100644 --- a/src/extension/features/accounts/thunks/addARC0200AssetHoldingsThunk.ts +++ b/src/extension/features/accounts/thunks/addARC0200AssetHoldingsThunk.ts @@ -128,7 +128,7 @@ const addARC0200AssetHoldingsThunk: AsyncThunk< ); // save the account to storage - await accountRepository.save([account]); + await accountRepository.saveMany([account]); return { account: { diff --git a/src/extension/features/accounts/thunks/addStandardAssetHoldingsThunk.ts b/src/extension/features/accounts/thunks/addStandardAssetHoldingsThunk.ts index c78c376c..03a1ac5d 100644 --- a/src/extension/features/accounts/thunks/addStandardAssetHoldingsThunk.ts +++ b/src/extension/features/accounts/thunks/addStandardAssetHoldingsThunk.ts @@ -252,7 +252,7 @@ const addStandardAssetHoldingsThunk: AsyncThunk< }); // save the account to storage - await accountRepository.save([account]); + await accountRepository.saveMany([account]); logger.debug( `${ThunkEnum.AddStandardAssetHoldings}: saved account "${account.id}" to storage` diff --git a/src/extension/features/accounts/thunks/removeARC0200AssetHoldingsThunk.ts b/src/extension/features/accounts/thunks/removeARC0200AssetHoldingsThunk.ts index c3f28a19..765e17ff 100644 --- a/src/extension/features/accounts/thunks/removeARC0200AssetHoldingsThunk.ts +++ b/src/extension/features/accounts/thunks/removeARC0200AssetHoldingsThunk.ts @@ -90,7 +90,7 @@ const removeARC0200AssetHoldingsThunk: AsyncThunk< ); // save the account to storage - await new AccountRepository().save([account]); + await new AccountRepository().saveMany([account]); return { account: { diff --git a/src/extension/features/accounts/thunks/removeStandardAssetHoldingsThunk.ts b/src/extension/features/accounts/thunks/removeStandardAssetHoldingsThunk.ts index 3a1ca874..986f6218 100644 --- a/src/extension/features/accounts/thunks/removeStandardAssetHoldingsThunk.ts +++ b/src/extension/features/accounts/thunks/removeStandardAssetHoldingsThunk.ts @@ -272,7 +272,7 @@ const removeStandardAssetHoldingsThunk: AsyncThunk< ); // save the account to storage - await new AccountRepository().save([account]); + await new AccountRepository().saveMany([account]); return { account: { diff --git a/src/extension/features/accounts/thunks/saveAccountNameThunk.ts b/src/extension/features/accounts/thunks/saveAccountNameThunk.ts index c06aaba2..f018c1b3 100644 --- a/src/extension/features/accounts/thunks/saveAccountNameThunk.ts +++ b/src/extension/features/accounts/thunks/saveAccountNameThunk.ts @@ -53,7 +53,7 @@ const saveAccountNameThunk: AsyncThunk< name, }; - await new AccountRepository().save([account]); + await new AccountRepository().saveMany([account]); return { ...account, diff --git a/src/extension/features/accounts/thunks/saveNewAccountsThunk.ts b/src/extension/features/accounts/thunks/saveNewAccountsThunk.ts index 282d0462..e9736062 100644 --- a/src/extension/features/accounts/thunks/saveNewAccountsThunk.ts +++ b/src/extension/features/accounts/thunks/saveNewAccountsThunk.ts @@ -103,7 +103,7 @@ const saveNewAccountsThunk: AsyncThunk< } // save the account to storage - await new AccountRepository().save(_accounts); + await new AccountRepository().saveMany(_accounts); logger.debug( `${ThunkEnum.SaveNewAccounts}: saved "${_accounts.length}" new accounts to storage` diff --git a/src/extension/features/accounts/thunks/saveNewWatchAccountThunk.ts b/src/extension/features/accounts/thunks/saveNewWatchAccountThunk.ts index ef1bf7e7..797d8834 100644 --- a/src/extension/features/accounts/thunks/saveNewWatchAccountThunk.ts +++ b/src/extension/features/accounts/thunks/saveNewWatchAccountThunk.ts @@ -90,7 +90,7 @@ const saveNewWatchAccountThunk: AsyncThunk< }); // save the account to storage - await accountRepository.save([account]); + await accountRepository.saveMany([account]); logger.debug( `${ThunkEnum.SaveNewWatchAccount}: saved watch account "${address}" to storage` diff --git a/src/extension/features/accounts/thunks/updateAccountsThunk.ts b/src/extension/features/accounts/thunks/updateAccountsThunk.ts index 0b8119a2..1e9338d6 100644 --- a/src/extension/features/accounts/thunks/updateAccountsThunk.ts +++ b/src/extension/features/accounts/thunks/updateAccountsThunk.ts @@ -199,7 +199,7 @@ const updateAccountsThunk: AsyncThunk< } // save accounts to storage - accounts = await new AccountRepository().save(accounts); + accounts = await new AccountRepository().saveMany(accounts); logger.debug( `${ThunkEnum.AddStandardAssetHoldings}: saved accounts [${accounts diff --git a/src/extension/features/registration/thunks/saveCredentialsThunk.ts b/src/extension/features/registration/thunks/saveCredentialsThunk.ts index 130477fd..9be3b066 100644 --- a/src/extension/features/registration/thunks/saveCredentialsThunk.ts +++ b/src/extension/features/registration/thunks/saveCredentialsThunk.ts @@ -119,7 +119,7 @@ const saveCredentialsThunk: AsyncThunk< ); // save the accounts to storage - await new AccountRepository().save(_accounts); + await new AccountRepository().saveMany(_accounts); logger.debug( `${ThunkEnum.SaveCredentials}: successfully saved ${_accounts.length} accounts to storage` diff --git a/src/extension/repositories/AccountRepository/AccountRepository.ts b/src/extension/repositories/AccountRepository/AccountRepository.ts index 474c6930..d3c6ee78 100644 --- a/src/extension/repositories/AccountRepository/AccountRepository.ts +++ b/src/extension/repositories/AccountRepository/AccountRepository.ts @@ -318,7 +318,7 @@ export default class AccountRepository extends BaseRepository { } /** - * Convenience function that saves accounts to local storage. Each network's account information is stored, but each + * Saves accounts to local storage. Each network's account information is stored, but each * network's account transactions are only stored, if the `options.saveTransactions` is set to true, but by default * no transaction data is saved. * @@ -329,33 +329,38 @@ export default class AccountRepository extends BaseRepository { * @public * @todo cache the first 100 transactions */ - public async save( + public async saveMany( accounts: IAccount[], { saveTransactions }: ISaveOptions = { saveTransactions: false } ): Promise { - await this._save( - accounts.reduce>( - (acc, account) => ({ - ...acc, - [this._createAccountItemKey(account.id)]: { - ...this._sanitize(account), - // only save transactions if explicitly allowed - // TODO: cache the first 100 - ...(saveTransactions && { - networkTransactions: networks.reduce( - (acc, { genesisHash }) => ({ - ...acc, - [convertGenesisHashToHex(genesisHash)]: - AccountRepository.initializeDefaultAccountTransactions(), - }), - {} - ), - }), - }, - }), - {} - ) - ); + const batches = this._itemize(accounts); + + // save accounts in batches + for (const batch of batches) { + await this._save( + batch.reduce>( + (acc, account) => ({ + ...acc, + [this._createAccountItemKey(account.id)]: { + ...this._sanitize(account), + // only save transactions if explicitly allowed + // TODO: cache the first 100 + ...(saveTransactions && { + networkTransactions: networks.reduce( + (acc, { genesisHash }) => ({ + ...acc, + [convertGenesisHashToHex(genesisHash)]: + AccountRepository.initializeDefaultAccountTransactions(), + }), + {} + ), + }), + }, + }), + {} + ) + ); + } return accounts; } diff --git a/src/extension/repositories/BaseRepository/BaseRepository.ts b/src/extension/repositories/BaseRepository/BaseRepository.ts index ec0e11d7..5bb3abe3 100644 --- a/src/extension/repositories/BaseRepository/BaseRepository.ts +++ b/src/extension/repositories/BaseRepository/BaseRepository.ts @@ -1,8 +1,9 @@ import { decode as decodeHex, encode as encodeHex } from '@stablelib/hex'; -import browser from 'webextension-polyfill'; +import browser, { Menus } from 'webextension-polyfill'; // types import type { TStorageItemTypes } from '@extension/types'; +import ItemType = Menus.ItemType; export default class BaseRepository { /** @@ -67,6 +68,23 @@ export default class BaseRepository { ); } + /** + * Convenience function that puts a list of items into batches. + * @param {Type} items - The items to put into batches. + * @param {number} batchSize - [optional] The batch size. Defaults to 5. + * @returns {Type[][]} The items in batches. + * @protected + */ + protected _itemize(items: Type[], batchSize: number = 5): Type[][] { + const batches: Type[][] = []; + + for (let i = 0; i < items.length; i += batchSize) { + batches.push(items.slice(i, i + batchSize)); + } + + return batches; + } + /** * Removes an item or a set of items from storage by their key(s). * @param {string | string[]} keys - a key or multiple keys diff --git a/src/extension/repositories/PrivateKeyRepository/PrivateKeyRepository.ts b/src/extension/repositories/PrivateKeyRepository/PrivateKeyRepository.ts index 00610c01..2be9fe4c 100644 --- a/src/extension/repositories/PrivateKeyRepository/PrivateKeyRepository.ts +++ b/src/extension/repositories/PrivateKeyRepository/PrivateKeyRepository.ts @@ -319,19 +319,23 @@ export default class PrivateKeyRepository extends BaseRepository { */ public async saveMany(items: IPrivateKey[]): Promise { const _items = items.map((value) => this._sanitize(value)); - - await this._save( - _items.reduce>( - (acc, currentValue) => ({ - ...acc, - [this._createItemKey(currentValue.publicKey)]: { - ...currentValue, - updatedAt: new Date().getTime(), - }, - }), - {} - ) - ); + const batches = this._itemize(items); + + // save in batches to avoid exceeding quota + for (const batch of batches) { + await this._save( + batch.reduce>( + (acc, currentValue) => ({ + ...acc, + [this._createItemKey(currentValue.publicKey)]: { + ...currentValue, + updatedAt: new Date().getTime(), + }, + }), + {} + ) + ); + } return _items; } diff --git a/webpack/utils/createCommonConfig.ts b/webpack/utils/createCommonConfig.ts index ea185164..ecfc08a0 100644 --- a/webpack/utils/createCommonConfig.ts +++ b/webpack/utils/createCommonConfig.ts @@ -1,5 +1,5 @@ -import { resolve } from 'path'; -import { Configuration } from 'webpack'; +import { resolve } from 'node:path'; +import type { Configuration } from 'webpack'; // constants import { SRC_PATH } from '../constants'; @@ -36,9 +36,11 @@ export default function createCommonConfig(): Configuration { ['@extension/fonts']: resolve(extensionPath, 'fonts'), ['@extension/hooks']: resolve(extensionPath, 'hooks'), ['@extension/images']: resolve(extensionPath, 'images'), + ['@extension/managers']: resolve(extensionPath, 'managers'), ['@extension/modals']: resolve(extensionPath, 'modals'), ['@extension/models']: resolve(extensionPath, 'models'), ['@extension/pages']: resolve(extensionPath, 'pages'), + ['@extension/repositories']: resolve(extensionPath, 'repositories'), ['@extension/routers']: resolve(extensionPath, 'routers'), ['@extension/selectors']: resolve(extensionPath, 'selectors'), ['@extension/services']: resolve(extensionPath, 'services'), @@ -53,7 +55,6 @@ export default function createCommonConfig(): Configuration { ['@external/types']: resolve(externalPath, 'types'), ['@external/utils']: resolve(externalPath, 'utils'), }, - extensions: ['.css', '.js', '.ts', '.tsx'], }, diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts index dfc5abcd..57186b71 100644 --- a/webpack/webpack.config.ts +++ b/webpack/webpack.config.ts @@ -1,7 +1,7 @@ import CopyPlugin from 'copy-webpack-plugin'; import { config } from 'dotenv'; import HtmlWebpackPlugin from 'html-webpack-plugin'; -import { resolve } from 'path'; +import { resolve } from 'node:path'; import { Configuration, DefinePlugin, RuleSetRule } from 'webpack'; import { Configuration as DevelopmentConfiguration } from 'webpack-dev-server'; import { merge } from 'webpack-merge';