diff --git a/.changeset/pretty-dingos-sing.md b/.changeset/pretty-dingos-sing.md
new file mode 100644
index 000000000000..babb94ab6b51
--- /dev/null
+++ b/.changeset/pretty-dingos-sing.md
@@ -0,0 +1,5 @@
+---
+"live-mobile": patch
+---
+
+Feature flags: take into account env variable FEATURE_FLAGS to override feature flags
diff --git a/.changeset/quiet-doors-cross.md b/.changeset/quiet-doors-cross.md
new file mode 100644
index 000000000000..af547b9dd2f4
--- /dev/null
+++ b/.changeset/quiet-doors-cross.md
@@ -0,0 +1,5 @@
+---
+"ledger-live-desktop": patch
+---
+
+Feature flags: take into account env variable FEATURE_FLAGS to override feature flags
diff --git a/.changeset/silent-beers-carry.md b/.changeset/silent-beers-carry.md
new file mode 100644
index 000000000000..9797daaca265
--- /dev/null
+++ b/.changeset/silent-beers-carry.md
@@ -0,0 +1,6 @@
+---
+"@ledgerhq/live-common": patch
+"@ledgerhq/types-live": patch
+---
+
+Add FEATURE_FLAGS env variable to override feature flags
diff --git a/apps/ledger-live-desktop/src/renderer/components/FirebaseFeatureFlags.tsx b/apps/ledger-live-desktop/src/renderer/components/FirebaseFeatureFlags.tsx
index f60e2e2f7396..6531ae273a29 100644
--- a/apps/ledger-live-desktop/src/renderer/components/FirebaseFeatureFlags.tsx
+++ b/apps/ledger-live-desktop/src/renderer/components/FirebaseFeatureFlags.tsx
@@ -6,6 +6,7 @@ import { Feature, FeatureId } from "@ledgerhq/types-live";
import { getValue } from "firebase/remote-config";
import { formatFeatureId, useFirebaseRemoteConfig } from "./FirebaseRemoteConfig";
+import { getEnv } from "@ledgerhq/live-common/env";
const checkFeatureFlagVersion = (feature: Feature) => {
if (
@@ -42,6 +43,17 @@ export const FirebaseFeatureFlagsProvider = ({ children }: Props): JSX.Element =
return checkFeatureFlagVersion(localOverrides[key]);
}
+ const envFlags = getEnv("FEATURE_FLAGS") as { [key in FeatureId]?: Feature } | undefined;
+ if (allowOverride && envFlags) {
+ const feature = envFlags[key];
+ if (feature)
+ return {
+ ...feature,
+ overridesRemote: true,
+ overriddenByEnv: true,
+ };
+ }
+
const value = getValue(remoteConfig, formatFeatureId(key));
const feature: Feature = JSON.parse(value.asString());
@@ -58,7 +70,8 @@ export const FirebaseFeatureFlagsProvider = ({ children }: Props): JSX.Element =
(key: FeatureId, value: Feature): void => {
const actualRemoteValue = getFeature(key, false);
if (!isEqual(actualRemoteValue, value)) {
- const overridenValue = { ...value, overridesRemote: true };
+ const { overriddenByEnv, ...pureValue } = value; // eslint-disable-line
+ const overridenValue = { ...pureValue, overridesRemote: true };
setLocalOverrides(currentOverrides => ({ ...currentOverrides, [key]: overridenValue }));
} else {
setLocalOverrides(currentOverrides => ({ ...currentOverrides, [key]: undefined }));
diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsButton.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsButton.tsx
deleted file mode 100644
index ff4c755ba585..000000000000
--- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsButton.tsx
+++ /dev/null
@@ -1,248 +0,0 @@
-import React, { useState, useMemo, useCallback } from "react";
-import Button from "~/renderer/components/Button";
-import { useTranslation } from "react-i18next";
-import { defaultFeatures, useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
-import { SettingsSectionRow as Row } from "../../SettingsSection";
-import { Text, Input, Icons, Flex, Tag, SearchInput } from "@ledgerhq/react-ui";
-import {
- InputRenderLeftContainer,
- InputRenderRightContainer,
-} from "@ledgerhq/react-ui/components/form/BaseInput/index";
-import { withV3StyleProvider } from "~/renderer/styles/StyleProviderV3";
-import { includes, lowerCase } from "lodash";
-import Box from "~/renderer/components/Box";
-import Switch from "~/renderer/components/Switch";
-import Alert from "~/renderer/components/Alert";
-import { Feature, FeatureId } from "@ledgerhq/types-live";
-
-type EditSectionProps = {
- error?: Error;
- value: string;
- disabled?: boolean;
-
- onOverride: () => void;
- onRestore: () => void;
- onChange: (_: string) => void;
-};
-
-const tryParse = (jsonString: string, fallback: any) => {
- try {
- return JSON.parse(jsonString);
- } catch (e) {
- return fallback;
- }
-};
-
-const EditSection = ({
- error,
- value,
- onOverride,
- onRestore,
- onChange,
- disabled,
-}: EditSectionProps) => {
- const { t } = useTranslation();
- const handleSwitchChange = useCallback(
- enabled => {
- const prevVal = JSON.parse(value);
- onChange(JSON.stringify({ ...prevVal, enabled }));
- },
- [value, onChange],
- );
- return (
-
- {error ? (
-
- {error.toString()}
-
- ) : null}
-
- (
-
-
-
- )}
- />
-
-
-
-
- );
-};
-
-const FeatureFlagsButton = () => {
- const { t } = useTranslation();
- const featureFlagsProvider = useFeatureFlags();
- const [visible, setVisible] = useState(false);
- const [error, setError] = useState();
- const [focusedName, setFocusedName] = useState("");
- const [hiddenFlagName, setHiddenFlagName] = useState(null);
- const [inputValues, setInputValues] = useState<
- {
- [key in FeatureId | string]?: string | undefined;
- }
- >({});
- const [searchInput, setSearchInput] = useState("");
-
- const featureFlags = useMemo(() => {
- const features: { [key in FeatureId | string]: Feature } = {};
- const featureKeys = Object.keys(defaultFeatures);
- if (hiddenFlagName && !featureKeys.includes(hiddenFlagName)) featureKeys.push(hiddenFlagName);
- featureKeys.forEach((key: FeatureId | string) => {
- const value = featureFlagsProvider.getFeature(key as FeatureId);
- if (value) {
- features[key] = value;
- }
- });
- return features;
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [focusedName, featureFlagsProvider, hiddenFlagName]);
-
- const handleInputChange = useCallback(
- value => {
- setError();
- setInputValues(currentValues => ({
- ...currentValues,
- [focusedName]: value,
- }));
- },
- [focusedName],
- );
-
- const handleRestoreFeature = useCallback(() => {
- setError();
- setInputValues(currentValues => ({
- ...currentValues,
- [focusedName]: undefined,
- }));
- featureFlagsProvider.resetFeature(focusedName);
- }, [featureFlagsProvider, focusedName]);
-
- const handleOverrideFeature = useCallback(() => {
- setError();
- try {
- // Nb if value is invalid or missing, JSON parse will fail
- const newValue = JSON.parse(inputValues[focusedName]);
- featureFlagsProvider.overrideFeature(focusedName, newValue);
- } catch (e) {
- setError(e);
- }
- }, [inputValues, focusedName, featureFlagsProvider]);
-
- const handleAddHiddenFlag = useCallback(
- value => {
- setHiddenFlagName(value);
- setSearchInput(value);
- },
- [setSearchInput, setHiddenFlagName],
- );
-
- const filteredFlags = useMemo(() => {
- return Object.entries(featureFlags)
- .sort((a, b) => a[0].localeCompare(b[0]))
- .filter(([name]) => !searchInput || includes(lowerCase(name), lowerCase(searchInput)));
- }, [featureFlags, searchInput]);
-
- return (
-
- {t("settings.developer.featureFlagsDesc")}
- {!visible ? null : (
- <>
-
- (
-
-
-
- )}
- clearable
- placeholder="Add missing flag"
- value={hiddenFlagName}
- onChange={handleAddHiddenFlag}
- />
-
- {filteredFlags.map(([flagName, value]) => (
- <>
-
- {focusedName === flagName ? (
-
-
-
-
- {JSON.stringify(featureFlags[flagName], null, 2)}
-
-
-
- ) : null}
- >
- ))}
- >
- )}
-
- }
- >
-
-
- );
-};
-
-export default withV3StyleProvider(FeatureFlagsButton);
diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/FeatureFlagDetails.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/FeatureFlagDetails.tsx
new file mode 100644
index 000000000000..d0b78d6d82c3
--- /dev/null
+++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/FeatureFlagDetails.tsx
@@ -0,0 +1,74 @@
+import React, { useCallback } from "react";
+import ButtonV2 from "~/renderer/components/Button";
+import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
+import { Text, Flex, Tag } from "@ledgerhq/react-ui";
+import { FeatureId } from "@ledgerhq/types-live";
+import { withV2StyleProvider } from "~/renderer/styles/StyleProvider";
+import Box from "~/renderer/components/Box";
+import FeatureFlagEdit from "./FeatureFlagEdit";
+
+const OldButton = withV2StyleProvider(ButtonV2);
+
+type Props = {
+ flagName: FeatureId;
+ focused?: boolean;
+ setFocusedName: (arg0: string | undefined) => void;
+};
+
+const FeatureFlagDetails: React.FC = props => {
+ const { flagName, focused, setFocusedName } = props;
+ const { getFeature } = useFeatureFlags();
+ const flagValue = getFeature(flagName as FeatureId);
+
+ const {
+ overriddenByEnv,
+ overridesRemote,
+ enabledOverriddenForCurrentLanguage,
+ enabledOverriddenForCurrentDesktopVersion,
+ } = flagValue || {};
+
+ const handleClick = useCallback(() => {
+ focused ? setFocusedName(undefined) : setFocusedName(flagName);
+ }, [focused, flagName, setFocusedName]);
+
+ if (!flagValue) return null;
+
+ return (
+ <>
+
+
+
+ {flagName}
+ {overriddenByEnv ? (
+
+ overridden by env
+
+ ) : overridesRemote ? (
+
+ overridden locally
+
+ ) : null}
+ {enabledOverriddenForCurrentLanguage ? (
+
+ disabled for current language
+
+ ) : null}
+ {enabledOverriddenForCurrentDesktopVersion ? (
+
+ disabled for current version
+
+ ) : null}
+
+
+ {focused ? : null}
+ >
+ );
+};
+
+export default FeatureFlagDetails;
diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/FeatureFlagEdit.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/FeatureFlagEdit.tsx
new file mode 100644
index 000000000000..4e474d3e34dd
--- /dev/null
+++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/FeatureFlagEdit.tsx
@@ -0,0 +1,113 @@
+import React, { useState, useMemo, useCallback } from "react";
+import Button from "~/renderer/components/ButtonV3";
+import { useTranslation } from "react-i18next";
+import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
+import { Text, Input, Flex } from "@ledgerhq/react-ui";
+import { Feature, FeatureId } from "@ledgerhq/types-live";
+import { InputRenderRightContainer } from "@ledgerhq/react-ui/components/form/BaseInput/index";
+import { withV2StyleProvider } from "~/renderer/styles/StyleProvider";
+import SwitchV2 from "~/renderer/components/Switch";
+import Alert from "~/renderer/components/Alert";
+
+const Switch = withV2StyleProvider(SwitchV2);
+
+const FeatureFlagEdit: React.FC<{ flagName: FeatureId; flagValue: Feature }> = props => {
+ const { flagName, flagValue } = props;
+ const [error, setError] = useState();
+ const [inputValue, setInputValue] = useState(undefined);
+
+ /**
+ * pureValue is the value of the flag without the keys set programmatically
+ * by Legder Live.
+ * */
+ const {
+ overriddenByEnv, // eslint-disable-line @typescript-eslint/no-unused-vars
+ overridesRemote, // eslint-disable-line @typescript-eslint/no-unused-vars
+ enabledOverriddenForCurrentLanguage, // eslint-disable-line @typescript-eslint/no-unused-vars
+ enabledOverriddenForCurrentDesktopVersion, // eslint-disable-line @typescript-eslint/no-unused-vars
+ ...pureValue
+ } = flagValue || {};
+
+ const stringifiedPureValue = useMemo(() => (pureValue ? JSON.stringify(pureValue) : undefined), [
+ pureValue,
+ ]);
+
+ const inputValueDefaulted = inputValue || stringifiedPureValue;
+
+ const featureFlagsProvider = useFeatureFlags();
+
+ const { t } = useTranslation();
+
+ const handleInputChange = useCallback(value => {
+ setError(undefined);
+ setInputValue(value);
+ }, []);
+
+ const handleRestoreFeature = useCallback(() => {
+ setError(undefined);
+ setInputValue(undefined);
+ featureFlagsProvider.resetFeature(flagName);
+ }, [featureFlagsProvider, flagName]);
+
+ const handleOverrideFeature = useCallback(() => {
+ setError(undefined);
+ try {
+ // Nb if value is invalid or missing, JSON parse will fail
+ const newValue = inputValue ? JSON.parse(inputValue) : undefined;
+ featureFlagsProvider.overrideFeature(flagName, newValue);
+ } catch (e) {
+ setError(e);
+ }
+ }, [inputValue, flagName, featureFlagsProvider]);
+
+ const isChecked = useMemo(() => {
+ if (!inputValueDefaulted) return false;
+ try {
+ return JSON.parse(inputValueDefaulted)?.enabled;
+ } catch (e) {
+ return false;
+ }
+ }, [inputValueDefaulted]);
+
+ const handleSwitchChange = useCallback(
+ enabled => {
+ featureFlagsProvider.overrideFeature(flagName, { ...flagValue, enabled });
+ },
+ [featureFlagsProvider, flagName, flagValue],
+ );
+
+ return (
+
+
+ {error ? (
+
+ {error.toString()}
+
+ ) : null}
+
+ (
+
+
+
+ )}
+ />
+
+
+
+
+
+
+ {JSON.stringify(pureValue, null, 2)}
+
+
+ );
+};
+
+export default FeatureFlagEdit;
diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/index.tsx
new file mode 100644
index 000000000000..1cd762341a93
--- /dev/null
+++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/FeatureFlagsSettings/index.tsx
@@ -0,0 +1,116 @@
+import React, { useState, useMemo, useCallback } from "react";
+import ButtonV2 from "~/renderer/components/Button";
+import { useTranslation } from "react-i18next";
+import { defaultFeatures } from "@ledgerhq/live-common/featureFlags/index";
+import { SettingsSectionRow as Row } from "../../../SettingsSection";
+import { Input, Icons, Flex, SearchInput, Alert } from "@ledgerhq/react-ui";
+import { FeatureId } from "@ledgerhq/types-live";
+import { InputRenderLeftContainer } from "@ledgerhq/react-ui/components/form/BaseInput/index";
+import { includes, lowerCase, trim } from "lodash";
+import { withV3StyleProvider } from "~/renderer/styles/StyleProviderV3";
+import FeatureFlagDetails from "./FeatureFlagDetails";
+
+const addFlagHint = `\
+If a feature flag is defined in the targeted Firebase environment \
+but it is missing from the following list, you can type its name in \
+the input field below and it will appear in the list. Type the \
+flag name in camelCase without the "feature" prefix.\
+`;
+
+const Content = withV3StyleProvider((props: { visible?: boolean }) => {
+ const { t } = useTranslation();
+ const [focusedName, setFocusedName] = useState();
+ const [hiddenFlagName, setHiddenFlagName] = useState("");
+ const [searchInput, setSearchInput] = useState("");
+
+ const trimmedHiddenFlagName = trim(hiddenFlagName);
+
+ const featureFlags = useMemo(() => {
+ const featureKeys = Object.keys(defaultFeatures);
+ if (trimmedHiddenFlagName && !featureKeys.includes(trimmedHiddenFlagName))
+ featureKeys.push(trimmedHiddenFlagName);
+ return featureKeys;
+ }, [trimmedHiddenFlagName]);
+
+ const handleAddHiddenFlag = useCallback(
+ value => {
+ setHiddenFlagName(value);
+ setSearchInput(value);
+ },
+ [setSearchInput, setHiddenFlagName],
+ );
+
+ const filteredFlags = useMemo(() => {
+ return featureFlags
+ .sort((a, b) => a[0].localeCompare(b[0]))
+ .filter(name => !searchInput || includes(lowerCase(name), lowerCase(searchInput)));
+ }, [featureFlags, searchInput]);
+
+ const content = useMemo(
+ () =>
+ filteredFlags.map(flagName => (
+
+ )),
+ [filteredFlags, focusedName],
+ );
+
+ return (
+
+ {t("settings.developer.featureFlagsDesc")}
+ {!props.visible ? null : (
+ <>
+
+
+ (
+
+
+
+ )}
+ clearable
+ placeholder={"Add missing flag (instructions above)"}
+ value={hiddenFlagName}
+ onChange={handleAddHiddenFlag}
+ />
+
+ {content}
+ >
+ )}
+
+ );
+});
+
+const FeatureFlagsSettings = () => {
+ const { t } = useTranslation();
+ const [visible, setVisible] = useState(false);
+
+ const handleClick = useCallback(() => {
+ setVisible(!visible);
+ }, [visible]);
+
+ return (
+
}
+ >
+
+ {visible ? "Hide" : "Show"}
+
+
+ );
+};
+
+export default FeatureFlagsSettings;
diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/index.jsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/index.jsx
index 8cdba548a3d4..96e5eee8ebb5 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/index.jsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/index.jsx
@@ -9,7 +9,7 @@ import AllowDebugAppsToggle from "./AllowDebugAppsToggle";
import EnablePlatformDevToolsToggle from "./EnablePlatformDevToolsToggle";
import CatalogProviderSelect from "./CatalogProviderSelect";
import RunLocalAppButton from "./RunLocalAppButton";
-import FeatureFlagsButton from "./FeatureFlagsButton";
+import FeatureFlagsSettings from "./FeatureFlagsSettings";
import EnableLearnPageStagingUrlToggle from "./EnableLearnPageStagingUrlToggle";
const SectionDeveloper = () => {
@@ -44,7 +44,7 @@ const SectionDeveloper = () => {
-
+
{
);
};
+export const withV2StyleProvider = (Component: React.ComponentType) => {
+ const WrappedComponent = props => {
+ const selectedPalette = useSelector(themeSelector) || "light";
+
+ return (
+
+
+
+ );
+ };
+ return WrappedComponent;
+};
+
export default StyleProvider;
diff --git a/apps/ledger-live-desktop/tests/fixtures/common.ts b/apps/ledger-live-desktop/tests/fixtures/common.ts
index a4f29ac05145..246bd4bff7ee 100644
--- a/apps/ledger-live-desktop/tests/fixtures/common.ts
+++ b/apps/ledger-live-desktop/tests/fixtures/common.ts
@@ -3,6 +3,7 @@ import { test as base, expect, Page, ElectronApplication } from "@playwright/tes
import * as fs from "fs";
import * as path from "path";
import * as crypto from "crypto";
+import { Feature, FeatureId } from "@ledgerhq/types-live";
export function generateUUID(): string {
return crypto.randomBytes(16).toString("hex");
@@ -17,6 +18,7 @@ type TestFixtures = {
userdataFile: any;
env: Record;
page: Page;
+ featureFlags: { [key in FeatureId]?: Feature };
};
const test = base.extend({
@@ -24,6 +26,7 @@ const test = base.extend({
lang: "en-US",
theme: "dark",
userdata: undefined,
+ featureFlags: undefined,
userdataDestinationPath: async ({}, use) => {
use(path.join(__dirname, "../artifacts/userdata", generateUUID()));
},
@@ -35,7 +38,15 @@ const test = base.extend({
use(fullFilePath);
},
page: async (
- { lang, theme, userdata, userdataDestinationPath, userdataOriginalFile, env }: TestFixtures,
+ {
+ lang,
+ theme,
+ userdata,
+ userdataDestinationPath,
+ userdataOriginalFile,
+ env,
+ featureFlags,
+ }: TestFixtures,
use: (page: Page) => void,
) => {
// create userdata path
@@ -55,6 +66,7 @@ const test = base.extend({
CI: process.env.CI || undefined,
PLAYWRIGHT_RUN: true,
LEDGER_MIN_HEIGHT: 768,
+ FEATURE_FLAGS: JSON.stringify(featureFlags),
},
env,
);
@@ -105,7 +117,7 @@ const test = base.extend({
});
// app is loaded
- //expect(await page.title()).toBe("Ledger Live");
+ // expect(await page.title()).toBe("Ledger Live");
await page.waitForLoadState("domcontentloaded");
await page.waitForSelector("#loader-container", { state: "hidden" });
diff --git a/apps/ledger-live-mobile/src/components/FirebaseFeatureFlags.tsx b/apps/ledger-live-mobile/src/components/FirebaseFeatureFlags.tsx
index f51ef376c405..ccad3a5b0896 100644
--- a/apps/ledger-live-mobile/src/components/FirebaseFeatureFlags.tsx
+++ b/apps/ledger-live-mobile/src/components/FirebaseFeatureFlags.tsx
@@ -7,6 +7,7 @@ import {
defaultFeatures,
} from "@ledgerhq/live-common/featureFlags/index";
import { FeatureId, Feature } from "@ledgerhq/types-live";
+import { getEnv } from "@ledgerhq/live-common/env";
import { formatFeatureId } from "./FirebaseRemoteConfig";
@@ -15,17 +16,33 @@ import { languageSelector } from "../reducers/settings";
// eslint-disable-next-line @typescript-eslint/ban-types
type Props = PropsWithChildren<{}>;
-const getFeature = (
- key: FeatureId,
- appLanguage: string,
- localOverrides?: { [key in FeatureId]?: Feature },
-) => {
+const getFeature = (args: {
+ key: FeatureId;
+ appLanguage: string;
+ localOverrides?: { [key in FeatureId]?: Feature };
+ allowOverride?: boolean;
+}) => {
+ const { key, appLanguage, localOverrides, allowOverride = true } = args;
try {
// Nb prioritize local overrides
- if (localOverrides && localOverrides[key]) {
+ if (allowOverride && localOverrides && localOverrides[key]) {
return localOverrides[key];
}
+ const envFlags = getEnv("FEATURE_FLAGS") as
+ | { [key in FeatureId]?: Feature }
+ | undefined;
+
+ if (allowOverride && envFlags) {
+ const feature = envFlags[key];
+ if (feature)
+ return {
+ ...feature,
+ overridesRemote: true,
+ overriddenByEnv: true,
+ };
+ }
+
const value = remoteConfig().getValue(formatFeatureId(key));
const feature = JSON.parse(value.asString());
@@ -57,8 +74,8 @@ export const getAllDivergedFlags = (
appLanguage: string,
): { [key in FeatureId]: boolean } => {
const res: { [key in FeatureId]: boolean } = {};
- Object.keys(defaultFeatures).forEach(key => {
- const value = getFeature(key, appLanguage);
+ (Object.keys(defaultFeatures) as FeatureId[]).forEach(key => {
+ const value = getFeature({ key, appLanguage });
if (value && value.enabled !== defaultFeatures[key].enabled) {
res[key] = value.enabled;
}
@@ -73,9 +90,14 @@ export const FirebaseFeatureFlagsProvider: React.FC = ({ children }) => {
const overrideFeature = useCallback(
(key: FeatureId, value: Feature): void => {
- const actualRemoteValue = getFeature(key, appLanguage);
+ const actualRemoteValue = getFeature({
+ key,
+ appLanguage,
+ allowOverride: false,
+ });
if (!isEqual(actualRemoteValue, value)) {
- const overridenValue = { ...value, overridesRemote: true };
+ const { overriddenByEnv: _, ...pureValue } = value;
+ const overridenValue = { ...pureValue, overridesRemote: true };
setLocalOverrides(currentOverrides => ({
...currentOverrides,
[key]: overridenValue,
@@ -99,7 +121,8 @@ export const FirebaseFeatureFlagsProvider: React.FC = ({ children }) => {
// Nb wrapped because the method is also called from outside.
const wrappedGetFeature = useCallback(
- (key: FeatureId): Feature => getFeature(key, appLanguage, localOverrides),
+ (key: FeatureId): Feature =>
+ getFeature({ key, appLanguage, localOverrides }),
[localOverrides, appLanguage],
);
diff --git a/apps/ledger-live-mobile/src/components/RootNavigator/SettingsNavigator.tsx b/apps/ledger-live-mobile/src/components/RootNavigator/SettingsNavigator.tsx
index a978314467a0..9500e1c3d4ae 100644
--- a/apps/ledger-live-mobile/src/components/RootNavigator/SettingsNavigator.tsx
+++ b/apps/ledger-live-mobile/src/components/RootNavigator/SettingsNavigator.tsx
@@ -16,7 +16,7 @@ import DebugBLE from "../../screens/DebugBLE";
import DebugBLEBenchmark from "../../screens/DebugBLEBenchmark";
import DebugCrash from "../../screens/DebugCrash";
import DebugHttpTransport from "../../screens/DebugHttpTransport";
-import DebugFeatureFlags from "../../screens/DebugFeatureFlags";
+import DebugFeatureFlags from "../../screens/FeatureFlagsSettings";
import DebugIcons from "../../screens/DebugIcons";
import DebugLottie from "../../screens/DebugLottie";
import DebugMultiAppInstall from "../../screens/DebugMultiAppInstall";
diff --git a/apps/ledger-live-mobile/src/screens/DebugFeatureFlags.tsx b/apps/ledger-live-mobile/src/screens/DebugFeatureFlags.tsx
deleted file mode 100644
index b8dbd9bb11d0..000000000000
--- a/apps/ledger-live-mobile/src/screens/DebugFeatureFlags.tsx
+++ /dev/null
@@ -1,294 +0,0 @@
-import React, { useCallback, useState, useMemo } from "react";
-import { Pressable, ScrollView, StyleSheet, View } from "react-native";
-import { useTranslation } from "react-i18next";
-import {
- defaultFeatures,
- useFeatureFlags,
-} from "@ledgerhq/live-common/featureFlags/index";
-import type { FeatureId, Feature } from "@ledgerhq/types-live";
-
-import {
- BaseInput,
- Text,
- Flex,
- Button,
- Box,
- Tag,
- SearchInput,
- Switch,
- Icons,
-} from "@ledgerhq/native-ui";
-import styled from "styled-components/native";
-import { includes, lowerCase } from "lodash";
-import {
- InputRenderLeftContainer,
- InputRenderRightContainer,
-} from "@ledgerhq/native-ui/components/Form/Input/BaseInput";
-import NavigationScrollView from "../components/NavigationScrollView";
-import Alert from "../components/Alert";
-
-const Divider = styled(Box).attrs({
- width: "100%",
- my: 4,
- height: 1,
- bg: "neutral.c50",
-})``;
-
-const TagEnabled = styled(Tag).attrs({
- bg: "success.c100",
- uppercase: false,
- type: "color",
- mr: 2,
-})``;
-
-const TagDisabled = styled(Tag).attrs({
- bg: "error.c100",
- uppercase: false,
- type: "color",
- mr: 2,
-})``;
-
-type EditSectionProps = {
- error?: Error;
- value: string;
- disabled?: boolean;
-
- onOverride: () => void;
- onRestore: () => void;
- onChange: (_: string) => void;
-};
-
-const tryParse = (jsonString: string, fallback: any) => {
- try {
- return JSON.parse(jsonString);
- } catch (e) {
- return fallback;
- }
-};
-
-const EditSection = ({
- error,
- value,
- onOverride,
- onRestore,
- onChange,
- disabled,
-}: EditSectionProps) => {
- const { t } = useTranslation();
- const handleSwitchChange = useCallback(
- newVal => {
- onChange(JSON.stringify({ ...JSON.parse(value), enabled: newVal }));
- },
- [value, onChange],
- );
- return (
-
- {error ? (
-
- {error.toString()}
-
- ) : null}
- (
-
-
-
- )}
- />
-
-
-
-
-
- );
-};
-
-export default function DebugFeatureFlags() {
- const { t } = useTranslation();
- const featureFlagsProvider = useFeatureFlags();
- const [error, setError] = useState(null);
- const [focusedName, setFocusedName] = useState(null);
- const [hiddenFlagName, setHiddenFlagName] = useState(null);
- const [searchInput, setSearchInput] = useState("");
- const [inputValues, setInputValues] = useState<{
- [key in FeatureId | string]?: string | undefined;
- }>({});
-
- const featureFlags = useMemo(() => {
- const features: { [key in FeatureId | string]: Feature } = {};
- const featureKeys = Object.keys(defaultFeatures);
- if (hiddenFlagName && !featureKeys.includes(hiddenFlagName))
- featureKeys.push(hiddenFlagName);
- featureKeys.forEach((key: FeatureId | string) => {
- const value = featureFlagsProvider.getFeature(key as FeatureId);
- if (value) {
- features[key] = value;
- }
- });
- return features;
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [focusedName, featureFlagsProvider, hiddenFlagName]);
-
- const handleInputChange = useCallback(
- value => {
- setError(null);
- if (!focusedName) return;
- setInputValues(currentValues => ({
- ...currentValues,
- [focusedName]: value,
- }));
- },
- [focusedName],
- );
-
- const handleRestoreFeature = useCallback(() => {
- setError(null);
- if (!focusedName) return;
- setInputValues(currentValues => ({
- ...currentValues,
- [focusedName]: undefined,
- }));
- featureFlagsProvider.resetFeature(focusedName);
- }, [featureFlagsProvider, focusedName]);
-
- const handleOverrideFeature = useCallback(() => {
- setError(null);
- if (!focusedName) return;
- try {
- // Nb if value is invalid or missing, JSON parse will fail
- const newValue = JSON.parse(inputValues[focusedName]);
- featureFlagsProvider.overrideFeature(focusedName as FeatureId, newValue);
- } catch (e) {
- setError(e);
- }
- }, [inputValues, focusedName, featureFlagsProvider]);
-
- const handleAddHiddenFlag = useCallback(
- value => {
- setHiddenFlagName(value);
- setSearchInput(value);
- },
- [setSearchInput, setHiddenFlagName],
- );
-
- const handleSearch = useCallback(value => {
- setSearchInput(value);
- }, []);
-
- const filteredFlags = useMemo(() => {
- return Object.entries(featureFlags)
- .sort((a, b) => a[0].localeCompare(b[0]))
- .filter(
- ([name]) =>
- !searchInput || includes(lowerCase(name), lowerCase(searchInput)),
- );
- }, [featureFlags, searchInput]);
-
- return (
-
-
- {t("settings.debug.featureFlagsTitle")}
-
- Legend:
- enabled flag
- disabled flag
-
-
-
-
- (
-
-
-
- )}
- placeholder="Add missing flag"
- onChange={handleAddHiddenFlag}
- autoCapitalize="none"
- />
-
- {filteredFlags.length === 0 ? (
- {`No flag matching "${searchInput}"`}
- ) : null}
- {filteredFlags.map(([flagName, value], index, arr) => {
- const isFocused = focusedName === flagName;
- const isLast = index === arr.length - 1;
- return (
-
- setFocusedName(isFocused ? null : flagName)}
- >
-
- {value?.enabled ? (
- {flagName}
- ) : (
- {flagName}
- )}
- {value?.overridesRemote && (
-
- overridden locally
-
- )}
- {value?.enabledOverriddenForCurrentLanguage && (
-
- disabled for current language
-
- )}
-
-
- {isFocused ? (
-
- ) : null}
- {isFocused && (
-
-
-
- {JSON.stringify(featureFlags[flagName], null, 2)}
-
-
-
- )}
- {!isLast && isFocused ? : null}
-
- );
- })}
-
-
- );
-}
-
-const styles = StyleSheet.create({
- root: {
- padding: 16,
- },
-});
diff --git a/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/FeatureFlagDetails.tsx b/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/FeatureFlagDetails.tsx
new file mode 100644
index 000000000000..4647f48f9a6f
--- /dev/null
+++ b/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/FeatureFlagDetails.tsx
@@ -0,0 +1,85 @@
+import React from "react";
+import { Pressable, View } from "react-native";
+import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
+import type { FeatureId } from "@ledgerhq/types-live";
+
+import { Flex, Box, Tag } from "@ledgerhq/native-ui";
+import styled from "styled-components/native";
+import FeatureFlagEdit from "./FeatureFlagEdit";
+
+export const Divider = styled(Box).attrs({
+ width: "100%",
+ my: 4,
+ height: 1,
+ bg: "neutral.c50",
+})``;
+
+export const TagEnabled = styled(Tag).attrs({
+ bg: "success.c100",
+ uppercase: false,
+ type: "color",
+ mr: 2,
+})``;
+
+export const TagDisabled = styled(Tag).attrs({
+ bg: "error.c100",
+ uppercase: false,
+ type: "color",
+ mr: 2,
+})``;
+
+type Props = {
+ flagName: FeatureId;
+ focused?: boolean;
+ setFocusedName: (arg0: string | undefined) => void;
+ isLast?: boolean;
+};
+
+const FeatureFlagDetails: React.FC = props => {
+ const { flagName, focused, setFocusedName, isLast } = props;
+
+ const { getFeature } = useFeatureFlags();
+ const flagValue = getFeature(flagName as FeatureId);
+
+ if (!flagValue) return null;
+
+ const {
+ overriddenByEnv,
+ overridesRemote,
+ enabledOverriddenForCurrentLanguage,
+ } = flagValue;
+
+ return (
+
+ setFocusedName(focused ? undefined : flagName)}>
+
+ {flagValue?.enabled ? (
+ {flagName}
+ ) : (
+ {flagName}
+ )}
+ {overriddenByEnv ? (
+
+ overridden by env
+
+ ) : overridesRemote ? (
+
+ overridden locally
+
+ ) : null}
+ {enabledOverriddenForCurrentLanguage && (
+
+ disabled for current language
+
+ )}
+
+
+ {focused ? (
+
+ ) : null}
+ {!isLast && focused ? : null}
+
+ );
+};
+
+export default FeatureFlagDetails;
diff --git a/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/FeatureFlagEdit.tsx b/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/FeatureFlagEdit.tsx
new file mode 100644
index 000000000000..f8c0fad6a919
--- /dev/null
+++ b/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/FeatureFlagEdit.tsx
@@ -0,0 +1,112 @@
+import React, { useCallback, useState, useMemo } from "react";
+import { ScrollView } from "react-native";
+import { useTranslation } from "react-i18next";
+import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
+import type { FeatureId, Feature } from "@ledgerhq/types-live";
+
+import { BaseInput, Text, Flex, Button, Switch } from "@ledgerhq/native-ui";
+import { InputRenderRightContainer } from "@ledgerhq/native-ui/components/Form/Input/BaseInput";
+import Alert from "../../components/Alert";
+
+const FeatureFlagEdit: React.FC<{
+ flagName: FeatureId;
+ flagValue: Feature;
+}> = props => {
+ const { flagName, flagValue } = props;
+ const [error, setError] = useState();
+ const [inputValue, setInputValue] = useState(undefined);
+
+ /**
+ * pureValue is the value of the flag without the keys set programmatically
+ * by Legder Live.
+ * */
+ const { overriddenByEnv, overridesRemote, ...pureValue } = flagValue || {};
+
+ const stringifiedPureValue = useMemo(
+ () => (pureValue ? JSON.stringify(pureValue) : undefined),
+ [pureValue],
+ );
+
+ const inputValueDefaulted = inputValue || stringifiedPureValue;
+
+ const featureFlagsProvider = useFeatureFlags();
+
+ const { t } = useTranslation();
+
+ const handleInputChange = useCallback(value => {
+ setError(undefined);
+ setInputValue(value);
+ }, []);
+
+ const handleRestoreFeature = useCallback(() => {
+ setError(undefined);
+ setInputValue(undefined);
+ featureFlagsProvider.resetFeature(flagName);
+ }, [featureFlagsProvider, flagName]);
+
+ const handleOverrideFeature = useCallback(() => {
+ setError(undefined);
+ try {
+ // Nb if value is invalid or missing, JSON parse will fail
+ const newValue = inputValue ? JSON.parse(inputValue) : undefined;
+ featureFlagsProvider.overrideFeature(flagName, newValue);
+ } catch (e) {
+ setError(e);
+ }
+ }, [inputValue, flagName, featureFlagsProvider]);
+
+ const isChecked = useMemo(() => {
+ if (!inputValueDefaulted) return false;
+ try {
+ return JSON.parse(inputValueDefaulted)?.enabled;
+ } catch (e) {
+ return false;
+ }
+ }, [inputValueDefaulted]);
+
+ const handleSwitchChange = useCallback(
+ enabled => {
+ featureFlagsProvider.overrideFeature(flagName, { ...flagValue, enabled });
+ },
+ [featureFlagsProvider, flagName, flagValue],
+ );
+
+ return (
+
+ {error ? (
+
+ {error.toString()}
+
+ ) : null}
+ (
+
+
+
+ )}
+ />
+
+
+
+
+
+
+ {JSON.stringify(pureValue, null, 2)}
+
+
+
+ );
+};
+
+export default FeatureFlagEdit;
diff --git a/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/index.tsx b/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/index.tsx
new file mode 100644
index 000000000000..f2a2f362c066
--- /dev/null
+++ b/apps/ledger-live-mobile/src/screens/FeatureFlagsSettings/index.tsx
@@ -0,0 +1,118 @@
+import React, { useCallback, useState, useMemo } from "react";
+import { StyleSheet, View } from "react-native";
+import { useTranslation } from "react-i18next";
+import { defaultFeatures } from "@ledgerhq/live-common/featureFlags/index";
+import type { FeatureId } from "@ledgerhq/types-live";
+
+import { BaseInput, Text, Flex, SearchInput, Icons } from "@ledgerhq/native-ui";
+import { includes, lowerCase, trim } from "lodash";
+import { InputRenderLeftContainer } from "@ledgerhq/native-ui/components/Form/Input/BaseInput";
+import NavigationScrollView from "../../components/NavigationScrollView";
+import FeatureFlagDetails, {
+ Divider,
+ TagDisabled,
+ TagEnabled,
+} from "./FeatureFlagDetails";
+import Alert from "../../components/Alert";
+
+const addFlagHint = `\
+If a feature flag is defined in the targeted Firebase environment \
+but it is missing from the following list, you can type its name in \
+the input field below and it will appear in the list.\nType the \
+flag name in camelCase without the "feature" prefix.\
+`;
+
+export default function DebugFeatureFlags() {
+ const { t } = useTranslation();
+ const [focusedName, setFocusedName] = useState();
+ const [hiddenFlagName, setHiddenFlagName] = useState("");
+ const trimmedHiddenFlagName = trim(hiddenFlagName);
+ const [searchInput, setSearchInput] = useState("");
+
+ const featureFlags = useMemo(() => {
+ const featureKeys = Object.keys(defaultFeatures);
+ if (trimmedHiddenFlagName && !featureKeys.includes(trimmedHiddenFlagName))
+ featureKeys.push(trimmedHiddenFlagName);
+ return featureKeys;
+ }, [trimmedHiddenFlagName]);
+
+ const handleAddHiddenFlag = useCallback(
+ value => {
+ setHiddenFlagName(trim(value));
+ setSearchInput(value);
+ },
+ [setSearchInput, setHiddenFlagName],
+ );
+
+ const handleSearch = useCallback(value => {
+ setSearchInput(value);
+ }, []);
+
+ const filteredFlags = useMemo(() => {
+ return featureFlags
+ .sort((a, b) => a[0].localeCompare(b[0]))
+ .filter(
+ name =>
+ !searchInput || includes(lowerCase(name), lowerCase(searchInput)),
+ );
+ }, [featureFlags, searchInput]);
+
+ const content = useMemo(
+ () =>
+ filteredFlags.map((flagName, index, arr) => (
+
+ )),
+ [filteredFlags, focusedName],
+ );
+
+ return (
+
+
+ {t("settings.debug.featureFlagsTitle")}
+
+ Legend:
+ enabled flag
+ disabled flag
+
+
+
+
+
+
+ (
+
+
+
+ )}
+ placeholder="Add missing flag (instructions above)"
+ onChange={handleAddHiddenFlag}
+ autoCapitalize="none"
+ />
+
+ {filteredFlags.length === 0 ? (
+ {`No flag matching "${searchInput}"`}
+ ) : null}
+ {content}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: {
+ padding: 16,
+ },
+});
diff --git a/libs/ledger-live-common/src/env.ts b/libs/ledger-live-common/src/env.ts
index 96c2c025c660..c143cd18b993 100644
--- a/libs/ledger-live-common/src/env.ts
+++ b/libs/ledger-live-common/src/env.ts
@@ -29,6 +29,23 @@ const boolParser = (v: unknown): boolean | null | undefined => {
const stringParser = (v: unknown): string | null | undefined =>
typeof v === "string" ? v : undefined;
+type JSONValue =
+ | string
+ | number
+ | boolean
+ | null
+ | { [x: string]: JSONValue }
+ | Array;
+
+const jsonParser = (v: unknown): JSONValue | undefined => {
+ try {
+ if (typeof v !== "string") throw new Error();
+ return JSON.parse(v);
+ } catch (e) {
+ return undefined;
+ }
+};
+
const envDefinitions = {
ANALYTICS_CONSOLE: {
def: false,
@@ -644,6 +661,11 @@ const envDefinitions = {
parser: boolParser,
desc: "use the staging URL for the learn page",
},
+ FEATURE_FLAGS: {
+ def: "",
+ parser: jsonParser,
+ desc: "key value map for feature flags: {[key in FeatureId]?: Feature]}",
+ },
};
const getDefinition = (name: string): EnvDef | null | undefined =>
diff --git a/libs/ledgerjs/packages/types-live/README.md b/libs/ledgerjs/packages/types-live/README.md
index 69b66c83dc81..41e4d8f13591 100644
--- a/libs/ledgerjs/packages/types-live/README.md
+++ b/libs/ledgerjs/packages/types-live/README.md
@@ -60,6 +60,7 @@ Ledger Live main types.
* [languages_blacklisted](#languages_blacklisted)
* [enabledOverriddenForCurrentLanguage](#enabledoverriddenforcurrentlanguage)
* [overridesRemote](#overridesremote)
+ * [overriddenByEnv](#overriddenbyenv)
* [params](#params)
* [DefaultFeatures](#defaultfeatures)
* [LedgerScriptParams](#ledgerscriptparams)
@@ -493,7 +494,7 @@ Type: (`"learn"` | `"pushNotifications"` | `"llmUsbFirmwareUpdate"` | `"ratings"
We use objects instead of direct booleans for potential future improvements
like feature versioning etc
-Type: {enabled: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), desktop_version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, enabledOverriddenForCurrentDesktopVersion: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, languages_whitelisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, languages_blacklisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, enabledOverriddenForCurrentLanguage: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, overridesRemote: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, params: any?}
+Type: {enabled: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), desktop_version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, enabledOverriddenForCurrentDesktopVersion: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, languages_whitelisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, languages_blacklisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, enabledOverriddenForCurrentLanguage: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, overridesRemote: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, overriddenByEnv: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, params: any?}
#### Properties
@@ -504,6 +505,7 @@ Type: {enabled: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Refe
* `languages_blacklisted` **\[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?**
* `enabledOverriddenForCurrentLanguage` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
* `overridesRemote` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `overriddenByEnv` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
* `params` **any?**
#### enabled
@@ -566,6 +568,12 @@ Whether the remote value of this object was overriden locally
Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+#### overriddenByEnv
+
+Whether the remote value of this object was overriden by an environment variable
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
#### params
Additional params
@@ -1403,3 +1411,925 @@ Type: {errors: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript
* `totalSpent` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
* `useAllAmount` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
* `recipientIsReadOnly` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+
+# <<<<<<< 459e02d258e1aa0e3d946e951b104da7ca6ab275
Type: {enabled: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), desktop_version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, enabledOverriddenForCurrentDesktopVersion: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, languages_whitelisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, languages_blacklisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, enabledOverriddenForCurrentLanguage: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, overridesRemote: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, params: any?}
+
+Type: {enabled: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), languages_whitelisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, languages_blacklisted: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?, enabledOverriddenForCurrentLanguage: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, overridesRemote: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, overriddenByEnv: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, params: any?}
+
+> > > > > > > Add env variable FEATURE_FLAGS for overriding flags with env
+
+#### Properties
+
+* `enabled` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `desktop_version` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `enabledOverriddenForCurrentDesktopVersion` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `languages_whitelisted` **\[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?**
+* `languages_blacklisted` **\[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]?**
+* `enabledOverriddenForCurrentLanguage` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `overridesRemote` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `overriddenByEnv` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `params` **any?**
+
+#### enabled
+
+If false, the feature is disabled (for every languages regardless of the languages_whitelisted option)
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
+#### desktop_version
+
+The `desktop_version` option is desktop specific, it has no impact on mobile
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### desktop_version
+
+If set, the feature is disabled when the desktop app version does not satisfies this param
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### desktop_version
+
+It should respect the semantic versioning specification (https://semver.org/)
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### enabledOverriddenForCurrentDesktopVersion
+
+Whether the remote value of `enabled` was overriden due to `desktop_version`
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
+#### languages_whitelisted
+
+You can optionnally use one of the two following options (languages_whitelisted and languages_blacklisted) (Only implemented on mobile for now)
+
+Type: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]
+
+#### languages_whitelisted
+
+List of languages for which the feature is enabled (it will be disabled by default for all of the others)
+
+Type: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]
+
+#### languages_blacklisted
+
+List of languages for which the feature is disabled
+
+Type: \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]
+
+#### enabledOverriddenForCurrentLanguage
+
+Whether the remote value of `enabled` was overriden due to `languages_whitelisted` or `languages_blacklisted`
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
+#### overridesRemote
+
+Whether the remote value of this object was overriden locally
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
+#### overriddenByEnv
+
+Whether the remote value of this object was overriden by an environment variable
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
+#### params
+
+Additional params
+
+Type: any
+
+### DefaultFeatures
+
+Type: any
+
+### LedgerScriptParams
+
+Type: {firmware: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), firmwareKey: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), delete: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, deleteKey: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, targetId: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))?, hash: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), perso: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}
+
+#### Properties
+
+* `firmware` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `firmwareKey` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `delete` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `deleteKey` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `targetId` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))?**
+* `hash` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `perso` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+
+### DeviceInfo
+
+Type: {mcuVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), majMin: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), targetId: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)), isBootloader: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), isRecoveryMode: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, isOSU: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), providerName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), managerAllowed: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), pinValidated: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), seVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, mcuBlVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, mcuTargetId: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, seTargetId: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, onboarded: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, hasDevFirmware: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, bootloaderVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, hardwareVersion: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, languageId: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?}
+
+#### Properties
+
+* `mcuVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `version` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `majMin` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `targetId` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))**
+* `isBootloader` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `isRecoveryMode` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `isOSU` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `providerName` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `managerAllowed` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `pinValidated` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `seVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `mcuBlVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `mcuTargetId` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `seTargetId` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `onboarded` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `hasDevFirmware` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `bootloaderVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `hardwareVersion` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `languageId` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+
+### DeviceModelInfo
+
+Type: {modelId: DeviceModelId, deviceInfo: [DeviceInfo](#deviceinfo), apps: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<{name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}>}
+
+#### Properties
+
+* `modelId` **DeviceModelId**
+* `deviceInfo` **[DeviceInfo](#deviceinfo)**
+* `apps` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<{name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}>**
+
+### DeviceVersion
+
+Type: {id: Id, name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), display_name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), target_id: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), description: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), device: Id, providers: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, mcu_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, se_firmware_final_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, osu_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, application_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, date_creation: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), date_last_modified: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}
+
+#### Properties
+
+* `id` **Id**
+* `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `display_name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `target_id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `description` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `device` **Id**
+* `providers` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `mcu_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `se_firmware_final_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `osu_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `application_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `date_creation` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `date_last_modified` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+
+### McuVersion
+
+Type: {id: Id, mcu: Id, name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), providers: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, from_bootloader_version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), device_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, se_firmware_final_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, date_creation: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), date_last_modified: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}
+
+#### Properties
+
+* `id` **Id**
+* `mcu` **Id**
+* `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `description` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `providers` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `from_bootloader_version` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `device_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `se_firmware_final_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `date_creation` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `date_last_modified` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+
+### SeedPhraseType
+
+### FirmwareInfo
+
+Type: {isBootloader: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), rawVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), targetId: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), seVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, mcuVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), mcuBlVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, mcuTargetId: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, seTargetId: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, flags: [Buffer](https://nodejs.org/api/buffer.html), bootloaderVersion: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, hardwareVersion: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, languageId: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?}
+
+#### Properties
+
+* `isBootloader` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `rawVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `targetId` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+* `seVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `mcuVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `mcuBlVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `mcuTargetId` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `seTargetId` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `flags` **[Buffer](https://nodejs.org/api/buffer.html)**
+* `bootloaderVersion` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `hardwareVersion` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `languageId` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+
+### OsuFirmware
+
+Type: any
+
+### FinalFirmware
+
+Type: any
+
+### FirmwareUpdateContext
+
+Type: {osu: [OsuFirmware](#osufirmware), final: [FinalFirmware](#finalfirmware), shouldFlashMCU: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)}
+
+#### Properties
+
+* `osu` **[OsuFirmware](#osufirmware)**
+* `final` **[FinalFirmware](#finalfirmware)**
+* `shouldFlashMCU` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+
+### ApplicationVersion
+
+Type: {id: Id, name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), app: Id, description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), display_name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), icon: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), notes: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), perso: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), hash: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), firmware: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), firmware_key: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), delete: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), delete_key: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), device_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, se_firmware_final_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, providers: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, date_creation: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), date_last_modified: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), type: [AppType](#apptype)?, bytes: ([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), warning: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), currency: CryptoCurrency?}
+
+#### Properties
+
+* `id` **Id**
+* `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `version` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `app` **Id**
+* `description` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `display_name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `icon` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `notes` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `perso` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `hash` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `firmware` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `firmware_key` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `delete` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `delete_key` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `device_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `se_firmware_final_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `providers` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `date_creation` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `date_last_modified` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `type` **[AppType](#apptype)?**
+* `bytes` **([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `warning` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `currency` **CryptoCurrency?**
+
+### Application
+
+Type: {id: Id, name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), application_versions: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[ApplicationVersion](#applicationversion)>, providers: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, category: Id, publisher: (Id | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), date_creation: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), date_last_modified: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), currencyId: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), authorName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), supportURL: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), contactURL: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), sourceURL: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), compatibleWalletsJSON: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))}
+
+#### Properties
+
+* `id` **Id**
+* `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `description` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `application_versions` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[ApplicationVersion](#applicationversion)>**
+* `providers` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `category` **Id**
+* `publisher` **(Id | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `date_creation` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `date_last_modified` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `currencyId` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `authorName` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `supportURL` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `contactURL` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `sourceURL` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `compatibleWalletsJSON` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+
+### AppType
+
+### App
+
+App is higher level on top of Application and ApplicationVersion
+with all fields Live needs and in normalized form (but still serializable)
+
+Type: {id: Id, name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), displayName: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), version: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), currencyId: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), dateModified: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), icon: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), authorName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), supportURL: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), contactURL: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), sourceURL: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), compatibleWallets: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<{name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), url: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))}>, hash: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), perso: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), firmware: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), firmware_key: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), delete: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), delete_key: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), dependencies: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>, bytes: ([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), warning: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), indexOfMarketCap: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), isDevTools: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), type: [AppType](#apptype)}
+
+#### Properties
+
+* `id` **Id**
+* `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `displayName` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `version` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `currencyId` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `description` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `dateModified` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `icon` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `authorName` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `supportURL` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `contactURL` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `sourceURL` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `compatibleWallets` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<{name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), url: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))}>**
+* `hash` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `perso` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `firmware` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `firmware_key` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `delete` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `delete_key` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `dependencies` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+* `bytes` **([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `warning` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `indexOfMarketCap` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+* `isDevTools` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `type` **[AppType](#apptype)**
+
+### Category
+
+Type: {id: Id, name: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), providers: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, applications: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\, date_creation: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), date_last_modified: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}
+
+#### Properties
+
+* `id` **Id**
+* `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `description` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `providers` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `applications` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+* `date_creation` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `date_last_modified` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+
+### SocketEvent
+
+Type: ({type: `"bulk-progress"`, progress: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), index: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), total: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)} | {type: `"result"`, payload: any} | {type: `"warning"`, message: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)} | {type: `"device-permission-requested"`, wording: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)} | {type: `"device-permission-granted"`} | {type: `"exchange-before"`, nonce: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), apdu: [Buffer](https://nodejs.org/api/buffer.html)} | {type: `"exchange"`, nonce: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), apdu: [Buffer](https://nodejs.org/api/buffer.html), data: [Buffer](https://nodejs.org/api/buffer.html), status: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)} | {type: `"opened"`} | {type: `"closed"`})
+
+### NFTStandard
+
+Type: (`"ERC721"` | `"ERC1155"`)
+
+### NFTMediaSize
+
+Type: (`"preview"` | `"big"` | `"original"`)
+
+### NFTMedias
+
+Type: Record<[NFTMediaSize](#nftmediasize), {uri: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), mediaType: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}>
+
+### NFTMetadata
+
+Type: {tokenName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), nftName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), medias: [NFTMedias](#nftmedias), description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), properties: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\>, links: Record<[NFTMetadataLinksProviders](#nftmetadatalinksproviders), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>}
+
+#### Properties
+
+* `tokenName` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null)**
+* `nftName` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null)**
+* `medias` **[NFTMedias](#nftmedias)**
+* `description` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null)**
+* `properties` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\>**
+* `links` **Record<[NFTMetadataLinksProviders](#nftmetadatalinksproviders), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+
+### NFTCollectionMetadata
+
+Type: {tokenName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null)}
+
+#### Properties
+
+* `tokenName` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null)**
+
+### ProtoNFT
+
+Type: {id: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), amount: BigNumber, contract: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), standard: [NFTStandard](#nftstandard), currencyId: CryptoCurrencyIds, metadata: [NFTMetadata](#nftmetadata)?}
+
+#### Properties
+
+* `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `tokenId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `amount` **BigNumber**
+* `contract` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `standard` **[NFTStandard](#nftstandard)**
+* `currencyId` **CryptoCurrencyIds**
+* `metadata` **[NFTMetadata](#nftmetadata)?**
+
+### ProtoNFTRaw
+
+Type: any
+
+### NFT
+
+Type: any
+
+### NFTMetadataLinksProviders
+
+Type: (`"opensea"` | `"rarible"` | `"explorer"`)
+
+### NFTMetadataResponse
+
+Type: {status: (`200` | `404` | `500`), result: ({contract: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), nftName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), medias: [NFTMedias](#nftmedias), description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), properties: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\>, links: Record<[NFTMetadataLinksProviders](#nftmetadatalinksproviders), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>} | null)?}
+
+#### Properties
+
+* `status` **(`200` | `404` | `500`)**
+* `result` **({contract: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), nftName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), medias: [NFTMedias](#nftmedias), description: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null), properties: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\>, links: Record<[NFTMetadataLinksProviders](#nftmetadatalinksproviders), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>} | null)?**
+
+### NFTCollectionMetadataResponse
+
+Type: {status: (`200` | `404` | `500`), result: ({contract: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null)} | null)?}
+
+#### Properties
+
+* `status` **(`200` | `404` | `500`)**
+* `result` **({contract: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenName: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null)} | null)?**
+
+### FloorPrice
+
+Type: {ticker: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), value: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}
+
+#### Properties
+
+* `ticker` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `value` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+
+### OperationType
+
+Type: (`"IN"` | `"OUT"` | `"NONE"` | `"CREATE"` | `"REVEAL"` | `"DELEGATE"` | `"UNDELEGATE"` | `"REDELEGATE"` | `"REWARD"` | `"FEES"` | `"FREEZE"` | `"UNFREEZE"` | `"VOTE"` | `"REWARD_PAYOUT"` | `"BOND"` | `"UNBOND"` | `"WITHDRAW_UNBONDED"` | `"SET_CONTROLLER"` | `"SLASH"` | `"NOMINATE"` | `"CHILL"` | `"SUPPLY"` | `"REDEEM"` | `"APPROVE"` | `"OPT_IN"` | `"OPT_OUT"` | `"LOCK"` | `"UNLOCK"` | `"WITHDRAW"` | `"REVOKE"` | `"ACTIVATE"` | `"REGISTER"` | `"NFT_IN"` | `"NFT_OUT"`)
+
+### Operation
+
+Type: {id: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), hash: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), type: [OperationType](#operationtype), value: BigNumber, fee: BigNumber, senders: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>, recipients: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>, blockHeight: ([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), blockHash: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), transactionSequenceNumber: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, accountId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), standard: ([NFTStandard](#nftstandard) | [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String))?, operator: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, contract: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, tokenId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, date: [Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date), extra: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>, hasFailed: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, subOperations: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>?, internalOperations: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>?, nftOperations: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>?}
+
+#### Properties
+
+* `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `hash` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `type` **[OperationType](#operationtype)**
+* `value` **BigNumber**
+* `fee` **BigNumber**
+* `senders` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+* `recipients` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+* `blockHeight` **([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `blockHash` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `transactionSequenceNumber` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `accountId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `standard` **([NFTStandard](#nftstandard) | [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String))?**
+* `operator` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `contract` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `tokenId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `date` **[Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date)**
+* `extra` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>**
+* `hasFailed` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `subOperations` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>?**
+* `internalOperations` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>?**
+* `nftOperations` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>?**
+
+### OperationRaw
+
+Type: {id: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), hash: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), type: [OperationType](#operationtype), value: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), fee: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), senders: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>, recipients: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>, blockHeight: ([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), blockHash: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), transactionSequenceNumber: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, accountId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), hasFailed: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, standard: ([NFTStandard](#nftstandard) | [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String))?, operator: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, contract: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, tokenId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, date: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), extra: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>, subOperations: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[OperationRaw](#operationraw)>?, internalOperations: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[OperationRaw](#operationraw)>?, nftOperations: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[OperationRaw](#operationraw)>?}
+
+#### Properties
+
+* `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `hash` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `type` **[OperationType](#operationtype)**
+* `value` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `fee` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `senders` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+* `recipients` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+* `blockHeight` **([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `blockHash` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `transactionSequenceNumber` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `accountId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `hasFailed` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `standard` **([NFTStandard](#nftstandard) | [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String))?**
+* `operator` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `contract` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `tokenId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `date` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `extra` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>**
+* `subOperations` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[OperationRaw](#operationraw)>?**
+* `internalOperations` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[OperationRaw](#operationraw)>?**
+* `nftOperations` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[OperationRaw](#operationraw)>?**
+
+### DailyOperationsSection
+
+Type: {day: [Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date), data: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>}
+
+#### Properties
+
+* `day` **[Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date)**
+* `data` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Operation](#operation)>**
+
+### DailyOperations
+
+Type: {sections: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[DailyOperationsSection](#dailyoperationssection)>, completed: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)}
+
+#### Properties
+
+* `sections` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[DailyOperationsSection](#dailyoperationssection)>**
+* `completed` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+
+### PaginationConfig
+
+A pagination config holds the user's pagination state
+this is a state that usually should leave during the app lifecycle, but is not persisted
+it drives the number of operations to poll in accounts
+when a user paginate more, the number should accordingly be incremented
+The UI should manage scrolling ahead of time (e.g. if 30 ops is displayed and UI have pages of 20 ops, the UI can already request to poll 70 ops so it have 2 pages in advance)
+The UI must always do max() to keep the increasing the counter and not going back to lower value: that optim the sync to not recompute things too much
+
+Type: {operationsPerAccountId: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)>?, operations: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?}
+
+#### Properties
+
+* `operationsPerAccountId` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)>?**
+* `operations` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+
+### SyncConfig
+
+Type: {paginationConfig: [PaginationConfig](#paginationconfig), withoutSynchronize: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, blacklistedTokenIds: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>?}
+
+#### Properties
+
+* `paginationConfig` **[PaginationConfig](#paginationconfig)**
+* `withoutSynchronize` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `blacklistedTokenIds` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>?**
+
+### BalanceHistoryData
+
+Type: {date: [Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date), value: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}
+
+#### Properties
+
+* `date` **[Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date)**
+* `value` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+
+### BalanceHistory
+
+Type: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[BalanceHistoryData](#balancehistorydata)>
+
+### BalanceHistoryRaw
+
+Type: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<\[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)]>
+
+### BalanceHistoryWithCountervalue
+
+Type: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\
+
+### ValueChange
+
+Type: {percentage: ([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)), value: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}
+
+#### Properties
+
+* `percentage` **([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+* `value` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+
+### AccountPortfolio
+
+Type: {history: [BalanceHistoryWithCountervalue](#balancehistorywithcountervalue), countervalueAvailable: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), countervalueReceiveSum: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), countervalueSendSum: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), cryptoChange: [ValueChange](#valuechange), countervalueChange: [ValueChange](#valuechange)}
+
+#### Properties
+
+* `history` **[BalanceHistoryWithCountervalue](#balancehistorywithcountervalue)**
+* `countervalueAvailable` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `countervalueReceiveSum` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+* `countervalueSendSum` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+* `cryptoChange` **[ValueChange](#valuechange)**
+* `countervalueChange` **[ValueChange](#valuechange)**
+
+### CurrencyPortfolio
+
+Type: {history: [BalanceHistoryWithCountervalue](#balancehistorywithcountervalue), countervalueAvailable: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), histories: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[BalanceHistoryWithCountervalue](#balancehistorywithcountervalue)>, accounts: [AccountLikeArray](#accountlikearray), cryptoChange: [ValueChange](#valuechange), range: [PortfolioRange](#portfoliorange), countervalueChange: [ValueChange](#valuechange)}
+
+#### Properties
+
+* `history` **[BalanceHistoryWithCountervalue](#balancehistorywithcountervalue)**
+* `countervalueAvailable` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `histories` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[BalanceHistoryWithCountervalue](#balancehistorywithcountervalue)>**
+* `accounts` **[AccountLikeArray](#accountlikearray)**
+* `cryptoChange` **[ValueChange](#valuechange)**
+* `range` **[PortfolioRange](#portfoliorange)**
+* `countervalueChange` **[ValueChange](#valuechange)**
+
+### Portfolio
+
+Type: {balanceHistory: [BalanceHistory](#balancehistory), balanceAvailable: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), availableAccounts: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[AccountLike](#accountlike)>, unavailableCurrencies: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<(CryptoCurrency | TokenCurrency)>, accounts: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[AccountLike](#accountlike)>, range: [PortfolioRange](#portfoliorange), histories: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[BalanceHistoryWithCountervalue](#balancehistorywithcountervalue)>, countervalueReceiveSum: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), countervalueSendSum: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), countervalueChange: [ValueChange](#valuechange)}
+
+#### Properties
+
+* `balanceHistory` **[BalanceHistory](#balancehistory)**
+* `balanceAvailable` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `availableAccounts` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[AccountLike](#accountlike)>**
+* `unavailableCurrencies` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<(CryptoCurrency | TokenCurrency)>**
+* `accounts` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[AccountLike](#accountlike)>**
+* `range` **[PortfolioRange](#portfoliorange)**
+* `histories` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[BalanceHistoryWithCountervalue](#balancehistorywithcountervalue)>**
+* `countervalueReceiveSum` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+* `countervalueSendSum` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+* `countervalueChange` **[ValueChange](#valuechange)**
+
+### PortfolioRangeConfig
+
+Type: {count: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?, granularityId: GranularityId, startOf: function (arg0: [Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date)): [Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date), increment: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}
+
+#### Properties
+
+* `count` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
+* `granularityId` **GranularityId**
+* `startOf` **function (arg0: [Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date)): [Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date)**
+* `increment` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+
+### PortfolioRange
+
+Type: (`"all"` | `"year"` | `"month"` | `"week"` | `"day"`)
+
+### AssetsDistribution
+
+Type: {isAvailable: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), list: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<{currency: (CryptoCurrency | TokenCurrency), accounts: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[AccountLike](#accountlike)>, distribution: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), amount: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), countervalue: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}>, showFirst: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), sum: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}
+
+#### Properties
+
+* `isAvailable` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `list` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<{currency: (CryptoCurrency | TokenCurrency), accounts: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[AccountLike](#accountlike)>, distribution: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), amount: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), countervalue: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}>**
+* `showFirst` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+* `sum` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
+
+### PostOnboardingActionId
+
+Unique identifier of a post onboarding action.
+
+### PostOnboardingAction
+
+All necessary information for complete integration of a post onboarding
+action.
+
+Type: {id: [PostOnboardingActionId](#postonboardingactionid), featureFlagId: [FeatureId](#featureid)?, navigationParams: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\?, Icon: function (props: {size: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), color: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}): any, title: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), description: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tagLabel: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, actionCompletedPopupLabel: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), actionCompletedHubTitle: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), startEvent: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, startEventProperties: any?}
+
+#### Properties
+
+* `id` **[PostOnboardingActionId](#postonboardingactionid)**
+* `featureFlagId` **[FeatureId](#featureid)?**
+* `navigationParams` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\?**
+* `Icon` **function (props: {size: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), color: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}): any**
+* `title` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `description` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `tagLabel` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `actionCompletedPopupLabel` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `actionCompletedHubTitle` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `startEvent` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `startEventProperties` **any?**
+
+#### featureFlagId
+
+If this action is linked to a feature that is enabled by a feature flag,
+use this property to identify the feature flag.
+
+Type: [FeatureId](#featureid)
+
+#### navigationParams
+
+Navigation params when the user presses the button for this action
+
+* In LLM, this will be used like this:
+ `navigation.navigate(...navigationParams)`
+* In LLD, this will be used like this:
+ `history.push(...navigationParams)`
+
+Type: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\
+
+#### Icon
+
+Icon displayed for this action in the post onboarding hub.
+
+Type: function (props: {size: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), color: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}): any
+
+#### title
+
+Title displayed for this action in the post onboarding hub.
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### description
+
+Description displayed for this action in the post onboarding hub.
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### tagLabel
+
+Tag displayed for this action in the post onboarding hub.
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### actionCompletedPopupLabel
+
+Will appear in an success alert at the bottom of the post-onboarding hub
+after completing this action.
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### actionCompletedHubTitle
+
+Will be used as a title success alert at the bottom of the post-onboarding
+hub after completing this action.
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### startEvent
+
+Event that will be dispatched when starting this action.
+
+Type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
+
+#### startEventProperties
+
+Event properties that will be dispatched when starting this action.
+
+Type: any
+
+### PostOnboardingActionState
+
+State of a post onboarding action.
+
+Type: {completed: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)}
+
+#### Properties
+
+* `completed` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+
+#### completed
+
+Whether the user has completed this action. This will be reflected in the
+UI of the post onboarding hub.
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
+### PostOnboardingState
+
+To be used for a redux reducer.
+Keeps all necessary information about the state of the post onboarding hub
+and can be persisted in storage.
+
+Type: {deviceModelId: (DeviceModelId | null), walletEntryPointDismissed: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), actionsToComplete: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[PostOnboardingActionId](#postonboardingactionid)>, actionsCompleted: any, lastActionCompleted: ([PostOnboardingActionId](#postonboardingactionid) | null)}
+
+#### Properties
+
+* `deviceModelId` **(DeviceModelId | null)**
+* `walletEntryPointDismissed` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
+* `actionsToComplete` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[PostOnboardingActionId](#postonboardingactionid)>**
+* `actionsCompleted` **any**
+* `lastActionCompleted` **([PostOnboardingActionId](#postonboardingactionid) | null)**
+
+#### deviceModelId
+
+Model Id of the device for which the post onboarding was started.
+
+Type: (DeviceModelId | null)
+
+#### walletEntryPointDismissed
+
+Did the user dismiss the post onboarding entry point on the wallet page.
+
+Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
+
+#### actionsToComplete
+
+List of all actions that have to be completed in this post onboarding
+(whether they are completed or).
+This is used to populate the list of actions in the post onboarding hub UI.
+
+Type: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[PostOnboardingActionId](#postonboardingactionid)>
+
+#### actionsCompleted
+
+"completed" state for each action.
+
+Type: any
+
+#### lastActionCompleted
+
+Last action that the user has completed.
+
+This is used to display potentially different content in the post
+onboarding hub UI depending on the last action that was completed.
+
+Type: ([PostOnboardingActionId](#postonboardingactionid) | null)
+
+### PostOnboardingHubState
+
+Digest of the store & list of actions into something directly consumable
+by UI. (All UI data will be in there).
+
+Type: {deviceModelId: (DeviceModelId | null), lastActionCompleted: ([PostOnboardingAction](#postonboardingaction) | null), actionsState: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\}
+
+#### Properties
+
+* `deviceModelId` **(DeviceModelId | null)**
+* `lastActionCompleted` **([PostOnboardingAction](#postonboardingaction) | null)**
+* `actionsState` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\**
+
+### SwapOperation
+
+Type: {provider: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), swapId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), status: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), receiverAccountId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, operationId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), fromAmount: BigNumber, toAmount: BigNumber}
+
+#### Properties
+
+* `provider` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `swapId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `status` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `receiverAccountId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `tokenId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `operationId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `fromAmount` **BigNumber**
+* `toAmount` **BigNumber**
+
+### SwapOperationRaw
+
+Type: {provider: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), swapId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), status: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), receiverAccountId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), tokenId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?, operationId: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), fromAmount: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), toAmount: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}
+
+#### Properties
+
+* `provider` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `swapId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `status` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `receiverAccountId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `tokenId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
+* `operationId` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `fromAmount` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `toAmount` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+
+### SignedOperation
+
+Type: {operation: [Operation](#operation), signature: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), signatureRaw: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>?, expirationDate: ([Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))}
+
+#### Properties
+
+* `operation` **[Operation](#operation)**
+* `signature` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `signatureRaw` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>?**
+* `expirationDate` **([Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+
+### SignedOperationRaw
+
+Type: {operation: [OperationRaw](#operationraw), signature: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), signatureRaw: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>?, expirationDate: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))}
+
+#### Properties
+
+* `operation` **[OperationRaw](#operationraw)**
+* `signature` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `signatureRaw` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), any>?**
+* `expirationDate` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
+
+### SignOperationEvent
+
+Type: ({type: `"device-streaming"`, progress: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), index: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), total: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)} | {type: `"device-signature-requested"`} | {type: `"device-signature-granted"`} | {type: `"signed"`, signedOperation: [SignedOperation](#signedoperation)})
+
+### SignOperationEventRaw
+
+Type: ({type: `"device-streaming"`, progress: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), index: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), total: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)} | {type: `"device-signature-requested"`} | {type: `"device-signature-granted"`} | {type: `"signed"`, signedOperation: [SignedOperationRaw](#signedoperationraw)})
+
+### TransactionCommon
+
+Transaction is a generic object that holds all state for all transactions
+there are generic fields and coin specific fields. That's why almost all fields are optionals
+
+Type: {amount: BigNumber, recipient: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), useAllAmount: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, subAccountId: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))?, feesStrategy: (`"slow"` | `"medium"` | `"fast"` | `"custom"` | null)?}
+
+#### Properties
+
+* `amount` **BigNumber**
+* `recipient` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `useAllAmount` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `subAccountId` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))?**
+* `feesStrategy` **(`"slow"` | `"medium"` | `"fast"` | `"custom"` | null)?**
+
+### TransactionCommonRaw
+
+Type: {amount: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), recipient: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), useAllAmount: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, subAccountId: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))?, feesStrategy: (`"slow"` | `"medium"` | `"fast"` | `"custom"` | null)?}
+
+#### Properties
+
+* `amount` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `recipient` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `useAllAmount` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `subAccountId` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | null | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))?**
+* `feesStrategy` **(`"slow"` | `"medium"` | `"fast"` | `"custom"` | null)?**
+
+### FeeStrategy
+
+User can have 3 differents choice for their fee
+Most of the time mid is low \* 1.25 and high is low \* 1.5
+They are some exception as eth that got his own meter
+
+Type: {amount: BigNumber, displayedAmount: BigNumber?, label: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), unit: Unit?}
+
+#### Properties
+
+* `amount` **BigNumber**
+* `displayedAmount` **BigNumber?**
+* `label` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `unit` **Unit?**
+
+### TransactionStatusCommon
+
+TransactionStatus is a view of Transaction with general info to be used on the UI and status info.
+
+Type: {errors: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)>, warnings: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)>, estimatedFees: BigNumber, amount: BigNumber, totalSpent: BigNumber, recipientIsReadOnly: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?}
+
+#### Properties
+
+* `errors` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)>**
+* `warnings` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)>**
+* `estimatedFees` **BigNumber**
+* `amount` **BigNumber**
+* `totalSpent` **BigNumber**
+* `recipientIsReadOnly` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+
+### TransactionStatusCommonRaw
+
+Type: {errors: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>, warnings: Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>, estimatedFees: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), amount: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), totalSpent: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), useAllAmount: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?, recipientIsReadOnly: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?}
+
+#### Properties
+
+* `errors` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+* `warnings` **Record<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
+* `estimatedFees` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `amount` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `totalSpent` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
+* `useAllAmount` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
+* `recipientIsReadOnly` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
diff --git a/libs/ledgerjs/packages/types-live/src/feature.ts b/libs/ledgerjs/packages/types-live/src/feature.ts
index 035000286c66..5170a969398b 100644
--- a/libs/ledgerjs/packages/types-live/src/feature.ts
+++ b/libs/ledgerjs/packages/types-live/src/feature.ts
@@ -49,6 +49,8 @@ export type Feature = {
enabledOverriddenForCurrentLanguage?: boolean;
/** Whether the remote value of this object was overriden locally */
overridesRemote?: boolean;
+ /** Whether the remote value of this object was overriden by an environment variable */
+ overriddenByEnv?: boolean;
/** Additional params */
params?: any;
};