From 7a31793af6fadd494b8b9934f3467805537d2b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 14 Nov 2024 19:09:19 -0300 Subject: [PATCH 1/6] chore: bump to v0.30.1 (#636) --- android/app/build.gradle | 4 ++-- ios/HathorMobile.xcodeproj/project.pbxproj | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 6a1c42629..9e81b1bed 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -79,8 +79,8 @@ android { applicationId "network.hathor.wallet" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 85 - versionName "0.30.1-rc.1" + versionCode 86 + versionName "0.30.1" missingDimensionStrategy "react-native-camera", "general" } signingConfigs { diff --git a/ios/HathorMobile.xcodeproj/project.pbxproj b/ios/HathorMobile.xcodeproj/project.pbxproj index bb3252289..02a9e022a 100644 --- a/ios/HathorMobile.xcodeproj/project.pbxproj +++ b/ios/HathorMobile.xcodeproj/project.pbxproj @@ -476,7 +476,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = HathorMobile/HathorMobile.entitlements; - CURRENT_PROJECT_VERSION = 0.1.0; + CURRENT_PROJECT_VERSION = 1.0.0; DEVELOPMENT_TEAM = 55SHY647CG; ENABLE_BITCODE = NO; INFOPLIST_FILE = HathorMobile/Info.plist; @@ -506,7 +506,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = HathorMobile/HathorMobile.entitlements; - CURRENT_PROJECT_VERSION = 0.1.0; + CURRENT_PROJECT_VERSION = 1.0.0; DEVELOPMENT_TEAM = 55SHY647CG; INFOPLIST_FILE = HathorMobile/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; diff --git a/package-lock.json b/package-lock.json index 66382c81e..28eeafb51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "HathorMobile", - "version": "0.30.1-rc.1", + "version": "0.30.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "HathorMobile", - "version": "0.30.1-rc.1", + "version": "0.30.1", "dependencies": { "@ethersproject/shims": "5.7.0", "@fortawesome/fontawesome-svg-core": "1.2.36", diff --git a/package.json b/package.json index 9f7adbc11..f233ffa72 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "HathorMobile", - "version": "0.30.1-rc.1", + "version": "0.30.1", "engines": { "node": ">=18.0.0", "npm": ">=9.0.0" From f791e6de75aac9d891dc97dc965f17b34a516986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Carneiro?= Date: Mon, 25 Nov 2024 13:47:12 -0500 Subject: [PATCH 2/6] fix: race condition on feature-flag during startup (#629) * fix: initialize biometry from asyncstorage instead of redux --- src/actions.js | 5 ----- src/reducers/reducer.js | 11 ----------- src/sagas/featureToggle.js | 6 +++--- src/sagas/wallet.js | 25 ------------------------- src/screens/PinScreen.js | 18 +++++++++--------- src/screens/Security.js | 34 ++++++++++++++++++---------------- src/store.js | 9 +++++++++ src/utils.js | 38 ++++++++++++++++++++++++++------------ 8 files changed, 65 insertions(+), 81 deletions(-) diff --git a/src/actions.js b/src/actions.js index a5a72a1da..c28c9755c 100644 --- a/src/actions.js +++ b/src/actions.js @@ -398,11 +398,6 @@ export const setUseWalletService = (data) => ({ payload: data, }); -export const setUseSafeBiometryMode = (data) => ({ - type: types.SET_USE_SAFE_BIOMETRY_MODE, - payload: data, -}); - export const setUniqueDeviceId = (uniqueId) => ({ type: types.SET_UNIQUE_DEVICE_ID, payload: uniqueId, diff --git a/src/reducers/reducer.js b/src/reducers/reducer.js index a145c3504..3033f3d0f 100644 --- a/src/reducers/reducer.js +++ b/src/reducers/reducer.js @@ -518,8 +518,6 @@ const initialState = { address: null, error: null, }, - - safeBiometryEnabled: false, }; export const reducer = (state = initialState, action) => { @@ -736,8 +734,6 @@ export const reducer = (state = initialState, action) => { return onNewNanoContractTransactionRetry(state); case types.REOWN_NEW_NANOCONTRACT_RETRY_DISMISS: return onNewNanoContractTransactionRetryDismiss(state); - case types.SET_USE_SAFE_BIOMETRY_MODE: - return onSetUseSafeBiometryMode(state, action); default: return state; } @@ -932,22 +928,15 @@ const onSetUseWalletService = (state, action) => ({ useWalletService: action.payload, }); -const onSetUseSafeBiometryMode = (state, action) => ({ - ...state, - safeBiometryEnabled: action.payload, -}); - const onResetWalletSuccess = (state) => { const oldUnleashClient = state.unleashClient; const oldFeatureTogglesInitialized = state.featureTogglesInitialized; const oldFeatureToggles = state.featureToggles; - const oldSafeBiometryEnabled = state.safeBiometryEnabled; return { ...initialState, unleashClient: oldUnleashClient, featureTogglesInitialized: oldFeatureTogglesInitialized, featureToggles: oldFeatureToggles, - safeBiometryEnabled: oldSafeBiometryEnabled, }; }; diff --git a/src/sagas/featureToggle.js b/src/sagas/featureToggle.js index 781e19951..f03754c09 100644 --- a/src/sagas/featureToggle.js +++ b/src/sagas/featureToggle.js @@ -26,7 +26,6 @@ import { setUnleashClient, setFeatureToggles, featureToggleInitialized, - setUseSafeBiometryMode, } from '../actions'; import { UNLEASH_URL, @@ -34,10 +33,10 @@ import { UNLEASH_POLLING_INTERVAL, STAGE, FEATURE_TOGGLE_DEFAULTS, - SAFE_BIOMETRY_MODE_FEATURE_TOGGLE, } from '../constants'; import { disableFeaturesIfNeeded } from './helpers'; import { logger } from '../logger'; +import { STORE, FEATURE_TOGGLES_LAST_KNOWN_VALUES_KEY } from '../store'; const MAX_RETRIES = 5; @@ -89,6 +88,7 @@ export function* handleToggleUpdate() { const toggles = unleashClient.getToggles(); const featureToggles = disableFeaturesIfNeeded(networkSettings, mapFeatureToggles(toggles)); + STORE.setItem(FEATURE_TOGGLES_LAST_KNOWN_VALUES_KEY, featureToggles); yield put(setFeatureToggles(featureToggles)); yield put({ type: types.FEATURE_TOGGLE_UPDATED }); @@ -126,9 +126,9 @@ export function* monitorFeatureFlags(currentRetry = 0) { // At this point, unleashClient.fetchToggles() already fetched the toggles // (this will throw if it hasn't) const featureToggles = mapFeatureToggles(unleashClient.getToggles()); + STORE.setItem(FEATURE_TOGGLES_LAST_KNOWN_VALUES_KEY, featureToggles); yield put(setFeatureToggles(featureToggles)); - yield put(setUseSafeBiometryMode(featureToggles[SAFE_BIOMETRY_MODE_FEATURE_TOGGLE])); yield put(featureToggleInitialized()); } catch (e) { log.error(e); diff --git a/src/sagas/wallet.js b/src/sagas/wallet.js index bd43b1843..9e51ae21b 100644 --- a/src/sagas/wallet.js +++ b/src/sagas/wallet.js @@ -37,7 +37,6 @@ import { DEFAULT_TOKEN, WALLET_SERVICE_FEATURE_TOGGLE, PUSH_NOTIFICATION_FEATURE_TOGGLE, - SAFE_BIOMETRY_MODE_FEATURE_TOGGLE, networkSettingsKeyMap, } from '../constants'; import { STORE } from '../store'; @@ -71,8 +70,6 @@ import { selectAddressAddressesFailure, firstAddressFailure, firstAddressSuccess, - setUseSafeBiometryMode, - lockScreen, firstAddressRequest, } from '../actions'; import { fetchTokenData } from './tokens'; @@ -90,7 +87,6 @@ import { getAllAddresses, getFirstAddress, setKeychainPin, - isBiometryEnabled, } from '../utils'; import { logger } from '../logger'; @@ -438,11 +434,6 @@ export function* onPushNotificationDisabled() { yield put(setAvailablePushNotification(false)); } -export function* onSafeBiometryToggleChanged() { - log.debug('Safe biometry mode feature toggle changed state, locking wallet.'); - yield put(lockScreen()); -} - /** * This saga will wait for feature toggle updates and react when a toggle state * transition is done @@ -457,22 +448,6 @@ export function* featureToggleUpdateListener() { const oldPushNotificationToggle = yield select((state) => state.pushNotification.available); const newPushNotificationToggle = yield call(isPushNotificationEnabled); - const oldSafeBiometryEnabled = yield select(({ safeBiometryEnabled }) => safeBiometryEnabled); - const newSafeBiometryEnabled = yield call( - checkForFeatureFlag, - SAFE_BIOMETRY_MODE_FEATURE_TOGGLE, - ); - - if (oldSafeBiometryEnabled !== newSafeBiometryEnabled) { - // Safe biometry feature changed, need to update the state. - yield put(setUseSafeBiometryMode(newSafeBiometryEnabled)); - if (isBiometryEnabled()) { - // Since biometry is enabled, a migration is required, this means the wallet - // needs to restart and the migration will fix the next time it opens. - yield call(onSafeBiometryToggleChanged); - } - } - // WalletService is currently ON and the featureToggle is now OFF if (!newWalletServiceToggle && oldWalletServiceToggle) { yield call(onWalletServiceDisabled); diff --git a/src/screens/PinScreen.js b/src/screens/PinScreen.js index 733eac784..391b4b243 100644 --- a/src/screens/PinScreen.js +++ b/src/screens/PinScreen.js @@ -26,9 +26,9 @@ import { resetOnLockScreen, onExceptionCaptured, } from '../actions'; -import { PIN_SIZE, SAFE_BIOMETRY_MODE_FEATURE_TOGGLE } from '../constants'; +import { PIN_SIZE } from '../constants'; import { COLORS } from '../styles/themes'; -import { STORE } from '../store'; +import { SAFE_BIOMETRY_FEATURE_FLAG_KEY, STORE } from '../store'; import baseStyle from '../styles/init'; import Spinner from '../components/Spinner'; import FeedbackModal from '../components/FeedbackModal'; @@ -43,7 +43,6 @@ const log = logger('PIN_SCREEN'); const mapStateToProps = (state) => ({ loadHistoryActive: state.loadHistoryStatus.active, wallet: state.wallet, - safeBiometryEnabled: state.featureToggles[SAFE_BIOMETRY_MODE_FEATURE_TOGGLE], }); const mapDispatchToProps = (dispatch) => ({ @@ -82,6 +81,7 @@ class PinScreen extends React.Component { this.biometryText = props.route.params.biometryText ?? this.biometryText; this.biometryLoadingText = props.route.params.biometryLoadingText ?? ''; } + this.useSafeBiometryFeature = STORE.getItem(SAFE_BIOMETRY_FEATURE_FLAG_KEY); this.biometryEnabled = isBiometryEnabled(); this.focusEvent = null; @@ -152,14 +152,14 @@ class PinScreen extends React.Component { // method an change redux state. No need to execute callback or go back on navigation try { await STORE.handleDataMigration(pin); - const newPin = await biometricsMigration(pin, this.props.safeBiometryEnabled); + const actualPin = await biometricsMigration(pin); if (!this.props.wallet) { // We have already made sure we have an available accessData // The handleDataMigration method ensures we have already migrated if necessary // This means the wallet is loaded and the access data is ready to be used. - const words = await STORE.getWalletWords(newPin); - this.props.startWalletRequested({ words, pin: newPin }); + const words = await STORE.getWalletWords(actualPin); + this.props.startWalletRequested({ words, pin: actualPin }); } this.props.unlockScreen(); } catch (e) { @@ -298,12 +298,12 @@ class PinScreen extends React.Component { ); const renderButton = () => { - if ((!this.state.biometryFailed) && this.props.safeBiometryEnabled && this.biometryEnabled) { + if ((!this.state.biometryFailed) && this.useSafeBiometryFeature && this.biometryEnabled) { // Biometry has not failed, so we should not show a cancellation button. return null; } const biometryFailed = this.state.biometryFailed - && this.props.safeBiometryEnabled + && this.useSafeBiometryFeature && this.biometryEnabled; let title; let onPress; @@ -372,7 +372,7 @@ class PinScreen extends React.Component { ); const renderBody = () => { - if (this.props.safeBiometryEnabled && this.biometryEnabled) { + if (this.useSafeBiometryFeature && this.biometryEnabled) { // Safe biometry mode is enabled, we should not render the pin input. return safeBiometryMessage(); } diff --git a/src/screens/Security.js b/src/screens/Security.js index c2e38c505..79d952593 100644 --- a/src/screens/Security.js +++ b/src/screens/Security.js @@ -22,12 +22,10 @@ import { import { HathorList, ListItem, ListMenu } from '../components/HathorList'; import { lockScreen, onExceptionCaptured } from '../actions'; import { COLORS } from '../styles/themes'; -import { STORE } from '../store'; -import { SAFE_BIOMETRY_MODE_FEATURE_TOGGLE } from '../constants'; +import { SAFE_BIOMETRY_FEATURE_FLAG_KEY, STORE } from '../store'; const mapStateToProps = (state) => ({ wallet: state.wallet, - safeBiometryEnabled: state.featureToggles[SAFE_BIOMETRY_MODE_FEATURE_TOGGLE], }); const mapDispatchToProps = (dispatch) => ({ @@ -67,16 +65,17 @@ export class Security extends React.Component { }; } - onBiometrySwitchChange = (value) => { - this.setState({ biometryEnabled: value }); - setBiometryEnabled(value); - } - - onSafeBiometrySwitchChange = (value) => { - if (value) { - this.onSafeBiometryEnabled(); + onBiometrySwitchChange(value) { + const useSafeBiometryFeature = STORE.getItem(SAFE_BIOMETRY_FEATURE_FLAG_KEY); + if (useSafeBiometryFeature) { + if (value) { + this.onSafeBiometryEnabled(); + } else { + this.onSafeBiometryDisabled(); + } } else { - this.onSafeBiometryDisabled(); + this.setState({ biometryEnabled: value }); + setBiometryEnabled(value); } } @@ -147,13 +146,18 @@ export class Security extends React.Component { } onLockWallet = () => { + // After the screen is unlocked the Home screen will be shown + this.props.navigation.navigate('Home'); this.props.lockScreen(); } render() { const switchDisabled = !this.supportedBiometry; const biometryText = (switchDisabled ? t`No biometry supported` : t`Use ${this.supportedBiometry}`); - const safeBiometryActive = this.state.biometryEnabled && this.props.safeBiometryEnabled; + + const useSafeBiometryFeature = STORE.getItem(SAFE_BIOMETRY_FEATURE_FLAG_KEY); + const safeBiometryActive = this.state.biometryEnabled && useSafeBiometryFeature; + return ( diff --git a/src/store.js b/src/store.js index e04ef712d..4bcbd3366 100644 --- a/src/store.js +++ b/src/store.js @@ -15,9 +15,18 @@ export const REGISTERED_TOKENS_KEY = 'asyncstorage:registeredTokens'; export const STORE_VERSION_KEY = 'asyncstorage:version'; export const REGISTERED_NANO_CONTRACTS_KEY = 'asyncstorage:registeredNanoContracts'; export const PIN_BACKUP_KEY = 'asyncstorage:pinBackup'; +// Wheather old biometry mode is active (by the user request) export const IS_OLD_BIOMETRY_ENABLED_KEY = 'mobile:isBiometryEnabled'; +// Wheather safe biometry is active (by the user request) export const IS_BIOMETRY_ENABLED_KEY = 'mobile:isSafeBiometryEnabled'; +// Which type of biometry the device can handle. export const SUPPORTED_BIOMETRY_KEY = 'mobile:supportedBiometry'; +// This key determines under which biometry mode the wallet is operating on. +// The value here only changes during a migration (when the user unlocks the wallet) +export const SAFE_BIOMETRY_FEATURE_FLAG_KEY = 'asyncstorage:featureFlagSafeBiometryMode'; +// These are the last known values of the unleash feature toggles +// These are updated on every call to unleash +export const FEATURE_TOGGLES_LAST_KNOWN_VALUES_KEY = 'asyncstorage:featureTogglesLastKnownValues'; export const walletKeys = [ ACCESS_DATA_KEY, diff --git a/src/utils.js b/src/utils.js index 7e1447d1e..9c168903b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -15,8 +15,8 @@ import { Linking, Platform, Text } from 'react-native'; import { getStatusBarHeight } from 'react-native-status-bar-height'; import moment from 'moment'; import baseStyle from './styles/init'; -import { KEYCHAIN_USER, NETWORK_MAINNET, NANO_CONTRACT_FEATURE_TOGGLE } from './constants'; -import { STORE, IS_BIOMETRY_ENABLED_KEY, IS_OLD_BIOMETRY_ENABLED_KEY, SUPPORTED_BIOMETRY_KEY } from './store'; +import { KEYCHAIN_USER, NETWORK_MAINNET, NANO_CONTRACT_FEATURE_TOGGLE, SAFE_BIOMETRY_MODE_FEATURE_TOGGLE } from './constants'; +import { STORE, IS_BIOMETRY_ENABLED_KEY, IS_OLD_BIOMETRY_ENABLED_KEY, SUPPORTED_BIOMETRY_KEY, SAFE_BIOMETRY_FEATURE_FLAG_KEY, FEATURE_TOGGLES_LAST_KNOWN_VALUES_KEY } from './store'; import { TxHistory } from './models'; import { COLORS, STYLE } from './styles/themes'; import { logger } from './logger'; @@ -94,17 +94,28 @@ export const getTokenLabel = (token) => `${token.name} (${token.symbol})`; /** * Migrate the biometry configuration state if needed. * - * @param {string} currentPassword - * @param {bool} safeBiometryEnabled + * @param {string} currentPassword - The password returned from the system keychain. * @return {Promise} The actual pin/password for the application. */ -export async function biometricsMigration(currentPassword, safeBiometryEnabled) { - const oldBiometry = STORE.getItem(IS_OLD_BIOMETRY_ENABLED_KEY); - const safeBiometry = STORE.getItem(IS_BIOMETRY_ENABLED_KEY); +export async function biometricsMigration(currentPassword) { + const storeSafeBiometryFeature = !!STORE.getItem(SAFE_BIOMETRY_FEATURE_FLAG_KEY); + const unleashToggles = STORE.getItem(FEATURE_TOGGLES_LAST_KNOWN_VALUES_KEY) ?? {}; + const unleashSafeBiometryFeature = !!unleashToggles[SAFE_BIOMETRY_MODE_FEATURE_TOGGLE]; + + if (storeSafeBiometryFeature === unleashSafeBiometryFeature) { + // No migration is required since the store and unleash flags are the same + return currentPassword; + } + + STORE.setItem(SAFE_BIOMETRY_FEATURE_FLAG_KEY, unleashSafeBiometryFeature); + // The safe biometry feature flag has changed, we need to check if a migration is required. - if (safeBiometryEnabled) { - // Safe biometry mode, need to migrate if old biometry is enabled. - if (oldBiometry) { + if (unleashSafeBiometryFeature) { + // Unleash flag is enabling safe biometry + // if we have the old mode active a migration is required. + // else we can ignore migration since the user is not using biometry. + const oldBiometryActive = STORE.getItem(IS_OLD_BIOMETRY_ENABLED_KEY); + if (oldBiometryActive) { // currentPassword is the pin, we need to generate a new random password // and encrypt the pin. const password = generateRandomPassword(); @@ -116,9 +127,12 @@ export async function biometricsMigration(currentPassword, safeBiometryEnabled) return password; } } else { - // Old biometry mode, need to migrate if safe biometry is enabled. + // Unleash flag is disabling safe biometry + // if we have safe mode active a migration is required. + // else we can ignore migration since the use is not using biometry. + const safeBiometryActive = STORE.getItem(IS_BIOMETRY_ENABLED_KEY); // eslint-disable-next-line no-lonely-if - if (safeBiometry) { + if (safeBiometryActive) { // currentPassword is the random password, we need to decrypt the pin and // toggle the old biometry key const pin = STORE.disableSafeBiometry(currentPassword); From 26de1037c0c7e3326e17593b6fcc0b4f9b71a694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Tue, 14 Jan 2025 11:52:56 -0300 Subject: [PATCH 3/6] feat: skip reown confirmation modal (#643) --- src/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.js b/src/config.js index 8ddfb9049..316fcaa99 100644 --- a/src/config.js +++ b/src/config.js @@ -61,4 +61,4 @@ export const _SENTRY_DSN = 'https://c1ebae9159f741e8937abdbfbeba8e8a@o239606.ing /** * Whether we should skip the initial modal on reown requests */ -export const REOWN_SKIP_CONFIRMATION_MODAL = false; +export const REOWN_SKIP_CONFIRMATION_MODAL = true; From 76cc10e201c9a6027aaaa3c2e462b94ab8b2ed8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Wed, 15 Jan 2025 11:15:24 -0300 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20show=20a=20warning=20if=20the=20use?= =?UTF-8?q?r=20has=20insufficient=20balance=20for=20the=20tra=E2=80=A6=20(?= =?UTF-8?q?#645)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: show a warning if the user has insufficient balance for the transaction * chore: updated locale --- locale/da/texts.po | 78 ++++++++++-------- locale/pt-br/texts.po | 79 ++++++++++-------- locale/ru-ru/texts.po | 78 ++++++++++-------- locale/texts.pot | 78 ++++++++++-------- .../NewNanoContractTransactionRequest.js | 81 ++++++++++++++++--- 5 files changed, 246 insertions(+), 148 deletions(-) diff --git a/locale/da/texts.po b/locale/da/texts.po index 70359a8a6..ce8bbd9eb 100644 --- a/locale/da/texts.po +++ b/locale/da/texts.po @@ -57,11 +57,11 @@ msgid "[Last] dddd [•] HH:mm" msgstr "[Sidste] dddd [•] HH:mm" #. See https://momentjs.com/docs/#/displaying/calendar-time/ -#: src/models.js:107 src/utils.js:553 +#: src/models.js:107 src/utils.js:567 msgid "DD MMM YYYY [•] HH:mm" msgstr "DD MMM YYYY [•] HH:mm" -#: src/utils.js:227 +#: src/utils.js:241 msgid "Invalid address" msgstr "Ugyldig adresse" @@ -438,7 +438,7 @@ msgstr "Indtast dine seed-ord adskilt med mellemrum" #: src/components/NanoContract/NanoContractDetails.js:238 #: src/components/Reown/CreateTokenRequest.js:197 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:399 #: src/screens/LoadHistoryScreen.js:51 src/screens/LoadWalletErrorScreen.js:20 #: src/screens/NanoContract/NanoContractRegisterScreen.js:168 #: src/screens/PinScreen.js:285 @@ -503,7 +503,7 @@ msgstr "Låst" msgid "Manual" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:260 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 msgid "Register Nano Contract" @@ -551,11 +551,11 @@ msgstr "Venter på bekræftelse" msgid "Incorrect PIN Code. Try again." msgstr "Forkert PIN-kode. Prøv igen." -#: src/screens/PinScreen.js:77 +#: src/screens/PinScreen.js:76 msgid "Enter your PIN Code " msgstr "Indtast din pinkode " -#: src/screens/PinScreen.js:78 +#: src/screens/PinScreen.js:77 msgid "Unlock Hathor Wallet" msgstr "Lås Hathor-wallet op" @@ -669,36 +669,36 @@ msgstr "" msgid "Reset Wallet" msgstr "Nulstil wallet" -#: src/screens/Security.js:131 +#: src/screens/Security.js:130 msgid "Disable biometry" msgstr "Deaktiver biometri" -#: src/screens/Security.js:132 +#: src/screens/Security.js:131 msgid "Disabling biometry" msgstr "Deaktiverer biometri" -#: src/screens/Security.js:144 +#: src/screens/Security.js:143 msgid "Enter your 6-digit pin to enable biometry" msgstr "Indtast din 6-cifrede pin for at aktivere biometri" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 msgid "No biometry supported" msgstr "Ingen biometri understøttet" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 #, javascript-format msgid "Use ${ this.supportedBiometry }" msgstr "Brug ${ this.supportedBiometry }" -#: src/screens/Security.js:160 +#: src/screens/Security.js:164 msgid "SECURITY" msgstr "SIKKERHED" -#: src/screens/Security.js:184 +#: src/screens/Security.js:186 msgid "Change PIN" msgstr "Skift pinkode" -#: src/screens/Security.js:189 +#: src/screens/Security.js:191 msgid "Lock wallet" msgstr "Lås wallet" @@ -1012,8 +1012,8 @@ msgstr "" #: src/components/NanoContract/NanoContractDetails.js:202 #: src/components/NanoContract/SelectAddressModal.js:105 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:243 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:284 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:272 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:313 #: src/screens/NanoContract/NanoContractRegisterScreen.js:184 msgid "Loading" msgstr "" @@ -1145,21 +1145,21 @@ msgstr "" msgid "Error loading the details of some tokens." msgstr "" -#: src/sagas/wallet.js:805 +#: src/sagas/wallet.js:781 msgid "Wallet is not ready to load addresses." msgstr "" #. This will show the message in the feedback content at SelectAddressModal -#: src/sagas/wallet.js:821 +#: src/sagas/wallet.js:797 msgid "There was an error while loading wallet addresses. Try again." msgstr "" -#: src/sagas/wallet.js:831 +#: src/sagas/wallet.js:807 msgid "Wallet is not ready to load the first address." msgstr "" #. This will show the message in the feedback content -#: src/sagas/wallet.js:847 +#: src/sagas/wallet.js:823 msgid "There was an error while loading first wallet address. Try again." msgstr "" @@ -1466,12 +1466,12 @@ msgid "Decline Request" msgstr "" #: src/components/Reown/CreateTokenRequest.js:172 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:323 msgid "Sending transaction" msgstr "" #: src/components/Reown/CreateTokenRequest.js:173 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:295 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:324 msgid "Please wait." msgstr "" @@ -1610,47 +1610,57 @@ msgstr "" msgid "Review transaction details" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:205 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:234 msgid "Success!" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:206 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:235 msgid "Transaction successfully sent." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:244 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:273 msgid "Registering Nano Contract." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:253 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:282 msgid "Nano Contract Not Found" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:254 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:283 msgid "" "The Nano Contract requested is not registered. First register the Nano " "Contract to interact with it." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:265 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:279 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:330 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:308 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:371 msgid "Decline Transaction" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:277 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:306 msgid "Error while registering Nano Contract." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:285 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:314 msgid "Loading transaction information." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:326 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +msgid "Insufficient Funds" +msgstr "" + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:359 +msgid "" +"Ensure your wallet balance covers the required amount to accept this " +"transaction." +msgstr "" + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:364 msgid "Accept Transaction" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:356 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:397 msgid "Error while sending transaction." msgstr "" diff --git a/locale/pt-br/texts.po b/locale/pt-br/texts.po index 01e276396..461038877 100644 --- a/locale/pt-br/texts.po +++ b/locale/pt-br/texts.po @@ -57,11 +57,11 @@ msgid "[Last] dddd [•] HH:mm" msgstr "[Última] dddd [•] HH:mm" #. See https://momentjs.com/docs/#/displaying/calendar-time/ -#: src/models.js:107 src/utils.js:553 +#: src/models.js:107 src/utils.js:567 msgid "DD MMM YYYY [•] HH:mm" msgstr "DD MMM YYYY [•] HH:mm" -#: src/utils.js:227 +#: src/utils.js:241 msgid "Invalid address" msgstr "Endereço inválido" @@ -449,7 +449,7 @@ msgstr "Digite suas palavras separadas por espaços" #: src/components/NanoContract/NanoContractDetails.js:238 #: src/components/Reown/CreateTokenRequest.js:197 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:399 #: src/screens/LoadHistoryScreen.js:51 src/screens/LoadWalletErrorScreen.js:20 #: src/screens/NanoContract/NanoContractRegisterScreen.js:168 #: src/screens/PinScreen.js:285 @@ -516,7 +516,7 @@ msgstr "Bloqueado" msgid "Manual" msgstr "Digitar" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:260 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 msgid "Register Nano Contract" @@ -564,11 +564,11 @@ msgstr "Aguardando confirmação" msgid "Incorrect PIN Code. Try again." msgstr "PIN incorreto. Tente novamente." -#: src/screens/PinScreen.js:77 +#: src/screens/PinScreen.js:76 msgid "Enter your PIN Code " msgstr "Digite seu PIN " -#: src/screens/PinScreen.js:78 +#: src/screens/PinScreen.js:77 msgid "Unlock Hathor Wallet" msgstr "Desbloqueie sua Hathor Wallet" @@ -685,36 +685,36 @@ msgstr "" msgid "Reset Wallet" msgstr "Resetar Wallet" -#: src/screens/Security.js:131 +#: src/screens/Security.js:130 msgid "Disable biometry" msgstr "Desativar biometria" -#: src/screens/Security.js:132 +#: src/screens/Security.js:131 msgid "Disabling biometry" msgstr "Desativando biometria" -#: src/screens/Security.js:144 +#: src/screens/Security.js:143 msgid "Enter your 6-digit pin to enable biometry" msgstr "Digite seu PIN de 6 dígitos para habilitar biometria" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 msgid "No biometry supported" msgstr "Nenhuma biometria suportada" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 #, javascript-format msgid "Use ${ this.supportedBiometry }" msgstr "Usar ${ this.supportedBiometry }" -#: src/screens/Security.js:160 +#: src/screens/Security.js:164 msgid "SECURITY" msgstr "SEGURANÇA" -#: src/screens/Security.js:184 +#: src/screens/Security.js:186 msgid "Change PIN" msgstr "Mudar PIN" -#: src/screens/Security.js:189 +#: src/screens/Security.js:191 msgid "Lock wallet" msgstr "Bloquear a wallet" @@ -1040,8 +1040,8 @@ msgstr "Erro ao carregar primeiro endereço da wallet" #: src/components/NanoContract/NanoContractDetails.js:202 #: src/components/NanoContract/SelectAddressModal.js:105 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:243 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:284 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:272 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:313 #: src/screens/NanoContract/NanoContractRegisterScreen.js:184 msgid "Loading" msgstr "Carregando" @@ -1174,21 +1174,21 @@ msgstr "A wallet não está pronta ainda." msgid "Error loading the details of some tokens." msgstr "Ocorreu um erro durante o carregamento de detalhes de alguns tokens." -#: src/sagas/wallet.js:805 +#: src/sagas/wallet.js:781 msgid "Wallet is not ready to load addresses." msgstr "A wallet não está pronta para carregar os endereços." #. This will show the message in the feedback content at SelectAddressModal -#: src/sagas/wallet.js:821 +#: src/sagas/wallet.js:797 msgid "There was an error while loading wallet addresses. Try again." msgstr "Ocorreu um erro ao carregar os endereços da wallet. Tente novamente." -#: src/sagas/wallet.js:831 +#: src/sagas/wallet.js:807 msgid "Wallet is not ready to load the first address." msgstr "A wallet não está pronta para carregar o primeiro endereço." #. This will show the message in the feedback content -#: src/sagas/wallet.js:847 +#: src/sagas/wallet.js:823 msgid "There was an error while loading first wallet address. Try again." msgstr "" "Ocorreu um erro ao carregar o primeiro endereço da wallet. Tente novamente." @@ -1502,12 +1502,12 @@ msgid "Decline Request" msgstr "Recusar Solicitação" #: src/components/Reown/CreateTokenRequest.js:172 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:323 msgid "Sending transaction" msgstr "Enviando transação" #: src/components/Reown/CreateTokenRequest.js:173 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:295 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:324 msgid "Please wait." msgstr "Por favor, espere." @@ -1649,23 +1649,23 @@ msgstr "" msgid "Review transaction details" msgstr "Revisar detalhes da transação" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:205 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:234 msgid "Success!" msgstr "Sucesso!" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:206 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:235 msgid "Transaction successfully sent." msgstr "Transação enviada com sucesso." -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:244 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:273 msgid "Registering Nano Contract." msgstr "Registrando Nano Contract" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:253 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:282 msgid "Nano Contract Not Found" msgstr "Nano Contract não encontrado" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:254 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:283 msgid "" "The Nano Contract requested is not registered. First register the Nano " "Contract to interact with it." @@ -1673,25 +1673,36 @@ msgstr "" "O Nano Contract solicitado não está registrado. Primeiro registre o Nano " "Contract para interagir com ele." -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:265 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:279 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:330 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:308 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:371 msgid "Decline Transaction" msgstr "Recusar transação" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:277 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:306 msgid "Error while registering Nano Contract." msgstr "Erro ao tentar registrar o Nano Contract." -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:285 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:314 msgid "Loading transaction information." msgstr "Carregando informações da transação." -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:326 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +msgid "Insufficient Funds" +msgstr "Saldo insuficiente" + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:359 +msgid "" +"Ensure your wallet balance covers the required amount to accept this " +"transaction." +msgstr "Certifique-se de que o saldo da sua carteira cubra o valor necessário" +"para aceitar esta transação." + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:364 msgid "Accept Transaction" msgstr "Aceitar transação" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:356 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:397 msgid "Error while sending transaction." msgstr "Ocorreu um erro durante o envio da transação." diff --git a/locale/ru-ru/texts.po b/locale/ru-ru/texts.po index b4716b8f4..f4aa2824d 100644 --- a/locale/ru-ru/texts.po +++ b/locale/ru-ru/texts.po @@ -58,11 +58,11 @@ msgid "[Last] dddd [•] HH:mm" msgstr "[Последний] dddd [•] HH:mm" #. See https://momentjs.com/docs/#/displaying/calendar-time/ -#: src/models.js:107 src/utils.js:553 +#: src/models.js:107 src/utils.js:567 msgid "DD MMM YYYY [•] HH:mm" msgstr "DD MMM YYYY [•] HH:mm" -#: src/utils.js:227 +#: src/utils.js:241 msgid "Invalid address" msgstr "Неправильный адрес" @@ -439,7 +439,7 @@ msgstr "Введите seed-фразу" #: src/components/NanoContract/NanoContractDetails.js:238 #: src/components/Reown/CreateTokenRequest.js:197 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:399 #: src/screens/LoadHistoryScreen.js:51 src/screens/LoadWalletErrorScreen.js:20 #: src/screens/NanoContract/NanoContractRegisterScreen.js:168 #: src/screens/PinScreen.js:285 @@ -505,7 +505,7 @@ msgstr "Заблокированный" msgid "Manual" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:260 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 msgid "Register Nano Contract" @@ -553,11 +553,11 @@ msgstr "Ожидание подтверждения" msgid "Incorrect PIN Code. Try again." msgstr "Неверный PIN-код. Попробуйте еще раз." -#: src/screens/PinScreen.js:77 +#: src/screens/PinScreen.js:76 msgid "Enter your PIN Code " msgstr "Введите свой PIN-код " -#: src/screens/PinScreen.js:78 +#: src/screens/PinScreen.js:77 msgid "Unlock Hathor Wallet" msgstr "Разблокировать Hathor Wallet" @@ -670,36 +670,36 @@ msgstr "" msgid "Reset Wallet" msgstr "Сбросить Кошелек" -#: src/screens/Security.js:131 +#: src/screens/Security.js:130 msgid "Disable biometry" msgstr "Отключить биометрию" -#: src/screens/Security.js:132 +#: src/screens/Security.js:131 msgid "Disabling biometry" msgstr "Отключение биометрии" -#: src/screens/Security.js:144 +#: src/screens/Security.js:143 msgid "Enter your 6-digit pin to enable biometry" msgstr "Введите 6-значный PIN-код, чтобы включить биометрию" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 msgid "No biometry supported" msgstr "Биометрия не поддерживается" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 #, javascript-format msgid "Use ${ this.supportedBiometry }" msgstr "Использовать ${ this.supportedBiometry }" -#: src/screens/Security.js:160 +#: src/screens/Security.js:164 msgid "SECURITY" msgstr "БЕЗОПАСНОСТЬ" -#: src/screens/Security.js:184 +#: src/screens/Security.js:186 msgid "Change PIN" msgstr "Изменить PIN-код" -#: src/screens/Security.js:189 +#: src/screens/Security.js:191 msgid "Lock wallet" msgstr "Заблокировать кошелек" @@ -1016,8 +1016,8 @@ msgstr "" #: src/components/NanoContract/NanoContractDetails.js:202 #: src/components/NanoContract/SelectAddressModal.js:105 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:243 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:284 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:272 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:313 #: src/screens/NanoContract/NanoContractRegisterScreen.js:184 msgid "Loading" msgstr "" @@ -1149,21 +1149,21 @@ msgstr "" msgid "Error loading the details of some tokens." msgstr "" -#: src/sagas/wallet.js:805 +#: src/sagas/wallet.js:781 msgid "Wallet is not ready to load addresses." msgstr "" #. This will show the message in the feedback content at SelectAddressModal -#: src/sagas/wallet.js:821 +#: src/sagas/wallet.js:797 msgid "There was an error while loading wallet addresses. Try again." msgstr "" -#: src/sagas/wallet.js:831 +#: src/sagas/wallet.js:807 msgid "Wallet is not ready to load the first address." msgstr "" #. This will show the message in the feedback content -#: src/sagas/wallet.js:847 +#: src/sagas/wallet.js:823 msgid "There was an error while loading first wallet address. Try again." msgstr "" @@ -1455,12 +1455,12 @@ msgid "Decline Request" msgstr "" #: src/components/Reown/CreateTokenRequest.js:172 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:323 msgid "Sending transaction" msgstr "" #: src/components/Reown/CreateTokenRequest.js:173 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:295 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:324 msgid "Please wait." msgstr "" @@ -1599,47 +1599,57 @@ msgstr "" msgid "Review transaction details" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:205 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:234 msgid "Success!" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:206 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:235 msgid "Transaction successfully sent." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:244 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:273 msgid "Registering Nano Contract." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:253 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:282 msgid "Nano Contract Not Found" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:254 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:283 msgid "" "The Nano Contract requested is not registered. First register the Nano " "Contract to interact with it." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:265 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:279 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:330 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:308 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:371 msgid "Decline Transaction" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:277 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:306 msgid "Error while registering Nano Contract." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:285 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:314 msgid "Loading transaction information." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:326 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +msgid "Insufficient Funds" +msgstr "" + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:359 +msgid "" +"Ensure your wallet balance covers the required amount to accept this " +"transaction." +msgstr "" + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:364 msgid "Accept Transaction" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:356 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:397 msgid "Error while sending transaction." msgstr "" diff --git a/locale/texts.pot b/locale/texts.pot index 04397ddc6..2ebbd085a 100644 --- a/locale/texts.pot +++ b/locale/texts.pot @@ -48,12 +48,12 @@ msgid "[Last] dddd [•] HH:mm" msgstr "" #: src/models.js:107 -#: src/utils.js:553 +#: src/utils.js:567 #. See https://momentjs.com/docs/#/displaying/calendar-time/ msgid "DD MMM YYYY [•] HH:mm" msgstr "" -#: src/utils.js:227 +#: src/utils.js:241 msgid "Invalid address" msgstr "" @@ -428,7 +428,7 @@ msgstr "" #: src/components/NanoContract/NanoContractDetails.js:238 #: src/components/Reown/CreateTokenRequest.js:197 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:399 #: src/screens/LoadHistoryScreen.js:51 #: src/screens/LoadWalletErrorScreen.js:20 #: src/screens/NanoContract/NanoContractRegisterScreen.js:168 @@ -496,7 +496,7 @@ msgstr "" msgid "Manual" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:260 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 msgid "Register Nano Contract" @@ -547,11 +547,11 @@ msgstr "" msgid "Incorrect PIN Code. Try again." msgstr "" -#: src/screens/PinScreen.js:77 +#: src/screens/PinScreen.js:76 msgid "Enter your PIN Code " msgstr "" -#: src/screens/PinScreen.js:78 +#: src/screens/PinScreen.js:77 msgid "Unlock Hathor Wallet" msgstr "" @@ -665,36 +665,36 @@ msgstr "" msgid "Reset Wallet" msgstr "" -#: src/screens/Security.js:131 +#: src/screens/Security.js:130 msgid "Disable biometry" msgstr "" -#: src/screens/Security.js:132 +#: src/screens/Security.js:131 msgid "Disabling biometry" msgstr "" -#: src/screens/Security.js:144 +#: src/screens/Security.js:143 msgid "Enter your 6-digit pin to enable biometry" msgstr "" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 msgid "No biometry supported" msgstr "" -#: src/screens/Security.js:155 +#: src/screens/Security.js:156 #, javascript-format msgid "Use ${ this.supportedBiometry }" msgstr "" -#: src/screens/Security.js:160 +#: src/screens/Security.js:164 msgid "SECURITY" msgstr "" -#: src/screens/Security.js:184 +#: src/screens/Security.js:186 msgid "Change PIN" msgstr "" -#: src/screens/Security.js:189 +#: src/screens/Security.js:191 msgid "Lock wallet" msgstr "" @@ -1014,8 +1014,8 @@ msgstr "" #: src/components/NanoContract/NanoContractDetails.js:202 #: src/components/NanoContract/SelectAddressModal.js:105 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:243 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:284 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:272 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:313 #: src/screens/NanoContract/NanoContractRegisterScreen.js:184 msgid "Loading" msgstr "" @@ -1147,20 +1147,20 @@ msgstr "" msgid "Error loading the details of some tokens." msgstr "" -#: src/sagas/wallet.js:805 +#: src/sagas/wallet.js:781 msgid "Wallet is not ready to load addresses." msgstr "" -#: src/sagas/wallet.js:821 +#: src/sagas/wallet.js:797 #. This will show the message in the feedback content at SelectAddressModal msgid "There was an error while loading wallet addresses. Try again." msgstr "" -#: src/sagas/wallet.js:831 +#: src/sagas/wallet.js:807 msgid "Wallet is not ready to load the first address." msgstr "" -#: src/sagas/wallet.js:847 +#: src/sagas/wallet.js:823 #. This will show the message in the feedback content msgid "There was an error while loading first wallet address. Try again." msgstr "" @@ -1453,12 +1453,12 @@ msgid "Decline Request" msgstr "" #: src/components/Reown/CreateTokenRequest.js:172 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:323 msgid "Sending transaction" msgstr "" #: src/components/Reown/CreateTokenRequest.js:173 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:295 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:324 msgid "Please wait." msgstr "" @@ -1596,47 +1596,57 @@ msgstr "" msgid "Review transaction details" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:205 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:234 msgid "Success!" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:206 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:235 msgid "Transaction successfully sent." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:244 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:273 msgid "Registering Nano Contract." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:253 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:282 msgid "Nano Contract Not Found" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:254 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:283 msgid "" "The Nano Contract requested is not registered. First register the Nano " "Contract to interact with it." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:265 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:279 -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:330 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:294 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:308 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:371 msgid "Decline Transaction" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:277 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:306 msgid "Error while registering Nano Contract." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:285 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:314 msgid "Loading transaction information." msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:326 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:358 +msgid "Insufficient Funds" +msgstr "" + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:359 +msgid "" +"Ensure your wallet balance covers the required amount to accept this " +"transaction." +msgstr "" + +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:364 msgid "Accept Transaction" msgstr "" -#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:356 +#: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:397 msgid "Error while sending transaction." msgstr "" diff --git a/src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js b/src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js index d89e05ecc..ecf5e0d4a 100644 --- a/src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js +++ b/src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js @@ -15,7 +15,8 @@ import { View, ScrollView, TouchableWithoutFeedback, - Image + Image, + Text } from 'react-native'; import { useDispatch, useSelector } from 'react-redux'; import { useNavigation } from '@react-navigation/native'; @@ -70,6 +71,7 @@ export const NewNanoContractTransactionRequest = ({ ncTxRequest }) => { // Nullable if the nano contract method is 'initialize' const registeredNc = useSelector((state) => state.nanoContract.registered[nc.ncId]); const knownTokens = useSelector((state) => ({ ...state.tokens, ...state.unregisteredTokens })); + const tokensBalance = useSelector((state) => state.tokensBalance); const blueprintInfo = useSelector((state) => state.nanoContract.blueprint[nc.blueprintId]); const registerStatus = useSelector((state) => state.nanoContract.registerStatus); const isNcRegistering = ( @@ -94,6 +96,33 @@ export const NewNanoContractTransactionRequest = ({ ncTxRequest }) => { caller: ncAddress, }), [ncAddress]) + // Check if we have enough balance for deposit actions + const hasInsufficientBalance = useMemo(() => { + if (!nc.actions) return false; + + // Track running balance per token + const tokenBalances = {}; + + for (const { type, token, amount } of nc.actions) { + if (type === 'deposit') { + // Initialize token balance if first time seeing this token + if (!(token in tokenBalances)) { + const balance = tokensBalance[token]?.data?.available || 0; + tokenBalances[token] = balance; + } + + tokenBalances[token] -= amount; + + if (tokenBalances[token] < 0) { + // Early exit if we go negative + return true; + } + } + } + + return false; + }, [nc.actions, tokensBalance]); + const toggleSelectAddressModal = () => setShowSelectAddressModal(!showSelectAddressModal); const handleAddressSelection = (newAddress) => { setNcAddress(newAddress); @@ -322,9 +351,21 @@ export const NewNanoContractTransactionRequest = ({ ncTxRequest }) => { {/* User actions */} + {hasInsufficientBalance && ( + + + + {t`Insufficient Funds`}. + {t`Ensure your wallet balance covers the required amount to accept this transaction.`} + + + )} Date: Thu, 16 Jan 2025 10:16:38 -0300 Subject: [PATCH 5/6] feat: added generic qr code on dashboard screen (#642) * feat: added generic qr code on dashboard screen * feat: added manual register navigation screen * refactor: removed tabbar qr code navigation * feat: better qr code icon, hide keyboard when navigating and better paddings * refactor: reduced title size for tokens and nano contracts * feat: considering feature toggles * fix: untranslatable string * chore: update locale * chore: lint * chore: added missing locale * chore: added missing locale --- locale/da/texts.po | 86 ++++++++++-- locale/pt-br/texts.po | 86 ++++++++++-- locale/ru-ru/texts.po | 86 ++++++++++-- locale/texts.pot | 92 +++++++++++-- src/App.js | 8 ++ src/components/Icons/QRCodeIcon.js | 21 +++ .../NanoContract/NanoContractsList.js | 5 +- src/components/TwoOptionsToggle.js | 9 +- src/screens/Dashboard.js | 39 +++--- .../NanoContractRegisterScreen.js | 2 +- src/screens/RegisterOptionsScreen.js | 123 ++++++++++++++++++ src/screens/RegisterTokenManual.js | 2 +- src/screens/UnifiedQRScanner.js | 105 +++++++++++++++ 13 files changed, 582 insertions(+), 82 deletions(-) create mode 100644 src/components/Icons/QRCodeIcon.js create mode 100644 src/screens/RegisterOptionsScreen.js create mode 100644 src/screens/UnifiedQRScanner.js diff --git a/locale/da/texts.po b/locale/da/texts.po index ce8bbd9eb..ec327d2e0 100644 --- a/locale/da/texts.po +++ b/locale/da/texts.po @@ -340,20 +340,16 @@ msgid "E.g. HTR" msgstr "F.eks. HTR" #. Only show the toggle button when Nano Contract is enabled to the wallet -#: src/screens/Dashboard.js:130 src/screens/Dashboard.js:187 +#: src/screens/Dashboard.js:131 src/screens/Dashboard.js:186 msgid "Tokens" msgstr "Tokens" #. Only show the toggle button when Nano Contract is enabled to the wallet #: src/components/NanoContract/NanoContractsList.js:75 -#: src/screens/Dashboard.js:131 +#: src/screens/Dashboard.js:132 msgid "Nano Contracts" msgstr "" -#: src/screens/Dashboard.js:178 src/screens/RegisterTokenManual.js:147 -msgid "Register token" -msgstr "Registrer token" - #: src/screens/InitWallet.js:62 msgid "Welcome to Hathor Wallet!" msgstr "Velkommen til Hathor Wallet!" @@ -499,13 +495,14 @@ msgstr "Låst" #. translator: Used when the QR Code Scanner is opened, and user will manually #. enter the information. #: src/screens/NanoContractRegisterQrCodeScreen.js:26 -#: src/screens/Reown/ReownScan.js:41 +#: src/screens/Reown/ReownScan.js:41 src/screens/UnifiedQRScanner.js:88 msgid "Manual" msgstr "" #: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 +#: src/screens/RegisterOptionsScreen.js:77 msgid "Register Nano Contract" msgstr "" @@ -604,6 +601,54 @@ msgstr "Betalingsanmodning" msgid "RECEIVE" msgstr "MODTAG" +#: src/screens/RegisterOptionsScreen.js:26 +msgid "You can register Tokens manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:30 +msgid "You can register Tokens and Nano Contracts manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:34 +msgid "You can register Tokens and use Reown manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:37 +msgid "You can register Tokens, Nano Contracts or Reown manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:43 +#: src/screens/RegisterOptionsScreen.js:55 src/screens/UnifiedQRScanner.js:52 +#: src/screens/UnifiedQRScanner.js:69 +msgid "Feature Not Available" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:44 src/screens/UnifiedQRScanner.js:69 +msgid "The nano contract feature is not enabled." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:45 +#: src/screens/RegisterOptionsScreen.js:57 src/screens/SendScanQRCode.js:39 +#: src/screens/UnifiedQRScanner.js:36 +msgid "OK" +msgstr "Okay" + +#: src/screens/RegisterOptionsScreen.js:56 src/screens/UnifiedQRScanner.js:52 +msgid "The reown feature is not enabled." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:67 +msgid "Register" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:83 +msgid "Register Token" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:89 +msgid "Reown Connection" +msgstr "" + #. translator: Used when the QR Code Scanner is opened, and user will manually #. enter the information. #: src/screens/RegisterToken.js:27 src/screens/SendScanQRCode.js:87 @@ -634,6 +679,10 @@ msgstr "Symbol: " msgid "Configuration string" msgstr "Konfigurationsstreng" +#: src/screens/RegisterTokenManual.js:147 +msgid "Register token" +msgstr "Registrer token" + #: src/screens/ResetWallet.js:104 msgid "RESET WALLET" msgstr "NULSTIL WALLET" @@ -758,16 +807,13 @@ msgstr "Send" msgid "Invalid QR code" msgstr "Ugyldig QR-kode" -#: src/screens/SendScanQRCode.js:39 -msgid "OK" -msgstr "Okay" - #: src/screens/SendScanQRCode.js:71 #, javascript-format msgid "You don't have the requested token [${ tokenLabel }]" msgstr "Du har ikke den anmodede token [${ tokenLabel }]" #: src/screens/Reown/ReownScan.js:49 src/screens/SendScanQRCode.js:103 +#: src/screens/UnifiedQRScanner.js:96 msgid "Scan the QR code" msgstr "Scan QR-koden" @@ -815,6 +861,20 @@ msgstr "" msgid "Unregister" msgstr "Afmeld" +#. If none of the patterns match, show an error or handle accordingly +#: src/screens/UnifiedQRScanner.js:77 +msgid "Invalid QR Code" +msgstr "" + +#. If none of the patterns match, show an error or handle accordingly +#: src/screens/UnifiedQRScanner.js:77 +msgid "The scanned QR code is not in a recognized format." +msgstr "" + +#: src/screens/UnifiedQRScanner.js:83 +msgid "Scan QR Code" +msgstr "" + #: src/screens/UnregisterToken.js:108 msgid "UNREGISTER TOKEN" msgstr "AFREGISTRER TOKEN" @@ -1764,11 +1824,11 @@ msgstr "" msgid "See transaction details" msgstr "" -#: src/components/NanoContract/NanoContractsList.js:85 +#: src/components/NanoContract/NanoContractsList.js:82 msgid "No Nano Contracts" msgstr "" -#: src/components/NanoContract/NanoContractsList.js:86 +#: src/components/NanoContract/NanoContractsList.js:83 msgid "" "You can keep track of your registered Nano Contracts here once you have " "registered them." diff --git a/locale/pt-br/texts.po b/locale/pt-br/texts.po index 461038877..2ebd22313 100644 --- a/locale/pt-br/texts.po +++ b/locale/pt-br/texts.po @@ -349,20 +349,16 @@ msgid "E.g. HTR" msgstr "Por exemplo, HTR" #. Only show the toggle button when Nano Contract is enabled to the wallet -#: src/screens/Dashboard.js:130 src/screens/Dashboard.js:187 +#: src/screens/Dashboard.js:131 src/screens/Dashboard.js:186 msgid "Tokens" msgstr "Tokens" #. Only show the toggle button when Nano Contract is enabled to the wallet #: src/components/NanoContract/NanoContractsList.js:75 -#: src/screens/Dashboard.js:131 +#: src/screens/Dashboard.js:132 msgid "Nano Contracts" msgstr "Nano Contracts" -#: src/screens/Dashboard.js:178 src/screens/RegisterTokenManual.js:147 -msgid "Register token" -msgstr "Registrar um token" - #: src/screens/InitWallet.js:62 msgid "Welcome to Hathor Wallet!" msgstr "Bem vindo à Hathor Wallet!" @@ -512,13 +508,14 @@ msgstr "Bloqueado" #. translator: Used when the QR Code Scanner is opened, and user will manually #. enter the information. #: src/screens/NanoContractRegisterQrCodeScreen.js:26 -#: src/screens/Reown/ReownScan.js:41 +#: src/screens/Reown/ReownScan.js:41 src/screens/UnifiedQRScanner.js:88 msgid "Manual" msgstr "Digitar" #: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 +#: src/screens/RegisterOptionsScreen.js:77 msgid "Register Nano Contract" msgstr "Registrar Nano Contract" @@ -619,6 +616,54 @@ msgstr "Requisição de Pagamento" msgid "RECEIVE" msgstr "RECEBER" +#: src/screens/RegisterOptionsScreen.js:26 +msgid "You can register Tokens manually." +msgstr "Você pode registrar Tokens manualmente." + +#: src/screens/RegisterOptionsScreen.js:30 +msgid "You can register Tokens and Nano Contracts manually." +msgstr "Você pode registrar Tokens e Nano Contracts manualmente." + +#: src/screens/RegisterOptionsScreen.js:34 +msgid "You can register Tokens and use Reown manually." +msgstr "Você pode registrar Tokens e usar o Reown manualmente." + +#: src/screens/RegisterOptionsScreen.js:37 +msgid "You can register Tokens, Nano Contracts or Reown manually." +msgstr "Você pode registrar Tokens, Nano Contracts ou o Reown manualmente." + +#: src/screens/RegisterOptionsScreen.js:43 +#: src/screens/RegisterOptionsScreen.js:55 src/screens/UnifiedQRScanner.js:52 +#: src/screens/UnifiedQRScanner.js:69 +msgid "Feature Not Available" +msgstr "Funcionalidade não disponível." + +#: src/screens/RegisterOptionsScreen.js:44 src/screens/UnifiedQRScanner.js:69 +msgid "The nano contract feature is not enabled." +msgstr "Nano Contracts não estão habilitados." + +#: src/screens/RegisterOptionsScreen.js:45 +#: src/screens/RegisterOptionsScreen.js:57 src/screens/SendScanQRCode.js:39 +#: src/screens/UnifiedQRScanner.js:36 +msgid "OK" +msgstr "OK" + +#: src/screens/RegisterOptionsScreen.js:56 src/screens/UnifiedQRScanner.js:52 +msgid "The reown feature is not enabled." +msgstr "Reown não está habilitado." + +#: src/screens/RegisterOptionsScreen.js:67 +msgid "Register" +msgstr "Registrar" + +#: src/screens/RegisterOptionsScreen.js:83 +msgid "Register Token" +msgstr "Registrar um token" + +#: src/screens/RegisterOptionsScreen.js:89 +msgid "Reown Connection" +msgstr "Reown" + #. translator: Used when the QR Code Scanner is opened, and user will manually #. enter the information. #: src/screens/RegisterToken.js:27 src/screens/SendScanQRCode.js:87 @@ -649,6 +694,10 @@ msgstr "Símbolo: " msgid "Configuration string" msgstr "Configuração" +#: src/screens/RegisterTokenManual.js:147 +msgid "Register token" +msgstr "Registrar um token" + #: src/screens/ResetWallet.js:104 msgid "RESET WALLET" msgstr "RESETAR WALLET" @@ -774,16 +823,13 @@ msgstr "Enviar" msgid "Invalid QR code" msgstr "QR code inválido" -#: src/screens/SendScanQRCode.js:39 -msgid "OK" -msgstr "OK" - #: src/screens/SendScanQRCode.js:71 #, javascript-format msgid "You don't have the requested token [${ tokenLabel }]" msgstr "Você não tem o token requisitado [${ tokenLabel }]" #: src/screens/Reown/ReownScan.js:49 src/screens/SendScanQRCode.js:103 +#: src/screens/UnifiedQRScanner.js:96 msgid "Scan the QR code" msgstr "Leia o QR code" @@ -831,6 +877,20 @@ msgstr "Configurações de Rede" msgid "Unregister" msgstr "Desregistrar" +#. If none of the patterns match, show an error or handle accordingly +#: src/screens/UnifiedQRScanner.js:77 +msgid "Invalid QR Code" +msgstr "QR code inválido" + +#. If none of the patterns match, show an error or handle accordingly +#: src/screens/UnifiedQRScanner.js:77 +msgid "The scanned QR code is not in a recognized format." +msgstr "O QR code escaneado não está em um formato reconhecível." + +#: src/screens/UnifiedQRScanner.js:83 +msgid "Scan QR Code" +msgstr "Leia o QR code" + #: src/screens/UnregisterToken.js:108 msgid "UNREGISTER TOKEN" msgstr "DESREGISTRAR TOKEN" @@ -1808,11 +1868,11 @@ msgstr "Desta wallet" msgid "See transaction details" msgstr "Ver detalhes" -#: src/components/NanoContract/NanoContractsList.js:85 +#: src/components/NanoContract/NanoContractsList.js:82 msgid "No Nano Contracts" msgstr "Nenhum Nano Contract" -#: src/components/NanoContract/NanoContractsList.js:86 +#: src/components/NanoContract/NanoContractsList.js:83 msgid "" "You can keep track of your registered Nano Contracts here once you have " "registered them." diff --git a/locale/ru-ru/texts.po b/locale/ru-ru/texts.po index f4aa2824d..68b671187 100644 --- a/locale/ru-ru/texts.po +++ b/locale/ru-ru/texts.po @@ -341,20 +341,16 @@ msgid "E.g. HTR" msgstr "Например, HTR" #. Only show the toggle button when Nano Contract is enabled to the wallet -#: src/screens/Dashboard.js:130 src/screens/Dashboard.js:187 +#: src/screens/Dashboard.js:131 src/screens/Dashboard.js:186 msgid "Tokens" msgstr "ТокенЫ" #. Only show the toggle button when Nano Contract is enabled to the wallet #: src/components/NanoContract/NanoContractsList.js:75 -#: src/screens/Dashboard.js:131 +#: src/screens/Dashboard.js:132 msgid "Nano Contracts" msgstr "" -#: src/screens/Dashboard.js:178 src/screens/RegisterTokenManual.js:147 -msgid "Register token" -msgstr "Зарегистрировать токен" - #: src/screens/InitWallet.js:62 msgid "Welcome to Hathor Wallet!" msgstr "Добро пожаловать в Hathor Wallet!" @@ -501,13 +497,14 @@ msgstr "Заблокированный" #. translator: Used when the QR Code Scanner is opened, and user will manually #. enter the information. #: src/screens/NanoContractRegisterQrCodeScreen.js:26 -#: src/screens/Reown/ReownScan.js:41 +#: src/screens/Reown/ReownScan.js:41 src/screens/UnifiedQRScanner.js:88 msgid "Manual" msgstr "" #: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 +#: src/screens/RegisterOptionsScreen.js:77 msgid "Register Nano Contract" msgstr "" @@ -606,6 +603,54 @@ msgstr "Запрос Средств" msgid "RECEIVE" msgstr "ПОЛУЧИТЬ" +#: src/screens/RegisterOptionsScreen.js:26 +msgid "You can register Tokens manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:30 +msgid "You can register Tokens and Nano Contracts manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:34 +msgid "You can register Tokens and use Reown manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:37 +msgid "You can register Tokens, Nano Contracts or Reown manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:43 +#: src/screens/RegisterOptionsScreen.js:55 src/screens/UnifiedQRScanner.js:52 +#: src/screens/UnifiedQRScanner.js:69 +msgid "Feature Not Available" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:44 src/screens/UnifiedQRScanner.js:69 +msgid "The nano contract feature is not enabled." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:45 +#: src/screens/RegisterOptionsScreen.js:57 src/screens/SendScanQRCode.js:39 +#: src/screens/UnifiedQRScanner.js:36 +msgid "OK" +msgstr "OK" + +#: src/screens/RegisterOptionsScreen.js:56 src/screens/UnifiedQRScanner.js:52 +msgid "The reown feature is not enabled." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:67 +msgid "Register" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:83 +msgid "Register Token" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:89 +msgid "Reown Connection" +msgstr "" + #. translator: Used when the QR Code Scanner is opened, and user will manually #. enter the information. #: src/screens/RegisterToken.js:27 src/screens/SendScanQRCode.js:87 @@ -636,6 +681,10 @@ msgstr "Символ: " msgid "Configuration string" msgstr "Конфигурация" +#: src/screens/RegisterTokenManual.js:147 +msgid "Register token" +msgstr "Зарегистрировать токен" + #: src/screens/ResetWallet.js:104 msgid "RESET WALLET" msgstr "СБРОСИТЬ КОШЕЛЕК" @@ -760,16 +809,13 @@ msgstr "Отправить" msgid "Invalid QR code" msgstr "Неверный QR-код" -#: src/screens/SendScanQRCode.js:39 -msgid "OK" -msgstr "OK" - #: src/screens/SendScanQRCode.js:71 #, javascript-format msgid "You don't have the requested token [${ tokenLabel }]" msgstr "У вас нет запрошенного токена [${ tokenLabel }]" #: src/screens/Reown/ReownScan.js:49 src/screens/SendScanQRCode.js:103 +#: src/screens/UnifiedQRScanner.js:96 msgid "Scan the QR code" msgstr "Сканировать QR-код" @@ -817,6 +863,20 @@ msgstr "" msgid "Unregister" msgstr "Отменить регистрацию" +#. If none of the patterns match, show an error or handle accordingly +#: src/screens/UnifiedQRScanner.js:77 +msgid "Invalid QR Code" +msgstr "" + +#. If none of the patterns match, show an error or handle accordingly +#: src/screens/UnifiedQRScanner.js:77 +msgid "The scanned QR code is not in a recognized format." +msgstr "" + +#: src/screens/UnifiedQRScanner.js:83 +msgid "Scan QR Code" +msgstr "" + #: src/screens/UnregisterToken.js:108 msgid "UNREGISTER TOKEN" msgstr "ОТМЕНИТЬ РЕГИСТРАЦИЮ ТОКЕНА" @@ -1753,11 +1813,11 @@ msgstr "" msgid "See transaction details" msgstr "" -#: src/components/NanoContract/NanoContractsList.js:85 +#: src/components/NanoContract/NanoContractsList.js:82 msgid "No Nano Contracts" msgstr "" -#: src/components/NanoContract/NanoContractsList.js:86 +#: src/components/NanoContract/NanoContractsList.js:83 msgid "" "You can keep track of your registered Nano Contracts here once you have " "registered them." diff --git a/locale/texts.pot b/locale/texts.pot index 2ebbd085a..d35a25a3f 100644 --- a/locale/texts.pot +++ b/locale/texts.pot @@ -334,23 +334,18 @@ msgstr "" msgid "E.g. HTR" msgstr "" -#: src/screens/Dashboard.js:130 -#: src/screens/Dashboard.js:187 +#: src/screens/Dashboard.js:131 +#: src/screens/Dashboard.js:186 #. Only show the toggle button when Nano Contract is enabled to the wallet msgid "Tokens" msgstr "" #: src/components/NanoContract/NanoContractsList.js:75 -#: src/screens/Dashboard.js:131 +#: src/screens/Dashboard.js:132 #. Only show the toggle button when Nano Contract is enabled to the wallet msgid "Nano Contracts" msgstr "" -#: src/screens/Dashboard.js:178 -#: src/screens/RegisterTokenManual.js:147 -msgid "Register token" -msgstr "" - #: src/screens/InitWallet.js:62 msgid "Welcome to Hathor Wallet!" msgstr "" @@ -491,6 +486,7 @@ msgstr "" #: src/screens/NanoContractRegisterQrCodeScreen.js:26 #: src/screens/Reown/ReownScan.js:41 +#: src/screens/UnifiedQRScanner.js:88 #. translator: Used when the QR Code Scanner is opened, and user will manually #. enter the information. msgid "Manual" @@ -499,6 +495,7 @@ msgstr "" #: src/components/Reown/NanoContract/NewNanoContractTransactionRequest.js:289 #: src/screens/NanoContract/NanoContractRegisterScreen.js:233 #: src/screens/NanoContractRegisterQrCodeScreen.js:48 +#: src/screens/RegisterOptionsScreen.js:77 msgid "Register Nano Contract" msgstr "" @@ -603,6 +600,58 @@ msgstr "" msgid "RECEIVE" msgstr "" +#: src/screens/RegisterOptionsScreen.js:26 +msgid "You can register Tokens manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:30 +msgid "You can register Tokens and Nano Contracts manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:34 +msgid "You can register Tokens and use Reown manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:37 +msgid "You can register Tokens, Nano Contracts or Reown manually." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:43 +#: src/screens/RegisterOptionsScreen.js:55 +#: src/screens/UnifiedQRScanner.js:52 +#: src/screens/UnifiedQRScanner.js:69 +msgid "Feature Not Available" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:44 +#: src/screens/UnifiedQRScanner.js:69 +msgid "The nano contract feature is not enabled." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:45 +#: src/screens/RegisterOptionsScreen.js:57 +#: src/screens/SendScanQRCode.js:39 +#: src/screens/UnifiedQRScanner.js:36 +msgid "OK" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:56 +#: src/screens/UnifiedQRScanner.js:52 +msgid "The reown feature is not enabled." +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:67 +msgid "Register" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:83 +msgid "Register Token" +msgstr "" + +#: src/screens/RegisterOptionsScreen.js:89 +msgid "Reown Connection" +msgstr "" + #: src/screens/RegisterToken.js:27 #: src/screens/SendScanQRCode.js:87 #. translator: Used when the QR Code Scanner is opened, and user will manually @@ -635,6 +684,10 @@ msgstr "" msgid "Configuration string" msgstr "" +#: src/screens/RegisterTokenManual.js:147 +msgid "Register token" +msgstr "" + #: src/screens/ResetWallet.js:104 msgid "RESET WALLET" msgstr "" @@ -759,10 +812,6 @@ msgstr "" msgid "Invalid QR code" msgstr "" -#: src/screens/SendScanQRCode.js:39 -msgid "OK" -msgstr "" - #: src/screens/SendScanQRCode.js:71 #, javascript-format msgid "You don't have the requested token [${ tokenLabel }]" @@ -770,6 +819,7 @@ msgstr "" #: src/screens/Reown/ReownScan.js:49 #: src/screens/SendScanQRCode.js:103 +#: src/screens/UnifiedQRScanner.js:96 msgid "Scan the QR code" msgstr "" @@ -817,6 +867,20 @@ msgstr "" msgid "Unregister" msgstr "" +#: src/screens/UnifiedQRScanner.js:77 +#. If none of the patterns match, show an error or handle accordingly +msgid "Invalid QR Code" +msgstr "" + +#: src/screens/UnifiedQRScanner.js:77 +#. If none of the patterns match, show an error or handle accordingly +msgid "The scanned QR code is not in a recognized format." +msgstr "" + +#: src/screens/UnifiedQRScanner.js:83 +msgid "Scan QR Code" +msgstr "" + #: src/screens/UnregisterToken.js:108 msgid "UNREGISTER TOKEN" msgstr "" @@ -1750,11 +1814,11 @@ msgstr "" msgid "See transaction details" msgstr "" -#: src/components/NanoContract/NanoContractsList.js:85 +#: src/components/NanoContract/NanoContractsList.js:82 msgid "No Nano Contracts" msgstr "" -#: src/components/NanoContract/NanoContractsList.js:86 +#: src/components/NanoContract/NanoContractsList.js:83 msgid "" "You can keep track of your registered Nano Contracts here once you have " "registered them." diff --git a/src/App.js b/src/App.js index c4c7ec049..dffe58a36 100644 --- a/src/App.js +++ b/src/App.js @@ -97,6 +97,8 @@ import { SignMessageRequestScreen } from './screens/Reown/SignMessageRequestScre import { SignOracleDataRequestScreen } from './screens/Reown/SignOracleDataRequestScreen'; import { CreateTokenRequestScreen } from './screens/Reown/CreateTokenScreen'; import { SuccessFeedbackScreen } from './screens/Reown/SuccessFeedbackScreen'; +import UnifiedQRScanner from './screens/UnifiedQRScanner'; +import RegisterOptionsScreen from './screens/RegisterOptionsScreen'; /** * This Stack Navigator is exhibited when there is no wallet initialized on the local storage. @@ -430,6 +432,9 @@ const AppStack = () => { case 'CreateTokenStack': case 'About': case 'ResetWallet': + case 'UnifiedQRScanner': + case 'RegisterOptions': + case 'RegisterTokenManual': newEdges = ['bottom']; break; default: @@ -453,6 +458,9 @@ const AppStack = () => { initialParams={{ hName: 'Main' }} component={TabNavigator} /> + + + diff --git a/src/components/Icons/QRCodeIcon.js b/src/components/Icons/QRCodeIcon.js new file mode 100644 index 000000000..58b60aa3c --- /dev/null +++ b/src/components/Icons/QRCodeIcon.js @@ -0,0 +1,21 @@ +/** + * Copyright (c) Hathor Labs and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import Svg, { Path } from 'react-native-svg'; +import { COLORS } from '../../styles/themes'; + +const QRCodeIcon = ({ size = 25, color = COLORS.primary }) => ( + + + +); + +export default QRCodeIcon; diff --git a/src/components/NanoContract/NanoContractsList.js b/src/components/NanoContract/NanoContractsList.js index 418797083..8fc002d84 100644 --- a/src/components/NanoContract/NanoContractsList.js +++ b/src/components/NanoContract/NanoContractsList.js @@ -74,9 +74,6 @@ const Header = () => ( {t`Nano Contracts`} - - - ); @@ -96,7 +93,7 @@ const styles = StyleSheet.create({ backgroundColor: COLORS.lowContrastDetail, // Defines an outer area on the main list content }, headerTitle: { - fontSize: 24, + fontSize: 20, lineHeight: 24, fontWeight: 'bold', }, diff --git a/src/components/TwoOptionsToggle.js b/src/components/TwoOptionsToggle.js index af02df398..c9eef74e0 100644 --- a/src/components/TwoOptionsToggle.js +++ b/src/components/TwoOptionsToggle.js @@ -58,18 +58,15 @@ const Option = ({ optionValue, isActive, onTap }) => ( const styles = StyleSheet.create({ wrapper: { - display: 'flex', flexDirection: 'row', - width: '80%', - marginTop: 16, + alignItems: 'center', borderRadius: 24, backgroundColor: 'hsla(220, 10%, 94%, 1)', }, button: { width: '50%', borderRadius: 24, - paddingTop: 9, - paddingBottom: 10, + paddingVertical: 12, color: COLORS.textColor, }, buttonFocus: { @@ -82,5 +79,5 @@ const styles = StyleSheet.create({ }, textFocus: { fontWeight: 'bold', - }, + } }); diff --git a/src/screens/Dashboard.js b/src/screens/Dashboard.js index 0e7f1ada3..df6dc5544 100644 --- a/src/screens/Dashboard.js +++ b/src/screens/Dashboard.js @@ -18,6 +18,7 @@ import TokenSelect from '../components/TokenSelect'; import SimpleButton from '../components/SimpleButton'; import OfflineBar from '../components/OfflineBar'; import { TwoOptionsToggle } from '../components/TwoOptionsToggle'; +import QRCodeIcon from '../components/Icons/QRCodeIcon'; import { tokenFetchBalanceRequested, updateSelectedToken } from '../actions'; import AskForPushNotificationRefresh from '../components/AskForPushNotificationRefresh'; import { COLORS } from '../styles/themes'; @@ -165,19 +166,17 @@ const Wrapper = ({ children }) => ( ); -const DashBoardHeader = ({ children }) => ( - - {children} - -); - -const RegisterToken = () => { +const DashBoardHeader = ({ children }) => { const navigation = useNavigation(); return ( - navigation.navigate('RegisterToken')} - /> + + + {children} + + navigation.navigate('UnifiedQRScanner')} style={{ marginLeft: 16 }}> + + + ); }; @@ -186,24 +185,30 @@ const TokensHeader = () => ( {t`Tokens`} - - - ); const styles = StyleSheet.create({ wrapper: { flex: 1, + marginTop: 8, }, headerWrapper: { - display: 'flex', flexDirection: 'row', - justifyContent: 'center', + alignItems: 'center', backgroundColor: COLORS.lowContrastDetail, + paddingHorizontal: 16, + height: 48, + }, + toggleContainer: { + flex: 1, + alignItems: 'center', + flexDirection: 'row', + justifyContent: 'center', + paddingLeft: 8, }, headerTitle: { - fontSize: 24, + fontSize: 20, lineHeight: 24, fontWeight: 'bold', }, diff --git a/src/screens/NanoContract/NanoContractRegisterScreen.js b/src/screens/NanoContract/NanoContractRegisterScreen.js index d5bed315c..7b7a16bcc 100644 --- a/src/screens/NanoContract/NanoContractRegisterScreen.js +++ b/src/screens/NanoContract/NanoContractRegisterScreen.js @@ -192,7 +192,7 @@ export function NanoContractRegisterScreen({ navigation, route }) { { + const featureToggles = useSelector((state) => state.featureToggles); + const serverInfo = useSelector((state) => state.serverInfo); + const isReownEnabled = featureToggles[REOWN_FEATURE_TOGGLE] && get(serverInfo, 'nano_contracts_enabled', false); + const isNanoContractEnabled = featureToggles[NANO_CONTRACT_FEATURE_TOGGLE] && get(serverInfo, 'nano_contracts_enabled', false); + + const getDescriptionText = () => { + if (!isNanoContractEnabled && !isReownEnabled) { + return t`You can register Tokens manually.`; + } + + if (isNanoContractEnabled && !isReownEnabled) { + return t`You can register Tokens and Nano Contracts manually.`; + } + + if (!isNanoContractEnabled && isReownEnabled) { + return t`You can register Tokens and use Reown manually.`; + } + + return t`You can register Tokens, Nano Contracts or Reown manually.`; + }; + + const handleNanoContractNavigation = () => { + if (!isNanoContractEnabled) { + Alert.alert( + t`Feature Not Available`, + t`The nano contract feature is not enabled.`, + [{ text: t`OK` }] + ); + return; + } + navigation.navigate('NanoContractRegisterScreen'); + }; + + const handleReownNavigation = () => { + if (!isReownEnabled) { + Alert.alert( + t`Feature Not Available`, + t`The reown feature is not enabled.`, + [{ text: t`OK` }] + ); + return; + } + navigation.navigate('ReownManual'); + }; + + return ( + + navigation.goBack()} + /> + + + {getDescriptionText()} + + + {isNanoContractEnabled && ( + + )} + navigation.navigate('RegisterTokenManual')} + style={styles.button} + /> + {isReownEnabled && ( + + )} + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: COLORS.white, + }, + content: { + flex: 1, + paddingHorizontal: 16, + paddingTop: 24, + }, + description: { + fontSize: 16, + color: COLORS.textColor, + marginBottom: 24, + }, + buttonContainer: { + gap: 16, + }, + button: { + backgroundColor: COLORS.black, + }, +}); + +export default RegisterOptionsScreen; diff --git a/src/screens/RegisterTokenManual.js b/src/screens/RegisterTokenManual.js index 0b07655ac..335e7e34d 100644 --- a/src/screens/RegisterTokenManual.js +++ b/src/screens/RegisterTokenManual.js @@ -130,7 +130,7 @@ class RegisterTokenManual extends React.Component { { + const dispatch = useDispatch(); + const [isProcessing, setIsProcessing] = useState(false); + const featureToggles = useSelector((state) => state.featureToggles); + const serverInfo = useSelector((state) => state.serverInfo); + const isReownEnabled = featureToggles[REOWN_FEATURE_TOGGLE] && get(serverInfo, 'nano_contracts_enabled', false); + const isNanoContractEnabled = featureToggles[NANO_CONTRACT_FEATURE_TOGGLE] && get(serverInfo, 'nano_contracts_enabled', false); + + const showAlert = (title, message) => { + if (isProcessing) return; + setIsProcessing(true); + Alert.alert( + title, + message, + [{ text: t`OK`, onPress: () => setIsProcessing(false) }] + ); + }; + + const onSuccess = (e) => { + if (isProcessing) return; + const qrData = e.data; + + // Regex patterns for different types + const reownPattern = /^wc:[a-f0-9]+@\d+\?.*$/; + const tokenPattern = /^\[.*:.*:.*:.*\]$/; + const nanoContractPattern = /^[a-f0-9]{64}$/; + + // Check if it's a reown URI + if (reownPattern.test(qrData)) { + if (!isReownEnabled) { + showAlert(t`Feature Not Available`, t`The reown feature is not enabled.`); + return; + } + dispatch(reownUriInputted(qrData)); + navigation.replace('ReownList'); + return; + } + + // Check if it's a token registration QR code + if (tokenPattern.test(qrData)) { + navigation.replace('RegisterTokenManual', { configurationString: qrData }); + return; + } + + // Check if it's a nano contract ID + if (nanoContractPattern.test(qrData)) { + if (!isNanoContractEnabled) { + showAlert(t`Feature Not Available`, t`The nano contract feature is not enabled.`); + return; + } + navigation.replace('NanoContractRegisterScreen', { ncId: qrData }); + return; + } + + // If none of the patterns match, show an error or handle accordingly + showAlert(t`Invalid QR Code`, t`The scanned QR code is not in a recognized format.`); + }; + + return ( + + navigation.pop()} + rightElement={( + navigation.navigate('RegisterOptions')} + /> + )} + /> + + + + + + ); +}; + +export default UnifiedQRScanner; From 77626f8ad8cd3208cb1de24428f89cf43693cc3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Fri, 17 Jan 2025 09:48:22 -0300 Subject: [PATCH 6/6] feat: show full network name from serverInfo (or versionData) (#644) * feat: show full network name from serverInfo (or versionData) * refactor: added docstring and using types.SET_NETWORK_NAME * chore: added networkName default (null) and docstring in the reducer * refactor: using a single selector in network status bar * refactor: setNetworkName -> setFullNodeNetworkName * refactor: removed typo --- src/actions.js | 9 ++++++++ .../NetworkSettings/NetworkStatusBar.js | 13 +++++++---- src/reducers/reducer.js | 23 ++++++++++++++++++- src/sagas/networkSettings.js | 4 ++++ src/sagas/wallet.js | 12 ++++++++++ 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/actions.js b/src/actions.js index c28c9755c..fa0476daf 100644 --- a/src/actions.js +++ b/src/actions.js @@ -209,6 +209,7 @@ export const types = { APPSTATE_UPDATED: 'APPSTATE_UPDATED', SET_USE_SAFE_BIOMETRY_MODE: 'SET_USE_SAFE_BIOMETRY_MODE', SHOW_SIGN_ORACLE_DATA_REQUEST_MODAL: 'SHOW_SIGN_ORACLE_DATA_REQUEST_MODAL', + SET_FULLNODE_NETWORK_NAME: 'SET_FULLNODE_NETWORK_NAME', }; export const featureToggleInitialized = () => ({ @@ -1507,3 +1508,11 @@ export const appStateUpdate = (oldState, newState) => ({ newState, } }); + +/** + * @param {string} fullNodeNetworkName The name of the connected network. + */ +export const setFullNodeNetworkName = (fullNodeNetworkName) => ({ + type: types.SET_FULLNODE_NETWORK_NAME, + payload: fullNodeNetworkName, +}); diff --git a/src/components/NetworkSettings/NetworkStatusBar.js b/src/components/NetworkSettings/NetworkStatusBar.js index ac4481877..d036abae7 100644 --- a/src/components/NetworkSettings/NetworkStatusBar.js +++ b/src/components/NetworkSettings/NetworkStatusBar.js @@ -48,10 +48,15 @@ const style = { }; export const NetworkStatusBar = () => { - const getStatusText = (networkSettings) => `${customNetworkText}: ${networkSettings.network}`; - const networkSettings = useSelector((state) => state.networkSettings); + const { networkSettings, fullNodeNetworkName } = useSelector((state) => ({ + networkSettings: state.networkSettings, + fullNodeNetworkName: state.fullNodeNetworkName, + })); - return notMainnet(networkSettings) && ( - + const getStatusText = (name) => `${customNetworkText}: ${name}`; + + // Only show the bar if we have a network name and we're not on mainnet + return fullNodeNetworkName && notMainnet(networkSettings) && ( + ); }; diff --git a/src/reducers/reducer.js b/src/reducers/reducer.js index 3033f3d0f..b6d3e7885 100644 --- a/src/reducers/reducer.js +++ b/src/reducers/reducer.js @@ -518,6 +518,14 @@ const initialState = { address: null, error: null, }, + /** + * The full network name of the connected server (e.g. testnet-golf instead + * of only testnet). + * + * @type {null|string} null if uninitialized, string after it's set in + * the wallet saga. + */ + fullNodeNetworkName: null, }; export const reducer = (state = initialState, action) => { @@ -734,6 +742,8 @@ export const reducer = (state = initialState, action) => { return onNewNanoContractTransactionRetry(state); case types.REOWN_NEW_NANOCONTRACT_RETRY_DISMISS: return onNewNanoContractTransactionRetryDismiss(state); + case types.SET_FULLNODE_NETWORK_NAME: + return onSetFullNodeNetworkName(state, action); default: return state; } @@ -886,7 +896,6 @@ const onSetTokens = (state, { payload }) => { selectedToken, }; }; - /** * Set loadHistoryStatus */ @@ -2131,3 +2140,15 @@ export const onUnregisteredTokensDownloadEnd = (state) => ({ isLoading: false, }, }); + +/** + * Handle network name changes + * + * @param {Object} state + * @param {string} action.payload Name of the connected network. This should be + * the full network name (e.g. testnet-golf instead of just testnet). + */ +export const onSetFullNodeNetworkName = (state, { payload }) => ({ + ...state, + fullNodeNetworkName: payload, +}); diff --git a/src/sagas/networkSettings.js b/src/sagas/networkSettings.js index daa457cfb..b3158b46a 100644 --- a/src/sagas/networkSettings.js +++ b/src/sagas/networkSettings.js @@ -13,6 +13,7 @@ import { onExceptionCaptured, networkSettingsUpdateReady, networkChanged, + setFullNodeNetworkName, } from '../actions'; import { NETWORK_MAINNET, @@ -283,6 +284,9 @@ export function* persistNetworkSettings(action) { return; } + // Reset network name when changing networks + yield put(setFullNodeNetworkName('')); + // Dispatch network changed so listeners can use it in other sagas // e.g. the Reown saga uses this to clear sessions yield put(networkChanged()); diff --git a/src/sagas/wallet.js b/src/sagas/wallet.js index 9e51ae21b..cc3ef7ced 100644 --- a/src/sagas/wallet.js +++ b/src/sagas/wallet.js @@ -71,6 +71,7 @@ import { firstAddressFailure, firstAddressSuccess, firstAddressRequest, + setFullNodeNetworkName, } from '../actions'; import { fetchTokenData } from './tokens'; import { @@ -260,6 +261,17 @@ export function* startWallet(action) { }); yield put(setServerInfo(serverInfo)); + + let network = get(serverInfo, 'network'); + if (useWalletService) { + // In the wallet-service facade, serverInfo is null, so we need to get + // version data + const versionData = yield call([wallet, wallet.getVersionData]); + network = versionData.network; + } + + // Set the network name in redux + yield put(setFullNodeNetworkName(network)); } catch (e) { // WalletRequestError can either be a network error making the request // fail or the wallet might have failed to start and returned status: error.