diff --git a/android/app/src/main/res/drawable-hdpi/networks.png b/android/app/src/main/res/drawable-hdpi/networks.png
new file mode 100644
index 000000000..4d3695740
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/networks.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/networks.png b/android/app/src/main/res/drawable-mdpi/networks.png
new file mode 100644
index 000000000..92d56f598
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/networks.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/networks.png b/android/app/src/main/res/drawable-xhdpi/networks.png
new file mode 100644
index 000000000..3a025a0c1
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/networks.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/networks.png b/android/app/src/main/res/drawable-xxhdpi/networks.png
new file mode 100644
index 000000000..9c59992ed
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/networks.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/networks.png b/android/app/src/main/res/drawable-xxxhdpi/networks.png
new file mode 100644
index 000000000..1e9ee03b8
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/networks.png differ
diff --git a/index.js b/index.js
index 375cd54b3..0d4f54f5c 100644
--- a/index.js
+++ b/index.js
@@ -22,6 +22,7 @@ import {name as appName} from './app.json';
import {App} from './src/app';
import './src/event-actions';
import {Jailbreak} from './src/jailbreak';
+import {Provider} from '@app/models/provider';
if (!global.BigInt) {
const BigInt = require('big-integer');
@@ -100,8 +101,8 @@ JsonRpcProvider.prototype.send = async function (method, params) {
const eventParams = {
type: 'EVM',
- network: app.provider.name,
- chainId: `${app.provider.ethChainId}`,
+ network: Provider.selectedProvider.name,
+ chainId: `${Provider.selectedProvider.ethChainId}`,
address: parsedAddressFrom,
};
diff --git a/ios/haqq/Images.xcassets/networks.imageset/Contents.json b/ios/haqq/Images.xcassets/networks.imageset/Contents.json
new file mode 100644
index 000000000..9f0cb4d8e
--- /dev/null
+++ b/ios/haqq/Images.xcassets/networks.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images": [
+ {
+ "filename": "networks.svg",
+ "idiom": "universal"
+ }
+ ],
+ "info": {
+ "author": "xcode",
+ "version": 1
+ }
+}
diff --git a/ios/haqq/Images.xcassets/networks.imageset/networks.svg b/ios/haqq/Images.xcassets/networks.imageset/networks.svg
new file mode 100644
index 000000000..7c9ba6b06
--- /dev/null
+++ b/ios/haqq/Images.xcassets/networks.imageset/networks.svg
@@ -0,0 +1,11 @@
+
diff --git a/package.json b/package.json
index 44d6375f9..cf08ca03f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "haqq",
- "version": "1.9.1",
+ "version": "1.9.2",
"private": true,
"scripts": {
"android": "react-native run-android",
diff --git a/src/app.tsx b/src/app.tsx
index 876fa28c7..58494991b 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -125,7 +125,7 @@ export const App = () => {
sleep(150)
.then(async () => await app.awaitForInitialization())
.then(() => SplashScreen.hide())
- .then(() => awaitForEventDone(Events.onAppInitialized))
+ .then(async () => await awaitForEventDone(Events.onAppInitialized))
.then(async () => await Language.init())
.then(async () => {
await Stories.fetch(true);
diff --git a/src/components/account-detail.tsx b/src/components/account-detail.tsx
index 67de5d7f2..9a89f050c 100644
--- a/src/components/account-detail.tsx
+++ b/src/components/account-detail.tsx
@@ -21,9 +21,9 @@ import {
InfoBlock,
Text,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {sendNotification} from '@app/services';
import {GRADIENT_END, GRADIENT_START} from '@app/variables/common';
@@ -76,7 +76,7 @@ export const AccountDetail = observer(
title={I18N.evmTitle}
component={null}
/>
- {app.provider.config.isBech32Enabled && (
+ {Provider.selectedProvider.config.isBech32Enabled && (
}
/>
diff --git a/src/components/animated-balance.tsx b/src/components/animated-balance.tsx
index 0372637c8..b8776ffbd 100644
--- a/src/components/animated-balance.tsx
+++ b/src/components/animated-balance.tsx
@@ -5,8 +5,8 @@ import Timer from 'react-timer-mixin';
import {Color, getColor} from '@app/colors';
import {Text, TextVariant} from '@app/components/ui';
-import {app} from '@app/contexts';
import {cleanNumber, createTheme} from '@app/helpers';
+import {Provider} from '@app/models/provider';
type Props = {
value: number;
@@ -85,7 +85,7 @@ export class AnimateNumber extends Component {
color={Color.textBase3}
numberOfLines={1}
style={styles.currencySuffixText}>
- {` ${app.provider.denom}`}
+ {` ${Provider.selectedProvider.denom}`}
);
diff --git a/src/components/home-earn.tsx b/src/components/home-earn.tsx
index be733cdde..8203fa8b6 100644
--- a/src/components/home-earn.tsx
+++ b/src/components/home-earn.tsx
@@ -5,10 +5,10 @@ import {RefreshControl, ScrollView, TouchableOpacity, View} from 'react-native';
import {RiveRef} from 'rive-react-native';
import {Color} from '@app/colors';
-import {app} from '@app/contexts';
import {cleanNumber, createTheme} from '@app/helpers';
import {useThemeSelector} from '@app/hooks';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Raffle} from '@app/types';
import {SHADOW_L} from '@app/variables/shadows';
@@ -114,7 +114,7 @@ export const HomeEarn = observer(
variant={TextVariant.t14}
color={Color.textBase2}
i18n={I18N.earnStakingDescription}
- i18params={{symbol: app.provider.denom}}
+ i18params={{symbol: Provider.selectedProvider.denom}}
/>
@@ -129,7 +129,7 @@ export const HomeEarn = observer(
- {`${formattedRewardAmount} ${app.provider.denom}`}
+ {`${formattedRewardAmount} ${Provider.selectedProvider.denom}`}
{showStakingGetRewardsButtons && (
diff --git a/src/components/home-staking/staking-active.tsx b/src/components/home-staking/staking-active.tsx
index 6a3bc2c7d..725c8355f 100644
--- a/src/components/home-staking/staking-active.tsx
+++ b/src/components/home-staking/staking-active.tsx
@@ -20,10 +20,10 @@ import {
TextPosition,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {useTheme} from '@app/hooks';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {AppTheme} from '@app/types';
import {IS_IOS} from '@app/variables/common';
@@ -106,7 +106,7 @@ export const StakingActive = observer(
position={TextPosition.center}
color={Color.textBase2}
i18n={I18N.homeStakingEmpty}
- i18params={{symbol: app.provider.denom}}
+ i18params={{symbol: Provider.selectedProvider.denom}}
/>
{
position={TextPosition.center}
color={Color.textBase2}
i18n={I18N.homeStakingEmpty}
- i18params={{symbol: app.provider.denom}}
+ i18params={{symbol: Provider.selectedProvider.denom}}
/>
diff --git a/src/components/json-rpc-sign/json-rpc-common-transaction.tsx b/src/components/json-rpc-sign/json-rpc-common-transaction.tsx
index 758cf7d5e..517623612 100644
--- a/src/components/json-rpc-sign/json-rpc-common-transaction.tsx
+++ b/src/components/json-rpc-sign/json-rpc-common-transaction.tsx
@@ -20,7 +20,7 @@ import {shortAddress} from '@app/helpers/short-address';
import {I18N} from '@app/i18n';
import {Contracts} from '@app/models/contracts';
import {Fee} from '@app/models/fee';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {Token} from '@app/models/tokens';
import {Balance} from '@app/services/balance';
import {JsonRpcMetadata, JsonRpcTransactionRequest} from '@app/types';
@@ -34,7 +34,7 @@ export interface JsonRpcCommonTransactionProps {
showSignContratAttention: boolean;
functionName?: string;
isContract: boolean;
- provider: Provider | undefined;
+ provider: ProviderModel | undefined;
isFeeLoading: boolean;
fee: Fee | null | undefined;
tx: Partial | undefined;
diff --git a/src/components/json-rpc-sign/json-rpc-swap-transaction.tsx b/src/components/json-rpc-sign/json-rpc-swap-transaction.tsx
index f9f433a5f..25e5d3da4 100644
--- a/src/components/json-rpc-sign/json-rpc-swap-transaction.tsx
+++ b/src/components/json-rpc-sign/json-rpc-swap-transaction.tsx
@@ -29,7 +29,7 @@ import {I18N} from '@app/i18n';
import {Contracts} from '@app/models/contracts';
import {Currencies} from '@app/models/currencies';
import {Fee} from '@app/models/fee';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {Token} from '@app/models/tokens';
import {Wallet} from '@app/models/wallet';
import {Balance} from '@app/services/balance';
@@ -50,7 +50,7 @@ import {
export interface JsonRpcSwapTransactionProps {
metadata: JsonRpcMetadata;
- provider: Provider | undefined;
+ provider: ProviderModel | undefined;
isFeeLoading: boolean;
functionName: string;
fee: Fee | null | undefined;
diff --git a/src/components/json-rpc-sign/json-rpc-transaction-info.tsx b/src/components/json-rpc-sign/json-rpc-transaction-info.tsx
index 1f63295e1..779dfe944 100644
--- a/src/components/json-rpc-sign/json-rpc-transaction-info.tsx
+++ b/src/components/json-rpc-sign/json-rpc-transaction-info.tsx
@@ -1,6 +1,7 @@
import React, {useCallback, useMemo, useState} from 'react';
-import {app} from '@app/contexts';
+import {observer} from 'mobx-react';
+
import {awaitForFee} from '@app/helpers/await-for-fee';
import {useTypedNavigation} from '@app/hooks';
import {useEffectAsync} from '@app/hooks/use-effect-async';
@@ -38,164 +39,168 @@ interface JsonRpcTransactionInfoProps {
setFeeLoading: React.Dispatch>;
}
-export const JsonRpcTransactionInfo = ({
- request,
- metadata,
- verifyAddressResponse,
- chainId,
- hideContractAttention,
- fee,
- setFee,
- isFeeLoading,
- setFeeLoading,
-}: JsonRpcTransactionInfoProps) => {
- const navigation = useTypedNavigation();
-
- const [isSwapRenderError, setIsSwapRenderError] = useState(false);
-
- const tx = useMemo(
- () => getTransactionFromJsonRpcRequest(request),
- [request],
- );
-
- const provider = useMemo(() => {
- return Provider.getByEthChainId(
- tx?.chainId ?? chainId ?? app.provider.ethChainId,
+export const JsonRpcTransactionInfo = observer(
+ ({
+ request,
+ metadata,
+ verifyAddressResponse,
+ chainId,
+ hideContractAttention,
+ fee,
+ setFee,
+ isFeeLoading,
+ setFeeLoading,
+ }: JsonRpcTransactionInfoProps) => {
+ const navigation = useTypedNavigation();
+
+ const [isSwapRenderError, setIsSwapRenderError] = useState(false);
+
+ const tx = useMemo(
+ () => getTransactionFromJsonRpcRequest(request),
+ [request],
+ );
+
+ const provider = useMemo(() => {
+ return Provider.getByEthChainId(
+ tx?.chainId ?? chainId ?? Provider.selectedProvider.ethChainId,
+ );
+ }, [chainId, tx]);
+
+ const isContract = useMemo(
+ () =>
+ verifyAddressResponse?.address_type === AddressType.contract ||
+ isContractTransaction(tx),
+ [tx, verifyAddressResponse],
+ );
+
+ const isInWhiteList = useMemo(
+ () => !!verifyAddressResponse?.is_in_white_list,
+ [verifyAddressResponse],
+ );
+
+ const showSignContratAttention =
+ !hideContractAttention && isContract && !isInWhiteList;
+
+ const txParsedData = useMemo(() => parseTxDataFromHexInput(tx?.data), [tx]);
+
+ const functionName = useMemo(() => {
+ if (txParsedData) {
+ return txParsedData.name;
+ }
+ return '';
+ }, [txParsedData]);
+
+ const isSwapTx = useMemo(
+ () => ['exactInput', 'deposit', 'withdraw'].includes(functionName),
+ [functionName],
);
- }, [chainId, tx]);
-
- const isContract = useMemo(
- () =>
- verifyAddressResponse?.address_type === AddressType.contract ||
- isContractTransaction(tx),
- [tx, verifyAddressResponse],
- );
-
- const isInWhiteList = useMemo(
- () => !!verifyAddressResponse?.is_in_white_list,
- [verifyAddressResponse],
- );
-
- const showSignContratAttention =
- !hideContractAttention && isContract && !isInWhiteList;
-
- const txParsedData = useMemo(() => parseTxDataFromHexInput(tx?.data), [tx]);
-
- const functionName = useMemo(() => {
- if (txParsedData) {
- return txParsedData.name;
- }
- return '';
- }, [txParsedData]);
-
- const isSwapTx = useMemo(
- () => ['exactInput', 'deposit', 'withdraw'].includes(functionName),
- [functionName],
- );
-
- const calculateFee = useCallback(async () => {
- if (!tx) {
- return Balance.Empty;
- }
-
- try {
- const data = await EthNetwork.estimate(
- {
+
+ const calculateFee = useCallback(async () => {
+ if (!tx) {
+ return Balance.Empty;
+ }
+
+ try {
+ const data = await EthNetwork.estimate(
+ {
+ from: tx.from!,
+ to: tx.to!,
+ value: new Balance(
+ tx.value || Balance.Empty,
+ provider?.decimals,
+ provider?.denom,
+ ),
+ data: tx.data,
+ },
+ EstimationVariant.average,
+ provider,
+ );
+ setFee(new Fee(data));
+ return data.expectedFee;
+ } catch {
+ return Balance.Empty;
+ }
+ }, [tx, provider]);
+
+ const onFeePress = useCallback(async () => {
+ if (!tx) {
+ return;
+ }
+
+ if (fee) {
+ const result = await awaitForFee({
+ fee,
from: tx.from!,
to: tx.to!,
value: new Balance(
- tx.value || Balance.Empty,
+ tx.value! || Balance.Empty,
provider?.decimals,
provider?.denom,
),
data: tx.data,
- },
- EstimationVariant.average,
- provider,
- );
- setFee(new Fee(data));
- return data.expectedFee;
- } catch {
- return Balance.Empty;
- }
- }, [tx, provider]);
-
- const onFeePress = useCallback(async () => {
- if (!tx) {
- return;
- }
-
- if (fee) {
- const result = await awaitForFee({
- fee,
- from: tx.from!,
- to: tx.to!,
- value: new Balance(
- tx.value! || Balance.Empty,
- provider?.decimals,
- provider?.denom,
- ),
- data: tx.data,
- chainId: provider?.ethChainId ? String(provider.ethChainId) : undefined,
- });
- setFee(result);
- }
- }, [navigation, tx, fee, provider]);
-
- const onSwapRenderError = useCallback(() => {
- setIsSwapRenderError(true);
- }, []);
-
- useEffectAsync(async () => {
- if (!fee?.calculatedFees) {
- try {
- if (tx) {
- setFeeLoading(true);
- await calculateFee();
- }
- } catch (err) {
- Logger.captureException(err, 'JsonRpcTransactionInfo:calculateFee', {
- params: tx,
- chainId,
+ chainId: provider?.ethChainId
+ ? String(provider.ethChainId)
+ : undefined,
});
- } finally {
+ setFee(result);
+ }
+ }, [navigation, tx, fee, provider]);
+
+ const onSwapRenderError = useCallback(() => {
+ setIsSwapRenderError(true);
+ }, []);
+
+ useEffectAsync(async () => {
+ if (!fee?.calculatedFees) {
+ try {
+ if (tx) {
+ setFeeLoading(true);
+ await calculateFee();
+ }
+ } catch (err) {
+ Logger.captureException(err, 'JsonRpcTransactionInfo:calculateFee', {
+ params: tx,
+ chainId,
+ });
+ } finally {
+ setFeeLoading(false);
+ }
+ } else {
setFeeLoading(false);
}
- } else {
- setFeeLoading(false);
- }
- }, [chainId]);
-
- return (
-
- {!isSwapRenderError && isSwapTx && isContract && (
-
+ {!isSwapRenderError && isSwapTx && isContract && (
+
+ )}
+
+
- )}
-
-
-
- );
-};
+
+ );
+ },
+);
diff --git a/src/components/locked-tokens.tsx b/src/components/locked-tokens.tsx
index 46ef3875a..a885cbb89 100644
--- a/src/components/locked-tokens.tsx
+++ b/src/components/locked-tokens.tsx
@@ -4,10 +4,10 @@ import {observer} from 'mobx-react';
import {View} from 'react-native';
import {Color} from '@app/colors';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {useIsBalancesFirstSync} from '@app/hooks/use-is-balances-sync';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {BalanceData} from '@app/types';
import {
@@ -34,8 +34,8 @@ export const LockedTokens = observer(
const {isBalanceLoadingError, isBalancesFirstSync} =
useIsBalancesFirstSync();
const defaultTotalValueISLM = useMemo(
- () => `0 ${app.provider.denom}`,
- [app.provider.denom],
+ () => `0 ${Provider.selectedProvider.denom}`,
+ [Provider.selectedProvider.denom],
);
const defaultTotalValueUSD = useMemo(() => '$0', []);
diff --git a/src/components/modals/details-qr.tsx b/src/components/modals/details-qr.tsx
index 732a6a66b..e52cb4108 100644
--- a/src/components/modals/details-qr.tsx
+++ b/src/components/modals/details-qr.tsx
@@ -17,9 +17,9 @@ import {
InfoBlock,
Text,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {sendNotification} from '@app/services';
import {ModalType, Modals} from '@app/types';
@@ -52,8 +52,8 @@ export const DetailsQrModal = observer(
style={page.info}
i18n={I18N.modalDetailsQRWarning}
i18params={{
- assetName: app.provider.denom,
- networkName: app.provider.name,
+ assetName: Provider.selectedProvider.denom,
+ networkName: Provider.selectedProvider.name,
}}
icon={}
/>
diff --git a/src/components/modals/providers-bottom-sheet.tsx b/src/components/modals/providers-bottom-sheet.tsx
index bd4608a48..c1124cb86 100644
--- a/src/components/modals/providers-bottom-sheet.tsx
+++ b/src/components/modals/providers-bottom-sheet.tsx
@@ -9,8 +9,10 @@ import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {useCalculatedDimensionsValue} from '@app/hooks/use-calculated-dimensions-value';
import {I18N} from '@app/i18n';
+import {ALL_NETWORKS_ID} from '@app/models/provider';
import {ModalType, Modals} from '@app/types';
+import {SettingsProvidersAllNetworksRow} from '../settings/settings-providers/settings-providers-all-networks-row';
import {SettingsProvidersRow} from '../settings/settings-providers/settings-providers-row';
export function ProvidersBottomSheet({
@@ -87,17 +89,30 @@ export function ProvidersBottomSheet({
leading={
}
+ style={styles.searchField}
/>
item.id}
- renderItem={({item}) => (
-
- )}
+ renderItem={({item}) => {
+ if (item.id === ALL_NETWORKS_ID) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+ }}
/>
@@ -108,4 +123,5 @@ const styles = createTheme({
container: {
height: '50%',
},
+ searchField: {marginBottom: 16},
});
diff --git a/src/components/proposal-deposit-finish/proposal-deposit-finish.tsx b/src/components/proposal-deposit-finish/proposal-deposit-finish.tsx
index 4f2eaf552..f47a18b9d 100644
--- a/src/components/proposal-deposit-finish/proposal-deposit-finish.tsx
+++ b/src/components/proposal-deposit-finish/proposal-deposit-finish.tsx
@@ -19,10 +19,10 @@ import {
TextVariant,
} from '@app/components/ui';
import {NetworkFee} from '@app/components/ui/network-fee';
-import {app} from '@app/contexts';
import {createTheme, openURL} from '@app/helpers';
import {cleanNumber} from '@app/helpers/clean-number';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
export type ProposalDepositFinishProps = {
@@ -65,7 +65,7 @@ export const ProposalDepositFinish = observer(
variant={TextVariant.t3}
position={TextPosition.center}
style={styles.sum}>
- {`${cleanNumber(amount)} ${app.provider.denom}`}
+ {`${cleanNumber(amount)} ${Provider.selectedProvider.denom}`}
{
const transactionFee = useMemo(() => {
- const maximumFee = fee.compare(FEE_AMOUNT, 'gt') ? fee : FEE_AMOUNT;
+ const maximumFee = fee.compare(new Balance(FEE_AMOUNT), 'gt')
+ ? fee
+ : new Balance(FEE_AMOUNT);
return new Balance(maximumFee);
}, [fee]);
const amounts = useSumAmount(
diff --git a/src/components/proposal-deposit-preview/proposal-deposit-preview.tsx b/src/components/proposal-deposit-preview/proposal-deposit-preview.tsx
index da527fd72..1d627f0eb 100644
--- a/src/components/proposal-deposit-preview/proposal-deposit-preview.tsx
+++ b/src/components/proposal-deposit-preview/proposal-deposit-preview.tsx
@@ -15,10 +15,10 @@ import {
TextPosition,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {cleanNumber} from '@app/helpers/clean-number';
import {I18N, getText} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
export type ProposalDepositPreviewProps = {
@@ -56,7 +56,7 @@ export const ProposalDepositPreview = observer(
variant={TextVariant.t3}
position={TextPosition.center}
style={styles.sum}>
- {`${cleanNumber(amount)} ${app.provider.denom}`}
+ {`${cleanNumber(amount)} ${Provider.selectedProvider.denom}`}
diff --git a/src/components/raffle-details.tsx b/src/components/raffle-details.tsx
index 90c2efc37..a49ff6ccd 100644
--- a/src/components/raffle-details.tsx
+++ b/src/components/raffle-details.tsx
@@ -4,10 +4,10 @@ import {observer} from 'mobx-react';
import {Image, View} from 'react-native';
import {Color} from '@app/colors';
-import {app} from '@app/contexts';
import {cleanNumber, createTheme} from '@app/helpers';
import {useTimer} from '@app/hooks/use-timer';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Raffle, TimerUpdateInterval} from '@app/types';
import {WEI} from '@app/variables/common';
@@ -96,7 +96,7 @@ export const RaffleDetails = observer(
source={require('@assets/images/islm_icon.png')}
/>
- {`${formattedBudget} ${app.provider.denom}`}
+ {`${formattedBudget} ${Provider.selectedProvider.denom}`}
@@ -145,7 +145,7 @@ export const RaffleDetails = observer(
i18params={{
islm: cleanNumber(prevIslmCount),
tickets: `${prevTicketsCount} `,
- symbol: app.provider.denom,
+ symbol: Provider.selectedProvider.denom,
}}
/>
diff --git a/src/components/raffle-reward.tsx b/src/components/raffle-reward.tsx
index 6e3801bf4..017ce6510 100644
--- a/src/components/raffle-reward.tsx
+++ b/src/components/raffle-reward.tsx
@@ -4,10 +4,10 @@ import {observer} from 'mobx-react';
import {Image, SafeAreaView, StyleSheet, View} from 'react-native';
import {Color} from '@app/colors';
-import {app} from '@app/contexts';
import {cleanNumber} from '@app/helpers';
import {useThemeSelector} from '@app/hooks';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Raffle} from '@app/types';
import {WEI} from '@app/variables/common';
@@ -79,7 +79,7 @@ export const RaffleReward = observer(
color={Color.textGreen1}
numberOfLines={1}
i18n={I18N.raffleRewardPrize}
- i18params={{islm: budget, symbol: app.provider.denom}}
+ i18params={{islm: budget, symbol: Provider.selectedProvider.denom}}
/>
diff --git a/src/components/settings/settings-account-detail/settings-account-detail.tsx b/src/components/settings/settings-account-detail/settings-account-detail.tsx
index 0d961db8e..dac3a0e79 100644
--- a/src/components/settings/settings-account-detail/settings-account-detail.tsx
+++ b/src/components/settings/settings-account-detail/settings-account-detail.tsx
@@ -21,12 +21,12 @@ import {
Text,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {AddressUtils} from '@app/helpers/address-utils';
import {Feature, isFeatureEnabled} from '@app/helpers/is-feature-enabled';
import {useCalculatedDimensionsValue} from '@app/hooks/use-calculated-dimensions-value';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {sendNotification} from '@app/services';
import {WalletType} from '@app/types';
@@ -122,7 +122,7 @@ export const SettingsAccountDetail = observer(
- {app.provider.config.isBech32Enabled && (
+ {Provider.selectedProvider.config.isBech32Enabled && (
,
+ Partial,
'ethChainId' | 'id'
> & {
isChanged: boolean;
@@ -45,9 +45,9 @@ export type SettingsProviderEditData = Omit<
};
export type SettingsProviderEditProps = {
- provider: Partial | null;
+ provider: Partial | null;
buttonType?: 'save' | 'del';
- onSubmit: (provider: Partial) => void;
+ onSubmit: (provider: Partial) => void;
onDelete: () => void;
onCancel: () => void;
onSelect: () => void;
diff --git a/src/components/settings/settings-providers/settings-providers-all-networks-row.tsx b/src/components/settings/settings-providers/settings-providers-all-networks-row.tsx
new file mode 100644
index 000000000..5903f0816
--- /dev/null
+++ b/src/components/settings/settings-providers/settings-providers-all-networks-row.tsx
@@ -0,0 +1,59 @@
+import React from 'react';
+
+import {TouchableWithoutFeedback, View} from 'react-native';
+
+import {Color} from '@app/colors';
+import {DataContent, Icon, IconsName, Spacer} from '@app/components/ui';
+import {createTheme} from '@app/helpers';
+import {ALL_NETWORKS_ID, ProviderModel} from '@app/models/provider';
+
+export type SettingsProvidersAllNetworksRowProps = {
+ item: ProviderModel;
+ providerId: string;
+ onPress: (providerId: string) => void;
+};
+export const SettingsProvidersAllNetworksRow = ({
+ item,
+ onPress,
+ providerId,
+}: SettingsProvidersAllNetworksRowProps) => {
+ return (
+ {
+ onPress(item.id);
+ }}>
+
+
+
+
+
+
+
+ {providerId === ALL_NETWORKS_ID && (
+
+ )}
+
+
+ );
+};
+
+const styles = createTheme({
+ container: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ info: {justifyContent: 'space-between'},
+ iconWrapper: {
+ width: 42,
+ height: 42,
+ backgroundColor: Color.bg3,
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 12,
+ },
+ icon: {width: 28, height: 28},
+});
diff --git a/src/components/settings/settings-providers/settings-providers-row.tsx b/src/components/settings/settings-providers/settings-providers-row.tsx
index c3451b2e6..a20c65fbd 100644
--- a/src/components/settings/settings-providers/settings-providers-row.tsx
+++ b/src/components/settings/settings-providers/settings-providers-row.tsx
@@ -5,10 +5,10 @@ import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native';
import {Color} from '@app/colors';
import {ImageWrapper} from '@app/components/image-wrapper';
import {DataContent, Icon, Spacer} from '@app/components/ui';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
export type SettingsProvidersRowProps = {
- item: Provider;
+ item: ProviderModel;
providerId: string;
onPress: (providerId: string) => void;
};
diff --git a/src/components/settings/settings-providers/settings-providers.tsx b/src/components/settings/settings-providers/settings-providers.tsx
index c9ecb87e5..54c105eaa 100644
--- a/src/components/settings/settings-providers/settings-providers.tsx
+++ b/src/components/settings/settings-providers/settings-providers.tsx
@@ -2,12 +2,12 @@ import React from 'react';
import {FlatList, StyleSheet} from 'react-native';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {SettingsProvidersRow} from './settings-providers-row';
export type SettingsProvidersProps = {
- providers: Provider[];
+ providers: ProviderModel[];
providerId: string;
onSelect: (providerId: string) => void;
};
diff --git a/src/components/staking-delegate-finish/staking-delegate-finish.tsx b/src/components/staking-delegate-finish/staking-delegate-finish.tsx
index 024134786..f982f3435 100644
--- a/src/components/staking-delegate-finish/staking-delegate-finish.tsx
+++ b/src/components/staking-delegate-finish/staking-delegate-finish.tsx
@@ -15,10 +15,10 @@ import {
TextVariant,
} from '@app/components/ui';
import {NetworkFee} from '@app/components/ui/network-fee';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {cleanNumber} from '@app/helpers/clean-number';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {ValidatorItem} from '@app/types';
@@ -66,7 +66,7 @@ export const StakingDelegateFinish = observer(
variant={TextVariant.t3}
position={TextPosition.center}
style={styles.sum}>
- - {`${cleanNumber(amount)} ${app.provider.denom}`}
+ - {`${cleanNumber(amount)} ${Provider.selectedProvider.denom}`}
{
const transactionFee = useMemo(
- () => (fee ? fee.max(FEE_AMOUNT) : Balance.Empty),
+ () => (fee ? fee.max(new Balance(FEE_AMOUNT)) : Balance.Empty),
[fee],
);
diff --git a/src/components/staking-delegate-preview/staking-delegate-preview.tsx b/src/components/staking-delegate-preview/staking-delegate-preview.tsx
index d84405091..5907e2691 100644
--- a/src/components/staking-delegate-preview/staking-delegate-preview.tsx
+++ b/src/components/staking-delegate-preview/staking-delegate-preview.tsx
@@ -17,11 +17,11 @@ import {
TextPosition,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {cleanNumber} from '@app/helpers/clean-number';
import {formatPercents} from '@app/helpers/format-percents';
import {I18N, getText} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {ValidatorItem, ValidatorStatus} from '@app/types';
@@ -74,7 +74,7 @@ export const StakingDelegatePreview = observer(
i18n={I18N.amount}
i18params={{
amount: cleanNumber(amount),
- symbol: app.provider.denom,
+ symbol: Provider.selectedProvider.denom,
}}
/>
- - {`${cleanNumber(amount)} ${app.provider.denom}`}
+ - {`${cleanNumber(amount)} ${Provider.selectedProvider.denom}`}
diff --git a/src/components/swap/swap.tsx b/src/components/swap/swap.tsx
index 0ea20594a..e67059394 100644
--- a/src/components/swap/swap.tsx
+++ b/src/components/swap/swap.tsx
@@ -4,12 +4,12 @@ import {observer} from 'mobx-react';
import {View} from 'react-native';
import {Color} from '@app/colors';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {shortAddress} from '@app/helpers/short-address';
import {useSumAmount} from '@app/hooks';
import {I18N} from '@app/i18n';
import {Contracts} from '@app/models/contracts';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {Balance} from '@app/services/balance';
import {
@@ -268,9 +268,10 @@ export const Swap = observer(
{(isWrapTx || isUnwrapTx) && (
item.is_in_white_list &&
// FIXME: only erc20 tokens or native currency (ISLM)
- (item.is_erc20 || item.symbol === app.provider.denom),
+ (item.is_erc20 ||
+ item.symbol === Provider.selectedProvider.denom),
)}
tokensOnly={!!wallet}
isLast={index === list.length - 1}
diff --git a/src/components/transaction-confirmation/transaction-confirmation.tsx b/src/components/transaction-confirmation/transaction-confirmation.tsx
index 419b1bf60..bf3953a4d 100644
--- a/src/components/transaction-confirmation/transaction-confirmation.tsx
+++ b/src/components/transaction-confirmation/transaction-confirmation.tsx
@@ -16,11 +16,11 @@ import {
TextPosition,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {I18N, getText} from '@app/i18n';
import {Contact} from '@app/models/contact';
import {Fee} from '@app/models/fee';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {BalanceData, IToken} from '@app/types';
import {splitAddress} from '@app/utils';
@@ -77,7 +77,7 @@ export const TransactionConfirmation = observer(
// When sanding native token than calculation includes
// amount + fee - availablebalance
- if (amount.getSymbol() === app.provider.denom) {
+ if (amount.getSymbol() === Provider.selectedProvider.denom) {
return (
fee.calculatedFees.expectedFee
.operate(amount, 'add')
@@ -179,7 +179,7 @@ export const TransactionConfirmation = observer(
- {app.provider.name}
+ {Provider.selectedProvider.name}
@@ -217,7 +217,7 @@ export const TransactionConfirmation = observer(
position={TextPosition.center}
color={Color.graphicRed1}
i18n={I18N.transactionSumError}
- i18params={{symbol: app.provider.weiDenom}}
+ i18params={{symbol: Provider.selectedProvider.weiDenom}}
/>
)}
diff --git a/src/components/transaction-detail.tsx b/src/components/transaction-detail.tsx
index 4ede79f1b..87c11a7dd 100644
--- a/src/components/transaction-detail.tsx
+++ b/src/components/transaction-detail.tsx
@@ -11,7 +11,7 @@ import {AddressUtils} from '@app/helpers/address-utils';
import {useCalculatedDimensionsValue} from '@app/hooks/use-calculated-dimensions-value';
import {I18N, getText} from '@app/i18n';
import {Contracts} from '@app/models/contracts';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {Transaction} from '@app/models/transaction';
import {Balance} from '@app/services/balance';
import {IndexerTxMsgType} from '@app/types';
@@ -21,7 +21,7 @@ import {ImageWrapper} from './image-wrapper';
type TransactionDetailProps = {
tx: Transaction;
- provider: Provider | null;
+ provider: ProviderModel | null;
splitted: string[];
timestamp: string;
fee: Balance;
diff --git a/src/components/transaction-finish.tsx b/src/components/transaction-finish.tsx
index 800bf4927..9810c7db2 100644
--- a/src/components/transaction-finish.tsx
+++ b/src/components/transaction-finish.tsx
@@ -19,11 +19,11 @@ import {
TextPosition,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme, openURL} from '@app/helpers';
import {I18N} from '@app/i18n';
import {Contact} from '@app/models/contact';
import {Fee} from '@app/models/fee';
+import {Provider} from '@app/models/provider';
import {sendNotification} from '@app/services';
import {Balance} from '@app/services/balance';
import {IToken, TransactionResponse} from '@app/types';
@@ -56,7 +56,9 @@ export const TransactionFinish = observer(
}: TransactionFinishProps) => {
const name = token?.name || contact?.name;
const onPressHash = async () => {
- const url = app.provider.getTxExplorerUrl(transaction?.hash!);
+ const url = Provider.selectedProvider.getTxExplorerUrl(
+ transaction?.hash!,
+ );
await openURL(url);
};
@@ -74,15 +76,15 @@ export const TransactionFinish = observer(
return new Balance(
(transaction as TransactionResponse)?.value._hex ?? 0,
undefined,
- token.symbol ?? app.provider.denom,
+ token.symbol ?? Provider.selectedProvider.denom,
);
}
return new Balance(
transaction?.value ?? 0,
undefined,
- token.symbol ?? app.provider.denom,
+ token.symbol ?? Provider.selectedProvider.denom,
);
- }, [transaction, token, amount, app.provider.denom]);
+ }, [transaction, token, amount, Provider.selectedProvider.denom]);
return (
@@ -118,7 +120,7 @@ export const TransactionFinish = observer(
position={TextPosition.center}
style={styles.address}>
{name}
- {STRINGS.NBSP}({token.symbol || app.provider.denom})
+ {STRINGS.NBSP}({token.symbol || Provider.selectedProvider.denom})
)}
- {app.provider.name}
+ {Provider.selectedProvider.name}
- {`${STRINGS.NBSP}(${app.provider.denom})`}
+ {`${STRINGS.NBSP}(${Provider.selectedProvider.denom})`}
diff --git a/src/components/transaction-nft-finish.tsx b/src/components/transaction-nft-finish.tsx
index a44f52257..59703a4d4 100644
--- a/src/components/transaction-nft-finish.tsx
+++ b/src/components/transaction-nft-finish.tsx
@@ -1,6 +1,7 @@
import React, {useCallback} from 'react';
import Clipboard from '@react-native-clipboard/clipboard';
+import {observer} from 'mobx-react';
import {View} from 'react-native';
import {Color} from '@app/colors';
@@ -17,13 +18,13 @@ import {
TextPosition,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme, openURL} from '@app/helpers';
import {useNftImage} from '@app/hooks/nft';
import {I18N} from '@app/i18n';
import {Contact} from '@app/models/contact';
import {Fee} from '@app/models/fee';
import {NftItem} from '@app/models/nft';
+import {Provider} from '@app/models/provider';
import {sendNotification} from '@app/services';
import {TransactionResponse} from '@app/types';
import {STRINGS} from '@app/variables/common';
@@ -40,139 +41,143 @@ type TransactionFinishProps = {
fee: Fee;
};
-export const TransactionNftFinish = ({
- transaction,
- item,
- onSubmit,
- onPressContact,
- contact,
- fee,
-}: TransactionFinishProps) => {
- const onPressHash = async () => {
- const url = app.provider.getTxExplorerUrl(transaction?.hash!);
- await openURL(url);
- };
+export const TransactionNftFinish = observer(
+ ({
+ transaction,
+ item,
+ onSubmit,
+ onPressContact,
+ contact,
+ fee,
+ }: TransactionFinishProps) => {
+ const onPressHash = async () => {
+ const url = Provider.selectedProvider.getTxExplorerUrl(
+ transaction?.hash!,
+ );
+ await openURL(url);
+ };
- const onPressToAddress = useCallback(() => {
- Clipboard.setString(transaction?.to ?? '');
- sendNotification(I18N.notificationCopied);
- }, [transaction]);
+ const onPressToAddress = useCallback(() => {
+ Clipboard.setString(transaction?.to ?? '');
+ sendNotification(I18N.notificationCopied);
+ }, [transaction]);
- const nftImageUri = useNftImage(
- typeof item.cached_url === 'string'
- ? item.cached_url
- : item.metadata?.image,
- );
+ const nftImageUri = useNftImage(
+ typeof item.cached_url === 'string'
+ ? item.cached_url
+ : item.metadata?.image,
+ );
- return (
-
-
-
+
+
+
+
+
-
-
-
-
- {item.name}
-
-
-
- {contact?.name && (
+
+ {item.name}
+
+
+
+ {contact?.name && (
+
+ {contact.name}
+
+ )}
- {contact.name}
+ {transaction?.to}
- )}
-
- {transaction?.to}
-
-
+
-
+
-
-
- {app.provider.name}
-
-
- {`${STRINGS.NBSP}(${app.provider.denom})`}
-
-
+
+
+ {Provider.selectedProvider.name}
+
+
+ {`${STRINGS.NBSP}(${Provider.selectedProvider.denom})`}
+
+
-
-
-
- {contact ? (
-
+
+
+ {contact ? (
+
+ ) : (
+
+ )}
+
- ) : (
+
+
- )}
-
-
-
-
-
-
-
-
-
- );
-};
+
+
+
+
+
+ );
+ },
+);
const styles = createTheme({
container: {
diff --git a/src/components/transaction-sum/transaction-sum.tsx b/src/components/transaction-sum/transaction-sum.tsx
index 51f428cfa..4442f0792 100644
--- a/src/components/transaction-sum/transaction-sum.tsx
+++ b/src/components/transaction-sum/transaction-sum.tsx
@@ -15,13 +15,13 @@ import {
Text,
TextVariant,
} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {shortAddress} from '@app/helpers/short-address';
import {useSumAmount} from '@app/hooks';
import {useKeyboard} from '@app/hooks/use-keyboard';
import {I18N} from '@app/i18n';
import {Contact} from '@app/models/contact';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {HapticEffects, vibrate} from '@app/services/haptic';
import {IToken} from '@app/types';
@@ -63,13 +63,15 @@ export const TransactionSum = observer(
const {keyboardShown} = useKeyboard();
const transactionFee = useMemo(() => {
return fee !== null
- ? fee.operate(BALANCE_MULTIPLIER, 'mul').max(FEE_AMOUNT)
+ ? fee
+ .operate(new Balance(BALANCE_MULTIPLIER, 0), 'mul')
+ .max(new Balance(FEE_AMOUNT))
: Balance.Empty;
}, [fee]);
const minAmount = useMemo(() => {
// for network native coin
- if (token.symbol === app.provider.denom) {
+ if (token.symbol === Provider.selectedProvider.denom) {
return new Balance(0.0000001, 0);
}
@@ -79,17 +81,17 @@ export const TransactionSum = observer(
token.decimals!,
token.symbol!,
);
- }, [token, app.provider.denom]);
+ }, [token, Provider.selectedProvider.denom]);
const maxAmount = useMemo(() => {
// for network native coin
- if (token.symbol === app.provider.denom) {
+ if (token.symbol === Provider.selectedProvider.denom) {
return balance.operate(transactionFee, 'sub');
}
// for others tokens
return new Balance(token.value.raw, token.decimals!, token.symbol!);
- }, [token, balance, transactionFee, app.provider.denom]);
+ }, [token, balance, transactionFee, Provider.selectedProvider.denom]);
const amounts = useSumAmount(START_AMOUNT, maxAmount, minAmount);
@@ -167,7 +169,7 @@ export const TransactionSum = observer(
color={Color.textBase1}
numberOfLines={1}
ellipsizeMode="tail">
- {app.provider.name}
+ {Provider.selectedProvider.name}
diff --git a/src/components/typed-data-viewer.tsx b/src/components/typed-data-viewer.tsx
index 36fdf6975..af5463225 100644
--- a/src/components/typed-data-viewer.tsx
+++ b/src/components/typed-data-viewer.tsx
@@ -1,14 +1,15 @@
import React, {useCallback, useMemo, useState} from 'react';
+import {observer} from 'mobx-react';
import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
import {ScrollView} from 'react-native-gesture-handler';
import {Renderable} from 'react-native-json-tree';
import {Color} from '@app/colors';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {useLayoutAnimation} from '@app/hooks/use-layout-animation';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {EIPMessage, EIPTypedData} from '@app/types';
@@ -28,125 +29,127 @@ export type TypedDataViewerProps = {
style?: StyleProp;
};
-export function TypedDataViewer({data, style}: TypedDataViewerProps) {
- const {animate} = useLayoutAnimation();
- const [isJsonHidden, setJsonHidden] = useState(true);
- const message = data?.message as EIPMessage;
- const amount = useMemo(() => {
- return message?.msgs.reduce((prev: Balance, {value}) => {
- if (value?.amount?.amount) {
- return prev.operate(new Balance(value?.amount?.amount), 'add');
- }
- return prev;
- }, Balance.Empty);
- }, [data]);
+export const TypedDataViewer = observer(
+ ({data, style}: TypedDataViewerProps) => {
+ const {animate} = useLayoutAnimation();
+ const [isJsonHidden, setJsonHidden] = useState(true);
+ const message = data?.message as EIPMessage;
+ const amount = useMemo(() => {
+ return message?.msgs.reduce((prev: Balance, {value}) => {
+ if (value?.amount?.amount) {
+ return prev.operate(new Balance(value?.amount?.amount), 'add');
+ }
+ return prev;
+ }, Balance.Empty);
+ }, [data]);
- const fee = useMemo(() => {
- return message?.fee?.amount?.reduce((prev: Balance, c) => {
- if (c.amount) {
- return prev.operate(new Balance(c.amount), 'add');
- }
- return prev;
- }, Balance.Empty);
- }, [data]);
+ const fee = useMemo(() => {
+ return message?.fee?.amount?.reduce((prev: Balance, c) => {
+ if (c.amount) {
+ return prev.operate(new Balance(c.amount), 'add');
+ }
+ return prev;
+ }, Balance.Empty);
+ }, [data]);
- const type = useMemo(() => {
- const firsMsg = message?.msgs?.[0];
- if (typeof firsMsg?.type === 'string') {
- const paths = firsMsg.type.split('/');
- const name = paths[paths.length - 1]?.replace(
- /Msg(Begin)?(Withdraw)?/,
- '',
- );
- return name;
- }
- return 'Unknown';
- }, [data]);
+ const type = useMemo(() => {
+ const firsMsg = message?.msgs?.[0];
+ if (typeof firsMsg?.type === 'string') {
+ const paths = firsMsg.type.split('/');
+ const name = paths[paths.length - 1]?.replace(
+ /Msg(Begin)?(Withdraw)?/,
+ '',
+ );
+ return name;
+ }
+ return 'Unknown';
+ }, [data]);
- const handleShowJsonViewer = useCallback(() => {
- animate();
- setJsonHidden(false);
- }, [animate]);
+ const handleShowJsonViewer = useCallback(() => {
+ animate();
+ setJsonHidden(false);
+ }, [animate]);
- const handleHideJsonViewer = useCallback(() => {
- animate();
- setJsonHidden(true);
- }, [animate]);
+ const handleHideJsonViewer = useCallback(() => {
+ animate();
+ setJsonHidden(true);
+ }, [animate]);
- return (
-
-
-
-
-
- {type}
-
-
-
-
- {`${app.provider.coinName} ${app.provider.denom}`}
-
-
- {amount?.isPositive() && (
-
+ return (
+
+
+
+
- {amount?.toBalanceString('auto')}
+ {type}
- )}
-
-
- {fee?.toBalanceString('auto')}
-
-
- {!!message?.memo?.length && (
-
-
- {message.memo}
+
+
+ {`${Provider.selectedProvider.coinName} ${Provider.selectedProvider.denom}`}
+
+
+ {amount?.isPositive() && (
+
+
+ {amount?.toBalanceString('auto')}
+
+
+ )}
+
+
+ {fee?.toBalanceString('auto')}
- )}
-
+ {!!message?.memo?.length && (
+
+
+ {message.memo}
+
+
+ )}
+
-
+
-
-
- {isJsonHidden && (
-
- )}
+
+
+ {isJsonHidden && (
+
+ )}
- <>
-
-
-
-
+
-
- >
-
-
-
-
- );
-}
+
+
+
+
+ >
+
+
+
+
+ );
+ },
+);
const styles = createTheme({
container: {
diff --git a/src/components/ui/copy-menu.tsx b/src/components/ui/copy-menu.tsx
index b0bcf241e..232218a57 100644
--- a/src/components/ui/copy-menu.tsx
+++ b/src/components/ui/copy-menu.tsx
@@ -22,11 +22,11 @@ import Popover from '@app/components/ui/popover';
import {RTLReverse} from '@app/components/ui/rtl-reverse';
import {Spacer} from '@app/components/ui/spacer';
import {Text, TextVariant} from '@app/components/ui/text';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {AddressUtils} from '@app/helpers/address-utils';
import {useTypedNavigation} from '@app/hooks';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {sendNotification} from '@app/services';
export type CopyMenuProps = ViewProps & {
@@ -86,7 +86,7 @@ export const CopyMenu = observer(
- {app.provider.config.isBech32Enabled && (
+ {Provider.selectedProvider.config.isBech32Enabled && (
<>
diff --git a/src/components/ui/icon.tsx b/src/components/ui/icon.tsx
index 9497d0f23..64c167c93 100644
--- a/src/components/ui/icon.tsx
+++ b/src/components/ui/icon.tsx
@@ -30,25 +30,26 @@ export enum IconsName {
color_gradient = 'color_gradient',
copy = 'copy',
currency = 'currency',
- drag = 'drag',
- doc = 'doc',
deposit = 'deposit',
+ doc = 'doc',
+ drag = 'drag',
flash = 'flash',
flashlight = 'flashlight',
global = 'global',
governance = 'governance',
help = 'help',
image = 'image',
+ info = 'info',
inprogress = 'inprogress',
instagram = 'instagram',
invoice = 'invoice',
islm = 'islm',
- info = 'info',
language = 'language',
list = 'list',
link = 'link',
lock = 'lock',
market = 'market',
+ networks = 'networks',
news = 'news',
no_proposal_voting = 'no_proposal_voting',
paste = 'paste',
diff --git a/src/components/ui/progress-line.tsx b/src/components/ui/progress-line.tsx
index 7cd33d0ef..d2fea08b0 100644
--- a/src/components/ui/progress-line.tsx
+++ b/src/components/ui/progress-line.tsx
@@ -10,8 +10,8 @@ import Animated, {
import {Color, getColor} from '@app/colors';
import {Spacer, Text, TextVariant} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
+import {Provider} from '@app/models/provider';
export type ProgressLineProps = {
initialProgress?: number;
@@ -70,9 +70,9 @@ export const ProgressLine = observer(
{showBottomInfo && (
- {`${total.toFixed(0)} ${app.provider.denom} from ${max.toFixed(
- 0,
- )} ${app.provider.denom}`}
+ {`${total.toFixed(0)} ${
+ Provider.selectedProvider.denom
+ } from ${max.toFixed(0)} ${Provider.selectedProvider.denom}`}
)}
>
diff --git a/src/components/ui/provider-menu.tsx b/src/components/ui/provider-menu.tsx
index 3ee9ffbef..ab6b01cf5 100644
--- a/src/components/ui/provider-menu.tsx
+++ b/src/components/ui/provider-menu.tsx
@@ -6,22 +6,22 @@ import {TouchableOpacity, View} from 'react-native';
import {Color} from '@app/colors';
import {Icon, IconsName} from '@app/components/ui/icon';
import {Text, TextPosition, TextVariant} from '@app/components/ui/text';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {awaitForProvider} from '@app/helpers/await-for-provider';
import {I18N} from '@app/i18n';
import {Provider} from '@app/models/provider';
export const ProviderMenu = observer(() => {
- const currentProvider = app.provider;
-
const open = useCallback(async () => {
const providerId = await awaitForProvider({
providers: Provider.getAll(),
- initialProviderId: app.providerId!,
+ initialProviderId: Provider.selectedProviderId,
title: I18N.networks,
});
- app.providerId = providerId;
+
+ if (providerId) {
+ Provider.setSelectedProviderId(providerId);
+ }
}, []);
return (
@@ -31,7 +31,7 @@ export const ProviderMenu = observer(() => {
color={Color.textBase2}
variant={TextVariant.t14}
position={TextPosition.center}>
- {currentProvider?.name}
+ {Provider.selectedProvider.name}
- {`${formattedAmount} ${app.provider.denom}`}
+ {`${formattedAmount} ${Provider.selectedProvider.denom}`}
diff --git a/src/components/ui/sum-block.tsx b/src/components/ui/sum-block.tsx
index 0aa5a3cf8..c3ecbdc26 100644
--- a/src/components/ui/sum-block.tsx
+++ b/src/components/ui/sum-block.tsx
@@ -14,9 +14,9 @@ import {
import {Color, getColor} from '@app/colors';
import {Button, ButtonSize, ButtonVariant} from '@app/components/ui/button';
import {Text, TextPosition, TextVariant} from '@app/components/ui/text';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {I18N, getText} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {HapticEffects, vibrate} from '@app/services/haptic';
import {IToken} from '@app/types';
@@ -100,7 +100,7 @@ export const SumBlock = observer(
position={TextPosition.center}
style={styles.subtitle}
color={Color.textBase2}>
- {currency || app.provider.denom}
+ {currency || Provider.selectedProvider.denom}
diff --git a/src/components/ui/text-sum.tsx b/src/components/ui/text-sum.tsx
index 4965cc108..f58b8dbc1 100644
--- a/src/components/ui/text-sum.tsx
+++ b/src/components/ui/text-sum.tsx
@@ -5,9 +5,9 @@ import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
import {Color} from '@app/colors';
import {Text, TextPosition, TextVariant} from '@app/components/ui';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {I18N, getText} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Spacer} from './spacer';
@@ -34,7 +34,7 @@ export const TextSum = observer(
const hasRightText = typeof rightText !== 'undefined';
const text = hasRightText
? getText(rightText)
- : app.provider.denom + suffix;
+ : Provider.selectedProvider.denom + suffix;
const viewStyles = StyleSheet.flatten([
center && styles.center,
diff --git a/src/components/web3-browser/web3-browser-action-menu.tsx b/src/components/web3-browser/web3-browser-action-menu.tsx
index a7165adf8..caa7a6d66 100644
--- a/src/components/web3-browser/web3-browser-action-menu.tsx
+++ b/src/components/web3-browser/web3-browser-action-menu.tsx
@@ -7,7 +7,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {Color} from '@app/colors';
import {createTheme} from '@app/helpers';
import {I18N} from '@app/i18n';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {IS_IOS} from '@app/variables/common';
import {SHADOW_L} from '@app/variables/shadows';
@@ -20,7 +20,7 @@ interface Web3BrowserActionMenuProps {
walletAddress?: string;
showActionMenu: boolean;
isSiteInBookmarks: boolean;
- currentProvider: Provider;
+ currentProvider: ProviderModel;
currentSessionOrigin?: string;
moreIconLayout: Partial;
popup?: boolean;
diff --git a/src/components/web3-browser/web3-browser.tsx b/src/components/web3-browser/web3-browser.tsx
index 1d92b2f4b..44197912f 100644
--- a/src/components/web3-browser/web3-browser.tsx
+++ b/src/components/web3-browser/web3-browser.tsx
@@ -1,6 +1,7 @@
// @refresh reset
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
+import {observer} from 'mobx-react';
import {View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import WebView from 'react-native-webview';
@@ -51,7 +52,6 @@ export interface Web3BrowserProps {
bookmarks: Realm.Results;
showActionMenu: boolean;
popup?: boolean;
- userProvider: Provider;
focused: boolean;
onPressHeaderUrl(event: Web3BrowserPressHeaderEvent): void;
@@ -89,110 +89,123 @@ export interface Web3BrowserProps {
addSiteToSearchHistory(windowInfo: WindowInfoEvent['payload']): void;
}
-export const Web3Browser = ({
- popup,
- initialUrl,
- helper,
- webviewRef,
- sessions,
- bookmarks,
- showActionMenu,
- userProvider,
- onPressClose,
- toggleActionMenu,
- onPressHeaderWallet,
- onPressHeaderUrl,
- onPressGoBack,
- onPressGoForward,
- onPressMore,
- onPressProviders,
- onPressHome,
- onPressRefresh,
- onPressCopyLink,
- onPressDisconnect,
- onPressShare,
- onPressAddBookmark,
- onPressRemoveBookmark,
- addSiteToSearchHistory,
- onPressPrivacy,
-}: Web3BrowserProps) => {
- const [inpageBridgeWeb3, setInpageBridgeWeb3] = useState('');
- const [selectedAccount, setSelectedAccount] = useState();
- const [windowInfo, setWindowInfo] = useState();
- const [webviewNavigationData, setWebviewNavigationData] =
- useState();
- const addedToSearchHistory = useRef(false);
- const [moreIconLayout, onMoreIconLayout] = useLayout();
-
- const insets = useSafeAreaInsets();
- const currentSession = useMemo(() => {
- if (!sessions?.length) {
- return;
- }
- return sessions.filtered(
- 'origin = $0',
- getOriginFromUrl(webviewNavigationData?.url || initialUrl),
- )[0];
- }, [initialUrl, sessions, webviewNavigationData?.url]);
- const prevSession = usePrevious(currentSession);
-
- const onPressRefreshHandler = useCallback(async () => {
- onPressRefresh?.();
- setInpageBridgeWeb3('');
- const script = await InpageBridgeWeb3.loadScript();
- setInpageBridgeWeb3(script);
- }, []);
-
- useEffect(() => {
- if (prevSession && !currentSession) {
- helper.disconnectAccount();
- onPressRefreshHandler();
- }
- }, [currentSession, helper, prevSession, webviewRef, onPressRefreshHandler]);
-
- useEffect(() => {
- // if saved account in session removed from wallet
- if (
- currentSession?.selectedAccount &&
- !Wallet.getById(currentSession?.selectedAccount)
- ) {
- helper.disconnectAccount();
- onPressRefreshHandler();
- }
- }, [currentSession, helper, webviewRef, onPressRefreshHandler]);
-
- const walletAddress = selectedAccount || currentSession?.selectedAccount;
- const siteUrl = useMemo(
- () =>
- webviewNavigationData?.url ||
- windowInfo?.url ||
- helper.currentUrl ||
- initialUrl,
- [
- helper.currentUrl,
- initialUrl,
- webviewNavigationData?.url,
- windowInfo?.url,
- ],
- );
- const isSiteInBookmarks = useMemo(
- () => !!bookmarks?.filtered(`url = '${siteUrl}'`)?.[0]?.id,
- [siteUrl, bookmarks],
- );
-
- const chainId = useMemo(
- () => currentSession?.selectedChainIdHex || userProvider?.ethChainIdHex,
- [currentSession?.selectedChainIdHex, userProvider?.ethChainIdHex],
- );
-
- const currentProvider = useMemo(
- () => Provider.getByChainIdHex(chainId!),
- [chainId],
- );
-
- const injectedJSBeforeContentLoaded = useMemo(
- () =>
- `
+export const Web3Browser = observer(
+ ({
+ popup,
+ initialUrl,
+ helper,
+ webviewRef,
+ sessions,
+ bookmarks,
+ showActionMenu,
+ onPressClose,
+ toggleActionMenu,
+ onPressHeaderWallet,
+ onPressHeaderUrl,
+ onPressGoBack,
+ onPressGoForward,
+ onPressMore,
+ onPressProviders,
+ onPressHome,
+ onPressRefresh,
+ onPressCopyLink,
+ onPressDisconnect,
+ onPressShare,
+ onPressAddBookmark,
+ onPressRemoveBookmark,
+ addSiteToSearchHistory,
+ onPressPrivacy,
+ }: Web3BrowserProps) => {
+ const [inpageBridgeWeb3, setInpageBridgeWeb3] = useState('');
+ const [selectedAccount, setSelectedAccount] = useState<
+ string | undefined
+ >();
+ const [windowInfo, setWindowInfo] = useState();
+ const [webviewNavigationData, setWebviewNavigationData] =
+ useState();
+ const addedToSearchHistory = useRef(false);
+ const [moreIconLayout, onMoreIconLayout] = useLayout();
+
+ const insets = useSafeAreaInsets();
+ const currentSession = useMemo(() => {
+ if (!sessions?.length) {
+ return;
+ }
+ return sessions.filtered(
+ 'origin = $0',
+ getOriginFromUrl(webviewNavigationData?.url || initialUrl),
+ )[0];
+ }, [initialUrl, sessions, webviewNavigationData?.url]);
+ const prevSession = usePrevious(currentSession);
+
+ const onPressRefreshHandler = useCallback(async () => {
+ onPressRefresh?.();
+ setInpageBridgeWeb3('');
+ const script = await InpageBridgeWeb3.loadScript();
+ setInpageBridgeWeb3(script);
+ }, []);
+
+ useEffect(() => {
+ if (prevSession && !currentSession) {
+ helper.disconnectAccount();
+ onPressRefreshHandler();
+ }
+ }, [
+ currentSession,
+ helper,
+ prevSession,
+ webviewRef,
+ onPressRefreshHandler,
+ ]);
+
+ useEffect(() => {
+ // if saved account in session removed from wallet
+ if (
+ currentSession?.selectedAccount &&
+ !Wallet.getById(currentSession?.selectedAccount)
+ ) {
+ helper.disconnectAccount();
+ onPressRefreshHandler();
+ }
+ }, [currentSession, helper, webviewRef, onPressRefreshHandler]);
+
+ const walletAddress = selectedAccount || currentSession?.selectedAccount;
+ const siteUrl = useMemo(
+ () =>
+ webviewNavigationData?.url ||
+ windowInfo?.url ||
+ helper.currentUrl ||
+ initialUrl,
+ [
+ helper.currentUrl,
+ initialUrl,
+ webviewNavigationData?.url,
+ windowInfo?.url,
+ ],
+ );
+ const isSiteInBookmarks = useMemo(
+ () => !!bookmarks?.filtered(`url = '${siteUrl}'`)?.[0]?.id,
+ [siteUrl, bookmarks],
+ );
+
+ const chainId = useMemo(
+ () =>
+ currentSession?.selectedChainIdHex ||
+ Provider.selectedProvider.ethChainIdHex,
+ [
+ currentSession?.selectedChainIdHex,
+ Provider.selectedProvider.ethChainIdHex,
+ ],
+ );
+
+ const currentProvider = useMemo(
+ () => Provider.getByChainIdHex(chainId!),
+ [chainId],
+ );
+
+ const injectedJSBeforeContentLoaded = useMemo(
+ () =>
+ `
function init() {
if(window?.ethereum?.isHaqqWallet || window?.keplr?.isHaqqWallet){
return;
@@ -233,183 +246,191 @@ export const Web3Browser = ({
}
${WebViewEventsJS.getWindowInformation}
true;`,
- [inpageBridgeWeb3],
- );
-
- const onContentProcessDidTerminate = useCallback(() => {
- onPressRefreshHandler();
- }, [webviewRef, onPressRefreshHandler]);
-
- const handlePressAddBookmark = useCallback(() => {
- const url =
- webviewNavigationData?.url || windowInfo?.url || helper.currentUrl;
- onPressAddBookmark?.({
- ...windowInfo,
- url,
- title: webviewNavigationData?.title || windowInfo?.title || clearUrl(url),
- });
- }, [
- helper.currentUrl,
- onPressAddBookmark,
- webviewNavigationData?.title,
- webviewNavigationData?.url,
- windowInfo,
- ]);
-
- const handlePressRemoveBookmark = useCallback(() => {
- const url =
- webviewNavigationData?.url || windowInfo?.url || helper.currentUrl;
- onPressRemoveBookmark?.(url);
- }, [
- helper.currentUrl,
- onPressRemoveBookmark,
- webviewNavigationData?.url,
- windowInfo,
- ]);
-
- const onLoad = useCallback(
- (event: WebViewNavigationEvent) => {
- if (detectDeeplink(event.nativeEvent.url)) {
- webviewRef.current?.stopLoading();
- return;
- }
+ [inpageBridgeWeb3],
+ );
- helper.onLoad(event);
- setWebviewNavigationData(event.nativeEvent);
+ const onContentProcessDidTerminate = useCallback(() => {
+ onPressRefreshHandler();
+ }, [webviewRef, onPressRefreshHandler]);
+
+ const handlePressAddBookmark = useCallback(() => {
+ const url =
+ webviewNavigationData?.url || windowInfo?.url || helper.currentUrl;
+ onPressAddBookmark?.({
+ ...windowInfo,
+ url,
+ title:
+ webviewNavigationData?.title || windowInfo?.title || clearUrl(url),
+ });
+ }, [
+ helper.currentUrl,
+ onPressAddBookmark,
+ webviewNavigationData?.title,
+ webviewNavigationData?.url,
+ windowInfo,
+ ]);
+
+ const handlePressRemoveBookmark = useCallback(() => {
+ const url =
+ webviewNavigationData?.url || windowInfo?.url || helper.currentUrl;
+ onPressRemoveBookmark?.(url);
+ }, [
+ helper.currentUrl,
+ onPressRemoveBookmark,
+ webviewNavigationData?.url,
+ windowInfo,
+ ]);
- if (
- event?.nativeEvent?.navigationType === 'backforward' &&
- !event.nativeEvent?.loading
- ) {
- onPressRefreshHandler();
- }
- },
- [helper, webviewRef, onPressRefreshHandler],
- );
+ const onLoad = useCallback(
+ (event: WebViewNavigationEvent) => {
+ if (detectDeeplink(event.nativeEvent.url)) {
+ webviewRef.current?.stopLoading();
+ return;
+ }
- const onNavigationStateChange = useCallback((navState: WebViewNavigation) => {
- if (detectDeeplink(navState.url)) {
- return;
- }
- setWebviewNavigationData(navState);
- }, []);
-
- useAndroidBackHandler(() => {
- if (webviewRef.current) {
- if (webviewNavigationData?.canGoBack) {
- webviewRef.current.goBack();
- return true;
- } else {
- return false;
- }
- }
- return false;
- }, [webviewNavigationData?.canGoBack, webviewRef]);
+ helper.onLoad(event);
+ setWebviewNavigationData(event.nativeEvent);
- useEffect(() => {
- InpageBridgeWeb3.loadScript().then(script => {
- setInpageBridgeWeb3(script);
- });
+ if (
+ event?.nativeEvent?.navigationType === 'backforward' &&
+ !event.nativeEvent?.loading
+ ) {
+ onPressRefreshHandler();
+ }
+ },
+ [helper, webviewRef, onPressRefreshHandler],
+ );
- helper?.on(WebViewEventsEnum.WINDOW_INFO, (event: WindowInfoEvent) => {
- setWindowInfo(event.payload);
- if (
- !addedToSearchHistory.current &&
- !Web3BrowserSearchHistory.getByUrl(event.payload.url)
- ) {
- addSiteToSearchHistory(event.payload);
- addedToSearchHistory.current = true;
- }
- });
-
- helper?.on(WebViewEventsEnum.ACCOUNTS_CHANGED, ([accountId]: string[]) => {
- if (accountId) {
- const foundWallet = Wallet.getById(accountId);
- setSelectedAccount(foundWallet?.address);
- } else {
- setSelectedAccount(undefined);
+ const onNavigationStateChange = useCallback(
+ (navState: WebViewNavigation) => {
+ if (detectDeeplink(navState.url)) {
+ return;
+ }
+ setWebviewNavigationData(navState);
+ },
+ [],
+ );
+
+ useAndroidBackHandler(() => {
+ if (webviewRef.current) {
+ if (webviewNavigationData?.canGoBack) {
+ webviewRef.current.goBack();
+ return true;
+ } else {
+ return false;
+ }
}
- });
+ return false;
+ }, [webviewNavigationData?.canGoBack, webviewRef]);
+
+ useEffect(() => {
+ InpageBridgeWeb3.loadScript().then(script => {
+ setInpageBridgeWeb3(script);
+ });
+
+ helper?.on(WebViewEventsEnum.WINDOW_INFO, (event: WindowInfoEvent) => {
+ setWindowInfo(event.payload);
+ if (
+ !addedToSearchHistory.current &&
+ !Web3BrowserSearchHistory.getByUrl(event.payload.url)
+ ) {
+ addSiteToSearchHistory(event.payload);
+ addedToSearchHistory.current = true;
+ }
+ });
+
+ helper?.on(
+ WebViewEventsEnum.ACCOUNTS_CHANGED,
+ ([accountId]: string[]) => {
+ if (accountId) {
+ const foundWallet = Wallet.getById(accountId);
+ setSelectedAccount(foundWallet?.address);
+ } else {
+ setSelectedAccount(undefined);
+ }
+ },
+ );
- return () => {
- helper.dispose();
- };
- }, [addSiteToSearchHistory, helper]);
+ return () => {
+ helper.dispose();
+ };
+ }, [addSiteToSearchHistory, helper]);
+
+ const webViewDefaultProps = useWebViewSharedProps(
+ webviewRef,
+ {
+ onMessage: helper.handleMessage,
+ injectedJavaScriptBeforeContentLoaded: injectedJSBeforeContentLoaded,
+ },
+ [injectedJSBeforeContentLoaded],
+ );
+
+ if (!inpageBridgeWeb3) {
+ return null;
+ }
- const webViewDefaultProps = useWebViewSharedProps(
- webviewRef,
- {
- onMessage: helper.handleMessage,
- injectedJavaScriptBeforeContentLoaded: injectedJSBeforeContentLoaded,
- },
- [injectedJSBeforeContentLoaded],
- );
-
- if (!inpageBridgeWeb3) {
- return null;
- }
-
- return (
-
-
-
-
-
+
-
-
-
-
- );
-};
+
+
+
+
+
+
+
+ );
+ },
+);
const styles = createTheme({
webview: {
diff --git a/src/contexts/app.ts b/src/contexts/app.ts
index 20ba1f941..d682d27e6 100644
--- a/src/contexts/app.ts
+++ b/src/contexts/app.ts
@@ -3,7 +3,6 @@ import {appleAuth} from '@invertase/react-native-apple-authentication';
import dynamicLinks from '@react-native-firebase/dynamic-links';
import {GoogleSignin} from '@react-native-google-signin/google-signin';
import {subMinutes} from 'date-fns';
-import {makeObservable, observable, runInAction} from 'mobx';
import {Alert, AppState, Appearance, Platform, StatusBar} from 'react-native';
import Config from 'react-native-config';
import Keychain, {
@@ -52,13 +51,7 @@ import {
ModalType,
WalletType,
} from '../types';
-import {
- ISLM_DENOM,
- LIGHT_GRAPHIC_GREEN_1,
- MAIN_NETWORK_ID,
- TEST_NETWORK_ID,
- WEI_PRECISION,
-} from '../variables/common';
+import {LIGHT_GRAPHIC_GREEN_1} from '../variables/common';
const optionalConfigObject = {
title: 'Fingerprint Login', // Android
@@ -97,10 +90,6 @@ class App extends AsyncEventEmitter {
constructor() {
super();
- makeObservable(this, {
- // @ts-ignore
- _provider: observable,
- });
this.startInitialization();
this.setMaxListeners(1000);
this._startUpTime = Date.now();
@@ -126,16 +115,9 @@ class App extends AsyncEventEmitter {
this.user = User.getOrCreate();
Provider.init()
- .then(() => {
- runInAction(() => {
- this._provider = Provider.getById(this.providerId);
- });
- })
.then(RemoteProviderConfig.init)
.then(() => {
- if (this._provider) {
- EthNetwork.init(this._provider);
- }
+ EthNetwork.init(Provider.selectedProvider);
this.checkBalance = this.checkBalance.bind(this);
this.checkBalance();
@@ -215,43 +197,8 @@ class App extends AsyncEventEmitter {
);
}
- private _provider: Provider | null = null;
-
- get provider() {
- return (this._provider || {
- // used as default value while first provider initialization
- denom: ISLM_DENOM,
- decimals: WEI_PRECISION,
- }) as Provider;
- }
-
- get providerId() {
- return (
- VariablesString.get('providerId') ??
- (Config.ENVIRONMENT === 'production' ||
- Config.ENVIRONMENT === 'distribution'
- ? MAIN_NETWORK_ID
- : TEST_NETWORK_ID)
- );
- }
-
- set providerId(value) {
- const p = Provider.getById(value);
- if (p) {
- VariablesString.set('providerId', value);
- runInAction(() => {
- this._provider = p;
- });
- EthNetwork.init(p);
- this._balances.clear();
- app.emit(Events.onProviderChanged, p.id);
- } else {
- throw new Error('Provider not found');
- }
- }
-
get cosmos() {
- return new Cosmos(app.provider);
+ return new Cosmos(Provider.selectedProvider);
}
get backend() {
@@ -786,7 +733,7 @@ class App extends AsyncEventEmitter {
}
async getRpcProvider() {
- return await getRpcProvider(this.provider);
+ return await getRpcProvider(Provider.selectedProvider);
}
resetAuth() {
diff --git a/src/event-actions/index.ts b/src/event-actions/index.ts
index 079459878..5f0f8fd82 100644
--- a/src/event-actions/index.ts
+++ b/src/event-actions/index.ts
@@ -10,7 +10,6 @@ import {onBlockRequestCheck} from '@app/event-actions/on-block-request-check';
import {onDeepLink} from '@app/event-actions/on-deep-link';
import {onDynamicLink} from '@app/event-actions/on-dynamic-link';
import {onNeedUpdate} from '@app/event-actions/on-need-update';
-import {onProviderChanged} from '@app/event-actions/on-provider-changed';
import {onPushNotification} from '@app/event-actions/on-push-notification';
import {onStakingSync} from '@app/event-actions/on-staking-sync';
import {onSyncAppBalances} from '@app/event-actions/on-sync-app-balances';
@@ -65,7 +64,6 @@ app.on(Events.onDynamicLink, onDynamicLink);
app.on(Events.onTransactionsLoad, onTransactionsLoad);
app.on(Events.onTransactionStatusLoad, onTransactionStatusLoad);
app.on(Events.onPushNotification, onPushNotification);
-app.on(Events.onProviderChanged, onProviderChanged);
app.on(Events.onAppReviewRequest, onAppReviewRequest);
app.on(Events.onNeedUpdate, onNeedUpdate);
app.on(Events.onBlockRequestCheck, onBlockRequestCheck);
diff --git a/src/event-actions/on-banner-claim-airdrop.ts b/src/event-actions/on-banner-claim-airdrop.ts
index b1928d93e..f3907af59 100644
--- a/src/event-actions/on-banner-claim-airdrop.ts
+++ b/src/event-actions/on-banner-claim-airdrop.ts
@@ -85,15 +85,16 @@ export async function onBannerClaimAirdrop(claimCode: string) {
});
if (referral) {
- const provider = Provider.getById(app.providerId);
-
const info = await Airdrop.instance.campaign_code(claimCode);
- if (provider?.id !== MAIN_NETWORK_ID && info.code_type !== 'raffle') {
+ if (
+ Provider.selectedProviderId !== MAIN_NETWORK_ID &&
+ info.code_type !== 'raffle'
+ ) {
showModal('claimOnMainnet', {
- network: provider?.name ?? '',
+ network: Provider.selectedProvider.name ?? '',
onChange: () => {
- app.providerId = MAIN_NETWORK_ID;
+ Provider.setSelectedProviderId(MAIN_NETWORK_ID);
},
});
}
diff --git a/src/event-actions/on-provider-changed.ts b/src/event-actions/on-provider-changed.ts
deleted file mode 100644
index 13248b0e7..000000000
--- a/src/event-actions/on-provider-changed.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import {app} from '@app/contexts';
-import {Events} from '@app/events';
-import {hideModal, showModal} from '@app/helpers';
-import {awaitForEventDone} from '@app/helpers/await-for-event-done';
-import {EthRpcEndpointAvailability} from '@app/helpers/eth-rpc-endpoint-availability';
-import {Currencies} from '@app/models/currencies';
-import {Nft} from '@app/models/nft';
-import {Provider, RemoteProviderConfig} from '@app/models/provider';
-import {Stories} from '@app/models/stories';
-import {Token} from '@app/models/tokens';
-import {Transaction} from '@app/models/transaction';
-import {Wallet} from '@app/models/wallet';
-import {ModalType} from '@app/types';
-import {createAsyncTask} from '@app/utils';
-
-export const onProviderChanged = createAsyncTask(async () => {
- try {
- showModal(ModalType.loading);
-
- Nft.clear();
- Token.clear();
- Transaction.clear();
- Currencies.clear();
-
- await RemoteProviderConfig.init();
- await awaitForEventDone(Events.onSyncAppBalances);
- await awaitForEventDone(Events.onRequestMarkup);
- await Token.fetchTokens(true);
- await Transaction.fetchLatestTransactions(Wallet.addressList(), true);
- await Currencies.fetchCurrencies();
-
- if (app.provider.config.isNftEnabled) {
- await Nft.fetchNft();
- }
- Provider.fetchProviders();
- } finally {
- hideModal(ModalType.loading);
- app.emit(Events.onProviderChangedFinish);
- }
-
- await Promise.allSettled([
- Currencies.setSelectedCurrency(),
- awaitForEventDone(Events.onTesterModeChanged, app.isTesterMode),
- EthRpcEndpointAvailability.checkEthRpcEndpointAvailability(),
- Stories.fetch(true),
- ]);
-});
diff --git a/src/event-actions/on-staking-rewards.ts b/src/event-actions/on-staking-rewards.ts
index b5bf07fca..2f6cc9f50 100644
--- a/src/event-actions/on-staking-rewards.ts
+++ b/src/event-actions/on-staking-rewards.ts
@@ -2,6 +2,7 @@ import {app} from '@app/contexts';
import {Events} from '@app/events';
import {getProviderInstanceForWallet} from '@app/helpers';
import {getRemoteBalanceValue} from '@app/helpers/get-remote-balance-value';
+import {Provider} from '@app/models/provider';
import {
StakingMetadata,
StakingMetadataType,
@@ -11,7 +12,7 @@ import {Cosmos} from '@app/services/cosmos';
import {AWAIT_NEW_BLOCK_MS} from '@app/variables/common';
export async function onStakingRewards() {
- const cosmos = new Cosmos(app.provider!);
+ const cosmos = new Cosmos(Provider.selectedProvider);
const visible = Wallet.getAllVisible();
const rewards = StakingMetadata.getAllByType(StakingMetadataType.reward);
const delegators: any = {};
diff --git a/src/event-actions/on-staking-sync.ts b/src/event-actions/on-staking-sync.ts
index 0465dd8f0..b7a08aa7d 100644
--- a/src/event-actions/on-staking-sync.ts
+++ b/src/event-actions/on-staking-sync.ts
@@ -1,6 +1,6 @@
-import {app} from '@app/contexts';
import {Events} from '@app/events';
import {AddressUtils} from '@app/helpers/address-utils';
+import {Provider} from '@app/models/provider';
import {
StakingMetadata,
StakingMetadataType,
@@ -10,7 +10,7 @@ import {Cosmos} from '@app/services/cosmos';
export async function onStakingSync() {
Logger.log(Events.onStakingSync);
- const cosmos = new Cosmos(app.provider!);
+ const cosmos = new Cosmos(Provider.selectedProvider);
const addressList = Wallet.getAllVisible().map(w =>
AddressUtils.toHaqq(w.address),
);
diff --git a/src/event-actions/on-transaction-status-load.ts b/src/event-actions/on-transaction-status-load.ts
index 0617523c5..68347290d 100644
--- a/src/event-actions/on-transaction-status-load.ts
+++ b/src/event-actions/on-transaction-status-load.ts
@@ -1,5 +1,5 @@
-import {app} from '@app/contexts';
import {getExplorerInstanceForProvider} from '@app/helpers/explorer-instance';
+import {Provider} from '@app/models/provider';
import {Transaction} from '@app/models/transaction';
import {IndexerTransactionStatus} from '@app/types';
@@ -20,7 +20,9 @@ export async function onTransactionStatusLoad(txHash: string) {
const loadStatus = async (tx: Transaction) => {
try {
if (tx) {
- const explorer = getExplorerInstanceForProvider(app.providerId);
+ const explorer = getExplorerInstanceForProvider(
+ Provider.selectedProviderId,
+ );
const receipt = await explorer.transactionReceiptStatus(tx.hash);
const status = await explorer.transactionStatus(tx.hash);
diff --git a/src/event-actions/on-vesting-sync.ts b/src/event-actions/on-vesting-sync.ts
index 0b10754b5..f2b0c8707 100644
--- a/src/event-actions/on-vesting-sync.ts
+++ b/src/event-actions/on-vesting-sync.ts
@@ -1,5 +1,5 @@
-import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
+import {Provider} from '@app/models/provider';
import {
VestingMetadata,
VestingMetadataType,
@@ -9,7 +9,7 @@ import {Cosmos} from '@app/services/cosmos';
export async function onVestingSync() {
Logger.log('onVestingSync');
- const cosmos = new Cosmos(app.provider!);
+ const cosmos = new Cosmos(Provider.selectedProvider);
const addressList = Wallet.getAllVisible().map(w =>
AddressUtils.toHaqq(w.address),
);
diff --git a/src/event-actions/on-wallet-connect-sign-transaction.ts b/src/event-actions/on-wallet-connect-sign-transaction.ts
index 203ca3cd7..1f3389b0f 100644
--- a/src/event-actions/on-wallet-connect-sign-transaction.ts
+++ b/src/event-actions/on-wallet-connect-sign-transaction.ts
@@ -1,6 +1,5 @@
import {getSdkError} from '@walletconnect/utils';
-import {app} from '@app/contexts';
import {Events} from '@app/events';
import {awaitForJsonRpcSign} from '@app/helpers/await-for-json-rpc-sign';
import {awaitForProvider} from '@app/helpers/await-for-provider';
@@ -34,12 +33,12 @@ export async function onWalletConnectSignTransaction(
const providers = Provider.getAll();
const providerId = await awaitForProvider({
providers,
- initialProviderId: app.providerId!,
+ initialProviderId: Provider.selectedProviderId,
title: I18N.networks,
});
if (providerId) {
- app.providerId = providerId;
+ Provider.setSelectedProviderId(providerId);
await WalletConnect.instance.approveSessionRequest(providerId, event);
} else {
await WalletConnect.instance.rejectSessionRequest(
diff --git a/src/event-actions/on-wallets-balance-check.ts b/src/event-actions/on-wallets-balance-check.ts
index dfef3f8ee..26cac2379 100644
--- a/src/event-actions/on-wallets-balance-check.ts
+++ b/src/event-actions/on-wallets-balance-check.ts
@@ -2,6 +2,7 @@ import {app} from '@app/contexts';
import {Events} from '@app/events';
import {AddressUtils} from '@app/helpers/address-utils';
import {Currencies} from '@app/models/currencies';
+import {Provider} from '@app/models/provider';
import {VariablesDate} from '@app/models/variables-date';
import {Wallet} from '@app/models/wallet';
import {Balance} from '@app/services/balance';
@@ -67,7 +68,7 @@ export const onWalletsBalanceCheck = createAsyncTask(async () => {
}
const wallets = Wallet.getAllVisible();
const lastBalanceUpdates = VariablesDate.get(
- `indexer_${app.provider.cosmosChainId}`,
+ `indexer_${Provider.selectedProvider.cosmosChainId}`,
);
let accounts = wallets.map(w => w.cosmosAddress);
@@ -78,7 +79,7 @@ export const onWalletsBalanceCheck = createAsyncTask(async () => {
);
VariablesDate.set(
- `indexer_${app.provider.cosmosChainId}`,
+ `indexer_${Provider.selectedProvider.cosmosChainId}`,
new Date(updates.last_update),
);
@@ -113,7 +114,7 @@ export async function onWalletsBalanceCheckRPC(
) {
try {
VariablesDate.set(
- `indexer_${app.provider.cosmosChainId}`,
+ `indexer_${Provider.selectedProvider.cosmosChainId}`,
new Date(updates.last_update),
);
diff --git a/src/events.ts b/src/events.ts
index ec93c558f..009090c6f 100644
--- a/src/events.ts
+++ b/src/events.ts
@@ -1,5 +1,4 @@
export enum Events {
- onProviderChanged = 'onProviderChanged',
onWalletsBalanceCheck = 'onWalletsBalanceCheck',
onWalletsBalanceCheckError = 'onWalletsBalanceCheckError',
onWalletCreate = 'onWalletCreate',
diff --git a/src/helpers/await-for-provider.ts b/src/helpers/await-for-provider.ts
index 27102f18d..56b011b55 100644
--- a/src/helpers/await-for-provider.ts
+++ b/src/helpers/await-for-provider.ts
@@ -3,13 +3,13 @@ import {Results} from 'realm';
import {app} from '@app/contexts';
import {showModal} from '@app/helpers/modal';
import {I18N} from '@app/i18n';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {getWindowHeight} from './scaling-utils';
export interface AwaitProviderParams {
title: I18N;
- providers: Provider[] | Results;
+ providers: ProviderModel[] | Results;
initialProviderId: string;
}
diff --git a/src/helpers/get-app-info.ts b/src/helpers/get-app-info.ts
index ec78cb6bf..5dc8dacbe 100644
--- a/src/helpers/get-app-info.ts
+++ b/src/helpers/get-app-info.ts
@@ -2,11 +2,11 @@ import {Platform} from 'react-native';
import {PlatformOSType} from 'react-native/Libraries/Utilities/Platform';
import {NetworkInfo} from 'react-native-network-info';
-import {app} from '@app/contexts';
import {getLeadingAccount} from '@app/helpers/get-leading-account';
import {getUid} from '@app/helpers/get-uid';
import {Currencies} from '@app/models/currencies';
import {Language} from '@app/models/language';
+import {Provider} from '@app/models/provider';
import {VariablesBool} from '@app/models/variables-bool';
import {VariablesString} from '@app/models/variables-string';
import {Wallet} from '@app/models/wallet';
@@ -56,7 +56,7 @@ export async function getAppInfo(): Promise {
return {
wallets,
uid,
- chain_id: app.provider.ethChainId.toString(),
+ chain_id: Provider.selectedProvider.ethChainId.toString(),
platform: Platform.OS,
version: getAppVersion(),
posthog_id,
diff --git a/src/helpers/get-remote-balance-value.tsx b/src/helpers/get-remote-balance-value.tsx
index a6dc0f1cb..edad64b69 100644
--- a/src/helpers/get-remote-balance-value.tsx
+++ b/src/helpers/get-remote-balance-value.tsx
@@ -20,17 +20,17 @@ export const getDefaultBalanceValue = <
): Balance => {
switch (key) {
case 'transfer_min_amount':
- return MIN_AMOUNT;
+ return new Balance(MIN_AMOUNT);
case 'staking_reward_min_amount':
- return MIN_STAKING_REWARD;
+ return new Balance(MIN_STAKING_REWARD);
case 'cosmos_min_amount':
- return COSMOS_MIN_AMOUNT;
+ return new Balance(COSMOS_MIN_AMOUNT);
case 'cosmos_min_gas_limit':
- return COSMOS_MIN_GAS_LIMIT;
+ return new Balance(COSMOS_MIN_GAS_LIMIT);
case 'eth_min_amount':
- return MIN_AMOUNT;
+ return new Balance(MIN_AMOUNT);
case 'eth_min_gas_limit':
- return MIN_GAS_LIMIT;
+ return new Balance(MIN_GAS_LIMIT, 0);
default:
return Balance.Empty;
}
@@ -55,11 +55,11 @@ export const getDefaultMultiplierValue = <
): number => {
switch (key) {
case 'cosmos_commission_multiplier':
- return parseFloat(String(BALANCE_MULTIPLIER));
+ return BALANCE_MULTIPLIER;
case 'eth_commission_multiplier':
- return parseFloat(String(BALANCE_MULTIPLIER));
+ return BALANCE_MULTIPLIER;
default:
- return parseFloat(String(BALANCE_MULTIPLIER));
+ return BALANCE_MULTIPLIER;
}
};
diff --git a/src/helpers/get-rpc-provider.ts b/src/helpers/get-rpc-provider.ts
index cfc5dcb69..5db226799 100644
--- a/src/helpers/get-rpc-provider.ts
+++ b/src/helpers/get-rpc-provider.ts
@@ -1,10 +1,10 @@
import {ethers} from 'ethers';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {EthRpcEndpointAvailability} from './eth-rpc-endpoint-availability';
-export async function getRpcProvider(provider: Provider) {
+export async function getRpcProvider(provider: ProviderModel) {
await EthRpcEndpointAvailability.awaitForInitialization();
return new ethers.providers.StaticJsonRpcProvider(provider.ethRpcEndpoint, {
chainId: provider.ethChainId,
diff --git a/src/helpers/indexer-transaction-utils.ts b/src/helpers/indexer-transaction-utils.ts
index b3a48c7bb..3c96fda00 100644
--- a/src/helpers/indexer-transaction-utils.ts
+++ b/src/helpers/indexer-transaction-utils.ts
@@ -1,7 +1,7 @@
import {IconsName} from '@app/components/ui';
-import {app} from '@app/contexts';
import {I18N, getText} from '@app/i18n';
import {Contracts} from '@app/models/contracts';
+import {Provider} from '@app/models/provider';
import {Token} from '@app/models/tokens';
import {ParsedTransactionData, Transaction} from '@app/models/transaction';
import {Balance} from '@app/services/balance';
@@ -20,14 +20,14 @@ import {shortAddress} from './short-address';
const getNativeToken = (): IndexerTxParsedTokenInfo => {
return {
- name: app.provider.isHaqqNetwork
+ name: Provider.selectedProvider.isHaqqNetwork
? getText(I18N.transactionConfirmationIslamicCoin)
- : app.provider.name,
- symbol: app.provider.denom,
- icon: app.provider.isHaqqNetwork
+ : Provider.selectedProvider.name,
+ symbol: Provider.selectedProvider.denom,
+ icon: Provider.selectedProvider.isHaqqNetwork
? require('@assets/images/islm_icon.png')
- : {uri: app.provider.icon},
- decimals: app.provider.decimals,
+ : {uri: Provider.selectedProvider.icon},
+ decimals: Provider.selectedProvider.decimals,
contract_address: '',
};
};
@@ -331,10 +331,12 @@ function parseMsgSend(
}
const decimals =
- a.denom === app.provider.weiDenom ? app.provider.decimals : 0;
+ a.denom === Provider.selectedProvider.weiDenom
+ ? Provider.selectedProvider.decimals
+ : 0;
const symbol =
- a.denom === app.provider.weiDenom
- ? app.provider.denom
+ a.denom === Provider.selectedProvider.weiDenom
+ ? Provider.selectedProvider.denom
: a.denom || IBC_DENOM;
return new Balance(a.amount, decimals, symbol);
});
@@ -457,7 +459,7 @@ function getTokensInfo(tx: IndexerTransaction): IndexerTxParsedTokenInfo[] {
}
// @ts-ignore
- if (tx.msg?.amount?.denom === app.provider.weiDenom) {
+ if (tx.msg?.amount?.denom === Provider.selectedProvider.weiDenom) {
return [getNativeToken()];
}
@@ -499,7 +501,7 @@ function getTokensInfo(tx: IndexerTransaction): IndexerTxParsedTokenInfo[] {
icon: contractInfo.icon
? {uri: contractInfo.icon}
: require('@assets/images/empty-icon.png'),
- decimals: contractInfo?.decimals || app.provider.decimals,
+ decimals: contractInfo?.decimals || Provider.selectedProvider.decimals,
contract_address: contractInfo.id,
},
];
diff --git a/src/helpers/provider-instance.ts b/src/helpers/provider-instance.ts
index 43a7e351e..734b72563 100644
--- a/src/helpers/provider-instance.ts
+++ b/src/helpers/provider-instance.ts
@@ -14,6 +14,7 @@ import {ProviderSSSReactNative} from '@haqq/provider-sss-react-native';
import {app} from '@app/contexts';
import {awaitForLedger} from '@app/helpers/await-for-ledger';
import {getProviderStorage} from '@app/helpers/get-provider-storage';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {EventTracker} from '@app/services/event-tracker';
import {MarketingEvents, WalletType} from '@app/types';
@@ -34,8 +35,8 @@ function getProviderWrapper(provider: ProviderInterface) {
): Promise {
const params = {
type: 'signTransaction',
- network: app.provider.name,
- chainId: `${app.provider.ethChainId}`,
+ network: Provider.selectedProvider.name,
+ chainId: `${Provider.selectedProvider.ethChainId}`,
};
try {
EventTracker.instance.trackEvent(MarketingEvents.signTxStart, params);
@@ -57,8 +58,8 @@ function getProviderWrapper(provider: ProviderInterface) {
): Promise {
const params = {
type: 'signPersonalMessage',
- network: app.provider.name,
- chainId: `${app.provider.ethChainId}`,
+ network: Provider.selectedProvider.name,
+ chainId: `${Provider.selectedProvider.ethChainId}`,
};
try {
EventTracker.instance.trackEvent(MarketingEvents.signTxFail, params);
@@ -77,8 +78,8 @@ function getProviderWrapper(provider: ProviderInterface) {
async signTypedData(hdPath: string, typedData: TypedData): Promise {
const params = {
type: 'signTypedData',
- network: app.provider.name,
- chainId: `${app.provider.ethChainId}`,
+ network: Provider.selectedProvider.name,
+ chainId: `${Provider.selectedProvider.ethChainId}`,
};
try {
EventTracker.instance.trackEvent(MarketingEvents.signTxStart, params);
diff --git a/src/helpers/safe-load-balances.ts b/src/helpers/safe-load-balances.ts
index 61a0385c2..9e0af73ce 100644
--- a/src/helpers/safe-load-balances.ts
+++ b/src/helpers/safe-load-balances.ts
@@ -1,5 +1,5 @@
-import {app} from '@app/contexts';
import {Currencies} from '@app/models/currencies';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {Indexer} from '@app/services/indexer';
import {IndexerBalance} from '@app/types';
@@ -24,7 +24,7 @@ export const safeLoadBalances = async (wallets: string[]) => {
if (!balances) {
try {
- const rpcProvider = await getRpcProvider(app.provider);
+ const rpcProvider = await getRpcProvider(Provider.selectedProvider);
const balancesFromRpc = await Promise.all(
wallets.map(async w => {
let balance = '0x00';
diff --git a/src/helpers/whitelist.ts b/src/helpers/whitelist.ts
index 1938a43e9..c17b84efb 100644
--- a/src/helpers/whitelist.ts
+++ b/src/helpers/whitelist.ts
@@ -2,7 +2,7 @@ import {JSONRPCError, jsonrpcRequest} from '@haqq/shared-react-native';
import {app} from '@app/contexts';
import {DEBUG_VARS} from '@app/debug-vars';
-import {Provider} from '@app/models/provider';
+import {Provider, ProviderModel} from '@app/models/provider';
import {Token} from '@app/models/tokens';
import {VariablesString} from '@app/models/variables-string';
import {Wallet} from '@app/models/wallet';
@@ -61,19 +61,19 @@ export class Whitelist {
static async checkAddress(
address: string,
- provider?: Provider,
+ provider?: ProviderModel,
): Promise {
- provider = provider ?? app.provider;
+ provider = provider ?? Provider.selectedProvider;
const result = await Whitelist.verifyAddress(address, provider);
return !!result?.is_in_white_list;
}
static async verifyAddress(
address: string,
- provider?: Provider,
+ provider?: ProviderModel,
force = false,
) {
- provider = provider ?? app.provider;
+ provider = provider ?? Provider.selectedProvider;
const isWallet = Wallet.getAll().some(wallet =>
AddressUtils.equals(wallet.address, address),
);
diff --git a/src/hooks/nft/use-show-nft.tsx b/src/hooks/nft/use-show-nft.tsx
index be70f6f5d..601c843f0 100644
--- a/src/hooks/nft/use-show-nft.tsx
+++ b/src/hooks/nft/use-show-nft.tsx
@@ -2,14 +2,16 @@ import {useEffect, useState} from 'react';
import {autorun} from 'mobx';
-import {app} from '@app/contexts';
+import {Provider} from '@app/models/provider';
export const useShowNft = () => {
- const [showNft, setShowNft] = useState(app.provider.config.isNftEnabled);
+ const [showNft, setShowNft] = useState(
+ Provider.selectedProvider.config.isNftEnabled,
+ );
useEffect(() => {
const disposer = autorun(() => {
- setShowNft(app.provider.config.isNftEnabled);
+ setShowNft(Provider.selectedProvider.config.isNftEnabled);
});
return () => {
diff --git a/src/hooks/use-cosmos.ts b/src/hooks/use-cosmos.ts
index 65342ce45..02f7bcb12 100644
--- a/src/hooks/use-cosmos.ts
+++ b/src/hooks/use-cosmos.ts
@@ -1,10 +1,10 @@
import {useRef} from 'react';
-import {app} from '@app/contexts';
+import {Provider} from '@app/models/provider';
import {Cosmos} from '@app/services/cosmos';
export function useCosmos() {
- const cosmos = useRef(new Cosmos(app.provider!)).current;
+ const cosmos = useRef(new Cosmos(Provider.selectedProvider)).current;
return cosmos;
}
diff --git a/src/hooks/use-provider.ts b/src/hooks/use-provider.ts
deleted file mode 100644
index d77647e54..000000000
--- a/src/hooks/use-provider.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import {useEffect, useState} from 'react';
-
-import {app} from '@app/contexts';
-import {Events} from '@app/events';
-import {Provider} from '@app/models/provider';
-
-export function useProvider() {
- const [provider, setProvider] = useState(
- Provider.getById(app.providerId) as Provider,
- );
-
- useEffect(() => {
- const callback = () => {
- const p = Provider.getById(app.providerId);
- setProvider(p as Provider);
- };
-
- app.on(Events.onProviderChanged, callback);
- return () => {
- app.off(Events.onProviderChanged, callback);
- };
- }, []);
-
- return provider;
-}
diff --git a/src/hooks/use-sum-amount.ts b/src/hooks/use-sum-amount.ts
index d41382a47..08ba724e0 100644
--- a/src/hooks/use-sum-amount.ts
+++ b/src/hooks/use-sum-amount.ts
@@ -2,9 +2,9 @@ import {useEffect, useRef, useState} from 'react';
import validate from 'validate.js';
-import {app} from '@app/contexts';
import {getRemoteBalanceValue} from '@app/helpers/get-remote-balance-value';
import {I18N, getText} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
export const useSumAmount = (
@@ -52,7 +52,10 @@ export const useSumAmount = (
const newString = errorArray?.length > 0 ? errorArray.join(' ') : '';
setError(
newString
- .replace(app.provider.denom, maxAmountRef.current.getSymbol())
+ .replace(
+ Provider.selectedProvider.denom,
+ maxAmountRef.current.getSymbol(),
+ )
.replace(
maxAmountRef.current.toFloat(),
maxAmountRef.current.toBalanceString('auto'),
@@ -64,7 +67,7 @@ export const useSumAmount = (
);
}
}
- }, [changed, amount, minAmount, maxAmount, app.provider.denom]);
+ }, [changed, amount, minAmount, maxAmount, Provider.selectedProvider.denom]);
return {
isValid:
@@ -123,12 +126,12 @@ export const useSumAmount = (
precision ??
maxAmountRef.current?.getPrecission?.() ??
minAmountRef.current?.getPrecission?.() ??
- app.provider.decimals;
+ Provider.selectedProvider.decimals;
const denom =
maxAmountRef.current?.getSymbol?.() ??
minAmountRef.current?.getSymbol?.() ??
- app.provider.denom;
+ Provider.selectedProvider.denom;
const newAmount = new Balance(+textFormatted, decimals, denom);
if (typeof onChange === 'function') {
diff --git a/src/hooks/use-wallets-balance.ts b/src/hooks/use-wallets-balance.ts
index a938ce8fa..cad313521 100644
--- a/src/hooks/use-wallets-balance.ts
+++ b/src/hooks/use-wallets-balance.ts
@@ -2,6 +2,7 @@ import {useEffect, useState} from 'react';
import {app} from '@app/contexts';
import {Events} from '@app/events';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {BalanceData, HaqqEthereumAddress} from '@app/types';
@@ -40,7 +41,7 @@ export function useWalletsBalance(wallets: Wallet[]): WalletBalance {
useEffect(() => {
setBalance(getBalance(wallets));
- }, [app.provider.denom]);
+ }, [Provider.selectedProvider.denom]);
return balance;
}
diff --git a/src/models/currencies.ts b/src/models/currencies.ts
index 6659cb43d..adb6c681c 100644
--- a/src/models/currencies.ts
+++ b/src/models/currencies.ts
@@ -2,7 +2,6 @@ import {hashMessage} from '@walletconnect/utils';
import {makeAutoObservable, runInAction, when} from 'mobx';
import {makePersistable} from 'mobx-persist-store';
-import {app} from '@app/contexts';
import {Currency, CurrencyRate} from '@app/models/types';
import {VariablesDate} from '@app/models/variables-date';
import {Wallet} from '@app/models/wallet';
@@ -15,6 +14,8 @@ import {RatesResponse} from '@app/types';
import {createAsyncTask} from '@app/utils';
import {STORE_REHYDRATION_TIMEOUT_MS} from '@app/variables/common';
+import {Provider} from './provider';
+
// optimization for `convert()` method
const convertedCache = new Map();
class CurrenciesStore {
@@ -75,7 +76,8 @@ class CurrenciesStore {
...prev,
[tokenKey?.toLocaleLowerCase()]: {
amount: rate?.amount
- ? parseFloat(rate.amount) / 10 ** app.provider.decimals
+ ? parseFloat(rate.amount) /
+ 10 ** Provider.selectedProvider.decimals
: 0,
denom: rate?.denom,
} as CurrencyRate,
@@ -131,7 +133,8 @@ class CurrenciesStore {
});
const wallets = Wallet.getAllVisible();
const lastBalanceUpdates =
- VariablesDate.get(`indexer_${app.provider.cosmosChainId}`) || new Date(0);
+ VariablesDate.get(`indexer_${Provider.selectedProvider.cosmosChainId}`) ||
+ new Date(0);
let accounts = wallets.map(w => w.cosmosAddress);
const updates = await Indexer.instance.updates(
@@ -141,7 +144,7 @@ class CurrenciesStore {
);
VariablesDate.set(
- `indexer_${app.provider.cosmosChainId}`,
+ `indexer_${Provider.selectedProvider.cosmosChainId}`,
new Date(updates.last_update),
);
@@ -152,7 +155,7 @@ class CurrenciesStore {
convert = (balance: Balance): Balance => {
const currencyId = this.selectedCurrency?.toLocaleLowerCase();
const serialized = balance.toJsonString();
- const cacheKey = `${serialized}-${app.providerId}-${currencyId}-${this._prevRatesHash}`;
+ const cacheKey = `${serialized}-${Provider.selectedProviderId}-${currencyId}-${this._prevRatesHash}`;
const cached = convertedCache.get(cacheKey);
if (cached) {
diff --git a/src/models/provider/index.ts b/src/models/provider/index.ts
index c03904fe6..77a9f1644 100644
--- a/src/models/provider/index.ts
+++ b/src/models/provider/index.ts
@@ -1,3 +1,5 @@
export * from './provider';
export * from './provider-config';
+export * from './provider-config.model';
+export * from './provider.model';
export * from './provider.types';
diff --git a/src/models/provider/provider-config-model.ts b/src/models/provider/provider-config.model.ts
similarity index 100%
rename from src/models/provider/provider-config-model.ts
rename to src/models/provider/provider-config.model.ts
diff --git a/src/models/provider/provider-config.ts b/src/models/provider/provider-config.ts
index ba009a7fc..bbcfe2ba6 100644
--- a/src/models/provider/provider-config.ts
+++ b/src/models/provider/provider-config.ts
@@ -1,14 +1,14 @@
import {makeAutoObservable, runInAction} from 'mobx';
import {makePersistable} from 'mobx-persist-store';
-import {app} from '@app/contexts';
import {Indexer} from '@app/services/indexer';
import {ProviderConfig} from '@app/services/indexer/indexer.types';
import {storage} from '@app/services/mmkv';
import {ChainId} from '@app/types';
import {Provider} from './provider';
-import {ProviderConfigModel} from './provider-config-model';
+import {ProviderConfigModel} from './provider-config.model';
+import {ALL_NETWORKS_ID} from './provider.types';
class ProviderConfigStore {
private _data: Record = {};
@@ -24,10 +24,12 @@ class ProviderConfigStore {
init = async () => {
try {
- const config = await Indexer.instance.getProviderConfig();
- runInAction(() => {
- this._data[app.provider.ethChainId] = config;
- });
+ if (Provider.selectedProviderId !== ALL_NETWORKS_ID) {
+ const config = await Indexer.instance.getProviderConfig();
+ runInAction(() => {
+ this._data[Provider.selectedProvider.ethChainId] = config;
+ });
+ }
this.lazyLoadOtherConfig();
return Promise.resolve();
} catch (error) {
@@ -41,7 +43,9 @@ class ProviderConfigStore {
lazyLoadOtherConfig = async () => {
const providers = Provider.getAll().filter(
- p => p.ethChainId !== app.provider.ethChainId,
+ p =>
+ p.ethChainId !== Provider.selectedProvider.ethChainId &&
+ p.id !== ALL_NETWORKS_ID,
);
for await (const p of providers) {
diff --git a/src/models/provider/provider.model.ts b/src/models/provider/provider.model.ts
new file mode 100644
index 000000000..395d6c265
--- /dev/null
+++ b/src/models/provider/provider.model.ts
@@ -0,0 +1,163 @@
+import {app} from '@app/contexts';
+import {AddressUtils} from '@app/helpers/address-utils';
+import {removeLastSlash} from '@app/helpers/url';
+import {NetworkProvider} from '@app/services/backend';
+import {ISLM_DENOM} from '@app/variables/common';
+
+import {RemoteProviderConfig} from './provider-config';
+
+const HAQQ_BENCH_32_PREFIX = 'haqq';
+const EXPLORER_URL_TEMPLATES = {
+ ADDRESS: '{{address}}',
+ TOKEN_ID: '{{token_id}}',
+ TX: '{{tx_hash}}',
+};
+
+export class ProviderModel {
+ #logger;
+
+ constructor(public model: NetworkProvider) {
+ this.#logger = Logger.create(`NetworkProvider:${model.name}`, {
+ stringifyJson: true,
+ });
+ }
+
+ get ethChainIdHex() {
+ return '0x' + this.model.chain_id.toString(16);
+ }
+
+ get networkVersion() {
+ const splitted = this.cosmosChainId.split('-');
+ return splitted[1] ?? splitted.shift();
+ }
+
+ get id() {
+ return this.model.id;
+ }
+
+ get name() {
+ return this.model.name;
+ }
+
+ get icon() {
+ return this.model.icon;
+ }
+
+ get ethRpcEndpoint() {
+ return this.model.entry_point;
+ }
+
+ get ethChainId() {
+ return this.model.chain_id;
+ }
+
+ get cosmosChainId() {
+ if (!this.model.cosmos_chain_id) {
+ return this.model.chain_id.toString();
+ }
+ return this.model.cosmos_chain_id;
+ }
+
+ get cosmosRestEndpoint() {
+ return this.model.cosmos_entry_point;
+ }
+
+ get cosmosExplorer() {
+ return removeLastSlash(this.model.cosmos_explorer_url ?? '');
+ }
+
+ get explorer() {
+ return removeLastSlash(this.model.explorer_url ?? '');
+ }
+
+ get indexer() {
+ return this.model.indexer_url;
+ }
+
+ get isEditable() {
+ return app.isDeveloper ? true : false;
+ }
+
+ get decimals() {
+ return this.model.decimals;
+ }
+
+ get weiDenom() {
+ return this.model.wei_denom;
+ }
+
+ get denom() {
+ return this.model.denom;
+ }
+
+ get isHaqqNetwork() {
+ return this.model.denom.toLowerCase() === ISLM_DENOM.toLowerCase();
+ }
+
+ get bench32Prefix() {
+ return HAQQ_BENCH_32_PREFIX;
+ }
+
+ get coinName() {
+ return this.model.coin_name;
+ }
+
+ get config() {
+ return RemoteProviderConfig.getConfig(this.ethChainId);
+ }
+
+ toJSON() {
+ return {
+ ethChainIdHex: this.ethChainIdHex,
+ networkVersion: this.networkVersion,
+ ethRpcEndpoint: this.ethRpcEndpoint,
+ ethChainId: this.ethChainId,
+ cosmosChainId: this.cosmosChainId,
+ cosmosRestEndpoint: this.cosmosRestEndpoint,
+ explorer: this.explorer,
+ indexer: this.indexer,
+ isEditable: this.isEditable,
+ ...this.model,
+ };
+ }
+
+ getTxExplorerUrl(txHash: string) {
+ if (!txHash) {
+ return '';
+ }
+
+ if (txHash.startsWith('0x') || txHash.startsWith('0X')) {
+ return this.config.explorerTxUrl.replace(
+ EXPLORER_URL_TEMPLATES.TX,
+ txHash,
+ );
+ }
+
+ return this.config.explorerCosmosTxUrl.replace(
+ EXPLORER_URL_TEMPLATES.TX,
+ txHash,
+ );
+ }
+
+ getAddressExplorerUrl(address: string) {
+ return this.config.explorerAddressUrl.replace(
+ EXPLORER_URL_TEMPLATES.ADDRESS,
+ AddressUtils.toEth(address),
+ );
+ }
+
+ getCollectionExplorerUrl(address: string) {
+ return this.config.explorerTokenUrl.replace(
+ EXPLORER_URL_TEMPLATES.ADDRESS,
+ AddressUtils.toEth(address),
+ );
+ }
+
+ getTokenExplorerUrl(address: string, tokenId: string | number) {
+ return this.config.explorerTokenIdUrl
+ .replace(EXPLORER_URL_TEMPLATES.ADDRESS, AddressUtils.toEth(address))
+ .replace(EXPLORER_URL_TEMPLATES.TOKEN_ID, tokenId.toString());
+ }
+}
+
+export type ProviderKeys = keyof Omit;
diff --git a/src/models/provider/provider.ts b/src/models/provider/provider.ts
index 5466e0998..9d6c90480 100644
--- a/src/models/provider/provider.ts
+++ b/src/models/provider/provider.ts
@@ -1,59 +1,121 @@
-import {observable, runInAction} from 'mobx';
+import {makeAutoObservable, runInAction} from 'mobx';
+import {makePersistable} from 'mobx-persist-store';
+import Config from 'react-native-config';
import {app} from '@app/contexts';
-import {AddressUtils} from '@app/helpers/address-utils';
-import {removeLastSlash} from '@app/helpers/url';
-import {
- Backend,
- NetworkProvider,
- NetworkProviderResponse,
-} from '@app/services/backend';
+import {Events} from '@app/events';
+import {hideModal, showModal} from '@app/helpers';
+import {awaitForEventDone} from '@app/helpers/await-for-event-done';
+import {EthRpcEndpointAvailability} from '@app/helpers/eth-rpc-endpoint-availability';
+import {Backend, NetworkProvider} from '@app/services/backend';
import {storage} from '@app/services/mmkv';
+import {WalletConnect} from '@app/services/wallet-connect';
+import {ModalType} from '@app/types';
import {createAsyncTask, sleep} from '@app/utils';
-import {DEFAULT_PROVIDERS, ISLM_DENOM} from '@app/variables/common';
+import {
+ DEFAULT_PROVIDERS,
+ MAIN_NETWORK_ID,
+ STORE_REHYDRATION_TIMEOUT_MS,
+ TEST_NETWORK_ID,
+} from '@app/variables/common';
import {RemoteProviderConfig} from './provider-config';
-import {ProviderID} from './provider.types';
-
-import {VariablesString} from '../variables-string';
+import {ProviderModel} from './provider.model';
+import {ALL_NETWORKS_PROVIDER, ProviderID} from './provider.types';
-const HAQQ_BENCH_32_PREFIX = 'haqq';
-const EXPLORER_URL_TEMPLATES = {
- ADDRESS: '{{address}}',
- TOKEN_ID: '{{token_id}}',
- TX: '{{tx_hash}}',
-};
+import {Currencies} from '../currencies';
+import {Nft} from '../nft';
+import {Stories} from '../stories';
+import {Token} from '../tokens';
+import {Transaction} from '../transaction';
+import {Wallet} from '../wallet';
+import {WalletConnectSessionMetadata} from '../wallet-connect-session-metadata';
const logger = Logger.create('NetworkProvider:store', {
stringifyJson: true,
emodjiPrefix: '🟡',
});
-export class Provider {
- /****************************
- * static Providers store *
- ****************************/
- static MMKV_KEY = 'network-providers';
- static PROVIDER_REQUEST_TIMEOUT = 3000;
- static CACHED_VALUE: NetworkProviderResponse = JSON.parse(
- (storage.getItem(Provider.MMKV_KEY) as string) || '[]',
- );
+class ProviderStore {
+ awaitForInitialization() {
+ throw new Error('Method not implemented.');
+ }
+ private _defaultProviderId =
+ Config.ENVIRONMENT === 'production' || Config.ENVIRONMENT === 'distribution'
+ ? MAIN_NETWORK_ID
+ : TEST_NETWORK_ID;
+
+ _selectedProviderId: ProviderID = this._defaultProviderId;
+ _data: Record = {};
+
+ constructor() {
+ makeAutoObservable(this);
+ makePersistable(this, {
+ name: this.constructor.name,
+ properties: ['_selectedProviderId', '_data'],
+ storage: storage,
+ });
+ }
- static data: Record = observable(
- Provider.CACHED_VALUE.reduce(
- (prev, item) => ({
- ...prev,
- [item.id]: new Provider(item),
- }),
- {},
- ),
- );
+ get selectedProviderId() {
+ return this._selectedProviderId;
+ }
+
+ get selectedProvider() {
+ return this._data[this._selectedProviderId];
+ }
- static init(): Promise {
+ setSelectedProviderId = async (id: ProviderID) => {
+ runInAction(() => {
+ this._selectedProviderId = id;
+ });
+ try {
+ showModal(ModalType.loading);
+
+ Nft.clear();
+ Token.clear();
+ Transaction.clear();
+ Currencies.clear();
+
+ await RemoteProviderConfig.init();
+ await awaitForEventDone(Events.onSyncAppBalances);
+ await awaitForEventDone(Events.onRequestMarkup);
+ await Token.fetchTokens(true);
+ await Transaction.fetchLatestTransactions(Wallet.addressList(), true);
+ await Currencies.fetchCurrencies();
+
+ if (this.selectedProvider.config.isNftEnabled) {
+ await Nft.fetchNft();
+ }
+ this.fetchProviders();
+
+ await this.awaitForInitialization();
+ for (let session of WalletConnectSessionMetadata.getAll()) {
+ // sleep to avoid frequency requests to wallet connect relay server
+ await sleep(300);
+ await WalletConnect.instance.emitChainChange(
+ this.selectedProvider.ethChainId,
+ session.topic,
+ );
+ }
+ } finally {
+ hideModal(ModalType.loading);
+ app.emit(Events.onProviderChangedFinish);
+ }
+
+ await Promise.allSettled([
+ Currencies.setSelectedCurrency(),
+ awaitForEventDone(Events.onTesterModeChanged, app.isTesterMode),
+ EthRpcEndpointAvailability.checkEthRpcEndpointAvailability(),
+ Stories.fetch(true),
+ ]);
+ };
+
+ init = async (): Promise => {
return new Promise(async resolve => {
let resolved = false;
try {
- if (Provider.getAll().length) {
+ if (this.getAll().length) {
resolved = true;
resolve();
}
@@ -61,247 +123,96 @@ export class Provider {
} catch (err) {
logger.error('init', err);
logger.captureException(err, 'init');
- await sleep(Provider.PROVIDER_REQUEST_TIMEOUT);
- return Provider.init();
+ await sleep(STORE_REHYDRATION_TIMEOUT_MS);
+ return this.init();
}
if (!resolved) {
resolve();
}
});
- }
+ };
- static fetchProviders = createAsyncTask(async () => {
- let providers = await Backend.instance.providers();
- if (!providers?.length) {
- providers = DEFAULT_PROVIDERS;
- }
- await storage.setItem(Provider.MMKV_KEY, JSON.stringify(providers));
- const providerId = VariablesString.get('providerId');
+ fetchProviders = createAsyncTask(async () => {
+ const providers = [ALL_NETWORKS_PROVIDER];
+ const remoteProviders = await Backend.instance.providers();
- if (
- providerId &&
- !providers.some(
- item => item.id.toLowerCase() === providerId.toLowerCase(),
- )
- ) {
- VariablesString.remove('providerId');
+ if (remoteProviders?.length) {
+ providers.push(...remoteProviders);
+ } else {
+ providers.push(...DEFAULT_PROVIDERS);
}
const parsed = providers.reduce(
(prev, item) => ({
...prev,
- [item.id]: new Provider(item),
+ [item.id]: new ProviderModel(item),
}),
- {},
+ {} as Record,
);
runInAction(() => {
- Provider.data = parsed;
+ this._data = parsed;
+ if (!parsed[this._selectedProviderId]) {
+ this._selectedProviderId = this._defaultProviderId;
+ }
});
});
- static getById(id: string) {
- return Provider.data[id];
+ getById(id: string) {
+ return this._data[id];
}
- static getAll() {
- return Object.values(Provider.data);
+ getAll() {
+ return Object.values(this._data);
}
- static create(id: string, item: NetworkProvider | Provider) {
- if (item instanceof Provider) {
- Provider.data[id] = item;
+ create(id: string, item: NetworkProvider | ProviderModel) {
+ if (item instanceof ProviderModel) {
+ this._data[id] = item;
} else {
- Provider.data[id] = new Provider(item);
+ this._data[id] = new ProviderModel(item);
}
return id;
}
- static remove(id: string): boolean {
- if (Provider.data[id]) {
- delete Provider.data[id];
+ remove(id: string): boolean {
+ if (this._data[id]) {
+ delete this._data[id];
return true;
}
return false;
}
- static removeAll(): void {
- Provider.data = {};
+ removeAll(): void {
+ this._data = {};
}
- static getAllIds(): string[] {
- return Object.keys(Provider.data);
+ getAllIds(): string[] {
+ return Object.keys(this._data);
}
- static getByCosmosChainId(cosmosChainId: string) {
- return Object.values(Provider.data).find(
+ getByCosmosChainId(cosmosChainId: string) {
+ return Object.values(this._data).find(
provider => provider.model.cosmos_chain_id === cosmosChainId,
);
}
- static getByEthChainId(ethChainId: number | string) {
+ getByEthChainId(ethChainId: number | string) {
if (!ethChainId || Number.isNaN(Number(ethChainId))) {
return undefined;
}
- return Object.values(Provider.data).find(
+ return Object.values(this._data).find(
provider => provider.model.chain_id === Number(ethChainId),
);
}
- static getByChainIdHex(ethChainIdHex: string) {
+ getByChainIdHex(ethChainIdHex: string) {
if (!ethChainIdHex) {
return undefined;
}
const ethChainId = parseInt(ethChainIdHex, 16);
- return Provider.getByEthChainId(ethChainId);
- }
-
- /****************************
- * single Provider instance *
- ****************************/
- #logger;
-
- constructor(public model: NetworkProvider) {
- this.#logger = Logger.create(`NetworkProvider:${model.name}`, {
- stringifyJson: true,
- });
- }
-
- get ethChainIdHex() {
- return '0x' + this.model.chain_id.toString(16);
- }
-
- get networkVersion() {
- const splitted = this.cosmosChainId.split('-');
- return splitted[1] ?? splitted.shift();
- }
-
- get id() {
- return this.model.id;
- }
-
- get name() {
- return this.model.name;
- }
-
- get icon() {
- return this.model.icon;
- }
-
- get ethRpcEndpoint() {
- return this.model.entry_point;
- }
-
- get ethChainId() {
- return this.model.chain_id;
- }
-
- get cosmosChainId() {
- if (!this.model.cosmos_chain_id) {
- return this.model.chain_id.toString();
- }
- return this.model.cosmos_chain_id;
- }
-
- get cosmosRestEndpoint() {
- return this.model.cosmos_entry_point;
- }
-
- get cosmosExplorer() {
- return removeLastSlash(this.model.cosmos_explorer_url ?? '');
- }
-
- get explorer() {
- return removeLastSlash(this.model.explorer_url ?? '');
- }
-
- get indexer() {
- return this.model.indexer_url;
- }
-
- get isEditable() {
- return app.isDeveloper ? true : false;
- }
-
- get decimals() {
- return this.model.decimals;
- }
-
- get weiDenom() {
- return this.model.wei_denom;
- }
-
- get denom() {
- return this.model.denom;
- }
-
- get isHaqqNetwork() {
- return this.model.denom.toLowerCase() === ISLM_DENOM.toLowerCase();
- }
-
- get bench32Prefix() {
- return HAQQ_BENCH_32_PREFIX;
- }
-
- get coinName() {
- return this.model.coin_name;
- }
-
- get config() {
- return RemoteProviderConfig.getConfig(this.ethChainId);
- }
-
- toJSON() {
- return {
- ethChainIdHex: this.ethChainIdHex,
- networkVersion: this.networkVersion,
- ethRpcEndpoint: this.ethRpcEndpoint,
- ethChainId: this.ethChainId,
- cosmosChainId: this.cosmosChainId,
- cosmosRestEndpoint: this.cosmosRestEndpoint,
- explorer: this.explorer,
- indexer: this.indexer,
- isEditable: this.isEditable,
- ...this.model,
- };
- }
-
- getTxExplorerUrl(txHash: string) {
- if (!txHash) {
- return '';
- }
-
- if (txHash.startsWith('0x') || txHash.startsWith('0X')) {
- return this.config.explorerTxUrl.replace(
- EXPLORER_URL_TEMPLATES.TX,
- txHash,
- );
- }
-
- return this.config.explorerCosmosTxUrl.replace(
- EXPLORER_URL_TEMPLATES.TX,
- txHash,
- );
- }
-
- getAddressExplorerUrl(address: string) {
- return this.config.explorerAddressUrl.replace(
- EXPLORER_URL_TEMPLATES.ADDRESS,
- AddressUtils.toEth(address),
- );
- }
-
- getCollectionExplorerUrl(address: string) {
- return this.config.explorerTokenUrl.replace(
- EXPLORER_URL_TEMPLATES.ADDRESS,
- AddressUtils.toEth(address),
- );
- }
-
- getTokenExplorerUrl(address: string, tokenId: string | number) {
- return this.config.explorerTokenIdUrl
- .replace(EXPLORER_URL_TEMPLATES.ADDRESS, AddressUtils.toEth(address))
- .replace(EXPLORER_URL_TEMPLATES.TOKEN_ID, tokenId.toString());
+ return this.getByEthChainId(ethChainId);
}
}
-export type ProviderKeys = keyof Omit;
+const instance = new ProviderStore();
+export {instance as Provider};
diff --git a/src/models/provider/provider.types.ts b/src/models/provider/provider.types.ts
index 97a715ee4..a4f37e854 100644
--- a/src/models/provider/provider.types.ts
+++ b/src/models/provider/provider.types.ts
@@ -1 +1,29 @@
+import {
+ NetworkProvider,
+ NetworkProviderStage,
+ NetworkProviderStatus,
+ NetworkProviderTypes,
+} from '@app/services/backend';
+
export type ProviderID = string;
+
+export const ALL_NETWORKS_ID = 'all_networks';
+export const ALL_NETWORKS_PROVIDER: NetworkProvider = {
+ id: ALL_NETWORKS_ID,
+ name: 'All Networks',
+ icon: '',
+ chain_id: -1,
+ coin_name: 'All Network',
+ cosmos_chain_id: undefined,
+ cosmos_entry_point: undefined,
+ cosmos_explorer_url: undefined,
+ decimals: 0,
+ denom: '',
+ entry_point: 'https://rpc.eth.haqq.network/',
+ explorer_url: undefined,
+ indexer_url: 'https://proxy.indexer.haqq.network',
+ network_type: NetworkProviderTypes.EVM,
+ stage: NetworkProviderStage.MAINNET,
+ status: NetworkProviderStatus.PUBLISHED,
+ wei_denom: '',
+};
diff --git a/src/models/tokens.ts b/src/models/tokens.ts
index a9ca04f46..69e1b02f5 100644
--- a/src/models/tokens.ts
+++ b/src/models/tokens.ts
@@ -23,6 +23,8 @@ import {
import {RPCMessage} from '@app/types/rpc';
import {createAsyncTask} from '@app/utils';
+import {Provider} from './provider';
+
class TokensStore implements MobXStore {
/**
* All tokens available for all wallets with commulative value
@@ -254,8 +256,8 @@ class TokensStore implements MobXStore {
contract_updated_at: contract.updated_at,
value: new Balance(
t.value,
- contract.decimals ?? app.provider.decimals,
- contract.symbol ?? app.provider.denom,
+ contract.decimals ?? Provider.selectedProvider.decimals,
+ contract.symbol ?? Provider.selectedProvider.denom,
),
decimals: contract.decimals,
is_erc20: contract.is_erc20,
@@ -306,19 +308,19 @@ class TokensStore implements MobXStore {
contract_created_at: '',
contract_updated_at: '',
value: balance,
- decimals: app.provider.decimals,
+ decimals: Provider.selectedProvider.decimals,
is_erc20: false,
is_erc721: false,
is_erc1155: false,
is_in_white_list: true,
- name: app.provider.coinName,
- symbol: app.provider.denom,
+ name: Provider.selectedProvider.coinName,
+ symbol: Provider.selectedProvider.denom,
created_at: '',
updated_at: '',
- image: app.provider.isHaqqNetwork
+ image: Provider.selectedProvider.isHaqqNetwork
? require('@assets/images/islm_icon.png')
: {
- uri: app.provider.icon,
+ uri: Provider.selectedProvider.icon,
},
};
};
@@ -330,18 +332,18 @@ class TokensStore implements MobXStore {
address_type: AddressType.contract,
is_skip_eth_tx: false,
min_input_amount: '18',
- decimals: app.provider.decimals,
+ decimals: Provider.selectedProvider.decimals,
is_erc20: false,
is_erc721: false,
is_erc1155: false,
is_in_white_list: true,
- name: app.provider.coinName,
- symbol: app.provider.denom,
+ name: Provider.selectedProvider.coinName,
+ symbol: Provider.selectedProvider.denom,
created_at: '',
updated_at: '',
- icon: app.provider.isHaqqNetwork
+ icon: Provider.selectedProvider.isHaqqNetwork
? require('@assets/images/islm_icon.png')
- : app.provider.icon,
+ : Provider.selectedProvider.icon,
};
};
@@ -368,8 +370,8 @@ class TokensStore implements MobXStore {
contract_updated_at: contractFromCache.updated_at,
value: new Balance(
token.value,
- contractFromCache.decimals || app.provider.decimals,
- contractFromCache.symbol || app.provider.denom,
+ contractFromCache.decimals || Provider.selectedProvider.decimals,
+ contractFromCache.symbol || Provider.selectedProvider.denom,
),
decimals: contractFromCache.decimals,
is_erc20: contractFromCache.is_erc20,
diff --git a/src/models/transaction.ts b/src/models/transaction.ts
index df3a8744c..6a76950e3 100644
--- a/src/models/transaction.ts
+++ b/src/models/transaction.ts
@@ -3,8 +3,6 @@ import {makeAutoObservable, runInAction, when} from 'mobx';
import {isHydrated} from 'mobx-persist-store';
import {IconProps} from '@app/components/ui';
-import {app} from '@app/contexts';
-import {Events} from '@app/events';
import {parseTransaction} from '@app/helpers/indexer-transaction-utils';
import {TransactionRealmObject} from '@app/models/realm-object-for-migration';
import {Socket} from '@app/models/socket';
@@ -14,6 +12,7 @@ import {Indexer} from '@app/services/indexer';
import {IndexerTransaction, IndexerTxParsedTokenInfo} from '@app/types';
import {RPCMessage, RPCObserver} from '@app/types/rpc';
+import {Provider} from './provider';
import {Token} from './tokens';
export enum TransactionStatus {
@@ -60,11 +59,6 @@ class TransactionStore implements RPCObserver {
() => Socket.lastMessage.type === 'transaction',
() => this.onMessage(Socket.lastMessage),
);
-
- app.on(Events.onProviderChanged, () => {
- this.removeAll();
- this.fetchLatestTransactions(Wallet.addressList());
- });
}
get isHydrated() {
@@ -188,7 +182,7 @@ class TransactionStore implements RPCObserver {
) => {
try {
const accountHash = hashMessage(accounts.join(''));
- const cacheKey: CacheKey = `${app.providerId}${accountHash}:${blockNumber}`;
+ const cacheKey: CacheKey = `${Provider.selectedProviderId}${accountHash}:${blockNumber}`;
runInAction(() => {
this._isLoading = true;
@@ -232,7 +226,7 @@ class TransactionStore implements RPCObserver {
return;
}
- const result = message.data.txs;
+ const result = message.data.txs || message.data.transactions || [];
const accounts = Wallet.addressList();
const parsed = result
.map(tx => parseTransaction(tx, accounts))
diff --git a/src/route-types.ts b/src/route-types.ts
index 3fece77ce..6efbb3c20 100644
--- a/src/route-types.ts
+++ b/src/route-types.ts
@@ -7,7 +7,7 @@ import {SessionTypes} from '@walletconnect/types';
import {TotalValueTabNames} from '@app/components/total-value-info';
import {AwaitValue} from '@app/helpers/await-for-value';
import {NftCollection, NftItem} from '@app/models/nft';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {Balance} from '@app/services/balance';
import {SssProviders} from '@app/services/provider-sss';
@@ -292,7 +292,7 @@ export type SettingsStackParamList = HomeStackParamList & {
screen: SettingsStackRoutes.SettingsProviderForm;
params: {
id?: string;
- data?: Partial;
+ data?: Partial;
};
};
[SettingsStackRoutes.SettingsAccounts]: undefined;
@@ -320,7 +320,7 @@ export type ProvidersStackParamList = {
[ProvidersStackRoutes.SettingsProviders]: undefined;
[ProvidersStackRoutes.SettingsProviderForm]: {
id?: string;
- data?: Partial;
+ data?: Partial;
};
};
diff --git a/src/screens/HomeStack/BrowserStack/web3-browser.tsx b/src/screens/HomeStack/BrowserStack/web3-browser.tsx
index 6d0f533b5..3d52778fd 100644
--- a/src/screens/HomeStack/BrowserStack/web3-browser.tsx
+++ b/src/screens/HomeStack/BrowserStack/web3-browser.tsx
@@ -1,7 +1,8 @@
-import React, {memo, useCallback, useMemo, useRef, useState} from 'react';
+import React, {useCallback, useRef, useState} from 'react';
import Clipboard from '@react-native-clipboard/clipboard';
import {useFocusEffect} from '@react-navigation/native';
+import {observer} from 'mobx-react';
import {Share} from 'react-native';
import WebView from 'react-native-webview';
@@ -30,7 +31,7 @@ import {Web3BrowserSession} from '@app/models/web3-browser-session';
import {BrowserStackParamList, BrowserStackRoutes} from '@app/route-types';
import {sendNotification} from '@app/services';
-export const Web3BrowserScreen = memo(() => {
+export const Web3BrowserScreen = observer(() => {
const [focused, setFocused] = useState(false);
const {url, popup} = useTypedRoute<
BrowserStackParamList,
@@ -48,7 +49,6 @@ export const Web3BrowserScreen = memo(() => {
const helper = useRef(
new Web3BrowserHelper({webviewRef, initialUrl: url}),
);
- const userProvider = useMemo(() => Provider.getById(app.providerId), []);
const [isLoading, setLoading] = useState(true);
const onPressHeaderUrl = useCallback(
({}: Web3BrowserPressHeaderEvent) => {
@@ -243,7 +243,6 @@ export const Web3BrowserScreen = memo(() => {
sessions={sessions}
bookmarks={bookmarks}
showActionMenu={showActionMenu}
- userProvider={userProvider!}
focused={focused}
onPressClose={onPressClose}
onPressHeaderUrl={onPressHeaderUrl}
diff --git a/src/screens/HomeStack/GovernanceStack/ProposalDepositStack/proposal-deposit-preview.tsx b/src/screens/HomeStack/GovernanceStack/ProposalDepositStack/proposal-deposit-preview.tsx
index a32a5364c..a20bc0cb3 100644
--- a/src/screens/HomeStack/GovernanceStack/ProposalDepositStack/proposal-deposit-preview.tsx
+++ b/src/screens/HomeStack/GovernanceStack/ProposalDepositStack/proposal-deposit-preview.tsx
@@ -3,9 +3,9 @@ import React, {useCallback, useState} from 'react';
import {observer} from 'mobx-react';
import {ProposalDepositPreview} from '@app/components/proposal-deposit-preview';
-import {app} from '@app/contexts';
import {getProviderInstanceForWallet} from '@app/helpers/provider-instance';
import {useTypedNavigation, useTypedRoute} from '@app/hooks';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {
ProposalDepositStackParamList,
@@ -30,7 +30,7 @@ export const ProposalDepositPreviewScreen = observer(() => {
try {
setDisabled(true);
- const cosmos = new Cosmos(app.provider!);
+ const cosmos = new Cosmos(Provider.selectedProvider);
const provider = await getProviderInstanceForWallet(wallet);
const resp = await cosmos.deposit(
provider,
diff --git a/src/screens/HomeStack/HomeFeedStack/transaction-detail.tsx b/src/screens/HomeStack/HomeFeedStack/transaction-detail.tsx
index ccf6d38d0..cb8c6a933 100644
--- a/src/screens/HomeStack/HomeFeedStack/transaction-detail.tsx
+++ b/src/screens/HomeStack/HomeFeedStack/transaction-detail.tsx
@@ -2,6 +2,7 @@ import React, {useCallback, useEffect, useMemo} from 'react';
import Clipboard from '@react-native-clipboard/clipboard';
import {format} from 'date-fns';
+import {observer} from 'mobx-react';
import {TransactionDetail} from '@app/components/transaction-detail';
import {Loading} from '@app/components/ui';
@@ -10,19 +11,19 @@ import {shortAddress} from '@app/helpers/short-address';
import {useTypedNavigation, useTypedRoute} from '@app/hooks';
import {useTransaction} from '@app/hooks/use-transaction';
import {I18N} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {HomeStackParamList, HomeStackRoutes} from '@app/route-types';
import {sendNotification} from '@app/services';
import {Balance} from '@app/services/balance';
import {openInAppBrowser, splitAddress} from '@app/utils';
-export const TransactionDetailScreen = () => {
+export const TransactionDetailScreen = observer(() => {
const navigation = useTypedNavigation();
const route = useTypedRoute<
HomeStackParamList,
HomeStackRoutes.TransactionDetail
>();
const tx = useTransaction(route.params.txId);
- const provider = useMemo(() => app.provider, []);
const timestamp = useMemo(
() => format(new Date(tx.ts), 'dd MMMM yyyy, HH:mm'),
@@ -41,7 +42,7 @@ export const TransactionDetailScreen = () => {
const total = useMemo(() => Balance.Empty, []);
const onPressInfo = useCallback(async () => {
- const url = app.provider.getTxExplorerUrl(tx?.hash);
+ const url = Provider.selectedProvider.getTxExplorerUrl(tx?.hash);
if (url) {
openInAppBrowser(url);
}
@@ -57,7 +58,7 @@ export const TransactionDetailScreen = () => {
}, [navigation]);
const onPressSpenderAddress = useCallback((address: string) => {
- const url = app.provider.getAddressExplorerUrl(address);
+ const url = Provider.selectedProvider.getAddressExplorerUrl(address);
return openInAppBrowser(url);
}, []);
@@ -80,7 +81,7 @@ export const TransactionDetailScreen = () => {
return (
{
onPressSpenderAddress={onPressSpenderAddress}
/>
);
-};
+});
diff --git a/src/screens/HomeStack/NftStack/nft-item-details.tsx b/src/screens/HomeStack/NftStack/nft-item-details.tsx
index 513fc5ce2..edb8cc5b8 100644
--- a/src/screens/HomeStack/NftStack/nft-item-details.tsx
+++ b/src/screens/HomeStack/NftStack/nft-item-details.tsx
@@ -1,7 +1,9 @@
-import React, {memo, useCallback} from 'react';
+import React, {useCallback} from 'react';
+
+import {observer} from 'mobx-react';
-import {app} from '@app/contexts';
import {useTypedNavigation, useTypedRoute} from '@app/hooks';
+import {Provider} from '@app/models/provider';
import {
HomeStackRoutes,
NftStackParamList,
@@ -11,7 +13,7 @@ import {openInAppBrowser} from '@app/utils';
import {NftItemDetails} from './components/nft-item-details/nft-item-details';
-export const NftItemDetailsScreen = memo(() => {
+export const NftItemDetailsScreen = observer(() => {
const navigation = useTypedNavigation();
const {params} = useTypedRoute<
NftStackParamList,
@@ -28,7 +30,7 @@ export const NftItemDetailsScreen = memo(() => {
}, [params.item, navigation]);
const onPressExplorer = useCallback(() => {
- const url = app.provider.getTokenExplorerUrl(
+ const url = Provider.selectedProvider.getTokenExplorerUrl(
params.item.contract,
params.item.tokenId,
);
diff --git a/src/screens/HomeStack/ProvidersStack/settings-provider-edit.tsx b/src/screens/HomeStack/ProvidersStack/settings-provider-edit.tsx
index 30ffffc04..62a67c468 100644
--- a/src/screens/HomeStack/ProvidersStack/settings-provider-edit.tsx
+++ b/src/screens/HomeStack/ProvidersStack/settings-provider-edit.tsx
@@ -1,14 +1,14 @@
-import React, {memo, useCallback, useMemo} from 'react';
+import React, {useCallback, useMemo} from 'react';
+import {observer} from 'mobx-react';
import {Alert} from 'react-native';
import {SettingsProviderEdit} from '@app/components/settings/settings-providers/settings-provider-edit';
-import {app} from '@app/contexts';
import {useTypedNavigation, useTypedRoute} from '@app/hooks';
-import {Provider} from '@app/models/provider';
+import {Provider, ProviderModel} from '@app/models/provider';
import {ProvidersStackParamList, ProvidersStackRoutes} from '@app/route-types';
-export const SettingsProviderEditScreen = memo(() => {
+export const SettingsProviderEditScreen = observer(() => {
const {goBack, setParams} = useTypedNavigation();
const route = useTypedRoute<
ProvidersStackParamList,
@@ -20,20 +20,12 @@ export const SettingsProviderEditScreen = memo(() => {
);
const onSubmit = useCallback(
- (_: Partial) => {
+ (_: Partial) => {
// TODO:
Alert.alert(
'This feature for developer',
'Edit providers not yet implemented',
);
- // if (provider) {
- // provider.update(data);
- // } else {
- // let id = Provider.create(data);
- // setParams({
- // id,
- // });
- // }
},
[provider, setParams],
);
@@ -47,7 +39,7 @@ export const SettingsProviderEditScreen = memo(() => {
const onSelect = useCallback(() => {
if (provider) {
- app.providerId = provider.id;
+ Provider.setSelectedProviderId(provider.id);
}
goBack();
}, [goBack, provider]);
diff --git a/src/screens/HomeStack/ProvidersStack/settings-providers.tsx b/src/screens/HomeStack/ProvidersStack/settings-providers.tsx
index 18bf36a1c..51141f986 100644
--- a/src/screens/HomeStack/ProvidersStack/settings-providers.tsx
+++ b/src/screens/HomeStack/ProvidersStack/settings-providers.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useEffect, useMemo, useState} from 'react';
+import React, {useCallback, useMemo} from 'react';
import {observer} from 'mobx-react';
@@ -6,7 +6,6 @@ import {Color} from '@app/colors';
import {SettingsProviders} from '@app/components/settings/settings-providers';
import {CustomHeader} from '@app/components/ui';
import {app} from '@app/contexts';
-import {Events} from '@app/events';
import {useTypedNavigation} from '@app/hooks';
import {I18N} from '@app/i18n';
import {Provider} from '@app/models/provider';
@@ -15,19 +14,6 @@ import {ProvidersStackParamList, ProvidersStackRoutes} from '@app/route-types';
export const SettingsProvidersScreen = observer(() => {
const navigation = useTypedNavigation();
const providers = Provider.getAll();
- const [providerId, setProviderId] = useState(app.providerId);
-
- useEffect(() => {
- const callback = () => {
- setProviderId(app.providerId);
- };
-
- app.on(Events.onProviderChanged, callback);
-
- return () => {
- app.off(Events.onProviderChanged, callback);
- };
- }, []);
const onSelectProvider = useCallback(
(pid: string) => {
@@ -70,7 +56,7 @@ export const SettingsProvidersScreen = observer(() => {
{header}
>
diff --git a/src/screens/HomeStack/SettingsStack/settings-test.tsx b/src/screens/HomeStack/SettingsStack/settings-test.tsx
index 8ff9fb11b..f7d7da8ea 100644
--- a/src/screens/HomeStack/SettingsStack/settings-test.tsx
+++ b/src/screens/HomeStack/SettingsStack/settings-test.tsx
@@ -204,7 +204,7 @@ const getTestModals = (): TestModals => {
},
notEnoughGas: {
currentAmount: app.getBalanceData(firstWalletAddress).available,
- gasLimit: MIN_GAS_LIMIT,
+ gasLimit: new Balance(MIN_GAS_LIMIT, 0),
onClose: () => logger.log('notEnoughGas closed'),
},
viewErrorDetails: {
@@ -727,7 +727,7 @@ export const SettingsTestScreen = observer(() => {
wallets: Wallet.getAllVisible(),
});
const providers = Provider.getAll();
- const initialProviderId = app.provider.id;
+ const initialProviderId = Provider.selectedProviderId;
const providerId = await awaitForProvider({
providers,
initialProviderId: initialProviderId!,
diff --git a/src/screens/HomeStack/StakingDelegateStack/staking-delegate-form.tsx b/src/screens/HomeStack/StakingDelegateStack/staking-delegate-form.tsx
index 2b81d6010..aee224a43 100644
--- a/src/screens/HomeStack/StakingDelegateStack/staking-delegate-form.tsx
+++ b/src/screens/HomeStack/StakingDelegateStack/staking-delegate-form.tsx
@@ -5,12 +5,12 @@ import _ from 'lodash';
import {observer} from 'mobx-react';
import {StakingDelegateForm} from '@app/components/staking-delegate-form';
-import {app} from '@app/contexts';
import {getProviderInstanceForWallet} from '@app/helpers';
import {AddressUtils} from '@app/helpers/address-utils';
import {useTypedNavigation, useTypedRoute} from '@app/hooks';
import {useLayoutEffectAsync} from '@app/hooks/use-effect-async';
import {useWalletsBalance} from '@app/hooks/use-wallets-balance';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {
StakingDelegateStackParamList,
@@ -41,7 +41,7 @@ export const StakingDelegateFormScreen = observer(() => {
const setFee = useCallback(
_.debounce(async (amount?: string) => {
- const cosmos = new Cosmos(app.provider);
+ const cosmos = new Cosmos(Provider.selectedProvider);
const instance = await getProviderInstanceForWallet(wallet!, true);
try {
diff --git a/src/screens/HomeStack/TransactionStack/transaction-confirmation.tsx b/src/screens/HomeStack/TransactionStack/transaction-confirmation.tsx
index 8e095d802..5fc1338f0 100644
--- a/src/screens/HomeStack/TransactionStack/transaction-confirmation.tsx
+++ b/src/screens/HomeStack/TransactionStack/transaction-confirmation.tsx
@@ -16,6 +16,7 @@ import {useWalletsBalance} from '@app/hooks/use-wallets-balance';
import {I18N} from '@app/i18n';
import {Contact} from '@app/models/contact';
import {Fee} from '@app/models/fee';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {
TransactionStackParamList,
@@ -124,7 +125,7 @@ export const TransactionConfirmationScreen = observer(() => {
walletType: wallet.type,
token,
contact,
- provider: app.provider.name,
+ provider: Provider.selectedProvider.name,
});
const err = e as EthSignErrorDataDetails;
diff --git a/src/screens/HomeStack/TransactionStack/transaction-nft-confirmation.tsx b/src/screens/HomeStack/TransactionStack/transaction-nft-confirmation.tsx
index 74306eaa0..8bdc4d38a 100644
--- a/src/screens/HomeStack/TransactionStack/transaction-nft-confirmation.tsx
+++ b/src/screens/HomeStack/TransactionStack/transaction-nft-confirmation.tsx
@@ -17,6 +17,7 @@ import {I18N} from '@app/i18n';
import {Contact} from '@app/models/contact';
import {Fee} from '@app/models/fee';
import {ContractType} from '@app/models/nft';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {
TransactionStackParamList,
@@ -152,7 +153,7 @@ export const TransactionNftConfirmationScreen = observer(() => {
id: errorId,
walletType: wallet.type,
contact,
- provider: app.provider.name,
+ provider: Provider.selectedProvider.name,
});
const err = e as EthSignErrorDataDetails;
diff --git a/src/screens/HomeStack/TransactionStack/transaction-sum.tsx b/src/screens/HomeStack/TransactionStack/transaction-sum.tsx
index e74e80c84..bf717b2d4 100644
--- a/src/screens/HomeStack/TransactionStack/transaction-sum.tsx
+++ b/src/screens/HomeStack/TransactionStack/transaction-sum.tsx
@@ -1,11 +1,11 @@
-import React, {memo, useCallback, useEffect, useMemo, useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
+
+import {observer} from 'mobx-react';
import {TransactionSum} from '@app/components/transaction-sum';
import {app} from '@app/contexts';
-import {Events} from '@app/events';
import {showModal} from '@app/helpers';
import {AddressUtils} from '@app/helpers/address-utils';
-import {awaitForEventDone} from '@app/helpers/await-for-event-done';
import {awaitForProvider} from '@app/helpers/await-for-provider';
import {useTypedNavigation, useTypedRoute} from '@app/hooks';
import {useAndroidBackHandler} from '@app/hooks/use-android-back-handler';
@@ -25,7 +25,7 @@ import {HapticEffects, vibrate} from '@app/services/haptic';
import {ModalType} from '@app/types';
import {generateUUID} from '@app/utils';
-export const TransactionSumScreen = memo(() => {
+export const TransactionSumScreen = observer(() => {
const navigation = useTypedNavigation();
useAndroidBackHandler(() => {
navigation.goBack();
@@ -135,11 +135,10 @@ export const TransactionSumScreen = memo(() => {
const onNetworkPress = useCallback(async () => {
const providerId = await awaitForProvider({
providers: Provider.getAll(),
- initialProviderId: app.providerId!,
+ initialProviderId: Provider.selectedProviderId,
title: I18N.networks,
});
- app.providerId = providerId;
- await awaitForEventDone(Events.onProviderChanged);
+ Provider.setSelectedProviderId(providerId);
navigation.goBack();
}, [navigation]);
diff --git a/src/screens/RootStack/index.tsx b/src/screens/RootStack/index.tsx
index 02ee8fbd3..b1efedc8f 100644
--- a/src/screens/RootStack/index.tsx
+++ b/src/screens/RootStack/index.tsx
@@ -1,10 +1,8 @@
-import React, {memo, useMemo} from 'react';
+import React, {memo} from 'react';
import {StyleSheet, View} from 'react-native';
import {ModalProvider} from '@app/components/modal-provider';
-import {getWelcomeScreen} from '@app/helpers/get-welcome-screen';
-import {themeUpdaterHOC} from '@app/helpers/theme-updater-hoc';
import {HomeStack} from '@app/screens/HomeStack';
import {ModalsScreen} from '@app/screens/modals-screen';
import {WelcomeStack} from '@app/screens/WelcomeStack';
@@ -16,27 +14,17 @@ type Props = {
};
const RootStack = memo(({onboarded, isPinReseted, isReady}: Props) => {
- const initialRouteName = useMemo(() => {
- return getWelcomeScreen();
- }, []);
-
- const CurrentStack = useMemo(() => {
- if (onboarded && !isPinReseted) {
- return ;
- }
-
- return ;
- }, [onboarded, isPinReseted, initialRouteName]);
-
- const WrappedModals = useMemo(() => {
- const Modals = themeUpdaterHOC(ModalsScreen);
- return ;
- }, [isReady]);
+ if (!isReady) {
+ return ;
+ }
return (
- {CurrentStack}
- {WrappedModals}
+ {onboarded && !isPinReseted && }
+ {!(onboarded && !isPinReseted) && }
+
+
+
);
});
diff --git a/src/screens/SwapStack/swap-screen.tsx b/src/screens/SwapStack/swap-screen.tsx
index 900d69460..934a356a5 100644
--- a/src/screens/SwapStack/swap-screen.tsx
+++ b/src/screens/SwapStack/swap-screen.tsx
@@ -174,17 +174,19 @@ export const SwapScreen = observer(() => {
);
const isWrapTx = useMemo(
() =>
- tokenIn?.symbol?.toLowerCase() === app.provider.denom?.toLowerCase() &&
+ tokenIn?.symbol?.toLowerCase() ===
+ Provider.selectedProvider.denom?.toLowerCase() &&
tokenOut?.symbol?.toLowerCase() ===
- app.provider.config.wethSymbol?.toLowerCase(),
- [tokenIn, tokenOut, app.provider.denom],
+ Provider.selectedProvider.config.wethSymbol?.toLowerCase(),
+ [tokenIn, tokenOut, Provider.selectedProvider.denom],
);
const isUnwrapTx = useMemo(
() =>
tokenIn?.symbol?.toLowerCase() ===
- app.provider.config.wethSymbol?.toLowerCase() &&
- tokenOut?.symbol?.toLowerCase() === app.provider.denom?.toLowerCase(),
- [tokenIn, tokenOut, app.provider.denom],
+ Provider.selectedProvider.config.wethSymbol?.toLowerCase() &&
+ tokenOut?.symbol?.toLowerCase() ===
+ Provider.selectedProvider.denom?.toLowerCase(),
+ [tokenIn, tokenOut, Provider.selectedProvider.denom],
);
const t0Current = useMemo(() => {
if (!amountsIn.amount || !tokenIn?.decimals) {
@@ -214,8 +216,8 @@ export const SwapScreen = observer(() => {
return Balance.Empty;
}
- if (tokenIn.symbol === app.provider.denom) {
- logger.log(`t0 available: currency ${app.provider.denom}`);
+ if (tokenIn.symbol === Provider.selectedProvider.denom) {
+ logger.log(`t0 available: currency ${Provider.selectedProvider.denom}`);
return app.getAvailableBalance(currentWallet.address);
}
@@ -229,14 +231,14 @@ export const SwapScreen = observer(() => {
logger.log('t0 available: tokenData is empty, symbol: ', tokenIn.symbol);
return new Balance(0, 0, tokenIn.symbol!);
- }, [currentWallet, tokenIn, Token.tokens, app.provider.denom]);
+ }, [currentWallet, tokenIn, Token.tokens, Provider.selectedProvider.denom]);
const t1Available = useMemo(() => {
if (!tokenOut) {
return Balance.Empty;
}
- if (tokenOut.symbol === app.provider.denom) {
+ if (tokenOut.symbol === Provider.selectedProvider.denom) {
return app.getAvailableBalance(currentWallet.address);
}
@@ -248,7 +250,7 @@ export const SwapScreen = observer(() => {
}
return new Balance(0, 0, tokenOut.symbol!);
- }, [currentWallet, tokenOut, app.provider.denom]);
+ }, [currentWallet, tokenOut, Provider.selectedProvider.denom]);
const estimate = async (force = false) => {
const errCtx: Record = {};
@@ -331,7 +333,7 @@ export const SwapScreen = observer(() => {
});
errCtx['⭕️sushi-pool-estimate-response'] = response;
- if (tokenIn?.symbol === app.provider.denom) {
+ if (tokenIn?.symbol === Provider.selectedProvider.denom) {
response.need_approve = false;
}
response.s_price_impact = (
@@ -489,7 +491,7 @@ export const SwapScreen = observer(() => {
{
- if (t.symbol === app.provider.denom) {
+ if (t.symbol === Provider.selectedProvider.denom) {
return {
...t,
value: app.getAvailableBalance(value?.wallet?.address),
@@ -570,9 +572,9 @@ export const SwapScreen = observer(() => {
?.value;
const availableIslm = app.getAvailableBalance(wallet);
- const symbol = t0.getSymbol() || app.provider.denom;
- const isNativeCurrency = symbol === app.provider.denom;
- const decimals = t0.getPrecission() || app.provider.decimals;
+ const symbol = t0.getSymbol() || Provider.selectedProvider.denom;
+ const isNativeCurrency = symbol === Provider.selectedProvider.denom;
+ const decimals = t0.getPrecission() || Provider.selectedProvider.decimals;
const zeroBalance = new Balance('0x0', decimals, symbol);
const value = new Balance(
(isNativeCurrency ? availableIslm : tokenValue) || zeroBalance,
@@ -694,14 +696,14 @@ export const SwapScreen = observer(() => {
setSwapInProgress(() => true);
const swapRouter = new ethers.Contract(
- app.provider.config.swapRouterV3,
+ Provider.selectedProvider.config.swapRouterV3,
V3SWAPROUTER_ABI,
);
const deadline =
Math.floor(Date.now() / 1000) + 60 * parseFloat(swapSettings.deadline);
- const tokenInIsISLM = tokenIn?.symbol === app.provider.denom;
+ const tokenInIsISLM = tokenIn?.symbol === Provider.selectedProvider.denom;
const encodedPath = `0x${estimateData.route}`;
const swapParams = [
@@ -725,13 +727,13 @@ export const SwapScreen = observer(() => {
const rawTx = await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
selectedAccount: currentWallet.address,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: 'eth_signTransaction',
params: [
{
from: currentWallet.address,
- to: app.provider.config.swapRouterV3,
+ to: Provider.selectedProvider.config.swapRouterV3,
value: tokenInIsISLM ? estimateData.amount_in : '0x0',
data: encodedTxData,
},
@@ -739,7 +741,7 @@ export const SwapScreen = observer(() => {
},
});
- const provider = await getRpcProvider(app.provider);
+ const provider = await getRpcProvider(Provider.selectedProvider);
const txHandler = await provider.sendTransaction(rawTx);
const txResp = await txHandler.wait();
navigator.goBack();
@@ -754,7 +756,7 @@ export const SwapScreen = observer(() => {
hash: txResp.transactionHash,
},
token: toJS(
- tokenIn?.symbol === app.provider.denom
+ tokenIn?.symbol === Provider.selectedProvider.denom
? Token.generateNativeToken(currentWallet)
: [
...poolsData.contracts,
@@ -786,13 +788,13 @@ export const SwapScreen = observer(() => {
amountsIn,
swapSettings,
minReceivedAmount,
- app.provider.denom,
+ Provider.selectedProvider.denom,
]);
const onPressApprove = useCallback(async () => {
try {
setApproveInProgress(() => true);
- const provider = await getRpcProvider(app.provider);
+ const provider = await getRpcProvider(Provider.selectedProvider);
const erc20Token = new ethers.Contract(tokenIn?.id!, ERC20_ABI, provider);
const amountBN = ethers.utils.parseUnits(
@@ -801,14 +803,14 @@ export const SwapScreen = observer(() => {
);
const data = erc20Token.interface.encodeFunctionData('approve', [
- app.provider.config.swapRouterV3,
+ Provider.selectedProvider.config.swapRouterV3,
amountBN._hex,
]);
const rawTx = await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
selectedAccount: currentWallet.address,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: 'eth_signTransaction',
params: [
@@ -846,9 +848,9 @@ export const SwapScreen = observer(() => {
// deposit
try {
setSwapInProgress(() => true);
- const provider = await getRpcProvider(app.provider);
+ const provider = await getRpcProvider(Provider.selectedProvider);
const WETH = new ethers.Contract(
- AddressUtils.toEth(app.provider.config.wethAddress),
+ AddressUtils.toEth(Provider.selectedProvider.config.wethAddress),
WETH_ABI,
provider,
);
@@ -856,13 +858,15 @@ export const SwapScreen = observer(() => {
const rawTx = await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
selectedAccount: currentWallet.address,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: 'eth_signTransaction',
params: [
{
from: currentWallet.address,
- to: AddressUtils.toEth(app.provider.config.wethAddress),
+ to: AddressUtils.toEth(
+ Provider.selectedProvider.config.wethAddress,
+ ),
value: t0Current.toHex(),
data: txData,
},
@@ -884,7 +888,7 @@ export const SwapScreen = observer(() => {
hash: txResp.transactionHash,
},
token: toJS(
- tokenIn?.symbol === app.provider.denom
+ tokenIn?.symbol === Provider.selectedProvider.denom
? Token.generateNativeToken(currentWallet)
: [
...poolsData.contracts,
@@ -911,15 +915,15 @@ export const SwapScreen = observer(() => {
t0Current,
estimate,
amountsIn.amount,
- app.provider.denom,
+ Provider.selectedProvider.denom,
]);
const onPressUnrap = useCallback(async () => {
// withdraw
try {
setSwapInProgress(() => true);
- const provider = await getRpcProvider(app.provider);
+ const provider = await getRpcProvider(Provider.selectedProvider);
const WETH = new ethers.Contract(
- AddressUtils.toEth(app.provider.config.wethAddress),
+ AddressUtils.toEth(Provider.selectedProvider.config.wethAddress),
WETH_ABI,
provider,
);
@@ -934,13 +938,15 @@ export const SwapScreen = observer(() => {
const rawTx = await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
selectedAccount: currentWallet.address,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: 'eth_signTransaction',
params: [
{
from: currentWallet.address,
- to: AddressUtils.toEth(app.provider.config.wethAddress),
+ to: AddressUtils.toEth(
+ Provider.selectedProvider.config.wethAddress,
+ ),
value: '0x0',
data: txData,
},
@@ -962,7 +968,7 @@ export const SwapScreen = observer(() => {
hash: txResp.transactionHash,
},
token: toJS(
- tokenIn?.symbol === app.provider.denom
+ tokenIn?.symbol === Provider.selectedProvider.denom
? Token.generateNativeToken(currentWallet)
: [
...poolsData.contracts,
@@ -990,7 +996,7 @@ export const SwapScreen = observer(() => {
tokenIn?.symbol,
currentWallet,
estimate,
- app.provider.denom,
+ Provider.selectedProvider.denom,
]);
const onPressMax = async () => {
@@ -1092,7 +1098,7 @@ export const SwapScreen = observer(() => {
]);
useEffect(() => {
- if (!app.provider.config.swapEnabled) {
+ if (!Provider.selectedProvider.config.swapEnabled) {
return navigator.goBack();
}
const fetchData = () => {
@@ -1157,7 +1163,10 @@ export const SwapScreen = observer(() => {
setCurrentRoute(
() =>
data.routes.find(r =>
- AddressUtils.equals(r.token0, app.provider.config.wethAddress),
+ AddressUtils.equals(
+ r.token0,
+ Provider.selectedProvider.config.wethAddress,
+ ),
) || data.routes[1],
);
if (!data.pools?.length || !data?.routes?.length) {
@@ -1189,11 +1198,10 @@ export const SwapScreen = observer(() => {
providers: Provider.getAll().filter(p =>
providersIDs.includes(p.id!),
),
- initialProviderId: app.providerId!,
+ initialProviderId: Provider.selectedProviderId,
title: I18N.swapSupportedNetworks,
});
- app.providerId = providerId;
- await awaitForEventDone(Events.onProviderChanged);
+ Provider.setSelectedProviderId(providerId);
},
});
}
diff --git a/src/screens/WelcomeStack/index.tsx b/src/screens/WelcomeStack/index.tsx
index 885a063d3..447dbf9b6 100644
--- a/src/screens/WelcomeStack/index.tsx
+++ b/src/screens/WelcomeStack/index.tsx
@@ -1,4 +1,4 @@
-import React, {memo} from 'react';
+import React, {memo, useMemo} from 'react';
import {
NativeStackNavigationOptions,
@@ -7,6 +7,7 @@ import {
import Config from 'react-native-config';
import {getModalScreenOptions} from '@app/helpers/get-modal-screen-options';
+import {getWelcomeScreen} from '@app/helpers/get-welcome-screen';
import {themeUpdaterHOC} from '@app/helpers/theme-updater-hoc';
import {WelcomeStackParamList, WelcomeStackRoutes} from '@app/route-types';
import {basicScreenOptions} from '@app/screens';
@@ -33,11 +34,11 @@ const newsDetailOptions: NativeStackNavigationOptions = {
...modalOptions,
};
-type Props = {
- initialRouteName: WelcomeStackRoutes.Welcome | WelcomeStackRoutes.WelcomeNews;
-};
+const WelcomeStack = memo(() => {
+ const initialRouteName = useMemo(() => {
+ return getWelcomeScreen();
+ }, []);
-const WelcomeStack = memo(({initialRouteName}: Props) => {
return (
{
wallets: Wallet.getAllVisible(),
});
const providers = Provider.getAll();
- const initialProviderId = app.provider.id;
+ const initialProviderId = Provider.selectedProviderId;
const providerId = await awaitForProvider({
providers,
initialProviderId: initialProviderId!,
diff --git a/src/screens/transaction-select-crypto.tsx b/src/screens/transaction-select-crypto.tsx
index 65a406a50..912fd7a7d 100644
--- a/src/screens/transaction-select-crypto.tsx
+++ b/src/screens/transaction-select-crypto.tsx
@@ -4,10 +4,10 @@ import {computed} from 'mobx';
import {observer} from 'mobx-react';
import {TransactionSelectCrypto} from '@app/components/transaction-select-crypto';
-import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
import {useTypedNavigation, useTypedRoute} from '@app/hooks';
import {useAndroidBackHandler} from '@app/hooks/use-android-back-handler';
+import {Provider} from '@app/models/provider';
import {Token} from '@app/models/tokens';
import {
TransactionStackParamList,
@@ -30,10 +30,11 @@ export const TransactionSelectCryptoScreen = observer(() => {
item =>
!!item.is_in_white_list &&
// FIXME: only erc20 tokens or native currency (ISLM)
- (item.is_erc20 || item.symbol === app.provider.denom),
+ (item.is_erc20 ||
+ item.symbol === Provider.selectedProvider.denom),
) ?? [],
),
- [params.from, app.provider.denom],
+ [params.from, Provider.selectedProvider.denom],
).get();
useAndroidBackHandler(() => {
diff --git a/src/services/balance.ts b/src/services/balance.ts
index 5ee3f82ba..acb358091 100644
--- a/src/services/balance.ts
+++ b/src/services/balance.ts
@@ -2,9 +2,9 @@ import Decimal from 'decimal.js';
import {BigNumber, BigNumberish} from 'ethers';
import {I18nManager} from 'react-native';
-import {app} from '@app/contexts';
import {cleanNumber} from '@app/helpers/clean-number';
import {Currencies} from '@app/models/currencies';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {
BalanceConstructor,
@@ -30,7 +30,11 @@ export class Balance implements IBalance, ISerializable {
private symbol: string;
static get Empty() {
- return new Balance(zeroBN, app.provider.decimals, app.provider.denom);
+ return new Balance(
+ zeroBN,
+ Provider.selectedProvider.decimals,
+ Provider.selectedProvider.denom,
+ );
}
constructor(
@@ -38,12 +42,9 @@ export class Balance implements IBalance, ISerializable {
precission?: number,
symbol?: string,
) {
- precission = precission ?? app.provider.decimals;
- symbol = symbol ?? app.provider.denom;
-
this.originalValue = balance;
- this.precission = precission ?? app.provider.decimals;
- this.symbol = symbol || app.provider.denom;
+ this.precission = precission ?? Provider.selectedProvider.decimals;
+ this.symbol = symbol || Provider.selectedProvider.denom;
if (BigNumber.isBigNumber(balance)) {
const {_hex} = BigNumber.from(balance);
@@ -92,7 +93,7 @@ export class Balance implements IBalance, ISerializable {
* Is current Balance instance is native network Coin
*/
get isNativeCoin() {
- return this.symbol === app.provider.denom;
+ return this.symbol === Provider.selectedProvider.denom;
}
getPrecission() {
@@ -108,7 +109,11 @@ export class Balance implements IBalance, ISerializable {
}
static getEmpty = () => {
- return new Balance(zeroBN, app.provider.decimals, app.provider.denom);
+ return new Balance(
+ zeroBN,
+ Provider.selectedProvider.decimals,
+ Provider.selectedProvider.denom,
+ );
};
static fromJsonString = (obj: string | Balance) => {
diff --git a/src/services/cosmos.ts b/src/services/cosmos.ts
index 806275499..17bbb3e2e 100644
--- a/src/services/cosmos.ts
+++ b/src/services/cosmos.ts
@@ -42,14 +42,13 @@ import {ProviderInterface, base64PublicKey} from '@haqq/provider-base';
import {normalize0x} from '@haqq/provider-keystone-react-native';
import Decimal from 'decimal.js';
-import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
import {
getRemoteBalanceValue,
getRemoteMultiplierValue,
} from '@app/helpers/get-remote-balance-value';
import {ledgerTransportCbWrapper} from '@app/helpers/ledger-transport-wrapper';
-import {Provider} from '@app/models/provider';
+import {Provider, ProviderModel} from '@app/models/provider';
import {Balance} from '@app/services/balance';
import {
DepositResponse,
@@ -93,9 +92,9 @@ export class Cosmos {
};
public stop = false;
- private _provider: Provider;
+ private _provider: ProviderModel;
- constructor(provider: Provider) {
+ constructor(provider: ProviderModel) {
this._provider = provider;
}
@@ -126,8 +125,8 @@ export class Cosmos {
async postQuery(path: string, data: string, account?: Sender): Promise {
const params = {
type: 'cosmos',
- network: app.provider.name,
- chainId: `${app.provider.ethChainId}`,
+ network: Provider.selectedProvider.name,
+ chainId: `${Provider.selectedProvider.ethChainId}`,
address: account?.accountAddress ?? 'unknown',
};
try {
diff --git a/src/services/eth-network/erc20.ts b/src/services/eth-network/erc20.ts
index a6817646d..111613c10 100644
--- a/src/services/eth-network/erc20.ts
+++ b/src/services/eth-network/erc20.ts
@@ -1,8 +1,8 @@
import {utils} from 'ethers';
-import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
import {Contracts} from '@app/models/contracts';
+import {Provider} from '@app/models/provider';
import {Token} from '@app/models/tokens';
import {Balance} from '@app/services/balance';
@@ -22,7 +22,8 @@ export const getERC20TransferData = (
Contracts.getById(haqqContractAddress) ||
Token.getById(haqqContractAddress);
- const decimals = contractInfo.decimals ?? app.provider.decimals;
+ const decimals =
+ contractInfo.decimals ?? Provider.selectedProvider.decimals;
const [amountClear] = new Balance(amount.toWei(), 0)
.operate(Math.pow(10, amount.getPrecission()), 'div')
diff --git a/src/services/eth-network/eth-network.ts b/src/services/eth-network/eth-network.ts
index 8922baadd..5de93d0bf 100644
--- a/src/services/eth-network/eth-network.ts
+++ b/src/services/eth-network/eth-network.ts
@@ -4,11 +4,10 @@ import {ProviderInterface} from '@haqq/provider-base';
import Decimal from 'decimal.js';
import {BigNumber, utils} from 'ethers';
-import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
import {getRpcProvider} from '@app/helpers/get-rpc-provider';
import {EstimationVariant} from '@app/models/fee';
-import {Provider} from '@app/models/provider';
+import {Provider, ProviderModel} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {getDefaultChainId} from '@app/network';
import {Balance} from '@app/services/balance';
@@ -28,7 +27,7 @@ export class EthNetwork {
static chainId: number = getDefaultChainId();
static explorer: string | undefined;
- static init(provider: Provider) {
+ static init(provider: ProviderModel) {
EthNetwork.chainId = provider.ethChainId;
EthNetwork.explorer = provider.explorer;
}
@@ -44,7 +43,7 @@ export class EthNetwork {
if (!AddressUtils.isEthAddress(from)) {
throw new Error('Invalid "to" address');
}
- const rpcProvider = await getRpcProvider(app.provider);
+ const rpcProvider = await getRpcProvider(Provider.selectedProvider);
const nonce = await rpcProvider.getTransactionCount(from, 'latest');
const transaction = {
@@ -56,7 +55,7 @@ export class EthNetwork {
maxPriorityFeePerGas: estimate.maxPriorityFee.toHex(),
gasLimit: estimate.gasLimit.toHex(),
data,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
};
const tx = await utils.resolveProperties(transaction);
@@ -79,7 +78,7 @@ export class EthNetwork {
value,
data,
...estimate,
- provider: app.provider.name,
+ provider: Provider.selectedProvider.name,
});
throw error;
}
@@ -87,7 +86,7 @@ export class EthNetwork {
static async getBalance(address: string): Promise {
try {
- const rpcProvider = await getRpcProvider(app.provider);
+ const rpcProvider = await getRpcProvider(Provider.selectedProvider);
const balanceResponse = await rpcProvider.getBalance(address);
const balanceWithWEI = new Balance(balanceResponse._hex);
const balance = new Balance(balanceWithWEI);
@@ -108,7 +107,7 @@ export class EthNetwork {
}
static async call(to: string, data: string) {
- const rpcProvider = await getRpcProvider(app.provider);
+ const rpcProvider = await getRpcProvider(Provider.selectedProvider);
return await rpcProvider.call({
to,
data,
@@ -117,7 +116,7 @@ export class EthNetwork {
static async getCode(address: string) {
try {
- const rpcProvider = await getRpcProvider(app.provider);
+ const rpcProvider = await getRpcProvider(Provider.selectedProvider);
return await rpcProvider.getCode(address);
} catch (e) {
return '0x';
@@ -125,12 +124,12 @@ export class EthNetwork {
}
static async sendTransaction(signedTx: string) {
- const rpcProvider = await getRpcProvider(app.provider);
+ const rpcProvider = await getRpcProvider(Provider.selectedProvider);
return await rpcProvider.sendTransaction(signedTx);
}
static async getTransactionReceipt(txHash: string) {
- const rpcProvider = await getRpcProvider(app.provider);
+ const rpcProvider = await getRpcProvider(Provider.selectedProvider);
return await rpcProvider.getTransactionReceipt(txHash);
}
@@ -138,7 +137,7 @@ export class EthNetwork {
static async customEstimate(
{from, to, value = Balance.Empty, data = '0x'}: TxEstimationParams,
{gasLimit, maxBaseFee, maxPriorityFee}: TxCustomEstimationParams,
- provider = app.provider,
+ provider = Provider.selectedProvider,
): Promise {
try {
const rpcProvider = await getRpcProvider(provider);
@@ -226,7 +225,7 @@ export class EthNetwork {
static async estimate(
{from, to, value = Balance.Empty, data = '0x', minGas}: TxEstimationParams,
calculationType: EstimationVariant = EstimationVariant.average,
- provider = app.provider,
+ provider = Provider.selectedProvider,
): Promise {
try {
const rpcProvider = await getRpcProvider(provider);
diff --git a/src/services/eth-sign.ts b/src/services/eth-sign.ts
index 68271c468..151f1fa77 100644
--- a/src/services/eth-sign.ts
+++ b/src/services/eth-sign.ts
@@ -3,6 +3,7 @@ import {TransactionRequest} from '@haqq/provider-base';
import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
import {awaitForJsonRpcSign} from '@app/helpers/await-for-json-rpc-sign';
+import {Provider} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {EIPTypedData} from '@app/types';
import {stringToHex} from '@app/utils';
@@ -81,7 +82,7 @@ export class EthSign {
const address = getWalletAddress(wallet);
return await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: EIP155_SIGNING_METHODS.PERSONAL_SIGN,
params: [address, stringToHex(message)],
@@ -106,7 +107,7 @@ export class EthSign {
try {
return await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: EIP155_SIGNING_METHODS.ETH_SIGN_TRANSACTION,
params: [preparedTx],
@@ -139,7 +140,7 @@ export class EthSign {
try {
return await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION,
params: [preparedTx],
@@ -185,7 +186,7 @@ export class EthSign {
try {
return await awaitForJsonRpcSign({
metadata: HAQQ_METADATA,
- chainId: app.provider.ethChainId,
+ chainId: Provider.selectedProvider.ethChainId,
request: {
method: EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA,
params: [address, typedData],
diff --git a/src/services/indexer/indexer.ts b/src/services/indexer/indexer.ts
index 4e34fdfb8..b6dfcfe3f 100644
--- a/src/services/indexer/indexer.ts
+++ b/src/services/indexer/indexer.ts
@@ -4,12 +4,11 @@ import {
} from '@haqq/shared-react-native/src/jsonrpc-request';
import _ from 'lodash';
-import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
import {Whitelist} from '@app/helpers/whitelist';
import {I18N, getText} from '@app/i18n';
import {NftCollectionIndexer} from '@app/models/nft';
-import {Provider} from '@app/models/provider';
+import {ALL_NETWORKS_ID, Provider} from '@app/models/provider';
import {
ContractNameMap,
IContract,
@@ -68,7 +67,7 @@ export class Indexer {
captureException = logger.captureException;
/**
- * @param chainId - Chain ID of the network for get endpoint by default get from app.provider
+ * @param chainId - Chain ID of the network for get endpoint by default get from Provider.selectedProvider
*/
constructor(public chainId?: number | string) {
if (chainId && !Provider.getByEthChainId(chainId)) {
@@ -82,7 +81,7 @@ export class Indexer {
return Provider.getByEthChainId(this.chainId)?.indexer!;
}
- return app.provider.indexer;
+ return Provider.selectedProvider.indexer;
}
checkIndexerAvailability = (): void => {
@@ -103,6 +102,20 @@ export class Indexer {
}
updates = createAsyncTask(
+ async (
+ accounts: string[],
+ lastUpdated: Date | undefined,
+ selectedCurrency?: string,
+ ) => {
+ if (Provider.selectedProviderId === ALL_NETWORKS_ID) {
+ return this.updatesV2(accounts, lastUpdated, selectedCurrency);
+ } else {
+ return this.updatesV1(accounts, lastUpdated, selectedCurrency);
+ }
+ },
+ );
+
+ updatesV1 = createAsyncTask(
async (
accounts: string[],
lastUpdated: Date | undefined,
@@ -129,6 +142,42 @@ export class Indexer {
},
);
+ updatesV2 = createAsyncTask(
+ async (
+ accounts: string[],
+ lastUpdated: Date | undefined,
+ selectedCurrency?: string,
+ ) => {
+ try {
+ this.checkIndexerAvailability();
+
+ const updated = lastUpdated || new Date(0);
+
+ const result: IndexerUpdatesResponse = await jsonrpcRequest(
+ this.endpoint,
+ 'updates_v2',
+ [
+ Provider.getAll()
+ .filter(item => item.id !== ALL_NETWORKS_ID)
+ .reduce(
+ (acc, item) => ({...acc, [item.ethChainId]: accounts}),
+ {},
+ ),
+ updated,
+ selectedCurrency,
+ ].filter(Boolean),
+ );
+
+ return result;
+ } catch (err) {
+ if (err instanceof JSONRPCError) {
+ this.captureException(err, 'Indexer:updates', err.meta);
+ }
+ throw err;
+ }
+ },
+ );
+
async getContractName(address: string): Promise {
const info = await Whitelist.verifyAddress(address);
return info?.name ?? getText(I18N.transactionContractDefaultName);
@@ -168,40 +217,56 @@ export class Indexer {
}
}
- async getBalances(accounts: string[]): Promise> {
+ async getTransaction(
+ accounts: string[],
+ tx_hash: string,
+ ): Promise {
try {
- this.checkIndexerAvailability();
+ if (!accounts.length) {
+ return null;
+ }
- const response = await jsonrpcRequest(
+ const haqqAddresses = accounts.filter(a => !!a).map(AddressUtils.toHaqq);
+ const response = await jsonrpcRequest(
this.endpoint,
- 'balances',
- [accounts],
+ 'transaction',
+ [haqqAddresses, tx_hash],
);
- return response.balance || {};
+ return response?.txs?.[0] || null;
} catch (err) {
if (err instanceof JSONRPCError) {
- this.captureException(err, 'Indexer:getBalances', err.meta);
+ this.captureException(err, 'Indexer:getTransactions', err.meta);
}
throw err;
}
}
- async getTransaction(
+ getTransactions = createAsyncTask(
+ async (accounts: string[], latestBlock: string = 'latest') => {
+ if (Provider.selectedProviderId === ALL_NETWORKS_ID) {
+ return this.getTransactionsV2(accounts, latestBlock);
+ } else {
+ return this.getTransactionsV1(accounts, latestBlock);
+ }
+ },
+ );
+
+ async getTransactionsV1(
accounts: string[],
- tx_hash: string,
- ): Promise {
+ latestBlock: string = 'latest',
+ ): Promise {
try {
if (!accounts.length) {
- return null;
+ return [];
}
const haqqAddresses = accounts.filter(a => !!a).map(AddressUtils.toHaqq);
const response = await jsonrpcRequest(
this.endpoint,
- 'transaction',
- [haqqAddresses, tx_hash],
+ 'transactions',
+ [haqqAddresses, latestBlock],
);
- return response?.txs[0] || {};
+ return response?.txs || [];
} catch (err) {
if (err instanceof JSONRPCError) {
this.captureException(err, 'Indexer:getTransactions', err.meta);
@@ -210,7 +275,7 @@ export class Indexer {
}
}
- async getTransactions(
+ async getTransactionsV2(
accounts: string[],
latestBlock: string = 'latest',
): Promise {
@@ -222,10 +287,19 @@ export class Indexer {
const haqqAddresses = accounts.filter(a => !!a).map(AddressUtils.toHaqq);
const response = await jsonrpcRequest(
this.endpoint,
- 'transactions',
- [haqqAddresses, latestBlock],
+ 'transactions_by_timestamp',
+ [
+ Provider.getAll()
+ .filter(item => item.id !== ALL_NETWORKS_ID)
+ .reduce(
+ (acc, item) => ({...acc, [item.ethChainId]: haqqAddresses}),
+ {},
+ ),
+ latestBlock,
+ ],
);
- return response?.txs || {};
+
+ return response?.transactions || [];
} catch (err) {
if (err instanceof JSONRPCError) {
this.captureException(err, 'Indexer:getTransactions', err.meta);
@@ -234,7 +308,15 @@ export class Indexer {
}
}
- async getNfts(accounts: string[]): Promise {
+ getNfts = createAsyncTask(async (accounts: string[]) => {
+ if (Provider.selectedProviderId === ALL_NETWORKS_ID) {
+ return this.getNftsV2(accounts);
+ } else {
+ return this.getNftsV1(accounts);
+ }
+ });
+
+ async getNftsV1(accounts: string[]): Promise {
try {
this.checkIndexerAvailability();
@@ -258,6 +340,37 @@ export class Indexer {
}
}
+ async getNftsV2(accounts: string[]): Promise {
+ try {
+ this.checkIndexerAvailability();
+
+ if (!accounts.length) {
+ return [];
+ }
+
+ const haqqAddresses = accounts.filter(a => !!a).map(AddressUtils.toHaqq);
+ const response = await jsonrpcRequest(
+ this.endpoint,
+ 'nfts',
+ [
+ Provider.getAll()
+ .filter(item => item.id !== ALL_NETWORKS_ID)
+ .reduce(
+ (acc, item) => ({...acc, [item.ethChainId]: haqqAddresses}),
+ {},
+ ),
+ ],
+ );
+
+ return response || [];
+ } catch (err) {
+ if (err instanceof JSONRPCError) {
+ this.captureException(err, 'Indexer:getNfts', err.meta);
+ }
+ throw err;
+ }
+ }
+
async sushiPools(): Promise {
try {
this.checkIndexerAvailability();
diff --git a/src/services/json-rpc-middleware/json-rpc-methods-handlers.ts b/src/services/json-rpc-middleware/json-rpc-methods-handlers.ts
index caf2495aa..a0e50268b 100644
--- a/src/services/json-rpc-middleware/json-rpc-methods-handlers.ts
+++ b/src/services/json-rpc-middleware/json-rpc-methods-handlers.ts
@@ -25,7 +25,7 @@ import {
import {getRpcProvider} from '@app/helpers/get-rpc-provider';
import {isEthereumChainParams} from '@app/helpers/web3-browser-utils';
import {I18N, getText} from '@app/i18n';
-import {Provider} from '@app/models/provider';
+import {Provider, ProviderModel} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {Web3BrowserSession} from '@app/models/web3-browser-session';
import {getDefaultNetwork} from '@app/network';
@@ -152,11 +152,11 @@ const getNetworkProvier = (helper: JsonRpcHelper) => {
// };
const session = Web3BrowserSession.getByOrigin(helper.origin);
- let provider: Provider | undefined;
+ let provider: ProviderModel | undefined;
if (session?.isActive) {
provider = Provider.getByChainIdHex(session?.selectedChainIdHex!);
} else {
- provider = Provider.getById(app.providerId);
+ provider = Provider.selectedProvider;
}
return provider;
};
diff --git a/src/services/remote-config/index.ts b/src/services/remote-config/index.ts
index 9b5934073..30233d0e0 100644
--- a/src/services/remote-config/index.ts
+++ b/src/services/remote-config/index.ts
@@ -1,2 +1,2 @@
-export * from './remote-config-service';
-export * from './remote-config-types';
+export * from './remote-config.service';
+export * from './remote-config.types';
diff --git a/src/services/remote-config/remote-config-default-values.ts b/src/services/remote-config/remote-config-default-values.ts
index 7160e7011..783c31572 100644
--- a/src/services/remote-config/remote-config-default-values.ts
+++ b/src/services/remote-config/remote-config-default-values.ts
@@ -1,9 +1,13 @@
import {
- getDefaultBalanceValue,
- getDefaultMultiplierValue,
-} from '@app/helpers/get-remote-balance-value';
+ BALANCE_MULTIPLIER,
+ COSMOS_MIN_AMOUNT,
+ COSMOS_MIN_GAS_LIMIT,
+ MIN_AMOUNT,
+ MIN_GAS_LIMIT,
+ MIN_STAKING_REWARD,
+} from '@app/variables/balance';
-import {RemoteConfigTypes} from './remote-config-types';
+import {RemoteConfigTypes} from './remote-config.types';
import {getAppVersion} from '../version';
@@ -83,20 +87,14 @@ export const REMOTE_CONFIG_DEFAULT_VALUES: Required = {
airdrop_gasdrop_secret: 'NX2HLGSlACcc2DWSNfVETLr5OzxxTcv5',
airdrop_gasdrop_campaign_id: '19851c43f2e9da721e0c8356019190b6',
pattern_source: 'https://storage.googleapis.com/mobile-static/',
- cosmos_min_amount: getDefaultBalanceValue('cosmos_min_amount').toHex(),
- cosmos_min_gas_limit: getDefaultBalanceValue('cosmos_min_gas_limit').toHex(),
- cosmos_commission_multiplier: getDefaultMultiplierValue(
- 'cosmos_commission_multiplier',
- ),
- eth_min_amount: getDefaultBalanceValue('eth_min_amount').toHex(),
- eth_min_gas_limit: getDefaultBalanceValue('eth_min_gas_limit').toHex(),
- eth_commission_multiplier: getDefaultMultiplierValue(
- 'eth_commission_multiplier',
- ),
- transfer_min_amount: getDefaultBalanceValue('transfer_min_amount').toHex(),
- staking_reward_min_amount: getDefaultBalanceValue(
- 'staking_reward_min_amount',
- ).toHex(),
+ cosmos_min_amount: COSMOS_MIN_AMOUNT,
+ cosmos_min_gas_limit: COSMOS_MIN_GAS_LIMIT,
+ cosmos_commission_multiplier: BALANCE_MULTIPLIER,
+ eth_min_amount: MIN_AMOUNT,
+ eth_min_gas_limit: MIN_GAS_LIMIT,
+ eth_commission_multiplier: BALANCE_MULTIPLIER,
+ transfer_min_amount: MIN_AMOUNT,
+ staking_reward_min_amount: MIN_STAKING_REWARD,
keystone_tutorial_url: 'https://keyst.one/mmm',
web3_browser_bookmarks: [
{
diff --git a/src/services/remote-config/remote-config-service.ts b/src/services/remote-config/remote-config.service.ts
similarity index 97%
rename from src/services/remote-config/remote-config-service.ts
rename to src/services/remote-config/remote-config.service.ts
index 387ba15ea..22aacf7c0 100644
--- a/src/services/remote-config/remote-config-service.ts
+++ b/src/services/remote-config/remote-config.service.ts
@@ -2,7 +2,7 @@ import {getAppInfo} from '@app/helpers/get-app-info';
import {Initializable} from '@app/helpers/initializable';
import {VariablesString} from '@app/models/variables-string';
import {Backend} from '@app/services/backend';
-import {RemoteConfigTypes} from '@app/services/remote-config/remote-config-types';
+import {RemoteConfigTypes} from '@app/services/remote-config';
import {isValidJSON} from '@app/utils';
import {REMOTE_CONFIG_DEFAULT_VALUES} from './remote-config-default-values';
diff --git a/src/services/remote-config/remote-config-types.ts b/src/services/remote-config/remote-config.types.ts
similarity index 100%
rename from src/services/remote-config/remote-config-types.ts
rename to src/services/remote-config/remote-config.types.ts
diff --git a/src/services/sign-json-rpc-request.ts b/src/services/sign-json-rpc-request.ts
index 142bf3b04..3937d2dd8 100644
--- a/src/services/sign-json-rpc-request.ts
+++ b/src/services/sign-json-rpc-request.ts
@@ -2,7 +2,6 @@ import {TransactionRequest} from '@haqq/provider-base';
import {normalize0x} from '@haqq/provider-keystone-react-native';
import {getSdkError} from '@walletconnect/utils';
-import {app} from '@app/contexts';
import {DEBUG_VARS} from '@app/debug-vars';
import {getProviderInstanceForWallet, hideModal} from '@app/helpers';
import {getRpcProvider} from '@app/helpers/get-rpc-provider';
@@ -105,7 +104,8 @@ export class SignJsonRpcRequest {
throw new Error(getText(I18N.jsonRpcErrorInvalidProvider));
}
- const provider = Provider.getByEthChainId(chainId!) || app.provider;
+ const provider =
+ Provider.getByEthChainId(chainId!) || Provider.selectedProvider;
const rpcProvider = provider
? await getRpcProvider(provider)
: getDefaultNetwork();
@@ -128,7 +128,7 @@ export class SignJsonRpcRequest {
case EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V4:
const typedData = getSignTypedDataParamsData(request.params);
if (isEthTypedData(typedData)) {
- const cosmos = new Cosmos(app.provider!);
+ const cosmos = new Cosmos(Provider.selectedProvider);
const signTypedDataResult = cosmos.signTypedData(
path,
instanceProvider,
diff --git a/src/services/wallet-connect.ts b/src/services/wallet-connect.ts
index f2de2b5fa..c4242a726 100644
--- a/src/services/wallet-connect.ts
+++ b/src/services/wallet-connect.ts
@@ -152,17 +152,6 @@ export class WalletConnect extends Initializable {
this._emitActiveSessions.bind(this),
);
- app.on(Events.onProviderChanged, async (providerId: string) => {
- const provider = Provider.getById(providerId)!;
- const chainId = provider.ethChainId;
- await this.awaitForInitialization();
- for (let session of WalletConnectSessionMetadata.getAll()) {
- // sleep to avoid frequency requests to wallet connect relay server
- await sleep(300);
- await this.emitChainChange(chainId, session.topic);
- }
- });
-
const end = Date.now();
const initDuration = end - this._initStartTime;
logger.log(
@@ -389,7 +378,10 @@ export class WalletConnect extends Initializable {
WalletConnectSessionMetadata.create(session.topic);
// set chain which currently active in app
- await this.emitChainChange(app.provider.ethChainId, session.topic);
+ await this.emitChainChange(
+ Provider.selectedProvider.ethChainId,
+ session.topic,
+ );
this._emitActiveSessions();
this.redirect();
diff --git a/src/types.ts b/src/types.ts
index bde60e543..c9c39507a 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -32,7 +32,7 @@ import {IconProps} from '@app/components/ui';
import {I18N} from '@app/i18n';
import {Banner} from '@app/models/banner';
import {NftCollection, NftItem} from '@app/models/nft';
-import {Provider} from '@app/models/provider';
+import {ProviderModel} from '@app/models/provider';
import {Wallet} from '@app/models/wallet';
import {SignUpStackRoutes, WelcomeStackRoutes} from '@app/route-types';
import {EthNetwork} from '@app/services';
@@ -479,7 +479,7 @@ export type RootStackParamList = {
};
settingsProviderForm: {
id?: string;
- data?: Partial;
+ data?: Partial;
};
stakingValidators: undefined;
stakingInfo: {
@@ -1089,7 +1089,7 @@ export type Modals = {
providersBottomSheet: {
onClose?: () => void;
title: I18N;
- providers: Provider[] | Results;
+ providers: ProviderModel[] | Results;
initialProviderId: string;
closeDistance?: () => number;
eventSuffix?: string;
@@ -1850,7 +1850,8 @@ export type IndexerTransactionWithType = Extract<
export type IndexerTransactionResponse = {
hash: string;
- txs: IndexerTransaction[];
+ txs?: IndexerTransaction[];
+ transactions?: IndexerTransaction[];
};
export type ChainId = string | number;
diff --git a/src/variables/balance.ts b/src/variables/balance.ts
index 6ece0f5a2..88999c8f5 100644
--- a/src/variables/balance.ts
+++ b/src/variables/balance.ts
@@ -1,9 +1,7 @@
-import {Balance} from '@app/services/balance';
-
-export const MIN_AMOUNT = new Balance(0.001);
-export const MIN_STAKING_REWARD = new Balance(0.01);
-export const MIN_GAS_LIMIT = new Balance(22_000, 0);
-export const FEE_AMOUNT = new Balance(0.00001);
-export const BALANCE_MULTIPLIER = new Balance(1.56, 0);
-export const COSMOS_MIN_AMOUNT = new Balance('2000000000');
-export const COSMOS_MIN_GAS_LIMIT = new Balance('2000000');
+export const MIN_AMOUNT = '0x38d7ea4c68000';
+export const MIN_STAKING_REWARD = '0x2386f26fc10000';
+export const MIN_GAS_LIMIT = '0x55f0';
+export const FEE_AMOUNT = 0.00001;
+export const BALANCE_MULTIPLIER = 1.56;
+export const COSMOS_MIN_AMOUNT = '0x77359400';
+export const COSMOS_MIN_GAS_LIMIT = '0x1e8480';
diff --git a/src/widgets/staking-widget/staking-widget.tsx b/src/widgets/staking-widget/staking-widget.tsx
index 1432976e7..d3cc656ab 100644
--- a/src/widgets/staking-widget/staking-widget.tsx
+++ b/src/widgets/staking-widget/staking-widget.tsx
@@ -13,10 +13,10 @@ import {
} from '@app/components/ui';
import {ShadowCard} from '@app/components/ui/shadow-card';
import {WidgetHeader} from '@app/components/ui/widget-header';
-import {app} from '@app/contexts';
import {createTheme} from '@app/helpers';
import {getRemoteBalanceValue} from '@app/helpers/get-remote-balance-value';
import {I18N, getText} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {Balance} from '@app/services/balance';
type Props = {
@@ -57,7 +57,7 @@ export const StakingWidget = observer(
icon={'staking_thin'}
title={getText(I18N.earnStaking)}
description={getText(I18N.earnStakingDescription, {
- symbol: app.provider.denom,
+ symbol: Provider.selectedProvider.denom,
})}
largeIcon
/>
diff --git a/src/widgets/tokens-widget/tokens-widget.tsx b/src/widgets/tokens-widget/tokens-widget.tsx
index 0672c07ef..d26735a28 100644
--- a/src/widgets/tokens-widget/tokens-widget.tsx
+++ b/src/widgets/tokens-widget/tokens-widget.tsx
@@ -8,8 +8,8 @@ import {TokenRow} from '@app/components/token-row';
import {Spacer, Text, TextVariant} from '@app/components/ui';
import {ShadowCard} from '@app/components/ui/shadow-card';
import {WidgetHeader} from '@app/components/ui/widget-header';
-import {app} from '@app/contexts';
import {I18N, getText} from '@app/i18n';
+import {Provider} from '@app/models/provider';
import {IToken} from '@app/types';
type Props = {
@@ -43,7 +43,7 @@ export const TokensWidget = observer(({onPress, tokens}: Props) => {
item =>
!!item.is_in_white_list &&
// FIXME: only erc20 tokens or native currency (ISLM)
- (item.is_erc20 || item.symbol === app.provider.denom),
+ (item.is_erc20 || item.symbol === Provider.selectedProvider.denom),
)
.slice(0, VISIBLE_ITEM_AMOUNT)
.map(item => {