mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-16 17:27:37 +00:00
Cw 451 wallet connect for ethereum (#1049)
* Update Flutter Update packages * Feat: Wallet connect for ethereum * Fix localization issues Fix UI issues Update old packages Update workflow Update how to build guide * feat: Wallet connect * feat: Add wallet connect for ethereum * chore: Add eth dependencies in configure file * Minor: `WalletConnect` settings name, not `Wallet connect` * fix: Merge conflicts * fix: Issues with test cases on various dApps, introduce Arbitrum rinkerby as suported chain * ui: Design fixes for WalletConnect flow * chore: Update repo and comment out send apk to channel in workflow * fix: Core implementation * feat: WalletConnect WIP * feat: WalletConnect WIP * feat: WalletConnect WIP * chore: Unused parameters WIP [skip ci] * fix: Code review fixes * Feat: WalletConnect feat WIP * feat: WalletConnect * feat: WalletConnect * feat: WalletConnect * Feat: WalletConnect * Feat: WalletConnect * feat: Remove queue support for the bottomsheet * feat: WalletConnect feature, bug fixes, folder restructuring, localization * Feat: Add positive feedback prompt on successful transaction * fix: Delete session bug * fix: dependencies registration WIP * feat: Registering dependencies for walletconnect * chore: Move key data to secrets * chore: ensure appropriate null checks * chore: localization * chore: Remove unused code * localization * chore: Remove unused code * chore: Remove unused code * chore: Add walletconnect project id key entry * fix: Revert bash command for linnux support * fix: Issues with translation in some languages and making unneeded external variable private * fix: Add bottomsheet listener to desktop dashboard page * Generalize ethereum not enough gas error check --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com> Co-authored-by: Justin Ehrenhofer <justin.ehrenhofer@gmail.com>
This commit is contained in:
parent
ae71f2045b
commit
32643823e5
67 changed files with 2819 additions and 314 deletions
8
.github/workflows/pr_test_build.yml
vendored
8
.github/workflows/pr_test_build.yml
vendored
|
@ -6,7 +6,6 @@ on:
|
|||
|
||||
jobs:
|
||||
PR_test_build:
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
STORE_PASS: test@cake_wallet
|
||||
|
@ -23,12 +22,12 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: '8.x'
|
||||
java-version: "8.x"
|
||||
|
||||
- name: Flutter action
|
||||
uses: subosito/flutter-action@v1
|
||||
with:
|
||||
flutter-version: '3.10.x'
|
||||
flutter-version: "3.10.x"
|
||||
channel: stable
|
||||
|
||||
- name: Install package dependencies
|
||||
|
@ -131,6 +130,7 @@ jobs:
|
|||
echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
|
||||
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
|
||||
echo "const robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
|
||||
echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart
|
||||
|
||||
- name: Rename app
|
||||
run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties
|
||||
|
@ -171,6 +171,6 @@ jobs:
|
|||
token: ${{ secrets.SLACK_APP_TOKEN }}
|
||||
path: /opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk
|
||||
channel: ${{ secrets.SLACK_APK_CHANNEL }}
|
||||
title: '${{github.head_ref}}.apk'
|
||||
title: "${{github.head_ref}}.apk"
|
||||
filename: ${{github.head_ref}}.apk
|
||||
initial_comment: ${{ github.event.head_commit.message }}
|
||||
|
|
BIN
assets/images/walletconnect_logo.png
Normal file
BIN
assets/images/walletconnect_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
|
@ -77,6 +77,8 @@ abstract class EthereumWalletBase
|
|||
|
||||
late final EthPrivateKey _ethPrivateKey;
|
||||
|
||||
EthPrivateKey get ethPrivateKey => _ethPrivateKey;
|
||||
|
||||
late EthereumClient _client;
|
||||
|
||||
int? _gasPrice;
|
||||
|
|
5
lib/core/wallet_connect/chain_service.dart
Normal file
5
lib/core/wallet_connect/chain_service.dart
Normal file
|
@ -0,0 +1,5 @@
|
|||
abstract class ChainService {
|
||||
String getNamespace();
|
||||
String getChainId();
|
||||
List<String> getEvents();
|
||||
}
|
60
lib/core/wallet_connect/eth_transaction_model.dart
Normal file
60
lib/core/wallet_connect/eth_transaction_model.dart
Normal file
|
@ -0,0 +1,60 @@
|
|||
class WCEthereumTransactionModel {
|
||||
final String from;
|
||||
final String to;
|
||||
final String value;
|
||||
final String? nonce;
|
||||
final String? gasPrice;
|
||||
final String? maxFeePerGas;
|
||||
final String? maxPriorityFeePerGas;
|
||||
final String? gas;
|
||||
final String? gasLimit;
|
||||
final String? data;
|
||||
|
||||
WCEthereumTransactionModel({
|
||||
required this.from,
|
||||
required this.to,
|
||||
required this.value,
|
||||
this.nonce,
|
||||
this.gasPrice,
|
||||
this.maxFeePerGas,
|
||||
this.maxPriorityFeePerGas,
|
||||
this.gas,
|
||||
this.gasLimit,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory WCEthereumTransactionModel.fromJson(Map<String, dynamic> json) {
|
||||
return WCEthereumTransactionModel(
|
||||
from: json['from'] as String,
|
||||
to: json['to'] as String,
|
||||
value: json['value'] as String,
|
||||
nonce: json['nonce'] as String?,
|
||||
gasPrice: json['gasPrice'] as String?,
|
||||
maxFeePerGas: json['maxFeePerGas'] as String?,
|
||||
maxPriorityFeePerGas: json['maxPriorityFeePerGas'] as String?,
|
||||
gas: json['gas'] as String?,
|
||||
gasLimit: json['gasLimit'] as String?,
|
||||
data: json['data'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'from': from,
|
||||
'to': to,
|
||||
'value': value,
|
||||
'nonce': nonce,
|
||||
'gasPrice': gasPrice,
|
||||
'maxFeePerGas': maxFeePerGas,
|
||||
'maxPriorityFeePerGas': maxPriorityFeePerGas,
|
||||
'gas': gas,
|
||||
'gasLimit': gasLimit,
|
||||
'data': data,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EthereumTransactionModel(from: $from, to: $to, nonce: $nonce, gasPrice: $gasPrice, maxFeePerGas: $maxFeePerGas, maxPriorityFeePerGas: $maxPriorityFeePerGas, gas: $gas, gasLimit: $gasLimit, value: $value, data: $data)';
|
||||
}
|
||||
}
|
35
lib/core/wallet_connect/evm_chain_id.dart
Normal file
35
lib/core/wallet_connect/evm_chain_id.dart
Normal file
|
@ -0,0 +1,35 @@
|
|||
import 'package:cake_wallet/core/wallet_connect/evm_chain_service.dart';
|
||||
|
||||
enum EVMChainId {
|
||||
ethereum,
|
||||
polygon,
|
||||
goerli,
|
||||
mumbai,
|
||||
arbitrum,
|
||||
}
|
||||
|
||||
extension EVMChainIdX on EVMChainId {
|
||||
String chain() {
|
||||
String name = '';
|
||||
|
||||
switch (this) {
|
||||
case EVMChainId.ethereum:
|
||||
name = '1';
|
||||
break;
|
||||
case EVMChainId.polygon:
|
||||
name = '137';
|
||||
break;
|
||||
case EVMChainId.goerli:
|
||||
name = '5';
|
||||
break;
|
||||
case EVMChainId.arbitrum:
|
||||
name = '42161';
|
||||
break;
|
||||
case EVMChainId.mumbai:
|
||||
name = '80001';
|
||||
break;
|
||||
}
|
||||
|
||||
return '${EvmChainServiceImpl.namespace}:$name';
|
||||
}
|
||||
}
|
294
lib/core/wallet_connect/evm_chain_service.dart
Normal file
294
lib/core/wallet_connect/evm_chain_service.dart
Normal file
|
@ -0,0 +1,294 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cake_wallet/core/wallet_connect/eth_transaction_model.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/error_display_widget.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/connection_model.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/utils/string_parsing.dart';
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:eth_sig_util/eth_sig_util.dart';
|
||||
import 'package:eth_sig_util/util/utils.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
import 'package:web3dart/web3dart.dart';
|
||||
import 'chain_service.dart';
|
||||
import 'wallet_connect_key_service.dart';
|
||||
|
||||
class EvmChainServiceImpl implements ChainService {
|
||||
final AppStore appStore;
|
||||
final BottomSheetService bottomSheetService;
|
||||
final Web3Wallet wallet;
|
||||
final WalletConnectKeyService wcKeyService;
|
||||
|
||||
static const namespace = 'eip155';
|
||||
static const pSign = 'personal_sign';
|
||||
static const eSign = 'eth_sign';
|
||||
static const eSignTransaction = 'eth_signTransaction';
|
||||
static const eSignTypedData = 'eth_signTypedData_v4';
|
||||
static const eSendTransaction = 'eth_sendTransaction';
|
||||
|
||||
final EVMChainId reference;
|
||||
|
||||
final Web3Client ethClient;
|
||||
|
||||
EvmChainServiceImpl({
|
||||
required this.reference,
|
||||
required this.appStore,
|
||||
required this.wcKeyService,
|
||||
required this.bottomSheetService,
|
||||
required this.wallet,
|
||||
Web3Client? ethClient,
|
||||
}) : ethClient = ethClient ??
|
||||
Web3Client(
|
||||
appStore.settingsStore.getCurrentNode(WalletType.ethereum).uri.toString(),
|
||||
http.Client(),
|
||||
) {
|
||||
|
||||
for (final String event in getEvents()) {
|
||||
wallet.registerEventEmitter(chainId: getChainId(), event: event);
|
||||
}
|
||||
wallet.registerRequestHandler(
|
||||
chainId: getChainId(),
|
||||
method: pSign,
|
||||
handler: personalSign,
|
||||
);
|
||||
wallet.registerRequestHandler(
|
||||
chainId: getChainId(),
|
||||
method: eSign,
|
||||
handler: ethSign,
|
||||
);
|
||||
wallet.registerRequestHandler(
|
||||
chainId: getChainId(),
|
||||
method: eSignTransaction,
|
||||
handler: ethSignTransaction,
|
||||
);
|
||||
wallet.registerRequestHandler(
|
||||
chainId: getChainId(),
|
||||
method: eSendTransaction,
|
||||
handler: ethSignTransaction,
|
||||
);
|
||||
wallet.registerRequestHandler(
|
||||
chainId: getChainId(),
|
||||
method: eSignTypedData,
|
||||
handler: ethSignTypedData,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
@override
|
||||
String getChainId() {
|
||||
return reference.chain();
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> getEvents() {
|
||||
return ['chainChanged', 'accountsChanged'];
|
||||
}
|
||||
|
||||
Future<String?> requestAuthorization(String? text) async {
|
||||
// Show the bottom sheet
|
||||
final bool? isApproved = await bottomSheetService.queueBottomSheet(
|
||||
widget: Web3RequestModal(
|
||||
child: ConnectionWidget(
|
||||
title: S.current.signTransaction,
|
||||
info: [
|
||||
ConnectionModel(
|
||||
text: text,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
) as bool?;
|
||||
|
||||
if (isApproved != null && isApproved == false) {
|
||||
return 'User rejected signature';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<String> personalSign(String topic, dynamic parameters) async {
|
||||
log('received personal sign request: $parameters');
|
||||
|
||||
final String message;
|
||||
if (parameters[0] == null) {
|
||||
message = '';
|
||||
} else {
|
||||
message = parameters[0].toString().utf8Message;
|
||||
}
|
||||
|
||||
final String? authError = await requestAuthorization(message);
|
||||
|
||||
if (authError != null) {
|
||||
return authError;
|
||||
}
|
||||
|
||||
try {
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
|
||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
final String signature = hex.encode(
|
||||
credentials.signPersonalMessageToUint8List(Uint8List.fromList(utf8.encode(message))),
|
||||
);
|
||||
|
||||
return '0x$signature';
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
bottomSheetService.queueBottomSheet(
|
||||
isModalDismissible: true,
|
||||
widget: BottomSheetMessageDisplayWidget(
|
||||
message: '${S.current.errorGettingCredentials} ${e.toString()}',
|
||||
),
|
||||
);
|
||||
return 'Failed: Error while getting credentials';
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> ethSign(String topic, dynamic parameters) async {
|
||||
log('received eth sign request: $parameters');
|
||||
|
||||
final String message;
|
||||
if (parameters[1] == null) {
|
||||
message = '';
|
||||
} else {
|
||||
message = parameters[1].toString().utf8Message;
|
||||
}
|
||||
|
||||
final String? authError = await requestAuthorization(message);
|
||||
if (authError != null) {
|
||||
return authError;
|
||||
}
|
||||
|
||||
try {
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
|
||||
final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
final String signature = hex.encode(
|
||||
credentials.signPersonalMessageToUint8List(
|
||||
Uint8List.fromList(utf8.encode(message)),
|
||||
),
|
||||
);
|
||||
log(signature);
|
||||
|
||||
return '0x$signature';
|
||||
} catch (e) {
|
||||
log('error: ${e.toString()}');
|
||||
bottomSheetService.queueBottomSheet(
|
||||
isModalDismissible: true,
|
||||
widget: BottomSheetMessageDisplayWidget(message: '${S.current.error}: ${e.toString()}'),
|
||||
);
|
||||
return 'Failed';
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> ethSignTransaction(String topic, dynamic parameters) async {
|
||||
log('received eth sign transaction request: $parameters');
|
||||
|
||||
final paramsData = parameters[0] as Map<String, dynamic>;
|
||||
|
||||
final message = _convertToReadable(paramsData);
|
||||
|
||||
final String? authError = await requestAuthorization(message);
|
||||
|
||||
if (authError != null) {
|
||||
return authError;
|
||||
}
|
||||
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
|
||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
WCEthereumTransactionModel ethTransaction =
|
||||
WCEthereumTransactionModel.fromJson(parameters[0] as Map<String, dynamic>);
|
||||
|
||||
final transaction = Transaction(
|
||||
from: EthereumAddress.fromHex(ethTransaction.from),
|
||||
to: EthereumAddress.fromHex(ethTransaction.to),
|
||||
maxGas: ethTransaction.gasLimit != null ? int.tryParse(ethTransaction.gasLimit ?? "") : null,
|
||||
gasPrice: ethTransaction.gasPrice != null
|
||||
? EtherAmount.inWei(BigInt.parse(ethTransaction.gasPrice ?? ""))
|
||||
: null,
|
||||
value: EtherAmount.inWei(BigInt.parse(ethTransaction.value)),
|
||||
data: hexToBytes(ethTransaction.data ?? ""),
|
||||
nonce: ethTransaction.nonce != null ? int.tryParse(ethTransaction.nonce ?? "") : null,
|
||||
);
|
||||
|
||||
try {
|
||||
final result = await ethClient.sendTransaction(credentials, transaction);
|
||||
|
||||
log('Result: $result');
|
||||
|
||||
bottomSheetService.queueBottomSheet(
|
||||
isModalDismissible: true,
|
||||
widget: BottomSheetMessageDisplayWidget(
|
||||
message: S.current.awaitDAppProcessing,
|
||||
isError: false,
|
||||
),
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
log('An error has occured while signing transaction: ${e.toString()}');
|
||||
bottomSheetService.queueBottomSheet(
|
||||
isModalDismissible: true,
|
||||
widget: BottomSheetMessageDisplayWidget(
|
||||
message: '${S.current.errorSigningTransaction}: ${e.toString()}',
|
||||
),
|
||||
);
|
||||
return 'Failed';
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> ethSignTypedData(String topic, dynamic parameters) async {
|
||||
log('received eth sign typed data request: $parameters');
|
||||
final String? data = parameters[1] as String?;
|
||||
|
||||
final String? authError = await requestAuthorization(data);
|
||||
|
||||
if (authError != null) {
|
||||
return authError;
|
||||
}
|
||||
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
|
||||
return EthSigUtil.signTypedData(
|
||||
privateKey: keys[0].privateKey,
|
||||
jsonData: data ?? '',
|
||||
version: TypedDataVersion.V4,
|
||||
);
|
||||
}
|
||||
|
||||
String _convertToReadable(Map<String, dynamic> data) {
|
||||
String gas = int.parse((data['gas'] as String).substring(2), radix: 16).toString();
|
||||
String value = data['value'] != null
|
||||
? (int.parse((data['value'] as String).substring(2), radix: 16) / 1e18).toString() + ' ETH'
|
||||
: '0 ETH';
|
||||
String from = data['from'] as String;
|
||||
String to = data['to'] as String;
|
||||
|
||||
return '''
|
||||
Gas: $gas\n
|
||||
Value: $value\n
|
||||
From: $from\n
|
||||
To: $to
|
||||
''';
|
||||
}
|
||||
}
|
16
lib/core/wallet_connect/models/auth_request_model.dart
Normal file
16
lib/core/wallet_connect/models/auth_request_model.dart
Normal file
|
@ -0,0 +1,16 @@
|
|||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
|
||||
class AuthRequestModel {
|
||||
final String iss;
|
||||
final AuthRequest request;
|
||||
|
||||
AuthRequestModel({
|
||||
required this.iss,
|
||||
required this.request,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthRequestModel(iss: $iss, request: $request)';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class BottomSheetQueueItemModel {
|
||||
final Widget widget;
|
||||
final bool isModalDismissible;
|
||||
final Completer<dynamic> completer;
|
||||
|
||||
BottomSheetQueueItemModel({
|
||||
required this.widget,
|
||||
required this.completer,
|
||||
this.isModalDismissible = false,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BottomSheetQueueItemModel(widget: $widget, completer: $completer)';
|
||||
}
|
||||
}
|
16
lib/core/wallet_connect/models/chain_key_model.dart
Normal file
16
lib/core/wallet_connect/models/chain_key_model.dart
Normal file
|
@ -0,0 +1,16 @@
|
|||
class ChainKeyModel {
|
||||
final List<String> chains;
|
||||
final String privateKey;
|
||||
final String publicKey;
|
||||
|
||||
ChainKeyModel({
|
||||
required this.chains,
|
||||
required this.privateKey,
|
||||
required this.publicKey,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChainKeyModel(chains: $chains, privateKey: $privateKey, publicKey: $publicKey)';
|
||||
}
|
||||
}
|
18
lib/core/wallet_connect/models/connection_model.dart
Normal file
18
lib/core/wallet_connect/models/connection_model.dart
Normal file
|
@ -0,0 +1,18 @@
|
|||
class ConnectionModel {
|
||||
final String? title;
|
||||
final String? text;
|
||||
final List<String>? elements;
|
||||
final Map<String, void Function()>? elementActions;
|
||||
|
||||
ConnectionModel({
|
||||
this.title,
|
||||
this.text,
|
||||
this.elements,
|
||||
this.elementActions,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'WalletConnectRequestModel(title: $title, text: $text, elements: $elements, elementActions: $elementActions)';
|
||||
}
|
||||
}
|
14
lib/core/wallet_connect/models/session_request_model.dart
Normal file
14
lib/core/wallet_connect/models/session_request_model.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
|
||||
class SessionRequestModel {
|
||||
final ProposalData request;
|
||||
|
||||
SessionRequestModel({
|
||||
required this.request,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SessionRequestModel(request: $request)';
|
||||
}
|
||||
}
|
72
lib/core/wallet_connect/wallet_connect_key_service.dart
Normal file
72
lib/core/wallet_connect/wallet_connect_key_service.dart
Normal file
|
@ -0,0 +1,72 @@
|
|||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
|
||||
abstract class WalletConnectKeyService {
|
||||
/// Returns a list of all the keys.
|
||||
List<ChainKeyModel> getKeys();
|
||||
|
||||
/// Returns a list of all the chain ids.
|
||||
List<String> getChains();
|
||||
|
||||
/// Returns a list of all the keys for a given chain id.
|
||||
/// If the chain is not found, returns an empty list.
|
||||
/// - [chain]: The chain to get the keys for.
|
||||
List<ChainKeyModel> getKeysForChain(String chain);
|
||||
|
||||
/// Returns a list of all the accounts in namespace:chainId:address format.
|
||||
List<String> getAllAccounts();
|
||||
}
|
||||
|
||||
class KeyServiceImpl implements WalletConnectKeyService {
|
||||
KeyServiceImpl(this.wallet)
|
||||
: _keys = [
|
||||
ChainKeyModel(
|
||||
chains: [
|
||||
'eip155:1',
|
||||
'eip155:5',
|
||||
'eip155:137',
|
||||
'eip155:42161',
|
||||
'eip155:80001',
|
||||
],
|
||||
privateKey: ethereum!.getPrivateKey(wallet),
|
||||
publicKey: ethereum!.getPublicKey(wallet),
|
||||
),
|
||||
|
||||
];
|
||||
|
||||
late final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet;
|
||||
|
||||
late final List<ChainKeyModel> _keys;
|
||||
|
||||
@override
|
||||
List<String> getChains() {
|
||||
final List<String> chainIds = [];
|
||||
for (final ChainKeyModel key in _keys) {
|
||||
chainIds.addAll(key.chains);
|
||||
}
|
||||
return chainIds;
|
||||
}
|
||||
|
||||
@override
|
||||
List<ChainKeyModel> getKeys() => _keys;
|
||||
|
||||
@override
|
||||
List<ChainKeyModel> getKeysForChain(String chain) {
|
||||
return _keys.where((e) => e.chains.contains(chain)).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> getAllAccounts() {
|
||||
final List<String> accounts = [];
|
||||
for (final ChainKeyModel key in _keys) {
|
||||
for (final String chain in key.chains) {
|
||||
accounts.add('$chain:${key.publicKey}');
|
||||
}
|
||||
}
|
||||
return accounts;
|
||||
}
|
||||
}
|
43
lib/core/wallet_connect/wc_bottom_sheet_service.dart
Normal file
43
lib/core/wallet_connect/wc_bottom_sheet_service.dart
Normal file
|
@ -0,0 +1,43 @@
|
|||
import 'dart:async';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/bottom_sheet_queue_item_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class BottomSheetService {
|
||||
abstract final ValueNotifier<BottomSheetQueueItemModel?> currentSheet;
|
||||
|
||||
Future<dynamic> queueBottomSheet({
|
||||
required Widget widget,
|
||||
bool isModalDismissible = false,
|
||||
});
|
||||
|
||||
void resetCurrentSheet();
|
||||
}
|
||||
|
||||
class BottomSheetServiceImpl implements BottomSheetService {
|
||||
|
||||
@override
|
||||
final ValueNotifier<BottomSheetQueueItemModel?> currentSheet = ValueNotifier(null);
|
||||
|
||||
@override
|
||||
Future<dynamic> queueBottomSheet({
|
||||
required Widget widget,
|
||||
bool isModalDismissible = false,
|
||||
}) async {
|
||||
// Create the bottom sheet queue item
|
||||
final completer = Completer<dynamic>();
|
||||
final queueItem = BottomSheetQueueItemModel(
|
||||
widget: widget,
|
||||
completer: completer,
|
||||
isModalDismissible: isModalDismissible,
|
||||
);
|
||||
|
||||
currentSheet.value = queueItem;
|
||||
|
||||
return await completer.future;
|
||||
}
|
||||
|
||||
@override
|
||||
void resetCurrentSheet() {
|
||||
currentSheet.value = null;
|
||||
}
|
||||
}
|
277
lib/core/wallet_connect/web3wallet_service.dart
Normal file
277
lib/core/wallet_connect/web3wallet_service.dart
Normal file
|
@ -0,0 +1,277 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/evm_chain_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/session_request_model.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_request_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/error_display_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:eth_sig_util/eth_sig_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
|
||||
import 'wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
|
||||
part 'web3wallet_service.g.dart';
|
||||
|
||||
class Web3WalletService = Web3WalletServiceBase with _$Web3WalletService;
|
||||
|
||||
abstract class Web3WalletServiceBase with Store {
|
||||
final AppStore appStore;
|
||||
final BottomSheetService _bottomSheetHandler;
|
||||
final WalletConnectKeyService walletKeyService;
|
||||
|
||||
late Web3Wallet _web3Wallet;
|
||||
|
||||
@observable
|
||||
bool isInitialized;
|
||||
|
||||
/// The list of requests from the dapp
|
||||
/// Potential types include, but aren't limited to:
|
||||
/// [SessionProposalEvent], [AuthRequest]
|
||||
@observable
|
||||
ObservableList<PairingInfo> pairings;
|
||||
|
||||
@observable
|
||||
ObservableList<SessionData> sessions;
|
||||
|
||||
@observable
|
||||
ObservableList<StoredCacao> auth;
|
||||
|
||||
Web3WalletServiceBase(this._bottomSheetHandler, this.walletKeyService, this.appStore)
|
||||
: pairings = ObservableList<PairingInfo>(),
|
||||
sessions = ObservableList<SessionData>(),
|
||||
auth = ObservableList<StoredCacao>(),
|
||||
isInitialized = false;
|
||||
|
||||
@action
|
||||
void create() {
|
||||
// Create the web3wallet client
|
||||
_web3Wallet = Web3Wallet(
|
||||
core: Core(projectId: secrets.walletConnectProjectId),
|
||||
metadata: const PairingMetadata(
|
||||
name: 'Cake Wallet',
|
||||
description: 'Cake Wallet',
|
||||
url: 'https://cakewallet.com',
|
||||
icons: ['https://cakewallet.com/assets/image/cake_logo.png'],
|
||||
),
|
||||
);
|
||||
|
||||
// Setup our accounts
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeys();
|
||||
for (final chainKey in chainKeys) {
|
||||
for (final chainId in chainKey.chains) {
|
||||
_web3Wallet.registerAccount(
|
||||
chainId: chainId,
|
||||
accountAddress: chainKey.publicKey,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup our listeners
|
||||
log('Created instance of web3wallet');
|
||||
_web3Wallet.core.pairing.onPairingInvalid.subscribe(_onPairingInvalid);
|
||||
_web3Wallet.core.pairing.onPairingCreate.subscribe(_onPairingCreate);
|
||||
_web3Wallet.core.pairing.onPairingDelete.subscribe(_onPairingDelete);
|
||||
_web3Wallet.core.pairing.onPairingExpire.subscribe(_onPairingDelete);
|
||||
_web3Wallet.pairings.onSync.subscribe(_onPairingsSync);
|
||||
_web3Wallet.onSessionProposal.subscribe(_onSessionProposal);
|
||||
_web3Wallet.onSessionProposalError.subscribe(_onSessionProposalError);
|
||||
_web3Wallet.onSessionConnect.subscribe(_onSessionConnect);
|
||||
_web3Wallet.onAuthRequest.subscribe(_onAuthRequest);
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> init() async {
|
||||
// Await the initialization of the web3wallet
|
||||
log('Intializing web3wallet');
|
||||
if (!isInitialized) {
|
||||
try {
|
||||
await _web3Wallet.init();
|
||||
log('Initialized');
|
||||
isInitialized = true;
|
||||
} catch (e) {
|
||||
log('Experimentallllll: $e');
|
||||
isInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
_refreshPairings();
|
||||
|
||||
final newSessions = _web3Wallet.sessions.getAll();
|
||||
sessions.addAll(newSessions);
|
||||
|
||||
final newAuthRequests = _web3Wallet.completeRequests.getAll();
|
||||
auth.addAll(newAuthRequests);
|
||||
|
||||
for (final cId in EVMChainId.values) {
|
||||
EvmChainServiceImpl(
|
||||
reference: cId,
|
||||
appStore: appStore,
|
||||
wcKeyService: walletKeyService,
|
||||
bottomSheetService: _bottomSheetHandler,
|
||||
wallet: _web3Wallet,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
FutureOr<void> onDispose() {
|
||||
log('web3wallet dispose');
|
||||
_web3Wallet.core.pairing.onPairingInvalid.unsubscribe(_onPairingInvalid);
|
||||
_web3Wallet.pairings.onSync.unsubscribe(_onPairingsSync);
|
||||
_web3Wallet.onSessionProposal.unsubscribe(_onSessionProposal);
|
||||
_web3Wallet.onSessionProposalError.unsubscribe(_onSessionProposalError);
|
||||
_web3Wallet.onSessionConnect.unsubscribe(_onSessionConnect);
|
||||
_web3Wallet.onAuthRequest.unsubscribe(_onAuthRequest);
|
||||
_web3Wallet.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete);
|
||||
_web3Wallet.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete);
|
||||
}
|
||||
|
||||
Web3Wallet getWeb3Wallet() {
|
||||
return _web3Wallet;
|
||||
}
|
||||
|
||||
void _onPairingsSync(StoreSyncEvent? args) {
|
||||
if (args != null) {
|
||||
_refreshPairings();
|
||||
}
|
||||
}
|
||||
|
||||
void _onPairingDelete(PairingEvent? event) {
|
||||
_refreshPairings();
|
||||
}
|
||||
|
||||
@action
|
||||
void _refreshPairings() {
|
||||
pairings.clear();
|
||||
final allPairings = _web3Wallet.pairings.getAll();
|
||||
pairings.addAll(allPairings);
|
||||
}
|
||||
|
||||
Future<void> _onSessionProposalError(SessionProposalErrorEvent? args) async {
|
||||
log(args.toString());
|
||||
}
|
||||
|
||||
void _onSessionProposal(SessionProposalEvent? args) async {
|
||||
if (args != null) {
|
||||
final Widget modalWidget = Web3RequestModal(
|
||||
child: ConnectionRequestWidget(
|
||||
wallet: _web3Wallet,
|
||||
sessionProposal: SessionRequestModel(request: args.params),
|
||||
),
|
||||
);
|
||||
// show the bottom sheet
|
||||
final bool? isApproved = await _bottomSheetHandler.queueBottomSheet(
|
||||
widget: modalWidget,
|
||||
) as bool?;
|
||||
|
||||
if (isApproved != null && isApproved) {
|
||||
_web3Wallet.approveSession(
|
||||
id: args.id,
|
||||
namespaces: args.params.generatedNamespaces!,
|
||||
);
|
||||
} else {
|
||||
_web3Wallet.rejectSession(
|
||||
id: args.id,
|
||||
reason: Errors.getSdkError(
|
||||
Errors.USER_REJECTED,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
void _onPairingInvalid(PairingInvalidEvent? args) {
|
||||
log('Pairing Invalid Event: $args');
|
||||
_bottomSheetHandler.queueBottomSheet(
|
||||
isModalDismissible: true,
|
||||
widget: BottomSheetMessageDisplayWidget(message: '${S.current.pairingInvalidEvent}: $args'),
|
||||
);
|
||||
}
|
||||
|
||||
void _onPairingCreate(PairingEvent? args) {
|
||||
log('Pairing Create Event: $args');
|
||||
}
|
||||
|
||||
@action
|
||||
void _onSessionConnect(SessionConnect? args) {
|
||||
if (args != null) {
|
||||
sessions.add(args.session);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> _onAuthRequest(AuthRequest? args) async {
|
||||
if (args != null) {
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeysForChain('eip155:1');
|
||||
// Create the message to be signed
|
||||
final String iss = 'did:pkh:eip155:1:${chainKeys.first.publicKey}';
|
||||
|
||||
final Widget modalWidget = Web3RequestModal(
|
||||
child: ConnectionRequestWidget(
|
||||
wallet: _web3Wallet,
|
||||
authRequest: AuthRequestModel(iss: iss, request: args),
|
||||
),
|
||||
);
|
||||
final bool? isAuthenticated = await _bottomSheetHandler.queueBottomSheet(
|
||||
widget: modalWidget,
|
||||
) as bool?;
|
||||
|
||||
if (isAuthenticated != null && isAuthenticated) {
|
||||
final String message = _web3Wallet.formatAuthMessage(
|
||||
iss: iss,
|
||||
cacaoPayload: CacaoRequestPayload.fromPayloadParams(
|
||||
args.payloadParams,
|
||||
),
|
||||
);
|
||||
|
||||
final String sig = EthSigUtil.signPersonalMessage(
|
||||
message: Uint8List.fromList(message.codeUnits),
|
||||
privateKey: chainKeys.first.privateKey,
|
||||
);
|
||||
|
||||
await _web3Wallet.respondAuthRequest(
|
||||
id: args.id,
|
||||
iss: iss,
|
||||
signature: CacaoSignature(
|
||||
t: CacaoSignature.EIP191,
|
||||
s: sig,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
await _web3Wallet.respondAuthRequest(
|
||||
id: args.id,
|
||||
iss: iss,
|
||||
error: Errors.getSdkError(
|
||||
Errors.USER_REJECTED_AUTH,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> disconnectSession(String topic) async {
|
||||
final session = sessions.firstWhere((element) => element.pairingTopic == topic);
|
||||
|
||||
await _web3Wallet.core.pairing.disconnect(topic: topic);
|
||||
await _web3Wallet.disconnectSession(
|
||||
topic: session.topic, reason: Errors.getSdkError(Errors.USER_DISCONNECTED));
|
||||
}
|
||||
|
||||
@action
|
||||
List<SessionData> getSessionsForPairingInfo(PairingInfo pairing) {
|
||||
return sessions.where((element) => element.pairingTopic == pairing.topic).toList();
|
||||
}
|
||||
}
|
39
lib/di.dart
39
lib/di.dart
|
@ -3,10 +3,12 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
|||
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/core/yat_service.dart';
|
||||
import 'package:cake_wallet/entities/background_tasks.dart';
|
||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
|
@ -399,6 +401,10 @@ Future<void> setup({
|
|||
}
|
||||
if (appStore.wallet != null) {
|
||||
authStore.allowed();
|
||||
|
||||
if (appStore.wallet!.type == WalletType.ethereum) {
|
||||
getIt.get<Web3WalletService>().init();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -419,6 +425,10 @@ Future<void> setup({
|
|||
} else {
|
||||
if (appStore.wallet != null) {
|
||||
authStore.allowed();
|
||||
|
||||
if (appStore.wallet!.type == WalletType.ethereum) {
|
||||
getIt.get<Web3WalletService>().init();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -438,11 +448,28 @@ Future<void> setup({
|
|||
}, closable: false);
|
||||
}, instanceName: 'login');
|
||||
|
||||
getIt.registerSingleton<BottomSheetService>(BottomSheetServiceImpl());
|
||||
|
||||
final appStore = getIt.get<AppStore>();
|
||||
|
||||
getIt.registerLazySingleton<WalletConnectKeyService>(() => KeyServiceImpl(appStore.wallet!));
|
||||
|
||||
getIt.registerLazySingleton<Web3WalletService>(() {
|
||||
final Web3WalletService web3WalletService = Web3WalletService(
|
||||
getIt.get<BottomSheetService>(),
|
||||
getIt.get<WalletConnectKeyService>(),
|
||||
appStore,
|
||||
);
|
||||
web3WalletService.create();
|
||||
return web3WalletService;
|
||||
});
|
||||
|
||||
getIt.registerFactory(() => BalancePage(
|
||||
dashboardViewModel: getIt.get<DashboardViewModel>(),
|
||||
settingsStore: getIt.get<SettingsStore>()));
|
||||
|
||||
getIt.registerFactory<DashboardPage>(() => DashboardPage(
|
||||
bottomSheetService: getIt.get<BottomSheetService>(),
|
||||
balancePage: getIt.get<BalancePage>(),
|
||||
dashboardViewModel: getIt.get<DashboardViewModel>(),
|
||||
addressListViewModel: getIt.get<WalletAddressListViewModel>(),
|
||||
|
@ -459,6 +486,7 @@ Future<void> setup({
|
|||
});
|
||||
getIt.registerFactoryParam<DesktopDashboardPage, GlobalKey<NavigatorState>, void>(
|
||||
(desktopKey, _) => DesktopDashboardPage(
|
||||
bottomSheetService: getIt.get<BottomSheetService>(),
|
||||
balancePage: getIt.get<BalancePage>(),
|
||||
dashboardViewModel: getIt.get<DashboardViewModel>(),
|
||||
addressListViewModel: getIt.get<WalletAddressListViewModel>(),
|
||||
|
@ -668,7 +696,9 @@ Future<void> setup({
|
|||
return NodeListViewModel(_nodeSource, appStore);
|
||||
});
|
||||
|
||||
getIt.registerFactory(() => ConnectionSyncPage(getIt.get<DashboardViewModel>()));
|
||||
getIt.registerFactory(
|
||||
() => ConnectionSyncPage(getIt.get<DashboardViewModel>(), getIt.get<Web3WalletService>()),
|
||||
);
|
||||
|
||||
getIt.registerFactory(
|
||||
() => SecurityBackupPage(getIt.get<SecuritySettingsViewModel>(), getIt.get<AuthService>()));
|
||||
|
@ -851,9 +881,8 @@ Future<void> setup({
|
|||
|
||||
getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>()));
|
||||
|
||||
getIt.registerFactory(() =>
|
||||
SupportChatPage(
|
||||
getIt.get<SupportViewModel>(), secureStorage: getIt.get<FlutterSecureStorage>()));
|
||||
getIt.registerFactory(() => SupportChatPage(getIt.get<SupportViewModel>(),
|
||||
secureStorage: getIt.get<FlutterSecureStorage>()));
|
||||
|
||||
getIt.registerFactory(() => SupportOtherLinksPage(getIt.get<SupportViewModel>()));
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ class PreferencesKey {
|
|||
static const disableSellKey = 'disable_sell';
|
||||
static const defaultBuyProvider = 'default_buy_provider';
|
||||
static const currentFiatApiModeKey = 'current_fiat_api_mode';
|
||||
static const allowBiometricalAuthenticationKey =
|
||||
'allow_biometrical_authentication';
|
||||
static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication';
|
||||
static const useTOTP2FA = 'use_totp_2fa';
|
||||
static const failedTotpTokenTrials = 'failed_token_trials';
|
||||
static const disableExchangeKey = 'disable_exchange';
|
||||
|
@ -54,8 +53,7 @@ class PreferencesKey {
|
|||
static const clearnetDonationLink = 'clearnet_donation_link';
|
||||
static const onionDonationLink = 'onion_donation_link';
|
||||
static const lastSeenAppVersion = 'last_seen_app_version';
|
||||
static const shouldShowMarketPlaceInDashboard =
|
||||
'should_show_marketplace_in_dashboard';
|
||||
static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard';
|
||||
static const isNewInstall = 'is_new_install';
|
||||
static const shouldRequireTOTP2FAForAccessingWallet =
|
||||
'should_require_totp_2fa_for_accessing_wallets';
|
||||
|
|
|
@ -33,6 +33,20 @@ class CWEthereum extends Ethereum {
|
|||
@override
|
||||
String getAddress(WalletBase wallet) => (wallet as EthereumWallet).walletAddresses.address;
|
||||
|
||||
@override
|
||||
String getPrivateKey(WalletBase wallet) {
|
||||
final privateKeyHolder = (wallet as EthereumWallet).ethPrivateKey;
|
||||
String stringKey = bytesToHex(privateKeyHolder.privateKey);
|
||||
return stringKey;
|
||||
}
|
||||
|
||||
@override
|
||||
String getPublicKey(WalletBase wallet) {
|
||||
final privateKeyInUnitInt = (wallet as EthereumWallet).ethPrivateKey;
|
||||
final publicKey = privateKeyInUnitInt.address.hex;
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getDefaultTransactionPriority() => EthereumTransactionPriority.medium;
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ import 'package:cake_wallet/src/screens/root/root.dart';
|
|||
import 'package:uni_links/uni_links.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
|
||||
final navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
@ -316,17 +315,17 @@ class _HomeState extends State<_Home> {
|
|||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
|
||||
void _setOrientation(BuildContext context) {
|
||||
final orientation = MediaQuery.of(context).orientation;
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
final height = MediaQuery.of(context).size.height;
|
||||
if (orientation == Orientation.portrait && width < height) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
||||
SystemChrome.setPreferredOrientations(
|
||||
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
||||
} else if (orientation == Orientation.landscape && width > height) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
|
||||
SystemChrome.setPreferredOrientations(
|
||||
[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import 'dart:async';
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/main_actions.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart';
|
||||
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
|
@ -35,12 +38,14 @@ import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
|
|||
|
||||
class DashboardPage extends StatelessWidget {
|
||||
DashboardPage({
|
||||
required this.bottomSheetService,
|
||||
required this.balancePage,
|
||||
required this.dashboardViewModel,
|
||||
required this.addressListViewModel,
|
||||
});
|
||||
|
||||
final BalancePage balancePage;
|
||||
final BottomSheetService bottomSheetService;
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
|
||||
|
@ -55,12 +60,14 @@ class DashboardPage extends StatelessWidget {
|
|||
} else {
|
||||
return _DashboardPageView(
|
||||
balancePage: balancePage,
|
||||
bottomSheetService: bottomSheetService,
|
||||
dashboardViewModel: dashboardViewModel,
|
||||
addressListViewModel: addressListViewModel,
|
||||
);
|
||||
}
|
||||
} else if (ResponsiveLayoutUtil.instance.shouldRenderMobileUI()) {
|
||||
return _DashboardPageView(
|
||||
bottomSheetService: bottomSheetService,
|
||||
balancePage: balancePage,
|
||||
dashboardViewModel: dashboardViewModel,
|
||||
addressListViewModel: addressListViewModel,
|
||||
|
@ -76,6 +83,7 @@ class DashboardPage extends StatelessWidget {
|
|||
|
||||
class _DashboardPageView extends BasePage {
|
||||
_DashboardPageView({
|
||||
required this.bottomSheetService,
|
||||
required this.balancePage,
|
||||
required this.dashboardViewModel,
|
||||
required this.addressListViewModel,
|
||||
|
@ -126,6 +134,7 @@ class _DashboardPageView extends BasePage {
|
|||
}
|
||||
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final BottomSheetService bottomSheetService;
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
|
||||
int get initialPage => dashboardViewModel.shouldShowMarketPlaceInDashboard ? 1 : 0;
|
||||
|
@ -158,6 +167,8 @@ class _DashboardPageView extends BasePage {
|
|||
|
||||
return SafeArea(
|
||||
minimum: EdgeInsets.only(bottom: 24),
|
||||
child: BottomSheetListener(
|
||||
bottomSheetService: bottomSheetService,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: <Widget>[
|
||||
|
@ -208,8 +219,9 @@ class _DashboardPageView extends BasePage {
|
|||
color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
|
||||
width: 1,
|
||||
),
|
||||
color:
|
||||
Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
|
||||
color: Theme.of(context)
|
||||
.extension<SyncIndicatorTheme>()!
|
||||
.syncedBackgroundColor,
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 32, right: 32),
|
||||
|
@ -255,6 +267,7 @@ class _DashboardPageView extends BasePage {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart';
|
||||
import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
|
@ -19,12 +21,14 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||
class DesktopDashboardPage extends StatelessWidget {
|
||||
DesktopDashboardPage({
|
||||
required this.balancePage,
|
||||
required this.bottomSheetService,
|
||||
required this.dashboardViewModel,
|
||||
required this.addressListViewModel,
|
||||
required this.desktopKey,
|
||||
});
|
||||
|
||||
final BalancePage balancePage;
|
||||
final BottomSheetService bottomSheetService;
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
final GlobalKey<NavigatorState> desktopKey;
|
||||
|
@ -36,7 +40,9 @@ class DesktopDashboardPage extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
_setEffects(context);
|
||||
|
||||
return Container(
|
||||
return BottomSheetListener(
|
||||
bottomSheetService: bottomSheetService,
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -62,6 +68,7 @@ class DesktopDashboardPage extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/totp_request_details.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/payment_request.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -97,8 +98,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!_isInactive &&
|
||||
widget.authenticationStore.state == AuthenticationState.allowed) {
|
||||
if (!_isInactive && widget.authenticationStore.state == AuthenticationState.allowed) {
|
||||
setState(() => _setInactive(true));
|
||||
}
|
||||
|
||||
|
@ -125,16 +125,15 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
|||
return;
|
||||
} else {
|
||||
final useTotp = widget.appStore.settingsStore.useTOTP2FA;
|
||||
final shouldUseTotp2FAToAccessWallets = widget.appStore
|
||||
.settingsStore.shouldRequireTOTP2FAForAccessingWallet;
|
||||
final shouldUseTotp2FAToAccessWallets =
|
||||
widget.appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet;
|
||||
if (useTotp && shouldUseTotp2FAToAccessWallets) {
|
||||
_reset();
|
||||
auth.close(
|
||||
route: Routes.totpAuthCodePage,
|
||||
arguments: TotpAuthArgumentsModel(
|
||||
onTotpAuthenticationFinished:
|
||||
(bool isAuthenticatedSuccessfully,
|
||||
TotpAuthCodePageState totpAuth) {
|
||||
(bool isAuthenticatedSuccessfully, TotpAuthCodePageState totpAuth) {
|
||||
if (!isAuthenticatedSuccessfully) {
|
||||
return;
|
||||
}
|
||||
|
@ -169,7 +168,10 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
|||
launchUri = null;
|
||||
}
|
||||
|
||||
return WillPopScope(onWillPop: () async => false, child: widget.child);
|
||||
return WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
void _reset() {
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/wallet_connect_button.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
|
@ -15,11 +18,12 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
|||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class ConnectionSyncPage extends BasePage {
|
||||
ConnectionSyncPage(this.dashboardViewModel);
|
||||
ConnectionSyncPage(this.dashboardViewModel, this.web3walletService);
|
||||
|
||||
@override
|
||||
String get title => S.current.connection_sync;
|
||||
|
||||
final Web3WalletService web3walletService;
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
|
||||
@override
|
||||
|
@ -66,6 +70,20 @@ class ConnectionSyncPage extends BasePage {
|
|||
handler: (context) => Navigator.of(context).pushNamed(Routes.manageNodes),
|
||||
),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[
|
||||
WalletConnectTile(
|
||||
onTap: () async {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return WalletConnectConnectionsView(web3walletService: web3walletService);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
46
lib/src/screens/settings/widgets/wallet_connect_button.dart
Normal file
46
lib/src/screens/settings/widgets/wallet_connect_button.dart
Normal file
|
@ -0,0 +1,46 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class WalletConnectTile extends StatelessWidget {
|
||||
const WalletConnectTile({required this.onTap});
|
||||
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Image.asset(
|
||||
'assets/images/walletconnect_logo.png',
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
S.current.walletConnect,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
Image.asset(
|
||||
'assets/images/select_arrow.png',
|
||||
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget.dart';
|
||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
|
||||
import '../../../../core/wallet_connect/models/connection_model.dart';
|
||||
|
||||
class ConnectionWidgetBuilder {
|
||||
static List<ConnectionWidget> buildFromRequiredNamespaces(
|
||||
Map<String, RequiredNamespace> requiredNamespaces,
|
||||
) {
|
||||
final List<ConnectionWidget> views = [];
|
||||
for (final key in requiredNamespaces.keys) {
|
||||
RequiredNamespace ns = requiredNamespaces[key]!;
|
||||
final List<ConnectionModel> models = [];
|
||||
// If the chains property is present, add the chain data to the models
|
||||
if (ns.chains != null) {
|
||||
models.add(ConnectionModel(title: S.current.chains, elements: ns.chains!));
|
||||
}
|
||||
models.add(ConnectionModel(title: S.current.methods, elements: ns.methods));
|
||||
models.add(ConnectionModel(title: S.current.events, elements: ns.events));
|
||||
|
||||
views.add(ConnectionWidget(title: key, info: models));
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
static List<ConnectionWidget> buildFromNamespaces(
|
||||
String topic,
|
||||
Map<String, Namespace> namespaces,
|
||||
Web3Wallet web3wallet,
|
||||
) {
|
||||
final List<ConnectionWidget> views = [];
|
||||
for (final key in namespaces.keys) {
|
||||
final Namespace ns = namespaces[key]!;
|
||||
final List<ConnectionModel> models = [];
|
||||
// If the chains property is present, add the chain data to the models
|
||||
models.add(
|
||||
ConnectionModel(
|
||||
title: S.current.chains,
|
||||
elements: ns.accounts,
|
||||
),
|
||||
);
|
||||
models.add(ConnectionModel(
|
||||
title: S.current.methods,
|
||||
elements: ns.methods,
|
||||
));
|
||||
|
||||
Map<String, void Function()> actions = {};
|
||||
for (final String event in ns.events) {
|
||||
actions[event] = () async {
|
||||
final String chainId = NamespaceUtils.isValidChainId(key)
|
||||
? key
|
||||
: NamespaceUtils.getChainFromAccount(ns.accounts.first);
|
||||
await web3wallet.emitSessionEvent(
|
||||
topic: topic,
|
||||
chainId: chainId,
|
||||
event: SessionEventParams(name: event, data: '${S.current.event}: $event'),
|
||||
);
|
||||
};
|
||||
}
|
||||
models.add(
|
||||
ConnectionModel(title: S.current.events, elements: ns.events, elementActions: actions),
|
||||
);
|
||||
|
||||
views.add(ConnectionWidget(title: key, info: models));
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
}
|
16
lib/src/screens/wallet_connect/utils/string_parsing.dart
Normal file
16
lib/src/screens/wallet_connect/utils/string_parsing.dart
Normal file
|
@ -0,0 +1,16 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:convert/convert.dart';
|
||||
|
||||
extension StringParsing on String {
|
||||
String get utf8Message {
|
||||
if (startsWith('0x')) {
|
||||
final List<int> decoded = hex.decode(
|
||||
substring(2),
|
||||
);
|
||||
return utf8.decode(decoded);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
142
lib/src/screens/wallet_connect/wc_connections_listing_view.dart
Normal file
142
lib/src/screens/wallet_connect/wc_connections_listing_view.dart
Normal file
|
@ -0,0 +1,142 @@
|
|||
import 'dart:developer';
|
||||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
import 'package:cake_wallet/entities/qr_scanner.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
|
||||
import 'widgets/pairing_item_widget.dart';
|
||||
import 'wc_pairing_detail_page.dart';
|
||||
|
||||
class WalletConnectConnectionsView extends StatelessWidget {
|
||||
final Web3WalletService web3walletService;
|
||||
|
||||
WalletConnectConnectionsView({required this.web3walletService, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WCPairingsWidget(web3walletService: web3walletService);
|
||||
}
|
||||
}
|
||||
|
||||
class WCPairingsWidget extends BasePage {
|
||||
WCPairingsWidget({required this.web3walletService, Key? key})
|
||||
: web3wallet = web3walletService.getWeb3Wallet();
|
||||
|
||||
final Web3Wallet web3wallet;
|
||||
final Web3WalletService web3walletService;
|
||||
|
||||
@override
|
||||
String get title => S.current.walletConnect;
|
||||
|
||||
Future<void> _onScanQrCode(BuildContext context, Web3Wallet web3Wallet) async {
|
||||
final String? uri = await presentQRScanner();
|
||||
|
||||
if (uri == null) return _invalidUriToast(context, S.current.nullURIError);
|
||||
|
||||
try {
|
||||
log('_onFoundUri: $uri');
|
||||
final Uri uriData = Uri.parse(uri);
|
||||
await web3Wallet.pair(uri: uriData);
|
||||
} on WalletConnectError catch (e) {
|
||||
await _invalidUriToast(context, e.message);
|
||||
} catch (e) {
|
||||
await _invalidUriToast(context, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _invalidUriToast(BuildContext context, String message) async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: message,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: Navigator.of(context).pop,
|
||||
alertBarrierDismissible: false,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 24),
|
||||
Text(
|
||||
S.current.connectWalletPrompt,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
PrimaryButton(
|
||||
text: S.current.newConnection,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
onPressed: () => _onScanQrCode(context, web3wallet),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 48),
|
||||
Expanded(
|
||||
child: Visibility(
|
||||
visible: web3walletService.pairings.isEmpty,
|
||||
child: Center(
|
||||
child: Text(
|
||||
S.current.activeConnectionsPrompt,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
replacement: ListView.builder(
|
||||
itemCount: web3walletService.pairings.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final pairing = web3walletService.pairings[index];
|
||||
return PairingItemWidget(
|
||||
key: ValueKey(pairing.topic),
|
||||
pairing: pairing,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => WalletConnectPairingDetailsPage(
|
||||
pairing: pairing,
|
||||
web3walletService: web3walletService,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 48),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
186
lib/src/screens/wallet_connect/wc_pairing_detail_page.dart
Normal file
186
lib/src/screens/wallet_connect/wc_pairing_detail_page.dart
Normal file
|
@ -0,0 +1,186 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
|
||||
import 'utils/namespace_model_builder.dart';
|
||||
|
||||
class WalletConnectPairingDetailsPage extends StatefulWidget {
|
||||
final PairingInfo pairing;
|
||||
final Web3WalletService web3walletService;
|
||||
|
||||
const WalletConnectPairingDetailsPage({
|
||||
required this.pairing,
|
||||
required this.web3walletService,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
WalletConnectPairingDetailsPageState createState() => WalletConnectPairingDetailsPageState();
|
||||
}
|
||||
|
||||
class WalletConnectPairingDetailsPageState extends State<WalletConnectPairingDetailsPage> {
|
||||
List<Widget> sessionWidgets = [];
|
||||
late String expiryDate;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initDateTime();
|
||||
initSessions();
|
||||
}
|
||||
|
||||
void initDateTime() {
|
||||
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(widget.pairing.expiry * 1000);
|
||||
int year = dateTime.year;
|
||||
int month = dateTime.month;
|
||||
int day = dateTime.day;
|
||||
|
||||
expiryDate = '$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
void initSessions() {
|
||||
List<SessionData> sessions = widget.web3walletService.getSessionsForPairingInfo(widget.pairing);
|
||||
|
||||
for (final SessionData session in sessions) {
|
||||
List<Widget> namespaceWidget = ConnectionWidgetBuilder.buildFromNamespaces(
|
||||
session.topic,
|
||||
session.namespaces,
|
||||
widget.web3walletService.getWeb3Wallet(),
|
||||
);
|
||||
// Loop through and add the namespace widgets, but put 20 pixels between each one
|
||||
for (int i = 0; i < namespaceWidget.length; i++) {
|
||||
sessionWidgets.add(namespaceWidget[i]);
|
||||
if (i != namespaceWidget.length - 1) {
|
||||
sessionWidgets.add(const SizedBox(height: 20.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WCCDetailsWidget(
|
||||
widget.pairing,
|
||||
expiryDate,
|
||||
sessionWidgets,
|
||||
widget.web3walletService,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WCCDetailsWidget extends BasePage {
|
||||
WCCDetailsWidget(
|
||||
this.pairing,
|
||||
this.expiryDate,
|
||||
this.sessionWidgets,
|
||||
this.web3walletService,
|
||||
);
|
||||
|
||||
final PairingInfo pairing;
|
||||
final String expiryDate;
|
||||
final List<Widget> sessionWidgets;
|
||||
final Web3WalletService web3walletService;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: CircleAvatar(
|
||||
backgroundImage: (pairing.peerMetadata!.icons.isNotEmpty
|
||||
? NetworkImage(pairing.peerMetadata!.icons[0])
|
||||
: const AssetImage('assets/images/default_icon.png'))
|
||||
as ImageProvider<Object>,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
Text(
|
||||
pairing.peerMetadata!.name,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
pairing.peerMetadata!.url,
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
'${S.current.expiresOn}: $expiryDate',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: sessionWidgets,
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
PrimaryButton(
|
||||
onPressed: () =>
|
||||
_onDeleteButtonPressed(context, pairing.peerMetadata!.name, web3walletService),
|
||||
text: S.current.delete,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onDeleteButtonPressed(
|
||||
BuildContext context, String dAppName, Web3WalletService web3walletService) async {
|
||||
bool confirmed = false;
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).delete,
|
||||
alertContent: '${S.current.deleteConnectionConfirmationPrompt} $dAppName?',
|
||||
leftButtonText: S.of(context).cancel,
|
||||
rightButtonText: S.of(context).delete,
|
||||
actionLeftButton: () => Navigator.of(dialogContext).pop(),
|
||||
actionRightButton: () {
|
||||
confirmed = true;
|
||||
Navigator.of(dialogContext).pop();
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (confirmed) {
|
||||
try {
|
||||
await web3walletService.disconnectSession(pairing.topic);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../../core/wallet_connect/models/connection_model.dart';
|
||||
|
||||
class ConnectionItemWidget extends StatelessWidget {
|
||||
const ConnectionItemWidget({required this.model, Key? key}) : super(key: key);
|
||||
|
||||
final ConnectionModel model;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).cardColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
margin: const EdgeInsetsDirectional.only(top: 8),
|
||||
child: Visibility(
|
||||
visible: model.elements != null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
model.title ?? '',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (model.elements != null)
|
||||
Wrap(
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
direction: Axis.horizontal,
|
||||
children: model.elements!
|
||||
.map((e) => _ModelElementWidget(model: model, modelElement: e))
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
replacement: _NoModelElementWidget(model: model),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _NoModelElementWidget extends StatelessWidget {
|
||||
const _NoModelElementWidget({required this.model});
|
||||
|
||||
final ConnectionModel model;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
model.text!,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ModelElementWidget extends StatelessWidget {
|
||||
const _ModelElementWidget({
|
||||
required this.model,
|
||||
required this.modelElement,
|
||||
});
|
||||
|
||||
final ConnectionModel model;
|
||||
final String modelElement;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: model.elementActions != null ? model.elementActions![modelElement] : null,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Text(
|
||||
modelElement,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
maxLines: 10,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
|
||||
import '../../../../core/wallet_connect/models/auth_request_model.dart';
|
||||
import '../../../../core/wallet_connect/models/connection_model.dart';
|
||||
import '../../../../core/wallet_connect/models/session_request_model.dart';
|
||||
import '../utils/namespace_model_builder.dart';
|
||||
import 'connection_widget.dart';
|
||||
|
||||
class ConnectionRequestWidget extends StatefulWidget {
|
||||
const ConnectionRequestWidget({
|
||||
required this.wallet,
|
||||
this.authRequest,
|
||||
this.sessionProposal,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final Web3Wallet wallet;
|
||||
final AuthRequestModel? authRequest;
|
||||
final SessionRequestModel? sessionProposal;
|
||||
|
||||
@override
|
||||
State<ConnectionRequestWidget> createState() => _ConnectionRequestWidgetState();
|
||||
}
|
||||
|
||||
class _ConnectionRequestWidgetState extends State<ConnectionRequestWidget> {
|
||||
ConnectionMetadata? metadata;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Get the connection metadata
|
||||
metadata = widget.authRequest?.request.requester ?? widget.sessionProposal?.request.proposer;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (metadata == null) {
|
||||
return Text(
|
||||
S.current.error,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return _ConnectionMetadataDisplayWidget(
|
||||
metadata: metadata,
|
||||
authRequest: widget.authRequest,
|
||||
sessionProposal: widget.sessionProposal,
|
||||
wallet: widget.wallet,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ConnectionMetadataDisplayWidget extends StatelessWidget {
|
||||
const _ConnectionMetadataDisplayWidget({
|
||||
required this.metadata,
|
||||
required this.wallet,
|
||||
this.authRequest,
|
||||
required this.sessionProposal,
|
||||
});
|
||||
|
||||
final ConnectionMetadata? metadata;
|
||||
final Web3Wallet wallet;
|
||||
final AuthRequestModel? authRequest;
|
||||
final SessionRequestModel? sessionProposal;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Color.fromARGB(255, 18, 18, 19),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
metadata!.metadata.name,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Text(
|
||||
S.current.wouoldLikeToConnect,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
metadata!.metadata.url,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Visibility(
|
||||
visible: authRequest != null,
|
||||
child: _AuthRequestWidget(wallet: wallet, authRequest: authRequest),
|
||||
|
||||
//If authRequest is null, sessionProposal is not null.
|
||||
replacement: _SessionProposalWidget(sessionProposal: sessionProposal!),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AuthRequestWidget extends StatelessWidget {
|
||||
const _AuthRequestWidget({required this.wallet, this.authRequest});
|
||||
|
||||
final Web3Wallet wallet;
|
||||
final AuthRequestModel? authRequest;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final model = ConnectionModel(
|
||||
text: wallet.formatAuthMessage(
|
||||
iss: 'did:pkh:eip155:1:${authRequest!.iss}',
|
||||
cacaoPayload: CacaoRequestPayload.fromPayloadParams(
|
||||
authRequest!.request.payloadParams,
|
||||
),
|
||||
),
|
||||
);
|
||||
return ConnectionWidget(
|
||||
title: S.current.message,
|
||||
info: [model],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SessionProposalWidget extends StatelessWidget {
|
||||
const _SessionProposalWidget({required this.sessionProposal});
|
||||
|
||||
final SessionRequestModel sessionProposal;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Create the connection models using the required and optional namespaces provided by the proposal data
|
||||
// The key is the title and the list of values is the data
|
||||
final List<ConnectionWidget> views = ConnectionWidgetBuilder.buildFromRequiredNamespaces(
|
||||
sessionProposal.request.requiredNamespaces,
|
||||
);
|
||||
|
||||
return Column(children: views);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../core/wallet_connect/models/connection_model.dart';
|
||||
import 'connection_item_widget.dart';
|
||||
|
||||
class ConnectionWidget extends StatelessWidget {
|
||||
const ConnectionWidget({required this.title, required this.info, super.key});
|
||||
|
||||
final String title;
|
||||
final List<ConnectionModel> info;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).primaryColorLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
...info.map((e) => ConnectionItemWidget(model: e)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BottomSheetMessageDisplayWidget extends StatelessWidget {
|
||||
final String message;
|
||||
final bool isError;
|
||||
|
||||
const BottomSheetMessageDisplayWidget({super.key, required this.message, this.isError = true});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
isError ? S.current.error : S.current.successful,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
message,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../../core/wallet_connect/models/bottom_sheet_queue_item_model.dart';
|
||||
|
||||
class BottomSheetListener extends StatefulWidget {
|
||||
final BottomSheetService bottomSheetService;
|
||||
final Widget child;
|
||||
|
||||
const BottomSheetListener({
|
||||
required this.child,
|
||||
required this.bottomSheetService,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
BottomSheetListenerState createState() => BottomSheetListenerState();
|
||||
}
|
||||
|
||||
class BottomSheetListenerState extends State<BottomSheetListener> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.bottomSheetService.currentSheet.addListener(_showBottomSheet);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.bottomSheetService.currentSheet.removeListener(_showBottomSheet);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _showBottomSheet() async {
|
||||
if (widget.bottomSheetService.currentSheet.value != null) {
|
||||
BottomSheetQueueItemModel item = widget.bottomSheetService.currentSheet.value!;
|
||||
final value = await showModalBottomSheet(
|
||||
context: context,
|
||||
isDismissible: item.isModalDismissible,
|
||||
backgroundColor: Color.fromARGB(0, 0, 0, 0),
|
||||
isScrollControlled: true,
|
||||
constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.9),
|
||||
builder: (context) {
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: Color.fromARGB(255, 18, 18, 19),
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
margin: const EdgeInsets.all(16),
|
||||
child: item.widget,
|
||||
);
|
||||
},
|
||||
);
|
||||
item.completer.complete(value);
|
||||
widget.bottomSheetService.resetCurrentSheet();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => widget.child;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Web3RequestModal extends StatelessWidget {
|
||||
const Web3RequestModal({required this.child, this.onAccept, this.onReject, super.key});
|
||||
|
||||
final Widget child;
|
||||
final VoidCallback? onAccept;
|
||||
final VoidCallback? onReject;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
child,
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: onReject ?? () => Navigator.of(context).pop(false),
|
||||
text: S.current.reject,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
textColor: Theme.of(context).colorScheme.onError,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: onAccept ?? () => Navigator.of(context).pop(true),
|
||||
text: S.current.approve,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/pairing_models.dart';
|
||||
|
||||
class PairingItemWidget extends StatelessWidget {
|
||||
const PairingItemWidget({required this.pairing, required this.onTap, super.key});
|
||||
|
||||
final PairingInfo pairing;
|
||||
final void Function() onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
PairingMetadata? metadata = pairing.peerMetadata;
|
||||
if (metadata == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
|
||||
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(pairing.expiry * 1000);
|
||||
int year = dateTime.year;
|
||||
int month = dateTime.month;
|
||||
int day = dateTime.day;
|
||||
|
||||
String expiryDate =
|
||||
'$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}';
|
||||
|
||||
return ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundImage: (metadata.icons.isNotEmpty
|
||||
? NetworkImage(metadata.icons[0])
|
||||
: const AssetImage(
|
||||
'assets/images/default_icon.png',
|
||||
)) as ImageProvider<Object>,
|
||||
),
|
||||
title: Text(
|
||||
metadata.name,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
metadata.url,
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${S.current.expiresOn}: $expiryDate',
|
||||
style: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
trailing: Container(
|
||||
height: 40,
|
||||
width: 44,
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).extension<ReceivePageTheme>()!.iconsBackgroundColor,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
size: 14,
|
||||
color: Theme.of(context).extension<ReceivePageTheme>()!.iconsColor,
|
||||
),
|
||||
),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -595,8 +595,7 @@ abstract class SettingsStoreBase with Store {
|
|||
SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0];
|
||||
final pinNativeTokenAtTop =
|
||||
sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
||||
final useEtherscan =
|
||||
sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
|
||||
// If no value
|
||||
if (pinLength == null || pinLength == 0) {
|
||||
|
|
|
@ -77,33 +77,33 @@ abstract class DashboardViewModelBase with Store {
|
|||
FilterItem(
|
||||
value: () => tradeFilterStore.displayAllTrades,
|
||||
caption: S.current.all_trades,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.all)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.all)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displayChangeNow,
|
||||
caption: ExchangeProviderDescription.changeNow.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.changeNow)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.changeNow)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displaySideShift,
|
||||
caption: ExchangeProviderDescription.sideShift.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.sideShift)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.sideShift)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displaySimpleSwap,
|
||||
caption: ExchangeProviderDescription.simpleSwap.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displayTrocador,
|
||||
caption: ExchangeProviderDescription.trocador.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.trocador)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.trocador)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displayExolix,
|
||||
caption: ExchangeProviderDescription.exolix.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.exolix)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.exolix)),
|
||||
]
|
||||
},
|
||||
subname = '',
|
||||
|
@ -125,15 +125,17 @@ abstract class DashboardViewModelBase with Store {
|
|||
if (_wallet.type == WalletType.monero) {
|
||||
subname = monero!.getCurrentAccount(_wallet).label;
|
||||
|
||||
_onMoneroAccountChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet)
|
||||
.account, (Account account) => _onMoneroAccountChange(_wallet));
|
||||
_onMoneroAccountChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).account,
|
||||
(Account account) => _onMoneroAccountChange(_wallet));
|
||||
|
||||
_onMoneroBalanceChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
_onMoneroBalanceChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
(MoneroBalance balance) => _onMoneroTransactionsUpdate(_wallet));
|
||||
|
||||
final _accountTransactions = _wallet
|
||||
.transactionHistory.transactions.values
|
||||
.where((tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
final _accountTransactions = _wallet.transactionHistory.transactions.values
|
||||
.where((tx) =>
|
||||
monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
.toList();
|
||||
|
||||
transactions = ObservableList.of(_accountTransactions.map((transaction) =>
|
||||
|
@ -142,9 +144,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
} else {
|
||||
transactions = ObservableList.of(wallet
|
||||
.transactionHistory.transactions.values
|
||||
.map((transaction) => TransactionListItem(
|
||||
transactions = ObservableList.of(wallet.transactionHistory.transactions.values.map(
|
||||
(transaction) => TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
|
@ -158,15 +159,15 @@ abstract class DashboardViewModelBase with Store {
|
|||
(TransactionInfo? transaction) => TransactionListItem(
|
||||
transaction: transaction!,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore),
|
||||
filter: (TransactionInfo? transaction) {
|
||||
settingsStore: appStore.settingsStore), filter: (TransactionInfo? transaction) {
|
||||
if (transaction == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final wallet = _wallet;
|
||||
if (wallet.type == WalletType.monero) {
|
||||
return monero!.getTransactionInfoAccountId(transaction) == monero!.getCurrentAccount(wallet).id;
|
||||
return monero!.getTransactionInfoAccountId(transaction) ==
|
||||
monero!.getCurrentAccount(wallet).id;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -216,8 +217,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
}
|
||||
|
||||
@computed
|
||||
BalanceDisplayMode get balanceDisplayMode =>
|
||||
appStore.settingsStore.balanceDisplayMode;
|
||||
BalanceDisplayMode get balanceDisplayMode => appStore.settingsStore.balanceDisplayMode;
|
||||
|
||||
@computed
|
||||
bool get shouldShowMarketPlaceInDashboard {
|
||||
|
@ -225,14 +225,12 @@ abstract class DashboardViewModelBase with Store {
|
|||
}
|
||||
|
||||
@computed
|
||||
List<TradeListItem> get trades => tradesStore.trades
|
||||
.where((trade) => trade.trade.walletId == wallet.id)
|
||||
.toList();
|
||||
List<TradeListItem> get trades =>
|
||||
tradesStore.trades.where((trade) => trade.trade.walletId == wallet.id).toList();
|
||||
|
||||
@computed
|
||||
List<OrderListItem> get orders => ordersStore.orders
|
||||
.where((item) => item.order.walletId == wallet.id)
|
||||
.toList();
|
||||
List<OrderListItem> get orders =>
|
||||
ordersStore.orders.where((item) => item.order.walletId == wallet.id).toList();
|
||||
|
||||
@computed
|
||||
List<AnonpayTransactionListItem> get anonpayTransactons => anonpayTransactionsStore.transactions
|
||||
|
@ -250,7 +248,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
List<ActionListItem> get items {
|
||||
final _items = <ActionListItem>[];
|
||||
|
||||
_items.addAll(transactionFilterStore.filtered(transactions: [...transactions, ...anonpayTransactons]));
|
||||
_items.addAll(
|
||||
transactionFilterStore.filtered(transactions: [...transactions, ...anonpayTransactons]));
|
||||
_items.addAll(tradeFilterStore.filtered(trades: trades, wallet: wallet));
|
||||
_items.addAll(orders);
|
||||
|
||||
|
@ -258,8 +257,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
}
|
||||
|
||||
@observable
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>
|
||||
wallet;
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet;
|
||||
|
||||
bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven;
|
||||
|
||||
|
@ -283,7 +281,6 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
Map<String, List<FilterItem>> filterItems;
|
||||
|
||||
|
||||
BuyProviderType get defaultBuyProvider => settingsStore.defaultBuyProvider;
|
||||
|
||||
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
|
||||
|
@ -291,8 +288,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
|
||||
|
||||
@action
|
||||
void furtherShowYatPopup(bool shouldShow) =>
|
||||
settingsStore.shouldShowYatPopup = shouldShow;
|
||||
void furtherShowYatPopup(bool shouldShow) => settingsStore.shouldShowYatPopup = shouldShow;
|
||||
|
||||
@computed
|
||||
bool get isEnabledExchangeAction => settingsStore.exchangeStatus != ExchangeApiMode.disabled;
|
||||
|
@ -301,8 +297,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
bool hasExchangeAction;
|
||||
|
||||
@computed
|
||||
bool get isEnabledBuyAction =>
|
||||
!settingsStore.disableBuy && wallet.type != WalletType.haven;
|
||||
bool get isEnabledBuyAction => !settingsStore.disableBuy && wallet.type != WalletType.haven;
|
||||
|
||||
@observable
|
||||
bool hasBuyAction;
|
||||
|
@ -330,9 +325,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
@action
|
||||
void _onWalletChange(
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
|
||||
TransactionInfo>?
|
||||
wallet) {
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? wallet) {
|
||||
if (wallet == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -350,10 +343,12 @@ abstract class DashboardViewModelBase with Store {
|
|||
_onMoneroAccountChangeReaction?.reaction.dispose();
|
||||
_onMoneroBalanceChangeReaction?.reaction.dispose();
|
||||
|
||||
_onMoneroAccountChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet)
|
||||
.account, (Account account) => _onMoneroAccountChange(wallet));
|
||||
_onMoneroAccountChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).account,
|
||||
(Account account) => _onMoneroAccountChange(wallet));
|
||||
|
||||
_onMoneroBalanceChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
_onMoneroBalanceChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
(MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet));
|
||||
|
||||
_onMoneroTransactionsUpdate(wallet);
|
||||
|
@ -364,8 +359,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
transactions.clear();
|
||||
|
||||
transactions.addAll(wallet.transactionHistory.transactions.values.map(
|
||||
(transaction) => TransactionListItem(
|
||||
transactions.addAll(wallet.transactionHistory.transactions.values.map((transaction) =>
|
||||
TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
|
@ -374,12 +369,10 @@ abstract class DashboardViewModelBase with Store {
|
|||
connectMapToListWithTransform(
|
||||
appStore.wallet!.transactionHistory.transactions,
|
||||
transactions,
|
||||
(TransactionInfo? transaction)
|
||||
=> TransactionListItem(
|
||||
(TransactionInfo? transaction) => TransactionListItem(
|
||||
transaction: transaction!,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore),
|
||||
filter: (TransactionInfo? tx) {
|
||||
settingsStore: appStore.settingsStore), filter: (TransactionInfo? tx) {
|
||||
if (tx == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -402,12 +395,15 @@ abstract class DashboardViewModelBase with Store {
|
|||
void _onMoneroTransactionsUpdate(WalletBase wallet) {
|
||||
transactions.clear();
|
||||
|
||||
final _accountTransactions = monero!.getTransactionHistory(wallet).transactions.values
|
||||
.where((tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
final _accountTransactions = monero!
|
||||
.getTransactionHistory(wallet)
|
||||
.transactions
|
||||
.values
|
||||
.where(
|
||||
(tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
.toList();
|
||||
|
||||
transactions.addAll(_accountTransactions.map((transaction) =>
|
||||
TransactionListItem(
|
||||
transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
|
|
|
@ -417,7 +417,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
|||
|
||||
String translateErrorMessage(String error, WalletType walletType, CryptoCurrency currency,) {
|
||||
if (walletType == WalletType.ethereum || walletType == WalletType.haven) {
|
||||
if (error.contains('gas required exceeds allowance (0)') || error.contains('insufficient funds for gas')) {
|
||||
if (error.contains('gas required exceeds allowance') || error.contains('insufficient funds for gas')) {
|
||||
return S.current.do_not_have_enough_gas_asset(currency.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,8 @@ dependencies:
|
|||
shared_preferences_android: 2.0.17
|
||||
url_launcher_android: 6.0.24
|
||||
sensitive_clipboard: ^1.0.0
|
||||
walletconnect_flutter_v2: ^2.1.4
|
||||
eth_sig_util: ^0.0.9
|
||||
bitcoin_flutter:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_flutter.git
|
||||
|
|
|
@ -689,8 +689,27 @@
|
|||
"default_buy_provider": "مزود شراء الافتراضي",
|
||||
"ask_each_time": "اسأل في كل مرة",
|
||||
"buy_provider_unavailable": "مزود حاليا غير متوفر.",
|
||||
|
||||
"signTransaction": " ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ",
|
||||
"errorGettingCredentials": "ﺩﺎﻤﺘﻋﻻﺍ ﺕﺎﻧﺎﻴﺑ ﻰﻠﻋ ﻝﻮﺼﺤﻟﺍ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ :ﻞﺸﻓ",
|
||||
"errorSigningTransaction": "ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ",
|
||||
"pairingInvalidEvent": "ﺢﻟﺎﺻ ﺮﻴﻏ ﺙﺪﺣ ﻥﺍﺮﻗﺇ",
|
||||
"chains": "ﻞﺳﻼﺴﻟﺍ",
|
||||
"methods": " ﻕﺮﻃُ",
|
||||
"events": "ﺙﺍﺪﺣﻷﺍ",
|
||||
"reject": "ﺾﻓﺮﻳ",
|
||||
"approve": "ﺪﻤﺘﻌﻳ",
|
||||
"expiresOn": "ﻲﻓ ﻪﺘﻴﺣﻼﺻ ﻲﻬﺘﻨﺗ",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "ﻍﺭﺎﻓ (URI) ﻢﻈﺘﻨﻤﻟﺍ ﺩﺭﺍﻮﻤﻟﺍ ﻑﺮﻌﻣ",
|
||||
"connectWalletPrompt": "ﺕﻼﻣﺎﻌﻤﻟﺍ ءﺍﺮﺟﻹ WalletConnect ﻊﻣ ﻚﺘﻈﻔﺤﻣ ﻞﻴﺻﻮﺘﺑ ﻢﻗ",
|
||||
"newConnection": "ﺪﻳﺪﺟ ﻝﺎﺼﺗﺍ",
|
||||
"activeConnectionsPrompt": "ﺎﻨﻫ ﺔﻄﺸﻨﻟﺍ ﺕﻻﺎﺼﺗﻻﺍ ﺮﻬﻈﺘﺳ",
|
||||
"deleteConnectionConfirmationPrompt": "ـﺑ ﻝﺎﺼﺗﻻﺍ ﻑﺬﺣ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ",
|
||||
"event": "ﺙﺪﺣ",
|
||||
"successful": "ﺢﺟﺎﻧ",
|
||||
"wouoldLikeToConnect": "ﻝﺎﺼﺗﻻﺍ ﻲﻓ ﺐﻏﺮﺗ",
|
||||
"message": "ﺔﻟﺎﺳﺭ",
|
||||
"do_not_have_enough_gas_asset": "ليس لديك ما يكفي من ${currency} لإجراء معاملة وفقًا لشروط شبكة blockchain الحالية. أنت بحاجة إلى المزيد من ${currency} لدفع رسوم شبكة blockchain، حتى لو كنت ترسل أصلًا مختلفًا.",
|
||||
"totp_auth_url": " TOTP ﺔﻗﺩﺎﺼﻤﻟ URL ﻥﺍﻮﻨﻋ"
|
||||
"totp_auth_url": "TOTP ﺔﻗﺩﺎﺼﻤﻟ URL ﻥﺍﻮﻨﻋ",
|
||||
"awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ"
|
||||
}
|
||||
|
||||
|
|
|
@ -685,6 +685,27 @@
|
|||
"default_buy_provider": "Доставчик по подразбиране купува",
|
||||
"ask_each_time": "Питайте всеки път",
|
||||
"buy_provider_unavailable": "Понастоящем доставчик не е наличен.",
|
||||
"signTransaction": "Подпишете транзакция",
|
||||
"errorGettingCredentials": "Неуспешно: Грешка при получаване на идентификационни данни",
|
||||
"errorSigningTransaction": "Възникна грешка при подписване на транзакция",
|
||||
"pairingInvalidEvent": "Невалидно събитие при сдвояване",
|
||||
"chains": "Вериги",
|
||||
"methods": "Методи",
|
||||
"events": "събития",
|
||||
"reject": "Отхвърляне",
|
||||
"approve": "Одобряване",
|
||||
"expiresOn": "Изтича на",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI е нула",
|
||||
"connectWalletPrompt": "Свържете портфейла си с WalletConnect, за да извършвате транзакции",
|
||||
"newConnection": "Нова връзка",
|
||||
"activeConnectionsPrompt": "Тук ще се появят активни връзки",
|
||||
"deleteConnectionConfirmationPrompt": "Сигурни ли сте, че искате да изтриете връзката към",
|
||||
"event": "Събитие",
|
||||
"successful": "Успешен",
|
||||
"wouoldLikeToConnect": "иска да се свърже",
|
||||
"message": "Съобщение",
|
||||
"do_not_have_enough_gas_asset": "Нямате достатъчно ${currency}, за да извършите транзакция с текущите условия на блокчейн мрежата. Имате нужда от повече ${currency}, за да платите таксите за блокчейн мрежа, дори ако изпращате различен актив.",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката."
|
||||
}
|
||||
|
|
|
@ -685,6 +685,27 @@
|
|||
"default_buy_provider": "Výchozí poskytovatel nákupu",
|
||||
"ask_each_time": "Zeptejte se pokaždé",
|
||||
"buy_provider_unavailable": "Poskytovatel aktuálně nedostupný.",
|
||||
"signTransaction": "Podepsat transakci",
|
||||
"errorGettingCredentials": "Selhalo: Chyba při získávání přihlašovacích údajů",
|
||||
"errorSigningTransaction": "Při podepisování transakce došlo k chybě",
|
||||
"pairingInvalidEvent": "Neplatná událost párování",
|
||||
"chains": "Řetězy",
|
||||
"methods": "Metody",
|
||||
"events": "Události",
|
||||
"reject": "Odmítnout",
|
||||
"approve": "Schvalovat",
|
||||
"expiresOn": "Vyprší dne",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI je nulové",
|
||||
"connectWalletPrompt": "Propojte svou peněženku s WalletConnect a provádějte transakce",
|
||||
"newConnection": "Nové připojení",
|
||||
"activeConnectionsPrompt": "Zde se zobrazí aktivní připojení",
|
||||
"deleteConnectionConfirmationPrompt": "Jste si jisti, že chcete smazat připojení k?",
|
||||
"event": "událost",
|
||||
"successful": "Úspěšný",
|
||||
"wouoldLikeToConnect": "by se chtělo připojit",
|
||||
"message": "Zpráva",
|
||||
"do_not_have_enough_gas_asset": "Nemáte dostatek ${currency} k provedení transakce s aktuálními podmínkami blockchainové sítě. K placení poplatků za blockchainovou síť potřebujete více ${currency}, i když posíláte jiné aktivum.",
|
||||
"totp_auth_url": "URL AUTH TOTP"
|
||||
"totp_auth_url": "URL AUTH TOTP",
|
||||
"awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Standard-Kaufanbieter",
|
||||
"ask_each_time": "Jedes Mal fragen",
|
||||
"buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.",
|
||||
"signTransaction": "Transaktion unterzeichnen",
|
||||
"errorGettingCredentials": "Fehlgeschlagen: Fehler beim Abrufen der Anmeldeinformationen",
|
||||
"errorSigningTransaction": "Beim Signieren der Transaktion ist ein Fehler aufgetreten",
|
||||
"pairingInvalidEvent": "Paarung ungültiges Ereignis",
|
||||
"chains": "Ketten",
|
||||
"methods": "Methoden",
|
||||
"events": "Veranstaltungen",
|
||||
"reject": "Ablehnen",
|
||||
"approve": "Genehmigen",
|
||||
"expiresOn": "Läuft aus am",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI ist null",
|
||||
"connectWalletPrompt": "Verbinden Sie Ihr Wallet mit WalletConnect, um Transaktionen durchzuführen",
|
||||
"newConnection": "Neue Verbindung",
|
||||
"activeConnectionsPrompt": "Hier werden aktive Verbindungen angezeigt",
|
||||
"deleteConnectionConfirmationPrompt": "Sind Sie sicher, dass Sie die Verbindung zu löschen möchten?",
|
||||
"event": "Ereignis",
|
||||
"successful": "Erfolgreich",
|
||||
"wouoldLikeToConnect": "möchte mich gerne vernetzen",
|
||||
"message": "Nachricht",
|
||||
"do_not_have_enough_gas_asset": "Sie verfügen nicht über genügend ${currency}, um eine Transaktion unter den aktuellen Bedingungen des Blockchain-Netzwerks durchzuführen. Sie benötigen mehr ${currency}, um die Gebühren für das Blockchain-Netzwerk zu bezahlen, auch wenn Sie einen anderen Vermögenswert senden.",
|
||||
"totp_auth_url": "TOTP-Auth-URL"
|
||||
"totp_auth_url": "TOTP-Auth-URL",
|
||||
"awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat."
|
||||
}
|
||||
|
|
|
@ -694,6 +694,27 @@
|
|||
"ask_each_time": "Ask each time",
|
||||
"robinhood_option_description": "Buy and transfer instantly using your debit card, bank account, or Robinhood balance. USA only.",
|
||||
"buy_provider_unavailable": "Provider currently unavailable.",
|
||||
"signTransaction": "Sign Transaction",
|
||||
"errorGettingCredentials": "Failed: Error while getting credentials",
|
||||
"errorSigningTransaction": "An error has occured while signing transaction",
|
||||
"pairingInvalidEvent": "Pairing Invalid Event",
|
||||
"chains": "Chains",
|
||||
"methods": "Methods",
|
||||
"events": "Events",
|
||||
"reject": "Reject",
|
||||
"approve": "Approve",
|
||||
"expiresOn": "Expires on",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI is null",
|
||||
"connectWalletPrompt": "Connect your wallet with WalletConnect to make transactions",
|
||||
"newConnection": "New Connection",
|
||||
"activeConnectionsPrompt": "Active connections will appear here",
|
||||
"deleteConnectionConfirmationPrompt": "Are you sure that you want to delete the connection to",
|
||||
"event": "Event",
|
||||
"successful": "Successful",
|
||||
"wouoldLikeToConnect": "would like to connect",
|
||||
"message": "Message",
|
||||
"do_not_have_enough_gas_asset": "You do not have enough ${currency} to make a transaction with the current blockchain network conditions. You need more ${currency} to pay blockchain network fees, even if you are sending a different asset.",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "Kindly wait for the dApp to finish processing."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Proveedor de compra predeterminado",
|
||||
"ask_each_time": "Pregunta cada vez",
|
||||
"buy_provider_unavailable": "Proveedor actualmente no disponible.",
|
||||
"signTransaction": "Firmar transacción",
|
||||
"errorGettingCredentials": "Error: error al obtener las credenciales",
|
||||
"errorSigningTransaction": "Se ha producido un error al firmar la transacción.",
|
||||
"pairingInvalidEvent": "Evento de emparejamiento no válido",
|
||||
"chains": "Cadenas",
|
||||
"methods": "Métodos",
|
||||
"events": "Eventos",
|
||||
"reject": "Rechazar",
|
||||
"approve": "Aprobar",
|
||||
"expiresOn": "Expira el",
|
||||
"walletConnect": "MonederoConectar",
|
||||
"nullURIError": "URI es nula",
|
||||
"connectWalletPrompt": "Conecte su billetera con WalletConnect para realizar transacciones",
|
||||
"newConnection": "Nueva conexión",
|
||||
"activeConnectionsPrompt": "Las conexiones activas aparecerán aquí",
|
||||
"deleteConnectionConfirmationPrompt": "¿Está seguro de que desea eliminar la conexión a",
|
||||
"event": "Evento",
|
||||
"successful": "Exitoso",
|
||||
"wouoldLikeToConnect": "quisiera conectar",
|
||||
"message": "Mensaje",
|
||||
"do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.",
|
||||
"totp_auth_url": "URL de autenticación TOTP"
|
||||
"totp_auth_url": "URL de autenticación TOTP",
|
||||
"awaitDAppProcessing": "Espere a que la dApp termine de procesarse."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Fournisseur d'achat par défaut",
|
||||
"ask_each_time": "Demandez à chaque fois",
|
||||
"buy_provider_unavailable": "Fournisseur actuellement indisponible.",
|
||||
"signTransaction": "Signer une transaction",
|
||||
"errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification",
|
||||
"errorSigningTransaction": "Une erreur s'est produite lors de la signature de la transaction",
|
||||
"pairingInvalidEvent": "Événement de couplage non valide",
|
||||
"chains": "Chaînes",
|
||||
"methods": "Méthodes",
|
||||
"events": "Événements",
|
||||
"reject": "Rejeter",
|
||||
"approve": "Approuver",
|
||||
"expiresOn": "Expire le",
|
||||
"walletConnect": "PortefeuilleConnect",
|
||||
"nullURIError": "L'URI est nul",
|
||||
"connectWalletPrompt": "Connectez votre portefeuille avec WalletConnect pour effectuer des transactions",
|
||||
"newConnection": "Nouvelle connexion",
|
||||
"activeConnectionsPrompt": "Les connexions actives apparaîtront ici",
|
||||
"deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à",
|
||||
"event": "Événement",
|
||||
"successful": "Réussi",
|
||||
"wouoldLikeToConnect": "je voudrais me connecter",
|
||||
"message": "Message",
|
||||
"do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.",
|
||||
"totp_auth_url": "URL D'AUTORISATION TOTP"
|
||||
"totp_auth_url": "URL D'AUTORISATION TOTP",
|
||||
"awaitDAppProcessing": "Veuillez attendre que le dApp termine le traitement."
|
||||
}
|
||||
|
|
|
@ -671,6 +671,27 @@
|
|||
"default_buy_provider": "Tsohuwar Siyarwa",
|
||||
"ask_each_time": "Tambaya kowane lokaci",
|
||||
"buy_provider_unavailable": "Mai ba da kyauta a halin yanzu babu.",
|
||||
"signTransaction": "Sa hannu Ma'amala",
|
||||
"errorGettingCredentials": "Ba a yi nasara ba: Kuskure yayin samun takaddun shaida",
|
||||
"errorSigningTransaction": "An sami kuskure yayin sanya hannu kan ciniki",
|
||||
"pairingInvalidEvent": "Haɗa Lamarin mara inganci",
|
||||
"chains": "Sarkoki",
|
||||
"methods": "Hanyoyin",
|
||||
"events": "Abubuwan da suka faru",
|
||||
"reject": "Ƙi",
|
||||
"approve": "Amincewa",
|
||||
"expiresOn": "Yana ƙarewa",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI banza ne",
|
||||
"connectWalletPrompt": "Haɗa walat ɗin ku tare da WalletConnect don yin ma'amala",
|
||||
"newConnection": "Sabuwar Haɗi",
|
||||
"activeConnectionsPrompt": "Haɗin kai mai aiki zai bayyana a nan",
|
||||
"deleteConnectionConfirmationPrompt": "Shin kun tabbata cewa kuna son share haɗin zuwa",
|
||||
"event": "Lamarin",
|
||||
"successful": "Nasara",
|
||||
"wouoldLikeToConnect": "ina son haɗi",
|
||||
"message": "Sako",
|
||||
"do_not_have_enough_gas_asset": "Ba ku da isassun ${currency} don yin ma'amala tare da yanayin cibiyar sadarwar blockchain na yanzu. Kuna buƙatar ƙarin ${currency} don biyan kuɗaɗen cibiyar sadarwar blockchain, koda kuwa kuna aika wata kadara daban.",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "डिफ़ॉल्ट खरीद प्रदाता",
|
||||
"ask_each_time": "हर बार पूछें",
|
||||
"buy_provider_unavailable": "वर्तमान में प्रदाता अनुपलब्ध है।",
|
||||
"signTransaction": "लेन-देन पर हस्ताक्षर करें",
|
||||
"errorGettingCredentials": "विफल: क्रेडेंशियल प्राप्त करते समय त्रुटि",
|
||||
"errorSigningTransaction": "लेन-देन पर हस्ताक्षर करते समय एक त्रुटि उत्पन्न हुई है",
|
||||
"pairingInvalidEvent": "अमान्य ईवेंट युग्मित करना",
|
||||
"chains": "चेन",
|
||||
"methods": "तरीकों",
|
||||
"events": "आयोजन",
|
||||
"reject": "अस्वीकार करना",
|
||||
"approve": "मंज़ूरी देना",
|
||||
"expiresOn": "पर समय सीमा समाप्त",
|
||||
"walletConnect": "वॉलेटकनेक्ट",
|
||||
"nullURIError": "यूआरआई शून्य है",
|
||||
"connectWalletPrompt": "लेन-देन करने के लिए अपने वॉलेट को वॉलेटकनेक्ट से कनेक्ट करें",
|
||||
"newConnection": "नया कनेक्शन",
|
||||
"activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे",
|
||||
"deleteConnectionConfirmationPrompt": "क्या आप वाकई कनेक्शन हटाना चाहते हैं?",
|
||||
"event": "आयोजन",
|
||||
"successful": "सफल",
|
||||
"wouoldLikeToConnect": "जुड़ना चाहेंगे",
|
||||
"message": "संदेश",
|
||||
"do_not_have_enough_gas_asset": "वर्तमान ब्लॉकचेन नेटवर्क स्थितियों में लेनदेन करने के लिए आपके पास पर्याप्त ${currency} नहीं है। ब्लॉकचेन नेटवर्क शुल्क का भुगतान करने के लिए आपको अधिक ${currency} की आवश्यकता है, भले ही आप एक अलग संपत्ति भेज रहे हों।",
|
||||
"totp_auth_url": "TOTP प्रामाणिक यूआरएल"
|
||||
"totp_auth_url": "TOTP प्रामाणिक यूआरएल",
|
||||
"awaitDAppProcessing": "कृपया डीएपी की प्रोसेसिंग पूरी होने तक प्रतीक्षा करें।"
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Zadani davatelj kupnje",
|
||||
"ask_each_time": "Pitajte svaki put",
|
||||
"buy_provider_unavailable": "Davatelj trenutno nije dostupan.",
|
||||
"signTransaction": "Potpišite transakciju",
|
||||
"errorGettingCredentials": "Neuspješno: Pogreška prilikom dobivanja vjerodajnica",
|
||||
"errorSigningTransaction": "Došlo je do pogreške prilikom potpisivanja transakcije",
|
||||
"pairingInvalidEvent": "Nevažeći događaj uparivanja",
|
||||
"chains": "Lanci",
|
||||
"methods": "Metode",
|
||||
"events": "Događaji",
|
||||
"reject": "Odbiti",
|
||||
"approve": "Odobriti",
|
||||
"expiresOn": "Istječe",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI je nula",
|
||||
"connectWalletPrompt": "Povežite svoj novčanik s WalletConnectom za obavljanje transakcija",
|
||||
"newConnection": "Nova veza",
|
||||
"activeConnectionsPrompt": "Ovdje će se pojaviti aktivne veze",
|
||||
"deleteConnectionConfirmationPrompt": "Jeste li sigurni da želite izbrisati vezu s",
|
||||
"event": "Događaj",
|
||||
"successful": "Uspješno",
|
||||
"wouoldLikeToConnect": "želio bi se povezati",
|
||||
"message": "Poruka",
|
||||
"do_not_have_enough_gas_asset": "Nemate dovoljno ${currency} da izvršite transakciju s trenutačnim uvjetima blockchain mreže. Trebate više ${currency} da platite naknade za blockchain mrežu, čak i ako šaljete drugu imovinu.",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "Molimo pričekajte da dApp završi obradu."
|
||||
}
|
|
@ -681,6 +681,27 @@
|
|||
"default_buy_provider": "Penyedia beli default",
|
||||
"ask_each_time": "Tanyakan setiap kali",
|
||||
"buy_provider_unavailable": "Penyedia saat ini tidak tersedia.",
|
||||
"signTransaction": "Tandatangani Transaksi",
|
||||
"errorGettingCredentials": "Gagal: Terjadi kesalahan saat mendapatkan kredensial",
|
||||
"errorSigningTransaction": "Terjadi kesalahan saat menandatangani transaksi",
|
||||
"pairingInvalidEvent": "Menyandingkan Acara Tidak Valid",
|
||||
"chains": "Rantai",
|
||||
"methods": "Metode",
|
||||
"events": "Acara",
|
||||
"reject": "Menolak",
|
||||
"approve": "Menyetujui",
|
||||
"expiresOn": "Kadaluarsa pada",
|
||||
"walletConnect": "DompetConnect",
|
||||
"nullURIError": "URI adalah nol",
|
||||
"connectWalletPrompt": "Hubungkan dompet Anda dengan WalletConnect untuk melakukan transaksi",
|
||||
"newConnection": "Koneksi Baru",
|
||||
"activeConnectionsPrompt": "Koneksi aktif akan muncul di sini",
|
||||
"deleteConnectionConfirmationPrompt": "Apakah Anda yakin ingin menghapus koneksi ke",
|
||||
"event": "Peristiwa",
|
||||
"successful": "Berhasil",
|
||||
"wouoldLikeToConnect": "ingin terhubung",
|
||||
"message": "Pesan",
|
||||
"do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.",
|
||||
"totp_auth_url": "URL Otentikasi TOTP"
|
||||
"totp_auth_url": "URL Otentikasi TOTP",
|
||||
"awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan."
|
||||
}
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Provider di acquisto predefinito",
|
||||
"ask_each_time": "Chiedi ogni volta",
|
||||
"buy_provider_unavailable": "Provider attualmente non disponibile.",
|
||||
"signTransaction": "Firma la transazione",
|
||||
"errorGettingCredentials": "Non riuscito: errore durante il recupero delle credenziali",
|
||||
"errorSigningTransaction": "Si è verificato un errore durante la firma della transazione",
|
||||
"pairingInvalidEvent": "Associazione evento non valido",
|
||||
"chains": "Catene",
|
||||
"methods": "Metodi",
|
||||
"events": "Eventi",
|
||||
"reject": "Rifiutare",
|
||||
"approve": "Approvare",
|
||||
"expiresOn": "Scade il",
|
||||
"walletConnect": "PortafoglioConnetti",
|
||||
"nullURIError": "L'URI è nullo",
|
||||
"connectWalletPrompt": "Collega il tuo portafoglio con WalletConnect per effettuare transazioni",
|
||||
"newConnection": "Nuova connessione",
|
||||
"activeConnectionsPrompt": "Le connessioni attive verranno visualizzate qui",
|
||||
"deleteConnectionConfirmationPrompt": "Sei sicuro di voler eliminare la connessione a",
|
||||
"event": "Evento",
|
||||
"successful": "Riuscito",
|
||||
"wouoldLikeToConnect": "vorrei connettermi",
|
||||
"message": "Messaggio",
|
||||
"do_not_have_enough_gas_asset": "Non hai abbastanza ${currency} per effettuare una transazione con le attuali condizioni della rete blockchain. Hai bisogno di più ${currency} per pagare le commissioni della rete blockchain, anche se stai inviando una risorsa diversa.",
|
||||
"totp_auth_url": "URL DI AUT. TOTP"
|
||||
"totp_auth_url": "URL DI AUT. TOTP",
|
||||
"awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "デフォルトの購入プロバイダー",
|
||||
"ask_each_time": "毎回尋ねてください",
|
||||
"buy_provider_unavailable": "現在、プロバイダーは利用できません。",
|
||||
"signTransaction": "トランザクションに署名する",
|
||||
"errorGettingCredentials": "失敗: 認証情報の取得中にエラーが発生しました",
|
||||
"errorSigningTransaction": "トランザクションの署名中にエラーが発生しました",
|
||||
"pairingInvalidEvent": "ペアリング無効イベント",
|
||||
"chains": "チェーン",
|
||||
"methods": "メソッド",
|
||||
"events": "イベント",
|
||||
"reject": "拒否する",
|
||||
"approve": "承認する",
|
||||
"expiresOn": "有効期限は次のとおりです",
|
||||
"walletConnect": "ウォレットコネクト",
|
||||
"nullURIError": "URIがnullです",
|
||||
"connectWalletPrompt": "ウォレットを WalletConnect に接続して取引を行う",
|
||||
"newConnection": "新しい接続",
|
||||
"activeConnectionsPrompt": "アクティブな接続がここに表示されます",
|
||||
"deleteConnectionConfirmationPrompt": "への接続を削除してもよろしいですか?",
|
||||
"event": "イベント",
|
||||
"successful": "成功",
|
||||
"wouoldLikeToConnect": "接続したいです",
|
||||
"message": "メッセージ",
|
||||
"do_not_have_enough_gas_asset": "現在のブロックチェーン ネットワークの状況では、トランザクションを行うのに十分な ${currency} がありません。別のアセットを送信する場合でも、ブロックチェーン ネットワーク料金を支払うにはさらに ${currency} が必要です。",
|
||||
"totp_auth_url": "TOTP認証URL"
|
||||
"totp_auth_url": "TOTP認証URL",
|
||||
"awaitDAppProcessing": "dAppの処理が完了するまでお待ちください。"
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "기본 구매 제공자",
|
||||
"ask_each_time": "매번 물어보십시오",
|
||||
"buy_provider_unavailable": "제공자는 현재 사용할 수 없습니다.",
|
||||
"signTransaction": "거래 서명",
|
||||
"errorGettingCredentials": "실패: 자격 증명을 가져오는 중 오류가 발생했습니다.",
|
||||
"errorSigningTransaction": "거래에 서명하는 동안 오류가 발생했습니다.",
|
||||
"pairingInvalidEvent": "잘못된 이벤트 페어링",
|
||||
"chains": "쇠사슬",
|
||||
"methods": "행동 양식",
|
||||
"events": "이벤트",
|
||||
"reject": "거부하다",
|
||||
"approve": "승인하다",
|
||||
"expiresOn": "만료 날짜",
|
||||
"walletConnect": "월렛커넥트",
|
||||
"nullURIError": "URI가 null입니다.",
|
||||
"connectWalletPrompt": "거래를 하려면 WalletConnect에 지갑을 연결하세요.",
|
||||
"newConnection": "새로운 연결",
|
||||
"activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다",
|
||||
"deleteConnectionConfirmationPrompt": "다음 연결을 삭제하시겠습니까?",
|
||||
"event": "이벤트",
|
||||
"successful": "성공적인",
|
||||
"wouoldLikeToConnect": "연결하고 싶습니다",
|
||||
"message": "메시지",
|
||||
"do_not_have_enough_gas_asset": "현재 블록체인 네트워크 조건으로 거래를 하기에는 ${currency}이(가) 충분하지 않습니다. 다른 자산을 보내더라도 블록체인 네트워크 수수료를 지불하려면 ${currency}가 더 필요합니다.",
|
||||
"totp_auth_url": "TOTP 인증 URL"
|
||||
"totp_auth_url": "TOTP 인증 URL",
|
||||
"awaitDAppProcessing": "dApp이 처리를 마칠 때까지 기다려주세요."
|
||||
}
|
||||
|
|
|
@ -691,6 +691,27 @@
|
|||
"default_buy_provider": "Default Provider ကိုဝယ်ပါ",
|
||||
"ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ",
|
||||
"buy_provider_unavailable": "လက်ရှိတွင်လက်ရှိမရနိုင်ပါ။",
|
||||
"signTransaction": "ငွေလွှဲဝင်ပါ။",
|
||||
"errorGettingCredentials": "မအောင်မြင်ပါ- အထောက်အထားများ ရယူနေစဉ် အမှားအယွင်း",
|
||||
"errorSigningTransaction": "ငွေပေးငွေယူ လက်မှတ်ထိုးစဉ် အမှားအယွင်းတစ်ခု ဖြစ်ပေါ်ခဲ့သည်။",
|
||||
"pairingInvalidEvent": "မမှန်ကန်သောဖြစ်ရပ်ကို တွဲချိတ်ခြင်း။",
|
||||
"chains": "ဆွဲကြိုး",
|
||||
"methods": "နည်းလမ်းများ",
|
||||
"events": "အဲ့ဒါနဲ့",
|
||||
"reject": "ငြင်းပယ်ပါ။",
|
||||
"approve": "လက်မခံပါ။",
|
||||
"expiresOn": "သက်တမ်းကုန်သည်။",
|
||||
"walletConnect": "Wallet ချိတ်ဆက်မှု",
|
||||
"nullURIError": "URI သည် null ဖြစ်သည်။",
|
||||
"connectWalletPrompt": "အရောင်းအဝယ်ပြုလုပ်ရန် သင့်ပိုက်ဆံအိတ်ကို WalletConnect နှင့် ချိတ်ဆက်ပါ။",
|
||||
"newConnection": "ချိတ်ဆက်မှုအသစ်",
|
||||
"activeConnectionsPrompt": "လက်ရှိချိတ်ဆက်မှုများ ဤနေရာတွင် ပေါ်လာပါမည်။",
|
||||
"deleteConnectionConfirmationPrompt": "ချိတ်ဆက်မှုကို ဖျက်လိုသည်မှာ သေချာပါသလား။",
|
||||
"event": "ပွဲ",
|
||||
"successful": "အောင်မြင်တယ်။",
|
||||
"wouoldLikeToConnect": "ချိတ်ဆက်ချင်ပါတယ်။",
|
||||
"message": "မက်ဆေ့ချ်",
|
||||
"do_not_have_enough_gas_asset": "လက်ရှိ blockchain ကွန်ရက်အခြေအနေများနှင့် အရောင်းအဝယ်ပြုလုပ်ရန် သင့်တွင် ${currency} လုံလောက်မှုမရှိပါ။ သင်သည် မတူညီသော ပိုင်ဆိုင်မှုတစ်ခုကို ပေးပို့နေသော်လည်း blockchain ကွန်ရက်အခကြေးငွေကို ပေးဆောင်ရန် သင်သည် နောက်ထပ် ${currency} လိုအပ်ပါသည်။",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။"
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Standaard Koopprovider",
|
||||
"ask_each_time": "Vraag het elke keer",
|
||||
"buy_provider_unavailable": "Provider momenteel niet beschikbaar.",
|
||||
"signTransaction": "Transactie ondertekenen",
|
||||
"errorGettingCredentials": "Mislukt: fout bij het ophalen van inloggegevens",
|
||||
"errorSigningTransaction": "Er is een fout opgetreden tijdens het ondertekenen van de transactie",
|
||||
"pairingInvalidEvent": "Koppelen Ongeldige gebeurtenis",
|
||||
"chains": "Ketens",
|
||||
"methods": "Methoden",
|
||||
"events": "Evenementen",
|
||||
"reject": "Afwijzen",
|
||||
"approve": "Goedkeuren",
|
||||
"expiresOn": "Verloopt op",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI is nul",
|
||||
"connectWalletPrompt": "Verbind uw portemonnee met WalletConnect om transacties uit te voeren",
|
||||
"newConnection": "Nieuwe verbinding",
|
||||
"activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven",
|
||||
"deleteConnectionConfirmationPrompt": "Weet u zeker dat u de verbinding met",
|
||||
"event": "Evenement",
|
||||
"successful": "Succesvol",
|
||||
"wouoldLikeToConnect": "wil graag verbinden",
|
||||
"message": "Bericht",
|
||||
"do_not_have_enough_gas_asset": "U heeft niet genoeg ${currency} om een transactie uit te voeren met de huidige blockchain-netwerkomstandigheden. U heeft meer ${currency} nodig om blockchain-netwerkkosten te betalen, zelfs als u een ander item verzendt.",
|
||||
"totp_auth_url": "TOTP AUTH-URL"
|
||||
"totp_auth_url": "TOTP AUTH-URL",
|
||||
"awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Domyślny dostawca zakupu",
|
||||
"ask_each_time": "Zapytaj za każdym razem",
|
||||
"buy_provider_unavailable": "Dostawca obecnie niedostępny.",
|
||||
"signTransaction": "Podpisz transakcję",
|
||||
"errorGettingCredentials": "Niepowodzenie: Błąd podczas uzyskiwania poświadczeń",
|
||||
"errorSigningTransaction": "Wystąpił błąd podczas podpisywania transakcji",
|
||||
"pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania",
|
||||
"chains": "Więzy",
|
||||
"methods": "Metody",
|
||||
"events": "Wydarzenia",
|
||||
"reject": "Odrzucić",
|
||||
"approve": "Zatwierdzić",
|
||||
"expiresOn": "Upływa w dniu",
|
||||
"walletConnect": "PortfelPołącz",
|
||||
"nullURIError": "URI ma wartość zerową",
|
||||
"connectWalletPrompt": "Połącz swój portfel z WalletConnect, aby dokonywać transakcji",
|
||||
"newConnection": "Nowe połączenie",
|
||||
"activeConnectionsPrompt": "Tutaj pojawią się aktywne połączenia",
|
||||
"deleteConnectionConfirmationPrompt": "Czy na pewno chcesz usunąć połączenie z",
|
||||
"event": "Wydarzenie",
|
||||
"successful": "Udany",
|
||||
"wouoldLikeToConnect": "chciałbym się połączyć",
|
||||
"message": "Wiadomość",
|
||||
"do_not_have_enough_gas_asset": "Nie masz wystarczającej ilości ${currency}, aby dokonać transakcji przy bieżących warunkach sieci blockchain. Potrzebujesz więcej ${currency}, aby uiścić opłaty za sieć blockchain, nawet jeśli wysyłasz inny zasób.",
|
||||
"totp_auth_url": "Adres URL TOTP AUTH"
|
||||
"totp_auth_url": "Adres URL TOTP AUTH",
|
||||
"awaitDAppProcessing": "Poczekaj, aż dApp zakończy przetwarzanie."
|
||||
}
|
||||
|
|
|
@ -692,6 +692,27 @@
|
|||
"default_buy_provider": "Provedor de compra padrão",
|
||||
"ask_each_time": "Pergunte cada vez",
|
||||
"buy_provider_unavailable": "Provedor atualmente indisponível.",
|
||||
"signTransaction": "Assinar transação",
|
||||
"errorGettingCredentials": "Falha: Erro ao obter credenciais",
|
||||
"errorSigningTransaction": "Ocorreu um erro ao assinar a transação",
|
||||
"pairingInvalidEvent": "Emparelhamento de evento inválido",
|
||||
"chains": "Correntes",
|
||||
"methods": "Métodos",
|
||||
"events": "Eventos",
|
||||
"reject": "Rejeitar",
|
||||
"approve": "Aprovar",
|
||||
"expiresOn": "Expira em",
|
||||
"walletConnect": "CarteiraConectada",
|
||||
"nullURIError": "URI é nulo",
|
||||
"connectWalletPrompt": "Conecte sua carteira ao WalletConnect para fazer transações",
|
||||
"newConnection": "Nova conexão",
|
||||
"activeConnectionsPrompt": "Conexões ativas aparecerão aqui",
|
||||
"deleteConnectionConfirmationPrompt": "Tem certeza de que deseja excluir a conexão com",
|
||||
"event": "Evento",
|
||||
"successful": "Bem-sucedido",
|
||||
"wouoldLikeToConnect": "gostaria de me conectar",
|
||||
"message": "Mensagem",
|
||||
"do_not_have_enough_gas_asset": "Você não tem ${currency} suficiente para fazer uma transação com as condições atuais da rede blockchain. Você precisa de mais ${currency} para pagar as taxas da rede blockchain, mesmo se estiver enviando um ativo diferente.",
|
||||
"totp_auth_url": "URL de autenticação TOTP"
|
||||
"totp_auth_url": "URL de autenticação TOTP",
|
||||
"awaitDAppProcessing": "Aguarde até que o dApp termine o processamento."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "По умолчанию поставщик покупки",
|
||||
"ask_each_time": "Спросите каждый раз",
|
||||
"buy_provider_unavailable": "Поставщик в настоящее время недоступен.",
|
||||
"signTransaction": "Подписать транзакцию",
|
||||
"errorGettingCredentials": "Не удалось: ошибка при получении учетных данных.",
|
||||
"errorSigningTransaction": "Произошла ошибка при подписании транзакции",
|
||||
"pairingInvalidEvent": "Недействительное событие сопряжения",
|
||||
"chains": "Цепи",
|
||||
"methods": "Методы",
|
||||
"events": "События",
|
||||
"reject": "Отклонять",
|
||||
"approve": "Утвердить",
|
||||
"expiresOn": "Годен до",
|
||||
"walletConnect": "КошелекПодключиться",
|
||||
"nullURIError": "URI имеет значение null",
|
||||
"connectWalletPrompt": "Подключите свой кошелек к WalletConnect для совершения транзакций.",
|
||||
"newConnection": "Новое соединение",
|
||||
"activeConnectionsPrompt": "Здесь появятся активные подключения",
|
||||
"deleteConnectionConfirmationPrompt": "Вы уверены, что хотите удалить подключение к",
|
||||
"event": "Событие",
|
||||
"successful": "Успешный",
|
||||
"wouoldLikeToConnect": "хотел бы подключиться",
|
||||
"message": "Сообщение",
|
||||
"do_not_have_enough_gas_asset": "У вас недостаточно ${currency} для совершения транзакции при текущих условиях сети блокчейн. Вам нужно больше ${currency} для оплаты комиссий за сеть блокчейна, даже если вы отправляете другой актив.",
|
||||
"totp_auth_url": "URL-адрес TOTP-АВТОРИЗАЦИИ"
|
||||
"totp_auth_url": "URL-адрес TOTP-АВТОРИЗАЦИИ",
|
||||
"awaitDAppProcessing": "Пожалуйста, подождите, пока dApp завершит обработку."
|
||||
}
|
||||
|
|
|
@ -691,6 +691,27 @@
|
|||
"default_buy_provider": "ผู้ให้บริการซื้อเริ่มต้น",
|
||||
"ask_each_time": "ถามทุกครั้ง",
|
||||
"buy_provider_unavailable": "ผู้ให้บริการไม่สามารถใช้งานได้ในปัจจุบัน",
|
||||
"signTransaction": "ลงนามในการทำธุรกรรม",
|
||||
"errorGettingCredentials": "ล้มเหลว: เกิดข้อผิดพลาดขณะรับข้อมูลรับรอง",
|
||||
"errorSigningTransaction": "เกิดข้อผิดพลาดขณะลงนามธุรกรรม",
|
||||
"pairingInvalidEvent": "การจับคู่เหตุการณ์ที่ไม่ถูกต้อง",
|
||||
"chains": "ห่วงโซ่",
|
||||
"methods": "วิธีการ",
|
||||
"events": "กิจกรรม",
|
||||
"reject": "ปฏิเสธ",
|
||||
"approve": "อนุมัติ",
|
||||
"expiresOn": "หมดอายุวันที่",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI เป็นโมฆะ",
|
||||
"connectWalletPrompt": "เชื่อมต่อกระเป๋าเงินของคุณด้วย WalletConnect เพื่อทำธุรกรรม",
|
||||
"newConnection": "การเชื่อมต่อใหม่",
|
||||
"activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะปรากฏที่นี่",
|
||||
"deleteConnectionConfirmationPrompt": "คุณแน่ใจหรือไม่ว่าต้องการลบการเชื่อมต่อไปยัง",
|
||||
"event": "เหตุการณ์",
|
||||
"successful": "ประสบความสำเร็จ",
|
||||
"wouoldLikeToConnect": "ต้องการเชื่อมต่อ",
|
||||
"message": "ข้อความ",
|
||||
"do_not_have_enough_gas_asset": "คุณมี ${currency} ไม่เพียงพอที่จะทำธุรกรรมกับเงื่อนไขเครือข่ายบล็อคเชนในปัจจุบัน คุณต้องมี ${currency} เพิ่มขึ้นเพื่อชำระค่าธรรมเนียมเครือข่ายบล็อคเชน แม้ว่าคุณจะส่งสินทรัพย์อื่นก็ตาม",
|
||||
"totp_auth_url": "URL การตรวจสอบสิทธิ์ TOTP"
|
||||
"totp_auth_url": "URL การตรวจสอบสิทธิ์ TOTP",
|
||||
"awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น"
|
||||
}
|
||||
|
|
|
@ -688,6 +688,33 @@
|
|||
"support_description_other_links": "Sumali sa aming mga komunidad o maabot sa amin ang aming mga kasosyo sa pamamagitan ng iba pang mga pamamaraan",
|
||||
"select_destination": "Mangyaring piliin ang patutunguhan para sa backup file.",
|
||||
"save_to_downloads": "I -save sa mga pag -download",
|
||||
"select_buy_provider_notice": "Pumili ng provider ng pagbili sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na provider ng pagbili sa mga setting ng app.",
|
||||
"onramper_option_description": "Mabilis na bumili ng crypto na may maraming paraan ng pagbabayad. Available sa karamihan ng mga bansa. Iba-iba ang mga spread at bayarin.",
|
||||
"default_buy_provider": "Default na Provider ng Pagbili",
|
||||
"ask_each_time": "Magtanong sa bawat oras",
|
||||
"robinhood_option_description": "Bumili at ilipat kaagad gamit ang iyong debit card, bank account, o balanse ng Robinhood. USA lang.",
|
||||
"buy_provider_unavailable": "Kasalukuyang hindi available ang provider.",
|
||||
"signTransaction": "Mag-sign Transaksyon",
|
||||
"errorGettingCredentials": "Nabigo: Error habang kumukuha ng mga kredensyal",
|
||||
"errorSigningTransaction": "May naganap na error habang pinipirmahan ang transaksyon",
|
||||
"pairingInvalidEvent": "Pagpares ng Di-wastong Kaganapan",
|
||||
"chains": "Mga tanikala",
|
||||
"methods": "Paraan",
|
||||
"events": "Mga kaganapan",
|
||||
"reject": "Tanggihan",
|
||||
"approve": "Aprubahan",
|
||||
"expiresOn": "Mag-e-expire sa",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "Ang URI ay null",
|
||||
"connectWalletPrompt": "Ikonekta ang iyong wallet sa WalletConnect upang gumawa ng mga transaksyon",
|
||||
"newConnection": "Bagong Koneksyon",
|
||||
"activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon",
|
||||
"deleteConnectionConfirmationPrompt": "Sigurado ka bang gusto mong tanggalin ang koneksyon sa",
|
||||
"event": "Kaganapan",
|
||||
"successful": "Matagumpay",
|
||||
"wouoldLikeToConnect": "gustong kumonekta",
|
||||
"message": "Mensahe",
|
||||
"do_not_have_enough_gas_asset": "Wala kang sapat na ${currency} para gumawa ng transaksyon sa kasalukuyang kundisyon ng network ng blockchain. Kailangan mo ng higit pang ${currency} upang magbayad ng mga bayarin sa network ng blockchain, kahit na nagpapadala ka ng ibang asset.",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "Pakihintay na matapos ang pagproseso ng dApp."
|
||||
}
|
|
@ -691,6 +691,27 @@
|
|||
"default_buy_provider": "Varsayılan Satın Alma Sağlayıcısı",
|
||||
"ask_each_time": "Her seferinde sor",
|
||||
"buy_provider_unavailable": "Sağlayıcı şu anda kullanılamıyor.",
|
||||
"signTransaction": "İşlem İmzala",
|
||||
"errorGettingCredentials": "Başarısız: Kimlik bilgileri alınırken hata oluştu",
|
||||
"errorSigningTransaction": "İşlem imzalanırken bir hata oluştu",
|
||||
"pairingInvalidEvent": "Geçersiz Etkinliği Eşleştirme",
|
||||
"chains": "Zincirler",
|
||||
"methods": "Yöntemler",
|
||||
"events": "Olaylar",
|
||||
"reject": "Reddetmek",
|
||||
"approve": "Onaylamak",
|
||||
"expiresOn": "Tarihinde sona eriyor",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI boş",
|
||||
"connectWalletPrompt": "İşlem yapmak için cüzdanınızı WalletConnect'e bağlayın",
|
||||
"newConnection": "Yeni bağlantı",
|
||||
"activeConnectionsPrompt": "Aktif bağlantılar burada görünecek",
|
||||
"deleteConnectionConfirmationPrompt": "Bağlantıyı silmek istediğinizden emin misiniz?",
|
||||
"event": "Etkinlik",
|
||||
"successful": "Başarılı",
|
||||
"wouoldLikeToConnect": "bağlanmak istiyorum",
|
||||
"message": "İleti",
|
||||
"do_not_have_enough_gas_asset": "Mevcut blockchain ağ koşullarıyla işlem yapmak için yeterli ${currency} paranız yok. Farklı bir varlık gönderiyor olsanız bile blockchain ağ ücretlerini ödemek için daha fazla ${currency} miktarına ihtiyacınız var.",
|
||||
"totp_auth_url": "TOTP YETKİ URL'si"
|
||||
"totp_auth_url": "TOTP YETKİ URL'si",
|
||||
"awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin."
|
||||
}
|
||||
|
|
|
@ -693,6 +693,27 @@
|
|||
"default_buy_provider": "Постачальник покупки за замовчуванням",
|
||||
"ask_each_time": "Запитайте кожен раз",
|
||||
"buy_provider_unavailable": "В даний час постачальник недоступний.",
|
||||
"signTransaction": "Підписати транзакцію",
|
||||
"errorGettingCredentials": "Помилка: помилка під час отримання облікових даних",
|
||||
"errorSigningTransaction": "Під час підписання транзакції сталася помилка",
|
||||
"pairingInvalidEvent": "Недійсна подія сполучення",
|
||||
"chains": "Ланцюги",
|
||||
"methods": "методи",
|
||||
"events": "Події",
|
||||
"reject": "Відхиляти",
|
||||
"approve": "Затвердити",
|
||||
"expiresOn": "Термін дії закінчується",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI нульовий",
|
||||
"connectWalletPrompt": "Підключіть свій гаманець до WalletConnect, щоб здійснювати транзакції",
|
||||
"newConnection": "Нове підключення",
|
||||
"activeConnectionsPrompt": "Тут з’являться активні підключення",
|
||||
"deleteConnectionConfirmationPrompt": "Ви впевнені, що хочете видалити з’єднання з",
|
||||
"event": "Подія",
|
||||
"successful": "Успішний",
|
||||
"wouoldLikeToConnect": "хотів би підключитися",
|
||||
"message": "повідомлення",
|
||||
"do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "Зачекайте, доки dApp завершить обробку."
|
||||
}
|
||||
|
|
|
@ -685,6 +685,27 @@
|
|||
"default_buy_provider": "پہلے سے طے شدہ خریدنے والا",
|
||||
"ask_each_time": "ہر بار پوچھیں",
|
||||
"buy_provider_unavailable": "فراہم کنندہ فی الحال دستیاب نہیں ہے۔",
|
||||
"signTransaction": "۔ﮟﯾﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ",
|
||||
"errorGettingCredentials": "۔ﯽﺑﺍﺮﺧ ﮟﯿﻣ ﮯﻧﺮﮐ ﻞﺻﺎﺣ ﺩﺎﻨﺳﺍ :ﻡﺎﮐﺎﻧ",
|
||||
"errorSigningTransaction": "۔ﮯﮨ ﯽﺌﮔﺁ ﺶﯿﭘ ﯽﺑﺍﺮﺧ ﮏﯾﺍ ﺖﻗﻭ ﮯﺗﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ",
|
||||
"pairingInvalidEvent": "ﭧﻧﻮﯾﺍ ﻂﻠﻏ ﺎﻧﺎﻨﺑ ﺍﮌﻮﺟ",
|
||||
"chains": "ﮟﯾﺮﯿﺠﻧﺯ",
|
||||
"methods": "ﮯﻘﯾﺮﻃ",
|
||||
"events": "ﺕﺎﺒﯾﺮﻘﺗ",
|
||||
"reject": "ﺎﻧﺮﮐ ﺩﺭ",
|
||||
"approve": "ﻭﺮﮐ ﺭﻮﻈﻨﻣ",
|
||||
"expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ",
|
||||
"walletConnect": "WalletConnect",
|
||||
"nullURIError": "URI ۔ﮯﮨ ﻡﺪﻌﻟﺎﮐ",
|
||||
"connectWalletPrompt": "۔ﮟﯾﮌﻮﺟ ﮫﺗﺎﺳ ﮯﮐ WalletConnect ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻦﯾﺩ ﻦﯿﻟ",
|
||||
"newConnection": "ﻦﺸﮑﻨﮐ ﺎﯿﻧ",
|
||||
"activeConnectionsPrompt": "۔ﮯﮔ ﮞﻮﮨ ﺮﮨﺎﻇ ﮞﺎﮩﯾ ﺰﻨﺸﮑﻨﮐ ﻝﺎﻌﻓ",
|
||||
"deleteConnectionConfirmationPrompt": "۔ﮟﯿﮨ ﮯﺘﮨﺎﭼ ﺎﻧﺮﮐ ﻑﺬﺣ ﻮﮐ ﻦﺸﮑﻨﮐ ﭖﺁ ﮧﮐ ﮯﮨ ﻦﯿﻘﯾ ﻮﮐ ﭖﺁ ﺎﯿﮐ",
|
||||
"event": "ﺐﯾﺮﻘﺗ",
|
||||
"successful": "ﺏﺎﯿﻣﺎﮐ",
|
||||
"wouoldLikeToConnect": "؟ﮯﮔ ﮟﯿﮨﺎﭼ ﺎﻧﮍﺟ",
|
||||
"message": "ﻡﺎﻐﯿﭘ",
|
||||
"do_not_have_enough_gas_asset": "آپ کے پاس موجودہ بلاکچین نیٹ ورک کی شرائط کے ساتھ لین دین کرنے کے لیے کافی ${currency} نہیں ہے۔ آپ کو بلاکچین نیٹ ورک کی فیس ادا کرنے کے لیے مزید ${currency} کی ضرورت ہے، چاہے آپ کوئی مختلف اثاثہ بھیج رہے ہوں۔",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ"
|
||||
}
|
||||
|
|
|
@ -687,6 +687,27 @@
|
|||
"default_buy_provider": "Aiyipada Ra Olupese",
|
||||
"ask_each_time": "Beere lọwọ kọọkan",
|
||||
"buy_provider_unavailable": "Olupese lọwọlọwọ ko si.",
|
||||
"signTransaction": "Wole Idunadura",
|
||||
"errorGettingCredentials": "Kuna: Aṣiṣe lakoko gbigba awọn iwe-ẹri",
|
||||
"errorSigningTransaction": "Aṣiṣe kan ti waye lakoko ti o fowo si iṣowo",
|
||||
"pairingInvalidEvent": "Pipọpọ Iṣẹlẹ Ti ko tọ",
|
||||
"chains": "Awọn ẹwọn",
|
||||
"methods": "Awọn ọna",
|
||||
"events": "Awọn iṣẹlẹ",
|
||||
"reject": "Kọ",
|
||||
"approve": "Fi ọwọ si",
|
||||
"expiresOn": "Ipari lori",
|
||||
"walletConnect": "Asopọmọra apamọwọ",
|
||||
"nullURIError": "URI jẹ asan",
|
||||
"connectWalletPrompt": "So apamọwọ rẹ pọ pẹlu WalletConnect lati ṣe awọn iṣowo",
|
||||
"newConnection": "Tuntun Asopọ",
|
||||
"activeConnectionsPrompt": "Awọn asopọ ti nṣiṣe lọwọ yoo han nibi",
|
||||
"deleteConnectionConfirmationPrompt": "Ṣe o da ọ loju pe o fẹ paarẹ asopọ si",
|
||||
"event": "Iṣẹlẹ",
|
||||
"successful": "Aseyori",
|
||||
"wouoldLikeToConnect": "yoo fẹ lati sopọ",
|
||||
"message": "Ifiranṣẹ",
|
||||
"do_not_have_enough_gas_asset": "O ko ni to ${currency} lati ṣe idunadura kan pẹlu awọn ipo nẹtiwọki blockchain lọwọlọwọ. O nilo diẹ sii ${currency} lati san awọn owo nẹtiwọọki blockchain, paapaa ti o ba nfi dukia miiran ranṣẹ.",
|
||||
"totp_auth_url": "TOTP AUTH URL"
|
||||
"totp_auth_url": "TOTP AUTH URL",
|
||||
"awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ."
|
||||
}
|
||||
|
|
|
@ -692,6 +692,27 @@
|
|||
"default_buy_provider": "默认购买提供商",
|
||||
"ask_each_time": "每次问",
|
||||
"buy_provider_unavailable": "提供者目前不可用。",
|
||||
"signTransaction": "签署交易",
|
||||
"errorGettingCredentials": "失败:获取凭据时出错",
|
||||
"errorSigningTransaction": "签署交易时发生错误",
|
||||
"pairingInvalidEvent": "配对无效事件",
|
||||
"chains": "链条",
|
||||
"methods": "方法",
|
||||
"events": "活动",
|
||||
"reject": "拒绝",
|
||||
"approve": "批准",
|
||||
"expiresOn": "到期",
|
||||
"walletConnect": "钱包连接",
|
||||
"nullURIError": "URI 为空",
|
||||
"connectWalletPrompt": "将您的钱包与 WalletConnect 连接以进行交易",
|
||||
"newConnection": "新连接",
|
||||
"activeConnectionsPrompt": "活动连接将出现在这里",
|
||||
"deleteConnectionConfirmationPrompt": "您确定要删除与",
|
||||
"event": "事件",
|
||||
"successful": "成功的",
|
||||
"wouoldLikeToConnect": "想要连接",
|
||||
"message": "信息",
|
||||
"do_not_have_enough_gas_asset": "您没有足够的 ${currency} 来在当前的区块链网络条件下进行交易。即使您发送的是不同的资产,您也需要更多的 ${currency} 来支付区块链网络费用。",
|
||||
"totp_auth_url": "TOTP 授权 URL"
|
||||
"totp_auth_url": "TOTP 授权 URL",
|
||||
"awaitDAppProcessing": "请等待 dApp 处理完成。"
|
||||
}
|
||||
|
|
|
@ -477,6 +477,7 @@ import 'package:cw_core/wallet_base.dart';
|
|||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:eth_sig_util/util/utils.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
""";
|
||||
const ethereumCWHeaders = """
|
||||
|
@ -498,6 +499,8 @@ abstract class Ethereum {
|
|||
WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
|
||||
WalletCredentials createEthereumRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
|
||||
String getAddress(WalletBase wallet);
|
||||
String getPrivateKey(WalletBase wallet);
|
||||
String getPublicKey(WalletBase wallet);
|
||||
TransactionPriority getDefaultTransactionPriority();
|
||||
List<TransactionPriority> getTransactionPriorities();
|
||||
TransactionPriority deserializeEthereumTransactionPriority(int raw);
|
||||
|
|
|
@ -35,6 +35,7 @@ class SecretKey {
|
|||
SecretKey('exolixApiKey', () => ''),
|
||||
SecretKey('robinhoodApplicationId', () => ''),
|
||||
SecretKey('robinhoodCIdApiSecret', () => ''),
|
||||
SecretKey('walletConnectProjectId', () => ''),
|
||||
];
|
||||
|
||||
static final ethereumSecrets = [
|
||||
|
|
Loading…
Reference in a new issue