Add support for wallet_getCapabilities from WalletConnect (#39)
Part of https://www.notion.so/Integrate-eSIM-buy-flow-into-app-18aa6b22d47280d4a77cf1b27e2ba193 - Add Base network - Check sufficient balance for Eth tx fees Co-authored-by: pranavjadhav007 <jadhavpranav89@gmail.com> Reviewed-on: LaconicNetwork/laconic-wallet-web#39
This commit is contained in:
+18
@@ -146,6 +146,23 @@ const App = (): React.JSX.Element => {
|
|||||||
requestSessionData,
|
requestSessionData,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EIP155_SIGNING_METHODS.WALLET_GET_CAPABILITIES:
|
||||||
|
const supportedNetworks = networksData
|
||||||
|
.filter(network => network.namespace === EIP155)
|
||||||
|
.map(network => `${network.namespace}:${network.chainId}`);
|
||||||
|
const capabilitiesResponse = formatJsonRpcResult(id, {
|
||||||
|
accountManagement: true,
|
||||||
|
sessionManagement: true,
|
||||||
|
supportedAuthMethods: ['personal_sign', 'eth_sendTransaction'],
|
||||||
|
supportedNetworks: supportedNetworks,
|
||||||
|
});
|
||||||
|
|
||||||
|
await web3wallet!.respondSessionRequest({
|
||||||
|
topic,
|
||||||
|
response: capabilitiesResponse,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
case COSMOS_METHODS.COSMOS_SIGN_DIRECT:
|
case COSMOS_METHODS.COSMOS_SIGN_DIRECT:
|
||||||
const message = {
|
const message = {
|
||||||
@@ -347,6 +364,7 @@ const App = (): React.JSX.Element => {
|
|||||||
// eslint-disable-next-line react/no-unstable-nested-components
|
// eslint-disable-next-line react/no-unstable-nested-components
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
<Button
|
<Button
|
||||||
|
testID="pair-button"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigation.navigate("AddSession");
|
navigation.navigate("AddSession");
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export const Header: React.FC<{
|
|||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
{showWalletConnect && (
|
{showWalletConnect && (
|
||||||
<Button onClick={() => navigation.navigate("WalletConnect")}>
|
<Button data-webviewId="wallet-connect-button" onClick={() => navigation.navigate("WalletConnect")}>
|
||||||
{<WCLogo />}
|
{<WCLogo />}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -282,20 +282,24 @@ const PairingModal = ({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<View style={styles.flexRow}>
|
{currentProposal && namespaces && (
|
||||||
<Button
|
<View style={styles.flexRow}>
|
||||||
mode="contained"
|
<Button
|
||||||
onPress={handleAccept}
|
mode="contained"
|
||||||
loading={isLoading}
|
testID="accept-pair-request-button"
|
||||||
disabled={isLoading}>
|
onPress={handleAccept}
|
||||||
{isLoading ? 'Connecting' : 'Yes'}
|
loading={isLoading}
|
||||||
</Button>
|
disabled={isLoading}>
|
||||||
<View style={styles.space} />
|
{isLoading ? 'Connecting' : 'Yes'}
|
||||||
<Button mode="outlined" onPress={handleReject}>
|
</Button>
|
||||||
No
|
<View style={styles.space} />
|
||||||
</Button>
|
<Button mode="outlined" onPress={handleReject}>
|
||||||
</View>
|
No
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const AddSession = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Box sx={{ mt: 2 }}>
|
<Box sx={{ mt: 2 }}>
|
||||||
<Button variant="contained" onClick={pair}>
|
<Button variant="contained" data-webviewId="pair-session-button" onClick={pair}>
|
||||||
Pair Session
|
Pair Session
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -82,23 +82,27 @@ const ApproveTransfer = ({ route }: ApproveTransferProps) => {
|
|||||||
useState<BigNumber | null>();
|
useState<BigNumber | null>();
|
||||||
|
|
||||||
const isSufficientFunds = useMemo(() => {
|
const isSufficientFunds = useMemo(() => {
|
||||||
if (!transaction.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!balance) {
|
if (!balance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const amountBigNum = BigNumber.from(String(transaction.value));
|
if (!fees) {
|
||||||
const balanceBigNum = BigNumber.from(balance);
|
return;
|
||||||
|
|
||||||
if (amountBigNum.gte(balanceBigNum)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}, [balance, transaction]);
|
|
||||||
|
const balanceBigNum = BigNumber.from(balance);
|
||||||
|
const feesBigNum = BigNumber.from(fees);
|
||||||
|
let totalRequiredBigNum = feesBigNum;
|
||||||
|
|
||||||
|
if (transaction.value) {
|
||||||
|
const amountBigNum = BigNumber.from(String(transaction.value));
|
||||||
|
totalRequiredBigNum = amountBigNum.add(feesBigNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the user's balance with the total required amount
|
||||||
|
const isSufficient = balanceBigNum.gte(totalRequiredBigNum);
|
||||||
|
return isSufficient;
|
||||||
|
}, [balance, transaction.value, fees]);
|
||||||
|
|
||||||
const requestedNetwork = networksData.find(
|
const requestedNetwork = networksData.find(
|
||||||
networkData =>
|
networkData =>
|
||||||
@@ -273,8 +277,12 @@ const ApproveTransfer = ({ route }: ApproveTransferProps) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (namespace === EIP155) {
|
if (namespace === EIP155) {
|
||||||
const ethFees = BigNumber.from(ethGasLimit ?? 0)
|
if (!ethGasLimit || !(ethMaxFee || ethGasPrice)){
|
||||||
.mul(BigNumber.from(ethMaxFee ?? ethGasPrice ?? 0))
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ethFees = BigNumber.from(ethGasLimit)
|
||||||
|
.mul(BigNumber.from(ethMaxFee ?? ethGasPrice))
|
||||||
.toString();
|
.toString();
|
||||||
setFees(ethFees);
|
setFees(ethFees);
|
||||||
} else {
|
} else {
|
||||||
@@ -495,7 +503,7 @@ const ApproveTransfer = ({ route }: ApproveTransferProps) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getEthGas = async () => {
|
const getEthGas = async () => {
|
||||||
try {
|
try {
|
||||||
if (!isSufficientFunds || !provider) {
|
if (!provider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,11 +576,11 @@ const ApproveTransfer = ({ route }: ApproveTransferProps) => {
|
|||||||
}, [cosmosStargateClient, isSufficientFunds, sendMsg, transaction,txMemo]);
|
}, [cosmosStargateClient, isSufficientFunds, sendMsg, transaction,txMemo]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (balance && !isSufficientFunds) {
|
if (balance && !isSufficientFunds && !fees) {
|
||||||
setTxError('Insufficient funds');
|
setTxError('Insufficient funds');
|
||||||
setIsTxErrorDialogOpen(true);
|
setIsTxErrorDialogOpen(true);
|
||||||
}
|
}
|
||||||
}, [isSufficientFunds, balance]);
|
}, [isSufficientFunds, balance, fees]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -614,14 +622,16 @@ const ApproveTransfer = ({ route }: ApproveTransferProps) => {
|
|||||||
{transaction && (
|
{transaction && (
|
||||||
<View style={styles.approveTransfer}>
|
<View style={styles.approveTransfer}>
|
||||||
<DataBox label="To" data={transaction.to!} />
|
<DataBox label="To" data={transaction.to!} />
|
||||||
<DataBox
|
{transaction.value !== undefined && transaction.value !== null && (
|
||||||
label={`Amount (${
|
<DataBox
|
||||||
namespace === EIP155 ? 'wei' : requestedNetwork!.nativeDenom
|
label={`Amount (${
|
||||||
})`}
|
namespace === EIP155 ? 'wei' : requestedNetwork!.nativeDenom
|
||||||
data={BigNumber.from(
|
})`}
|
||||||
transaction.value?.toString(),
|
data={BigNumber.from(
|
||||||
).toString()}
|
transaction.value?.toString(),
|
||||||
/>
|
).toString()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{namespace === COSMOS && (
|
{namespace === COSMOS && (
|
||||||
<DataBox
|
<DataBox
|
||||||
label="Memo"
|
label="Memo"
|
||||||
|
|||||||
@@ -116,7 +116,8 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (route.path) {
|
const requestEvent = route.params.requestEvent;
|
||||||
|
if (route.path && !requestEvent) {
|
||||||
const sanitizedRoute = sanitizePath(route.path);
|
const sanitizedRoute = sanitizePath(route.path);
|
||||||
sanitizedRoute &&
|
sanitizedRoute &&
|
||||||
retrieveData(
|
retrieveData(
|
||||||
@@ -127,7 +128,6 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const requestEvent = route.params.requestEvent;
|
|
||||||
const requestChainId = requestEvent?.params.chainId;
|
const requestChainId = requestEvent?.params.chainId;
|
||||||
|
|
||||||
const requestedChain = networksData.find(
|
const requestedChain = networksData.find(
|
||||||
@@ -310,6 +310,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
<View style={styles.buttonContainer}>
|
<View style={styles.buttonContainer}>
|
||||||
<Button
|
<Button
|
||||||
mode="contained"
|
mode="contained"
|
||||||
|
testID="accept-sign-request-button"
|
||||||
onPress={signMessageHandler}
|
onPress={signMessageHandler}
|
||||||
loading={isApproving}
|
loading={isApproving}
|
||||||
disabled={isApproving}>
|
disabled={isApproving}>
|
||||||
|
|||||||
@@ -43,15 +43,20 @@ export default function WalletConnect() {
|
|||||||
// eslint-disable-next-line react/no-unstable-nested-components
|
// eslint-disable-next-line react/no-unstable-nested-components
|
||||||
left={() => (
|
left={() => (
|
||||||
<>
|
<>
|
||||||
{session.peer.metadata.icons[0].endsWith(".svg") ? (
|
{session.peer.metadata.icons && session.peer.metadata.icons.length > 0 ? (
|
||||||
<View style={styles.dappLogo}>
|
session.peer.metadata.icons[0].endsWith(".svg") ? (
|
||||||
<Text>SvgURI peerMetaDataIcon</Text>
|
<View style={styles.dappLogo}>
|
||||||
</View>
|
<Text>SvgURI peerMetaDataIcon</Text>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<Image
|
||||||
|
style={styles.dappLogo}
|
||||||
|
source={{ uri: session.peer.metadata.icons[0] }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<Image
|
// Render nothing if no icon is available
|
||||||
style={styles.dappLogo}
|
<View style={styles.dappLogo} /> // Or simply null
|
||||||
source={{ uri: session.peer.metadata.icons[0] }}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ const retrieveSingleAccount = async (
|
|||||||
throw new Error('Accounts for given chain not found');
|
throw new Error('Accounts for given chain not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return loadedAccounts.find(account => account.address === address);
|
return loadedAccounts.find(account => account.address.toLowerCase() === address.toLowerCase());
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetWallet = async () => {
|
const resetWallet = async () => {
|
||||||
|
|||||||
@@ -40,6 +40,18 @@ export const DEFAULT_NETWORKS: NetworksFormData[] = [
|
|||||||
coinType: '60',
|
coinType: '60',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Base Chain Network
|
||||||
|
{
|
||||||
|
chainId: '8453',
|
||||||
|
networkName: EIP155_CHAINS['eip155:8453'].name,
|
||||||
|
namespace: EIP155,
|
||||||
|
rpcUrl: EIP155_CHAINS['eip155:8453'].rpc,
|
||||||
|
blockExplorerUrl: '',
|
||||||
|
currencySymbol: 'ETH',
|
||||||
|
coinType: '60',
|
||||||
|
isDefault: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
chainId: 'provider',
|
chainId: 'provider',
|
||||||
networkName: COSMOS_TESTNET_CHAINS['cosmos:provider'].name,
|
networkName: COSMOS_TESTNET_CHAINS['cosmos:provider'].name,
|
||||||
|
|||||||
@@ -11,13 +11,8 @@
|
|||||||
export type TEIP155Chain = keyof typeof EIP155_CHAINS;
|
export type TEIP155Chain = keyof typeof EIP155_CHAINS;
|
||||||
|
|
||||||
export type EIP155Chain = {
|
export type EIP155Chain = {
|
||||||
chainId: number;
|
|
||||||
name: string;
|
name: string;
|
||||||
logo: string;
|
|
||||||
rgb: string;
|
|
||||||
rpc: string;
|
rpc: string;
|
||||||
namespace: string;
|
|
||||||
smartAccountEnabled?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,12 +20,14 @@ export type EIP155Chain = {
|
|||||||
*/
|
*/
|
||||||
export const EIP155_CHAINS: Record<string, EIP155Chain> = {
|
export const EIP155_CHAINS: Record<string, EIP155Chain> = {
|
||||||
'eip155:1': {
|
'eip155:1': {
|
||||||
chainId: 1,
|
|
||||||
name: 'Ethereum',
|
name: 'Ethereum',
|
||||||
logo: '/chain-logos/eip155-1.png',
|
|
||||||
rgb: '99, 125, 234',
|
|
||||||
rpc: 'https://cloudflare-eth.com/',
|
rpc: 'https://cloudflare-eth.com/',
|
||||||
namespace: 'eip155',
|
},
|
||||||
|
|
||||||
|
// Ref: https://docs.base.org/base-chain/quickstart/connecting-to-base#base-mainnet
|
||||||
|
'eip155:8453': {
|
||||||
|
name: 'Base',
|
||||||
|
rpc: 'https://mainnet.base.org',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,4 +37,5 @@ export const EIP155_CHAINS: Record<string, EIP155Chain> = {
|
|||||||
export const EIP155_SIGNING_METHODS = {
|
export const EIP155_SIGNING_METHODS = {
|
||||||
PERSONAL_SIGN: 'personal_sign',
|
PERSONAL_SIGN: 'personal_sign',
|
||||||
ETH_SEND_TRANSACTION: 'eth_sendTransaction',
|
ETH_SEND_TRANSACTION: 'eth_sendTransaction',
|
||||||
|
WALLET_GET_CAPABILITIES: 'wallet_getCapabilities'
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user