Add method to send cosmos tokens (#66)

* Add support to send cosmos tokens

* Fix approve transaction page ui

* Take gas amount from dApp

* Handle review changes

* Add check while creating stargate client

* Remove unnecessary checks

* Remove unnecessary states

* Fix balance showing undefined while loading
This commit is contained in:
shreerang6921 2024-03-27 18:09:01 +05:30 committed by GitHub
parent b275f376c4
commit 3a2087b389
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 474 additions and 130 deletions

1
.env
View File

@ -1 +1,2 @@
WALLET_CONNECT_PROJECT_ID=

View File

@ -14,6 +14,7 @@
"@cosmjs/amino": "^0.32.3",
"@cosmjs/crypto": "^0.32.3",
"@cosmjs/proto-signing": "^0.32.3",
"@cosmjs/stargate": "^0.32.3",
"@ethersproject/shims": "^5.7.0",
"@json-rpc-tools/utils": "^1.7.6",
"@react-native-async-storage/async-storage": "^1.22.3",

View File

@ -120,6 +120,17 @@ const App = (): React.JSX.Element => {
});
break;
case 'cosmos_sendTokens':
navigation.navigate('ApproveTransaction', {
network: 'cosmos',
transaction: request.params[0],
requestEvent,
requestSessionData,
});
break;
default:
throw new Error('Invalid method');
}

View File

@ -9,6 +9,12 @@ import {
NativeStackScreenProps,
} from '@react-navigation/native-stack';
import { getHeaderTitle } from '@react-navigation/elements';
import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing';
import {
calculateFee,
GasPrice,
SigningStargateClient,
} from '@cosmjs/stargate';
import { Account, StackParamsList } from '../types';
import AccountDetails from '../components/AccountDetails';
@ -19,11 +25,11 @@ import {
rejectWalletConnectRequest,
} from '../utils/wallet-connect/WalletConnectRequests';
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
import {
TEIP155Chain,
EIP155_CHAINS,
} from '../utils/wallet-connect/EIP155Data';
import { EIP155_CHAINS } from '../utils/wallet-connect/EIP155Data';
import DataBox from '../components/DataBox';
import { getPathKey } from '../utils/misc';
import { COSMOS_TESTNET_CHAINS } from '../utils/wallet-connect/COSMOSData';
import { COSMOS_DENOM } from '../utils/constants';
type SignRequestProps = NativeStackScreenProps<
StackParamsList,
@ -31,87 +37,69 @@ type SignRequestProps = NativeStackScreenProps<
>;
const ApproveTransaction = ({ route }: SignRequestProps) => {
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 requestSession = route.params.requestSessionData;
const requestName = requestSession.peer.metadata.name;
const requestIcon = requestSession.peer.metadata.icons[0];
const requestURL = requestSession.peer.metadata.url;
const network = route.params.network;
const transaction = route.params.transaction;
const requestEvent = route.params.requestEvent;
const chainId = requestEvent.params.chainId;
const [account, setAccount] = useState<Account>();
const [transactionData, setTransactionData] =
useState<PopulatedTransaction>();
const [network, setNetwork] = useState<string>('');
const [isLoading, setIsLoading] = useState(true);
const [balance, setBalance] = useState<string>('');
const [cosmosStargateClient, setCosmosStargateClient] =
useState<SigningStargateClient>();
const requestParams = route.params!.requestEvent;
const chainId = requestParams?.params.chainId;
const provider = useMemo(() => {
return new providers.JsonRpcProvider(
EIP155_CHAINS[chainId as TEIP155Chain].rpc,
);
}, [chainId]);
if (network === 'eth') {
return new providers.JsonRpcProvider(EIP155_CHAINS[chainId].rpc);
}
}, [chainId, network]);
const navigation =
useNavigation<NativeStackNavigationProp<StackParamsList>>();
const retrieveData = async (
requestNetwork: string,
requestAddress: string,
) => {
const requestAccount = await retrieveSingleAccount(
requestNetwork,
requestAddress,
);
const retrieveData = async (requestAddress: string) => {
const requestAccount = await retrieveSingleAccount(network, requestAddress);
if (!requestAccount) {
navigation.navigate('InvalidPath');
return;
}
if (requestAccount !== account) {
setAccount(requestAccount);
}
if (requestNetwork !== network) {
setNetwork(requestNetwork);
}
if (route.params?.transaction) {
setTransactionData(route.params?.transaction);
}
setIsLoading(false);
};
const gasFees = useMemo(() => {
if (!transactionData) {
return;
}
return BigNumber.from(transactionData?.gasLimit)
.mul(BigNumber.from(transactionData?.gasPrice))
if (network === 'eth') {
return BigNumber.from(transaction.gasLimit)
.mul(BigNumber.from(transaction.gasPrice))
.toString();
}, [transactionData]);
} else {
const gasPrice = GasPrice.fromString(transaction.gasPrice!.toString());
const cosmosFees = calculateFee(Number(transaction.gasLimit), gasPrice);
return cosmosFees.amount[0].amount;
}
}, [transaction, network]);
useEffect(() => {
route.params &&
retrieveData(route.params?.network, route.params?.transaction.from!);
retrieveData(transaction.from!);
}, [route]);
const acceptRequestHandler = async () => {
const { requestEvent } = route.params || {};
if (!account) {
throw new Error('account not found');
}
if (!requestEvent) {
throw new Error('Request event not found');
}
const response = await approveWalletConnectRequest(
requestEvent,
account,
network,
'',
provider,
network === 'eth' ? provider : cosmosStargateClient,
);
const { topic } = requestEvent;
@ -121,27 +109,37 @@ const ApproveTransaction = ({ route }: SignRequestProps) => {
};
const rejectRequestHandler = async () => {
if (route.params?.requestEvent) {
const response = rejectWalletConnectRequest(route.params?.requestEvent);
const { topic } = route.params?.requestEvent;
const response = rejectWalletConnectRequest(requestEvent);
const { topic } = requestEvent;
await web3wallet!.respondSessionRequest({
topic,
response,
});
}
navigation.navigate('Laconic');
};
useEffect(() => {
const getAccountBalance = async (account: Account) => {
const fetchedBalance = await provider.getBalance(account.address);
setBalance(fetchedBalance.toString());
if (network === 'eth') {
const fetchedBalance =
provider && (await provider.getBalance(account.address));
setBalance(fetchedBalance ? fetchedBalance.toString() : '0');
} else {
const cosmosBalance = await cosmosStargateClient?.getBalance(
account.address,
COSMOS_DENOM,
);
setBalance(cosmosBalance?.amount!);
}
};
if (account) {
getAccountBalance(account);
}
}, [account, provider]);
}, [account, provider, network, cosmosStargateClient]);
useEffect(() => {
navigation.setOptions({
@ -167,6 +165,34 @@ const ApproveTransaction = ({ route }: SignRequestProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [navigation, route.name]);
useEffect(() => {
if (network !== 'cosmos') {
return;
}
const setClient = async () => {
if (!account) {
return;
}
const cosmosPrivKey = (await getPathKey('cosmos', account.counterId))
.privKey;
const sender = await DirectSecp256k1Wallet.fromKey(
Buffer.from(cosmosPrivKey.split('0x')[1], 'hex'),
);
const client = await SigningStargateClient.connectWithSigner(
COSMOS_TESTNET_CHAINS[chainId as string].rpc,
sender,
);
setCosmosStargateClient(client);
};
setClient();
}, [account, chainId, network]);
return (
<>
{isLoading ? (
@ -174,7 +200,7 @@ const ApproveTransaction = ({ route }: SignRequestProps) => {
<ActivityIndicator size="large" color="#0000ff" />
</View>
) : (
<ScrollView style={styles.appContainer}>
<ScrollView contentContainerStyle={styles.appContainer}>
<View style={styles.dappDetails}>
{requestIcon && (
<Image
@ -192,20 +218,33 @@ const ApproveTransaction = ({ route }: SignRequestProps) => {
</View>
</View>
<DataBox
label="Balance (Wei)"
data={balance !== '' ? `${balance}` : 'Loading balance...'}
label={`Balance ${
network === 'eth' ? '(Wei)' : `(${COSMOS_DENOM})`
}`}
data={
balance === '' || balance === undefined
? 'Loading balance...'
: `${balance}`
}
/>
{transactionData && (
{transaction && (
<View style={styles.approveTransaction}>
<DataBox label="To" data={transactionData.to!} />
<DataBox label="To" data={transaction.to!} />
<DataBox
label="Amount (Wei)"
data={BigNumber.from(
transactionData.value?.toString(),
).toString()}
label={`Amount ${
network === 'eth' ? '(Wei)' : `(${COSMOS_DENOM})`
}`}
data={BigNumber.from(transaction.value?.toString()).toString()}
/>
<DataBox label="Gas Fees (Wei)" data={gasFees!} />
<DataBox label="Data" data={transactionData.data!} />
<DataBox
label={`Gas Fees ${
network === 'eth' ? '(Wei)' : `(${COSMOS_DENOM})`
}`}
data={gasFees!}
/>
{network === 'eth' && (
<DataBox label="Data" data={transaction.data!} />
)}
</View>
)}
<View style={styles.buttonContainer}>

View File

@ -12,23 +12,18 @@ import AccountDetails from '../components/AccountDetails';
type SignProps = NativeStackScreenProps<StackParamsList, 'SignMessage'>;
const SignMessage = ({ route }: SignProps) => {
const network = route.params?.selectedNetwork;
const account = route.params?.accountInfo;
const network = route.params.selectedNetwork;
const account = route.params.accountInfo;
const [message, setMessage] = useState<string>('');
const signMessageHandler = async () => {
if (network) {
if (!account) {
throw new Error('Account is not valid');
}
const signedMessage = await signMessage({
message,
network,
accountId: account.counterId,
});
Alert.alert('Signature', signedMessage);
}
};
return (

View File

@ -24,7 +24,7 @@ import { EIP155_SIGNING_METHODS } from '../utils/wallet-connect/EIP155Data';
type SignRequestProps = NativeStackScreenProps<StackParamsList, 'SignRequest'>;
const SignRequest = ({ route }: SignRequestProps) => {
const requestSession = route.params?.requestSessionData;
const requestSession = route.params.requestSessionData;
const requestName = requestSession?.peer?.metadata?.name;
const requestIcon = requestSession?.peer?.metadata?.icons[0];
const requestURL = requestSession?.peer?.metadata?.url;
@ -38,7 +38,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
useNavigation<NativeStackNavigationProp<StackParamsList>>();
const isCosmosSignDirect = useMemo(() => {
const requestParams = route.params!.requestEvent;
const requestParams = route.params.requestEvent;
if (!requestParams) {
return false;
@ -48,7 +48,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
}, [route.params]);
const isEthSendTransaction = useMemo(() => {
const requestParams = route.params!.requestEvent;
const requestParams = route.params.requestEvent;
if (!requestParams) {
return false;
@ -107,24 +107,22 @@ const SignRequest = ({ route }: SignRequestProps) => {
if (route.path) {
const sanitizedRoute = sanitizePath(route.path);
sanitizedRoute &&
route.params &&
retrieveData(
route.params?.network,
route.params?.address,
route.params?.message,
route.params.network,
route.params.address,
route.params.message,
);
return;
}
route.params &&
retrieveData(
route.params?.network,
route.params?.address,
route.params?.message,
route.params.network,
route.params.address,
route.params.message,
);
}, [route]);
const handleWalletConnectRequest = async () => {
const { requestEvent } = route.params || {};
const { requestEvent } = route.params;
if (!account) {
throw new Error('account not found');
@ -160,7 +158,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
};
const signMessageHandler = async () => {
if (route.params?.requestEvent) {
if (route.params.requestEvent) {
await handleWalletConnectRequest();
} else {
await handleIntent();
@ -170,9 +168,9 @@ const SignRequest = ({ route }: SignRequestProps) => {
};
const rejectRequestHandler = async () => {
if (route.params?.requestEvent) {
const response = rejectWalletConnectRequest(route.params?.requestEvent);
const { topic } = route.params?.requestEvent;
if (route.params.requestEvent) {
const response = rejectWalletConnectRequest(route.params.requestEvent);
const { topic } = route.params.requestEvent;
await web3wallet!.respondSessionRequest({
topic,
response,
@ -212,7 +210,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
<ActivityIndicator size="large" color="#0000ff" />
</View>
) : (
<ScrollView style={styles.appContainer}>
<ScrollView contentContainerStyle={styles.appContainer}>
<View style={styles.dappDetails}>
{requestIcon && (
<Image

View File

@ -135,7 +135,6 @@ const styles = StyleSheet.create({
height: '40%',
},
buttonContainer: {
marginTop: 50,
flexDirection: 'row',
marginLeft: 20,
justifyContent: 'space-evenly',

View File

@ -5,24 +5,20 @@ import { Web3WalletTypes } from '@walletconnect/web3wallet';
export type StackParamsList = {
Laconic: undefined;
SignMessage: { selectedNetwork: string; accountInfo: Account } | undefined;
SignRequest:
| {
SignMessage: { selectedNetwork: string; accountInfo: Account };
SignRequest: {
network: string;
address: string;
message: string;
requestEvent?: Web3WalletTypes.SessionRequest;
requestSessionData?: SessionTypes.Struct;
}
| undefined;
ApproveTransaction:
| {
};
ApproveTransaction: {
network: string;
transaction: PopulatedTransaction;
requestEvent?: Web3WalletTypes.SessionRequest;
requestSessionData?: SessionTypes.Struct;
}
| undefined;
requestEvent: Web3WalletTypes.SessionRequest;
requestSessionData: SessionTypes.Struct;
};
InvalidPath: undefined;
WalletConnect: undefined;
AddSession: undefined;

1
src/utils/constants.ts Normal file
View File

@ -0,0 +1 @@
export const COSMOS_DENOM = 'uatom';

View File

@ -0,0 +1,37 @@
// Taken from https://github.com/WalletConnect/web-examples/blob/main/advanced/wallets/react-wallet-v2/src/data/COSMOSData.ts
/**
* Types
*/
export type TCosmosChain = keyof typeof COSMOS_TESTNET_CHAINS;
/**
* Chains
*/
// Added for pay.laconic.com
export const COSMOS_TESTNET_CHAINS: Record<
string,
{
chainId: string;
name: string;
rpc: string;
namespace: string;
}
> = {
'cosmos:theta-testnet-001': {
chainId: 'theta-testnet-001',
name: 'Cosmos Hub Testnet',
rpc: 'https://rpc-t.cosmos.nodestake.top',
namespace: 'cosmos',
},
};
/**
* Methods
*/
export const COSMOS_METHODS = {
COSMOS_SIGN_DIRECT: 'cosmos_signDirect',
COSMOS_SIGN_AMINO: 'cosmos_signAmino',
COSMOS_SEND_TOKENS: 'cosmos_sendTokens', // Added for pay.laconic.com
};

View File

@ -4,19 +4,26 @@ import { Wallet, providers } from 'ethers';
import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils';
import { SignClientTypes } from '@walletconnect/types';
import { getSdkError } from '@walletconnect/utils';
import {
SigningStargateClient,
coins,
GasPrice,
calculateFee,
} from '@cosmjs/stargate';
import { EIP155_SIGNING_METHODS } from './EIP155Lib';
import { signDirectMessage, signEthMessage } from '../sign-message';
import { Account } from '../../types';
import { getMnemonic, getPathKey } from '../misc';
import { getCosmosAccounts } from '../accounts';
import { COSMOS_DENOM } from '../constants';
export async function approveWalletConnectRequest(
requestEvent: SignClientTypes.EventArguments['session_request'],
account: Account,
network: string,
message?: string,
provider?: providers.JsonRpcProvider,
provider?: providers.JsonRpcProvider | SigningStargateClient,
) {
const { params, id } = requestEvent;
const { request } = params;
@ -35,10 +42,17 @@ export async function approveWalletConnectRequest(
const privKey = (await getPathKey('eth', account.counterId)).privKey;
const wallet = new Wallet(privKey);
const sendTransaction = request.params[0];
const connectedWallet = await wallet.connect(provider);
if (!(provider instanceof providers.JsonRpcProvider)) {
throw new Error('Provider not found');
}
const connectedWallet = wallet.connect(provider);
const hash = await connectedWallet.sendTransaction(sendTransaction);
const receipt = typeof hash === 'string' ? hash : hash?.hash;
return formatJsonRpcResult(id, receipt);
return formatJsonRpcResult(id, {
signature: receipt,
});
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
if (!message) {
@ -46,7 +60,9 @@ export async function approveWalletConnectRequest(
}
const ethSignature = await signEthMessage(message, account.counterId);
return formatJsonRpcResult(id, ethSignature);
return formatJsonRpcResult(id, {
signature: ethSignature,
});
case 'cosmos_signDirect':
// Reference: https://github.com/confio/cosmjs-types/blob/66e52711914fccd2a9d1a03e392d3628fdf499e2/src/cosmos/tx/v1beta1/tx.ts#L51
@ -86,6 +102,34 @@ export async function approveWalletConnectRequest(
signature: cosmosAminoSignature.signature.signature,
});
case 'cosmos_sendTokens':
const amount = coins(request.params[0].value, COSMOS_DENOM);
const gasPrice = GasPrice.fromString(
request.params[0].gasPrice.toString(),
);
const cosmosFee = calculateFee(
Number(request.params[0].gasLimit),
gasPrice,
);
const receiverAddress = request.params[0].to;
if (!(provider instanceof SigningStargateClient)) {
throw new Error('Cosmos stargate client not found');
}
const result = await provider.sendTokens(
address,
receiverAddress,
amount,
cosmosFee,
'Sending signed tx from Laconic Wallet',
);
return formatJsonRpcResult(id, {
signature: result.transactionHash,
});
default:
throw new Error(getSdkError('INVALID_METHOD').message);
}

226
yarn.lock
View File

@ -1167,6 +1167,14 @@
deepmerge "^3.2.0"
hoist-non-react-statics "^3.3.0"
"@confio/ics23@^0.6.8":
version "0.6.8"
resolved "https://registry.yarnpkg.com/@confio/ics23/-/ics23-0.6.8.tgz#2a6b4f1f2b7b20a35d9a0745bb5a446e72930b3d"
integrity sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==
dependencies:
"@noble/hashes" "^1.0.0"
protobufjs "^6.8.8"
"@cosmjs/amino@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.32.3.tgz#b81d4a2b8d61568431a1afcd871e1344a19d97ff"
@ -1199,6 +1207,14 @@
bech32 "^1.1.4"
readonly-date "^1.0.0"
"@cosmjs/json-rpc@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.32.3.tgz#ccffdd7f722cecfab6daaa7463843b92f5d25355"
integrity sha512-JwFRWZa+Y95KrAG8CuEbPVOSnXO2uMSEBcaAB/FBU3Mo4jQnDoUjXvt3vwtFWxfAytrWCn1I4YDFaOAinnEG/Q==
dependencies:
"@cosmjs/stream" "^0.32.3"
xstream "^11.14.0"
"@cosmjs/math@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.32.3.tgz#16e4256f4da507b9352327da12ae64056a2ba6c9"
@ -1218,6 +1234,55 @@
"@cosmjs/utils" "^0.32.3"
cosmjs-types "^0.9.0"
"@cosmjs/socket@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.32.3.tgz#fa5c36bf58e87c0ad865d6318ecb0f8d9c89a28a"
integrity sha512-F2WwNmaUPdZ4SsH6Uyreq3wQk7jpaEkb3wfOP951f5Jt6HCW/PxbxhKzHkAAf6+Sqks6SPhkbWoE8XaZpjL2KA==
dependencies:
"@cosmjs/stream" "^0.32.3"
isomorphic-ws "^4.0.1"
ws "^7"
xstream "^11.14.0"
"@cosmjs/stargate@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.32.3.tgz#5a92b222ada960ebecea72cc9f366370763f4b66"
integrity sha512-OQWzO9YWKerUinPIxrO1MARbe84XkeXJAW0lyMIjXIEikajuXZ+PwftiKA5yA+8OyditVmHVLtPud6Pjna2s5w==
dependencies:
"@confio/ics23" "^0.6.8"
"@cosmjs/amino" "^0.32.3"
"@cosmjs/encoding" "^0.32.3"
"@cosmjs/math" "^0.32.3"
"@cosmjs/proto-signing" "^0.32.3"
"@cosmjs/stream" "^0.32.3"
"@cosmjs/tendermint-rpc" "^0.32.3"
"@cosmjs/utils" "^0.32.3"
cosmjs-types "^0.9.0"
xstream "^11.14.0"
"@cosmjs/stream@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.32.3.tgz#7522579aaf18025d322c2f33d6fb7573220395d6"
integrity sha512-J2zVWDojkynYifAUcRmVczzmp6STEpyiAARq0rSsviqjreGIfspfuws/8rmkPa6qQBZvpQOBQCm2HyZZwYplIw==
dependencies:
xstream "^11.14.0"
"@cosmjs/tendermint-rpc@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.32.3.tgz#f0406b9f0233e588fb924dca8c614972f9038aff"
integrity sha512-xeprW+VR9xKGstqZg0H/KBZoUp8/FfFyS9ljIUTLM/UINjP2MhiwncANPS2KScfJVepGufUKk0/phHUeIBSEkw==
dependencies:
"@cosmjs/crypto" "^0.32.3"
"@cosmjs/encoding" "^0.32.3"
"@cosmjs/json-rpc" "^0.32.3"
"@cosmjs/math" "^0.32.3"
"@cosmjs/socket" "^0.32.3"
"@cosmjs/stream" "^0.32.3"
"@cosmjs/utils" "^0.32.3"
axios "^1.6.0"
readonly-date "^1.0.0"
xstream "^11.14.0"
"@cosmjs/utils@^0.32.3":
version "0.32.3"
resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.32.3.tgz#5dcaee6dd7cc846cdc073e9a7a7f63242f5f7e31"
@ -1944,6 +2009,11 @@
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
"@noble/hashes@^1.0.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426"
integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@ -2062,6 +2132,59 @@
resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec"
integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug==
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==
"@protobufjs/base64@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
"@protobufjs/codegen@^2.0.4":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
"@protobufjs/eventemitter@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==
"@protobufjs/fetch@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==
dependencies:
"@protobufjs/aspromise" "^1.1.1"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/float@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==
"@protobufjs/inquire@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==
"@protobufjs/path@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==
"@protobufjs/pool@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==
"@protobufjs/utf8@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
"@react-native-async-storage/async-storage@^1.22.3":
version "1.22.3"
resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.22.3.tgz#ad490236a9eda8ac68cffc12c738f20b1815464e"
@ -2686,6 +2809,11 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
"@types/long@^4.0.1":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==
"@types/node@*":
version "20.11.16"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708"
@ -2693,6 +2821,13 @@
dependencies:
undici-types "~5.26.4"
"@types/node@>=13.7.0":
version "20.11.30"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f"
integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==
dependencies:
undici-types "~5.26.4"
"@types/node@^17.0.31":
version "17.0.45"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
@ -3323,6 +3458,11 @@ asynciterator.prototype@^1.0.0:
dependencies:
has-symbols "^1.0.3"
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
at-least-node@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
@ -3338,6 +3478,15 @@ available-typed-arrays@^1.0.5, available-typed-arrays@^1.0.6:
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz#ac812d8ce5a6b976d738e1c45f08d0b00bc7d725"
integrity sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==
axios@^1.6.0:
version "1.6.8"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66"
integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
babel-core@^7.0.0-bridge.0:
version "7.0.0-bridge.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece"
@ -3864,6 +4013,13 @@ colorette@^1.0.7:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
command-exists@^1.2.8:
version "1.2.9"
resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
@ -4120,6 +4276,11 @@ defu@^6.1.3, defu@^6.1.4:
resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
denodeify@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
@ -4881,6 +5042,11 @@ flow-parser@^0.206.0:
resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef"
integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==
follow-redirects@^1.15.6:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
for-each@^0.3.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
@ -4888,6 +5054,15 @@ for-each@^0.3.3:
dependencies:
is-callable "^1.1.3"
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@ -5040,7 +5215,7 @@ globals@^13.19.0:
dependencies:
type-fest "^0.20.2"
globalthis@^1.0.3:
globalthis@^1.0.1, globalthis@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
@ -5641,6 +5816,11 @@ isomorphic-unfetch@3.1.0, isomorphic-unfetch@^3.1.0:
node-fetch "^2.6.1"
unfetch "^4.2.0"
isomorphic-ws@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc"
integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==
istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756"
@ -6390,6 +6570,11 @@ logkitty@^0.7.1:
dayjs "^1.8.15"
yargs "^15.1.0"
long@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@ -6731,7 +6916,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.27, mime-types@~2.1.34:
mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
@ -7426,6 +7611,30 @@ prop-types@^15.7.2, prop-types@^15.8.1:
object-assign "^4.1.1"
react-is "^16.13.1"
protobufjs@^6.8.8:
version "6.11.4"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa"
integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==
dependencies:
"@protobufjs/aspromise" "^1.1.2"
"@protobufjs/base64" "^1.1.2"
"@protobufjs/codegen" "^2.0.4"
"@protobufjs/eventemitter" "^1.1.0"
"@protobufjs/fetch" "^1.1.0"
"@protobufjs/float" "^1.0.2"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/path" "^1.1.2"
"@protobufjs/pool" "^1.1.0"
"@protobufjs/utf8" "^1.1.0"
"@types/long" "^4.0.1"
"@types/node" ">=13.7.0"
long "^4.0.0"
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
public-encrypt@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
@ -8409,6 +8618,11 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
symbol-observable@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-2.0.3.tgz#5b521d3d07a43c351055fa43b8355b62d33fd16a"
integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==
system-architecture@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/system-architecture/-/system-architecture-0.1.0.tgz#71012b3ac141427d97c67c56bc7921af6bff122d"
@ -8933,6 +9147,14 @@ ws@^7, ws@^7.5.1:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
xstream@^11.14.0:
version "11.14.0"
resolved "https://registry.yarnpkg.com/xstream/-/xstream-11.14.0.tgz#2c071d26b18310523b6877e86b4e54df068a9ae5"
integrity sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==
dependencies:
globalthis "^1.0.1"
symbol-observable "^2.0.3"
xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"