mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
Merge branch 'v4.10.5_v1.7.5' of https://github.com/cake-tech/cake_wallet into cw_linux_direct_input_password
Conflicts: .github/workflows/pr_test_build.yml cw_bitcoin/lib/electrum_wallet.dart cw_monero/ios/Classes/monero_api.cpp cw_monero/lib/monero_wallet.dart lib/core/auth_service.dart lib/core/backup_service.dart lib/core/wallet_creation_service.dart lib/di.dart lib/ionia/ionia_service.dart lib/store/settings_store.dart macos/Flutter/GeneratedPluginRegistrant.swift pubspec_base.yaml
This commit is contained in:
commit
06fd8b640c
103 changed files with 1356 additions and 775 deletions
2
.github/workflows/cache_dependencies.yml
vendored
2
.github/workflows/cache_dependencies.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: '8.x'
|
||||
java-version: '11.x'
|
||||
|
||||
- name: Flutter action
|
||||
uses: subosito/flutter-action@v1
|
||||
|
|
2
.github/workflows/pr_test_build.yml
vendored
2
.github/workflows/pr_test_build.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: '11.x'
|
||||
java-version: "11.x"
|
||||
|
||||
- name: Flutter action
|
||||
uses: subosito/flutter-action@v1
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
UI enhancements
|
||||
Coin control fixes and enhancements
|
||||
Accessibility enhancements
|
||||
Privacy settings enhancements
|
||||
Tablet/iPad fixes
|
||||
UI enhancements
|
||||
Backup flow fixes
|
||||
Bug fixes
|
|
@ -1,5 +1,6 @@
|
|||
WalletConnect enhancements
|
||||
UI enhancements
|
||||
Coin control fixes and enhancements
|
||||
Accessibility enhancements
|
||||
Privacy settings enhancements
|
||||
Tablet/iPad fixes
|
||||
UI enhancements
|
||||
Backup flow fixes
|
||||
Bug fixes
|
|
@ -2,41 +2,42 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:cw_bitcoin/address_to_output_script.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
|
||||
import 'package:cw_bitcoin/electrum_transaction_history.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
|
||||
import 'package:cw_bitcoin/electrum.dart';
|
||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||
import 'package:cw_bitcoin/electrum_transaction_history.dart';
|
||||
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_bitcoin/file.dart';
|
||||
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
|
||||
import 'package:cw_bitcoin/script_hash.dart';
|
||||
import 'package:cw_bitcoin/utils.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_bitcoin/electrum.dart';
|
||||
import 'package:hex/hex.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:bip32/bip32.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hex/hex.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
|
||||
part 'electrum_wallet.g.dart';
|
||||
|
||||
|
@ -58,8 +59,8 @@ abstract class ElectrumWalletBase
|
|||
ElectrumBalance? initialBalance,
|
||||
CryptoCurrency? currency})
|
||||
: hd = currency == CryptoCurrency.bch
|
||||
? bitcoinCashHDWallet(seedBytes)
|
||||
: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"),
|
||||
? bitcoinCashHDWallet(seedBytes)
|
||||
: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"),
|
||||
syncStatus = NotConnectedSyncStatus(),
|
||||
_password = password,
|
||||
_feeRates = <int>[],
|
||||
|
@ -68,9 +69,9 @@ abstract class ElectrumWalletBase
|
|||
_scripthashesUpdateSubject = {},
|
||||
balance = ObservableMap<CryptoCurrency, ElectrumBalance>.of(currency != null
|
||||
? {
|
||||
currency:
|
||||
initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0)
|
||||
}
|
||||
currency:
|
||||
initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0)
|
||||
}
|
||||
: {}),
|
||||
this.unspentCoinsInfo = unspentCoinsInfo,
|
||||
super(walletInfo) {
|
||||
|
@ -84,8 +85,7 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
|
||||
static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) =>
|
||||
bitcoin.HDWallet.fromSeed(seedBytes)
|
||||
.derivePath("m/44'/145'/0'/0");
|
||||
bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0");
|
||||
|
||||
static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
|
||||
inputsCount * 146 + outputsCounts * 33 + 8;
|
||||
|
@ -303,10 +303,12 @@ abstract class ElectrumWalletBase
|
|||
if (input.isP2wpkh) {
|
||||
final p2wpkh = bitcoin
|
||||
.P2WPKH(
|
||||
data: generatePaymentData(
|
||||
hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
|
||||
index: input.bitcoinAddressRecord.index),
|
||||
network: networkType)
|
||||
data: generatePaymentData(
|
||||
hd: input.bitcoinAddressRecord.isHidden
|
||||
? walletAddresses.sideHd
|
||||
: walletAddresses.mainHd,
|
||||
index: input.bitcoinAddressRecord.index),
|
||||
network: networkType)
|
||||
.data;
|
||||
|
||||
txb.addInput(input.hash, input.vout, null, p2wpkh.output);
|
||||
|
@ -356,12 +358,12 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
|
||||
String toJSON() => json.encode({
|
||||
'mnemonic': mnemonic,
|
||||
'account_index': walletAddresses.currentReceiveAddressIndex.toString(),
|
||||
'change_address_index': walletAddresses.currentChangeAddressIndex.toString(),
|
||||
'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(),
|
||||
'balance': balance[currency]?.toJSON()
|
||||
});
|
||||
'mnemonic': mnemonic,
|
||||
'account_index': walletAddresses.currentReceiveAddressIndex.toString(),
|
||||
'change_address_index': walletAddresses.currentChangeAddressIndex.toString(),
|
||||
'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(),
|
||||
'balance': balance[currency]?.toJSON()
|
||||
});
|
||||
|
||||
int feeRate(TransactionPriority priority) {
|
||||
try {
|
||||
|
@ -376,7 +378,7 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
|
||||
int feeAmountForPriority(
|
||||
BitcoinTransactionPriority priority, int inputsCount, int outputsCount) =>
|
||||
BitcoinTransactionPriority priority, int inputsCount, int outputsCount) =>
|
||||
feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount);
|
||||
|
||||
int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) =>
|
||||
|
@ -476,18 +478,20 @@ abstract class ElectrumWalletBase
|
|||
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||
|
||||
Future<void> updateUnspent() async {
|
||||
final unspent = await Future.wait(walletAddresses
|
||||
.addresses.map((address) => electrumClient
|
||||
final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient
|
||||
.getListUnspentWithAddress(address.address, networkType)
|
||||
.then((unspent) => unspent
|
||||
.map((unspent) {
|
||||
try {
|
||||
return BitcoinUnspent.fromJSON(address, unspent);
|
||||
} catch(_) {
|
||||
return null;
|
||||
}
|
||||
}).whereNotNull())));
|
||||
.then((unspent) => unspent.map((unspent) {
|
||||
try {
|
||||
return BitcoinUnspent.fromJSON(address, unspent);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}).whereNotNull())));
|
||||
unspentCoins = unspent.expand((e) => e).toList();
|
||||
unspentCoins.forEach((coin) async {
|
||||
final tx = await fetchTransactionInfo(hash: coin.hash, height: 0);
|
||||
coin.isChange = tx!.direction == TransactionDirection.outgoing;
|
||||
});
|
||||
|
||||
if (unspentCoinsInfo.isEmpty) {
|
||||
unspentCoins.forEach((coin) => _addCoinInfo(coin));
|
||||
|
@ -524,6 +528,7 @@ abstract class ElectrumWalletBase
|
|||
address: coin.bitcoinAddressRecord.address,
|
||||
value: coin.value,
|
||||
vout: coin.vout,
|
||||
isChange: coin.isChange,
|
||||
);
|
||||
|
||||
await unspentCoinsInfo.add(newInfo);
|
||||
|
@ -533,7 +538,7 @@ abstract class ElectrumWalletBase
|
|||
try {
|
||||
final List<dynamic> keys = <dynamic>[];
|
||||
final currentWalletUnspentCoins =
|
||||
unspentCoinsInfo.values.where((element) => element.walletId.contains(id));
|
||||
unspentCoinsInfo.values.where((element) => element.walletId.contains(id));
|
||||
|
||||
if (currentWalletUnspentCoins.isNotEmpty) {
|
||||
currentWalletUnspentCoins.forEach((element) {
|
||||
|
@ -666,7 +671,7 @@ abstract class ElectrumWalletBase
|
|||
final addresses = walletAddresses.addresses.toList();
|
||||
final balanceFutures = <Future<Map<String, dynamic>>>[];
|
||||
for (var i = 0; i < addresses.length; i++) {
|
||||
final addressRecord = addresses[i] ;
|
||||
final addressRecord = addresses[i];
|
||||
final sh = scriptHash(addressRecord.address, networkType: networkType);
|
||||
final balanceFuture = electrumClient.getBalance(sh);
|
||||
balanceFutures.add(balanceFuture);
|
||||
|
|
|
@ -2,4 +2,5 @@ import 'package:bitbox/bitbox.dart' as bitbox;
|
|||
|
||||
class AddressUtils {
|
||||
static String getCashAddrFormat(String address) => bitbox.Address.toCashAddress(address);
|
||||
static String toLegacyAddress(String address) => bitbox.Address.toLegacyAddress(address);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:bitbox/bitbox.dart' as bitbox;
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
|
@ -301,4 +303,16 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@override
|
||||
String signMessage(String message, {String? address = null}) {
|
||||
final index = address != null
|
||||
? walletAddresses.addresses
|
||||
.firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address))
|
||||
.index
|
||||
: null;
|
||||
return index == null
|
||||
? base64Encode(hd.sign(message))
|
||||
: base64Encode(hd.derive(index).sign(message));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,13 @@ class BitcoinCashWalletService extends WalletService<BitcoinCashNewWalletCredent
|
|||
@override
|
||||
Future<BitcoinCashWallet> create(
|
||||
credentials) async {
|
||||
final strength = (credentials.seedPhraseLength == 12)
|
||||
? 128
|
||||
: (credentials.seedPhraseLength == 24)
|
||||
? 256
|
||||
: 128;
|
||||
final wallet = await BitcoinCashWalletBase.create(
|
||||
mnemonic: await Mnemonic.generate(),
|
||||
mnemonic: await Mnemonic.generate(strength: strength),
|
||||
password: credentials.password!,
|
||||
walletInfo: credentials.walletInfo!,
|
||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||
|
|
|
@ -1 +1 @@
|
|||
/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
||||
/Users/omarhatem/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
|
@ -9,5 +9,5 @@ abstract class Balance {
|
|||
|
||||
String get formattedAdditionalBalance;
|
||||
|
||||
String get formattedFrozenBalance => '';
|
||||
String get formattedUnAvailableBalance => '';
|
||||
}
|
||||
|
|
|
@ -4,17 +4,18 @@ import 'package:cw_core/monero_amount_format.dart';
|
|||
class MoneroBalance extends Balance {
|
||||
MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
|
||||
: formattedFullBalance = moneroAmountToString(amount: fullBalance),
|
||||
formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance),
|
||||
frozenFormatted = moneroAmountToString(amount: frozenBalance),
|
||||
formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance - frozenBalance),
|
||||
formattedLockedBalance =
|
||||
moneroAmountToString(amount: frozenBalance + fullBalance - unlockedBalance),
|
||||
super(unlockedBalance, fullBalance);
|
||||
|
||||
MoneroBalance.fromString(
|
||||
{required this.formattedFullBalance,
|
||||
required this.formattedUnlockedBalance,
|
||||
this.frozenFormatted = '0.0'})
|
||||
this.formattedLockedBalance = '0.0'})
|
||||
: fullBalance = moneroParseAmount(amount: formattedFullBalance),
|
||||
unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance),
|
||||
frozenBalance = moneroParseAmount(amount: frozenFormatted),
|
||||
frozenBalance = moneroParseAmount(amount: formattedLockedBalance),
|
||||
super(moneroParseAmount(amount: formattedUnlockedBalance),
|
||||
moneroParseAmount(amount: formattedFullBalance));
|
||||
|
||||
|
@ -23,10 +24,11 @@ class MoneroBalance extends Balance {
|
|||
final int frozenBalance;
|
||||
final String formattedFullBalance;
|
||||
final String formattedUnlockedBalance;
|
||||
final String frozenFormatted;
|
||||
final String formattedLockedBalance;
|
||||
|
||||
@override
|
||||
String get formattedFrozenBalance => frozenFormatted == '0.0' ? '' : frozenFormatted;
|
||||
String get formattedUnAvailableBalance =>
|
||||
formattedLockedBalance == '0.0' ? '' : formattedLockedBalance;
|
||||
|
||||
@override
|
||||
String get formattedAvailableBalance => formattedUnlockedBalance;
|
||||
|
|
|
@ -14,7 +14,9 @@ class UnspentCoinsInfo extends HiveObject {
|
|||
required this.address,
|
||||
required this.vout,
|
||||
required this.value,
|
||||
this.keyImage = null
|
||||
this.keyImage = null,
|
||||
this.isChange = false,
|
||||
this.accountIndex = 0
|
||||
});
|
||||
|
||||
static const typeId = UNSPENT_COINS_INFO_TYPE_ID;
|
||||
|
@ -47,6 +49,12 @@ class UnspentCoinsInfo extends HiveObject {
|
|||
|
||||
@HiveField(8, defaultValue: null)
|
||||
String? keyImage;
|
||||
|
||||
@HiveField(9, defaultValue: false)
|
||||
bool isChange;
|
||||
|
||||
@HiveField(10, defaultValue: 0)
|
||||
int accountIndex;
|
||||
|
||||
String get note => noteRaw ?? '';
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ class Unspent {
|
|||
Unspent(this.address, this.hash, this.value, this.vout, this.keyImage)
|
||||
: isSending = true,
|
||||
isFrozen = false,
|
||||
isChange = false,
|
||||
note = '';
|
||||
|
||||
final String address;
|
||||
|
@ -10,6 +11,7 @@ class Unspent {
|
|||
final int vout;
|
||||
final String? keyImage;
|
||||
|
||||
bool isChange;
|
||||
bool isSending;
|
||||
bool isFrozen;
|
||||
String note;
|
||||
|
|
|
@ -4,6 +4,7 @@ abstract class WalletCredentials {
|
|||
WalletCredentials({
|
||||
required this.name,
|
||||
this.height,
|
||||
this.seedPhraseLength,
|
||||
this.walletInfo,
|
||||
this.password,
|
||||
this.derivationType,
|
||||
|
@ -12,6 +13,7 @@ abstract class WalletCredentials {
|
|||
|
||||
final String name;
|
||||
final int? height;
|
||||
int? seedPhraseLength;
|
||||
String? password;
|
||||
DerivationType? derivationType;
|
||||
String? derivationPath;
|
||||
|
|
|
@ -38,8 +38,13 @@ class EthereumClient {
|
|||
// });
|
||||
}
|
||||
|
||||
Future<EtherAmount> getBalance(EthereumAddress address) async =>
|
||||
await _client!.getBalance(address);
|
||||
Future<EtherAmount> getBalance(EthereumAddress address) async {
|
||||
try {
|
||||
return await _client!.getBalance(address);
|
||||
} catch (_) {
|
||||
return EtherAmount.zero();
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> getGasUnitPrice() async {
|
||||
try {
|
||||
|
|
|
@ -22,7 +22,14 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
|
|||
|
||||
@override
|
||||
Future<EthereumWallet> create(EthereumNewWalletCredentials credentials) async {
|
||||
final mnemonic = bip39.generateMnemonic();
|
||||
|
||||
final strength = (credentials.seedPhraseLength == 12)
|
||||
? 128
|
||||
: (credentials.seedPhraseLength == 24)
|
||||
? 256
|
||||
: 128;
|
||||
|
||||
final mnemonic = bip39.generateMnemonic(strength: strength);
|
||||
final wallet = EthereumWallet(
|
||||
walletInfo: credentials.walletInfo!,
|
||||
mnemonic: mnemonic,
|
||||
|
|
|
@ -893,6 +893,13 @@ extern "C"
|
|||
return m_transaction_history->count();
|
||||
}
|
||||
|
||||
FUNCTION_VISABILITY_ATTRIBUTE
|
||||
TransactionInfoRow* get_transaction(char * txId)
|
||||
{
|
||||
Monero::TransactionInfo *row = m_transaction_history->transaction(std::string(txId));
|
||||
return new TransactionInfoRow(row);
|
||||
}
|
||||
|
||||
FUNCTION_VISABILITY_ATTRIBUTE
|
||||
int LedgerExchange(
|
||||
unsigned char *command,
|
||||
|
@ -1033,6 +1040,15 @@ extern "C"
|
|||
return result;
|
||||
}
|
||||
|
||||
void freeze_coin(int index)
|
||||
{
|
||||
m_coins->setFrozen(index);
|
||||
}
|
||||
|
||||
void thaw_coin(int index)
|
||||
{
|
||||
m_coins->thaw(index);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -16,8 +16,20 @@ final coinNative = moneroApi
|
|||
.lookup<NativeFunction<coin>>('coin')
|
||||
.asFunction<GetCoin>();
|
||||
|
||||
final freezeCoinNative = moneroApi
|
||||
.lookup<NativeFunction<freeze_coin>>('freeze_coin')
|
||||
.asFunction<FreezeCoin>();
|
||||
|
||||
final thawCoinNative = moneroApi
|
||||
.lookup<NativeFunction<thaw_coin>>('thaw_coin')
|
||||
.asFunction<ThawCoin>();
|
||||
|
||||
void refreshCoins(int accountIndex) => refreshCoinsNative(accountIndex);
|
||||
|
||||
int countOfCoins() => coinsCountNative();
|
||||
|
||||
CoinsInfoRow getCoin(int index) => coinNative(index).ref;
|
||||
|
||||
void freezeCoin(int index) => freezeCoinNative(index);
|
||||
|
||||
void thawCoin(int index) => thawCoinNative(index);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:cw_monero/api/structs/coins_info_row.dart';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_monero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
|
@ -81,6 +82,8 @@ typedef account_set_label = Void Function(Int32 accountIndex, Pointer<Utf8> labe
|
|||
|
||||
typedef transactions_refresh = Void Function();
|
||||
|
||||
typedef get_transaction = Pointer<TransactionInfoRow> Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef get_tx_key = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef transactions_count = Int64 Function();
|
||||
|
@ -139,3 +142,7 @@ typedef coins_count = Int64 Function();
|
|||
// typedef coins_from_txid = Pointer<CoinsInfoRow> Function(Pointer<Utf8> txid);
|
||||
|
||||
typedef coin = Pointer<CoinsInfoRow> Function(Int32 index);
|
||||
|
||||
typedef freeze_coin = Void Function(Int32 index);
|
||||
|
||||
typedef thaw_coin = Void Function(Int32 index);
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import 'dart:ffi';
|
||||
|
||||
import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
||||
import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart';
|
||||
import 'package:cw_monero/api/monero_api.dart';
|
||||
import 'package:cw_monero/api/monero_output.dart';
|
||||
import 'package:cw_monero/api/signatures.dart';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_monero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
||||
import 'package:cw_monero/api/types.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_monero/api/signatures.dart';
|
||||
import 'package:cw_monero/api/types.dart';
|
||||
import 'package:cw_monero/api/monero_api.dart';
|
||||
import 'package:cw_monero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart';
|
||||
|
||||
final transactionsRefreshNative = moneroApi
|
||||
.lookup<NativeFunction<transactions_refresh>>('transactions_refresh')
|
||||
|
@ -38,6 +39,10 @@ final transactionCommitNative = moneroApi
|
|||
final getTxKeyNative =
|
||||
moneroApi.lookup<NativeFunction<get_tx_key>>('get_tx_key').asFunction<GetTxKey>();
|
||||
|
||||
final getTransactionNative = moneroApi
|
||||
.lookup<NativeFunction<get_transaction>>('get_transaction')
|
||||
.asFunction<GetTransaction>();
|
||||
|
||||
String getTxKey(String txId) {
|
||||
final txIdPointer = txId.toNativeUtf8();
|
||||
final keyPointer = getTxKeyNative(txIdPointer);
|
||||
|
@ -65,6 +70,11 @@ List<TransactionInfoRow> getAllTransactions() {
|
|||
.toList();
|
||||
}
|
||||
|
||||
TransactionInfoRow getTransaction(String txId) {
|
||||
final txIdPointer = txId.toNativeUtf8();
|
||||
return getTransactionNative(txIdPointer).ref;
|
||||
}
|
||||
|
||||
PendingTransactionDescription createTransactionSync(
|
||||
{required String address,
|
||||
required String paymentId,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:cw_monero/api/structs/coins_info_row.dart';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_monero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
|
@ -81,6 +82,8 @@ typedef AccountSetLabel = void Function(int accountIndex, Pointer<Utf8> label);
|
|||
|
||||
typedef TransactionsRefresh = void Function();
|
||||
|
||||
typedef GetTransaction = Pointer<TransactionInfoRow> Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef GetTxKey = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef TransactionsCount = int Function();
|
||||
|
@ -139,3 +142,7 @@ typedef RefreshCoins = void Function(int);
|
|||
typedef CoinsCount = int Function();
|
||||
|
||||
typedef GetCoin = Pointer<CoinsInfoRow> Function(int);
|
||||
|
||||
typedef FreezeCoin = void Function(int);
|
||||
|
||||
typedef ThawCoin = void Function(int);
|
||||
|
|
|
@ -1,28 +1,20 @@
|
|||
import 'package:cw_core/unspent_transaction_output.dart';
|
||||
import 'package:cw_monero/api/structs/coins_info_row.dart';
|
||||
|
||||
class MoneroUnspent {
|
||||
MoneroUnspent(this.address, this.hash, this.keyImage, this.value, this.isFrozen, this.isUnlocked)
|
||||
: isSending = true,
|
||||
note = '';
|
||||
class MoneroUnspent extends Unspent {
|
||||
MoneroUnspent(
|
||||
String address, String hash, String keyImage, int value, bool isFrozen, this.isUnlocked)
|
||||
: super(address, hash, value, 0, keyImage) {
|
||||
this.isFrozen = isFrozen;
|
||||
}
|
||||
|
||||
MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow)
|
||||
: address = coinsInfoRow.getAddress(),
|
||||
hash = coinsInfoRow.getHash(),
|
||||
keyImage = coinsInfoRow.getKeyImage(),
|
||||
value = coinsInfoRow.amount,
|
||||
isFrozen = coinsInfoRow.frozen == 1,
|
||||
isUnlocked = coinsInfoRow.unlocked == 1,
|
||||
isSending = true,
|
||||
note = '';
|
||||
|
||||
final String address;
|
||||
final String hash;
|
||||
final String keyImage;
|
||||
final int value;
|
||||
factory MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow) => MoneroUnspent(
|
||||
coinsInfoRow.getAddress(),
|
||||
coinsInfoRow.getHash(),
|
||||
coinsInfoRow.getKeyImage(),
|
||||
coinsInfoRow.amount,
|
||||
coinsInfoRow.frozen == 1,
|
||||
coinsInfoRow.unlocked == 1);
|
||||
|
||||
final bool isUnlocked;
|
||||
|
||||
bool isFrozen;
|
||||
bool isSending;
|
||||
String note;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'dart:io';
|
||||
import 'package:cw_core/account.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/monero_amount_format.dart';
|
||||
|
@ -25,14 +25,14 @@ import 'package:cw_monero/api/transaction_history.dart' as transaction_history;
|
|||
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
|
||||
import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart';
|
||||
import 'package:cw_monero/exceptions/monero_transaction_no_inputs_exception.dart';
|
||||
import 'package:cw_monero/pending_monero_transaction.dart';
|
||||
import 'package:cw_monero/monero_transaction_creation_credentials.dart';
|
||||
import 'package:cw_monero/monero_transaction_history.dart';
|
||||
import 'package:cw_monero/monero_transaction_info.dart';
|
||||
import 'package:cw_monero/monero_unspent.dart';
|
||||
import 'package:cw_monero/monero_wallet_addresses.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_monero/pending_monero_transaction.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'monero_wallet.g.dart';
|
||||
|
||||
|
@ -213,7 +213,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
for (final utx in unspentCoins) {
|
||||
if (utx.isSending) {
|
||||
allInputsAmount += utx.value;
|
||||
inputs.add(utx.keyImage);
|
||||
inputs.add(utx.keyImage!);
|
||||
}
|
||||
}
|
||||
final spendAllCoins = inputs.length == unspentCoins.length;
|
||||
|
@ -407,7 +407,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
for (var i = 0; i < coinCount; i++) {
|
||||
final coin = getCoin(i);
|
||||
if (coin.spent == 0) {
|
||||
unspentCoins.add(MoneroUnspent.fromCoinsInfoRow(coin));
|
||||
final unspent = MoneroUnspent.fromCoinsInfoRow(coin);
|
||||
unspent.isChange = transaction_history.getTransaction(unspent.hash).direction == 1;
|
||||
unspentCoins.add(unspent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,8 +420,10 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
|
||||
if (unspentCoins.isNotEmpty) {
|
||||
unspentCoins.forEach((coin) {
|
||||
final coinInfoList = unspentCoinsInfo.values
|
||||
.where((element) => element.walletId.contains(id) && element.hash.contains(coin.hash));
|
||||
final coinInfoList = unspentCoinsInfo.values.where((element) =>
|
||||
element.walletId.contains(id) &&
|
||||
element.accountIndex == walletAddresses.account!.id &&
|
||||
element.keyImage!.contains(coin.keyImage!));
|
||||
|
||||
if (coinInfoList.isNotEmpty) {
|
||||
final coinInfo = coinInfoList.first;
|
||||
|
@ -447,7 +451,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
address: coin.address,
|
||||
value: coin.value,
|
||||
vout: 0,
|
||||
keyImage: coin.keyImage);
|
||||
keyImage: coin.keyImage,
|
||||
isChange: coin.isChange,
|
||||
accountIndex: walletAddresses.account!.id);
|
||||
|
||||
await unspentCoinsInfo.add(newInfo);
|
||||
}
|
||||
|
@ -455,12 +461,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
Future<void> _refreshUnspentCoinsInfo() async {
|
||||
try {
|
||||
final List<dynamic> keys = <dynamic>[];
|
||||
final currentWalletUnspentCoins =
|
||||
unspentCoinsInfo.values.where((element) => element.walletId.contains(id));
|
||||
final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) =>
|
||||
element.walletId.contains(id) && element.accountIndex == walletAddresses.account!.id);
|
||||
|
||||
if (currentWalletUnspentCoins.isNotEmpty) {
|
||||
currentWalletUnspentCoins.forEach((element) {
|
||||
final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash));
|
||||
final existUnspentCoins =
|
||||
unspentCoins.where((coin) => element.keyImage!.contains(coin.keyImage!));
|
||||
|
||||
if (existUnspentCoins.isEmpty) {
|
||||
keys.add(element.key);
|
||||
|
@ -578,7 +585,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
int _getFrozenBalance() {
|
||||
var frozenBalance = 0;
|
||||
|
||||
for (var coin in unspentCoinsInfo.values) {
|
||||
for (var coin in unspentCoinsInfo.values.where((element) =>
|
||||
element.walletId == id && element.accountIndex == walletAddresses.account!.id)) {
|
||||
if (coin.isFrozen) frozenBalance += coin.value;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,18 +8,28 @@ import 'package:cw_nano/nano_util.dart';
|
|||
import 'package:http/http.dart' as http;
|
||||
import 'package:nanodart/nanodart.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class NanoClient {
|
||||
static const String DEFAULT_REPRESENTATIVE =
|
||||
"nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579";
|
||||
|
||||
static const Map<String, String> CAKE_HEADERS = {
|
||||
"Content-Type": "application/json",
|
||||
"nano-app": "cake-wallet"
|
||||
};
|
||||
|
||||
NanoClient() {
|
||||
SharedPreferences.getInstance().then((value) => prefs = value);
|
||||
}
|
||||
|
||||
late SharedPreferences prefs;
|
||||
Node? _node;
|
||||
Node? _powNode;
|
||||
static const String _defaultDefaultRepresentative =
|
||||
"nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579";
|
||||
|
||||
String getRepFromPrefs() {
|
||||
// from preferences_key.dart "defaultNanoRep" key:
|
||||
return prefs.getString("default_nano_representative") ?? _defaultDefaultRepresentative;
|
||||
}
|
||||
|
||||
bool connect(Node node) {
|
||||
try {
|
||||
|
@ -84,44 +94,45 @@ class NanoClient {
|
|||
required String repAddress,
|
||||
required String ourAddress,
|
||||
}) async {
|
||||
AccountInfoResponse? accountInfo = await getAccountInfo(ourAddress);
|
||||
|
||||
if (accountInfo == null) {
|
||||
throw Exception(
|
||||
"error while getting account info, you can't change the rep of an unopened account");
|
||||
}
|
||||
|
||||
// construct the change block:
|
||||
Map<String, String> changeBlock = {
|
||||
"type": "state",
|
||||
"account": ourAddress,
|
||||
"previous": accountInfo.frontier,
|
||||
"representative": repAddress,
|
||||
"balance": accountInfo.balance,
|
||||
"link": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp",
|
||||
};
|
||||
|
||||
// sign the change block:
|
||||
final String hash = NanoBlocks.computeStateHash(
|
||||
NanoAccountType.NANO,
|
||||
changeBlock["account"]!,
|
||||
changeBlock["previous"]!,
|
||||
changeBlock["representative"]!,
|
||||
BigInt.parse(changeBlock["balance"]!),
|
||||
changeBlock["link"]!,
|
||||
);
|
||||
final String signature = NanoSignatures.signBlock(hash, privateKey);
|
||||
|
||||
// get PoW for the send block:
|
||||
final String work = await requestWork(accountInfo.frontier);
|
||||
|
||||
changeBlock["signature"] = signature;
|
||||
changeBlock["work"] = work;
|
||||
|
||||
try {
|
||||
AccountInfoResponse? accountInfo = await getAccountInfo(ourAddress);
|
||||
|
||||
if (accountInfo == null) {
|
||||
throw Exception("error while getting account info");
|
||||
}
|
||||
|
||||
// construct the change block:
|
||||
Map<String, String> changeBlock = {
|
||||
"type": "state",
|
||||
"account": ourAddress,
|
||||
"previous": accountInfo.frontier,
|
||||
"representative": repAddress,
|
||||
"balance": accountInfo.balance,
|
||||
"link": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp",
|
||||
};
|
||||
|
||||
// sign the change block:
|
||||
final String hash = NanoBlocks.computeStateHash(
|
||||
NanoAccountType.NANO,
|
||||
changeBlock["account"]!,
|
||||
changeBlock["previous"]!,
|
||||
changeBlock["representative"]!,
|
||||
BigInt.parse(changeBlock["balance"]!),
|
||||
changeBlock["link"]!,
|
||||
);
|
||||
final String signature = NanoSignatures.signBlock(hash, privateKey);
|
||||
|
||||
// get PoW for the send block:
|
||||
final String work = await requestWork(accountInfo.frontier);
|
||||
|
||||
changeBlock["signature"] = signature;
|
||||
changeBlock["work"] = work;
|
||||
|
||||
return await processBlock(changeBlock, "change");
|
||||
} catch (e) {
|
||||
throw Exception("error while changing representative");
|
||||
throw Exception("error while changing representative: $e");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,68 +202,63 @@ class NanoClient {
|
|||
BigInt? balanceAfterTx,
|
||||
String? previousHash,
|
||||
}) async {
|
||||
try {
|
||||
// our address:
|
||||
final String publicAddress = NanoUtil.privateKeyToAddress(privateKey);
|
||||
// our address:
|
||||
final String publicAddress = NanoUtil.privateKeyToAddress(privateKey);
|
||||
|
||||
// first get the current account balance:
|
||||
if (balanceAfterTx == null) {
|
||||
final BigInt currentBalance = (await getBalance(publicAddress)).currentBalance;
|
||||
final BigInt txAmount = BigInt.parse(amountRaw);
|
||||
balanceAfterTx = currentBalance - txAmount;
|
||||
}
|
||||
|
||||
// get the account info (we need the frontier and representative):
|
||||
AccountInfoResponse? infoResponse = await getAccountInfo(publicAddress);
|
||||
if (infoResponse == null) {
|
||||
throw Exception(
|
||||
"error while getting account info! (we probably don't have an open account yet)");
|
||||
}
|
||||
|
||||
String frontier = infoResponse.frontier;
|
||||
// override if provided:
|
||||
if (previousHash != null) {
|
||||
frontier = previousHash;
|
||||
}
|
||||
final String representative = infoResponse.representative;
|
||||
// link = destination address:
|
||||
final String link = NanoAccounts.extractPublicKey(destinationAddress);
|
||||
final String linkAsAccount = destinationAddress;
|
||||
|
||||
// construct the send block:
|
||||
Map<String, String> sendBlock = {
|
||||
"type": "state",
|
||||
"account": publicAddress,
|
||||
"previous": frontier,
|
||||
"representative": representative,
|
||||
"balance": balanceAfterTx.toString(),
|
||||
"link": link,
|
||||
};
|
||||
|
||||
// sign the send block:
|
||||
final String hash = NanoBlocks.computeStateHash(
|
||||
NanoAccountType.NANO,
|
||||
sendBlock["account"]!,
|
||||
sendBlock["previous"]!,
|
||||
sendBlock["representative"]!,
|
||||
BigInt.parse(sendBlock["balance"]!),
|
||||
sendBlock["link"]!,
|
||||
);
|
||||
final String signature = NanoSignatures.signBlock(hash, privateKey);
|
||||
|
||||
// get PoW for the send block:
|
||||
final String work = await requestWork(frontier);
|
||||
|
||||
sendBlock["link_as_account"] = linkAsAccount;
|
||||
sendBlock["signature"] = signature;
|
||||
sendBlock["work"] = work;
|
||||
|
||||
// ready to post send block:
|
||||
return sendBlock;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
rethrow;
|
||||
// first get the current account balance:
|
||||
if (balanceAfterTx == null) {
|
||||
final BigInt currentBalance = (await getBalance(publicAddress)).currentBalance;
|
||||
final BigInt txAmount = BigInt.parse(amountRaw);
|
||||
balanceAfterTx = currentBalance - txAmount;
|
||||
}
|
||||
|
||||
// get the account info (we need the frontier and representative):
|
||||
AccountInfoResponse? infoResponse = await getAccountInfo(publicAddress);
|
||||
if (infoResponse == null) {
|
||||
throw Exception(
|
||||
"error while getting account info! (we probably don't have an open account yet)");
|
||||
}
|
||||
|
||||
String frontier = infoResponse.frontier;
|
||||
// override if provided:
|
||||
if (previousHash != null) {
|
||||
frontier = previousHash;
|
||||
}
|
||||
final String representative = infoResponse.representative;
|
||||
// link = destination address:
|
||||
final String link = NanoAccounts.extractPublicKey(destinationAddress);
|
||||
final String linkAsAccount = destinationAddress;
|
||||
|
||||
// construct the send block:
|
||||
Map<String, String> sendBlock = {
|
||||
"type": "state",
|
||||
"account": publicAddress,
|
||||
"previous": frontier,
|
||||
"representative": representative,
|
||||
"balance": balanceAfterTx.toString(),
|
||||
"link": link,
|
||||
};
|
||||
|
||||
// sign the send block:
|
||||
final String hash = NanoBlocks.computeStateHash(
|
||||
NanoAccountType.NANO,
|
||||
sendBlock["account"]!,
|
||||
sendBlock["previous"]!,
|
||||
sendBlock["representative"]!,
|
||||
BigInt.parse(sendBlock["balance"]!),
|
||||
sendBlock["link"]!,
|
||||
);
|
||||
final String signature = NanoSignatures.signBlock(hash, privateKey);
|
||||
|
||||
// get PoW for the send block:
|
||||
final String work = await requestWork(frontier);
|
||||
|
||||
sendBlock["link_as_account"] = linkAsAccount;
|
||||
sendBlock["signature"] = signature;
|
||||
sendBlock["work"] = work;
|
||||
|
||||
// ready to post send block:
|
||||
return sendBlock;
|
||||
}
|
||||
|
||||
Future<void> receiveBlock({
|
||||
|
@ -274,7 +280,7 @@ class NanoClient {
|
|||
// account is not open yet, we need to create an open block:
|
||||
openBlock = true;
|
||||
// we don't have a representative set yet:
|
||||
representative = DEFAULT_REPRESENTATIVE;
|
||||
representative = await getRepFromPrefs();
|
||||
// we don't have a frontier yet:
|
||||
frontier = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
} else {
|
||||
|
|
|
@ -395,7 +395,7 @@ abstract class NanoWalletBase
|
|||
_representativeAddress = accountInfo.representative;
|
||||
} catch (e) {
|
||||
// account not found:
|
||||
_representativeAddress = NanoClient.DEFAULT_REPRESENTATIVE;
|
||||
_representativeAddress = await _client.getRepFromPrefs();
|
||||
throw Exception("Failed to get representative address $e");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,6 +315,11 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -619,6 +624,62 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.4"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -786,4 +847,4 @@ packages:
|
|||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
|
|
@ -21,6 +21,7 @@ dependencies:
|
|||
ed25519_hd_key: ^2.2.0
|
||||
hex: ^0.2.0
|
||||
http: ^1.1.0
|
||||
shared_preferences: ^2.0.15
|
||||
cw_core:
|
||||
path: ../cw_core
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@ PODS:
|
|||
- Flutter
|
||||
- device_display_brightness (0.0.1):
|
||||
- Flutter
|
||||
- device_info (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- devicelocale (0.0.1):
|
||||
|
@ -126,13 +124,13 @@ PODS:
|
|||
- OrderedSet (5.0.0)
|
||||
- package_info (0.0.1):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- permission_handler_apple (9.1.1):
|
||||
- Flutter
|
||||
- platform_device_id (0.0.1):
|
||||
- Flutter
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- SDWebImage (5.16.0):
|
||||
- SDWebImage/Core (= 5.16.0)
|
||||
|
@ -154,7 +152,7 @@ PODS:
|
|||
- CryptoSwift
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- wakelock (0.0.1):
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- workmanager (0.0.1):
|
||||
- Flutter
|
||||
|
@ -167,7 +165,6 @@ DEPENDENCIES:
|
|||
- cw_monero (from `.symlinks/plugins/cw_monero/ios`)
|
||||
- cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
|
||||
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
|
||||
- device_info (from `.symlinks/plugins/device_info/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
|
@ -179,16 +176,16 @@ DEPENDENCIES:
|
|||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
|
||||
- package_info (from `.symlinks/plugins/package_info/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- platform_device_id (from `.symlinks/plugins/platform_device_id/ios`)
|
||||
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||
- UnstoppableDomainsResolution (~> 4.0.0)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
- workmanager (from `.symlinks/plugins/workmanager/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
|
@ -219,8 +216,6 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/cw_shared_external/ios"
|
||||
device_display_brightness:
|
||||
:path: ".symlinks/plugins/device_display_brightness/ios"
|
||||
device_info:
|
||||
:path: ".symlinks/plugins/device_info/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
devicelocale:
|
||||
|
@ -243,12 +238,12 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/local_auth_ios/ios"
|
||||
package_info:
|
||||
:path: ".symlinks/plugins/package_info/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
platform_device_id:
|
||||
:path: ".symlinks/plugins/platform_device_id/ios"
|
||||
sensitive_clipboard:
|
||||
:path: ".symlinks/plugins/sensitive_clipboard/ios"
|
||||
share_plus:
|
||||
|
@ -259,8 +254,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/uni_links/ios"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
wakelock:
|
||||
:path: ".symlinks/plugins/wakelock/ios"
|
||||
wakelock_plus:
|
||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||
workmanager:
|
||||
:path: ".symlinks/plugins/workmanager/ios"
|
||||
|
||||
|
@ -273,12 +268,11 @@ SPEC CHECKSUMS:
|
|||
cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d
|
||||
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
|
||||
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
|
||||
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
|
||||
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
devicelocale: b22617f40038496deffba44747101255cee005b0
|
||||
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
|
||||
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
|
||||
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
|
||||
file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf
|
||||
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
|
||||
|
@ -289,9 +283,9 @@ SPEC CHECKSUMS:
|
|||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
|
||||
platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6
|
||||
sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
|
||||
|
@ -303,7 +297,7 @@ SPEC CHECKSUMS:
|
|||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
||||
url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86
|
||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
|
||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||
|
||||
PODFILE CHECKSUM: 09df1114e7c360f55770d35a79356bf5446e0100
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'dart:convert';
|
|||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
@ -12,8 +11,7 @@ import 'package:http/http.dart' as http;
|
|||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class RobinhoodBuyProvider {
|
||||
RobinhoodBuyProvider({required WalletBase wallet})
|
||||
: this._wallet = wallet;
|
||||
RobinhoodBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
||||
|
||||
final WalletBase _wallet;
|
||||
|
||||
|
@ -21,10 +19,15 @@ class RobinhoodBuyProvider {
|
|||
static const _cIdBaseUrl = 'exchange-helper.cakewallet.com';
|
||||
|
||||
String get _applicationId => secrets.robinhoodApplicationId;
|
||||
|
||||
String get _apiSecret => secrets.robinhoodCIdApiSecret;
|
||||
|
||||
bool get isAvailable =>
|
||||
[WalletType.bitcoin, WalletType.litecoin, WalletType.ethereum].contains(_wallet.type);
|
||||
bool get isAvailable => [
|
||||
WalletType.bitcoin,
|
||||
WalletType.bitcoinCash,
|
||||
WalletType.litecoin,
|
||||
WalletType.ethereum
|
||||
].contains(_wallet.type);
|
||||
|
||||
String getSignature(String message) {
|
||||
switch (_wallet.type) {
|
||||
|
@ -32,6 +35,7 @@ class RobinhoodBuyProvider {
|
|||
return _wallet.signMessage(message);
|
||||
case WalletType.litecoin:
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.bitcoinCash:
|
||||
return _wallet.signMessage(message, address: _wallet.walletAddresses.address);
|
||||
default:
|
||||
throw Exception("WalletType is not available for Robinhood ${_wallet.type}");
|
||||
|
@ -55,7 +59,8 @@ class RobinhoodBuyProvider {
|
|||
if (response.statusCode == 200) {
|
||||
return (jsonDecode(response.body) as Map<String, dynamic>)['connectId'] as String;
|
||||
} else {
|
||||
throw Exception('Provider currently unavailable. Status: ${response.statusCode} ${response.body}');
|
||||
throw Exception(
|
||||
'Provider currently unavailable. Status: ${response.statusCode} ${response.body}');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,8 +81,7 @@ class RobinhoodBuyProvider {
|
|||
try {
|
||||
final uri = await requestUrl();
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} catch (e, s) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(exception: e, stack: s));
|
||||
} catch (_) {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/core/totp_request_details.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||
|
@ -38,6 +40,11 @@ class AuthService with Store {
|
|||
Future<void> setPassword(String password) async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final encodedPassword = encodedPinCode(pin: password);
|
||||
// secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless
|
||||
// we delete what's there first:
|
||||
if (Platform.isMacOS) {
|
||||
await secureStorage.delete(key: key);
|
||||
}
|
||||
await secureStorage.write(key: key, value: encodedPassword);
|
||||
}
|
||||
|
||||
|
@ -104,8 +111,7 @@ class AuthService with Store {
|
|||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Navigator.of(context).pushNamed(Routes.auth,
|
||||
arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async {
|
||||
|
@ -140,8 +146,6 @@ class AuthService with Store {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:cake_wallet/themes/theme_list.dart';
|
||||
import 'package:cw_core/root_dir.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
@ -247,6 +248,8 @@ class BackupService {
|
|||
final sortBalanceTokensBy = data[PreferencesKey.sortBalanceBy] as int?;
|
||||
final pinNativeTokenAtTop = data[PreferencesKey.pinNativeTokenAtTop] as bool?;
|
||||
final useEtherscan = data[PreferencesKey.useEtherscan] as bool?;
|
||||
final defaultNanoRep = data[PreferencesKey.defaultNanoRep] as String?;
|
||||
final defaultBananoRep = data[PreferencesKey.defaultBananoRep] as String?;
|
||||
final lookupsTwitter = data[PreferencesKey.lookupsTwitter] as bool?;
|
||||
final lookupsMastodon = data[PreferencesKey.lookupsMastodon] as bool?;
|
||||
final lookupsYatService = data[PreferencesKey.lookupsYatService] as bool?;
|
||||
|
@ -255,7 +258,8 @@ class BackupService {
|
|||
final lookupsENS = data[PreferencesKey.lookupsENS] as bool?;
|
||||
final syncAll = data[PreferencesKey.syncAllKey] as bool?;
|
||||
final syncMode = data[PreferencesKey.syncModeKey] as int?;
|
||||
final autoGenerateSubaddressStatus = data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?;
|
||||
final autoGenerateSubaddressStatus =
|
||||
data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?;
|
||||
|
||||
await _sharedPreferences.setString(PreferencesKey.currentWalletName, currentWalletName);
|
||||
|
||||
|
@ -292,9 +296,12 @@ class BackupService {
|
|||
await _sharedPreferences.setInt(
|
||||
PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy);
|
||||
|
||||
if (allowBiometricalAuthentication != null && !Platform.isMacOS && !Platform.isLinux)
|
||||
if (DeviceInfo.instance.isDesktop) {
|
||||
await _sharedPreferences.setBool(PreferencesKey.allowBiometricalAuthenticationKey, false);
|
||||
} else if (allowBiometricalAuthentication != null) {
|
||||
await _sharedPreferences.setBool(
|
||||
PreferencesKey.allowBiometricalAuthenticationKey, allowBiometricalAuthentication);
|
||||
}
|
||||
|
||||
if (currentBitcoinElectrumSererId != null)
|
||||
await _sharedPreferences.setInt(
|
||||
|
@ -310,14 +317,18 @@ class BackupService {
|
|||
if (fiatApiMode != null)
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentFiatApiModeKey, fiatApiMode);
|
||||
if (autoGenerateSubaddressStatus != null)
|
||||
await _sharedPreferences.setInt(PreferencesKey.autoGenerateSubaddressStatusKey,
|
||||
autoGenerateSubaddressStatus);
|
||||
await _sharedPreferences.setInt(
|
||||
PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus);
|
||||
|
||||
if (currentPinLength != null)
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength);
|
||||
|
||||
if (currentTheme != null && DeviceInfo.instance.isMobile)
|
||||
if (currentTheme != null && DeviceInfo.instance.isMobile) {
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme);
|
||||
// enforce dark theme on desktop platforms until the design is ready:
|
||||
} else if (DeviceInfo.instance.isDesktop) {
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw);
|
||||
}
|
||||
|
||||
if (exchangeStatus != null)
|
||||
await _sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, exchangeStatus);
|
||||
|
@ -380,6 +391,13 @@ class BackupService {
|
|||
if (useEtherscan != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan);
|
||||
|
||||
if (defaultNanoRep != null)
|
||||
await _sharedPreferences.setString(PreferencesKey.defaultNanoRep, defaultNanoRep);
|
||||
|
||||
if (defaultBananoRep != null)
|
||||
await _sharedPreferences.setString(PreferencesKey.defaultBananoRep, defaultBananoRep);
|
||||
|
||||
if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
|
||||
if (lookupsTwitter != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.lookupsTwitter, lookupsTwitter);
|
||||
|
||||
|
@ -390,19 +408,17 @@ class BackupService {
|
|||
await _sharedPreferences.setBool(PreferencesKey.lookupsYatService, lookupsYatService);
|
||||
|
||||
if (lookupsUnstoppableDomains != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains);
|
||||
await _sharedPreferences.setBool(
|
||||
PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains);
|
||||
|
||||
if (lookupsOpenAlias != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, lookupsOpenAlias);
|
||||
|
||||
if (lookupsENS != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS);
|
||||
if (lookupsENS != null) await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS);
|
||||
|
||||
if (syncAll != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
|
||||
if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
|
||||
|
||||
if (syncMode != null)
|
||||
await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode);
|
||||
if (syncMode != null) await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode);
|
||||
|
||||
await preferencesFile.delete();
|
||||
}
|
||||
|
@ -507,7 +523,8 @@ class BackupService {
|
|||
_sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey),
|
||||
PreferencesKey.disableBuyKey: _sharedPreferences.getBool(PreferencesKey.disableBuyKey),
|
||||
PreferencesKey.disableSellKey: _sharedPreferences.getBool(PreferencesKey.disableSellKey),
|
||||
PreferencesKey.defaultBuyProvider: _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider),
|
||||
PreferencesKey.defaultBuyProvider:
|
||||
_sharedPreferences.getInt(PreferencesKey.defaultBuyProvider),
|
||||
PreferencesKey.isDarkThemeLegacy:
|
||||
_sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy),
|
||||
PreferencesKey.currentPinLength: _sharedPreferences.getInt(PreferencesKey.currentPinLength),
|
||||
|
@ -549,28 +566,23 @@ class BackupService {
|
|||
_sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets),
|
||||
PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings: _sharedPreferences
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings),
|
||||
PreferencesKey.sortBalanceBy:
|
||||
_sharedPreferences.getInt(PreferencesKey.sortBalanceBy),
|
||||
PreferencesKey.sortBalanceBy: _sharedPreferences.getInt(PreferencesKey.sortBalanceBy),
|
||||
PreferencesKey.pinNativeTokenAtTop:
|
||||
_sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop),
|
||||
PreferencesKey.useEtherscan:
|
||||
_sharedPreferences.getBool(PreferencesKey.useEtherscan),
|
||||
PreferencesKey.lookupsTwitter:
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsTwitter),
|
||||
PreferencesKey.lookupsMastodon:
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsMastodon),
|
||||
PreferencesKey.useEtherscan: _sharedPreferences.getBool(PreferencesKey.useEtherscan),
|
||||
PreferencesKey.defaultNanoRep: _sharedPreferences.getString(PreferencesKey.defaultNanoRep),
|
||||
PreferencesKey.defaultBananoRep:
|
||||
_sharedPreferences.getString(PreferencesKey.defaultBananoRep),
|
||||
PreferencesKey.lookupsTwitter: _sharedPreferences.getBool(PreferencesKey.lookupsTwitter),
|
||||
PreferencesKey.lookupsMastodon: _sharedPreferences.getBool(PreferencesKey.lookupsMastodon),
|
||||
PreferencesKey.lookupsYatService:
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsYatService),
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsYatService),
|
||||
PreferencesKey.lookupsUnstoppableDomains:
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains),
|
||||
PreferencesKey.lookupsOpenAlias:
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias),
|
||||
PreferencesKey.lookupsENS:
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsENS),
|
||||
PreferencesKey.syncModeKey:
|
||||
_sharedPreferences.getInt(PreferencesKey.syncModeKey),
|
||||
PreferencesKey.syncAllKey:
|
||||
_sharedPreferences.getBool(PreferencesKey.syncAllKey),
|
||||
_sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains),
|
||||
PreferencesKey.lookupsOpenAlias: _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias),
|
||||
PreferencesKey.lookupsENS: _sharedPreferences.getBool(PreferencesKey.lookupsENS),
|
||||
PreferencesKey.syncModeKey: _sharedPreferences.getInt(PreferencesKey.syncModeKey),
|
||||
PreferencesKey.syncAllKey: _sharedPreferences.getBool(PreferencesKey.syncAllKey),
|
||||
PreferencesKey.autoGenerateSubaddressStatusKey:
|
||||
_sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey),
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -16,6 +17,7 @@ class WalletCreationService {
|
|||
{required WalletType initialType,
|
||||
required this.keyService,
|
||||
required this.sharedPreferences,
|
||||
required this.settingsStore,
|
||||
required this.walletInfoSource})
|
||||
: type = initialType {
|
||||
changeWalletType(type: type);
|
||||
|
@ -23,6 +25,7 @@ class WalletCreationService {
|
|||
|
||||
WalletType type;
|
||||
final SharedPreferences sharedPreferences;
|
||||
final SettingsStore settingsStore;
|
||||
final KeyService keyService;
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
WalletService? _service;
|
||||
|
@ -58,6 +61,10 @@ class WalletCreationService {
|
|||
password: credentials.password!, walletName: credentials.name);
|
||||
}
|
||||
|
||||
if (type == WalletType.bitcoinCash || type == WalletType.ethereum) {
|
||||
credentials.seedPhraseLength = settingsStore.seedPhraseLength.value;
|
||||
}
|
||||
|
||||
final wallet = await _service!.create(credentials);
|
||||
|
||||
if (wallet.type == WalletType.monero) {
|
||||
|
|
27
lib/di.dart
27
lib/di.dart
|
@ -55,6 +55,7 @@ import 'package:cake_wallet/themes/theme_list.dart';
|
|||
import 'package:cake_wallet/utils/payment_request.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
||||
|
@ -103,6 +104,7 @@ import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
|
|||
import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
|
||||
|
@ -345,6 +347,7 @@ Future<void> setup({
|
|||
initialType: type,
|
||||
keyService: getIt.get<KeyService>(),
|
||||
sharedPreferences: getIt.get<SharedPreferences>(),
|
||||
settingsStore: getIt.get<SettingsStore>(),
|
||||
walletInfoSource: _walletInfoSource));
|
||||
|
||||
getIt.registerFactory<WalletLoadingService>(() => WalletLoadingService(
|
||||
|
@ -352,9 +355,10 @@ Future<void> setup({
|
|||
getIt.get<KeyService>(),
|
||||
(WalletType type) => getIt.get<WalletService>(param1: type)));
|
||||
|
||||
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) => WalletNewVM(
|
||||
getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||
type: type));
|
||||
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) =>
|
||||
WalletNewVM(getIt.get<AppStore>(),
|
||||
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||
type: type));
|
||||
|
||||
getIt.registerFactoryParam<WalletRestorationFromQRVM, WalletType, void>((WalletType type, _) {
|
||||
return WalletRestorationFromQRVM(getIt.get<AppStore>(),
|
||||
|
@ -532,8 +536,7 @@ Future<void> setup({
|
|||
getIt.registerFactory<Modify2FAPage>(
|
||||
() => Modify2FAPage(setup2FAViewModel: getIt.get<Setup2FAViewModel>()));
|
||||
|
||||
getIt.registerFactory<DesktopSettingsPage>(
|
||||
() => DesktopSettingsPage());
|
||||
getIt.registerFactory<DesktopSettingsPage>(() => DesktopSettingsPage());
|
||||
|
||||
getIt.registerFactoryParam<ReceiveOptionViewModel, ReceivePageOption?, void>(
|
||||
(pageOption, _) => ReceiveOptionViewModel(getIt.get<AppStore>().wallet!, pageOption));
|
||||
|
@ -713,6 +716,8 @@ Future<void> setup({
|
|||
return PrivacySettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!);
|
||||
});
|
||||
|
||||
getIt.registerFactory(() => TrocadorProvidersViewModel(getIt.get<SettingsStore>()));
|
||||
|
||||
getIt.registerFactory(() {
|
||||
return OtherSettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!);
|
||||
});
|
||||
|
@ -766,13 +771,18 @@ Future<void> setup({
|
|||
|
||||
getIt.registerFactory(() => PrivacyPage(getIt.get<PrivacySettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => TrocadorProvidersPage(getIt.get<TrocadorProvidersViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => DomainLookupsPage(getIt.get<PrivacySettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => DisplaySettingsPage(getIt.get<DisplaySettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => OtherSettingsPage(getIt.get<OtherSettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => NanoChangeRepPage(getIt.get<AppStore>().wallet!));
|
||||
getIt.registerFactory(() => NanoChangeRepPage(
|
||||
settingsStore: getIt.get<AppStore>().settingsStore,
|
||||
wallet: getIt.get<AppStore>().wallet!,
|
||||
));
|
||||
|
||||
getIt.registerFactoryParam<NodeCreateOrEditViewModel, WalletType?, bool?>(
|
||||
(WalletType? type, bool? isPow) => NodeCreateOrEditViewModel(
|
||||
|
@ -907,8 +917,9 @@ Future<void> setup({
|
|||
getIt.registerFactoryParam<NewWalletTypePage, void Function(BuildContext, WalletType), bool?>(
|
||||
(param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true));
|
||||
|
||||
getIt.registerFactoryParam<PreSeedPage, WalletType, void>(
|
||||
(WalletType type, _) => PreSeedPage(type));
|
||||
getIt.registerFactoryParam<PreSeedPage, WalletType, AdvancedPrivacySettingsViewModel>(
|
||||
(WalletType type, AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel)
|
||||
=> PreSeedPage(type, advancedPrivacySettingsViewModel));
|
||||
|
||||
getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>((trade, _) =>
|
||||
TradeDetailsViewModel(
|
||||
|
|
|
@ -2,18 +2,18 @@ import 'package:encrypt/encrypt.dart';
|
|||
// import 'package:password/password.dart';
|
||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
|
||||
String encrypt({required String source, required String key, int keyLength = 16}) {
|
||||
String encrypt({required String source, required String key}) {
|
||||
final _key = Key.fromUtf8(key);
|
||||
final iv = IV.fromLength(keyLength);
|
||||
final iv = IV.allZerosOfLength(16);
|
||||
final encrypter = Encrypter(AES(_key));
|
||||
final encrypted = encrypter.encrypt(source, iv: iv);
|
||||
|
||||
return encrypted.base64;
|
||||
}
|
||||
|
||||
String decrypt({required String source, required String key, int keyLength = 16}) {
|
||||
String decrypt({required String source, required String key}) {
|
||||
final _key = Key.fromUtf8(key);
|
||||
final iv = IV.fromLength(keyLength);
|
||||
final iv = IV.allZerosOfLength(16);
|
||||
final encrypter = Encrypter(AES(_key));
|
||||
final decrypted = encrypter.decrypt64(source, iv: iv);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class MainActions {
|
|||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
case WalletType.ethereum:
|
||||
// case WalletType.bitcoinCash: // TODO: add sign message function to BCH first
|
||||
case WalletType.bitcoinCash:
|
||||
switch (defaultBuyProvider) {
|
||||
case BuyProviderType.AskEachTime:
|
||||
Navigator.pushNamed(context, Routes.buy);
|
||||
|
|
|
@ -50,6 +50,8 @@ class PreferencesKey {
|
|||
static const sortBalanceBy = 'sort_balance_by';
|
||||
static const pinNativeTokenAtTop = 'pin_native_token_at_top';
|
||||
static const useEtherscan = 'use_etherscan';
|
||||
static const defaultNanoRep = 'default_nano_representative';
|
||||
static const defaultBananoRep = 'default_banano_representative';
|
||||
static const lookupsTwitter = 'looks_up_twitter';
|
||||
static const lookupsMastodon = 'looks_up_mastodon';
|
||||
static const lookupsYatService = 'looks_up_mastodon';
|
||||
|
@ -87,4 +89,5 @@ class PreferencesKey {
|
|||
'should_require_totp_2fa_for_all_security_and_backup_settings';
|
||||
static const selectedCake2FAPreset = 'selected_cake_2fa_preset';
|
||||
static const totpSecretKey = 'totp_secret_key';
|
||||
static const currentSeedPhraseLength = 'current_seed_phrase_length';
|
||||
}
|
||||
|
|
26
lib/entities/seed_phrase_length.dart
Normal file
26
lib/entities/seed_phrase_length.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
enum SeedPhraseLength {
|
||||
twelveWords(12),
|
||||
twentyFourWords(24);
|
||||
|
||||
const SeedPhraseLength(this.value);
|
||||
final int value;
|
||||
|
||||
static SeedPhraseLength deserialize({required int raw}) =>
|
||||
SeedPhraseLength.values.firstWhere((e) => e.value == raw);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
String label = '';
|
||||
switch (this) {
|
||||
case SeedPhraseLength.twelveWords:
|
||||
label = '12 Words';
|
||||
break;
|
||||
case SeedPhraseLength.twentyFourWords:
|
||||
label = '24 Words';
|
||||
break;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
|
@ -12,11 +12,27 @@ import 'package:cw_core/crypto_currency.dart';
|
|||
import 'package:http/http.dart';
|
||||
|
||||
class TrocadorExchangeProvider extends ExchangeProvider {
|
||||
TrocadorExchangeProvider({this.useTorOnly = false})
|
||||
: _lastUsedRateId = '',
|
||||
TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}})
|
||||
: _lastUsedRateId = '', _provider = [],
|
||||
super(pairList: supportedPairs(_notSupported));
|
||||
|
||||
bool useTorOnly;
|
||||
final Map<String, bool> providerStates;
|
||||
|
||||
static const List<String> availableProviders = [
|
||||
'Swapter',
|
||||
'StealthEx',
|
||||
'Simpleswap',
|
||||
'Swapuz'
|
||||
'ChangeNow',
|
||||
'Changehero',
|
||||
'FixedFloat',
|
||||
'LetsExchange',
|
||||
'Exolix',
|
||||
'Godex',
|
||||
'Exch',
|
||||
'CoinCraddle'
|
||||
];
|
||||
|
||||
static const List<CryptoCurrency> _notSupported = [
|
||||
CryptoCurrency.stx,
|
||||
|
@ -33,6 +49,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
|||
static const coinPath = 'api/coin';
|
||||
|
||||
String _lastUsedRateId;
|
||||
List<dynamic> _provider;
|
||||
|
||||
@override
|
||||
String get title => 'Trocador';
|
||||
|
@ -105,7 +122,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
|||
'payment': isFixedRateMode ? 'True' : 'False',
|
||||
'min_kycrating': 'C',
|
||||
'markup': markup,
|
||||
'best_only': 'True',
|
||||
};
|
||||
|
||||
final uri = await _getUri(newRatePath, params);
|
||||
|
@ -115,6 +131,9 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
|||
final toAmount = double.parse(responseJSON['amount_to'].toString());
|
||||
final rateId = responseJSON['trade_id'] as String? ?? '';
|
||||
|
||||
var quotes = responseJSON['quotes']['quotes'] as List;
|
||||
_provider = quotes.map((quote) => quote['provider']).toList();
|
||||
|
||||
if (rateId.isNotEmpty) _lastUsedRateId = rateId;
|
||||
|
||||
return isReceiveAmount ? (amount / fromAmount) : (toAmount / amount);
|
||||
|
@ -126,6 +145,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
|||
|
||||
@override
|
||||
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
|
||||
|
||||
final params = {
|
||||
'api_key': apiKey,
|
||||
'ticker_from': _normalizeCurrency(request.fromCurrency),
|
||||
|
@ -135,7 +155,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
|||
'payment': isFixedRateMode ? 'True' : 'False',
|
||||
'min_kycrating': 'C',
|
||||
'markup': markup,
|
||||
'best_only': 'True',
|
||||
if (!isFixedRateMode) 'amount_from': request.fromAmount,
|
||||
if (isFixedRateMode) 'amount_to': request.toAmount,
|
||||
'address': request.toAddress,
|
||||
|
@ -153,6 +172,22 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
|||
params['id'] = _lastUsedRateId;
|
||||
}
|
||||
|
||||
|
||||
String firstAvailableProvider = '';
|
||||
|
||||
for (var provider in _provider) {
|
||||
if (providerStates.containsKey(provider) && providerStates[provider] == true) {
|
||||
firstAvailableProvider = provider as String;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstAvailableProvider.isEmpty) {
|
||||
throw Exception('No available provider is enabled');
|
||||
}
|
||||
|
||||
params['provider'] = firstAvailableProvider;
|
||||
|
||||
final uri = await _getUri(createTradePath, params);
|
||||
final response = await get(uri);
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
|||
import 'package:cake_wallet/ionia/ionia_api.dart';
|
||||
import 'package:cake_wallet/ionia/ionia_gift_card.dart';
|
||||
import 'package:cake_wallet/ionia/ionia_category.dart';
|
||||
// import 'package:platform_device_id/platform_device_id.dart';
|
||||
|
||||
class IoniaService {
|
||||
IoniaService(this.secureStorage, this.ioniaApi);
|
||||
|
|
|
@ -321,10 +321,7 @@ class CWMonero extends Monero {
|
|||
@override
|
||||
List<Unspent> getUnspents(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.unspentCoins
|
||||
.map((MoneroUnspent moneroUnspent) => Unspent(moneroUnspent.address, moneroUnspent.hash,
|
||||
moneroUnspent.value, 0, moneroUnspent.keyImage))
|
||||
.toList();
|
||||
return moneroWallet.unspentCoins;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -166,7 +166,10 @@ class CWNano extends Nano {
|
|||
|
||||
@override
|
||||
Future<void> changeRep(Object wallet, String address) async {
|
||||
return (wallet as NanoWallet).changeRep(address);
|
||||
if ((wallet as NanoWallet).transactionHistory.transactions.isEmpty) {
|
||||
throw Exception("Can't change representative without an existing transaction history");
|
||||
}
|
||||
return wallet.changeRep(address);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
|||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/update_haven_rate.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
|
|
|
@ -42,6 +42,7 @@ import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart';
|
|||
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
|
||||
import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
||||
|
@ -354,6 +355,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<PrivacyPage>());
|
||||
|
||||
case Routes.trocadorProvidersPage:
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<TrocadorProvidersPage>());
|
||||
|
||||
case Routes.domainLookupsPage:
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<DomainLookupsPage>());
|
||||
|
@ -455,7 +460,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
|
||||
case Routes.preSeed:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => getIt.get<PreSeedPage>(param1: settings.arguments as WalletType));
|
||||
builder: (_) => getIt.get<PreSeedPage>(
|
||||
param1: settings.arguments as WalletType,
|
||||
param2: getIt.get<AdvancedPrivacySettingsViewModel>(
|
||||
param1: settings.arguments as WalletType)));
|
||||
|
||||
case Routes.backup:
|
||||
return CupertinoPageRoute<void>(
|
||||
|
|
|
@ -81,6 +81,7 @@ class Routes {
|
|||
static const connectionSync = '/connection_sync_page';
|
||||
static const securityBackupPage = '/security_and_backup_page';
|
||||
static const privacyPage = '/privacy_page';
|
||||
static const trocadorProvidersPage = '/trocador_providers_page';
|
||||
static const domainLookupsPage = '/domain_lookups_page';
|
||||
static const displaySettingsPage = '/display_settings_page';
|
||||
static const otherSettingsPage = '/other_settings_page';
|
||||
|
|
|
@ -17,7 +17,6 @@ import 'package:file_picker/file_picker.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
class BackupPage extends BasePage {
|
||||
BackupPage(this.backupViewModelBase);
|
||||
|
@ -129,15 +128,8 @@ class BackupPage extends BasePage {
|
|||
alertTitle: S.of(context).export_backup,
|
||||
alertContent: S.of(context).select_destination,
|
||||
rightButtonText: S.of(context).save_to_downloads,
|
||||
leftButtonText:S.of(context).share,
|
||||
leftButtonText: S.of(context).share,
|
||||
actionRightButton: () async {
|
||||
final permission = await Permission.storage.request();
|
||||
|
||||
if (permission.isDenied) {
|
||||
Navigator.of(dialogContext).pop();
|
||||
return;
|
||||
}
|
||||
|
||||
await backupViewModelBase.saveToDownload(backup.name, backup.content);
|
||||
Navigator.of(dialogContext).pop();
|
||||
},
|
||||
|
|
|
@ -34,16 +34,6 @@ class BuyOptionsPage extends BasePage {
|
|||
constraints: BoxConstraints(maxWidth: 330),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconRobinhood,
|
||||
title: "Robinhood Connect",
|
||||
description: S.of(context).robinhood_option_description,
|
||||
onPressed: () async =>
|
||||
await getIt.get<RobinhoodBuyProvider>().launchProvider(context),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
|
@ -54,6 +44,16 @@ class BuyOptionsPage extends BasePage {
|
|||
await getIt.get<OnRamperBuyProvider>().launchProvider(context),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconRobinhood,
|
||||
title: "Robinhood Connect",
|
||||
description: S.of(context).robinhood_option_description,
|
||||
onPressed: () async =>
|
||||
await getIt.get<RobinhoodBuyProvider>().launchProvider(context),
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||
|
|
|
@ -165,7 +165,9 @@ class BalancePage extends StatelessWidget {
|
|||
children: [
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: hasAdditionalBalance ? () => _showBalanceDescription(context) : null,
|
||||
onTap: hasAdditionalBalance ? () =>
|
||||
_showBalanceDescription(context, S.current.available_balance_description)
|
||||
: null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
@ -225,47 +227,65 @@ class BalancePage extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
if (frozenBalance.isNotEmpty)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 26),
|
||||
Text(
|
||||
S.current.frozen_balance,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
|
||||
height: 1,
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: hasAdditionalBalance ?
|
||||
() => _showBalanceDescription(context, S.current.unavailable_balance_description)
|
||||
: null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 26),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
S.current.unavailable_balance,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Icon(Icons.help_outline,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
AutoSizeText(
|
||||
frozenBalance,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
|
||||
height: 1,
|
||||
SizedBox(height: 8),
|
||||
AutoSizeText(
|
||||
frozenBalance,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
|
||||
height: 1,
|
||||
),
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
frozenFiatBalance,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
|
||||
height: 1,
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
frozenFiatBalance,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
if (hasAdditionalBalance)
|
||||
Column(
|
||||
|
@ -316,9 +336,9 @@ class BalancePage extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
void _showBalanceDescription(BuildContext context) {
|
||||
void _showBalanceDescription(BuildContext context, String content) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => InformationPage(information: S.current.available_balance_description));
|
||||
builder: (_) => InformationPage(information: content));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class MoneroAccountListPage extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double itemHeight = 80;
|
||||
double itemHeight = 65;
|
||||
double buttonHeight = 62;
|
||||
|
||||
return Observer(builder: (_) {
|
||||
|
@ -31,7 +31,7 @@ class MoneroAccountListPage extends StatelessWidget {
|
|||
child: ListView.separated(
|
||||
padding: EdgeInsets.zero,
|
||||
controller: controller,
|
||||
separatorBuilder: (context, index) => const VerticalSectionDivider(),
|
||||
separatorBuilder: (context, index) => const HorizontalSectionDivider(),
|
||||
itemCount: accounts.length,
|
||||
itemBuilder: (context, index) {
|
||||
final account = accounts[index];
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:cake_wallet/themes/extensions/account_list_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
@ -33,7 +32,7 @@ class AccountTile extends StatelessWidget {
|
|||
final Widget cell = GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
height: 77,
|
||||
height: 60,
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
color: color,
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import 'package:cake_wallet/core/address_validator.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/src/widgets/address_text_field.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/themes/extensions/address_theme.dart';
|
||||
import 'package:cake_wallet/utils/payment_request.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
|
@ -14,21 +17,28 @@ import 'package:cake_wallet/src/screens/base_page.dart';
|
|||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
|
||||
class NanoChangeRepPage extends BasePage {
|
||||
NanoChangeRepPage(WalletBase wallet)
|
||||
NanoChangeRepPage({required SettingsStore settingsStore, required WalletBase wallet})
|
||||
: _wallet = wallet,
|
||||
_addressController = TextEditingController() {
|
||||
_settingsStore = settingsStore,
|
||||
_addressController = TextEditingController(),
|
||||
_formKey = GlobalKey<FormState>() {
|
||||
_addressController.text = nano!.getRepresentative(wallet);
|
||||
}
|
||||
|
||||
final TextEditingController _addressController;
|
||||
final WalletBase _wallet;
|
||||
final SettingsStore _settingsStore;
|
||||
|
||||
final GlobalKey<FormState> _formKey;
|
||||
|
||||
@override
|
||||
String get title => S.current.change_rep;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Container(
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(bottom: 24.0),
|
||||
|
@ -38,9 +48,17 @@ class NanoChangeRepPage extends BasePage {
|
|||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: BaseTextFormField(
|
||||
child: AddressTextField(
|
||||
controller: _addressController,
|
||||
hintText: S.of(context).node_address,
|
||||
onURIScanned: (uri) {
|
||||
final paymentRequest = PaymentRequest.fromUri(uri);
|
||||
_addressController.text = paymentRequest.address;
|
||||
},
|
||||
options: [
|
||||
AddressTextFieldOption.paste,
|
||||
AddressTextFieldOption.qrCode,
|
||||
],
|
||||
buttonColor: Theme.of(context).extension<AddressTheme>()!.actionButtonColor,
|
||||
validator: AddressValidator(type: CryptoCurrency.nano),
|
||||
),
|
||||
)
|
||||
|
@ -59,6 +77,11 @@ class NanoChangeRepPage extends BasePage {
|
|||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: LoadingPrimaryButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState != null &&
|
||||
!_formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final confirmed = await showPopUp<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
|
@ -74,8 +97,19 @@ class NanoChangeRepPage extends BasePage {
|
|||
|
||||
if (confirmed) {
|
||||
try {
|
||||
_settingsStore.defaultNanoRep = _addressController.text;
|
||||
|
||||
await nano!.changeRep(_wallet, _addressController.text);
|
||||
Navigator.of(context).pop();
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).successful,
|
||||
alertContent: S.of(context).change_rep_successful,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.pop(context));
|
||||
});
|
||||
} catch (e) {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
|
@ -97,6 +131,8 @@ class NanoChangeRepPage extends BasePage {
|
|||
)),
|
||||
],
|
||||
)),
|
||||
));
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.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/themes/extensions/new_wallet_theme.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||
|
@ -94,6 +96,17 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
|
|||
],
|
||||
);
|
||||
}),
|
||||
if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption)
|
||||
Observer(builder: (_) {
|
||||
return SettingsPickerCell<SeedPhraseLength>(
|
||||
title: S.current.seed_phrase_length,
|
||||
items: SeedPhraseLength.values,
|
||||
selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
|
||||
onItemSelected: (SeedPhraseLength length) {
|
||||
widget.privacySettingsViewModel.setSeedPhraseLength(length);
|
||||
},
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.all(24),
|
||||
|
|
|
@ -78,7 +78,7 @@ class NodeCreateOrEditPage extends BasePage {
|
|||
'assets/images/qr_code_icon.png',
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
final NodeCreateOrEditViewModel nodeCreateOrEditViewModel;
|
||||
final Node? editingNode;
|
||||
final bool? isSelected;
|
||||
|
@ -133,27 +133,20 @@ class NodeCreateOrEditPage extends BasePage {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: LoadingPrimaryButton(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: LoadingPrimaryButton(
|
||||
onPressed: () async {
|
||||
final confirmed = await showPopUp<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle:
|
||||
S.of(context).remove_node,
|
||||
alertContent: S
|
||||
.of(context)
|
||||
.remove_node_message,
|
||||
rightButtonText:
|
||||
S.of(context).remove,
|
||||
leftButtonText:
|
||||
S.of(context).cancel,
|
||||
actionRightButton: () =>
|
||||
Navigator.pop(context, true),
|
||||
actionLeftButton: () =>
|
||||
Navigator.pop(context, false));
|
||||
alertTitle: S.of(context).remove_node,
|
||||
alertContent: S.of(context).remove_node_message,
|
||||
rightButtonText: S.of(context).remove,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionRightButton: () => Navigator.pop(context, true),
|
||||
actionLeftButton: () => Navigator.pop(context, false));
|
||||
}) ??
|
||||
false;
|
||||
|
||||
|
@ -163,11 +156,14 @@ class NodeCreateOrEditPage extends BasePage {
|
|||
}
|
||||
},
|
||||
text: S.of(context).delete,
|
||||
isDisabled: !nodeCreateOrEditViewModel.isReady ||
|
||||
isDisabled: editingNode == null ||
|
||||
!nodeCreateOrEditViewModel.isReady ||
|
||||
(isSelected ?? false),
|
||||
color: Palette.red,
|
||||
textColor: Colors.white),
|
||||
)),
|
||||
textColor: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 8.0),
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
|||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/view_model/restore_from_backup_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
|
@ -31,10 +30,11 @@ class RestoreFromBackupPage extends BasePage {
|
|||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop(),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -44,42 +44,97 @@ class RestoreFromBackupPage extends BasePage {
|
|||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: 24, left: 24, right: 24),
|
||||
child: Column(children: [
|
||||
padding: EdgeInsets.only(bottom: 24, left: 24, right: 24),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: Center(
|
||||
child: TextFormField(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFormField(
|
||||
obscureText: true,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
hintText: S.of(context).enter_backup_password),
|
||||
decoration:
|
||||
InputDecoration(hintText: S.of(context).enter_backup_password),
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
controller: textEditingController,
|
||||
style: TextStyle(fontSize: 26, color: Colors.black))),
|
||||
style: TextStyle(fontSize: 26, color: Colors.black),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) {
|
||||
if (restoreFromBackupViewModel.filePath.isNotEmpty) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 100),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"File Name: ",
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Lato',
|
||||
color: titleColor(context),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
restoreFromBackupViewModel.filePath.split("/").last,
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Lato',
|
||||
color: titleColor(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Row(children: [
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () => presentFilePicker(),
|
||||
text: S.of(context).select_backup_file,
|
||||
color: Colors.grey,
|
||||
textColor: Colors.white)),
|
||||
SizedBox(width: 20),
|
||||
Expanded(child: Observer(builder: (_) {
|
||||
return LoadingPrimaryButton(
|
||||
isLoading:
|
||||
restoreFromBackupViewModel.state is IsExecutingState,
|
||||
onPressed: () => onImportHandler(context),
|
||||
text: S.of(context).import,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white);
|
||||
}))
|
||||
])),
|
||||
])),
|
||||
textColor: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return LoadingPrimaryButton(
|
||||
isLoading: restoreFromBackupViewModel.state is IsExecutingState,
|
||||
onPressed: () => onImportHandler(context),
|
||||
text: S.of(context).import,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -87,7 +142,7 @@ class RestoreFromBackupPage extends BasePage {
|
|||
Future<void> presentFilePicker() async {
|
||||
final result = await FilePicker.platform.pickFiles();
|
||||
|
||||
if (result?.files?.isEmpty ?? true) {
|
||||
if (result?.files.isEmpty ?? true) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -95,8 +150,7 @@ class RestoreFromBackupPage extends BasePage {
|
|||
}
|
||||
|
||||
Future<void> onImportHandler(BuildContext context) async {
|
||||
if (textEditingController.text.isEmpty ||
|
||||
(restoreFromBackupViewModel.filePath.isEmpty ?? true)) {
|
||||
if (textEditingController.text.isEmpty || (restoreFromBackupViewModel.filePath.isEmpty)) {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
|
|
|
@ -21,7 +21,6 @@ class RestoreOptionsPage extends BasePage {
|
|||
@override
|
||||
String get title => S.current.restore_restore_wallet;
|
||||
|
||||
|
||||
final bool isNewInstall;
|
||||
final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png');
|
||||
final imageBackup = Image.asset('assets/images/backup.png');
|
||||
|
@ -38,8 +37,7 @@ class RestoreOptionsPage extends BasePage {
|
|||
child: Column(
|
||||
children: <Widget>[
|
||||
OptionTile(
|
||||
onPressed: () => Navigator.pushNamed(
|
||||
context, Routes.restoreWalletFromSeedKeys,
|
||||
onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys,
|
||||
arguments: isNewInstall),
|
||||
image: imageSeedKeys,
|
||||
title: S.of(context).restore_title_from_seed_keys,
|
||||
|
@ -58,7 +56,7 @@ class RestoreOptionsPage extends BasePage {
|
|||
child: OptionTile(
|
||||
onPressed: () async {
|
||||
bool isCameraPermissionGranted =
|
||||
await PermissionHandler.checkPermission(Permission.camera, context);
|
||||
await PermissionHandler.checkPermission(Permission.camera, context);
|
||||
if (!isCameraPermissionGranted) return;
|
||||
bool isPinSet = false;
|
||||
if (isNewInstall) {
|
||||
|
@ -73,7 +71,8 @@ class RestoreOptionsPage extends BasePage {
|
|||
final restoreWallet =
|
||||
await WalletRestoreFromQRCode.scanQRCodeForRestoring(context);
|
||||
|
||||
final restoreFromQRViewModel = getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
|
||||
final restoreFromQRViewModel =
|
||||
getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
|
||||
|
||||
await restoreFromQRViewModel.create(restoreWallet: restoreWallet);
|
||||
if (restoreFromQRViewModel.state is FailureState) {
|
||||
|
|
|
@ -204,23 +204,35 @@ class WalletRestorePage extends BasePage {
|
|||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20, bottom: 24, left: 24, right: 24),
|
||||
child: Observer(
|
||||
builder: (context) {
|
||||
return LoadingPrimaryButton(
|
||||
onPressed: () async {
|
||||
await _confirmForm(context);
|
||||
child: Column(
|
||||
children: [
|
||||
Observer(
|
||||
builder: (context) {
|
||||
return LoadingPrimaryButton(
|
||||
onPressed: () async {
|
||||
await _confirmForm(context);
|
||||
},
|
||||
text: S.of(context).restore_recover,
|
||||
color: Theme.of(context)
|
||||
.extension<WalletListTheme>()!
|
||||
.createNewWalletButtonBackgroundColor,
|
||||
textColor: Theme.of(context)
|
||||
.extension<WalletListTheme>()!
|
||||
.restoreWalletButtonTextColor,
|
||||
isLoading: walletRestoreViewModel.state is IsExecutingState,
|
||||
isDisabled: !walletRestoreViewModel.isButtonEnabled,
|
||||
);
|
||||
},
|
||||
text: S.of(context).restore_recover,
|
||||
color: Theme.of(context)
|
||||
.extension<WalletListTheme>()!
|
||||
.createNewWalletButtonBackgroundColor,
|
||||
textColor: Theme.of(context)
|
||||
.extension<WalletListTheme>()!
|
||||
.restoreWalletButtonTextColor,
|
||||
isLoading: walletRestoreViewModel.state is IsExecutingState,
|
||||
isDisabled: !walletRestoreViewModel.isButtonEnabled,
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.advancedPrivacySettings, arguments: walletRestoreViewModel.type);
|
||||
},
|
||||
child: Text(S.of(context).advanced_privacy_settings),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
|
@ -9,15 +10,19 @@ import 'package:cake_wallet/themes/theme_base.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class PreSeedPage extends BasePage {
|
||||
PreSeedPage(this.type)
|
||||
PreSeedPage(this.type, this.advancedPrivacySettingsViewModel)
|
||||
: imageLight = Image.asset('assets/images/pre_seed_light.png'),
|
||||
imageDark = Image.asset('assets/images/pre_seed_dark.png'),
|
||||
wordsCount = _wordsCount(type);
|
||||
seedPhraseLength = advancedPrivacySettingsViewModel.seedPhraseLength.value {
|
||||
wordsCount = _wordsCount(type, seedPhraseLength);
|
||||
}
|
||||
|
||||
final Image imageDark;
|
||||
final Image imageLight;
|
||||
final WalletType type;
|
||||
final int wordsCount;
|
||||
final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel;
|
||||
final int seedPhraseLength;
|
||||
late final int wordsCount;
|
||||
|
||||
@override
|
||||
Widget? leading(BuildContext context) => null;
|
||||
|
@ -68,13 +73,13 @@ class PreSeedPage extends BasePage {
|
|||
));
|
||||
}
|
||||
|
||||
static int _wordsCount(WalletType type) {
|
||||
static int _wordsCount(WalletType type, int seedPhraseLength) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return 25;
|
||||
case WalletType.ethereum:
|
||||
case WalletType.bitcoinCash:
|
||||
return 12;
|
||||
return seedPhraseLength;
|
||||
default:
|
||||
return 24;
|
||||
}
|
||||
|
|
|
@ -22,77 +22,83 @@ class PrivacyPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Observer(builder: (_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<FiatApiMode>(
|
||||
title: S.current.fiat_api,
|
||||
items: FiatApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.fiatApiMode,
|
||||
onItemSelected: (FiatApiMode fiatApiMode) =>
|
||||
_privacySettingsViewModel.setFiatMode(fiatApiMode),
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Observer(builder: (_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<FiatApiMode>(
|
||||
title: S.current.fiat_api,
|
||||
items: FiatApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.fiatApiMode,
|
||||
onItemSelected: (FiatApiMode fiatApiMode) =>
|
||||
_privacySettingsViewModel.setFiatMode(fiatApiMode),
|
||||
),
|
||||
),
|
||||
),
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<ExchangeApiMode>(
|
||||
title: S.current.exchange,
|
||||
items: ExchangeApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.exchangeStatus,
|
||||
onItemSelected: (ExchangeApiMode mode) =>
|
||||
_privacySettingsViewModel.setExchangeApiMode(mode),
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<ExchangeApiMode>(
|
||||
title: S.current.exchange,
|
||||
items: ExchangeApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.exchangeStatus,
|
||||
onItemSelected: (ExchangeApiMode mode) =>
|
||||
_privacySettingsViewModel.setExchangeApiMode(mode),
|
||||
),
|
||||
),
|
||||
),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.settings_save_recipient_address,
|
||||
value: _privacySettingsViewModel.shouldSaveRecipientAddress,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setShouldSaveRecipientAddress(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.auto_generate_subaddresses,
|
||||
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setAutoGenerateSubaddresses(value);
|
||||
},
|
||||
),
|
||||
if (DeviceInfo.instance.isMobile)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.prevent_screenshots,
|
||||
value: _privacySettingsViewModel.isAppSecure,
|
||||
title: S.current.settings_save_recipient_address,
|
||||
value: _privacySettingsViewModel.shouldSaveRecipientAddress,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setIsAppSecure(value);
|
||||
_privacySettingsViewModel.setShouldSaveRecipientAddress(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_buy,
|
||||
value: _privacySettingsViewModel.disableBuy,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableBuy(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_sell,
|
||||
value: _privacySettingsViewModel.disableSell,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableSell(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.canUseEtherscan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.etherscan_history,
|
||||
value: _privacySettingsViewModel.useEtherscan,
|
||||
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.auto_generate_subaddresses,
|
||||
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseEtherscan(value);
|
||||
_privacySettingsViewModel.setAutoGenerateSubaddresses(value);
|
||||
},
|
||||
),
|
||||
if (DeviceInfo.instance.isMobile)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.prevent_screenshots,
|
||||
value: _privacySettingsViewModel.isAppSecure,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setIsAppSecure(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_buy,
|
||||
value: _privacySettingsViewModel.disableBuy,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableBuy(value);
|
||||
}),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.domain_looks_up,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_sell,
|
||||
value: _privacySettingsViewModel.disableSell,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableSell(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.canUseEtherscan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.etherscan_history,
|
||||
value: _privacySettingsViewModel.useEtherscan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseEtherscan(value);
|
||||
}),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.domain_looks_up,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: 'Trocador providers',
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
37
lib/src/screens/settings/trocador_providers_page.dart
Normal file
37
lib/src/screens/settings/trocador_providers_page.dart
Normal file
|
@ -0,0 +1,37 @@
|
|||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class TrocadorProvidersPage extends BasePage {
|
||||
TrocadorProvidersPage(this.trocadorProvidersViewModel);
|
||||
|
||||
@override
|
||||
String get title => 'Trocador Providers';
|
||||
|
||||
final TrocadorProvidersViewModel trocadorProvidersViewModel;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final availableProviders = TrocadorExchangeProvider.availableProviders;
|
||||
final providerStates = trocadorProvidersViewModel.providerStates;
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: ListView.builder(
|
||||
itemCount: availableProviders.length,
|
||||
itemBuilder: (_, index) {
|
||||
String provider = availableProviders[index];
|
||||
return Observer(
|
||||
builder: (_) => SettingsSwitcherCell(
|
||||
title: provider,
|
||||
value: providerStates[provider] ?? false,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
trocadorProvidersViewModel.toggleProviderState(provider);
|
||||
}));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,13 @@
|
|||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
class UnspentCoinsListPage extends BasePage {
|
||||
UnspentCoinsListPage({required this.unspentCoinsListViewModel});
|
||||
|
@ -17,31 +15,10 @@ class UnspentCoinsListPage extends BasePage {
|
|||
@override
|
||||
String get title => S.current.unspent_coins_title;
|
||||
|
||||
//@override
|
||||
//Widget trailing(BuildContext context) {
|
||||
// final questionImage = Image.asset('assets/images/question_mark.png',
|
||||
// color: Theme.of(context).extension<CakeTextTheme>()!.titleColor);
|
||||
|
||||
// return SizedBox(
|
||||
// height: 20.0,
|
||||
// width: 20.0,
|
||||
// child: ButtonTheme(
|
||||
// minWidth: double.minPositive,
|
||||
// child: FlatButton(
|
||||
// highlightColor: Colors.transparent,
|
||||
// splashColor: Colors.transparent,
|
||||
// padding: EdgeInsets.all(0),
|
||||
// onPressed: () => showUnspentCoinsAlert(context),
|
||||
// child: questionImage),
|
||||
// ),
|
||||
// );
|
||||
//}
|
||||
|
||||
final UnspentCoinsListViewModel unspentCoinsListViewModel;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) =>
|
||||
UnspentCoinsListForm(unspentCoinsListViewModel);
|
||||
Widget body(BuildContext context) => UnspentCoinsListForm(unspentCoinsListViewModel);
|
||||
}
|
||||
|
||||
class UnspentCoinsListForm extends StatefulWidget {
|
||||
|
@ -50,8 +27,7 @@ class UnspentCoinsListForm extends StatefulWidget {
|
|||
final UnspentCoinsListViewModel unspentCoinsListViewModel;
|
||||
|
||||
@override
|
||||
UnspentCoinsListFormState createState() =>
|
||||
UnspentCoinsListFormState(unspentCoinsListViewModel);
|
||||
UnspentCoinsListFormState createState() => UnspentCoinsListFormState(unspentCoinsListViewModel);
|
||||
}
|
||||
|
||||
class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
|
||||
|
@ -59,16 +35,6 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
|
|||
|
||||
final UnspentCoinsListViewModel unspentCoinsListViewModel;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
|
||||
}
|
||||
|
||||
void afterLayout(dynamic _) {
|
||||
//showUnspentCoinsAlert(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
|
@ -76,8 +42,7 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
|
|||
child: Observer(
|
||||
builder: (_) => ListView.separated(
|
||||
itemCount: unspentCoinsListViewModel.items.length,
|
||||
separatorBuilder: (_, __) =>
|
||||
SizedBox(height: 15),
|
||||
separatorBuilder: (_, __) => SizedBox(height: 15),
|
||||
itemBuilder: (_, int index) {
|
||||
return Observer(builder: (_) {
|
||||
final item = unspentCoinsListViewModel.items[index];
|
||||
|
@ -86,38 +51,22 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
|
|||
: item.address;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () =>
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.unspentCoinsDetails,
|
||||
arguments: [item, unspentCoinsListViewModel]),
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsDetails,
|
||||
arguments: [item, unspentCoinsListViewModel]),
|
||||
child: UnspentCoinsListItem(
|
||||
note: item.note,
|
||||
amount: item.amount,
|
||||
address: address,
|
||||
isSending: item.isSending,
|
||||
isFrozen: item.isFrozen,
|
||||
isChange: item.isChange,
|
||||
onCheckBoxTap: item.isFrozen
|
||||
? null
|
||||
: () async {
|
||||
item.isSending = !item.isSending;
|
||||
await unspentCoinsListViewModel
|
||||
.saveUnspentCoinInfo(item);}));
|
||||
? null
|
||||
: () async {
|
||||
item.isSending = !item.isSending;
|
||||
await unspentCoinsListViewModel.saveUnspentCoinInfo(item);
|
||||
}));
|
||||
});
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
void showUnspentCoinsAlert(BuildContext context) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: '',
|
||||
alertContent: 'Information about unspent coins',
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
});
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
class UnspentCoinsListItem extends StatelessWidget {
|
||||
UnspentCoinsListItem({
|
||||
|
@ -11,6 +11,7 @@ class UnspentCoinsListItem extends StatelessWidget {
|
|||
required this.address,
|
||||
required this.isSending,
|
||||
required this.isFrozen,
|
||||
required this.isChange,
|
||||
this.onCheckBoxTap,
|
||||
});
|
||||
|
||||
|
@ -19,6 +20,7 @@ class UnspentCoinsListItem extends StatelessWidget {
|
|||
final String address;
|
||||
final bool isSending;
|
||||
final bool isFrozen;
|
||||
final bool isChange;
|
||||
final Function()? onCheckBoxTap;
|
||||
|
||||
@override
|
||||
|
@ -27,9 +29,8 @@ class UnspentCoinsListItem extends StatelessWidget {
|
|||
final selectedItemColor = Theme.of(context).primaryColor;
|
||||
final itemColor = isSending ? selectedItemColor : unselectedItemColor;
|
||||
|
||||
final amountColor = isSending
|
||||
? Colors.white
|
||||
: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor;
|
||||
final amountColor =
|
||||
isSending ? Colors.white : Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor;
|
||||
final addressColor = isSending
|
||||
? Colors.white.withOpacity(0.5)
|
||||
: Theme.of(context).extension<CakeTextTheme>()!.buttonSecondaryTextColor;
|
||||
|
@ -47,7 +48,8 @@ class UnspentCoinsListItem extends StatelessWidget {
|
|||
child: StandardCheckbox(
|
||||
iconColor: amountColor,
|
||||
borderColor: addressColor,
|
||||
value: isSending, onChanged: (value) => onCheckBoxTap?.call())),
|
||||
value: isSending,
|
||||
onChanged: (value) => onCheckBoxTap?.call())),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -57,9 +59,7 @@ class UnspentCoinsListItem extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
if (note.isNotEmpty)
|
||||
AutoSizeText(
|
||||
note,
|
||||
|
@ -69,8 +69,8 @@ class UnspentCoinsListItem extends StatelessWidget {
|
|||
),
|
||||
AutoSizeText(
|
||||
amount,
|
||||
style:
|
||||
TextStyle(color: amountColor, fontSize: 15, fontWeight: FontWeight.w600),
|
||||
style: TextStyle(
|
||||
color: amountColor, fontSize: 15, fontWeight: FontWeight.w600),
|
||||
maxLines: 1,
|
||||
)
|
||||
]),
|
||||
|
@ -84,23 +84,41 @@ class UnspentCoinsListItem extends StatelessWidget {
|
|||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
S.of(context).frozen,
|
||||
style:
|
||||
TextStyle(color: amountColor, fontSize: 7, fontWeight: FontWeight.w600),
|
||||
))
|
||||
style: TextStyle(
|
||||
color: amountColor, fontSize: 7, fontWeight: FontWeight.w600),
|
||||
)),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
AutoSizeText(
|
||||
'${address.substring(0, 5)}...${address.substring(address.length-5)}', // ToDo: Maybe use address label
|
||||
'${address.substring(0, 5)}...${address.substring(address.length - 5)}', // ToDo: Maybe use address label
|
||||
style: TextStyle(
|
||||
color: addressColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
maxLines: 1,
|
||||
),
|
||||
if (isChange)
|
||||
Container(
|
||||
height: 17,
|
||||
padding: EdgeInsets.only(left: 6, right: 6),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.5)),
|
||||
color: Colors.white),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
S.of(context).unspent_change,
|
||||
style: TextStyle(
|
||||
color: itemColor,
|
||||
fontSize: 7,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'dart:ui';
|
|||
import 'package:cake_wallet/src/widgets/section_divider.dart';
|
||||
import 'package:cake_wallet/themes/extensions/alert_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
|
||||
class BaseAlertDialog extends StatelessWidget {
|
||||
String get titleText => '';
|
||||
|
@ -49,7 +48,7 @@ class BaseAlertDialog extends StatelessWidget {
|
|||
|
||||
Widget actionButtons(BuildContext context) {
|
||||
return Container(
|
||||
height: 52,
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
|
|
@ -52,7 +52,7 @@ class OptionTile extends StatelessWidget {
|
|||
child: Text(
|
||||
description,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<OptionTileTheme>()!.descriptionColor,
|
||||
),
|
||||
|
|
|
@ -9,7 +9,9 @@ import 'package:cake_wallet/entities/background_tasks.dart';
|
|||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/entities/sort_balance_types.dart';
|
||||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
|
@ -71,6 +73,7 @@ abstract class SettingsStoreBase with Store {
|
|||
required this.isBitcoinBuyEnabled,
|
||||
required this.actionlistDisplayMode,
|
||||
required this.pinTimeOutDuration,
|
||||
required this.seedPhraseLength,
|
||||
required Cake2FAPresetsOptions initialCake2FAPresetOptions,
|
||||
required bool initialShouldRequireTOTP2FAForAccessingWallet,
|
||||
required bool initialShouldRequireTOTP2FAForSendsToContact,
|
||||
|
@ -84,6 +87,8 @@ abstract class SettingsStoreBase with Store {
|
|||
required this.sortBalanceBy,
|
||||
required this.pinNativeTokenAtTop,
|
||||
required this.useEtherscan,
|
||||
required this.defaultNanoRep,
|
||||
required this.defaultBananoRep,
|
||||
required this.lookupsTwitter,
|
||||
required this.lookupsMastodon,
|
||||
required this.lookupsYatService,
|
||||
|
@ -162,6 +167,8 @@ abstract class SettingsStoreBase with Store {
|
|||
priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority;
|
||||
}
|
||||
|
||||
initializeTrocadorProviderStates();
|
||||
|
||||
reaction(
|
||||
(_) => fiatCurrency,
|
||||
(FiatCurrency fiatCurrency) => sharedPreferences.setString(
|
||||
|
@ -327,6 +334,11 @@ abstract class SettingsStoreBase with Store {
|
|||
(String languageCode) =>
|
||||
sharedPreferences.setString(PreferencesKey.currentLanguageCode, languageCode));
|
||||
|
||||
reaction(
|
||||
(_) => seedPhraseLength,
|
||||
(SeedPhraseLength seedPhraseWordCount) =>
|
||||
sharedPreferences.setInt(PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value));
|
||||
|
||||
reaction(
|
||||
(_) => pinTimeOutDuration,
|
||||
(PinCodeRequiredDuration pinCodeInterval) =>
|
||||
|
@ -369,6 +381,13 @@ abstract class SettingsStoreBase with Store {
|
|||
(bool useEtherscan) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan));
|
||||
|
||||
reaction((_) => defaultNanoRep,
|
||||
(String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep));
|
||||
|
||||
reaction(
|
||||
(_) => defaultBananoRep,
|
||||
(String bananoRep) =>
|
||||
_sharedPreferences.setString(PreferencesKey.defaultBananoRep, bananoRep));
|
||||
reaction(
|
||||
(_) => lookupsTwitter,
|
||||
(bool looksUpTwitter) =>
|
||||
|
@ -417,6 +436,7 @@ abstract class SettingsStoreBase with Store {
|
|||
static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes;
|
||||
static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized;
|
||||
static final walletPasswordDirectInput = Platform.isLinux;
|
||||
static const defaultSeedPhraseLength = SeedPhraseLength.twelveWords;
|
||||
|
||||
@observable
|
||||
FiatCurrency fiatCurrency;
|
||||
|
@ -508,6 +528,9 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
PinCodeRequiredDuration pinTimeOutDuration;
|
||||
|
||||
@observable
|
||||
SeedPhraseLength seedPhraseLength;
|
||||
|
||||
@computed
|
||||
ThemeData get theme => currentTheme.themeData;
|
||||
|
||||
|
@ -517,6 +540,9 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
ObservableMap<WalletType, TransactionPriority> priority;
|
||||
|
||||
@observable
|
||||
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
|
||||
|
||||
@observable
|
||||
SortBalanceBy sortBalanceBy;
|
||||
|
||||
|
@ -526,6 +552,12 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
bool useEtherscan;
|
||||
|
||||
@observable
|
||||
String defaultNanoRep;
|
||||
|
||||
@observable
|
||||
String defaultBananoRep;
|
||||
|
||||
@observable
|
||||
bool lookupsTwitter;
|
||||
|
||||
|
@ -603,8 +635,8 @@ abstract class SettingsStoreBase with Store {
|
|||
TransactionPriority? moneroTransactionPriority = monero?.deserializeMoneroTransactionPriority(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!);
|
||||
TransactionPriority? bitcoinTransactionPriority =
|
||||
bitcoin?.deserializeBitcoinTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!);
|
||||
bitcoin?.deserializeBitcoinTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!);
|
||||
|
||||
TransactionPriority? havenTransactionPriority;
|
||||
TransactionPriority? litecoinTransactionPriority;
|
||||
|
@ -643,8 +675,8 @@ abstract class SettingsStoreBase with Store {
|
|||
final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false;
|
||||
final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false;
|
||||
final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false;
|
||||
final defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt(
|
||||
PreferencesKey.defaultBuyProvider) ?? 0];
|
||||
final defaultBuyProvider =
|
||||
BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0];
|
||||
final currentFiatApiMode = FiatApiMode.deserialize(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ??
|
||||
FiatApiMode.enabled.raw);
|
||||
|
@ -663,7 +695,7 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ??
|
||||
false;
|
||||
final shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ??
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ??
|
||||
false;
|
||||
final shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ??
|
||||
|
@ -674,7 +706,7 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ??
|
||||
false;
|
||||
final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ??
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ??
|
||||
false;
|
||||
final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false;
|
||||
final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? '';
|
||||
|
@ -695,14 +727,20 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode));
|
||||
var pinLength = sharedPreferences.getInt(PreferencesKey.currentPinLength);
|
||||
final timeOutDuration = sharedPreferences.getInt(PreferencesKey.pinTimeOutDuration);
|
||||
final seedPhraseCount = sharedPreferences.getInt(PreferencesKey.currentSeedPhraseLength);
|
||||
final pinCodeTimeOutDuration = timeOutDuration != null
|
||||
? PinCodeRequiredDuration.deserialize(raw: timeOutDuration)
|
||||
: defaultPinCodeTimeOutDuration;
|
||||
final seedPhraseWordCount = seedPhraseCount != null
|
||||
? SeedPhraseLength.deserialize(raw: seedPhraseCount)
|
||||
: defaultSeedPhraseLength;
|
||||
final sortBalanceBy =
|
||||
SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0];
|
||||
SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0];
|
||||
final pinNativeTokenAtTop =
|
||||
sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
||||
final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
|
||||
final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
|
||||
final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;
|
||||
final lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true;
|
||||
final lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true;
|
||||
|
@ -719,11 +757,11 @@ abstract class SettingsStoreBase with Store {
|
|||
await LanguageService.localeDetection();
|
||||
final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
|
||||
final bitcoinElectrumServerId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
|
||||
final litecoinElectrumServerId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
|
||||
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
|
||||
final bitcoinCashElectrumServerId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
|
||||
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
|
||||
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
|
@ -740,7 +778,7 @@ abstract class SettingsStoreBase with Store {
|
|||
final deviceName = await _getDeviceName() ?? '';
|
||||
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
|
||||
final generateSubaddresses =
|
||||
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
|
||||
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
|
||||
|
||||
final autoGenerateSubaddressStatus = generateSubaddresses != null
|
||||
? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses)
|
||||
|
@ -781,10 +819,10 @@ abstract class SettingsStoreBase with Store {
|
|||
powNodes[WalletType.nano] = nanoPowNode;
|
||||
}
|
||||
|
||||
final savedSyncMode = SyncMode.all.firstWhere((element) {
|
||||
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1);
|
||||
});
|
||||
final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true;
|
||||
final savedSyncMode = SyncMode.all.firstWhere((element) {
|
||||
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1);
|
||||
});
|
||||
final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true;
|
||||
|
||||
return SettingsStore(
|
||||
sharedPreferences: sharedPreferences,
|
||||
|
@ -813,10 +851,13 @@ abstract class SettingsStoreBase with Store {
|
|||
actionlistDisplayMode: actionListDisplayMode,
|
||||
initialPinLength: pinLength,
|
||||
pinTimeOutDuration: pinCodeTimeOutDuration,
|
||||
seedPhraseLength: seedPhraseWordCount,
|
||||
initialLanguageCode: savedLanguageCode,
|
||||
sortBalanceBy: sortBalanceBy,
|
||||
pinNativeTokenAtTop: pinNativeTokenAtTop,
|
||||
useEtherscan: useEtherscan,
|
||||
defaultNanoRep: defaultNanoRep,
|
||||
defaultBananoRep: defaultBananoRep,
|
||||
lookupsTwitter: lookupsTwitter,
|
||||
lookupsMastodon: lookupsMastodon,
|
||||
lookupsYatService: lookupsYatService,
|
||||
|
@ -855,35 +896,35 @@ abstract class SettingsStoreBase with Store {
|
|||
raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!);
|
||||
|
||||
priority[WalletType.monero] = monero?.deserializeMoneroTransactionPriority(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ??
|
||||
raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ??
|
||||
priority[WalletType.monero]!;
|
||||
priority[WalletType.bitcoin] = bitcoin?.deserializeBitcoinTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ??
|
||||
sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ??
|
||||
priority[WalletType.bitcoin]!;
|
||||
|
||||
if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) {
|
||||
priority[WalletType.haven] = monero?.deserializeMoneroTransactionPriority(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ??
|
||||
raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ??
|
||||
priority[WalletType.haven]!;
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority) != null) {
|
||||
priority[WalletType.litecoin] = bitcoin?.deserializeLitecoinTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ??
|
||||
sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ??
|
||||
priority[WalletType.litecoin]!;
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority) != null) {
|
||||
priority[WalletType.ethereum] = ethereum?.deserializeEthereumTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ??
|
||||
sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ??
|
||||
priority[WalletType.ethereum]!;
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) {
|
||||
priority[WalletType.bitcoinCash] = bitcoinCash?.deserializeBitcoinCashTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ??
|
||||
sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ??
|
||||
priority[WalletType.bitcoinCash]!;
|
||||
}
|
||||
|
||||
final generateSubaddresses =
|
||||
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
|
||||
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
|
||||
|
||||
autoGenerateSubaddressStatus = generateSubaddresses != null
|
||||
? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses)
|
||||
|
@ -902,7 +943,7 @@ abstract class SettingsStoreBase with Store {
|
|||
disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy;
|
||||
disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell;
|
||||
defaultBuyProvider =
|
||||
BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0];
|
||||
BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0];
|
||||
allowBiometricalAuthentication =
|
||||
sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ??
|
||||
allowBiometricalAuthentication;
|
||||
|
@ -919,7 +960,7 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ??
|
||||
false;
|
||||
shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ??
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ??
|
||||
false;
|
||||
shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ??
|
||||
|
@ -930,7 +971,7 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ??
|
||||
false;
|
||||
shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ??
|
||||
.getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ??
|
||||
false;
|
||||
shouldShowMarketPlaceInDashboard =
|
||||
sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ??
|
||||
|
@ -963,6 +1004,8 @@ abstract class SettingsStoreBase with Store {
|
|||
.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index];
|
||||
pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
||||
useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
|
||||
defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
|
||||
lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;
|
||||
lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true;
|
||||
lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true;
|
||||
|
@ -972,11 +1015,11 @@ abstract class SettingsStoreBase with Store {
|
|||
|
||||
final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
|
||||
final bitcoinElectrumServerId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
|
||||
final litecoinElectrumServerId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
|
||||
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
|
||||
final bitcoinCashElectrumServerId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
|
||||
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
|
||||
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
|
@ -1038,7 +1081,8 @@ abstract class SettingsStoreBase with Store {
|
|||
await _sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int);
|
||||
break;
|
||||
case WalletType.bitcoinCash:
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
|
||||
await _sharedPreferences.setInt(
|
||||
PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
|
||||
break;
|
||||
case WalletType.nano:
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int);
|
||||
|
@ -1062,6 +1106,19 @@ abstract class SettingsStoreBase with Store {
|
|||
powNodes[walletType] = node;
|
||||
}
|
||||
|
||||
void initializeTrocadorProviderStates() {
|
||||
for (var provider in TrocadorExchangeProvider.availableProviders) {
|
||||
final savedState = _sharedPreferences.getBool(provider) ?? true;
|
||||
trocadorProviderStates[provider] = savedState;
|
||||
}
|
||||
}
|
||||
|
||||
void saveTrocadorProviderState(String providerName, bool state) {
|
||||
_sharedPreferences.setBool(providerName, state);
|
||||
trocadorProviderStates[providerName] = state;
|
||||
}
|
||||
|
||||
|
||||
static Future<String?> _getDeviceName() async {
|
||||
String? deviceName = '';
|
||||
final deviceInfoPlugin = DeviceInfoPlugin();
|
||||
|
|
|
@ -17,7 +17,9 @@ class PermissionHandler {
|
|||
var status = await permission.status;
|
||||
|
||||
if (status.isDenied) {
|
||||
status = await permission.request();
|
||||
try {
|
||||
status = await permission.request();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
if (status.isPermanentlyDenied || status.isDenied) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -25,9 +26,15 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
|||
|
||||
final SettingsStore _settingsStore;
|
||||
|
||||
bool get hasSeedPhraseLengthOption =>
|
||||
type == WalletType.bitcoinCash || type == WalletType.ethereum;
|
||||
|
||||
@computed
|
||||
bool get addCustomNode => _addCustomNode;
|
||||
|
||||
@computed
|
||||
SeedPhraseLength get seedPhraseLength => _settingsStore.seedPhraseLength;
|
||||
|
||||
@action
|
||||
void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode;
|
||||
|
||||
|
@ -36,4 +43,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
|||
|
||||
@action
|
||||
void toggleAddCustomNode() => _addCustomNode = !_addCustomNode;
|
||||
|
||||
@action
|
||||
void setSeedPhraseLength(SeedPhraseLength length) => _settingsStore.seedPhraseLength = length;
|
||||
}
|
||||
|
|
|
@ -175,10 +175,8 @@ abstract class BalanceViewModelBase with Store {
|
|||
return '---';
|
||||
}
|
||||
|
||||
return _getFiatBalance(
|
||||
price: price,
|
||||
cryptoAmount: getFormattedFrozenBalance(walletBalance)) + ' ' + fiatCurrency.toString();
|
||||
|
||||
return _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(walletBalance)) +
|
||||
' ${fiatCurrency.toString()}';
|
||||
}
|
||||
|
||||
@computed
|
||||
|
@ -201,10 +199,8 @@ abstract class BalanceViewModelBase with Store {
|
|||
return '---';
|
||||
}
|
||||
|
||||
return _getFiatBalance(
|
||||
price: price,
|
||||
cryptoAmount: walletBalance.formattedAvailableBalance) + ' ' + fiatCurrency.toString();
|
||||
|
||||
return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAvailableBalance) +
|
||||
' ${fiatCurrency.toString()}';
|
||||
}
|
||||
|
||||
@computed
|
||||
|
@ -216,10 +212,8 @@ abstract class BalanceViewModelBase with Store {
|
|||
return '---';
|
||||
}
|
||||
|
||||
return _getFiatBalance(
|
||||
price: price,
|
||||
cryptoAmount: walletBalance.formattedAdditionalBalance) + ' ' + fiatCurrency.toString();
|
||||
|
||||
return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAdditionalBalance) +
|
||||
' ${fiatCurrency.toString()}';
|
||||
}
|
||||
|
||||
@computed
|
||||
|
@ -398,6 +392,6 @@ abstract class BalanceViewModelBase with Store {
|
|||
}
|
||||
}
|
||||
|
||||
String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedFrozenBalance;
|
||||
String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedUnAvailableBalance;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
ChangeNowExchangeProvider(settingsStore: _settingsStore),
|
||||
SideShiftExchangeProvider(),
|
||||
SimpleSwapExchangeProvider(),
|
||||
TrocadorExchangeProvider(useTorOnly: _useTorOnly),
|
||||
TrocadorExchangeProvider(useTorOnly: _useTorOnly,
|
||||
providerStates: _settingsStore.trocadorProviderStates),
|
||||
if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(),
|
||||
];
|
||||
|
||||
|
|
21
lib/view_model/settings/trocador_providers_view_model.dart
Normal file
21
lib/view_model/settings/trocador_providers_view_model.dart
Normal file
|
@ -0,0 +1,21 @@
|
|||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'trocador_providers_view_model.g.dart';
|
||||
|
||||
class TrocadorProvidersViewModel = TrocadorProvidersViewModelBase with _$TrocadorProvidersViewModel;
|
||||
|
||||
abstract class TrocadorProvidersViewModelBase with Store {
|
||||
TrocadorProvidersViewModelBase(this._settingsStore);
|
||||
|
||||
final SettingsStore _settingsStore;
|
||||
|
||||
@computed
|
||||
Map<String, bool> get providerStates => _settingsStore.trocadorProviderStates;
|
||||
|
||||
@action
|
||||
void toggleProviderState(String providerName) {
|
||||
final currentState = providerStates[providerName] ?? false;
|
||||
_settingsStore.saveTrocadorProviderState(providerName, !currentState);
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ abstract class UnspentCoinsItemBase with Store {
|
|||
required this.isFrozen,
|
||||
required this.note,
|
||||
required this.isSending,
|
||||
required this.isChange,
|
||||
required this.amountRaw,
|
||||
required this.vout,
|
||||
required this.keyImage
|
||||
|
@ -35,6 +36,9 @@ abstract class UnspentCoinsItemBase with Store {
|
|||
@observable
|
||||
bool isSending;
|
||||
|
||||
@observable
|
||||
bool isChange;
|
||||
|
||||
@observable
|
||||
int amountRaw;
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cw_core/unspent_transaction_output.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/wallet_addresses.dart';
|
||||
import 'package:cw_core/unspent_transaction_output.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
@ -26,66 +24,49 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
|||
|
||||
@computed
|
||||
ObservableList<UnspentCoinsItem> get items => ObservableList.of(_getUnspents().map((elem) {
|
||||
final amount = formatAmountToString(elem.value) + ' ${wallet.currency.title}';
|
||||
|
||||
final info =
|
||||
getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage);
|
||||
|
||||
return UnspentCoinsItem(
|
||||
address: elem.address,
|
||||
amount: amount,
|
||||
amount: '${formatAmountToString(elem.value)} ${wallet.currency.title}',
|
||||
hash: elem.hash,
|
||||
isFrozen: info?.isFrozen ?? false,
|
||||
note: info?.note ?? '',
|
||||
isSending: info?.isSending ?? true,
|
||||
isFrozen: info.isFrozen,
|
||||
note: info.note,
|
||||
isSending: info.isSending,
|
||||
amountRaw: elem.value,
|
||||
vout: elem.vout,
|
||||
keyImage: elem.keyImage);
|
||||
keyImage: elem.keyImage,
|
||||
isChange: elem.isChange,
|
||||
);
|
||||
}));
|
||||
|
||||
Future<void> saveUnspentCoinInfo(UnspentCoinsItem item) async {
|
||||
try {
|
||||
final info =
|
||||
getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout, item.keyImage);
|
||||
if (info == null) {
|
||||
final newInfo = UnspentCoinsInfo(
|
||||
walletId: wallet.id,
|
||||
hash: item.hash,
|
||||
address: item.address,
|
||||
value: item.amountRaw,
|
||||
vout: item.vout,
|
||||
isFrozen: item.isFrozen,
|
||||
isSending: item.isSending,
|
||||
noteRaw: item.note,
|
||||
keyImage: item.keyImage);
|
||||
|
||||
await _unspentCoinsInfo.add(newInfo);
|
||||
_updateUnspents();
|
||||
wallet.updateBalance();
|
||||
return;
|
||||
}
|
||||
info.isFrozen = item.isFrozen;
|
||||
info.isSending = item.isSending;
|
||||
info.note = item.note;
|
||||
|
||||
await info.save();
|
||||
_updateUnspents();
|
||||
wallet.updateBalance();
|
||||
await _updateUnspents();
|
||||
await wallet.updateBalance();
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
UnspentCoinsInfo? getUnspentCoinInfo(
|
||||
String hash, String address, int value, int vout, String? keyImage) {
|
||||
return _unspentCoinsInfo.values.firstWhereOrNull((element) =>
|
||||
element.walletId == wallet.id &&
|
||||
element.hash == hash &&
|
||||
element.address == address &&
|
||||
element.value == value &&
|
||||
element.vout == vout &&
|
||||
element.keyImage == keyImage);
|
||||
}
|
||||
UnspentCoinsInfo getUnspentCoinInfo(
|
||||
String hash, String address, int value, int vout, String? keyImage) =>
|
||||
_unspentCoinsInfo.values.firstWhere((element) =>
|
||||
element.walletId == wallet.id &&
|
||||
element.hash == hash &&
|
||||
element.address == address &&
|
||||
element.value == value &&
|
||||
element.vout == vout &&
|
||||
element.keyImage == keyImage);
|
||||
|
||||
String formatAmountToString(int fullBalance) {
|
||||
if (wallet.type == WalletType.monero)
|
||||
|
@ -95,7 +76,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
|
|||
return '';
|
||||
}
|
||||
|
||||
void _updateUnspents() {
|
||||
Future<void> _updateUnspents() async {
|
||||
if (wallet.type == WalletType.monero) return monero!.updateUnspents(wallet);
|
||||
if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type))
|
||||
return bitcoin!.updateUnspents(wallet);
|
||||
|
|
|
@ -12,8 +12,6 @@ import devicelocale
|
|||
import in_app_review
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import platform_device_id
|
||||
import platform_device_id_macos
|
||||
import share_plus_macos
|
||||
import shared_preferences_foundation
|
||||
import url_launcher_macos
|
||||
|
@ -27,8 +25,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
|
||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin"))
|
||||
PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
|
|
|
@ -30,13 +30,11 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- package_info (0.0.1):
|
||||
- FlutterMacOS
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- platform_device_id (0.0.1):
|
||||
- FlutterMacOS
|
||||
- platform_device_id_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- share_plus_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
@ -45,7 +43,7 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- wakelock_macos (0.0.1):
|
||||
- wakelock_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
|
@ -57,13 +55,12 @@ DEPENDENCIES:
|
|||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
|
||||
- package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`)
|
||||
- platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`)
|
||||
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`)
|
||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
|
@ -86,20 +83,18 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos
|
||||
package_info:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info/macos
|
||||
package_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
platform_device_id:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos
|
||||
platform_device_id_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos
|
||||
share_plus_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
wakelock_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos
|
||||
wakelock_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
|
||||
|
@ -110,14 +105,13 @@ SPEC CHECKSUMS:
|
|||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
|
||||
package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2
|
||||
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763
|
||||
platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||
wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9
|
||||
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
||||
|
||||
PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ dependencies:
|
|||
lottie: ^1.3.0
|
||||
animate_do: ^2.1.0
|
||||
cupertino_icons: ^1.0.5
|
||||
encrypt: 5.0.1
|
||||
encrypt: 5.0.2
|
||||
crypto: ^3.0.2
|
||||
# password: ^1.0.0
|
||||
basic_utils: ^5.6.1
|
||||
|
@ -53,7 +53,10 @@ dependencies:
|
|||
another_flushbar: ^1.12.29
|
||||
archive: ^3.3.0
|
||||
cryptography: ^2.0.5
|
||||
file_picker: ^5.2.5
|
||||
file_picker:
|
||||
git:
|
||||
url: https://github.com/cake-tech/flutter_file_picker.git
|
||||
ref: master
|
||||
unorm_dart: ^0.2.0
|
||||
# check unorm_dart for usage and for replace
|
||||
permission_handler: ^10.0.0
|
||||
|
@ -62,10 +65,9 @@ dependencies:
|
|||
url: https://github.com/cake-tech/device_display_brightness.git
|
||||
ref: master
|
||||
workmanager: ^0.5.1
|
||||
# platform_device_id: ^1.0.1
|
||||
wakelock_plus: ^1.1.1
|
||||
wakelock_plus: ^1.1.3
|
||||
flutter_mailer: ^2.0.2
|
||||
device_info_plus: 8.1.0
|
||||
device_info_plus: ^9.1.0
|
||||
base32: 2.1.3
|
||||
in_app_review: ^2.0.6
|
||||
cake_backup:
|
||||
|
|
|
@ -591,7 +591,6 @@
|
|||
"sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلاً. لا تترك هذه الشاشة وإلا فقد يتم فقد أموال سويبت",
|
||||
"decimal_places_error": "عدد كبير جدًا من المنازل العشرية",
|
||||
"edit_node": "تحرير العقدة",
|
||||
"frozen_balance": "الرصيد المجمد",
|
||||
"invoice_details": "تفاصيل الفاتورة",
|
||||
"donation_link_details": "تفاصيل رابط التبرع",
|
||||
"anonpay_description": "توليد ${type}. يمكن للمستلم ${method} بأي عملة مشفرة مدعومة ، وستتلقى أموالاً في هذه",
|
||||
|
@ -727,10 +726,15 @@
|
|||
"enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ",
|
||||
"seed_key": "مفتاح البذور",
|
||||
"enter_seed_phrase": "أدخل عبارة البذور الخاصة بك",
|
||||
"change_rep_successful": "تم تغيير ممثل بنجاح",
|
||||
"add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ",
|
||||
"exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!",
|
||||
"domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ",
|
||||
"require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ",
|
||||
"camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ",
|
||||
"switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ"
|
||||
"switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ",
|
||||
"seed_phrase_length": " ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ",
|
||||
"unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ",
|
||||
"unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ",
|
||||
"unspent_change": "يتغير"
|
||||
}
|
||||
|
|
|
@ -588,7 +588,6 @@
|
|||
"error_dialog_content": "Получихме грешка.\n\nМоля, изпратете доклада до нашия отдел поддръжка, за да подобрим приложението.",
|
||||
"decimal_places_error": "Твърде много знаци след десетичната запетая",
|
||||
"edit_node": "Редактиране на възел",
|
||||
"frozen_balance": "Замразен баланс",
|
||||
"invoice_details": "IДанни за фактура",
|
||||
"donation_link_details": "Подробности за връзката за дарение",
|
||||
"anonpay_description": "Генерирайте ${type}. Получателят може да ${method} с всяка поддържана криптовалута и вие ще получите средства в този портфейл.",
|
||||
|
@ -723,10 +722,15 @@
|
|||
"enterWalletConnectURI": "Въведете URI на WalletConnect",
|
||||
"seed_key": "Ключ за семена",
|
||||
"enter_seed_phrase": "Въведете вашата фраза за семена",
|
||||
"change_rep_successful": "Успешно промени представител",
|
||||
"add_contact": "Добави контакт",
|
||||
"exchange_provider_unsupported": "${providerName} вече не се поддържа!",
|
||||
"domain_looks_up": "Търсене на домейни",
|
||||
"require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли",
|
||||
"camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.",
|
||||
"switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново"
|
||||
"switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново",
|
||||
"seed_phrase_length": "Дължина на началната фраза",
|
||||
"unavailable_balance": "Неналично салдо",
|
||||
"unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.",
|
||||
"unspent_change": "Промяна"
|
||||
}
|
||||
|
|
|
@ -588,7 +588,6 @@
|
|||
"error_dialog_content": "Nastala chyba.\n\nProsím odešlete zprávu o chybě naší podpoře, aby mohli zajistit opravu.",
|
||||
"decimal_places_error": "Příliš mnoho desetinných míst",
|
||||
"edit_node": "Upravit uzel",
|
||||
"frozen_balance": "Zmrazená bilance",
|
||||
"invoice_details": "detaily faktury",
|
||||
"donation_link_details": "Podrobnosti odkazu na darování",
|
||||
"anonpay_description": "Vygenerujte ${type}. Příjemce může ${method} s jakoukoli podporovanou kryptoměnou a vy obdržíte prostředky v této peněžence.",
|
||||
|
@ -723,10 +722,15 @@
|
|||
"enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect",
|
||||
"seed_key": "Klíč semen",
|
||||
"enter_seed_phrase": "Zadejte svou frázi semen",
|
||||
"change_rep_successful": "Úspěšně změnil zástupce",
|
||||
"add_contact": "Přidat kontakt",
|
||||
"exchange_provider_unsupported": "${providerName} již není podporováno!",
|
||||
"domain_looks_up": "Vyhledávání domén",
|
||||
"require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek",
|
||||
"camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.",
|
||||
"switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu"
|
||||
"switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu",
|
||||
"seed_phrase_length": "Délka fráze semene",
|
||||
"unavailable_balance": "Nedostupný zůstatek",
|
||||
"unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.",
|
||||
"unspent_change": "Změna"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE GELDER VERLOREN GEHEN",
|
||||
"decimal_places_error": "Zu viele Nachkommastellen",
|
||||
"edit_node": "Knoten bearbeiten",
|
||||
"frozen_balance": "Gefrorenes Guthaben",
|
||||
"invoice_details": "Rechnungs-Details",
|
||||
"donation_link_details": "Details zum Spendenlink",
|
||||
"anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.",
|
||||
|
@ -729,12 +728,17 @@
|
|||
"awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.",
|
||||
"copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein",
|
||||
"enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein",
|
||||
"seed_key": "Seed-Schlüssel",
|
||||
"enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein",
|
||||
"seed_key": "Samenschlüssel",
|
||||
"enter_seed_phrase": "Geben Sie Ihre Samenphrase ein",
|
||||
"change_rep_successful": "Erfolgreich veränderte Vertreter",
|
||||
"add_contact": "Kontakt hinzufügen",
|
||||
"exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!",
|
||||
"domain_looks_up": "Domain-Suchen",
|
||||
"require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets",
|
||||
"camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.",
|
||||
"switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut"
|
||||
"switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut",
|
||||
"seed_phrase_length": "Länge der Seed-Phrase",
|
||||
"unavailable_balance": "Nicht verfügbares Guthaben",
|
||||
"unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.",
|
||||
"unspent_change": "Wechselgeld"
|
||||
}
|
||||
|
|
|
@ -606,7 +606,6 @@
|
|||
"onion_link": "Onion link",
|
||||
"decimal_places_error": "Too many decimal places",
|
||||
"edit_node": "Edit Node",
|
||||
"frozen_balance": "Frozen Balance",
|
||||
"settings": "Settings",
|
||||
"sell_monero_com_alert_content": "Selling Monero is not supported yet",
|
||||
"error_text_input_below_minimum_limit": "Amount is less than the minimum",
|
||||
|
@ -732,10 +731,15 @@
|
|||
"enterWalletConnectURI": "Enter WalletConnect URI",
|
||||
"seed_key": "Seed key",
|
||||
"enter_seed_phrase": "Enter your seed phrase",
|
||||
"change_rep_successful": "Successfully changed representative",
|
||||
"add_contact": "Add contact",
|
||||
"exchange_provider_unsupported": "${providerName} is no longer supported!",
|
||||
"domain_looks_up": "Domain lookups",
|
||||
"require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets",
|
||||
"camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.",
|
||||
"switchToETHWallet": "Please switch to an Ethereum wallet and try again"
|
||||
"switchToETHWallet": "Please switch to an Ethereum wallet and try again",
|
||||
"seed_phrase_length": "Seed phrase length",
|
||||
"unavailable_balance": "Unavailable balance",
|
||||
"unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.",
|
||||
"unspent_change": "Change"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS",
|
||||
"decimal_places_error": "Demasiados lugares decimales",
|
||||
"edit_node": "Editar nodo",
|
||||
"frozen_balance": "Balance congelado",
|
||||
"invoice_details": "Detalles de la factura",
|
||||
"donation_link_details": "Detalles del enlace de donación",
|
||||
"anonpay_description": "Genera ${type}. El destinatario puede ${method} con cualquier criptomoneda admitida, y recibirá fondos en esta billetera.",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "Ingrese el URI de WalletConnect",
|
||||
"seed_key": "Llave de semilla",
|
||||
"enter_seed_phrase": "Ingrese su frase de semillas",
|
||||
"change_rep_successful": "Representante cambiado con éxito",
|
||||
"add_contact": "Agregar contacto",
|
||||
"exchange_provider_unsupported": "¡${providerName} ya no es compatible!",
|
||||
"domain_looks_up": "Búsquedas de dominio",
|
||||
"require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas",
|
||||
"camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.",
|
||||
"switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente."
|
||||
"switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.",
|
||||
"seed_phrase_length": "Longitud de la frase inicial",
|
||||
"unavailable_balance": "Saldo no disponible",
|
||||
"unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.",
|
||||
"unspent_change": "Cambiar"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Cette opération ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS CONSOLIDÉS POURRAIENT ÊTRE PERDUS",
|
||||
"decimal_places_error": "Trop de décimales",
|
||||
"edit_node": "Modifier le nœud",
|
||||
"frozen_balance": "Solde gelé",
|
||||
"invoice_details": "Détails de la facture",
|
||||
"donation_link_details": "Détails du lien de don",
|
||||
"anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).",
|
||||
|
@ -726,15 +725,20 @@
|
|||
"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",
|
||||
"awaitDAppProcessing": "Veuillez attendre que le dApp termine le traitement.",
|
||||
"copyWalletConnectLink": "Copiez le lien WalletConnect depuis dApp et collez-le ici",
|
||||
"awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.",
|
||||
"copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici",
|
||||
"enterWalletConnectURI": "Saisissez l'URI de WalletConnect.",
|
||||
"seed_key": "Clé de graines",
|
||||
"enter_seed_phrase": "Entrez votre phrase de semence",
|
||||
"seed_key": "Clé secrète (seed key)",
|
||||
"enter_seed_phrase": "Entrez votre phrase secrète (seed)",
|
||||
"change_rep_successful": "Représentant changé avec succès",
|
||||
"add_contact": "Ajouter le contact",
|
||||
"exchange_provider_unsupported": "${providerName} n'est plus pris en charge!",
|
||||
"domain_looks_up": "Recherches de domaine",
|
||||
"require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes",
|
||||
"camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.",
|
||||
"switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer"
|
||||
"exchange_provider_unsupported": "${providerName} n'est plus pris en charge !",
|
||||
"domain_looks_up": "Résolution de nom",
|
||||
"require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes",
|
||||
"seed_phrase_length": "Longueur de la phrase de départ",
|
||||
"unavailable_balance": "Solde indisponible",
|
||||
"unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.",
|
||||
"camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.",
|
||||
"switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer",
|
||||
"unspent_change": "Changement"
|
||||
}
|
||||
|
|
|
@ -602,7 +602,6 @@
|
|||
"onion_link": "Lambar onion",
|
||||
"decimal_places_error": "Wadannan suna da tsawon harsuna",
|
||||
"edit_node": "Shirya Node",
|
||||
"frozen_balance": "Falin kuma maɓallin",
|
||||
"settings": "Saiti",
|
||||
"sell_monero_com_alert_content": "Selling Monero bai sami ƙarshen mai bukatar samun ba",
|
||||
"error_text_input_below_minimum_limit": "Kudin ba a kamai",
|
||||
|
@ -709,10 +708,15 @@
|
|||
"enterWalletConnectURI": "Shigar da WalletConnect URI",
|
||||
"seed_key": "Maɓallin iri",
|
||||
"enter_seed_phrase": "Shigar da Sert Sentarku",
|
||||
"change_rep_successful": "An samu nasarar canzawa wakilin",
|
||||
"add_contact": "Ƙara lamba",
|
||||
"exchange_provider_unsupported": "${providerName}",
|
||||
"domain_looks_up": "Binciken yanki",
|
||||
"require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje",
|
||||
"camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.",
|
||||
"switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa"
|
||||
"switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa",
|
||||
"seed_phrase_length": "Tsawon jimlar iri",
|
||||
"unavailable_balance": "Ma'aunin da ba ya samuwa",
|
||||
"unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.",
|
||||
"unspent_change": "Canza"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "इसमें अधिक समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें या स्वैप्ट फंड खो सकते हैं",
|
||||
"decimal_places_error": "बहुत अधिक दशमलव स्थान",
|
||||
"edit_node": "नोड संपादित करें",
|
||||
"frozen_balance": "जमे हुए संतुलन",
|
||||
"invoice_details": "चालान विवरण",
|
||||
"donation_link_details": "दान लिंक विवरण",
|
||||
"anonpay_description": "${type} उत्पन्न करें। प्राप्तकर्ता किसी भी समर्थित क्रिप्टोकरेंसी के साथ ${method} कर सकता है, और आपको इस वॉलेट में धन प्राप्त होगा।",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें",
|
||||
"seed_key": "बीज कुंजी",
|
||||
"enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें",
|
||||
"change_rep_successful": "सफलतापूर्वक बदलकर प्रतिनिधि",
|
||||
"add_contact": "संपर्क जोड़ें",
|
||||
"exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!",
|
||||
"domain_looks_up": "डोमेन लुकअप",
|
||||
"require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है",
|
||||
"camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।",
|
||||
"switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें"
|
||||
"switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें",
|
||||
"seed_phrase_length": "बीज वाक्यांश की लंबाई",
|
||||
"unavailable_balance": "अनुपलब्ध शेष",
|
||||
"unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।",
|
||||
"unspent_change": "परिवर्तन"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON INAČE SE POBREŠENA SREDSTVA MOGU IZGUBITI",
|
||||
"decimal_places_error": "Previše decimalnih mjesta",
|
||||
"edit_node": "Uredi čvor",
|
||||
"frozen_balance": "Zamrznuti saldo",
|
||||
"invoice_details": "Podaci o fakturi",
|
||||
"donation_link_details": "Detalji veza za donacije",
|
||||
"anonpay_description": "Generiraj ${type}. Primatelj može ${method} s bilo kojom podržanom kriptovalutom, a vi ćete primiti sredstva u ovaj novčanik.",
|
||||
|
@ -729,10 +728,15 @@
|
|||
"enterWalletConnectURI": "Unesite WalletConnect URI",
|
||||
"seed_key": "Sjemenski ključ",
|
||||
"enter_seed_phrase": "Unesite svoju sjemensku frazu",
|
||||
"change_rep_successful": "Uspješno promijenjena reprezentativna",
|
||||
"add_contact": "Dodaj kontakt",
|
||||
"exchange_provider_unsupported": "${providerName} više nije podržan!",
|
||||
"domain_looks_up": "Pretraga domena",
|
||||
"require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike",
|
||||
"camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.",
|
||||
"switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno"
|
||||
"switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno",
|
||||
"seed_phrase_length": "Duljina početne fraze",
|
||||
"unavailable_balance": "Nedostupno stanje",
|
||||
"unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.",
|
||||
"unspent_change": "Promijeniti"
|
||||
}
|
||||
|
|
|
@ -584,7 +584,6 @@
|
|||
"contact_list_wallets": "Dompet Saya",
|
||||
"decimal_places_error": "Terlalu banyak tempat desimal",
|
||||
"edit_node": "Sunting Node",
|
||||
"frozen_balance": "Saldo Beku",
|
||||
"invoice_details": "Detail faktur",
|
||||
"donation_link_details": "Detail tautan donasi",
|
||||
"anonpay_description": "Hasilkan ${type}. Penerima dapat ${method} dengan cryptocurrency apa pun yang didukung, dan Anda akan menerima dana di dompet ini.",
|
||||
|
@ -719,10 +718,15 @@
|
|||
"enterWalletConnectURI": "Masukkan URI WalletConnect",
|
||||
"seed_key": "Kunci benih",
|
||||
"enter_seed_phrase": "Masukkan frasa benih Anda",
|
||||
"change_rep_successful": "Berhasil mengubah perwakilan",
|
||||
"add_contact": "Tambah kontak",
|
||||
"exchange_provider_unsupported": "${providerName} tidak lagi didukung!",
|
||||
"domain_looks_up": "Pencarian domain",
|
||||
"require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal",
|
||||
"camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.",
|
||||
"switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi"
|
||||
"switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi",
|
||||
"seed_phrase_length": "Panjang frase benih",
|
||||
"unavailable_balance": "Saldo tidak tersedia",
|
||||
"unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.",
|
||||
"unspent_change": "Mengubah"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPAZZATI POTREBBERO ANDARE PERSI",
|
||||
"decimal_places_error": "Troppe cifre decimali",
|
||||
"edit_node": "Modifica nodo",
|
||||
"frozen_balance": "Equilibrio congelato",
|
||||
"invoice_details": "Dettagli della fattura",
|
||||
"donation_link_details": "Dettagli del collegamento alla donazione",
|
||||
"anonpay_description": "Genera ${type}. Il destinatario può ${method} con qualsiasi criptovaluta supportata e riceverai fondi in questo portafoglio.",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "Inserisci l'URI di WalletConnect",
|
||||
"seed_key": "Chiave di semi",
|
||||
"enter_seed_phrase": "Inserisci la tua frase di semi",
|
||||
"change_rep_successful": "Rappresentante modificato con successo",
|
||||
"add_contact": "Aggiungi contatto",
|
||||
"exchange_provider_unsupported": "${providerName} non è più supportato!",
|
||||
"domain_looks_up": "Ricerche di domini",
|
||||
"require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni",
|
||||
"camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.",
|
||||
"switchToETHWallet": "Passa a un portafoglio Ethereum e riprova"
|
||||
"switchToETHWallet": "Passa a un portafoglio Ethereum e riprova",
|
||||
"seed_phrase_length": "Lunghezza della frase seed",
|
||||
"unavailable_balance": "Saldo non disponibile",
|
||||
"unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.",
|
||||
"unspent_change": "Modifica"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "これには時間がかかりません。この画面から離れないでください。そうしないと、スイープ ファンドが失われる可能性があります",
|
||||
"decimal_places_error": "小数点以下の桁数が多すぎる",
|
||||
"edit_node": "ノードを編集",
|
||||
"frozen_balance": "冷凍残高",
|
||||
"invoice_details": "請求の詳細",
|
||||
"donation_link_details": "寄付リンクの詳細",
|
||||
"anonpay_description": "${type} を生成します。受取人はサポートされている任意の暗号通貨で ${method} でき、あなたはこのウォレットで資金を受け取ります。",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "WalletConnect URI を入力してください",
|
||||
"seed_key": "シードキー",
|
||||
"enter_seed_phrase": "シードフレーズを入力してください",
|
||||
"change_rep_successful": "代表者の変更に成功しました",
|
||||
"add_contact": "連絡先を追加",
|
||||
"exchange_provider_unsupported": "${providerName}はサポートされなくなりました!",
|
||||
"domain_looks_up": "ドメイン検索",
|
||||
"require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要",
|
||||
"camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。",
|
||||
"switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください"
|
||||
"switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください",
|
||||
"seed_phrase_length": "シードフレーズの長さ",
|
||||
"unavailable_balance": "利用できない残高",
|
||||
"unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。",
|
||||
"unspent_change": "変化"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마십시오. 그렇지 않으면 스웹트 자금이 손실될 수 있습니다.",
|
||||
"decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.",
|
||||
"edit_node": "노드 편집",
|
||||
"frozen_balance": "얼어붙은 균형",
|
||||
"invoice_details": "인보이스 세부정보",
|
||||
"donation_link_details": "기부 링크 세부정보",
|
||||
"anonpay_description": "${type} 생성. 수신자는 지원되는 모든 암호화폐로 ${method}할 수 있으며 이 지갑에서 자금을 받게 됩니다.",
|
||||
|
@ -729,10 +728,15 @@
|
|||
"enterWalletConnectURI": "WalletConnect URI를 입력하세요.",
|
||||
"seed_key": "시드 키",
|
||||
"enter_seed_phrase": "시드 문구를 입력하십시오",
|
||||
"change_rep_successful": "대리인이 성공적으로 변경되었습니다",
|
||||
"add_contact": "주소록에 추가",
|
||||
"exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!",
|
||||
"domain_looks_up": "도메인 조회",
|
||||
"require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요",
|
||||
"camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.",
|
||||
"switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요."
|
||||
"switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.",
|
||||
"seed_phrase_length": "시드 문구 길이",
|
||||
"unavailable_balance": "사용할 수 없는 잔액",
|
||||
"unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.",
|
||||
"unspent_change": "변화"
|
||||
}
|
||||
|
|
|
@ -593,7 +593,6 @@
|
|||
"sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဤစခရင်ကို ချန်မထားပါနှင့် သို့မဟုတ် ထုတ်ယူထားသော ရန်ပုံငွေများ ဆုံးရှုံးနိုင်သည်",
|
||||
"decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။",
|
||||
"edit_node": "Node ကို တည်းဖြတ်ပါ။",
|
||||
"frozen_balance": "ေးခဲမှူ",
|
||||
"invoice_details": "ပြေစာအသေးစိတ်",
|
||||
"donation_link_details": "လှူဒါန်းရန်လင့်ခ်အသေးစိတ်",
|
||||
"anonpay_description": "${type} ကို ဖန်တီးပါ။ လက်ခံသူက ${method} ကို ပံ့ပိုးပေးထားသည့် cryptocurrency တစ်ခုခုဖြင့် လုပ်ဆောင်နိုင်ပြီး၊ သင်သည် ဤပိုက်ဆံအိတ်တွင် ရံပုံငွေများ ရရှိမည်ဖြစ်သည်။",
|
||||
|
@ -729,10 +728,15 @@
|
|||
"enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။",
|
||||
"seed_key": "မျိုးစေ့သော့",
|
||||
"enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ",
|
||||
"change_rep_successful": "အောင်မြင်စွာကိုယ်စားလှယ်ပြောင်းလဲသွားတယ်",
|
||||
"add_contact": "အဆက်အသွယ်ထည့်ပါ။",
|
||||
"exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!",
|
||||
"domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ",
|
||||
"require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။",
|
||||
"camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။",
|
||||
"switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။"
|
||||
"switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။",
|
||||
"seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်",
|
||||
"unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။",
|
||||
"unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။",
|
||||
"unspent_change": "ပေြာင်းလဲခြင်း"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KAN HET SWEPT-GELD VERLOREN WORDEN",
|
||||
"decimal_places_error": "Te veel decimalen",
|
||||
"edit_node": "Knooppunt bewerken",
|
||||
"frozen_balance": "Bevroren saldo",
|
||||
"invoice_details": "Factuurgegevens",
|
||||
"donation_link_details": "Details van de donatielink",
|
||||
"anonpay_description": "Genereer ${type}. De ontvanger kan ${method} gebruiken met elke ondersteunde cryptocurrency en u ontvangt geld in deze portemonnee",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "Voer WalletConnect-URI in",
|
||||
"seed_key": "Zaadsleutel",
|
||||
"enter_seed_phrase": "Voer uw zaadzin in",
|
||||
"change_rep_successful": "Met succes veranderde vertegenwoordiger",
|
||||
"add_contact": "Contactpersoon toevoegen",
|
||||
"exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!",
|
||||
"domain_looks_up": "Domein opzoeken",
|
||||
"require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees",
|
||||
"camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.",
|
||||
"switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw"
|
||||
"switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw",
|
||||
"seed_phrase_length": "Lengte van de zaadzin",
|
||||
"unavailable_balance": "Onbeschikbaar saldo",
|
||||
"unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.",
|
||||
"unspent_change": "Wijziging"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI",
|
||||
"decimal_places_error": "Za dużo miejsc dziesiętnych",
|
||||
"edit_node": "Edytuj węzeł",
|
||||
"frozen_balance": "Zamrożona równowaga",
|
||||
"invoice_details": "Dane do faktury",
|
||||
"donation_link_details": "Szczegóły linku darowizny",
|
||||
"anonpay_description": "Wygeneruj ${type}. Odbiorca może ${method} z dowolną obsługiwaną kryptowalutą, a Ty otrzymasz środki w tym portfelu.",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect",
|
||||
"seed_key": "Klucz nasion",
|
||||
"enter_seed_phrase": "Wprowadź swoją frazę nasienną",
|
||||
"change_rep_successful": "Pomyślnie zmienił przedstawiciela",
|
||||
"add_contact": "Dodaj kontakt",
|
||||
"exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!",
|
||||
"domain_looks_up": "Wyszukiwanie domen",
|
||||
"require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne",
|
||||
"camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.",
|
||||
"switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie"
|
||||
"switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie",
|
||||
"seed_phrase_length": "Długość frazy początkowej",
|
||||
"unavailable_balance": "Niedostępne saldo",
|
||||
"unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.",
|
||||
"unspent_change": "Zmiana"
|
||||
}
|
||||
|
|
|
@ -594,7 +594,6 @@
|
|||
"sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI",
|
||||
"decimal_places_error": "Muitas casas decimais",
|
||||
"edit_node": "Editar nó",
|
||||
"frozen_balance": "Saldo Congelado",
|
||||
"invoice_details": "Detalhes da fatura",
|
||||
"donation_link_details": "Detalhes do link de doação",
|
||||
"anonpay_description": "Gere ${type}. O destinatário pode ${method} com qualquer criptomoeda suportada e você receberá fundos nesta carteira.",
|
||||
|
@ -730,10 +729,15 @@
|
|||
"enterWalletConnectURI": "Insira o URI do WalletConnect",
|
||||
"seed_key": "Chave de semente",
|
||||
"enter_seed_phrase": "Digite sua frase de semente",
|
||||
"change_rep_successful": "Mudou com sucesso o representante",
|
||||
"add_contact": "Adicionar contato",
|
||||
"exchange_provider_unsupported": "${providerName} não é mais suportado!",
|
||||
"domain_looks_up": "Pesquisas de domínio",
|
||||
"require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas",
|
||||
"camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.",
|
||||
"switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente"
|
||||
"switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente",
|
||||
"seed_phrase_length": "Comprimento da frase-semente",
|
||||
"unavailable_balance": "Saldo indisponível",
|
||||
"unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.",
|
||||
"unspent_change": "Mudar"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ВЫЧИСЛЕННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ",
|
||||
"decimal_places_error": "Слишком много десятичных знаков",
|
||||
"edit_node": "Редактировать узел",
|
||||
"frozen_balance": "Замороженный баланс",
|
||||
"invoice_details": "Детали счета",
|
||||
"donation_link_details": "Информация о ссылке для пожертвований",
|
||||
"anonpay_description": "Создайте ${type}. Получатель может использовать ${method} с любой поддерживаемой криптовалютой, и вы получите средства на этот кошелек.",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "Введите URI WalletConnect",
|
||||
"seed_key": "Ключ семян",
|
||||
"enter_seed_phrase": "Введите свою семенную фразу",
|
||||
"change_rep_successful": "Успешно изменил представитель",
|
||||
"add_contact": "Добавить контакт",
|
||||
"exchange_provider_unsupported": "${providerName} больше не поддерживается!",
|
||||
"domain_looks_up": "Поиск доменов",
|
||||
"require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки",
|
||||
"camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.",
|
||||
"switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку."
|
||||
"switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.",
|
||||
"seed_phrase_length": "Длина исходной фразы",
|
||||
"unavailable_balance": "Недоступный баланс",
|
||||
"unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.",
|
||||
"unspent_change": "Изменять"
|
||||
}
|
||||
|
|
|
@ -593,7 +593,6 @@
|
|||
"sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน อย่าออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดไปอาจสูญหาย",
|
||||
"decimal_places_error": "ทศนิยมมากเกินไป",
|
||||
"edit_node": "แก้ไขโหนด",
|
||||
"frozen_balance": "ยอดคงเหลือแช่แข็ง",
|
||||
"invoice_details": "รายละเอียดใบแจ้งหนี้",
|
||||
"donation_link_details": "รายละเอียดลิงค์บริจาค",
|
||||
"anonpay_description": "สร้าง ${type} ผู้รับสามารถ ${method} ด้วยสกุลเงินดิจิทัลที่รองรับ และคุณจะได้รับเงินในกระเป๋าสตางค์นี้",
|
||||
|
@ -729,10 +728,15 @@
|
|||
"enterWalletConnectURI": "เข้าสู่ WalletConnect URI",
|
||||
"seed_key": "คีย์เมล็ดพันธุ์",
|
||||
"enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ",
|
||||
"change_rep_successful": "เปลี่ยนตัวแทนสำเร็จ",
|
||||
"add_contact": "เพิ่มผู้ติดต่อ",
|
||||
"exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!",
|
||||
"domain_looks_up": "การค้นหาโดเมน",
|
||||
"require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก",
|
||||
"camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป",
|
||||
"switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง"
|
||||
"switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง",
|
||||
"seed_phrase_length": "ความยาววลีของเมล็ด",
|
||||
"unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน",
|
||||
"unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง",
|
||||
"unspent_change": "เปลี่ยน"
|
||||
}
|
||||
|
|
|
@ -606,7 +606,6 @@
|
|||
"onion_link": "Link ng Onion",
|
||||
"decimal_places_error": "Masyadong maraming mga lugar na desimal",
|
||||
"edit_node": "I -edit ang node",
|
||||
"frozen_balance": "Frozen na balanse",
|
||||
"settings": "Mga setting",
|
||||
"sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado",
|
||||
"error_text_input_below_minimum_limit": "Ang halaga ay mas mababa sa minimum",
|
||||
|
@ -726,10 +725,15 @@
|
|||
"enterWalletConnectURI": "Ilagay ang WalletConnect URI",
|
||||
"seed_key": "Seed Key",
|
||||
"enter_seed_phrase": "Ipasok ang iyong pariralang binhi",
|
||||
"change_rep_successful": "Matagumpay na nagbago ng kinatawan",
|
||||
"add_contact": "Magdagdag ng contact",
|
||||
"exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!",
|
||||
"domain_looks_up": "Mga paghahanap ng domain",
|
||||
"require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet",
|
||||
"camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.",
|
||||
"switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli"
|
||||
"switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli",
|
||||
"seed_phrase_length": "Haba ng parirala ng binhi",
|
||||
"unavailable_balance": "Hindi available na balanse",
|
||||
"unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.",
|
||||
"unspent_change": "Baguhin"
|
||||
}
|
||||
|
|
|
@ -593,7 +593,6 @@
|
|||
"sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN BIRAKMAYIN YOKSA SÜPÜRÜLEN FONLAR KAYBOLABİLİR",
|
||||
"decimal_places_error": "Çok fazla ondalık basamak",
|
||||
"edit_node": "Düğümü Düzenle",
|
||||
"frozen_balance": "Dondurulmuş Bakiye",
|
||||
"invoice_details": "fatura detayları",
|
||||
"donation_link_details": "Bağış bağlantısı ayrıntıları",
|
||||
"anonpay_description": "${type} oluşturun. Alıcı, desteklenen herhangi bir kripto para birimi ile ${method} yapabilir ve bu cüzdanda para alırsınız.",
|
||||
|
@ -729,10 +728,15 @@
|
|||
"enterWalletConnectURI": "WalletConnect URI'sini girin",
|
||||
"seed_key": "Tohum",
|
||||
"enter_seed_phrase": "Tohum ifadenizi girin",
|
||||
"change_rep_successful": "Temsilciyi başarıyla değiştirdi",
|
||||
"add_contact": "Kişi ekle",
|
||||
"exchange_provider_unsupported": "${providerName} artık desteklenmiyor!",
|
||||
"domain_looks_up": "Etki alanı aramaları",
|
||||
"require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın",
|
||||
"camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.",
|
||||
"switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin"
|
||||
"switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin",
|
||||
"seed_phrase_length": "Çekirdek cümle uzunluğu",
|
||||
"unavailable_balance": "Kullanılamayan bakiye",
|
||||
"unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.",
|
||||
"unspent_change": "Değiştirmek"
|
||||
}
|
||||
|
|
|
@ -595,7 +595,6 @@
|
|||
"sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЬОГО ЕКРАНУ, АБО КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ",
|
||||
"decimal_places_error": "Забагато знаків після коми",
|
||||
"edit_node": "Редагувати вузол",
|
||||
"frozen_balance": "Заморожений баланс",
|
||||
"invoice_details": "Реквізити рахунку-фактури",
|
||||
"donation_link_details": "Деталі посилання для пожертв",
|
||||
"anonpay_description": "Згенерувати ${type}. Одержувач може ${method} будь-якою підтримуваною криптовалютою, і ви отримаєте кошти на цей гаманець.",
|
||||
|
@ -731,10 +730,15 @@
|
|||
"enterWalletConnectURI": "Введіть URI WalletConnect",
|
||||
"seed_key": "Насіннєвий ключ",
|
||||
"enter_seed_phrase": "Введіть свою насіннєву фразу",
|
||||
"change_rep_successful": "Успішно змінив представник",
|
||||
"add_contact": "Додати контакт",
|
||||
"exchange_provider_unsupported": "${providerName} більше не підтримується!",
|
||||
"domain_looks_up": "Пошук доменів",
|
||||
"require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці",
|
||||
"camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.",
|
||||
"switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу"
|
||||
"switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу",
|
||||
"seed_phrase_length": "Довжина початкової фрази",
|
||||
"unavailable_balance": "Недоступний баланс",
|
||||
"unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.",
|
||||
"unspent_change": "Зміна"
|
||||
}
|
||||
|
|
|
@ -588,7 +588,6 @@
|
|||
"error_dialog_content": "افوہ، ہمیں کچھ خرابی ملی۔\n\nایپلی کیشن کو بہتر بنانے کے لیے براہ کرم کریش رپورٹ ہماری سپورٹ ٹیم کو بھیجیں۔",
|
||||
"decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔",
|
||||
"edit_node": "نوڈ میں ترمیم کریں۔",
|
||||
"frozen_balance": "منجمد بیلنس",
|
||||
"invoice_details": "رسید کی تفصیلات",
|
||||
"donation_link_details": "عطیہ کے لنک کی تفصیلات",
|
||||
"anonpay_description": "${type} بنائیں۔ وصول کنندہ کسی بھی تعاون یافتہ کرپٹو کرنسی کے ساتھ ${method} کرسکتا ہے، اور آپ کو اس بٹوے میں فنڈز موصول ہوں گے۔",
|
||||
|
@ -723,10 +722,15 @@
|
|||
"enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ",
|
||||
"seed_key": "بیج کی کلید",
|
||||
"enter_seed_phrase": "اپنے بیج کا جملہ درج کریں",
|
||||
"change_rep_successful": "نمائندہ کو کامیابی کے ساتھ تبدیل کیا",
|
||||
"add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ",
|
||||
"exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!",
|
||||
"domain_looks_up": "ڈومین تلاش کرنا",
|
||||
"require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ",
|
||||
"camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ",
|
||||
"switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ"
|
||||
"switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ",
|
||||
"seed_phrase_length": " ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ",
|
||||
"unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ",
|
||||
"unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ",
|
||||
"unspent_change": "تبدیل کریں"
|
||||
}
|
||||
|
|
|
@ -599,7 +599,6 @@
|
|||
"onion_link": "Kọja ilọ alubosa",
|
||||
"decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ",
|
||||
"edit_node": "Tun awọn ọwọnrin ṣiṣe",
|
||||
"frozen_balance": "Aferugbo Iye",
|
||||
"settings": "Awọn aseṣe",
|
||||
"sell_monero_com_alert_content": "Kọ ju lọwọ Monero ko ṣe ni ibamu",
|
||||
"error_text_input_below_minimum_limit": "Iye jọwọ ni o kere ti o wọle diẹ",
|
||||
|
@ -725,10 +724,15 @@
|
|||
"enterWalletConnectURI": "Tẹ WalletConnect URI sii",
|
||||
"seed_key": "Bọtini Ose",
|
||||
"enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ",
|
||||
"change_rep_successful": "Ni ifijišẹ yipada aṣoju",
|
||||
"add_contact": "Fi olubasọrọ kun",
|
||||
"exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!",
|
||||
"domain_looks_up": "Awọn wiwa agbegbe",
|
||||
"require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita",
|
||||
"camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.",
|
||||
"switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi"
|
||||
"switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi",
|
||||
"seed_phrase_length": "Gigun gbolohun irugbin",
|
||||
"unavailable_balance": "Iwontunwonsi ti ko si",
|
||||
"unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.",
|
||||
"unspent_change": "Yipada"
|
||||
}
|
||||
|
|
|
@ -594,7 +594,6 @@
|
|||
"sweeping_wallet_alert": "\n这应该不会花很长时间。请勿离开此屏幕,否则可能会丢失所掠取的资金",
|
||||
"decimal_places_error": "小数位太多",
|
||||
"edit_node": "编辑节点",
|
||||
"frozen_balance": "冻结余额",
|
||||
"invoice_details": "发票明细",
|
||||
"donation_link_details": "捐赠链接详情",
|
||||
"anonpay_description": "生成 ${type}。收款人可以使用任何受支持的加密货币 ${method},您将在此钱包中收到资金。",
|
||||
|
@ -730,10 +729,15 @@
|
|||
"enterWalletConnectURI": "输入 WalletConnect URI",
|
||||
"seed_key": "种子钥匙",
|
||||
"enter_seed_phrase": "输入您的种子短语",
|
||||
"change_rep_successful": "成功改变了代表",
|
||||
"add_contact": "增加联系人",
|
||||
"exchange_provider_unsupported": "${providerName}不再支持!",
|
||||
"domain_looks_up": "域名查找",
|
||||
"require_for_exchanges_to_external_wallets": "需要兑换到外部钱包",
|
||||
"camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。",
|
||||
"switchToETHWallet": "请切换到以太坊钱包并重试"
|
||||
"switchToETHWallet": "请切换到以太坊钱包并重试",
|
||||
"seed_phrase_length": "种子短语长度",
|
||||
"unavailable_balance": "不可用余额",
|
||||
"unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。",
|
||||
"unspent_change": "改变"
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue