Update wallet code for token transfer using android embedded webview (#36)
Part of https://www.notion.so/Integrate-eSIM-buy-flow-into-app-18aa6b22d47280d4a77cf1b27e2ba193 Co-authored-by: AdityaSalunkhe21 <adityasalunkhe2204@gmail.com> Co-authored-by: pranavjadhav007 <jadhavpranav89@gmail.com> Reviewed-on: #36
This commit is contained in:
parent
d0623be1c3
commit
1e88321490
@ -1,6 +1,5 @@
|
||||
REACT_APP_WALLET_CONNECT_PROJECT_ID=
|
||||
|
||||
REACT_APP_DEFAULT_GAS_PRICE=0.025
|
||||
# Reference: https://github.com/cosmos/cosmos-sdk/issues/16020
|
||||
REACT_APP_GAS_ADJUSTMENT=2
|
||||
REACT_APP_LACONICD_RPC_URL=https://laconicd-sapo.laconic.com
|
||||
|
21
src/global.d.ts
vendored
21
src/global.d.ts
vendored
@ -14,10 +14,31 @@ declare global {
|
||||
|
||||
// Called when accounts are ready for use
|
||||
onAccountsReady?: () => void;
|
||||
|
||||
// Called when transfer is successfully completed
|
||||
onTransferComplete?: (result: string) => void;
|
||||
|
||||
// Called when transfer fails
|
||||
onTransferError?: (error: string) => void;
|
||||
|
||||
// Called when transfer is cancelled
|
||||
onTransferCancelled?: () => void;
|
||||
|
||||
// Called when account is created
|
||||
onAccountCreated?: (account: string) => void;
|
||||
|
||||
// Called when account creation fails
|
||||
onAccountError?: (error: string) => void;
|
||||
};
|
||||
|
||||
// Handles incoming signature requests from Android
|
||||
receiveSignRequestFromAndroid?: (message: string) => void;
|
||||
|
||||
// Handles incoming transfer requests from Android
|
||||
receiveTransferRequestFromAndroid?: (to: string, amount: string, namespace: String, chainId: string, memo: string) => void;
|
||||
|
||||
// Handles account creation requests from Android
|
||||
receiveGetOrCreateAccountFromAndroid?: (chainId: string) => void;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,35 +58,14 @@ const useGetOrCreateAccounts = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const autoCreateAccounts = async () => {
|
||||
const defaultChainId = networksData[0]?.chainId;
|
||||
|
||||
if (!defaultChainId) {
|
||||
console.log('useGetOrCreateAccounts: No default chainId found');
|
||||
return;
|
||||
}
|
||||
const accounts = await getOrCreateAccountsForChain(defaultChainId);
|
||||
|
||||
// Only notify Android when we actually have accounts
|
||||
if (accounts.length > 0 && window.Android?.onAccountsReady) {
|
||||
window.Android.onAccountsReady();
|
||||
} else {
|
||||
console.log('No accounts created or Android bridge not available');
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleCreateAccounts);
|
||||
|
||||
const isAndroidWebView = !!(window.Android);
|
||||
|
||||
if (isAndroidWebView) {
|
||||
autoCreateAccounts();
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', handleCreateAccounts);
|
||||
};
|
||||
}, [networksData, getAccountsData, getOrCreateAccountsForChain]);
|
||||
|
||||
return { getOrCreateAccountsForChain };
|
||||
};
|
||||
|
||||
export default useGetOrCreateAccounts;
|
||||
|
@ -4,17 +4,38 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||
|
||||
import { useAccounts } from '../context/AccountsContext';
|
||||
import { useNetworks } from '../context/NetworksContext';
|
||||
import useAccountsData from "../hooks/useAccountsData";
|
||||
|
||||
import { StackParamsList } from '../types';
|
||||
import useGetOrCreateAccounts from './useGetOrCreateAccounts';
|
||||
import { retrieveAccountsForNetwork } from '../utils/accounts';
|
||||
|
||||
export const useWebViewHandler = () => {
|
||||
// Navigation and context hooks
|
||||
const navigation = useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
||||
const { selectedNetwork } = useNetworks();
|
||||
const { accounts, currentIndex } = useAccounts();
|
||||
const { getAccountsData } = useAccountsData();
|
||||
const { getOrCreateAccountsForChain } = useGetOrCreateAccounts();
|
||||
|
||||
// Initialize accounts
|
||||
useGetOrCreateAccounts();
|
||||
const handleGetOrCreateAccount = useCallback(async (chainId: string) => {
|
||||
try {
|
||||
|
||||
const accountsData = await getOrCreateAccountsForChain(chainId);
|
||||
|
||||
if (!accountsData || accountsData.length === 0) {
|
||||
window.Android?.onAccountError?.('Failed to create/retrieve account');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window.Android?.onAccountCreated?.(JSON.stringify(accountsData[0]));
|
||||
} catch (error) {
|
||||
console.error('Account operation error:', error);
|
||||
window.Android?.onAccountError?.(`Operation failed: ${error}`);
|
||||
}
|
||||
}, [getOrCreateAccountsForChain, getAccountsData]);
|
||||
|
||||
// Core navigation handler
|
||||
const navigateToSignRequest = useCallback((message: string) => {
|
||||
@ -27,12 +48,14 @@ export const useWebViewHandler = () => {
|
||||
|
||||
if (!accounts?.length) {
|
||||
window.Android?.onSignatureError?.('No accounts available');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const currentAccount = accounts[currentIndex];
|
||||
if (!currentAccount) {
|
||||
window.Android?.onSignatureError?.('Current account not found');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -43,6 +66,7 @@ export const useWebViewHandler = () => {
|
||||
|
||||
if (!match) {
|
||||
window.Android?.onSignatureError?.('Invalid signing path');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -70,12 +94,67 @@ export const useWebViewHandler = () => {
|
||||
}
|
||||
}, [selectedNetwork, accounts, currentIndex, navigation]);
|
||||
|
||||
// Handle incoming transfer requests
|
||||
const navigateToTransfer = useCallback(async (to: string, amount: string, namespace: String, chainId: string, memo: string) => {
|
||||
|
||||
try {
|
||||
// TODO: Pass the account info for transferring tokens
|
||||
// Get first account
|
||||
const [chainAccount] = await retrieveAccountsForNetwork(
|
||||
`${namespace}:${chainId}`,
|
||||
'0'
|
||||
);
|
||||
|
||||
if (!chainAccount) {
|
||||
console.error('Accounts not found');
|
||||
if (window.Android?.onTransferError) {
|
||||
window.Android.onTransferError('Accounts not found');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const path = `/transfer/${namespace}/${chainId}/${chainAccount.address}/${to}/${amount}`;
|
||||
|
||||
navigation.reset({
|
||||
index: 0,
|
||||
routes: [
|
||||
{
|
||||
name: 'ApproveTransfer',
|
||||
path: path,
|
||||
params: {
|
||||
namespace: namespace,
|
||||
chainId: `${namespace}:${chainId}`,
|
||||
transaction: {
|
||||
from: chainAccount.address,
|
||||
to: to,
|
||||
value: amount
|
||||
},
|
||||
accountInfo: chainAccount,
|
||||
memo: memo
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
} catch (error) {
|
||||
if (window.Android?.onTransferError) {
|
||||
window.Android.onTransferError(`Navigation error: ${error}`);
|
||||
}
|
||||
}
|
||||
}, [navigation]);
|
||||
|
||||
useEffect(() => {
|
||||
// Assign the function to the window object
|
||||
window.receiveSignRequestFromAndroid = navigateToSignRequest;
|
||||
|
||||
window.receiveTransferRequestFromAndroid = navigateToTransfer;
|
||||
|
||||
window.receiveGetOrCreateAccountFromAndroid = handleGetOrCreateAccount;
|
||||
|
||||
return () => {
|
||||
window.receiveSignRequestFromAndroid = undefined;
|
||||
window.receiveTransferRequestFromAndroid = undefined;
|
||||
window.receiveGetOrCreateAccountFromAndroid = undefined;
|
||||
};
|
||||
}, [navigateToSignRequest]); // Only the function reference as dependency
|
||||
}, [navigateToSignRequest, navigateToTransfer, handleGetOrCreateAccount]); // Only the function reference as dependency
|
||||
};
|
||||
|
@ -2,11 +2,11 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Image, ScrollView, View } from 'react-native';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Button,
|
||||
Text,
|
||||
Appbar,
|
||||
TextInput,
|
||||
} from 'react-native-paper';
|
||||
import JSONbig from 'json-bigint';
|
||||
import { providers, BigNumber } from 'ethers';
|
||||
import { Deferrable } from 'ethers/lib/utils';
|
||||
|
||||
@ -41,28 +41,29 @@ import { COSMOS, EIP155, IS_NUMBER_REGEX } from '../utils/constants';
|
||||
import TxErrorDialog from '../components/TxErrorDialog';
|
||||
import { EIP155_SIGNING_METHODS } from '../utils/wallet-connect/EIP155Data';
|
||||
import { COSMOS_METHODS } from '../utils/wallet-connect/COSMOSData';
|
||||
import { Button } from '@mui/material';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
|
||||
export const MEMO = 'Sending signed tx from Laconic Wallet';
|
||||
// Reference: https://ethereum.org/en/developers/docs/gas/#what-is-gas-limit
|
||||
const ETH_MINIMUM_GAS = 21000;
|
||||
|
||||
type SignRequestProps = NativeStackScreenProps<
|
||||
StackParamsList,
|
||||
'ApproveTransfer'
|
||||
>;
|
||||
type ApproveTransferProps = NativeStackScreenProps<StackParamsList, 'ApproveTransfer'>
|
||||
|
||||
const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
const ApproveTransfer = ({ route }: ApproveTransferProps) => {
|
||||
const { networksData } = useNetworks();
|
||||
const { web3wallet } = useWalletConnect();
|
||||
|
||||
// Extract data from route params or path
|
||||
const requestSession = route.params.requestSessionData;
|
||||
const requestName = requestSession.peer.metadata.name;
|
||||
const requestIcon = requestSession.peer.metadata.icons[0];
|
||||
const requestURL = requestSession.peer.metadata.url;
|
||||
const requestName = requestSession?.peer.metadata.name;
|
||||
const requestIcon = requestSession?.peer.metadata.icons[0];
|
||||
const requestURL = requestSession?.peer.metadata.url;
|
||||
const transaction = route.params.transaction;
|
||||
const requestEvent = route.params.requestEvent;
|
||||
const chainId = requestEvent.params.chainId;
|
||||
const requestMethod = requestEvent.params.request.method;
|
||||
const chainId = requestEvent?.params.chainId || route.params.chainId;
|
||||
const requestMethod = requestEvent?.params.request.method;
|
||||
const txMemo = route.params.memo || MEMO;
|
||||
|
||||
const [account, setAccount] = useState<Account>();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@ -205,6 +206,58 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
[navigation, requestedNetwork],
|
||||
);
|
||||
|
||||
//TODO: Handle ETH transactions
|
||||
const handleIntent = async () => {
|
||||
if (!account) {
|
||||
throw new Error('Account is not valid');
|
||||
}
|
||||
|
||||
console.log('Sending transaction request:', {
|
||||
from: account.address,
|
||||
to: transaction.to,
|
||||
amount: transaction.value,
|
||||
denom: requestedNetwork!.nativeDenom,
|
||||
memo: txMemo,
|
||||
gas: cosmosGasLimit,
|
||||
fees: fees
|
||||
});
|
||||
|
||||
if (!requestedNetwork) {
|
||||
throw new Error('Network not found');
|
||||
}
|
||||
|
||||
if (!cosmosStargateClient) {
|
||||
throw new Error('Cosmos stargate client not found');
|
||||
}
|
||||
|
||||
const result = await cosmosStargateClient.signAndBroadcast(
|
||||
account.address,
|
||||
[sendMsg],
|
||||
{
|
||||
amount: [
|
||||
{
|
||||
amount: fees,
|
||||
denom: requestedNetwork.nativeDenom!,
|
||||
},
|
||||
],
|
||||
gas: cosmosGasLimit,
|
||||
},
|
||||
txMemo,
|
||||
);
|
||||
|
||||
console.log('Transaction result:', result);
|
||||
|
||||
// Convert BigInt values to strings before sending to Android
|
||||
const serializedResult = JSONbig.stringify(result);
|
||||
|
||||
// Send the result back to Android and close dialog
|
||||
if (window.Android?.onTransferComplete) {
|
||||
window.Android.onTransferComplete(serializedResult);
|
||||
} else {
|
||||
alert(`Transaction: ${serializedResult}`);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Set loading to false when gas values for requested chain are fetched
|
||||
// If requested chain is EVM compatible, the cosmos gas values will be undefined and vice-versa, hence the condition checks only one of them at the same time
|
||||
@ -246,6 +299,7 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
requestedNetwork,
|
||||
ethMaxFee,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
retrieveData(transaction.from!);
|
||||
}, [retrieveData, transaction]);
|
||||
@ -267,78 +321,82 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
throw new Error('account not found');
|
||||
}
|
||||
|
||||
if (ethGasLimit && ethGasLimit.lt(ETH_MINIMUM_GAS)) {
|
||||
throw new Error(`Atleast ${ETH_MINIMUM_GAS} gas limit is required`);
|
||||
}
|
||||
if (requestEvent) {
|
||||
// Handle WalletConnect request
|
||||
if (ethGasLimit && ethGasLimit.lt(ETH_MINIMUM_GAS)) {
|
||||
throw new Error(`Atleast ${ETH_MINIMUM_GAS} gas limit is required`);
|
||||
}
|
||||
|
||||
if (ethMaxFee && ethMaxPriorityFee && ethMaxFee.lte(ethMaxPriorityFee)) {
|
||||
throw new Error(
|
||||
`Max fee per gas (${ethMaxFee.toNumber()}) cannot be lower than or equal to max priority fee per gas (${ethMaxPriorityFee.toNumber()})`,
|
||||
if (ethMaxFee && ethMaxPriorityFee && ethMaxFee.lte(ethMaxPriorityFee)) {
|
||||
throw new Error(
|
||||
`Max fee per gas (${ethMaxFee.toNumber()}) cannot be lower than or equal to max priority fee per gas (${ethMaxPriorityFee.toNumber()})`,
|
||||
);
|
||||
}
|
||||
|
||||
let options: WalletConnectRequests;
|
||||
|
||||
switch (requestMethod) {
|
||||
case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION:
|
||||
if (
|
||||
ethMaxFee === undefined ||
|
||||
ethMaxPriorityFee === undefined ||
|
||||
ethGasPrice === undefined
|
||||
) {
|
||||
throw new Error('Gas values not found');
|
||||
}
|
||||
|
||||
options = {
|
||||
type: 'eth_sendTransaction',
|
||||
provider: provider!,
|
||||
ethGasLimit: BigNumber.from(ethGasLimit),
|
||||
ethGasPrice: ethGasPrice ? ethGasPrice.toHexString() : null,
|
||||
maxFeePerGas: ethMaxFee,
|
||||
maxPriorityFeePerGas: ethMaxPriorityFee,
|
||||
};
|
||||
break;
|
||||
case COSMOS_METHODS.COSMOS_SEND_TOKENS:
|
||||
if (!cosmosStargateClient) {
|
||||
throw new Error('Cosmos stargate client not found');
|
||||
}
|
||||
|
||||
options = {
|
||||
type: 'cosmos_sendTokens',
|
||||
signingStargateClient: cosmosStargateClient,
|
||||
cosmosFee: {
|
||||
amount: [
|
||||
{
|
||||
amount: fees,
|
||||
denom: requestedNetwork!.nativeDenom!,
|
||||
},
|
||||
],
|
||||
gas: cosmosGasLimit,
|
||||
},
|
||||
sendMsg,
|
||||
memo: txMemo,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid method');
|
||||
}
|
||||
|
||||
const response = await approveWalletConnectRequest(
|
||||
requestEvent,
|
||||
account!,
|
||||
namespace,
|
||||
requestedNetwork!.chainId,
|
||||
options,
|
||||
);
|
||||
|
||||
const { topic } = requestEvent;
|
||||
await web3wallet!.respondSessionRequest({ topic, response });
|
||||
navigation.navigate('Home');
|
||||
} else {
|
||||
await handleIntent();
|
||||
}
|
||||
|
||||
let options: WalletConnectRequests;
|
||||
|
||||
switch (requestMethod) {
|
||||
case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION:
|
||||
if (
|
||||
ethMaxFee === undefined ||
|
||||
ethMaxPriorityFee === undefined ||
|
||||
ethGasPrice === undefined
|
||||
) {
|
||||
throw new Error('Gas values not found');
|
||||
}
|
||||
|
||||
options = {
|
||||
type: 'eth_sendTransaction',
|
||||
provider: provider!,
|
||||
ethGasLimit: BigNumber.from(ethGasLimit),
|
||||
ethGasPrice: ethGasPrice ? ethGasPrice.toHexString() : null,
|
||||
maxFeePerGas: ethMaxFee,
|
||||
maxPriorityFeePerGas: ethMaxPriorityFee,
|
||||
};
|
||||
break;
|
||||
case COSMOS_METHODS.COSMOS_SEND_TOKENS:
|
||||
if (!cosmosStargateClient) {
|
||||
throw new Error('Cosmos stargate client not found');
|
||||
}
|
||||
|
||||
options = {
|
||||
type: 'cosmos_sendTokens',
|
||||
signingStargateClient: cosmosStargateClient,
|
||||
// StdFee object
|
||||
cosmosFee: {
|
||||
// This amount is total fees required for transaction
|
||||
amount: [
|
||||
{
|
||||
amount: fees,
|
||||
denom: requestedNetwork!.nativeDenom!,
|
||||
},
|
||||
],
|
||||
gas: cosmosGasLimit,
|
||||
},
|
||||
sendMsg,
|
||||
memo: MEMO,
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('Invalid method');
|
||||
}
|
||||
|
||||
const response = await approveWalletConnectRequest(
|
||||
requestEvent,
|
||||
account,
|
||||
namespace,
|
||||
requestedNetwork!.chainId,
|
||||
options,
|
||||
);
|
||||
|
||||
const { topic } = requestEvent;
|
||||
await web3wallet!.respondSessionRequest({ topic, response });
|
||||
navigation.navigate('Home');
|
||||
} catch (error) {
|
||||
if (window.Android?.onTransferError) {
|
||||
window.Android.onTransferError(`Transaction Failed: ${error}`);
|
||||
}
|
||||
if (!(error instanceof Error)) {
|
||||
throw error;
|
||||
}
|
||||
@ -350,14 +408,31 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
};
|
||||
|
||||
const rejectRequestHandler = async () => {
|
||||
const response = rejectWalletConnectRequest(requestEvent);
|
||||
const { topic } = requestEvent;
|
||||
await web3wallet!.respondSessionRequest({
|
||||
topic,
|
||||
response,
|
||||
});
|
||||
setIsTxLoading(true);
|
||||
try {
|
||||
if (requestEvent) {
|
||||
const response = rejectWalletConnectRequest(requestEvent);
|
||||
const { topic } = requestEvent;
|
||||
await web3wallet!.respondSessionRequest({
|
||||
topic,
|
||||
response,
|
||||
});
|
||||
}
|
||||
|
||||
navigation.navigate('Home');
|
||||
if (window.Android?.onTransferCancelled) {
|
||||
window.Android.onTransferCancelled();
|
||||
} else {
|
||||
navigation.navigate('Home');
|
||||
}
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
setTxError(error.message);
|
||||
setIsTxErrorDialogOpen(true);
|
||||
}
|
||||
setIsTxLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -472,7 +547,7 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
const gasEstimation = await cosmosStargateClient.simulate(
|
||||
transaction.from!,
|
||||
[sendMsg],
|
||||
MEMO,
|
||||
txMemo,
|
||||
);
|
||||
|
||||
setCosmosGasLimit(
|
||||
@ -490,7 +565,7 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
}
|
||||
};
|
||||
getCosmosGas();
|
||||
}, [cosmosStargateClient, isSufficientFunds, sendMsg, transaction]);
|
||||
}, [cosmosStargateClient, isSufficientFunds, sendMsg, transaction,txMemo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (balance && !isSufficientFunds) {
|
||||
@ -508,16 +583,18 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
) : (
|
||||
<>
|
||||
<ScrollView contentContainerStyle={styles.appContainer}>
|
||||
<View style={styles.dappDetails}>
|
||||
{requestIcon && (
|
||||
<Image
|
||||
style={styles.dappLogo}
|
||||
source={requestIcon ? { uri: requestIcon } : undefined}
|
||||
/>
|
||||
)}
|
||||
<Text>{requestName}</Text>
|
||||
<Text variant="bodyMedium">{requestURL}</Text>
|
||||
</View>
|
||||
{requestSession && (
|
||||
<View style={styles.dappDetails}>
|
||||
{requestIcon && (
|
||||
<Image
|
||||
style={styles.dappLogo}
|
||||
source={requestIcon ? { uri: requestIcon } : undefined}
|
||||
/>
|
||||
)}
|
||||
<Text>{requestName}</Text>
|
||||
<Text variant="bodyMedium">{requestURL}</Text>
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.dataBoxContainer}>
|
||||
<Text style={styles.dataBoxLabel}>From</Text>
|
||||
<View style={styles.dataBox}>
|
||||
@ -545,6 +622,12 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
transaction.value?.toString(),
|
||||
).toString()}
|
||||
/>
|
||||
{namespace === COSMOS && (
|
||||
<DataBox
|
||||
label="Memo"
|
||||
data={txMemo}
|
||||
/>
|
||||
)}
|
||||
|
||||
{namespace === EIP155 ? (
|
||||
<>
|
||||
@ -638,17 +721,18 @@ const ApproveTransfer = ({ route }: SignRequestProps) => {
|
||||
)}
|
||||
</ScrollView>
|
||||
<View style={styles.buttonContainer}>
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={acceptRequestHandler}
|
||||
<LoadingButton
|
||||
variant="contained"
|
||||
onClick={acceptRequestHandler}
|
||||
loading={isTxLoading}
|
||||
disabled={!balance || !fees}>
|
||||
disabled={!balance || !fees}
|
||||
id="approve-transaction-button">
|
||||
{isTxLoading ? 'Processing' : 'Yes'}
|
||||
</Button>
|
||||
</LoadingButton>
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={rejectRequestHandler}
|
||||
buttonColor="#B82B0D">
|
||||
variant="contained"
|
||||
onClick={rejectRequestHandler}
|
||||
color="error">
|
||||
No
|
||||
</Button>
|
||||
</View>
|
||||
|
@ -21,9 +21,11 @@ export type StackParamsList = {
|
||||
requestSessionData?: SessionTypes.Struct;
|
||||
};
|
||||
ApproveTransfer: {
|
||||
chainId?: string;
|
||||
transaction: PopulatedTransaction;
|
||||
requestEvent: Web3WalletTypes.SessionRequest;
|
||||
requestSessionData: SessionTypes.Struct;
|
||||
requestEvent?: Web3WalletTypes.SessionRequest;
|
||||
requestSessionData?: SessionTypes.Struct;
|
||||
memo?: string;
|
||||
};
|
||||
InvalidPath: undefined;
|
||||
WalletConnect: undefined;
|
||||
|
@ -41,10 +41,10 @@ export const DEFAULT_NETWORKS: NetworksFormData[] = [
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
chainId: 'theta-testnet-001',
|
||||
networkName: COSMOS_TESTNET_CHAINS['cosmos:theta-testnet-001'].name,
|
||||
chainId: 'provider',
|
||||
networkName: COSMOS_TESTNET_CHAINS['cosmos:provider'].name,
|
||||
namespace: COSMOS,
|
||||
rpcUrl: COSMOS_TESTNET_CHAINS['cosmos:theta-testnet-001'].rpc,
|
||||
rpcUrl: COSMOS_TESTNET_CHAINS['cosmos:provider'].rpc,
|
||||
blockExplorerUrl: '',
|
||||
nativeDenom: 'uatom',
|
||||
addressPrefix: 'cosmos',
|
||||
@ -52,6 +52,22 @@ export const DEFAULT_NETWORKS: NetworksFormData[] = [
|
||||
gasPrice: '0.025',
|
||||
isDefault: true,
|
||||
},
|
||||
|
||||
//TODO: Add network from android app
|
||||
{
|
||||
chainId: 'nyx',
|
||||
networkName: 'Nym',
|
||||
namespace: COSMOS,
|
||||
rpcUrl: 'https://rpc.nymtech.net',
|
||||
blockExplorerUrl: 'https://explorer.nymtech.net',
|
||||
nativeDenom: 'unym',
|
||||
addressPrefix: 'n',
|
||||
coinType: '118',
|
||||
|
||||
// Ref: https://nym.com/docs/operators/nodes/validator-setup#apptoml-configuration
|
||||
gasPrice: '0.025',
|
||||
isDefault: true,
|
||||
},
|
||||
];
|
||||
|
||||
export const CHAINID_DEBOUNCE_DELAY = 250;
|
||||
|
@ -19,10 +19,10 @@ export const COSMOS_TESTNET_CHAINS: Record<
|
||||
namespace: string;
|
||||
}
|
||||
> = {
|
||||
'cosmos:theta-testnet-001': {
|
||||
chainId: 'theta-testnet-001',
|
||||
'cosmos:provider': {
|
||||
chainId: 'provider',
|
||||
name: 'Cosmos Hub Testnet',
|
||||
rpc: 'https://rpc-t.cosmos.nodestake.top',
|
||||
rpc: 'https://rpc-rs.cosmos.nodestake.top',
|
||||
namespace: 'cosmos',
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user