From 06e75551a77325539eabc4a0f27fb1df033e6b8a Mon Sep 17 00:00:00 2001 From: David Adegoke <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 26 Aug 2026 04:45:03 +0100 Subject: [PATCH] CW-1615: Harden walletconnect auth (#3547) * fix android CI * fix: harden walletconnect auth so a connected session won't transfer on dApp when wallet is switched within the app * refactor: improve session mgmt and better error handling, also added a loader to the listing page * feat: switch to newer id for solana dapps connections and fix requests not triggering --- .../chain_service/eth/evm_chain_service.dart | 213 ++++++++++++++++-- .../chain_service/solana/solana_chain_id.dart | 6 +- .../solana/solana_chain_service.dart | 89 +++++++- .../wallet_connect_key_service.dart | 54 +++-- .../services/walletkit_service.dart | 143 +++++++----- .../wallet_connect/utils/method_utils.dart | 30 ++- .../wc_connections_listing_view.dart | 21 ++ lib/store/app_store.dart | 22 +- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fa.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_gn.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_hy.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_pt_BR.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_vi.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 39 files changed, 495 insertions(+), 114 deletions(-) diff --git a/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_service.dart b/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_service.dart index c8618d85f..e30fc2e54 100644 --- a/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_service.dart +++ b/lib/src/screens/wallet_connect/services/chain_service/eth/evm_chain_service.dart @@ -1,3 +1,4 @@ +import "dart:async"; import 'dart:convert'; import 'package:cake_wallet/di.dart'; @@ -5,6 +6,7 @@ import 'package:cake_wallet/entities/calculate_fiat_amount.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cw_core/crypto_currency.dart'; +import "package:cw_core/utils/print_verbose.dart"; import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:eth_sig_util/eth_sig_util.dart'; import 'package:eth_sig_util/util/utils.dart'; @@ -18,6 +20,7 @@ import 'package:cake_wallet/src/screens/wallet_connect/services/key_service/wall import 'package:cake_wallet/src/screens/wallet_connect/models/wc_connection_model.dart'; import 'package:cake_wallet/src/screens/wallet_connect/utils/eth_utils.dart'; import 'package:cake_wallet/src/screens/wallet_connect/utils/method_utils.dart'; +import "package:cake_wallet/src/screens/wallet_connect/widgets/bottom_sheet/bottom_sheet_message_display_widget.dart"; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/evm/evm.dart'; @@ -82,7 +85,9 @@ class EvmChainServiceImpl { if (appStore.wallet != null && isEVMCompatibleChain(appStore.wallet!.type)) { final walletClient = evm?.getWeb3Client(appStore.wallet!); - if (walletClient != null) return walletClient; + if (walletClient != null) { + return walletClient; + } } final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type); @@ -93,8 +98,18 @@ class EvmChainServiceImpl { Future personalSign(String topic, dynamic parameters) async { debugPrint('personalSign request: $parameters'); - final pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, EVMSupportedMethods.personalSign.name); + if (pRequest == null) { + return; + } + final address = EthUtils.getAddressFromSessionRequest(pRequest); + + if (!_isRequestAuthorized(topic, requestAddress: address)) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } + final data = EthUtils.getDataFromSessionRequest(pRequest); final message = EthUtils.getUtf8Message(data.toString()); var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); @@ -104,6 +119,7 @@ class EvmChainServiceImpl { method: pRequest.method, chainId: pRequest.chainId, address: address, + topic: topic, transportType: pRequest.transportType.name, verifyContext: pRequest.verifyContext, ); @@ -141,8 +157,18 @@ class EvmChainServiceImpl { Future ethSign(String topic, dynamic parameters) async { debugPrint('ethSign request: $parameters'); - final pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, EVMSupportedMethods.ethSign.name); + if (pRequest == null) { + return; + } + final address = EthUtils.getAddressFromSessionRequest(pRequest); + + if (!_isRequestAuthorized(topic, requestAddress: address)) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } + final data = EthUtils.getDataFromSessionRequest(pRequest); final message = EthUtils.getUtf8Message(data.toString()); var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); @@ -152,6 +178,7 @@ class EvmChainServiceImpl { method: pRequest.method, chainId: pRequest.chainId, address: address, + topic: topic, transportType: pRequest.transportType.name, verifyContext: pRequest.verifyContext, ); @@ -189,8 +216,18 @@ class EvmChainServiceImpl { Future ethSignTypedData(String topic, dynamic parameters) async { debugPrint('ethSignTypedData request: $parameters'); - final pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, EVMSupportedMethods.ethSignTypedData.name); + if (pRequest == null) { + return; + } + final address = EthUtils.getAddressFromSessionRequest(pRequest); + + if (!_isRequestAuthorized(topic, requestAddress: address)) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } + final data = EthUtils.getDataFromSessionRequest(pRequest) as String; var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); @@ -199,6 +236,7 @@ class EvmChainServiceImpl { method: pRequest.method, chainId: pRequest.chainId, address: address, + topic: topic, transportType: pRequest.transportType.name, verifyContext: pRequest.verifyContext, ); @@ -236,8 +274,18 @@ class EvmChainServiceImpl { final permitRequestMessage = await extractPermitData(parameters); - final pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, EVMSupportedMethods.ethSignTypedDataV4.name); + if (pRequest == null) { + return; + } + final address = EthUtils.getAddressFromSessionRequest(pRequest); + + if (!_isRequestAuthorized(topic, requestAddress: address)) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } + final data = EthUtils.getDataFromSessionRequest(pRequest) as String; var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); @@ -246,6 +294,7 @@ class EvmChainServiceImpl { method: pRequest.method, chainId: pRequest.chainId, address: address, + topic: topic, transportType: pRequest.transportType.name, verifyContext: pRequest.verifyContext, ); @@ -280,10 +329,22 @@ class EvmChainServiceImpl { Future ethSignTransaction(String topic, dynamic parameters) async { debugPrint('ethSignTransaction request: $parameters'); - final SessionRequest pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, EVMSupportedMethods.ethSignTransaction.name); + if (pRequest == null) { + return; + } + final data = EthUtils.getTransactionFromSessionRequest(pRequest); - if (data == null) return; + if (data == null) { + _respondMalformedRequest(topic, pRequest.id); + return; + } + + if (!_isRequestAuthorized(topic, requestAddress: data['from']?.toString())) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } final address = EthUtils.getAddressFromSessionRequest(pRequest); var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); @@ -293,6 +354,7 @@ class EvmChainServiceImpl { method: pRequest.method, chainId: pRequest.chainId, address: address, + topic: topic, transportType: pRequest.transportType.name, verifyContext: pRequest.verifyContext, ); @@ -333,10 +395,21 @@ class EvmChainServiceImpl { Future ethSendTransaction(String topic, dynamic parameters) async { debugPrint('ethSendTransaction request: $parameters'); - final SessionRequest pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, EVMSupportedMethods.ethSendTransaction.name); + if (pRequest == null) { + return; + } final data = EthUtils.getTransactionFromSessionRequest(pRequest); - if (data == null) return; + if (data == null) { + _respondMalformedRequest(topic, pRequest.id); + return; + } + + if (!_isRequestAuthorized(topic, requestAddress: data['from']?.toString())) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); @@ -344,6 +417,7 @@ class EvmChainServiceImpl { data, method: pRequest.method, chainId: pRequest.chainId, + topic: topic, transportType: pRequest.transportType.name, verifyContext: pRequest.verifyContext, ); @@ -379,6 +453,77 @@ class EvmChainServiceImpl { _handleResponseForTopic(topic, response); } + void _respondMalformedRequest(String topic, int requestId) { + final error = Errors.getSdkError(Errors.MALFORMED_REQUEST_PARAMS); + _handleResponseForTopic( + topic, + JsonRpcResponse( + id: requestId, + jsonrpc: "2.0", + error: JsonRpcError(code: error.code, message: error.message), + ), + ); + } + + SessionRequest? _pendingRequest(String topic, String method) { + final matches = walletKit.pendingRequests + .getAll() + .where((request) => request.topic == topic && request.method == method); + + return matches.isEmpty ? null : matches.last; + } + + bool _isRequestAuthorized(String topic, {String? requestAddress}) { + final wallet = appStore.wallet; + if (wallet == null) { + return false; + } + + final keys = wcKeyService.getKeysForChain(wallet); + if (keys.isEmpty) { + return false; + } + + final walletAddress = keys.first.publicKey; + + if (!MethodsUtils.isSessionOwnedByWallet(walletKit.sessions.get(topic), walletAddress)) { + return false; + } + + if (requestAddress != null && !MethodsUtils.isSameAccount(requestAddress, walletAddress)) { + return false; + } + + return true; + } + + Future _rejectUnauthorizedRequest(String topic, int requestId) async { + unawaited( + bottomSheetService.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget( + message: S.current.wc_request_for_different_wallet, + ), + ), + ); + + try { + await walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: requestId, + jsonrpc: "2.0", + error: const JsonRpcError( + code: 4100, + message: "The requested account has not been authorized by the user.", + ), + ), + ); + } catch (e) { + printV("rejectUnauthorizedRequest: $e"); + } + } + void _handleResponseForTopic(String topic, JsonRpcResponse response) async { final session = walletKit.sessions.get(topic); @@ -388,7 +533,9 @@ class EvmChainServiceImpl { response: response, ); - if (session == null) return; + if (session == null) { + return; + } MethodsUtils.handleRedirect( topic, @@ -397,7 +544,9 @@ class EvmChainServiceImpl { response.error == null, ); } on ReownSignError catch (error) { - if (session == null) return; + if (session == null) { + return; + } MethodsUtils.handleRedirect( topic, @@ -413,6 +562,7 @@ class EvmChainServiceImpl { String? method, String? chainId, String? address, + String? topic, VerifyContext? verifyContext, required String transportType, }) async { @@ -456,6 +606,7 @@ class EvmChainServiceImpl { method: method, chainId: chainId, address: address ?? transaction.from?.hex ?? '', + topic: topic, transportType: transportType, verifyContext: verifyContext, extraModels: feeRows, @@ -472,13 +623,17 @@ class EvmChainServiceImpl { String nativeSymbol, ) { final gasLimit = transaction.maxGas; - if (gasLimit == null || gasLimit <= 0) return const []; + if (gasLimit == null || gasLimit <= 0) { + return const []; + } final gasLimitBig = BigInt.from(gasLimit); final isEip1559 = transaction.isEIP1559; final perGasWei = isEip1559 ? transaction.maxFeePerGas?.getInWei : transaction.gasPrice?.getInWei; - if (perGasWei == null || perGasWei <= BigInt.zero) return const []; + if (perGasWei == null || perGasWei <= BigInt.zero) { + return const []; + } final feeWei = gasLimitBig * perGasWei; final feeNative = feeWei.toDouble() / 1e18; @@ -500,19 +655,25 @@ class EvmChainServiceImpl { ) { final cryptoPart = '${_formatNativeAmount(feeNative)} $nativeSymbol'; - if (nativeCurrency == null) return cryptoPart; + if (nativeCurrency == null) { + return cryptoPart; + } try { final fiatStore = getIt.get(); final price = fiatStore.prices[nativeCurrency]; - if (price == null || price <= 0) return cryptoPart; + if (price == null || price <= 0) { + return cryptoPart; + } final fiatSymbol = appStore.settingsStore.fiatCurrency.title; final fiatValue = calculateFiatAmount( price: price, cryptoAmount: feeNative.toString(), ); - if (fiatValue.isEmpty || fiatValue == '0.00') return cryptoPart; + if (fiatValue.isEmpty || fiatValue == '0.00') { + return cryptoPart; + } return '$cryptoPart (~ $fiatValue $fiatSymbol)'; } catch (_) { @@ -521,14 +682,20 @@ class EvmChainServiceImpl { } String _formatNativeAmount(double value) { - if (value == 0) return '0'; - if (value >= 0.0001) return value.toStringAsFixed(6); + if (value == 0) { + return '0'; + } + if (value >= 0.0001) { + return value.toStringAsFixed(6); + } return value.toStringAsExponential(4); } Future _ensureWCTransactionHasGasLimit(Transaction transaction) async { final hasGasLimit = transaction.maxGas != null && transaction.maxGas! > 0; - if (hasGasLimit) return transaction; + if (hasGasLimit) { + return transaction; + } final hint = transaction.gasPrice ?? transaction.maxFeePerGas ?? await ethClient.getGasPrice(); @@ -689,7 +856,9 @@ $messageDetails'''; final fieldType = field['type'] as String; final value = message[field['name'] as String]; - if (value == null) continue; + if (value == null) { + continue; + } if (types.containsKey(fieldType)) { final nestedFields = types[fieldType] as List; @@ -714,7 +883,9 @@ $messageDetails'''; } String _toCamelCase(String input) { - if (input.isEmpty) return input; + if (input.isEmpty) { + return input; + } return input[0].toUpperCase() + input.substring(1).toLowerCase(); } diff --git a/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_id.dart b/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_id.dart index c5a3c9d25..a4012cd57 100644 --- a/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_id.dart +++ b/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_id.dart @@ -1,4 +1,4 @@ -enum SolanaChainId { mainnet, devnet, testnet } +enum SolanaChainId { mainnet, mainnetLegacy, devnet, testnet } extension SolanaChainIdX on SolanaChainId { String chain() { @@ -6,8 +6,10 @@ extension SolanaChainIdX on SolanaChainId { switch (this) { case SolanaChainId.mainnet: + name = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"; + break; + case SolanaChainId.mainnetLegacy: name = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ'; - // '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'; break; case SolanaChainId.devnet: name = 'EtWTRABZaYq6iMfeYKouRu166VU2xqa1'; diff --git a/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_service.dart b/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_service.dart index b5d12f357..dfba2bf59 100644 --- a/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_service.dart +++ b/lib/src/screens/wallet_connect/services/chain_service/solana/solana_chain_service.dart @@ -1,16 +1,20 @@ +import "dart:async"; import 'dart:convert'; import 'package:blockchain_utils/base58/base58.dart'; import 'package:blockchain_utils/blockchain_utils.dart' as blockchain_utils; import 'package:cake_wallet/src/screens/wallet_connect/services/chain_service/solana/solana_supported_methods.dart'; +import "package:cw_core/utils/print_verbose.dart"; import 'package:flutter/material.dart'; import 'package:on_chain/solana/solana.dart'; import 'package:reown_walletkit/reown_walletkit.dart'; +import "package:cake_wallet/generated/i18n.dart"; import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart'; import 'package:cake_wallet/src/screens/wallet_connect/services/chain_service/solana/solana_chain_id.dart'; import 'package:cake_wallet/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart'; import 'package:cake_wallet/src/screens/wallet_connect/utils/method_utils.dart'; +import "package:cake_wallet/src/screens/wallet_connect/widgets/bottom_sheet/bottom_sheet_message_display_widget.dart"; import 'package:cake_wallet/store/app_store.dart'; class SolanaChainService { @@ -47,7 +51,16 @@ class SolanaChainService { Future solanaSignMessage(String topic, dynamic parameters) async { debugPrint('solanaSignMessage request: $parameters'); - final pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, SolanaSupportedMethods.solSignMessage.name); + if (pRequest == null) { + return; + } + + if (!_isRequestAuthorized(topic)) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } + var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); try { @@ -65,6 +78,7 @@ class SolanaChainService { method: pRequest.method, chainId: pRequest.chainId, address: privateKey.publicKey().toAddress().address, + topic: topic, transportType: pRequest.transportType.name, ); @@ -95,7 +109,16 @@ class SolanaChainService { Future solanaSignTransaction(String topic, dynamic parameters) async { debugPrint('solanaSignTransaction: ${jsonEncode(parameters)}'); - final pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, SolanaSupportedMethods.solSignTransaction.name); + if (pRequest == null) { + return; + } + + if (!_isRequestAuthorized(topic)) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } + var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); try { @@ -130,6 +153,7 @@ class SolanaChainService { method: pRequest.method, chainId: pRequest.chainId, address: privateKey.publicKey().toAddress().address, + topic: topic, transportType: pRequest.transportType.name, ); @@ -160,7 +184,16 @@ class SolanaChainService { Future solanaSignAllTransaction(String topic, dynamic parameters) async { debugPrint('solanaSignAllTransaction: ${jsonEncode(parameters)}'); - final pRequest = walletKit.pendingRequests.getAll().last; + final pRequest = _pendingRequest(topic, SolanaSupportedMethods.solSignAllTransaction.name); + if (pRequest == null) { + return; + } + + if (!_isRequestAuthorized(topic)) { + await _rejectUnauthorizedRequest(topic, pRequest.id); + return; + } + var response = JsonRpcResponse(id: pRequest.id, jsonrpc: '2.0'); try { @@ -174,6 +207,7 @@ class SolanaChainService { method: pRequest.method, chainId: pRequest.chainId, address: privateKey.publicKey().toAddress().address, + topic: topic, transportType: pRequest.transportType.name, ); @@ -224,6 +258,55 @@ class SolanaChainService { return SolanaPrivateKey.fromSeedHex(keys[0].privateKey); } + SessionRequest? _pendingRequest(String topic, String method) { + final matches = walletKit.pendingRequests + .getAll() + .where((request) => request.topic == topic && request.method == method); + + return matches.isEmpty ? null : matches.last; + } + + bool _isRequestAuthorized(String topic) { + final wallet = appStore.wallet; + if (wallet == null) { + return false; + } + + final keys = wcKeyService.getKeysForChain(wallet); + if (keys.isEmpty) { + return false; + } + + return MethodsUtils.isSessionOwnedByWallet(walletKit.sessions.get(topic), keys.first.publicKey); + } + + Future _rejectUnauthorizedRequest(String topic, int requestId) async { + unawaited( + bottomSheetService.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget( + message: S.current.wc_request_for_different_wallet, + ), + ), + ); + + try { + await walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: requestId, + jsonrpc: "2.0", + error: const JsonRpcError( + code: 4100, + message: "The requested account has not been authorized by the user.", + ), + ), + ); + } catch (e) { + printV("rejectUnauthorizedRequest: $e"); + } + } + void _handleResponseForTopic(String topic, JsonRpcResponse response) async { final session = walletKit.sessions.get(topic); diff --git a/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart b/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart index 38772da10..4d09213d7 100644 --- a/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart +++ b/lib/src/screens/wallet_connect/services/key_service/wallet_connect_key_service.dart @@ -43,30 +43,36 @@ class KeyServiceImpl implements WalletConnectKeyService { @override List getKeys(WalletBase wallet) { - final keys = [ - ChainKeyModel( - chains: [ - 'eip155:1', - 'eip155:5', - 'eip155:56', - 'eip155:137', - 'eip155:8453', - 'eip155:42161', - 'eip155:80001', - ], - privateKey: _getPrivateKeyForWallet(wallet), - publicKey: _getPublicKeyForWallet(wallet), - ), - ChainKeyModel( - chains: [ - 'solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ', // main-net - 'solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K', // test-net - ], - privateKey: _getPrivateKeyForWallet(wallet), - publicKey: _getPublicKeyForWallet(wallet), - ), - ]; - return keys; + if (isEVMCompatibleChain(wallet.type)) { + return [ + ChainKeyModel( + chains: [ + 'eip155:1', + 'eip155:56', + 'eip155:137', + 'eip155:8453', + 'eip155:42161', + ], + privateKey: _getPrivateKeyForWallet(wallet), + publicKey: _getPublicKeyForWallet(wallet), + ), + ]; + } + + if (wallet.type == WalletType.solana) { + return [ + ChainKeyModel( + chains: [ + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // main-net + 'solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ', // legacy main-net id older dapps still use + ], + privateKey: _getPrivateKeyForWallet(wallet), + publicKey: _getPublicKeyForWallet(wallet), + ), + ]; + } + + return []; } @override diff --git a/lib/src/screens/wallet_connect/services/walletkit_service.dart b/lib/src/screens/wallet_connect/services/walletkit_service.dart index aa3c26307..09c1432f5 100644 --- a/lib/src/screens/wallet_connect/services/walletkit_service.dart +++ b/lib/src/screens/wallet_connect/services/walletkit_service.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/util/utils.dart'; import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; @@ -42,7 +41,8 @@ abstract class WalletKitServiceBase with Store { ) : pairings = ObservableList(), sessions = ObservableList(), auth = ObservableList(), - isInitialized = false; + isInitialized = false, + isLoadingConnections = true; final AppStore appStore; final SharedPreferences sharedPreferences; @@ -54,6 +54,9 @@ abstract class WalletKitServiceBase with Store { @observable bool isInitialized; + @observable + bool isLoadingConnections; + /// The list of requests from the dapp @observable ObservableList pairings; @@ -91,33 +94,23 @@ abstract class WalletKitServiceBase with Store { _walletKit.onSessionProposal.subscribe(_onSessionProposal); _walletKit.onSessionProposalError.subscribe(_onSessionProposalError); _walletKit.onSessionConnect.subscribe(_onSessionConnect); - _walletKit.onSessionAuthRequest.subscribe(_onSessionAuthRequest); + + if (isEVMCompatibleChain(appStore.wallet!.type)) { + _walletKit.onSessionAuthRequest.subscribe(_onSessionAuthRequest); + } _walletKit.pairings.onSync.subscribe(_onPairingsSync); _walletKit.core.pairing.onPairingDelete.subscribe(_onPairingDelete); _walletKit.core.pairing.onPairingExpire.subscribe(_onPairingDelete); // Setup our accounts - List chainKeys = walletKeyService.getKeys(appStore.wallet!); + final chainKeys = walletKeyService.getKeys(appStore.wallet!); for (final chainKey in chainKeys) { for (final chainId in chainKey.chains) { - if (isEVMCompatibleChain(appStore.wallet!.type)) { - // Register account for all EVM chains (chainId is already in eip155:format) - _walletKit.registerAccount( - chainId: chainId, - accountAddress: chainKey.publicKey, - ); - } else { - final chainNameSpace = getChainNameSpaceAndIdBasedOnWalletType( - appStore.wallet!.type, - ); - if (chainNameSpace == chainId) { - _walletKit.registerAccount( - chainId: chainId, - accountAddress: chainKey.publicKey, - ); - } - } + _walletKit.registerAccount( + chainId: chainId, + accountAddress: chainKey.publicKey, + ); } } } @@ -144,42 +137,43 @@ abstract class WalletKitServiceBase with Store { } } - await _emitEvent(); - _refreshPairings(); - sessions.clear(); - auth.clear(); + _reloadSessionsForCurrentWallet(); - final newSessions = _walletKit.sessions.getAll(); - sessions.addAll(newSessions); + auth.clear(); final newAuthRequests = _walletKit.sessionAuthRequests.getAll(); auth.addAll(newAuthRequests); - if (isEVMCompatibleChain(appStore.wallet!.type)) { - for (final cId in EVMChainId.values) { - EvmChainServiceImpl( - reference: cId, - appStore: appStore, - wcKeyService: walletKeyService, - bottomSheetService: _bottomSheetHandler, - walletKit: _walletKit, - ); - } + isLoadingConnections = false; + for (final cId in EVMChainId.values) { + EvmChainServiceImpl( + reference: cId, + appStore: appStore, + wcKeyService: walletKeyService, + bottomSheetService: _bottomSheetHandler, + walletKit: _walletKit, + ); } - if (appStore.wallet!.type == WalletType.solana) { - for (final cId in SolanaChainId.values) { - SolanaChainService( - reference: cId, - appStore: appStore, - wcKeyService: walletKeyService, - bottomSheetService: _bottomSheetHandler, - walletKit: _walletKit, - ); - } + for (final cId in SolanaChainId.values) { + SolanaChainService( + reference: cId, + appStore: appStore, + wcKeyService: walletKeyService, + bottomSheetService: _bottomSheetHandler, + walletKit: _walletKit, + ); } + + unawaited(() async { + try { + await _emitEvent(); + } catch (e) { + printV("emitEvent failed: $e"); + } + }()); } @action @@ -195,6 +189,10 @@ abstract class WalletKitServiceBase with Store { for (var session in engineSessions) { final chainKeys = walletKeyService.getKeysForChain(appStore.wallet!); for (var chain in chainKeys) { + if (!MethodsUtils.isSessionOwnedByWallet(session, chain.publicKey)) { + continue; + } + for (var chainID in chain.chains) { try { final events = NamespaceUtils.getNamespacesEventsForChain( @@ -228,8 +226,21 @@ abstract class WalletKitServiceBase with Store { } @action - FutureOr onDispose() { - log('walletKit dispose'); + void resetConnectionsState() { + sessions.clear(); + auth.clear(); + pairings.clear(); + + isInitialized = false; + isLoadingConnections = true; + } + + @action + Future onDispose() async { + log("walletKit dispose"); + + resetConnectionsState(); + _walletKit.core.removeLogListener(_logListener); _walletKit.core.pairing.onPairingInvalid.unsubscribe(_onPairingInvalid); @@ -246,11 +257,11 @@ abstract class WalletKitServiceBase with Store { _walletKit.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete); _walletKit.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete); - sessions.clear(); - auth.clear(); - pairings.clear(); - - isInitialized = false; + try { + await _walletKit.core.relayClient.disconnect().timeout(const Duration(seconds: 3)); + } catch (e) { + printV("walletKit relay disconnect: $e"); + } } ReownWalletKit get walletKit => _walletKit; @@ -534,8 +545,7 @@ abstract class WalletKitServiceBase with Store { } await _removePairingTopicFromLocalStorage(topic); - sessions.clear(); - sessions.addAll(_walletKit.sessions.getAll()); + _reloadSessionsForCurrentWallet(); _refreshPairings(); } @@ -559,8 +569,7 @@ abstract class WalletKitServiceBase with Store { printV('disconnectSession: $e'); } - sessions.clear(); - sessions.addAll(_walletKit.sessions.getAll()); + _reloadSessionsForCurrentWallet(); if (pairingTopic != null && !_walletKit.sessions.getAll().any((s) => s.pairingTopic == pairingTopic)) { @@ -619,6 +628,24 @@ abstract class WalletKitServiceBase with Store { pairings.addAll(filteredPairings); } + @action + void _reloadSessionsForCurrentWallet() { + sessions.clear(); + + final chainKeys = walletKeyService.getKeysForChain(appStore.wallet!); + if (chainKeys.isEmpty) { + return; + } + + final walletPublicKey = chainKeys.first.publicKey; + + sessions.addAll( + _walletKit.sessions + .getAll() + .where((session) => MethodsUtils.isSessionOwnedByWallet(session, walletPublicKey)), + ); + } + @action List getSessionsForPairingInfo(PairingInfo pairing) { return sessions.where((element) => element.pairingTopic == pairing.topic).toList(); diff --git a/lib/src/screens/wallet_connect/utils/method_utils.dart b/lib/src/screens/wallet_connect/utils/method_utils.dart index 78a11f871..9a0e83a59 100644 --- a/lib/src/screens/wallet_connect/utils/method_utils.dart +++ b/lib/src/screens/wallet_connect/utils/method_utils.dart @@ -11,9 +11,27 @@ import 'package:flutter/material.dart'; import 'package:reown_walletkit/reown_walletkit.dart'; class MethodsUtils { - static final walletKit = getIt.get().walletKit; + static ReownWalletKit get walletKit => getIt.get().walletKit; static final bottomSheetService = getIt.get(); + static bool isSessionOwnedByWallet(SessionData? session, String walletPublicKey) { + if (session == null || walletPublicKey.isEmpty) { + return false; + } + + final accounts = session.namespaces.values.expand((namespace) => namespace.accounts); + + return accounts.any((account) => isSameAccount(account.split(":").last, walletPublicKey)); + } + + static bool isSameAccount(String a, String b) { + if (a.startsWith("0x") && b.startsWith("0x")) { + return a.toLowerCase() == b.toLowerCase(); + } + + return a == b; + } + static const _transactionMethods = { 'eth_sendTransaction', 'eth_signTransaction', @@ -28,13 +46,19 @@ class MethodsUtils { String? method, String? chainId, String? address, + String? topic, required String transportType, List extraModels = const [], VerifyContext? verifyContext, }) async { final appStore = getIt.get(); - final pending = walletKit.pendingRequests.getAll(); - final session = pending.isNotEmpty ? walletKit.sessions.get(pending.last.topic) : null; + SessionData? session; + if (topic != null) { + session = walletKit.sessions.get(topic); + } else { + final pending = walletKit.pendingRequests.getAll(); + session = pending.isNotEmpty ? walletKit.sessions.get(pending.last.topic) : null; + } final dAppMetadata = session?.peer.metadata; final isTransaction = method != null && _transactionMethods.contains(method); diff --git a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart index b422b801b..f688994ce 100644 --- a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart +++ b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/permission_handler.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import "package:flutter/cupertino.dart"; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -145,6 +146,26 @@ class WalletConnectConnectionsView extends StatelessWidget { const SizedBox(height: 24), Observer( builder: (_) { + if (walletKitService.isLoadingConnections) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 32), + child: Center( + child: Column( + spacing: 12, + children: [ + const CupertinoActivityIndicator(), + Text( + "${S.of(context).loading}...", + style: theme.textTheme.bodyMedium?.copyWith( + color: colors.onSurfaceVariant, + ), + ), + ], + ), + ), + ); + } + if (walletKitService.pairings.isEmpty) { return Padding( padding: const EdgeInsets.symmetric(vertical: 32), diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart index 85a9bbba5..706a9a0ea 100644 --- a/lib/store/app_store.dart +++ b/lib/store/app_store.dart @@ -1,5 +1,3 @@ -import "dart:async"; - import "package:cake_wallet/core/amount_parsing_proxy.dart"; import "package:cake_wallet/di.dart"; import "package:cake_wallet/entities/preferences_key.dart"; @@ -60,13 +58,17 @@ abstract class AppStoreBase with Store { Future changeCurrentWallet( WalletBase, TransactionInfo> wallet) async { final changingToSameWalletType = this.wallet?.type == wallet.type; + final previousWalletType = this.wallet?.type; await this.wallet?.close(shouldCleanup: !changingToSameWalletType); this.wallet = wallet; this.wallet!.setExceptionHandler(ExceptionHandler.onError); if (isWalletConnectCompatibleChain(wallet.type)) { - unawaited(_setupWalletConnect()); + getIt.get().resetConnectionsState(); + _queueWalletConnectAction(_setupWalletConnect); + } else if (previousWalletType != null && isWalletConnectCompatibleChain(previousWalletType)) { + _queueWalletConnectAction(_disposeWalletConnect); } await getIt.get().setString(PreferencesKey.currentWalletName, wallet.name); await getIt @@ -74,6 +76,12 @@ abstract class AppStoreBase with Store { .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type)); } + Future _lastWalletConnectAction = Future.value(); + + void _queueWalletConnectAction(Future Function() action) { + _lastWalletConnectAction = _lastWalletConnectAction.then((_) => action()); + } + Future _setupWalletConnect() async { try { final wcService = getIt.get(); @@ -84,4 +92,12 @@ abstract class AppStoreBase with Store { printV("WalletConnect setup failed: $e\n$s"); } } + + Future _disposeWalletConnect() async { + try { + await getIt.get().onDispose(); + } catch (e) { + printV("WalletConnect teardown failed: $e"); + } + } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 24f501597..3b13b21dc 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "توقيع الرسائل والبيانات المكتوبة", "wc_permission_switch_chains": "قم بالتبديل وإضافة سلاسل EVM", "wc_permission_view_balance": "عرض رصيد محفظتك ونشاطك", + "wc_request_for_different_wallet": "تم تقديم هذا الطلب لمحفظة مختلفة. افتح المحفظة المتصلة بهذا التطبيق وحاول مرة أخرى.", "wc_scam_warning_message": "يبدو أن هذا الطلب مرسل من عملية احتيال معروفة. يرجى المضي قدما بحذر.", "wc_scam_warning_title": "تحذير!", "wc_scan_qr": "مسح QR", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b443d1af8..c94868932 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Подписвайте съобщения и въведени данни", "wc_permission_switch_chains": "Превключете и добавете EVM вериги", "wc_permission_view_balance": "Вижте баланса и активността на вашия портфейл", + "wc_request_for_different_wallet": "Тази заявка е направена за различен портфейл. Отворете портфейла, свързан с това приложение, и опитайте отново.", "wc_scam_warning_message": "Тази заявка изглежда е от известна измама. Моля, продължете с повишено внимание.", "wc_scam_warning_title": "ПРЕДУПРЕЖДЕНИЕ!", "wc_scan_qr": "Сканирайте QR", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index f62daa6d3..2e68008be 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Podepisujte zprávy a zadaná data", "wc_permission_switch_chains": "Přepněte a přidejte řetězy EVM", "wc_permission_view_balance": "Prohlédněte si zůstatek a aktivitu v peněžence", + "wc_request_for_different_wallet": "Tento požadavek byl podán pro jinou peněženku. Otevřete peněženku připojenou k této aplikaci a zkuste to znovu.", "wc_scam_warning_message": "Zdá se, že tento požadavek pochází od známého podvodu. Postupujte prosím opatrně.", "wc_scam_warning_title": "VAROVÁNÍ!", "wc_scan_qr": "Naskenujte QR", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index dd7abc180..8044948e8 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -1460,6 +1460,7 @@ "wc_permission_sign_messages": "Nachrichten und strukturierte Daten signieren", "wc_permission_switch_chains": "EVM-Ketten wechseln und hinzufügen", "wc_permission_view_balance": "Kontostand und Aktivität Ihrer Wallet anzeigen", + "wc_request_for_different_wallet": "Diese Anfrage wurde für eine andere Wallet gestellt. Öffnen Sie die mit dieser App verbundene Wallet und versuchen Sie es erneut.", "wc_scam_warning_message": "Diese Anfrage scheint von einem bekannten Betrug zu stammen. Bitte gehen Sie vorsichtig vor.", "wc_scam_warning_title": "WARNUNG!", "wc_scan_qr": "QR scannen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 9c04a21c4..b208f6836 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -1462,6 +1462,7 @@ "wc_permission_sign_messages": "Sign messages and typed data", "wc_permission_switch_chains": "Switch and add EVM chains", "wc_permission_view_balance": "View your wallet balance and activity", + "wc_request_for_different_wallet": "This request was made for a different wallet. Open the wallet connected to this app and try again.", "wc_scam_warning_message": "This request appears to be from a known scam. Please proceed with caution.", "wc_scam_warning_title": "WARNING!", "wc_scan_qr": "Scan QR", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 78321bd2c..ac702c0f6 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -1423,6 +1423,7 @@ "wc_permission_sign_messages": "Firmar mensajes y datos escritos", "wc_permission_switch_chains": "Cambie y agregue cadenas EVM", "wc_permission_view_balance": "Ver el saldo y la actividad de su billetera", + "wc_request_for_different_wallet": "Esta solicitud se realizó para una billetera diferente. Abra la billetera conectada a esta aplicación e inténtelo nuevamente.", "wc_scam_warning_message": "Esta solicitud parece provenir de una estafa conocida. Proceda con precaución.", "wc_scam_warning_title": "¡ADVERTENCIA!", "wc_scan_qr": "Escanear QR", diff --git a/res/values/strings_fa.arb b/res/values/strings_fa.arb index cf886a43b..17f55785a 100644 --- a/res/values/strings_fa.arb +++ b/res/values/strings_fa.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "پیام ها و داده های تایپ شده را امضا کنید", "wc_permission_switch_chains": "زنجیره های EVM را تغییر دهید و اضافه کنید", "wc_permission_view_balance": "موجودی و فعالیت کیف پول خود را مشاهده کنید", + "wc_request_for_different_wallet": "این درخواست برای یک کیف پول متفاوت انجام شده است. کیف پول متصل به این برنامه را باز کنید و دوباره امتحان کنید.", "wc_scam_warning_message": "به نظر می رسد این درخواست از یک کلاهبرداری شناخته شده باشد. لطفا با احتیاط ادامه دهید", "wc_scam_warning_title": "هشدار!", "wc_scan_qr": "اسکن QR", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d3f135c88..a8c8df56a 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Signer les messages et les données saisies", "wc_permission_switch_chains": "Changer et ajouter des chaînes EVM", "wc_permission_view_balance": "Consultez le solde et l'activité de votre portefeuille", + "wc_request_for_different_wallet": "Cette demande a été faite pour un autre portefeuille. Ouvrez le portefeuille connecté à cette application et réessayez.", "wc_scam_warning_message": "Cette demande semble provenir d'une arnaque connue. Veuillez procéder avec prudence.", "wc_scam_warning_title": "AVERTISSEMENT!", "wc_scan_qr": "Scanner le QR", diff --git a/res/values/strings_gn.arb b/res/values/strings_gn.arb index 551e16d42..c86512e7b 100644 --- a/res/values/strings_gn.arb +++ b/res/values/strings_gn.arb @@ -1428,6 +1428,7 @@ "wc_permission_sign_messages": "Marandu ofirma ha dato ojehaipyréva", "wc_permission_switch_chains": "Embohasa ha emoĩve umi cadena EVM rehegua", "wc_permission_view_balance": "Ehecha nde billetera saldo ha actividad", + "wc_request_for_different_wallet": "Ko mba’ejerure ojejapo peteĩ billetera iñambuéva rehe. Eipe’a pe billetera oñembojoajúva ko app-pe ha eñeha’ã jey.", "wc_scam_warning_message": "Ko pedido ojekuaa oúha peteî estafa ojekuaávagui. Por favor, peprocede ñeñangareko reheve.", "wc_scam_warning_title": "ÑEMONGYHYJE!", "wc_scan_qr": "Escanear QR", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index ea901d7c4..29cda58b1 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -1423,6 +1423,7 @@ "wc_permission_sign_messages": "Sa hannu kan saƙonni da rubutattun bayanai", "wc_permission_switch_chains": "Canja kuma ƙara sarƙoƙin EVM", "wc_permission_view_balance": "Duba ma'auni na walat ɗin ku da aiki", + "wc_request_for_different_wallet": "An yi wannan buƙatar don wani walat ɗin daban. Bude walat ɗin da aka haɗa zuwa wannan app ɗin kuma a sake gwadawa.", "wc_scam_warning_message": "Wannan buƙatar ta bayyana daga wata zamba da aka sani. Da fatan za a ci gaba da taka tsantsan.", "wc_scam_warning_title": "GARGADI!", "wc_scan_qr": "Duba QR", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 15edf0080..13d18ae19 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -1423,6 +1423,7 @@ "wc_permission_sign_messages": "संदेशों पर हस्ताक्षर करें और डेटा टाइप करें", "wc_permission_switch_chains": "स्विच करें और ईवीएम चेन जोड़ें", "wc_permission_view_balance": "अपना वॉलेट बैलेंस और गतिविधि देखें", + "wc_request_for_different_wallet": "यह अनुरोध एक अलग वॉलेट के लिए किया गया था. इस ऐप से जुड़ा वॉलेट खोलें और पुनः प्रयास करें।", "wc_scam_warning_message": "ऐसा प्रतीत होता है कि यह अनुरोध किसी ज्ञात घोटाले से आया है। कृपया सावधानी से आगे बढ़ें.", "wc_scam_warning_title": "चेतावनी!", "wc_scan_qr": "QR स्कैन करें", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 2d99234eb..0e4f55c43 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Potpisivati ​​poruke i upisane podatke", "wc_permission_switch_chains": "Prebacite i dodajte EVM lance", "wc_permission_view_balance": "Pogledajte svoj novčanik i aktivnost", + "wc_request_for_different_wallet": "Ovaj je zahtjev upućen za drugi novčanik. Otvorite novčanik povezan s ovom aplikacijom i pokušajte ponovno.", "wc_scam_warning_message": "Čini se da ovaj zahtjev potječe iz poznate prijevare. Molimo nastavite s oprezom.", "wc_scam_warning_title": "UPOZORENJE!", "wc_scan_qr": "Skeniraj QR", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index f1a209c91..e45a24dce 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Ստորագրեք հաղորդագրությունները և մուտքագրված տվյալները", "wc_permission_switch_chains": "Միացրեք և ավելացրեք EVM շղթաներ", "wc_permission_view_balance": "Դիտեք ձեր դրամապանակի մնացորդը և գործունեությունը", + "wc_request_for_different_wallet": "Այս հարցումն արվել է այլ դրամապանակի համար: Բացեք այս հավելվածին միացված դրամապանակը և նորից փորձեք:", "wc_scam_warning_message": "Այս հարցումը, կարծես, հայտնի խարդախությունից է: Խնդրում ենք շարունակել զգուշությամբ:", "wc_scam_warning_title": "ԶԳՈՒՇԱՑՈՒՄ.", "wc_scan_qr": "Սկանավորել QR", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c1fea5b4d..478dc7d68 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -1424,6 +1424,7 @@ "wc_permission_sign_messages": "Menandatangani pesan dan mengetik data", "wc_permission_switch_chains": "Beralih dan tambahkan rantai EVM", "wc_permission_view_balance": "Lihat saldo dan aktivitas dompet Anda", + "wc_request_for_different_wallet": "Permintaan ini dibuat untuk dompet yang berbeda. Buka dompet yang terhubung ke aplikasi ini dan coba lagi.", "wc_scam_warning_message": "Permintaan ini tampaknya berasal dari penipuan yang diketahui. Silakan lanjutkan dengan hati-hati.", "wc_scam_warning_title": "PERINGATAN!", "wc_scan_qr": "Pindai QR", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index d7ae0b9c0..1fc6ff179 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -1422,6 +1422,7 @@ "wc_permission_sign_messages": "Firmare messaggi e dati digitati", "wc_permission_switch_chains": "Cambia e aggiungi catene EVM", "wc_permission_view_balance": "Visualizza il saldo e l'attività del tuo portafoglio", + "wc_request_for_different_wallet": "Questa richiesta è stata effettuata per un portafoglio diverso. Apri il portafoglio connesso a questa app e riprova.", "wc_scam_warning_message": "Questa richiesta sembra provenire da una truffa nota. Si prega di procedere con cautela.", "wc_scam_warning_title": "AVVERTIMENTO!", "wc_scan_qr": "Scansione QR", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index e9708e48d..b6836bf67 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "メッセージと入力されたデータに署名する", "wc_permission_switch_chains": "EVMチェーンの切り替えと追加", "wc_permission_view_balance": "ウォレットの残高とアクティビティを表示する", + "wc_request_for_different_wallet": "このリクエストは別のウォレットに対して行われました。このアプリに接続されているウォレットを開いて、もう一度お試しください。", "wc_scam_warning_message": "このリクエストは既知の詐欺によるものと思われます。慎重に進めてください。", "wc_scam_warning_title": "警告!", "wc_scan_qr": "QRをスキャン", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 35dd2e704..852be390a 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -1420,6 +1420,7 @@ "wc_permission_sign_messages": "메시지 및 입력된 데이터에 서명", "wc_permission_switch_chains": "EVM 체인 전환 및 추가", "wc_permission_view_balance": "지갑 잔액 및 활동 보기", + "wc_request_for_different_wallet": "이 요청은 다른 지갑에 대해 이루어졌습니다. 이 앱에 연결된 지갑을 열고 다시 시도해 보세요.", "wc_scam_warning_message": "이 요청은 알려진 사기에서 나온 것 같습니다. 주의해서 진행하시기 바랍니다.", "wc_scam_warning_title": "경고!", "wc_scan_qr": "QR 스캔", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 990a568e2..879e8382c 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -1420,6 +1420,7 @@ "wc_permission_sign_messages": "မက်ဆေ့ချ်များကို လက်မှတ်ထိုးပြီး ဒေတာကို ရိုက်ထည့်ပါ။", "wc_permission_switch_chains": "EVM chain များကို ပြောင်းပြီး ထည့်ပါ", "wc_permission_view_balance": "သင့်ပိုက်ဆံအိတ်လက်ကျန်ငွေနှင့် လုပ်ဆောင်ချက်ကို ကြည့်ရှုပါ။", + "wc_request_for_different_wallet": "ဤတောင်းဆိုချက်ကို မတူညီသော ပိုက်ဆံအိတ်အတွက် ပြုလုပ်ထားပါသည်။ ဤအက်ပ်နှင့်ချိတ်ဆက်ထားသော ပိုက်ဆံအိတ်ကိုဖွင့်ပြီး ထပ်စမ်းကြည့်ပါ။", "wc_scam_warning_message": "ဤတောင်းဆိုချက်သည် လူသိများသော လိမ်လည်မှုတစ်ခုမှ ဖြစ်ပုံရသည်။ ကျေးဇူးပြု၍ သတိဖြင့် ဆက်လုပ်ပါ။", "wc_scam_warning_title": "သတိပေးချက်။", "wc_scan_qr": "QR ကိုစကင်န်ဖတ်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 0671d7e14..9f7bc6d20 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Onderteken berichten en getypte gegevens", "wc_permission_switch_chains": "Schakel over en voeg EVM-ketens toe", "wc_permission_view_balance": "Bekijk je walletsaldo en activiteit", + "wc_request_for_different_wallet": "Dit verzoek is gedaan voor een andere portemonnee. Open de portemonnee die met deze app is verbonden en probeer het opnieuw.", "wc_scam_warning_message": "Dit verzoek lijkt afkomstig te zijn van een bekende oplichting. Ga alstublieft voorzichtig te werk.", "wc_scam_warning_title": "WAARSCHUWING!", "wc_scan_qr": "QR scannen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index e0de2a835..013896b11 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -1420,6 +1420,7 @@ "wc_permission_sign_messages": "Podpisuj wiadomości i wpisywane dane", "wc_permission_switch_chains": "Przełącz i dodaj łańcuchy EVM", "wc_permission_view_balance": "Sprawdź saldo i aktywność swojego portfela", + "wc_request_for_different_wallet": "To żądanie dotyczyło innego portfela. Otwórz portfel połączony z tą aplikacją i spróbuj ponownie.", "wc_scam_warning_message": "Wygląda na to, że to żądanie pochodzi ze znanego oszustwa. Proszę postępować ostrożnie.", "wc_scam_warning_title": "OSTRZEŻENIE!", "wc_scan_qr": "Zeskanuj kod QR", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index d9204e345..c3ab4bae7 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -1423,6 +1423,7 @@ "wc_permission_sign_messages": "Assinar mensagens e dados digitados", "wc_permission_switch_chains": "Alternar e adicionar cadeias EVM", "wc_permission_view_balance": "Veja o saldo e a atividade da sua carteira", + "wc_request_for_different_wallet": "Esta solicitação foi feita para uma carteira diferente. Abra a carteira conectada a este aplicativo e tente novamente.", "wc_scam_warning_message": "Esta solicitação parece ser de um golpe conhecido. Por favor, proceda com cautela.", "wc_scam_warning_title": "AVISO!", "wc_scan_qr": "Digitalize QR", diff --git a/res/values/strings_pt_BR.arb b/res/values/strings_pt_BR.arb index d703a3ec8..c552992e0 100644 --- a/res/values/strings_pt_BR.arb +++ b/res/values/strings_pt_BR.arb @@ -1361,6 +1361,7 @@ "wc_permission_sign_messages": "Assinar mensagens e dados digitados", "wc_permission_switch_chains": "Alternar e adicionar cadeias EVM", "wc_permission_view_balance": "Veja o saldo e a atividade da sua carteira", + "wc_request_for_different_wallet": "Esta solicitação foi feita para uma carteira diferente. Abra a carteira conectada a este aplicativo e tente novamente.", "wc_scam_warning_message": "Esta solicitação parece ser de um golpe conhecido. Por favor, proceda com cautela.", "wc_scam_warning_title": "AVISO!", "wc_scan_qr": "Digitalize QR", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index aeb56f31c..ca12a089d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Подписывать сообщения и вводимые данные", "wc_permission_switch_chains": "Переключение и добавление цепочек EVM", "wc_permission_view_balance": "Просматривайте баланс и активность своего кошелька", + "wc_request_for_different_wallet": "Этот запрос был сделан для другого кошелька. Откройте кошелек, подключенный к этому приложению, и повторите попытку.", "wc_scam_warning_message": "Судя по всему, этот запрос поступил от известного мошенника. Пожалуйста, действуйте осторожно.", "wc_scam_warning_title": "ПРЕДУПРЕЖДЕНИЕ!", "wc_scan_qr": "Сканировать QR-код", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 44096cbd1..818a8f6c1 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -1420,6 +1420,7 @@ "wc_permission_sign_messages": "เซ็นข้อความและพิมพ์ข้อมูล", "wc_permission_switch_chains": "สลับและเพิ่มเชน EVM", "wc_permission_view_balance": "ดูยอดคงเหลือในกระเป๋าสตางค์และกิจกรรมของคุณ", + "wc_request_for_different_wallet": "คำขอนี้สร้างขึ้นสำหรับกระเป๋าเงินอื่น เปิดกระเป๋าเงินที่เชื่อมต่อกับแอพนี้แล้วลองอีกครั้ง", "wc_scam_warning_message": "ดูเหมือนว่าคำขอนี้มาจากกลโกงที่ทราบ โปรดดำเนินการด้วยความระมัดระวัง", "wc_scam_warning_title": "คำเตือน!", "wc_scan_qr": "สแกนคิวอาร์", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index bdb4d46a6..374cb1616 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -1420,6 +1420,7 @@ "wc_permission_sign_messages": "Mag-sign ng mga mensahe at nai-type na data", "wc_permission_switch_chains": "Lumipat at magdagdag ng mga EVM chain", "wc_permission_view_balance": "Tingnan ang balanse at aktibidad ng iyong wallet", + "wc_request_for_different_wallet": "Ang kahilingang ito ay ginawa para sa ibang wallet. Buksan ang wallet na nakakonekta sa app na ito at subukang muli.", "wc_scam_warning_message": "Mukhang mula sa isang kilalang scam ang kahilingang ito. Mangyaring magpatuloy nang may pag-iingat.", "wc_scam_warning_title": "BABALA!", "wc_scan_qr": "I-scan ang QR", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 67684f6df..82b27c80f 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -1420,6 +1420,7 @@ "wc_permission_sign_messages": "Mesajları ve yazılan verileri imzalayın", "wc_permission_switch_chains": "EVM zincirlerini değiştirin ve ekleyin", "wc_permission_view_balance": "Cüzdan bakiyenizi ve etkinliğinizi görüntüleyin", + "wc_request_for_different_wallet": "Bu istek farklı bir cüzdan için yapıldı. Bu uygulamaya bağlı cüzdanı açın ve tekrar deneyin.", "wc_scam_warning_message": "Bu isteğin bilinen bir dolandırıcılıktan geldiği anlaşılıyor. Lütfen dikkatli bir şekilde ilerleyin.", "wc_scam_warning_title": "UYARI!", "wc_scan_qr": "QR'yi tara", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 14fa38f59..6558649ff 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Підписуйте повідомлення та введені дані", "wc_permission_switch_chains": "Перемикайте та додавайте ланцюжки EVM", "wc_permission_view_balance": "Перегляньте свій баланс гаманця та активність", + "wc_request_for_different_wallet": "Цей запит було зроблено для іншого гаманця. Відкрийте гаманець, підключений до цієї програми, і повторіть спробу.", "wc_scam_warning_message": "Схоже, цей запит надійшов від відомого шахрая. Будь ласка, будьте обережні.", "wc_scam_warning_title": "УВАГА!", "wc_scan_qr": "Сканувати QR", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index ba77da2bf..f241478ab 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -1422,6 +1422,7 @@ "wc_permission_sign_messages": "پیغامات پر دستخط کریں اور ڈیٹا ٹائپ کریں۔", "wc_permission_switch_chains": "ای وی ایم چینز کو تبدیل کریں اور شامل کریں۔", "wc_permission_view_balance": "اپنے والیٹ کا بیلنس اور سرگرمی دیکھیں", + "wc_request_for_different_wallet": "یہ درخواست ایک مختلف بٹوے کے لیے کی گئی تھی۔ اس ایپ سے منسلک والیٹ کھولیں اور دوبارہ کوشش کریں۔", "wc_scam_warning_message": "یہ درخواست کسی معروف اسکام کی طرف سے معلوم ہوتی ہے۔ براہ کرم احتیاط کے ساتھ آگے بڑھیں۔", "wc_scam_warning_title": "وارننگ!", "wc_scan_qr": "QR اسکین کریں۔", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index 41b269d47..594657af9 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Ký tin nhắn và dữ liệu có cấu trúc", "wc_permission_switch_chains": "Chuyển đổi và thêm chuỗi EVM", "wc_permission_view_balance": "Xem số dư và hoạt động ví của bạn", + "wc_request_for_different_wallet": "Yêu cầu này được thực hiện cho một ví khác. Hãy mở ví được kết nối với ứng dụng này và thử lại.", "wc_scam_warning_message": "Yêu cầu này có vẻ là từ một trò lừa đảo đã biết. Hãy tiến hành thận trọng.", "wc_scam_warning_title": "CẢNH BÁO!", "wc_scan_qr": "Quét QR", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 15f858b93..def4de265 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "Wole awọn ifiranṣẹ ati titẹ data", "wc_permission_switch_chains": "Yipada ki o si fi EVM dè", "wc_permission_view_balance": "Wo iwọntunwọnsi apamọwọ rẹ ati iṣẹ ṣiṣe", + "wc_request_for_different_wallet": "A ṣe ibeere yii fun apamọwọ ti o yatọ. Ṣii apamọwọ ti a ti sopọ si app yii ki o tun gbiyanju lẹẹkansi.", "wc_scam_warning_message": "Ibeere yii han lati wa lati itanjẹ ti a mọ. Jọwọ tẹsiwaju pẹlu iṣọra.", "wc_scam_warning_title": "IKILO!", "wc_scan_qr": "Ṣayẹwo QR", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 711735023..91e885810 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -1421,6 +1421,7 @@ "wc_permission_sign_messages": "签署消息和键入的数据", "wc_permission_switch_chains": "切换并添加EVM链", "wc_permission_view_balance": "查看您的钱包余额和活动", + "wc_request_for_different_wallet": "此请求是针对不同的钱包提出的。打开连接到该应用程序的钱包并重试。", "wc_scam_warning_message": "此请求似乎来自一个已知的骗局。请谨慎行事。", "wc_scam_warning_title": "警告!", "wc_scan_qr": "扫描二维码",