From eaf8af3f3a86a2ec375a0ea8e409be29f4834808 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 18:59:48 +0300 Subject: [PATCH 1/9] fixed csl factory to not require early load --- packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js | 2 +- packages/yoroi-extension/chrome/extension/index.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js b/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js index 838e0a5f03..72121781f0 100644 --- a/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js +++ b/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js @@ -89,7 +89,7 @@ export default class AdaAddressesStore extends Store { apiKey: 'czsajliz-wxgu6tujd1zqq7hey_pclfqhdjsqolsxjfsurgh', }, }, - cslFactory: RustModule.CrossCsl.init, + cslFactory: () => RustModule.CrossCsl.init(), }); } diff --git a/packages/yoroi-extension/chrome/extension/index.js b/packages/yoroi-extension/chrome/extension/index.js index ae1b5ce491..6eb867da84 100644 --- a/packages/yoroi-extension/chrome/extension/index.js +++ b/packages/yoroi-extension/chrome/extension/index.js @@ -29,8 +29,6 @@ BigNumber.DEBUG = true; // Entry point into our application const initializeYoroi: void => Promise = async () => { - await RustModule.load(); - const api = await setupApi(); const router = new RouterStore(); const hashHistory = createHashHistory(); From 98809dcf0190776759011a2c2b846b46308ca986 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:00:17 +0300 Subject: [PATCH 2/9] simplify local-storage flag reading a bit --- packages/yoroi-extension/app/api/localStorage/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/yoroi-extension/app/api/localStorage/index.js b/packages/yoroi-extension/app/api/localStorage/index.js index 5ef023ba91..a4d061d775 100644 --- a/packages/yoroi-extension/app/api/localStorage/index.js +++ b/packages/yoroi-extension/app/api/localStorage/index.js @@ -343,12 +343,9 @@ export default class LocalStorageApi { unsetAcceptedTosVersion: void => Promise = () => removeLocalItem(storageKeys.ACCEPTED_TOS_VERSION); - loadIsAnalyticsAllowed: () => Promise = async () => { + loadIsAnalyticsAllowed: () => Promise = async () => { const json = await getLocalItem(storageKeys.IS_ANALYTICS_ALLOWED); - if (!json) { - return undefined; - } - return JSON.parse(json); + return json === 'true'; } saveIsAnalysticsAllowed: (flag: boolean) => Promise = async (flag) => { From d6c0a1e63e74a1fde7f95c9506e5353f340a5336 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:04:42 +0300 Subject: [PATCH 3/9] update to base load to handle post-load correctly and to log error type better --- .../app/stores/base/BaseLoadingStore.js | 62 +++++++++++------- .../app/stores/base/BaseProfileStore.js | 65 ++++++++++--------- 2 files changed, 72 insertions(+), 55 deletions(-) diff --git a/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js b/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js index c6cf85970e..3f712b9099 100644 --- a/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js +++ b/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js @@ -1,7 +1,7 @@ // @flow import type { lf$Database, lf$lovefieldExport, } from 'lovefield'; import { schema, } from 'lovefield'; -import { observable, computed, when, runInAction } from 'mobx'; +import { observable, computed, runInAction } from 'mobx'; import Store from './Store'; import environment from '../../environment'; import LocalizableError from '../../i18n/LocalizableError'; @@ -29,35 +29,40 @@ export default class BaseLoadingStore extends Store Promise> = new Request Promise>( - async () => await loadLovefieldDB(schema.DataStoreType.INDEXED_DB) + () => loadLovefieldDB(schema.DataStoreType.INDEXED_DB) ); - blockingLoadingRequests: Array> = []; + __blockingLoadingRequests: Array<[Request<() => void>, name]> = []; setup(): void { } - registerBlockingLoadingRequest(promise: Promise): void { - this.blockingLoadingRequests.push(promise); + registerBlockingLoadingRequest(promise: Promise, name: string): void { + this.__blockingLoadingRequests.push([new Request(() => promise), name]); } load(env: 'connector' | 'extension'): void { - when(() => this.isLoading, this.postLoadingScreenEnd.bind(this)); + const rustLoadingParams = (env === 'extension') ? ['dontLoadMessagesSigning'] : []; + const rustLoaderPromise = this.loadRustRequest.execute(rustLoadingParams).promise; + const dbLoaderPromise = this.loadPersistentDbRequest.execute().promise; + const blockingPromises = this.__blockingLoadingRequests.map(([r]) => r.execute().promise); Promise .all([ - // $FlowFixMe[invalid-tuple-arity]: this is correct, flow is confused - this.loadRustRequest.execute( - (env === 'extension') ? [ 'dontLoadMessagesSigning' ] : [] - ).promise, - this.loadPersistentDbRequest.execute().promise, - ...this.blockingLoadingRequests, + rustLoaderPromise, + dbLoaderPromise, + ...blockingPromises, ]) .then(async () => { Logger.debug(`[yoroi] closing other instances`); await closeOtherInstances(this.getTabIdKey.bind(this)()); Logger.debug(`[yoroi] loading persistent db`); const persistentDb = this.loadPersistentDbRequest.result; - if (persistentDb == null) throw new Error(`${nameof(BaseLoadingStore)}::${nameof(this.load)} load db was not loaded. Should never happen`); + if (persistentDb == null) { + throw new Error( + `${nameof(BaseLoadingStore)}::${nameof(this.load)} + DB was not loaded. Should never happen` + ); + } Logger.debug(`[yoroi] check migrations`); await this.migrationRequest.execute({ localStorageApi: this.api.localStorage, @@ -69,20 +74,29 @@ export default class BaseLoadingStore extends Store { this.error = null; this._loading = false; + this.postLoadingScreenEnd(); Logger.debug(`[yoroi] loading ended`); }); return undefined; - }).catch((error) => { - Logger.error(`${nameof(BaseLoadingStore)}::${nameof(this.load)} Unable to load libraries ` + stringifyError(error)); - if (this.loadPersistentDbRequest.error != null) { - runInAction(() => { - this.error = new StorageLoadError(); - }); - } else { - runInAction(() => { - this.error = new UnableToLoadError(); - }); - } + }) + .catch((error) => { + const isRustLoadError = this.loadRustRequest.error != null; + const isDbLoadError = this.loadPersistentDbRequest.error != null; + const failedBlockingLoadingRequestName = + this.__blockingLoadingRequests.find(([r]) => r.error != null)?.[1]; + const errorType = + (isRustLoadError && 'rust') + || (isDbLoadError && 'db') + || failedBlockingLoadingRequestName + || 'unclear'; + Logger.error( + `${nameof(BaseLoadingStore)}::${nameof(this.load)} + Unable to load libraries (error type: ${errorType}) ` + + stringifyError(error) + ); + runInAction(() => { + this.error = isDbLoadError ? new StorageLoadError() : new UnableToLoadError(); + }); }); } diff --git a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js index 91ceb75c1d..4be809c5c4 100644 --- a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js +++ b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js @@ -25,7 +25,7 @@ interface CoinPriceStore { } interface LoadingStore { - +registerBlockingLoadingRequest: (promise: Promise) => void + +registerBlockingLoadingRequest: (promise: Promise, name: string) => void } export default class BaseProfileStore @@ -198,41 +198,44 @@ export default class BaseProfileStore noop(this.isRevampAnnounced); noop(this.didUserMigratedToRevampTheme); this.stores.loading.registerBlockingLoadingRequest( - this._loadAcceptedTosVersion() + this._loadAcceptedTosVersion(), + 'load-tos-version', ); this.stores.loading.registerBlockingLoadingRequest( - (async () => { - const option = await this.getIsAnalyticsAllowed.execute() - const AMPLI_FLUSH_INTERVAL_MS = 5000; - await ampli.load(({ - environment: environment.isProduction() ? 'production' : 'development', - client: { - configuration: { - optOut: !option, - flushIntervalMillis: AMPLI_FLUSH_INTERVAL_MS, - trackingOptions: { - ipAddress: false, - }, - defaultTracking: false, - }, - }, - }: LoadOptionsWithEnvironment)).promise; - - if (environment.isDev()) { - ampli.client.add({ - name: 'info-plugin', - type: 'enrichment', - setup: () => Promise.resolve(), - execute: async (event) => { - console.info('[metrics]', event.event_type, event.event_properties) - return Promise.resolve(event) - }, - }); - } - })() + this._isAnalyticsAllowed(), + 'load-analytics-flag', ); } + _isAnalyticsAllowed: () => Promise = async () => { + const isAnalyticsAllowed = await this.getIsAnalyticsAllowed.execute() + const AMPLI_FLUSH_INTERVAL_MS = 5000; + await ampli.load(({ + environment: environment.isProduction() ? 'production' : 'development', + client: { + configuration: { + optOut: !isAnalyticsAllowed, + flushIntervalMillis: AMPLI_FLUSH_INTERVAL_MS, + trackingOptions: { + ipAddress: false, + }, + defaultTracking: false, + }, + }, + }: LoadOptionsWithEnvironment)).promise; + if (environment.isDev()) { + ampli.client.add({ + name: 'info-plugin', + type: 'enrichment', + setup: () => Promise.resolve(), + execute: async (event) => { + console.info('[metrics]', event.event_type, event.event_properties) + return Promise.resolve(event) + }, + }); + } + } + teardown(): void { super.teardown(); } From c6851ec0971cf67c62b323e769b4e87c4f2377be Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:15:16 +0300 Subject: [PATCH 4/9] rolled back flag reading --- packages/yoroi-extension/app/api/localStorage/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/yoroi-extension/app/api/localStorage/index.js b/packages/yoroi-extension/app/api/localStorage/index.js index a4d061d775..5ef023ba91 100644 --- a/packages/yoroi-extension/app/api/localStorage/index.js +++ b/packages/yoroi-extension/app/api/localStorage/index.js @@ -343,9 +343,12 @@ export default class LocalStorageApi { unsetAcceptedTosVersion: void => Promise = () => removeLocalItem(storageKeys.ACCEPTED_TOS_VERSION); - loadIsAnalyticsAllowed: () => Promise = async () => { + loadIsAnalyticsAllowed: () => Promise = async () => { const json = await getLocalItem(storageKeys.IS_ANALYTICS_ALLOWED); - return json === 'true'; + if (!json) { + return undefined; + } + return JSON.parse(json); } saveIsAnalysticsAllowed: (flag: boolean) => Promise = async (flag) => { From 0ab98f315f527a876c7f0f6a74e4a012b328683a Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:30:19 +0300 Subject: [PATCH 5/9] var rename for readability --- .../app/stores/base/BaseProfileStore.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js index 4be809c5c4..5405e95a26 100644 --- a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js +++ b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js @@ -208,7 +208,7 @@ export default class BaseProfileStore } _isAnalyticsAllowed: () => Promise = async () => { - const isAnalyticsAllowed = await this.getIsAnalyticsAllowed.execute() + const isAnalyticsAllowed = await this.getIsAnalyticsAllowed.execute(); const AMPLI_FLUSH_INTERVAL_MS = 5000; await ampli.load(({ environment: environment.isProduction() ? 'production' : 'development', @@ -566,10 +566,10 @@ export default class BaseProfileStore return this.getUnitOfAccountRequest.wasExecuted && this.getUnitOfAccountRequest.result !== null; } - _onOptForAnalytics: (boolean) => void = (option) => { - this.getIsAnalyticsAllowed.patch(_ => option); - this.api.localStorage.saveIsAnalysticsAllowed(option); - ampli.client.setOptOut(!option); + _onOptForAnalytics: (boolean) => void = (isAnalyticsAllowed) => { + this.getIsAnalyticsAllowed.patch(_ => isAnalyticsAllowed); + this.api.localStorage.saveIsAnalysticsAllowed(isAnalyticsAllowed); + ampli.client.setOptOut(!isAnalyticsAllowed); } @computed get isAnalyticsOpted(): boolean { From c86afeffca737a29df87219eb6d2a51eab1b5128 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:30:44 +0300 Subject: [PATCH 6/9] readability --- .../app/stores/base/BaseLoadingStore.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js b/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js index 3f712b9099..b743cc6b91 100644 --- a/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js +++ b/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js @@ -1,17 +1,17 @@ // @flow import type { lf$Database, lf$lovefieldExport, } from 'lovefield'; import { schema, } from 'lovefield'; -import { observable, computed, runInAction } from 'mobx'; +import { computed, observable, runInAction } from 'mobx'; import Store from './Store'; import environment from '../../environment'; import LocalizableError from '../../i18n/LocalizableError'; -import { UnableToLoadError, StorageLoadError } from '../../i18n/errors'; +import { StorageLoadError, UnableToLoadError } from '../../i18n/errors'; import Request from '../lib/LocalizedRequest'; import type { MigrationRequest } from '../../api/common/migration'; import { migrateAndRefresh } from '../../api/common/migration'; import { Logger, stringifyError } from '../../utils/logging'; import { closeOtherInstances } from '../../utils/tabManager'; -import { loadLovefieldDB, importOldDb, } from '../../api/ada/lib/storage/database/index'; +import { importOldDb, loadLovefieldDB, } from '../../api/ada/lib/storage/database/index'; import { RustModule } from '../../api/ada/lib/cardanoCrypto/rustLoader'; /** Load dependencies before launching the app */ @@ -43,14 +43,11 @@ export default class BaseLoadingStore extends Store r.execute().promise); Promise .all([ - rustLoaderPromise, - dbLoaderPromise, - ...blockingPromises, + this.loadRustRequest.execute(rustLoadingParams), + this.loadPersistentDbRequest.execute(), + ...(this.__blockingLoadingRequests.map(([r]) => r.execute())), ]) .then(async () => { Logger.debug(`[yoroi] closing other instances`); From 39f6a4afc93da80da6e06ef6d34aab060c3d9d93 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:49:54 +0300 Subject: [PATCH 7/9] safety check for ampli function on load --- packages/yoroi-extension/app/stores/base/BaseProfileStore.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js index 5405e95a26..f13a1f8080 100644 --- a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js +++ b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js @@ -210,6 +210,9 @@ export default class BaseProfileStore _isAnalyticsAllowed: () => Promise = async () => { const isAnalyticsAllowed = await this.getIsAnalyticsAllowed.execute(); const AMPLI_FLUSH_INTERVAL_MS = 5000; + if (ampli.load == null || typeof ampli.load !== 'function') { + throw new Error(`ampli.load is not available or not a function (${typeof ampli.load})`) + } await ampli.load(({ environment: environment.isProduction() ? 'production' : 'development', client: { From 42cb21b083da1e5d2f06c204d3b641a16d6cb19c Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:54:52 +0300 Subject: [PATCH 8/9] flow fixes --- packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js | 2 +- packages/yoroi-extension/app/stores/base/BaseLoadingStore.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js b/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js index 72121781f0..5b8c06529d 100644 --- a/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js +++ b/packages/yoroi-extension/app/stores/ada/AdaAddressesStore.js @@ -89,7 +89,7 @@ export default class AdaAddressesStore extends Store { apiKey: 'czsajliz-wxgu6tujd1zqq7hey_pclfqhdjsqolsxjfsurgh', }, }, - cslFactory: () => RustModule.CrossCsl.init(), + cslFactory: (ctx) => RustModule.CrossCsl.init(ctx), }); } diff --git a/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js b/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js index b743cc6b91..fa367d15b4 100644 --- a/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js +++ b/packages/yoroi-extension/app/stores/base/BaseLoadingStore.js @@ -32,7 +32,7 @@ export default class BaseLoadingStore extends Store loadLovefieldDB(schema.DataStoreType.INDEXED_DB) ); - __blockingLoadingRequests: Array<[Request<() => void>, name]> = []; + __blockingLoadingRequests: Array<[Request<() => Promise>, string]> = []; setup(): void { } @@ -45,6 +45,7 @@ export default class BaseLoadingStore extends Store r.execute())), From 6759d54418d82d1916e0ac63ae1ba1e0721de20e Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Wed, 28 Feb 2024 19:58:25 +0300 Subject: [PATCH 9/9] lint fixes --- packages/yoroi-extension/app/stores/base/BaseProfileStore.js | 4 ++-- packages/yoroi-extension/chrome/extension/index.js | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js index f13a1f8080..692a2124a0 100644 --- a/packages/yoroi-extension/app/stores/base/BaseProfileStore.js +++ b/packages/yoroi-extension/app/stores/base/BaseProfileStore.js @@ -202,12 +202,12 @@ export default class BaseProfileStore 'load-tos-version', ); this.stores.loading.registerBlockingLoadingRequest( - this._isAnalyticsAllowed(), + this._loadWhetherAnalyticsAllowed(), 'load-analytics-flag', ); } - _isAnalyticsAllowed: () => Promise = async () => { + _loadWhetherAnalyticsAllowed: () => Promise = async () => { const isAnalyticsAllowed = await this.getIsAnalyticsAllowed.execute(); const AMPLI_FLUSH_INTERVAL_MS = 5000; if (ampli.load == null || typeof ampli.load !== 'function') { diff --git a/packages/yoroi-extension/chrome/extension/index.js b/packages/yoroi-extension/chrome/extension/index.js index 6eb867da84..deb065ceb6 100644 --- a/packages/yoroi-extension/chrome/extension/index.js +++ b/packages/yoroi-extension/chrome/extension/index.js @@ -17,7 +17,6 @@ import { LazyLoadPromises } from '../../app/Routes'; import environment from '../../app/environment'; import { ampli } from '../../ampli/index'; import { ROUTES } from '../../app/routes-config'; -import { RustModule } from '../../app/api/ada/lib/cardanoCrypto/rustLoader'; // run MobX in strict mode configure({ enforceActions: 'always' });