> = ({ isApiError, setO
setIsApiError(true);
}
})
- .finally(() => setLoading(false));
+ .finally(() => setOrderIsProcessing(false));
};
const handleInputAmountChange = (amount?: number) => setInputAmount(amount);
+ const isLoading = orderIsProcessing || estimationIsLoading || isMinMaxLoading;
+
return (
<>
@@ -156,7 +157,7 @@ export const InitialStep: FC> = ({ isApiError, setO
paddingTop: '0.625rem',
paddingBottom: '0.625rem'
}}
- loading={isLoading || isMinMaxLoading}
+ loading={isLoading}
testID={WithdrawSelectors.AliceBobNextButton}
onClick={handleSubmit}
>
diff --git a/src/app/store/balance-mode/actions.ts b/src/app/store/balance-mode/actions.ts
new file mode 100644
index 0000000000..b4f3a7f089
--- /dev/null
+++ b/src/app/store/balance-mode/actions.ts
@@ -0,0 +1,5 @@
+import { createAction } from '@reduxjs/toolkit';
+
+import { BalanceMode } from './state';
+
+export const toggleBalanceMode = createAction('balance-mode/TOGGLE_BALANCE_MODE');
diff --git a/src/app/store/balance-mode/reducers.ts b/src/app/store/balance-mode/reducers.ts
new file mode 100644
index 0000000000..6bef9a20b1
--- /dev/null
+++ b/src/app/store/balance-mode/reducers.ts
@@ -0,0 +1,10 @@
+import { createReducer } from '@reduxjs/toolkit';
+
+import { toggleBalanceMode } from './actions';
+import { balanceModeInitialState, BalanceModeState } from './state';
+
+export const balanceModeReducer = createReducer(balanceModeInitialState, builder => {
+ builder.addCase(toggleBalanceMode, (state, { payload }) => {
+ state.balanceMode = payload;
+ });
+});
diff --git a/src/app/store/balance-mode/selectors.ts b/src/app/store/balance-mode/selectors.ts
new file mode 100644
index 0000000000..e6bf370ec3
--- /dev/null
+++ b/src/app/store/balance-mode/selectors.ts
@@ -0,0 +1,3 @@
+import { useSelector } from '../index';
+
+export const useBalanceModeSelector = () => useSelector(({ balanceMode }) => balanceMode.balanceMode);
diff --git a/src/app/store/balance-mode/state.mock.ts b/src/app/store/balance-mode/state.mock.ts
new file mode 100644
index 0000000000..9d5e484cbb
--- /dev/null
+++ b/src/app/store/balance-mode/state.mock.ts
@@ -0,0 +1,5 @@
+import { BalanceMode, BalanceModeState } from './state';
+
+export const mockBalanceModeState: BalanceModeState = {
+ balanceMode: BalanceMode.Fiat
+};
diff --git a/src/app/store/balance-mode/state.ts b/src/app/store/balance-mode/state.ts
new file mode 100644
index 0000000000..8a58c4eb46
--- /dev/null
+++ b/src/app/store/balance-mode/state.ts
@@ -0,0 +1,10 @@
+export enum BalanceMode {
+ Fiat = 'fiat',
+ Gas = 'gas'
+}
+export interface BalanceModeState {
+ balanceMode: BalanceMode;
+}
+export const balanceModeInitialState: BalanceModeState = {
+ balanceMode: BalanceMode.Fiat
+};
diff --git a/src/app/store/index.ts b/src/app/store/index.ts
index 878bbff761..60c83deef7 100644
--- a/src/app/store/index.ts
+++ b/src/app/store/index.ts
@@ -8,6 +8,7 @@ import { createStore, GetStateType, rootStateReducer } from 'lib/store';
import { advertisingEpics } from './advertising/epics';
import { advertisingReducer } from './advertising/reducers';
+import { balanceModeReducer } from './balance-mode/reducers';
import { currencyEpics } from './currency/epics';
import { currencyReducer } from './currency/reducers';
import { dAppsEpics } from './d-apps/epics';
@@ -17,7 +18,8 @@ const baseReducer = rootStateReducer({
advertising: advertisingReducer,
currency: currencyReducer,
notifications: notificationsReducers,
- dApps: dAppsReducer
+ dApps: dAppsReducer,
+ balanceMode: balanceModeReducer
});
export type RootState = GetStateType;
diff --git a/src/app/store/root-state.mock.ts b/src/app/store/root-state.mock.ts
index 56e0622861..5a36d5a3c7 100644
--- a/src/app/store/root-state.mock.ts
+++ b/src/app/store/root-state.mock.ts
@@ -1,6 +1,7 @@
import { mockNotificationsState } from 'lib/notifications';
import { mockAdvertisingState } from './advertising/state.mock';
+import { mockBalanceModeState } from './balance-mode/state.mock';
import { mockCurrencyState } from './currency/state.mock';
import { mockDAppsState } from './d-apps/state.mock';
import { RootState } from './index';
@@ -10,5 +11,6 @@ export const mockRootState: RootState = {
advertising: mockAdvertisingState,
currency: mockCurrencyState,
notifications: mockNotificationsState,
- dApps: mockDAppsState
+ dApps: mockDAppsState,
+ balanceMode: mockBalanceModeState
};
diff --git a/src/app/templates/AssetIcon.tsx b/src/app/templates/AssetIcon.tsx
index a8bbc5eb2c..f216a8204b 100644
--- a/src/app/templates/AssetIcon.tsx
+++ b/src/app/templates/AssetIcon.tsx
@@ -4,8 +4,7 @@ import classNames from 'clsx';
import Identicon from 'app/atoms/Identicon';
import { ReactComponent as CollectiblePlaceholder } from 'app/icons/collectible-placeholder.svg';
-import { buildTokenIconURLs, buildCollectibleImageURLs } from 'lib/image-uri';
-import { useAssetMetadata } from 'lib/temple/front';
+import { useAssetMetadata, buildTokenIconURLs, buildCollectibleImageURLs } from 'lib/temple/front';
import { AssetMetadata, getAssetSymbol } from 'lib/temple/metadata';
import { Image } from 'lib/ui/Image';
diff --git a/src/app/templates/LedgerLiveSettings.tsx b/src/app/templates/LedgerLiveSettings.tsx
index d70b81412b..affa544d5c 100644
--- a/src/app/templates/LedgerLiveSettings.tsx
+++ b/src/app/templates/LedgerLiveSettings.tsx
@@ -2,8 +2,8 @@ import React from 'react';
import { FormCheckbox } from 'app/atoms';
import { T, t } from 'lib/i18n';
-import { useLocalStorage } from 'lib/temple/front';
import { TempleSharedStorageKey } from 'lib/temple/types';
+import { useLocalStorage } from 'lib/ui/local-storage';
const LedgerLiveSettings: React.FC<{}> = () => {
const [ledgerLiveEnabled, setLedgerLiveEnabled] = useLocalStorage(
diff --git a/src/app/templates/LockUpSettings.tsx b/src/app/templates/LockUpSettings.tsx
index 520c1bc0c1..3fbba6f6c0 100644
--- a/src/app/templates/LockUpSettings.tsx
+++ b/src/app/templates/LockUpSettings.tsx
@@ -2,10 +2,10 @@ import React, { FC } from 'react';
import { FormCheckbox } from 'app/atoms';
import { t, T } from 'lib/i18n';
-import { getIsLockUpEnabled, saveIsLockUpEnabled } from 'lib/lock-up';
+import { useIsLockUpEnabled } from 'lib/lock-up';
const LockUpSettings: FC<{}> = () => {
- const isLockUpEnabled = getIsLockUpEnabled();
+ const [isLockUpEnabled, saveIsLockUpEnabled] = useIsLockUpEnabled();
const handleLockUpChange = (evt: React.ChangeEvent) => {
saveIsLockUpEnabled(evt.target.checked);
diff --git a/src/app/templates/RevealSecret.tsx b/src/app/templates/RevealSecrets/RevealSecret.tsx
similarity index 94%
rename from src/app/templates/RevealSecret.tsx
rename to src/app/templates/RevealSecrets/RevealSecret.tsx
index 0ef527f383..21b149bfa8 100644
--- a/src/app/templates/RevealSecret.tsx
+++ b/src/app/templates/RevealSecrets/RevealSecret.tsx
@@ -10,6 +10,8 @@ import { T, t } from 'lib/i18n';
import { useAccount, useSecretState, useTempleClient } from 'lib/temple/front';
import { TempleAccountType } from 'lib/temple/types';
+import { RevealSecretsTestIDS } from './RevealSecrets.test-ids';
+
const SUBMIT_ERROR_TYPE = 'submit-error';
type FormData = {
@@ -224,6 +226,7 @@ const RevealSecret: FC = ({ reveal }) => {
containerClassName="mb-4"
className="resize-none notranslate"
value={secret}
+ testID={RevealSecretsTestIDS.RevealSecretsValue}
/>
{texts.attention}
} className="my-4" />
@@ -244,9 +247,16 @@ const RevealSecret: FC = ({ reveal }) => {
errorCaption={errors.password?.message}
containerClassName="mb-4"
onChange={() => clearError()}
+ testID={RevealSecretsTestIDS.RevealPasswordField}
/>
- {message => {message}}
+
+ {message => (
+
+ {message}
+
+ )}
+
);
}, [
diff --git a/src/app/templates/RevealSecrets/RevealSecrets.test-ids.ts b/src/app/templates/RevealSecrets/RevealSecrets.test-ids.ts
new file mode 100644
index 0000000000..208da6e403
--- /dev/null
+++ b/src/app/templates/RevealSecrets/RevealSecrets.test-ids.ts
@@ -0,0 +1,5 @@
+export enum RevealSecretsTestIDS {
+ RevealButton = 'RevealSecrets/Reveal Button',
+ RevealPasswordField = 'RevealSecrets/Reveal Password Field',
+ RevealSecretsValue = 'RevealSecrets/Reveal Secrets Value'
+}
diff --git a/src/app/templates/SwapForm/SwapForm.tsx b/src/app/templates/SwapForm/SwapForm.tsx
index 869c2c5203..97d428b0b6 100644
--- a/src/app/templates/SwapForm/SwapForm.tsx
+++ b/src/app/templates/SwapForm/SwapForm.tsx
@@ -24,12 +24,7 @@ import OperationStatus from 'app/templates/OperationStatus';
import { useFormAnalytics } from 'lib/analytics';
import { T, t } from 'lib/i18n';
import { getRoutingFeeTransferParams } from 'lib/swap-router';
-import {
- ROUTING_FEE_ADDRESS,
- ROUTING_FEE_PERCENT,
- ROUTING_FEE_RATIO,
- TEZOS_DEXES_API_URL
-} from 'lib/swap-router/config';
+import { ROUTING_FEE_ADDRESS, ROUTING_FEE_PERCENT, ROUTING_FEE_RATIO } from 'lib/swap-router/config';
import { useAccount, useTezos, useAssetMetadata } from 'lib/temple/front';
import { atomsToTokens, tokensToAtoms } from 'lib/temple/helpers';
import useTippy from 'lib/ui/useTippy';
@@ -47,6 +42,12 @@ import { SwapMinimumReceived } from './SwapMinimumReceived/SwapMinimumReceived';
import { SwapPriceUpdateBar } from './SwapPriceUpdateBar/SwapPriceUpdateBar';
import { SwapRoute } from './SwapRoute/SwapRoute';
+const TEMPLE_WALLET_DEXES_API_URL = process.env.TEMPLE_WALLET_DEXES_API_URL;
+
+if (!TEMPLE_WALLET_DEXES_API_URL) {
+ throw new Error('TEMPLE_WALLET_DEXES_API_URL is not defined');
+}
+
const KNOWN_DEX_TYPES = [
DexTypeEnum.QuipuSwap,
DexTypeEnum.QuipuSwap20,
@@ -84,7 +85,7 @@ export const SwapForm: FC = () => {
const inputAssetMetadata = useAssetMetadata(inputValue.assetSlug ?? 'tez')!;
const outputAssetMetadata = useAssetMetadata(outputValue.assetSlug ?? 'tez')!;
- const allRoutePairs = useAllRoutePairs(TEZOS_DEXES_API_URL);
+ const allRoutePairs = useAllRoutePairs(TEMPLE_WALLET_DEXES_API_URL);
const filteredRoutePairs = useMemo(
() => allRoutePairs.data.filter(routePair => KNOWN_DEX_TYPES.includes(routePair.dexType)),
[allRoutePairs.data]
diff --git a/src/contentScript.ts b/src/contentScript.ts
index 31f807d1bb..989c1e3eba 100644
--- a/src/contentScript.ts
+++ b/src/contentScript.ts
@@ -36,7 +36,7 @@ type BeaconPageMessage = BeaconMessage | { message: BeaconMessage; sender: { id:
const SENDER = {
id: browser.runtime.id,
name: 'Temple - Tezos Wallet',
- iconUrl: process.env.TEMPLE_WALLET_LOGO_URL || undefined
+ iconUrl: 'https://templewallet.com/logo.png'
};
window.addEventListener(
diff --git a/src/lib/analytics/use-analytics-state.hook.ts b/src/lib/analytics/use-analytics-state.hook.ts
index 7559b18bdf..9a54605e04 100644
--- a/src/lib/analytics/use-analytics-state.hook.ts
+++ b/src/lib/analytics/use-analytics-state.hook.ts
@@ -1,8 +1,9 @@
import { nanoid } from 'nanoid';
import { AnalyticsEventCategory } from 'lib/temple/analytics-types';
-import { useLocalStorage, assertResponse, request } from 'lib/temple/front';
+import { assertResponse, request } from 'lib/temple/front';
import { TempleMessageType } from 'lib/temple/types';
+import { useLocalStorage } from 'lib/ui/local-storage';
interface AnalyticsStateInterface {
enabled?: boolean;
diff --git a/src/lib/apis/temple/endpoints/templewallet.api.ts b/src/lib/apis/temple/endpoints/templewallet.api.ts
index 580bae1951..cbc531d18b 100644
--- a/src/lib/apis/temple/endpoints/templewallet.api.ts
+++ b/src/lib/apis/temple/endpoints/templewallet.api.ts
@@ -1,3 +1,9 @@
import axios from 'axios';
-export const templeWalletApi = axios.create({ baseURL: 'https://temple-api-mainnet.prod.templewallet.com/api' });
+const TEMPLE_WALLET_API_URL = process.env.TEMPLE_WALLET_API_URL;
+
+if (!TEMPLE_WALLET_API_URL) {
+ throw new Error('TEMPLE_WALLET_API_URL is not defined');
+}
+
+export const templeWalletApi = axios.create({ baseURL: TEMPLE_WALLET_API_URL + '/api' });
diff --git a/src/lib/apis/temple/metadata.ts b/src/lib/apis/temple/metadata.ts
index cd15b48f99..581b13a24f 100644
--- a/src/lib/apis/temple/metadata.ts
+++ b/src/lib/apis/temple/metadata.ts
@@ -2,7 +2,13 @@ import axios from 'axios';
import { DetailedAssetMetdata } from 'lib/temple/metadata';
-const api = axios.create({ baseURL: 'https://metadata-api-mainnet.prod.templewallet.com' });
+const TEMPLE_WALLET_METADATA_API_URL = process.env.TEMPLE_WALLET_METADATA_API_URL;
+
+if (!TEMPLE_WALLET_METADATA_API_URL) {
+ throw new Error('TEMPLE_WALLET_METADATA_API_URL is not defined');
+}
+
+const api = axios.create({ baseURL: TEMPLE_WALLET_METADATA_API_URL });
export async function getTokensMetadata(slugs: string[], timeout?: number) {
if (slugs.length === 0) return [];
diff --git a/src/lib/e2e/types.ts b/src/lib/e2e/types.ts
new file mode 100644
index 0000000000..0d19fb9a38
--- /dev/null
+++ b/src/lib/e2e/types.ts
@@ -0,0 +1,4 @@
+export enum E2eMessageType {
+ ResetRequest = 'E2E/Reset/Request',
+ ResetResponse = 'E2E/Reset/Response'
+}
diff --git a/src/lib/icons/assets/tezos-logo.svg b/src/lib/icons/assets/tezos-logo.svg
new file mode 100644
index 0000000000..a55b87c69c
--- /dev/null
+++ b/src/lib/icons/assets/tezos-logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/lib/icons/index.ts b/src/lib/icons/index.ts
index 30cd63c290..c20e84d045 100644
--- a/src/lib/icons/index.ts
+++ b/src/lib/icons/index.ts
@@ -8,3 +8,4 @@ export { ReactComponent as NewsIcon } from './assets/news.svg';
export { ReactComponent as NoResultIcon } from './assets/no-result.svg';
export { ReactComponent as NotificationDotIcon } from './assets/notification-dot.svg';
export { ReactComponent as UpdateIcon } from './assets/update.svg';
+export { ReactComponent as TezosLogoIcon } from './assets/tezos-logo.svg';
diff --git a/src/lib/lock-up/index.ts b/src/lib/lock-up/index.ts
index ddcbf94c52..9bb856560d 100644
--- a/src/lib/lock-up/index.ts
+++ b/src/lib/lock-up/index.ts
@@ -1,4 +1,7 @@
-const STORAGE_KEY = 'lock_up';
+import { TempleSharedStorageKey } from 'lib/temple/types';
+import { useLocalStorage } from 'lib/ui/local-storage';
+
+const STORAGE_KEY = TempleSharedStorageKey.LockUpEnabled;
const DEFAULT_VALUE = true;
export const getIsLockUpEnabled = () => {
@@ -6,6 +9,4 @@ export const getIsLockUpEnabled = () => {
return stored ? stored === 'true' : DEFAULT_VALUE;
};
-export const saveIsLockUpEnabled = (value: boolean) => {
- localStorage.setItem(STORAGE_KEY, String(value));
-};
+export const useIsLockUpEnabled = () => useLocalStorage(STORAGE_KEY, DEFAULT_VALUE);
diff --git a/src/lib/swap-router/config.ts b/src/lib/swap-router/config.ts
index c9b3bf44f5..59562fc608 100644
--- a/src/lib/swap-router/config.ts
+++ b/src/lib/swap-router/config.ts
@@ -1,5 +1,3 @@
-export const TEZOS_DEXES_API_URL = 'wss://dexes-api-mainnet.prod.templewallet.com';
-
export const ROUTING_FEE_ADDRESS = 'tz1UbRzhYjQKTtWYvGUWcRtVT4fN3NESDVYT';
export const ROUTING_FEE_PERCENT = 0.5;
diff --git a/src/lib/temple/back/analytics.ts b/src/lib/temple/back/analytics.ts
index d131355acd..28a8e9f6b2 100644
--- a/src/lib/temple/back/analytics.ts
+++ b/src/lib/temple/back/analytics.ts
@@ -4,11 +4,13 @@ import Analytics from 'analytics-node';
import { TempleSendPageEventRequest, TempleSendTrackEventRequest } from 'lib/temple/analytics-types';
import { loadChainId } from 'lib/temple/helpers';
-if (!process.env.TEMPLE_WALLET_SEGMENT_WRITE_KEY) {
+const WRITE_KEY = process.env.TEMPLE_WALLET_SEGMENT_WRITE_KEY;
+
+if (!WRITE_KEY) {
throw new Error("Require a 'TEMPLE_WALLET_SEGMENT_WRITE_KEY' environment variable to be set");
}
-const client = new Analytics(process.env.TEMPLE_WALLET_SEGMENT_WRITE_KEY, {
+const client = new Analytics(WRITE_KEY, {
axiosConfig: { adapter: fetchAdapter }
} as {});
diff --git a/src/lib/temple/back/main.ts b/src/lib/temple/back/main.ts
index 3c01bbec06..28b116913b 100644
--- a/src/lib/temple/back/main.ts
+++ b/src/lib/temple/back/main.ts
@@ -1,7 +1,9 @@
-import { Runtime } from 'webextension-polyfill';
+import browser, { Runtime } from 'webextension-polyfill';
+import { E2eMessageType } from 'lib/e2e/types';
import { BACKGROUND_IS_WORKER } from 'lib/env';
import { encodeMessage, encryptMessage, getSenderId, MessageType, Response } from 'lib/temple/beacon';
+import { clearAsyncStorages } from 'lib/temple/reset';
import { TempleMessageType, TempleRequest, TempleResponse } from 'lib/temple/types';
import * as Actions from './actions';
@@ -239,3 +241,13 @@ const processRequest = async (req: TempleRequest, port: Runtime.Port): Promise {
+ if (msg?.type === E2eMessageType.ResetRequest) {
+ return new Promise(async resolve => {
+ await clearAsyncStorages();
+ resolve({ type: E2eMessageType.ResetResponse });
+ });
+ }
+ return;
+});
diff --git a/src/lib/temple/beacon.ts b/src/lib/temple/beacon.ts
index 8ba763a05f..f8511dd56a 100644
--- a/src/lib/temple/beacon.ts
+++ b/src/lib/temple/beacon.ts
@@ -229,7 +229,7 @@ export function formatOpParams(op: any) {
export const PAIRING_RESPONSE_BASE: Partial = {
type: MessageType.HandshakeResponse,
name: 'Temple - Tezos Wallet',
- icon: process.env.TEMPLE_WALLET_LOGO_URL || undefined,
+ icon: 'https://templewallet.com/logo.png',
appUrl: browser.runtime.getURL('fullpage.html')
};
diff --git a/src/lib/image-uri.ts b/src/lib/temple/front/image-uri.ts
similarity index 100%
rename from src/lib/image-uri.ts
rename to src/lib/temple/front/image-uri.ts
diff --git a/src/lib/temple/front/index.ts b/src/lib/temple/front/index.ts
index 94baa6ddea..a84f19d00e 100644
--- a/src/lib/temple/front/index.ts
+++ b/src/lib/temple/front/index.ts
@@ -1,5 +1,3 @@
-export { useLocalStorage } from './local-storage';
-
export { useStorage, fetchFromStorage, putToStorage } from './storage';
export { useTempleClient, request, assertResponse } from './client';
@@ -65,3 +63,5 @@ export { useSecretState } from './use-secret-state.hook';
export { useFilteredContacts } from './use-filtered-contacts.hook';
export { decryptKukaiSeedPhrase } from './kukai';
+
+export { buildTokenIconURLs, buildCollectibleImageURLs } from './image-uri';
diff --git a/src/lib/temple/types.ts b/src/lib/temple/types.ts
index b8cd9bcfcb..b2a8b740b9 100644
--- a/src/lib/temple/types.ts
+++ b/src/lib/temple/types.ts
@@ -129,8 +129,8 @@ export interface TempleSettings {
export enum TempleSharedStorageKey {
DAppEnabled = 'dappenabled',
- LocaleCode = 'localecode',
UseLedgerLive = 'useledgerlive',
+ LockUpEnabled = 'lock_up',
PasswordAttempts = 'passwordAttempts',
TimeLock = 'timelock'
}
diff --git a/src/lib/temple/front/local-storage.ts b/src/lib/ui/local-storage.ts
similarity index 100%
rename from src/lib/temple/front/local-storage.ts
rename to src/lib/ui/local-storage.ts