forked from cerc-io/laconic-wallet
Compare commits
3 Commits
ag-use-den
...
main
Author | SHA1 | Date | |
---|---|---|---|
bb5223afda | |||
e975f4c9f7 | |||
4827fa8c7c |
@ -21,6 +21,7 @@
|
|||||||
"@hookform/resolvers": "^3.3.4",
|
"@hookform/resolvers": "^3.3.4",
|
||||||
"@json-rpc-tools/utils": "^1.7.6",
|
"@json-rpc-tools/utils": "^1.7.6",
|
||||||
"@react-native-async-storage/async-storage": "^1.22.3",
|
"@react-native-async-storage/async-storage": "^1.22.3",
|
||||||
|
"@react-native-clipboard/clipboard": "^1.14.1",
|
||||||
"@react-native-community/netinfo": "^11.3.1",
|
"@react-native-community/netinfo": "^11.3.1",
|
||||||
"@react-navigation/elements": "^1.3.30",
|
"@react-navigation/elements": "^1.3.30",
|
||||||
"@react-navigation/native": "^6.1.10",
|
"@react-navigation/native": "^6.1.10",
|
||||||
|
31
scripts/build-apk.sh
Executable file
31
scripts/build-apk.sh
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Default value for IS_RELEASE
|
||||||
|
IS_RELEASE=${IS_RELEASE:-false}
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
yarn
|
||||||
|
|
||||||
|
# Create the necessary directory for assets
|
||||||
|
mkdir -p android/app/src/main/assets/
|
||||||
|
|
||||||
|
# Bundle the React Native application
|
||||||
|
yarn react-native bundle \
|
||||||
|
--platform android \
|
||||||
|
--dev false \
|
||||||
|
--entry-file index.js \
|
||||||
|
--bundle-output android/app/src/main/assets/index.android.bundle \
|
||||||
|
--assets-dest android/app/src/main/res
|
||||||
|
|
||||||
|
# Navigate to the android directory
|
||||||
|
cd android
|
||||||
|
|
||||||
|
# Run the Gradle build based on the IS_RELEASE flag
|
||||||
|
if [ "$IS_RELEASE" = "true" ]; then
|
||||||
|
echo "Building release version..."
|
||||||
|
./gradlew assembleRelease
|
||||||
|
else
|
||||||
|
echo "Building debug version..."
|
||||||
|
./gradlew assembleDebug
|
||||||
|
fi
|
@ -60,7 +60,6 @@ const Accounts = () => {
|
|||||||
networksData,
|
networksData,
|
||||||
selectedNetwork!,
|
selectedNetwork!,
|
||||||
accounts,
|
accounts,
|
||||||
currentIndex,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!updatedNamespaces) {
|
if (!updatedNamespaces) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
import { Button, Dialog, Portal, Text } from 'react-native-paper';
|
import { Button, Dialog, Portal, Snackbar, Text } from 'react-native-paper';
|
||||||
|
|
||||||
|
import Clipboard from '@react-native-clipboard/clipboard';
|
||||||
|
|
||||||
import styles from '../styles/stylesheet';
|
import styles from '../styles/stylesheet';
|
||||||
import GridView from './Grid';
|
import GridView from './Grid';
|
||||||
@ -11,17 +13,25 @@ const DialogComponent = ({
|
|||||||
hideDialog,
|
hideDialog,
|
||||||
contentText,
|
contentText,
|
||||||
}: CustomDialogProps) => {
|
}: CustomDialogProps) => {
|
||||||
|
const [toastVisible, setToastVisible] = useState(false);
|
||||||
|
|
||||||
const words = contentText.split(' ');
|
const words = contentText.split(' ');
|
||||||
|
|
||||||
|
const handleCopy = () => {
|
||||||
|
Clipboard.setString(contentText);
|
||||||
|
setToastVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Portal>
|
<Portal>
|
||||||
<Dialog visible={visible} onDismiss={hideDialog}>
|
<Dialog visible={visible} onDismiss={hideDialog}>
|
||||||
<Dialog.Content>
|
<Dialog.Content>
|
||||||
<Text variant="titleLarge">Mnemonic</Text>
|
<Text variant="titleLarge">Mnemonic</Text>
|
||||||
<View style={styles.dialogTitle}>
|
<View style={styles.dialogTitle}>
|
||||||
<Text variant="titleMedium">
|
<Text variant="titleMedium">
|
||||||
Your mnemonic provides full access to your wallet and funds. Make
|
Your mnemonic provides full access to your wallet and funds.
|
||||||
sure to note it down.{' '}
|
Make sure to note it down.{' '}
|
||||||
</Text>
|
</Text>
|
||||||
<Text variant="titleMedium" style={styles.dialogWarning}>
|
<Text variant="titleMedium" style={styles.dialogWarning}>
|
||||||
Do not share your mnemonic with anyone
|
Do not share your mnemonic with anyone
|
||||||
@ -30,10 +40,18 @@ const DialogComponent = ({
|
|||||||
</View>
|
</View>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
<Dialog.Actions>
|
<Dialog.Actions>
|
||||||
|
<Button onPress={handleCopy}>Copy</Button>
|
||||||
<Button onPress={hideDialog}>Done</Button>
|
<Button onPress={hideDialog}>Done</Button>
|
||||||
</Dialog.Actions>
|
</Dialog.Actions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Portal>
|
</Portal>
|
||||||
|
<Snackbar
|
||||||
|
visible={toastVisible}
|
||||||
|
onDismiss={() => setToastVisible(false)}
|
||||||
|
duration={1000}>
|
||||||
|
Mnemonic copied to clipboard
|
||||||
|
</Snackbar>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ const PairingModal = ({
|
|||||||
setModalVisible,
|
setModalVisible,
|
||||||
setToastVisible,
|
setToastVisible,
|
||||||
}: PairingModalProps) => {
|
}: PairingModalProps) => {
|
||||||
const { accounts, currentIndex } = useAccounts();
|
const { accounts } = useAccounts();
|
||||||
const { selectedNetwork, networksData } = useNetworks();
|
const { selectedNetwork, networksData } = useNetworks();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [chainError, setChainError] = useState('');
|
const [chainError, setChainError] = useState('');
|
||||||
@ -103,7 +103,6 @@ const PairingModal = ({
|
|||||||
networksData,
|
networksData,
|
||||||
selectedNetwork!,
|
selectedNetwork!,
|
||||||
accounts,
|
accounts,
|
||||||
currentIndex,
|
|
||||||
);
|
);
|
||||||
setSupportedNamespaces(nameSpaces);
|
setSupportedNamespaces(nameSpaces);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -129,7 +128,6 @@ const PairingModal = ({
|
|||||||
networksData,
|
networksData,
|
||||||
selectedNetwork,
|
selectedNetwork,
|
||||||
accounts,
|
accounts,
|
||||||
currentIndex,
|
|
||||||
web3wallet,
|
web3wallet,
|
||||||
setCurrentProposal,
|
setCurrentProposal,
|
||||||
setModalVisible,
|
setModalVisible,
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { Image, ScrollView, View } from 'react-native';
|
import { Image, ScrollView, View } from 'react-native';
|
||||||
import { Button, Text, TextInput } from 'react-native-paper';
|
import { Button, Text, TextInput } from 'react-native-paper';
|
||||||
import { SvgUri } from 'react-native-svg';
|
import { SvgUri } from 'react-native-svg';
|
||||||
import Config from 'react-native-config';
|
import Config from 'react-native-config';
|
||||||
|
import { MsgCreateValidator } from 'cosmjs-types/cosmos/staking/v1beta1/tx';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NativeStackNavigationProp,
|
NativeStackNavigationProp,
|
||||||
NativeStackScreenProps,
|
NativeStackScreenProps,
|
||||||
} from '@react-navigation/native-stack';
|
} from '@react-navigation/native-stack';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing';
|
import { DirectSecp256k1Wallet, EncodeObject } from '@cosmjs/proto-signing';
|
||||||
import { LaconicClient } from '@cerc-io/registry-sdk';
|
import { LaconicClient } from '@cerc-io/registry-sdk';
|
||||||
import { GasPrice, calculateFee } from '@cosmjs/stargate';
|
import { GasPrice, calculateFee } from '@cosmjs/stargate';
|
||||||
import { formatJsonRpcError } from '@json-rpc-tools/utils';
|
import { formatJsonRpcError } from '@json-rpc-tools/utils';
|
||||||
@ -42,7 +43,6 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
|
|||||||
const requestName = requestSession.peer.metadata.name;
|
const requestName = requestSession.peer.metadata.name;
|
||||||
const requestIcon = requestSession.peer.metadata.icons[0];
|
const requestIcon = requestSession.peer.metadata.icons[0];
|
||||||
const requestURL = requestSession.peer.metadata.url;
|
const requestURL = requestSession.peer.metadata.url;
|
||||||
const transactionMessage = route.params.transactionMessage;
|
|
||||||
const signer = route.params.signer;
|
const signer = route.params.signer;
|
||||||
const requestEvent = route.params.requestEvent;
|
const requestEvent = route.params.requestEvent;
|
||||||
const chainId = requestEvent.params.chainId;
|
const chainId = requestEvent.params.chainId;
|
||||||
@ -69,6 +69,20 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
|
|||||||
);
|
);
|
||||||
const namespace = requestedNetwork!.namespace;
|
const namespace = requestedNetwork!.namespace;
|
||||||
|
|
||||||
|
const transactionMessage = useMemo((): EncodeObject => {
|
||||||
|
const inputTxMsg = route.params.transactionMessage;
|
||||||
|
|
||||||
|
// If it's a MsgCreateValidator, decode the tx msg value using MsgCreateValidator type
|
||||||
|
if (inputTxMsg.typeUrl.includes('MsgCreateValidator')) {
|
||||||
|
return {
|
||||||
|
typeUrl: inputTxMsg.typeUrl,
|
||||||
|
value: MsgCreateValidator.fromJSON(inputTxMsg.value),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputTxMsg;
|
||||||
|
}, [route.params.transactionMessage]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (namespace !== COSMOS) {
|
if (namespace !== COSMOS) {
|
||||||
return;
|
return;
|
||||||
@ -144,7 +158,7 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const gasEstimation = await cosmosStargateClient!.simulate(
|
const gasEstimation = await cosmosStargateClient!.simulate(
|
||||||
transactionMessage.value.participant!,
|
signer,
|
||||||
[transactionMessage],
|
[transactionMessage],
|
||||||
MEMO,
|
MEMO,
|
||||||
);
|
);
|
||||||
@ -168,6 +182,7 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
|
|||||||
requestEventId,
|
requestEventId,
|
||||||
topic,
|
topic,
|
||||||
web3wallet,
|
web3wallet,
|
||||||
|
signer,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -243,6 +258,13 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
|
|||||||
navigation.navigate('Laconic');
|
navigation.navigate('Laconic');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const replacer = (key: string, value: any): any => {
|
||||||
|
if (value instanceof Uint8Array) {
|
||||||
|
return Buffer.from(value).toString('hex');
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ScrollView contentContainerStyle={styles.approveTransaction}>
|
<ScrollView contentContainerStyle={styles.approveTransaction}>
|
||||||
@ -267,7 +289,7 @@ const ApproveTransaction = ({ route }: ApproveTransactionProps) => {
|
|||||||
</Text>
|
</Text>
|
||||||
<View style={styles.messageBody}>
|
<View style={styles.messageBody}>
|
||||||
<Text variant="bodyLarge">
|
<Text variant="bodyLarge">
|
||||||
{JSON.stringify(transactionMessage, null, 2)}
|
{JSON.stringify(transactionMessage, replacer, 2)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<>
|
<>
|
||||||
|
@ -88,21 +88,13 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestAccount !== account) {
|
|
||||||
setAccount(requestAccount);
|
setAccount(requestAccount);
|
||||||
}
|
|
||||||
if (requestMessage !== message) {
|
|
||||||
setMessage(decodeURIComponent(requestMessage));
|
setMessage(decodeURIComponent(requestMessage));
|
||||||
}
|
|
||||||
if (requestNamespace !== namespace) {
|
|
||||||
setNamespace(requestNamespace);
|
setNamespace(requestNamespace);
|
||||||
}
|
|
||||||
if (requestChainId !== chainId) {
|
|
||||||
setChainId(requestChainId);
|
setChainId(requestChainId);
|
||||||
}
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
},
|
},
|
||||||
[account, message, navigation, namespace, chainId],
|
[navigation],
|
||||||
);
|
);
|
||||||
|
|
||||||
const sanitizePath = useCallback(
|
const sanitizePath = useCallback(
|
||||||
|
@ -40,7 +40,6 @@ export const getNamespaces = async (
|
|||||||
networksData: NetworksDataState[],
|
networksData: NetworksDataState[],
|
||||||
selectedNetwork: NetworksDataState,
|
selectedNetwork: NetworksDataState,
|
||||||
accounts: Account[],
|
accounts: Account[],
|
||||||
currentIndex: number,
|
|
||||||
) => {
|
) => {
|
||||||
const namespaceChainId = `${selectedNetwork.namespace}:${selectedNetwork.chainId}`;
|
const namespaceChainId = `${selectedNetwork.namespace}:${selectedNetwork.chainId}`;
|
||||||
|
|
||||||
@ -101,23 +100,6 @@ export const getNamespaces = async (
|
|||||||
const requiredAddressesArray = await Promise.all(requiredAddressesPromise);
|
const requiredAddressesArray = await Promise.all(requiredAddressesPromise);
|
||||||
const requiredAddresses = requiredAddressesArray.flat();
|
const requiredAddresses = requiredAddressesArray.flat();
|
||||||
|
|
||||||
let sortedAccounts = requiredAddresses;
|
|
||||||
|
|
||||||
// If selected network is included in chains requested from dApp,
|
|
||||||
// Put selected account as first account
|
|
||||||
if (walletConnectChains.includes(namespaceChainId)) {
|
|
||||||
const currentAddresses = requiredAddresses.filter(address =>
|
|
||||||
address.includes(namespaceChainId),
|
|
||||||
);
|
|
||||||
sortedAccounts = [
|
|
||||||
currentAddresses[currentIndex],
|
|
||||||
...currentAddresses.filter((address, index) => index !== currentIndex),
|
|
||||||
...requiredAddresses.filter(
|
|
||||||
address => !currentAddresses.includes(address),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// construct namespace object
|
// construct namespace object
|
||||||
const newNamespaces = {
|
const newNamespaces = {
|
||||||
eip155: {
|
eip155: {
|
||||||
@ -133,7 +115,7 @@ export const getNamespaces = async (
|
|||||||
...(optionalNamespaces.eip155?.events ?? []),
|
...(optionalNamespaces.eip155?.events ?? []),
|
||||||
...(requiredNamespaces.eip155?.events ?? []),
|
...(requiredNamespaces.eip155?.events ?? []),
|
||||||
],
|
],
|
||||||
accounts: sortedAccounts.filter(account => account.includes(EIP155)),
|
accounts: requiredAddresses.filter(account => account.includes(EIP155)),
|
||||||
},
|
},
|
||||||
cosmos: {
|
cosmos: {
|
||||||
chains: walletConnectChains.filter(chain => chain.includes(COSMOS)),
|
chains: walletConnectChains.filter(chain => chain.includes(COSMOS)),
|
||||||
@ -147,18 +129,12 @@ export const getNamespaces = async (
|
|||||||
...(optionalNamespaces.cosmos?.events ?? []),
|
...(optionalNamespaces.cosmos?.events ?? []),
|
||||||
...(requiredNamespaces.cosmos?.events ?? []),
|
...(requiredNamespaces.cosmos?.events ?? []),
|
||||||
],
|
],
|
||||||
accounts: sortedAccounts.filter(account => account.includes(COSMOS)),
|
accounts: requiredAddresses.filter(account => account.includes(COSMOS)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return newNamespaces;
|
return newNamespaces;
|
||||||
} else {
|
} else {
|
||||||
// Set selected account as the first account in supported namespaces
|
|
||||||
const sortedAccounts = [
|
|
||||||
accounts[currentIndex],
|
|
||||||
...accounts.filter((account, index) => index !== currentIndex),
|
|
||||||
];
|
|
||||||
|
|
||||||
switch (selectedNetwork.namespace) {
|
switch (selectedNetwork.namespace) {
|
||||||
case EIP155:
|
case EIP155:
|
||||||
return {
|
return {
|
||||||
@ -175,7 +151,7 @@ export const getNamespaces = async (
|
|||||||
...(optionalNamespaces.eip155?.events ?? []),
|
...(optionalNamespaces.eip155?.events ?? []),
|
||||||
...(requiredNamespaces.eip155?.events ?? []),
|
...(requiredNamespaces.eip155?.events ?? []),
|
||||||
],
|
],
|
||||||
accounts: sortedAccounts.map(ethAccount => {
|
accounts: accounts.map(ethAccount => {
|
||||||
return `${namespaceChainId}:${ethAccount.address}`;
|
return `${namespaceChainId}:${ethAccount.address}`;
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@ -200,7 +176,7 @@ export const getNamespaces = async (
|
|||||||
...(optionalNamespaces.cosmos?.events ?? []),
|
...(optionalNamespaces.cosmos?.events ?? []),
|
||||||
...(requiredNamespaces.cosmos?.events ?? []),
|
...(requiredNamespaces.cosmos?.events ?? []),
|
||||||
],
|
],
|
||||||
accounts: sortedAccounts.map(cosmosAccount => {
|
accounts: accounts.map(cosmosAccount => {
|
||||||
return `${namespaceChainId}:${cosmosAccount.address}`;
|
return `${namespaceChainId}:${cosmosAccount.address}`;
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
@ -2071,6 +2071,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
merge-options "^3.0.4"
|
merge-options "^3.0.4"
|
||||||
|
|
||||||
|
"@react-native-clipboard/clipboard@^1.14.1":
|
||||||
|
version "1.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@react-native-clipboard/clipboard/-/clipboard-1.14.1.tgz#835f82fc86881a0808a8405f2576617bb5383554"
|
||||||
|
integrity sha512-SM3el0A28SwoeJljVNhF217o0nI4E7RfalLmuRQcT1/7tGcxUjgFa3jyrEndYUct8/uxxK5EUNGUu1YEDqzxqw==
|
||||||
|
|
||||||
"@react-native-community/cli-clean@12.3.2":
|
"@react-native-community/cli-clean@12.3.2":
|
||||||
version "12.3.2"
|
version "12.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.2.tgz#d4f1730c3d22d816b4d513d330d5f3896a3f5921"
|
resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-12.3.2.tgz#d4f1730c3d22d816b4d513d330d5f3896a3f5921"
|
||||||
|
Loading…
Reference in New Issue
Block a user