mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-17 01:37:40 +00:00
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into CW-659-Automated-Integrated-Tests
This commit is contained in:
commit
b8627d8e32
75 changed files with 454 additions and 243 deletions
1
.github/workflows/pr_test_build.yml
vendored
1
.github/workflows/pr_test_build.yml
vendored
|
@ -161,6 +161,7 @@ jobs:
|
|||
echo "const quantexExchangeMarkup = '${{ secrets.QUANTEX_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
|
||||
echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
|
||||
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||
echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
|
||||
|
||||
- name: Rename app
|
||||
run: |
|
||||
|
|
|
@ -4,5 +4,9 @@
|
|||
useSSL: true
|
||||
-
|
||||
uri: api.trongrid.io
|
||||
is_default: false
|
||||
useSSL: true
|
||||
-
|
||||
uri: trx.nownodes.io
|
||||
is_default: true
|
||||
useSSL: true
|
|
@ -2,9 +2,9 @@ import 'dart:convert';
|
|||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:unorm_dart/unorm_dart.dart' as unorm;
|
||||
import 'package:cryptography/cryptography.dart' as cryptography;
|
||||
import 'package:cw_core/sec_random_native.dart';
|
||||
import 'package:cw_core/utils/text_normalizer.dart';
|
||||
|
||||
const segwit = '100';
|
||||
final wordlist = englishWordlist;
|
||||
|
@ -137,121 +137,6 @@ bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
|
|||
}
|
||||
}
|
||||
|
||||
final COMBININGCODEPOINTS = combiningcodepoints();
|
||||
|
||||
List<int> combiningcodepoints() {
|
||||
final source = '300:34e|350:36f|483:487|591:5bd|5bf|5c1|5c2|5c4|5c5|5c7|610:61a|64b:65f|670|' +
|
||||
'6d6:6dc|6df:6e4|6e7|6e8|6ea:6ed|711|730:74a|7eb:7f3|816:819|81b:823|825:827|' +
|
||||
'829:82d|859:85b|8d4:8e1|8e3:8ff|93c|94d|951:954|9bc|9cd|a3c|a4d|abc|acd|b3c|' +
|
||||
'b4d|bcd|c4d|c55|c56|cbc|ccd|d4d|dca|e38:e3a|e48:e4b|eb8|eb9|ec8:ecb|f18|f19|' +
|
||||
'f35|f37|f39|f71|f72|f74|f7a:f7d|f80|f82:f84|f86|f87|fc6|1037|1039|103a|108d|' +
|
||||
'135d:135f|1714|1734|17d2|17dd|18a9|1939:193b|1a17|1a18|1a60|1a75:1a7c|1a7f|' +
|
||||
'1ab0:1abd|1b34|1b44|1b6b:1b73|1baa|1bab|1be6|1bf2|1bf3|1c37|1cd0:1cd2|' +
|
||||
'1cd4:1ce0|1ce2:1ce8|1ced|1cf4|1cf8|1cf9|1dc0:1df5|1dfb:1dff|20d0:20dc|20e1|' +
|
||||
'20e5:20f0|2cef:2cf1|2d7f|2de0:2dff|302a:302f|3099|309a|a66f|a674:a67d|a69e|' +
|
||||
'a69f|a6f0|a6f1|a806|a8c4|a8e0:a8f1|a92b:a92d|a953|a9b3|a9c0|aab0|aab2:aab4|' +
|
||||
'aab7|aab8|aabe|aabf|aac1|aaf6|abed|fb1e|fe20:fe2f|101fd|102e0|10376:1037a|' +
|
||||
'10a0d|10a0f|10a38:10a3a|10a3f|10ae5|10ae6|11046|1107f|110b9|110ba|11100:11102|' +
|
||||
'11133|11134|11173|111c0|111ca|11235|11236|112e9|112ea|1133c|1134d|11366:1136c|' +
|
||||
'11370:11374|11442|11446|114c2|114c3|115bf|115c0|1163f|116b6|116b7|1172b|11c3f|' +
|
||||
'16af0:16af4|16b30:16b36|1bc9e|1d165:1d169|1d16d:1d172|1d17b:1d182|1d185:1d18b|' +
|
||||
'1d1aa:1d1ad|1d242:1d244|1e000:1e006|1e008:1e018|1e01b:1e021|1e023|1e024|' +
|
||||
'1e026:1e02a|1e8d0:1e8d6|1e944:1e94a';
|
||||
|
||||
return source.split('|').map((e) {
|
||||
if (e.contains(':')) {
|
||||
return e.split(':').map((hex) => int.parse(hex, radix: 16));
|
||||
}
|
||||
|
||||
return int.parse(e, radix: 16);
|
||||
}).fold(<int>[], (List<int> acc, element) {
|
||||
if (element is List) {
|
||||
for (var i = element[0] as int; i <= (element[1] as int); i++) {}
|
||||
} else if (element is int) {
|
||||
acc.add(element);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
String removeCombiningCharacters(String source) {
|
||||
return source
|
||||
.split('')
|
||||
.where((char) => !COMBININGCODEPOINTS.contains(char.codeUnits.first))
|
||||
.join('');
|
||||
}
|
||||
|
||||
bool isCJK(String char) {
|
||||
final n = char.codeUnitAt(0);
|
||||
|
||||
for (var x in CJKINTERVALS) {
|
||||
final imin = x[0] as num;
|
||||
final imax = x[1] as num;
|
||||
|
||||
if (n >= imin && n <= imax) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String removeCJKSpaces(String source) {
|
||||
final splitted = source.split('');
|
||||
final filtered = <String>[];
|
||||
|
||||
for (var i = 0; i < splitted.length; i++) {
|
||||
final char = splitted[i];
|
||||
final isSpace = char.trim() == '';
|
||||
final prevIsCJK = i != 0 && isCJK(splitted[i - 1]);
|
||||
final nextIsCJK = i != splitted.length - 1 && isCJK(splitted[i + 1]);
|
||||
|
||||
if (!(isSpace && prevIsCJK && nextIsCJK)) {
|
||||
filtered.add(char);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered.join('');
|
||||
}
|
||||
|
||||
String normalizeText(String source) {
|
||||
final res =
|
||||
removeCombiningCharacters(unorm.nfkd(source).toLowerCase()).trim().split('/\s+/').join(' ');
|
||||
|
||||
return removeCJKSpaces(res);
|
||||
}
|
||||
|
||||
const CJKINTERVALS = [
|
||||
[0x4e00, 0x9fff, 'CJK Unified Ideographs'],
|
||||
[0x3400, 0x4dbf, 'CJK Unified Ideographs Extension A'],
|
||||
[0x20000, 0x2a6df, 'CJK Unified Ideographs Extension B'],
|
||||
[0x2a700, 0x2b73f, 'CJK Unified Ideographs Extension C'],
|
||||
[0x2b740, 0x2b81f, 'CJK Unified Ideographs Extension D'],
|
||||
[0xf900, 0xfaff, 'CJK Compatibility Ideographs'],
|
||||
[0x2f800, 0x2fa1d, 'CJK Compatibility Ideographs Supplement'],
|
||||
[0x3190, 0x319f, 'Kanbun'],
|
||||
[0x2e80, 0x2eff, 'CJK Radicals Supplement'],
|
||||
[0x2f00, 0x2fdf, 'CJK Radicals'],
|
||||
[0x31c0, 0x31ef, 'CJK Strokes'],
|
||||
[0x2ff0, 0x2fff, 'Ideographic Description Characters'],
|
||||
[0xe0100, 0xe01ef, 'Variation Selectors Supplement'],
|
||||
[0x3100, 0x312f, 'Bopomofo'],
|
||||
[0x31a0, 0x31bf, 'Bopomofo Extended'],
|
||||
[0xff00, 0xffef, 'Halfwidth and Fullwidth Forms'],
|
||||
[0x3040, 0x309f, 'Hiragana'],
|
||||
[0x30a0, 0x30ff, 'Katakana'],
|
||||
[0x31f0, 0x31ff, 'Katakana Phonetic Extensions'],
|
||||
[0x1b000, 0x1b0ff, 'Kana Supplement'],
|
||||
[0xac00, 0xd7af, 'Hangul Syllables'],
|
||||
[0x1100, 0x11ff, 'Hangul Jamo'],
|
||||
[0xa960, 0xa97f, 'Hangul Jamo Extended A'],
|
||||
[0xd7b0, 0xd7ff, 'Hangul Jamo Extended B'],
|
||||
[0x3130, 0x318f, 'Hangul Compatibility Jamo'],
|
||||
[0xa4d0, 0xa4ff, 'Lisu'],
|
||||
[0x16f00, 0x16f9f, 'Miao'],
|
||||
[0xa000, 0xa48f, 'Yi Syllables'],
|
||||
[0xa490, 0xa4cf, 'Yi Radicals'],
|
||||
];
|
||||
|
||||
final englishWordlist = <String>[
|
||||
'abandon',
|
||||
'ability',
|
||||
|
@ -2301,4 +2186,4 @@ final englishWordlist = <String>[
|
|||
'zero',
|
||||
'zone',
|
||||
'zoo'
|
||||
];
|
||||
];
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
|||
import 'package:convert/convert.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:cw_bitcoin/electrum_derivations.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
|
||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||
|
@ -150,7 +151,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
);
|
||||
|
||||
// set the default if not present:
|
||||
walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? "m/0'/0";
|
||||
walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? electrum_path;
|
||||
walletInfo.derivationInfo!.derivationType = snp.derivationType ?? DerivationType.electrum;
|
||||
|
||||
Uint8List? seedBytes = null;
|
||||
|
|
|
@ -108,3 +108,6 @@ Map<DerivationType, List<DerivationInfo>> electrum_derivations = {
|
|||
),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
String electrum_path = electrum_derivations[DerivationType.electrum]!.first.derivationPath!;
|
|
@ -17,6 +17,7 @@ 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_derivations.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';
|
||||
|
@ -133,7 +134,7 @@ abstract class ElectrumWalletBase
|
|||
return currency == CryptoCurrency.bch
|
||||
? bitcoinCashHDWallet(seedBytes)
|
||||
: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
|
||||
.derivePath(_hardenedDerivationPath(derivationInfo?.derivationPath ?? "m/0'"));
|
||||
.derivePath(_hardenedDerivationPath(derivationInfo?.derivationPath ?? electrum_path));
|
||||
}
|
||||
|
||||
return bitcoin.HDWallet.fromBase58(xpub!);
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||
import 'package:cw_bitcoin/electrum_derivations.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/utils/file.dart';
|
||||
|
@ -71,7 +72,7 @@ class ElectrumWalletSnapshot {
|
|||
|
||||
final derivationType = DerivationType
|
||||
.values[(data['derivationTypeIndex'] as int?) ?? DerivationType.electrum.index];
|
||||
final derivationPath = data['derivationPath'] as String? ?? "m/0'/0";
|
||||
final derivationPath = data['derivationPath'] as String? ?? electrum_path;
|
||||
|
||||
try {
|
||||
regularAddressIndexByType = {
|
||||
|
|
|
@ -5,58 +5,64 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
|||
import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
|
||||
import 'package:hex/hex.dart';
|
||||
|
||||
bitcoin.PaymentData generatePaymentData({required bitcoin.HDWallet hd, int? index}) {
|
||||
final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!;
|
||||
bitcoin.PaymentData generatePaymentData({
|
||||
required bitcoin.HDWallet hd,
|
||||
required int index,
|
||||
}) {
|
||||
final pubKey = hd.derive(index).pubKey!;
|
||||
return PaymentData(pubkey: Uint8List.fromList(HEX.decode(pubKey)));
|
||||
}
|
||||
|
||||
ECPrivate generateECPrivate(
|
||||
{required bitcoin.HDWallet hd, required BasedUtxoNetwork network, int? index}) {
|
||||
final wif = index != null ? hd.derive(index).wif! : hd.wif!;
|
||||
ECPrivate generateECPrivate({
|
||||
required bitcoin.HDWallet hd,
|
||||
required BasedUtxoNetwork network,
|
||||
required int index,
|
||||
}) {
|
||||
final wif = hd.derive(index).wif!;
|
||||
return ECPrivate.fromWif(wif, netVersion: network.wifNetVer);
|
||||
}
|
||||
|
||||
String generateP2WPKHAddress({
|
||||
required bitcoin.HDWallet hd,
|
||||
required BasedUtxoNetwork network,
|
||||
int? index,
|
||||
required int index,
|
||||
}) {
|
||||
final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!;
|
||||
final pubKey = hd.derive(index).pubKey!;
|
||||
return ECPublic.fromHex(pubKey).toP2wpkhAddress().toAddress(network);
|
||||
}
|
||||
|
||||
String generateP2SHAddress({
|
||||
required bitcoin.HDWallet hd,
|
||||
required BasedUtxoNetwork network,
|
||||
int? index,
|
||||
required int index,
|
||||
}) {
|
||||
final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!;
|
||||
final pubKey = hd.derive(index).pubKey!;
|
||||
return ECPublic.fromHex(pubKey).toP2wpkhInP2sh().toAddress(network);
|
||||
}
|
||||
|
||||
String generateP2WSHAddress({
|
||||
required bitcoin.HDWallet hd,
|
||||
required BasedUtxoNetwork network,
|
||||
int? index,
|
||||
required int index,
|
||||
}) {
|
||||
final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!;
|
||||
final pubKey = hd.derive(index).pubKey!;
|
||||
return ECPublic.fromHex(pubKey).toP2wshAddress().toAddress(network);
|
||||
}
|
||||
|
||||
String generateP2PKHAddress({
|
||||
required bitcoin.HDWallet hd,
|
||||
required BasedUtxoNetwork network,
|
||||
int? index,
|
||||
required int index,
|
||||
}) {
|
||||
final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!;
|
||||
final pubKey = hd.derive(index).pubKey!;
|
||||
return ECPublic.fromHex(pubKey).toP2pkhAddress().toAddress(network);
|
||||
}
|
||||
|
||||
String generateP2TRAddress({
|
||||
required bitcoin.HDWallet hd,
|
||||
required BasedUtxoNetwork network,
|
||||
int? index,
|
||||
required int index,
|
||||
}) {
|
||||
final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!;
|
||||
final pubKey = hd.derive(index).pubKey!;
|
||||
return ECPublic.fromHex(pubKey).toTaprootAddress().toAddress(network);
|
||||
}
|
||||
|
|
|
@ -863,7 +863,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.3.2"
|
||||
unorm_dart:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: unorm_dart
|
||||
sha256: "5b35bff83fce4d76467641438f9e867dc9bcfdb8c1694854f230579d68cd8f4b"
|
||||
|
|
|
@ -28,7 +28,6 @@ dependencies:
|
|||
url: https://github.com/cake-tech/bitbox-flutter.git
|
||||
ref: Add-Support-For-OP-Return-data
|
||||
rxdart: ^0.27.5
|
||||
unorm_dart: ^0.2.0
|
||||
cryptography: ^2.0.5
|
||||
bitcoin_base:
|
||||
git:
|
||||
|
|
|
@ -16,6 +16,7 @@ abstract class TransactionInfo extends Object with Keyable {
|
|||
void changeFiatAmount(String amount);
|
||||
String? to;
|
||||
String? from;
|
||||
String? evmSignatureName;
|
||||
List<String>? inputAddresses;
|
||||
List<String>? outputAddresses;
|
||||
|
||||
|
|
117
cw_core/lib/utils/text_normalizer.dart
Normal file
117
cw_core/lib/utils/text_normalizer.dart
Normal file
|
@ -0,0 +1,117 @@
|
|||
import 'package:unorm_dart/unorm_dart.dart' as unorm;
|
||||
|
||||
const CJKINTERVALS = [
|
||||
[0x4e00, 0x9fff, 'CJK Unified Ideographs'],
|
||||
[0x3400, 0x4dbf, 'CJK Unified Ideographs Extension A'],
|
||||
[0x20000, 0x2a6df, 'CJK Unified Ideographs Extension B'],
|
||||
[0x2a700, 0x2b73f, 'CJK Unified Ideographs Extension C'],
|
||||
[0x2b740, 0x2b81f, 'CJK Unified Ideographs Extension D'],
|
||||
[0xf900, 0xfaff, 'CJK Compatibility Ideographs'],
|
||||
[0x2f800, 0x2fa1d, 'CJK Compatibility Ideographs Supplement'],
|
||||
[0x3190, 0x319f, 'Kanbun'],
|
||||
[0x2e80, 0x2eff, 'CJK Radicals Supplement'],
|
||||
[0x2f00, 0x2fdf, 'CJK Radicals'],
|
||||
[0x31c0, 0x31ef, 'CJK Strokes'],
|
||||
[0x2ff0, 0x2fff, 'Ideographic Description Characters'],
|
||||
[0xe0100, 0xe01ef, 'Variation Selectors Supplement'],
|
||||
[0x3100, 0x312f, 'Bopomofo'],
|
||||
[0x31a0, 0x31bf, 'Bopomofo Extended'],
|
||||
[0xff00, 0xffef, 'Halfwidth and Fullwidth Forms'],
|
||||
[0x3040, 0x309f, 'Hiragana'],
|
||||
[0x30a0, 0x30ff, 'Katakana'],
|
||||
[0x31f0, 0x31ff, 'Katakana Phonetic Extensions'],
|
||||
[0x1b000, 0x1b0ff, 'Kana Supplement'],
|
||||
[0xac00, 0xd7af, 'Hangul Syllables'],
|
||||
[0x1100, 0x11ff, 'Hangul Jamo'],
|
||||
[0xa960, 0xa97f, 'Hangul Jamo Extended A'],
|
||||
[0xd7b0, 0xd7ff, 'Hangul Jamo Extended B'],
|
||||
[0x3130, 0x318f, 'Hangul Compatibility Jamo'],
|
||||
[0xa4d0, 0xa4ff, 'Lisu'],
|
||||
[0x16f00, 0x16f9f, 'Miao'],
|
||||
[0xa000, 0xa48f, 'Yi Syllables'],
|
||||
[0xa490, 0xa4cf, 'Yi Radicals'],
|
||||
];
|
||||
|
||||
final COMBININGCODEPOINTS = combiningcodepoints();
|
||||
|
||||
List<int> combiningcodepoints() {
|
||||
final source = '300:34e|350:36f|483:487|591:5bd|5bf|5c1|5c2|5c4|5c5|5c7|610:61a|64b:65f|670|' +
|
||||
'6d6:6dc|6df:6e4|6e7|6e8|6ea:6ed|711|730:74a|7eb:7f3|816:819|81b:823|825:827|' +
|
||||
'829:82d|859:85b|8d4:8e1|8e3:8ff|93c|94d|951:954|9bc|9cd|a3c|a4d|abc|acd|b3c|' +
|
||||
'b4d|bcd|c4d|c55|c56|cbc|ccd|d4d|dca|e38:e3a|e48:e4b|eb8|eb9|ec8:ecb|f18|f19|' +
|
||||
'f35|f37|f39|f71|f72|f74|f7a:f7d|f80|f82:f84|f86|f87|fc6|1037|1039|103a|108d|' +
|
||||
'135d:135f|1714|1734|17d2|17dd|18a9|1939:193b|1a17|1a18|1a60|1a75:1a7c|1a7f|' +
|
||||
'1ab0:1abd|1b34|1b44|1b6b:1b73|1baa|1bab|1be6|1bf2|1bf3|1c37|1cd0:1cd2|' +
|
||||
'1cd4:1ce0|1ce2:1ce8|1ced|1cf4|1cf8|1cf9|1dc0:1df5|1dfb:1dff|20d0:20dc|20e1|' +
|
||||
'20e5:20f0|2cef:2cf1|2d7f|2de0:2dff|302a:302f|3099|309a|a66f|a674:a67d|a69e|' +
|
||||
'a69f|a6f0|a6f1|a806|a8c4|a8e0:a8f1|a92b:a92d|a953|a9b3|a9c0|aab0|aab2:aab4|' +
|
||||
'aab7|aab8|aabe|aabf|aac1|aaf6|abed|fb1e|fe20:fe2f|101fd|102e0|10376:1037a|' +
|
||||
'10a0d|10a0f|10a38:10a3a|10a3f|10ae5|10ae6|11046|1107f|110b9|110ba|11100:11102|' +
|
||||
'11133|11134|11173|111c0|111ca|11235|11236|112e9|112ea|1133c|1134d|11366:1136c|' +
|
||||
'11370:11374|11442|11446|114c2|114c3|115bf|115c0|1163f|116b6|116b7|1172b|11c3f|' +
|
||||
'16af0:16af4|16b30:16b36|1bc9e|1d165:1d169|1d16d:1d172|1d17b:1d182|1d185:1d18b|' +
|
||||
'1d1aa:1d1ad|1d242:1d244|1e000:1e006|1e008:1e018|1e01b:1e021|1e023|1e024|' +
|
||||
'1e026:1e02a|1e8d0:1e8d6|1e944:1e94a';
|
||||
|
||||
return source.split('|').map((e) {
|
||||
if (e.contains(':')) {
|
||||
return e.split(':').map((hex) => int.parse(hex, radix: 16));
|
||||
}
|
||||
|
||||
return int.parse(e, radix: 16);
|
||||
}).fold(<int>[], (List<int> acc, element) {
|
||||
if (element is List) {
|
||||
for (var i = element[0] as int; i <= (element[1] as int); i++) {}
|
||||
} else if (element is int) {
|
||||
acc.add(element);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
String _removeCombiningCharacters(String source) {
|
||||
return source
|
||||
.split('')
|
||||
.where((char) => !COMBININGCODEPOINTS.contains(char.codeUnits.first))
|
||||
.join('');
|
||||
}
|
||||
|
||||
String _removeCJKSpaces(String source) {
|
||||
final splitted = source.split('');
|
||||
final filtered = <String>[];
|
||||
|
||||
for (var i = 0; i < splitted.length; i++) {
|
||||
final char = splitted[i];
|
||||
final isSpace = char.trim() == '';
|
||||
final prevIsCJK = i != 0 && _isCJK(splitted[i - 1]);
|
||||
final nextIsCJK = i != splitted.length - 1 && _isCJK(splitted[i + 1]);
|
||||
|
||||
if (!(isSpace && prevIsCJK && nextIsCJK)) {
|
||||
filtered.add(char);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered.join('');
|
||||
}
|
||||
|
||||
bool _isCJK(String char) {
|
||||
final n = char.codeUnitAt(0);
|
||||
|
||||
for (var x in CJKINTERVALS) {
|
||||
final imin = x[0] as num;
|
||||
final imax = x[1] as num;
|
||||
|
||||
if (n >= imin && n <= imax) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// This method normalize text which transforms Unicode text into an equivalent decomposed form, allowing for easier sorting and searching of text.
|
||||
String normalizeText(String source) {
|
||||
final res =
|
||||
_removeCombiningCharacters(unorm.nfkd(source).toLowerCase()).trim().split('/\s+/').join(' ');
|
||||
|
||||
return _removeCJKSpaces(res);
|
||||
}
|
|
@ -656,6 +656,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
unorm_dart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: unorm_dart
|
||||
sha256: "5b35bff83fce4d76467641438f9e867dc9bcfdb8c1694854f230579d68cd8f4b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -20,6 +20,7 @@ dependencies:
|
|||
intl: ^0.18.0
|
||||
encrypt: ^5.0.1
|
||||
socks5_proxy: ^1.0.4
|
||||
unorm_dart: ^0.3.0
|
||||
# tor:
|
||||
# git:
|
||||
# url: https://github.com/cake-tech/tor.git
|
||||
|
|
|
@ -29,6 +29,11 @@ class EthereumClient extends EVMChainClient {
|
|||
|
||||
final jsonResponse = json.decode(response.body) as Map<String, dynamic>;
|
||||
|
||||
if (jsonResponse['result'] is String) {
|
||||
log(jsonResponse['result']);
|
||||
return [];
|
||||
}
|
||||
|
||||
if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) {
|
||||
return (jsonResponse['result'] as List)
|
||||
.map((e) => EVMChainTransactionModel.fromJson(e as Map<String, dynamic>, 'ETH'))
|
||||
|
|
|
@ -14,6 +14,7 @@ class EthereumTransactionInfo extends EVMChainTransactionInfo {
|
|||
required super.confirmations,
|
||||
required super.to,
|
||||
required super.from,
|
||||
super.evmSignatureName,
|
||||
super.exponent,
|
||||
});
|
||||
|
||||
|
@ -31,6 +32,7 @@ class EthereumTransactionInfo extends EVMChainTransactionInfo {
|
|||
tokenSymbol: data['tokenSymbol'] as String,
|
||||
to: data['to'],
|
||||
from: data['from'],
|
||||
evmSignatureName: data['evmSignatureName'],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ class EthereumWallet extends EVMChainWallet {
|
|||
tokenSymbol: transactionModel.tokenSymbol ?? "ETH",
|
||||
to: transactionModel.to,
|
||||
from: transactionModel.from,
|
||||
evmSignatureName: transactionModel.evmSignatureName,
|
||||
);
|
||||
return model;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ abstract class EVMChainTransactionInfo extends TransactionInfo {
|
|||
required this.confirmations,
|
||||
required this.to,
|
||||
required this.from,
|
||||
this.evmSignatureName,
|
||||
}) : amount = ethAmount.toInt(),
|
||||
fee = ethFee.toInt();
|
||||
|
||||
|
@ -38,6 +39,7 @@ abstract class EVMChainTransactionInfo extends TransactionInfo {
|
|||
String? _fiatAmount;
|
||||
final String? to;
|
||||
final String? from;
|
||||
final String? evmSignatureName;
|
||||
|
||||
//! Getter to be overridden in child classes
|
||||
String get feeCurrency;
|
||||
|
@ -73,5 +75,6 @@ abstract class EVMChainTransactionInfo extends TransactionInfo {
|
|||
'tokenSymbol': tokenSymbol,
|
||||
'to': to,
|
||||
'from': from,
|
||||
'evmSignatureName': evmSignatureName,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ class EVMChainTransactionModel {
|
|||
final String? tokenSymbol;
|
||||
final int? tokenDecimal;
|
||||
final bool isError;
|
||||
final String input;
|
||||
String? evmSignatureName;
|
||||
|
||||
EVMChainTransactionModel({
|
||||
required this.date,
|
||||
|
@ -27,6 +29,8 @@ class EVMChainTransactionModel {
|
|||
required this.tokenSymbol,
|
||||
required this.tokenDecimal,
|
||||
required this.isError,
|
||||
required this.input,
|
||||
this.evmSignatureName,
|
||||
});
|
||||
|
||||
factory EVMChainTransactionModel.fromJson(Map<String, dynamic> json, String defaultSymbol) =>
|
||||
|
@ -44,5 +48,7 @@ class EVMChainTransactionModel {
|
|||
tokenSymbol: json["tokenSymbol"] ?? defaultSymbol,
|
||||
tokenDecimal: int.tryParse(json["tokenDecimal"] ?? ""),
|
||||
isError: json["isError"] == "1",
|
||||
input: json["input"] ?? "",
|
||||
evmSignatureName: json["evmSignatureName"],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,20 @@ import 'evm_erc20_balance.dart';
|
|||
|
||||
part 'evm_chain_wallet.g.dart';
|
||||
|
||||
const Map<String, String> methodSignatureToType = {
|
||||
'0x095ea7b3': 'approval',
|
||||
'0xa9059cbb': 'transfer',
|
||||
'0x23b872dd': 'transferFrom',
|
||||
'0x574da717': 'transferOut',
|
||||
'0x2e1a7d4d': 'withdraw',
|
||||
'0x7ff36ab5': 'swapExactETHForTokens',
|
||||
'0x40c10f19': 'mint',
|
||||
'0x44bc937b': 'depositWithExpiry',
|
||||
'0xd0e30db0': 'deposit',
|
||||
'0xe8e33700': 'addLiquidity',
|
||||
'0xd505accf': 'permit',
|
||||
};
|
||||
|
||||
abstract class EVMChainWallet = EVMChainWalletBase with _$EVMChainWallet;
|
||||
|
||||
abstract class EVMChainWalletBase
|
||||
|
@ -235,7 +249,8 @@ abstract class EVMChainWalletBase
|
|||
|
||||
String? hexOpReturnMemo;
|
||||
if (opReturnMemo != null) {
|
||||
hexOpReturnMemo = '0x${opReturnMemo.codeUnits.map((char) => char.toRadixString(16).padLeft(2, '0')).join()}';
|
||||
hexOpReturnMemo =
|
||||
'0x${opReturnMemo.codeUnits.map((char) => char.toRadixString(16).padLeft(2, '0')).join()}';
|
||||
}
|
||||
|
||||
final CryptoCurrency transactionCurrency =
|
||||
|
@ -337,11 +352,21 @@ abstract class EVMChainWalletBase
|
|||
|
||||
@override
|
||||
Future<Map<String, EVMChainTransactionInfo>> fetchTransactions() async {
|
||||
final List<EVMChainTransactionModel> transactions = [];
|
||||
final List<Future<List<EVMChainTransactionModel>>> erc20TokensTransactions = [];
|
||||
|
||||
final address = _evmChainPrivateKey.address.hex;
|
||||
final transactions = await _client.fetchTransactions(address);
|
||||
final externalTransactions = await _client.fetchTransactions(address);
|
||||
final internalTransactions = await _client.fetchInternalTransactions(address);
|
||||
|
||||
final List<Future<List<EVMChainTransactionModel>>> erc20TokensTransactions = [];
|
||||
for (var transaction in externalTransactions) {
|
||||
final evmSignatureName = analyzeTransaction(transaction.input);
|
||||
|
||||
if (evmSignatureName != 'depositWithExpiry' && evmSignatureName != 'transfer') {
|
||||
transaction.evmSignatureName = evmSignatureName;
|
||||
transactions.add(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
for (var token in balance.keys) {
|
||||
if (token is Erc20Token) {
|
||||
|
@ -369,6 +394,17 @@ abstract class EVMChainWalletBase
|
|||
return result;
|
||||
}
|
||||
|
||||
String? analyzeTransaction(String? transactionInput) {
|
||||
if (transactionInput == '0x' || transactionInput == null || transactionInput.isEmpty) {
|
||||
return 'simpleTransfer';
|
||||
}
|
||||
|
||||
final methodSignature =
|
||||
transactionInput.length >= 10 ? transactionInput.substring(0, 10) : null;
|
||||
|
||||
return methodSignatureToType[methodSignature];
|
||||
}
|
||||
|
||||
@override
|
||||
Object get keys => throw UnimplementedError("keys");
|
||||
|
||||
|
@ -482,11 +518,11 @@ abstract class EVMChainWalletBase
|
|||
await token.delete();
|
||||
|
||||
balance.remove(token);
|
||||
await _removeTokenTransactionsInHistory(token);
|
||||
await removeTokenTransactionsInHistory(token);
|
||||
_updateBalance();
|
||||
}
|
||||
|
||||
Future<void> _removeTokenTransactionsInHistory(Erc20Token token) async {
|
||||
Future<void> removeTokenTransactionsInHistory(Erc20Token token) async {
|
||||
transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title);
|
||||
await transactionHistory.save();
|
||||
}
|
||||
|
|
|
@ -108,6 +108,8 @@ abstract class MoneroWalletBase
|
|||
publicSpendKey: monero_wallet.getPublicSpendKey(),
|
||||
publicViewKey: monero_wallet.getPublicViewKey());
|
||||
|
||||
int? get restoreHeight => transactionHistory.transactions.values.firstOrNull?.height;
|
||||
|
||||
monero_wallet.SyncListener? _listener;
|
||||
ReactionDisposer? _onAccountChangeReaction;
|
||||
bool _isTransactionUpdating;
|
||||
|
|
|
@ -19,7 +19,7 @@ dependencies:
|
|||
flutter_mobx: ^2.0.6+1
|
||||
intl: ^0.18.0
|
||||
encrypt: ^5.0.1
|
||||
polyseed: ^0.0.2
|
||||
polyseed: ^0.0.5
|
||||
cw_core:
|
||||
path: ../cw_core
|
||||
|
||||
|
|
|
@ -456,7 +456,7 @@ class SolanaWalletClient {
|
|||
funder: ownerKeypair,
|
||||
);
|
||||
} catch (e) {
|
||||
throw Exception('Insufficient lamports balance to complete this transaction');
|
||||
throw Exception('Insufficient SOL balance to complete this transaction');
|
||||
}
|
||||
|
||||
// Input by the user
|
||||
|
|
|
@ -20,6 +20,7 @@ class TronHTTPProvider implements TronServiceProvider {
|
|||
final response = await client.get(Uri.parse(params.url(url)), headers: {
|
||||
'Content-Type': 'application/json',
|
||||
if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
|
||||
if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey,
|
||||
}).timeout(timeout ?? defaultRequestTimeout);
|
||||
final data = json.decode(response.body) as Map<String, dynamic>;
|
||||
return data;
|
||||
|
@ -32,6 +33,7 @@ class TronHTTPProvider implements TronServiceProvider {
|
|||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
|
||||
if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey,
|
||||
},
|
||||
body: params.toRequestBody())
|
||||
.timeout(timeout ?? defaultRequestTimeout);
|
||||
|
|
1
devtools_options.yaml
Normal file
1
devtools_options.yaml
Normal file
|
@ -0,0 +1 @@
|
|||
extensions:
|
|
@ -295,14 +295,7 @@ class CWBitcoin extends Bitcoin {
|
|||
|
||||
List<DerivationType> types = await compareDerivationMethods(mnemonic: mnemonic, node: node);
|
||||
if (types.length == 1 && types.first == DerivationType.electrum) {
|
||||
return [
|
||||
DerivationInfo(
|
||||
derivationType: DerivationType.electrum,
|
||||
derivationPath: "m/0'",
|
||||
description: "Electrum",
|
||||
scriptType: "p2wpkh",
|
||||
)
|
||||
];
|
||||
return [getElectrumDerivations()[DerivationType.electrum]!.first];
|
||||
}
|
||||
|
||||
final electrumClient = ElectrumClient();
|
||||
|
@ -339,38 +332,34 @@ class CWBitcoin extends Bitcoin {
|
|||
scriptType: dInfo.scriptType,
|
||||
);
|
||||
|
||||
String derivationPath = dInfoCopy.derivationPath!;
|
||||
int derivationDepth = _countOccurrences(derivationPath, "/");
|
||||
|
||||
// the correct derivation depth is dependant on the derivation type:
|
||||
// the derivation paths defined in electrum_derivations are at the ROOT level, i.e.:
|
||||
// electrum's format doesn't specify subaddresses, just subaccounts:
|
||||
String balancePath = dInfoCopy.derivationPath!;
|
||||
int derivationDepth = _countOccurrences(balancePath, "/");
|
||||
|
||||
// for BIP44
|
||||
if (derivationDepth == 3) {
|
||||
// we add "/0/0" so that we generate account 0, index 0 and correctly get balance
|
||||
derivationPath += "/0/0";
|
||||
if (derivationDepth == 3 || derivationDepth == 1) {
|
||||
// we add "/0" so that we generate account 0
|
||||
balancePath += "/0";
|
||||
}
|
||||
|
||||
// var hd = bip32.BIP32.fromSeed(seedBytes).derivePath(derivationPath);
|
||||
final hd = btc.HDWallet.fromSeed(
|
||||
seedBytes,
|
||||
network: networkType,
|
||||
).derivePath(derivationPath);
|
||||
).derivePath(balancePath);
|
||||
|
||||
// derive address at index 0:
|
||||
String? address;
|
||||
switch (dInfoCopy.scriptType) {
|
||||
case "p2wpkh":
|
||||
address = generateP2WPKHAddress(hd: hd, network: network);
|
||||
address = generateP2WPKHAddress(hd: hd, network: network, index: 0);
|
||||
break;
|
||||
case "p2pkh":
|
||||
address = generateP2PKHAddress(hd: hd, network: network);
|
||||
address = generateP2PKHAddress(hd: hd, network: network, index: 0);
|
||||
break;
|
||||
case "p2wpkh-p2sh":
|
||||
address = generateP2SHAddress(hd: hd, network: network);
|
||||
address = generateP2SHAddress(hd: hd, network: network, index: 0);
|
||||
break;
|
||||
case "p2tr":
|
||||
address = generateP2TRAddress(hd: hd, network: network);
|
||||
address = generateP2TRAddress(hd: hd, network: network, index: 0);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
|
@ -396,6 +385,11 @@ class CWBitcoin extends Bitcoin {
|
|||
return list;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<DerivationType, List<DerivationInfo>> getElectrumDerivations() {
|
||||
return electrum_derivations;
|
||||
}
|
||||
|
||||
@override
|
||||
bool hasTaprootInput(PendingTransaction pendingTransaction) {
|
||||
return (pendingTransaction as PendingBitcoinTransaction).hasTaprootInputs;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/entities/mnemonic_item.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/utils/language_list.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
class SeedValidator extends Validator<MnemonicItem> {
|
||||
SeedValidator({required this.type, required this.language})
|
||||
|
@ -41,13 +41,16 @@ class SeedValidator extends Validator<MnemonicItem> {
|
|||
return polygon!.getPolygonWordList(language);
|
||||
case WalletType.solana:
|
||||
return solana!.getSolanaWordList(language);
|
||||
case WalletType.tron:
|
||||
case WalletType.tron:
|
||||
return tron!.getTronWordList(language);
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
static bool needsNormalization(String language) =>
|
||||
["POLYSEED_French", "POLYSEED_Spanish"].contains(language);
|
||||
|
||||
static List<String> getBitcoinWordList(String language) {
|
||||
assert(language.toLowerCase() == LanguageList.english.toLowerCase());
|
||||
return bitcoin!.getWordList();
|
||||
|
|
|
@ -37,7 +37,7 @@ const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002';
|
|||
const nanoDefaultNodeUri = 'rpc.nano.to';
|
||||
const nanoDefaultPowNodeUri = 'rpc.nano.to';
|
||||
const solanaDefaultNodeUri = 'rpc.ankr.com';
|
||||
const tronDefaultNodeUri = 'api.trongrid.io';
|
||||
const tronDefaultNodeUri = 'trx.nownodes.io';
|
||||
const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002';
|
||||
|
||||
Future<void> defaultSettingsMigration(
|
||||
|
@ -233,6 +233,12 @@ Future<void> defaultSettingsMigration(
|
|||
case 36:
|
||||
await changeTronCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
break;
|
||||
case 37:
|
||||
await replaceTronDefaultNode(sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
break;
|
||||
case 38:
|
||||
await fixBtcDerivationPaths(walletInfoSource);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -775,6 +781,19 @@ Future<void> changeDefaultMoneroNode(
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> fixBtcDerivationPaths(Box<WalletInfo> walletsInfoSource) async {
|
||||
for (WalletInfo walletInfo in walletsInfoSource.values) {
|
||||
if (walletInfo.type == WalletType.bitcoin ||
|
||||
walletInfo.type == WalletType.bitcoinCash ||
|
||||
walletInfo.type == WalletType.litecoin) {
|
||||
if (walletInfo.derivationInfo?.derivationPath == "m/0'/0") {
|
||||
walletInfo.derivationInfo!.derivationPath = "m/0'";
|
||||
await walletInfo.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateBtcNanoWalletInfos(Box<WalletInfo> walletsInfoSource) async {
|
||||
for (WalletInfo walletInfo in walletsInfoSource.values) {
|
||||
if (walletInfo.type == WalletType.nano || walletInfo.type == WalletType.bitcoin) {
|
||||
|
@ -1127,3 +1146,29 @@ Future<void> changeTronCurrentNodeToDefault(
|
|||
|
||||
await sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, nodeId);
|
||||
}
|
||||
|
||||
Future<void> replaceTronDefaultNode({
|
||||
required SharedPreferences sharedPreferences,
|
||||
required Box<Node> nodes,
|
||||
}) async {
|
||||
// Get the currently active node
|
||||
final currentTronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
|
||||
final currentTronNode =
|
||||
nodes.values.firstWhereOrNull((Node node) => node.key == currentTronNodeId);
|
||||
|
||||
//Confirm if this node is part of the default nodes from CakeWallet
|
||||
final tronDefaultNodeList = [
|
||||
'tron-rpc.publicnode.com:443',
|
||||
'api.trongrid.io',
|
||||
];
|
||||
bool needsToBeReplaced =
|
||||
currentTronNode == null ? true : tronDefaultNodeList.contains(currentTronNode.uriRaw);
|
||||
|
||||
// If it's a custom node, return. We don't want to switch users from their custom nodes
|
||||
if (!needsToBeReplaced) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's not, we switch user to the new default node: NowNodes
|
||||
await changeTronCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
}
|
|
@ -201,7 +201,7 @@ class AddressResolver {
|
|||
final txtRecord = await OpenaliasRecord.lookupOpenAliasRecord(formattedName);
|
||||
if (txtRecord != null) {
|
||||
final record = await OpenaliasRecord.fetchAddressAndName(
|
||||
formattedName: formattedName, ticker: ticker, txtRecord: txtRecord);
|
||||
formattedName: formattedName, ticker: ticker.toLowerCase(), txtRecord: txtRecord);
|
||||
return ParsedAddress.fetchOpenAliasAddress(record: record, name: text);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ class PreferencesKey {
|
|||
static const moneroSeedType = 'monero_seed_type';
|
||||
static const clearnetDonationLink = 'clearnet_donation_link';
|
||||
static const onionDonationLink = 'onion_donation_link';
|
||||
static const donationLinkWalletName = 'donation_link_wallet_name';
|
||||
static const lastSeenAppVersion = 'last_seen_app_version';
|
||||
static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard';
|
||||
static const isNewInstall = 'is_new_install';
|
||||
|
|
|
@ -137,6 +137,10 @@ class CWEthereum extends Ethereum {
|
|||
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) async =>
|
||||
await (wallet as EthereumWallet).deleteErc20Token(token as Erc20Token);
|
||||
|
||||
@override
|
||||
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async =>
|
||||
await (wallet as EthereumWallet).removeTokenTransactionsInHistory(token as Erc20Token);
|
||||
|
||||
@override
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
|
||||
final ethereumWallet = wallet as EthereumWallet;
|
||||
|
|
|
@ -202,7 +202,7 @@ Future<void> initializeAppConfigs() async {
|
|||
transactionDescriptions: transactionDescriptions,
|
||||
secureStorage: secureStorage,
|
||||
anonpayInvoiceInfo: anonpayInvoiceInfo,
|
||||
initialMigrationVersion: 36,
|
||||
initialMigrationVersion: 38,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -244,6 +244,12 @@ class CWMonero extends Monero {
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
int? getRestoreHeight(Object wallet) {
|
||||
final moneroWallet = wallet as MoneroWallet;
|
||||
return moneroWallet.restoreHeight;
|
||||
}
|
||||
|
||||
@override
|
||||
Object createMoneroTransactionCreationCredentials(
|
||||
{required List<Output> outputs, required TransactionPriority priority}) =>
|
||||
|
|
|
@ -135,6 +135,10 @@ class CWPolygon extends Polygon {
|
|||
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) async =>
|
||||
await (wallet as PolygonWallet).deleteErc20Token(token as Erc20Token);
|
||||
|
||||
@override
|
||||
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async =>
|
||||
await (wallet as PolygonWallet).removeTokenTransactionsInHistory(token as Erc20Token);
|
||||
|
||||
@override
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
|
||||
final polygonWallet = wallet as PolygonWallet;
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
|||
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart';
|
||||
import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
|
@ -14,7 +13,6 @@ import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
|
|||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/share_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
@ -171,8 +169,7 @@ class AddressPage extends BasePage {
|
|||
textSize: 14,
|
||||
height: 50,
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
}),
|
||||
|
@ -204,8 +201,12 @@ class AddressPage extends BasePage {
|
|||
final sharedPreferences = getIt.get<SharedPreferences>();
|
||||
final clearnetUrl = sharedPreferences.getString(PreferencesKey.clearnetDonationLink);
|
||||
final onionUrl = sharedPreferences.getString(PreferencesKey.onionDonationLink);
|
||||
final donationWalletName =
|
||||
sharedPreferences.getString(PreferencesKey.donationLinkWalletName);
|
||||
|
||||
if (clearnetUrl != null && onionUrl != null) {
|
||||
if (clearnetUrl != null &&
|
||||
onionUrl != null &&
|
||||
addressListViewModel.wallet.name == donationWalletName) {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.anonPayReceivePage,
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.d
|
|||
import 'package:cake_wallet/view_model/dashboard/order_list_item.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
@ -87,6 +88,10 @@ class TransactionsPage extends StatelessWidget {
|
|||
}
|
||||
|
||||
final transaction = item.transaction;
|
||||
final transactionType = dashboardViewModel.type == WalletType.ethereum &&
|
||||
transaction.evmSignatureName == 'approval'
|
||||
? ' (${transaction.evmSignatureName})'
|
||||
: '';
|
||||
|
||||
return Observer(
|
||||
builder: (_) => TransactionRow(
|
||||
|
@ -100,7 +105,8 @@ class TransactionsPage extends StatelessWidget {
|
|||
? ''
|
||||
: item.formattedFiatAmount,
|
||||
isPending: transaction.isPending,
|
||||
title: item.formattedTitle + item.formattedStatus,
|
||||
title: item.formattedTitle +
|
||||
item.formattedStatus + ' $transactionType',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -60,8 +60,7 @@ class AnonPayInvoicePage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget middle(BuildContext context) => PresentReceiveOptionPicker(
|
||||
receiveOptionViewModel: receiveOptionViewModel,
|
||||
color: titleColor(context));
|
||||
receiveOptionViewModel: receiveOptionViewModel, color: titleColor(context));
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) => TrailButton(
|
||||
|
@ -87,30 +86,36 @@ class AnonPayInvoicePage extends BasePage {
|
|||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
focusNode: _amountFocusNode,
|
||||
toolbarButtons: [(_) => KeyboardDoneButton()],
|
||||
),
|
||||
]),
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(bottom: 24),
|
||||
content: Container(
|
||||
decoration: responsiveLayoutUtil.shouldRenderMobileUI ? BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor,
|
||||
Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
focusNode: _amountFocusNode,
|
||||
toolbarButtons: [(_) => KeyboardDoneButton()],
|
||||
),
|
||||
) : null,
|
||||
]),
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(bottom: 24),
|
||||
content: Container(
|
||||
decoration: responsiveLayoutUtil.shouldRenderMobileUI
|
||||
? BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context)
|
||||
.extension<ExchangePageTheme>()!
|
||||
.firstGradientTopPanelColor,
|
||||
Theme.of(context)
|
||||
.extension<ExchangePageTheme>()!
|
||||
.secondGradientTopPanelColor,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
child: Observer(builder: (_) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
|
||||
|
@ -143,9 +148,11 @@ class AnonPayInvoicePage extends BasePage {
|
|||
: S.of(context).anonpay_description("a donation link", "donate"),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).extension<ExchangePageTheme>()!.receiveAmountColor,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12),
|
||||
color: Theme.of(context)
|
||||
.extension<ExchangePageTheme>()!
|
||||
.receiveAmountColor,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -172,7 +179,7 @@ class AnonPayInvoicePage extends BasePage {
|
|||
anonInvoicePageViewModel.generateDonationLink();
|
||||
}
|
||||
},
|
||||
color: Theme.of(context).primaryColor,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
isLoading: anonInvoicePageViewModel.state is IsExecutingState,
|
||||
),
|
||||
|
@ -199,8 +206,12 @@ class AnonPayInvoicePage extends BasePage {
|
|||
final sharedPreferences = getIt.get<SharedPreferences>();
|
||||
final clearnetUrl = sharedPreferences.getString(PreferencesKey.clearnetDonationLink);
|
||||
final onionUrl = sharedPreferences.getString(PreferencesKey.onionDonationLink);
|
||||
final donationWalletName =
|
||||
sharedPreferences.getString(PreferencesKey.donationLinkWalletName);
|
||||
|
||||
if (clearnetUrl != null && onionUrl != null) {
|
||||
if (clearnetUrl != null &&
|
||||
onionUrl != null &&
|
||||
anonInvoicePageViewModel.currentWalletName == donationWalletName) {
|
||||
Navigator.pushReplacementNamed(context, Routes.anonPayReceivePage,
|
||||
arguments: AnonpayDonationLinkInfo(
|
||||
clearnetUrl: clearnetUrl,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import 'package:cake_wallet/core/seed_validator.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:cake_wallet/core/seed_validator.dart';
|
||||
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||
|
||||
class SeedWidget extends StatefulWidget {
|
||||
SeedWidget({
|
||||
|
@ -24,7 +24,6 @@ class SeedWidget extends StatefulWidget {
|
|||
}
|
||||
|
||||
class SeedWidgetState extends State<SeedWidget> {
|
||||
|
||||
SeedWidgetState(String language, this.type)
|
||||
: controller = TextEditingController(),
|
||||
focusNode = FocusNode(),
|
||||
|
@ -47,6 +46,7 @@ class SeedWidgetState extends State<SeedWidget> {
|
|||
final FocusNode focusNode;
|
||||
final WalletType type;
|
||||
List<String> words;
|
||||
bool normalizeSeed = false;
|
||||
bool _showPlaceholder;
|
||||
|
||||
String get text => controller.text;
|
||||
|
@ -61,6 +61,7 @@ class SeedWidgetState extends State<SeedWidget> {
|
|||
void changeSeedLanguage(String language) {
|
||||
setState(() {
|
||||
words = SeedValidator.getWordList(type: type, language: language);
|
||||
normalizeSeed = SeedValidator.needsNormalization(language);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -99,6 +100,7 @@ class SeedWidgetState extends State<SeedWidget> {
|
|||
focusNode: focusNode,
|
||||
controller: controller,
|
||||
words: words,
|
||||
normalizeSeed: normalizeSeed,
|
||||
textStyle: TextStyle(
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
backgroundColor: Colors.transparent,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:cw_core/utils/text_normalizer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
extension Compare<T> on Comparable<T> {
|
||||
bool operator <=(T other) => compareTo(other) <= 0;
|
||||
bool operator >=(T other) => compareTo(other) >= 0;
|
||||
|
@ -39,6 +39,7 @@ class ValidatableAnnotatedEditableText extends EditableText {
|
|||
required this.validStyle,
|
||||
required this.invalidStyle,
|
||||
required this.words,
|
||||
this.normalizeSeed = false,
|
||||
TextStyle textStyle = const TextStyle(
|
||||
color: Colors.black,
|
||||
backgroundColor: Colors.transparent,
|
||||
|
@ -74,6 +75,7 @@ class ValidatableAnnotatedEditableText extends EditableText {
|
|||
showSelectionHandles: true,
|
||||
showCursor: true);
|
||||
|
||||
final bool normalizeSeed;
|
||||
final List<String> words;
|
||||
final TextStyle validStyle;
|
||||
final TextStyle invalidStyle;
|
||||
|
@ -137,7 +139,8 @@ class ValidatableAnnotatedEditableTextState extends EditableTextState {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool validate(String source) => widget.words.indexOf(source) >= 0;
|
||||
bool validate(String source) =>
|
||||
widget.words.indexOf(widget.normalizeSeed ? normalizeText(source) : source) >= 0;
|
||||
|
||||
List<TextRange> range(String pattern, String source) {
|
||||
final result = <TextRange>[];
|
||||
|
@ -173,4 +176,4 @@ class ValidatableAnnotatedEditableTextState extends EditableTextState {
|
|||
|
||||
return TextSpan(style: widget.style, text: text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,6 +150,7 @@ abstract class AnonInvoicePageViewModelBase with Store {
|
|||
|
||||
await sharedPreferences.setString(PreferencesKey.clearnetDonationLink, result.clearnetUrl);
|
||||
await sharedPreferences.setString(PreferencesKey.onionDonationLink, result.onionUrl);
|
||||
await sharedPreferences.setString(PreferencesKey.donationLinkWalletName, _wallet.name);
|
||||
|
||||
state = ExecutedSuccessfullyState(payload: result);
|
||||
}
|
||||
|
@ -163,10 +164,13 @@ abstract class AnonInvoicePageViewModelBase with Store {
|
|||
maximum = limit.max != null ? limit.max! / 4 : null;
|
||||
}
|
||||
|
||||
@computed
|
||||
String get currentWalletName => _wallet.name;
|
||||
|
||||
@action
|
||||
void reset() {
|
||||
selectedCurrency = walletTypeToCryptoCurrency(_wallet.type);
|
||||
cryptoCurrency = walletTypeToCryptoCurrency(_wallet.type);
|
||||
cryptoCurrency = walletTypeToCryptoCurrency(_wallet.type);
|
||||
receipientEmail = '';
|
||||
receipientName = '';
|
||||
description = '';
|
||||
|
@ -177,7 +181,10 @@ abstract class AnonInvoicePageViewModelBase with Store {
|
|||
Future<void> _getPreviousDonationLink() async {
|
||||
if (pageOption == ReceivePageOption.anonPayDonationLink) {
|
||||
final donationLink = sharedPreferences.getString(PreferencesKey.clearnetDonationLink);
|
||||
if (donationLink != null) {
|
||||
final donationLinkWalletName =
|
||||
sharedPreferences.getString(PreferencesKey.donationLinkWalletName);
|
||||
|
||||
if (donationLink != null && currentWalletName == donationLinkWalletName) {
|
||||
final url = Uri.parse(donationLink);
|
||||
url.queryParameters.forEach((key, value) {
|
||||
if (key == 'name') receipientName = value;
|
||||
|
|
|
@ -39,7 +39,7 @@ abstract class ContactListViewModelBase with Store {
|
|||
));
|
||||
}
|
||||
});
|
||||
} else if (info.addresses?.isNotEmpty == true) {
|
||||
} else if (info.addresses?.isNotEmpty == true && info.addresses!.length > 1) {
|
||||
info.addresses!.forEach((address, label) {
|
||||
if (label.isEmpty) {
|
||||
return;
|
||||
|
|
|
@ -144,10 +144,12 @@ abstract class HomeSettingsViewModelBase with Store {
|
|||
|
||||
if (_balanceViewModel.wallet.type == WalletType.ethereum) {
|
||||
ethereum!.addErc20Token(_balanceViewModel.wallet, token as Erc20Token);
|
||||
if (!value) ethereum!.removeTokenTransactionsInHistory(_balanceViewModel.wallet, token);
|
||||
}
|
||||
|
||||
if (_balanceViewModel.wallet.type == WalletType.polygon) {
|
||||
polygon!.addErc20Token(_balanceViewModel.wallet, token as Erc20Token);
|
||||
if (!value) polygon!.removeTokenTransactionsInHistory(_balanceViewModel.wallet, token);
|
||||
}
|
||||
|
||||
if (_balanceViewModel.wallet.type == WalletType.solana) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/background_tasks.dart';
|
||||
|
@ -98,10 +99,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
);
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
return DerivationInfo(
|
||||
derivationType: DerivationType.electrum,
|
||||
derivationPath: "m/0'",
|
||||
);
|
||||
return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
|
||||
part 'wallet_keys_view_model.g.dart';
|
||||
|
@ -83,6 +82,12 @@ abstract class WalletKeysViewModelBase with Store {
|
|||
.toLegacySeed(legacyLang);
|
||||
items.add(StandartListItem(title: S.current.wallet_seed_legacy, value: legacySeed));
|
||||
}
|
||||
|
||||
final restoreHeight = monero!.getRestoreHeight(_appStore.wallet!);
|
||||
if (restoreHeight != null) {
|
||||
items.add(StandartListItem(
|
||||
title: S.current.wallet_recovery_height, value: restoreHeight.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (_appStore.wallet!.type == WalletType.haven) {
|
||||
|
|
|
@ -60,8 +60,6 @@ dependencies:
|
|||
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
|
||||
device_display_brightness:
|
||||
git:
|
||||
|
@ -100,7 +98,7 @@ dependencies:
|
|||
# ref: main
|
||||
socks5_proxy: ^1.0.4
|
||||
flutter_svg: ^2.0.9
|
||||
polyseed: ^0.0.4
|
||||
polyseed: ^0.0.5
|
||||
nostr_tools: ^1.0.9
|
||||
solana: ^0.30.1
|
||||
bitcoin_base:
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "قائمة",
|
||||
"wallet_name": "اسم المحفظة",
|
||||
"wallet_name_exists": "توجد بالفعل محفظة بهذا الاسم. الرجاء اختيار اسم مختلف أو إعادة تسمية المحفظة الأخرى أولاً.",
|
||||
"wallet_recovery_height": "ارتفاع الاسترداد",
|
||||
"wallet_restoration_store_incorrect_seed_length": "طول السييد غير صحيح",
|
||||
"wallet_seed": "سييد المحفظة",
|
||||
"wallet_seed_legacy": "بذرة محفظة قديمة",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Меню",
|
||||
"wallet_name": "Име на портфейл",
|
||||
"wallet_name_exists": "Вече има портфейл с това име. Моля, изберете друго име или преименувайте другия портфейл.",
|
||||
"wallet_recovery_height": "Височина на възстановяване",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Грешна дължина на seed-а",
|
||||
"wallet_seed": "Seed на портфейла",
|
||||
"wallet_seed_legacy": "Наследено портфейл семе",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Menu",
|
||||
"wallet_name": "Název peněženky",
|
||||
"wallet_name_exists": "Peněženka s tímto názvem už existuje. Prosím zvolte si jiný název, nebo nejprve přejmenujte nejprve druhou peněženku.",
|
||||
"wallet_recovery_height": "Výška zotavení",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Nesprávná délka seedu",
|
||||
"wallet_seed": "Seed peněženky",
|
||||
"wallet_seed_legacy": "Starší semeno peněženky",
|
||||
|
|
|
@ -837,6 +837,7 @@
|
|||
"wallet_menu": "Wallet-Menü",
|
||||
"wallet_name": "Walletname",
|
||||
"wallet_name_exists": "Wallet mit diesem Namen existiert bereits",
|
||||
"wallet_recovery_height": "Erstellungshöhe",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Falsche Seed-Länge",
|
||||
"wallet_seed": "Wallet-Seed",
|
||||
"wallet_seed_legacy": "Legacy Wallet Seed",
|
||||
|
@ -875,4 +876,4 @@
|
|||
"you_will_get": "Konvertieren zu",
|
||||
"you_will_send": "Konvertieren von",
|
||||
"yy": "YY"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Menu",
|
||||
"wallet_name": "Wallet name",
|
||||
"wallet_name_exists": "A wallet with that name already exists. Please choose a different name or rename the other wallet first.",
|
||||
"wallet_recovery_height": "Recovery Height",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Incorrect seed length",
|
||||
"wallet_seed": "Wallet seed",
|
||||
"wallet_seed_legacy": "Legacy wallet seed",
|
||||
|
|
|
@ -835,6 +835,7 @@
|
|||
"wallet_menu": "Menú de billetera",
|
||||
"wallet_name": "Nombre de la billetera",
|
||||
"wallet_name_exists": "Wallet con ese nombre ya ha existido",
|
||||
"wallet_recovery_height": "Altura de recuperación",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Longitud de semilla incorrecta",
|
||||
"wallet_seed": "Semilla de billetera",
|
||||
"wallet_seed_legacy": "Semilla de billetera heredada",
|
||||
|
|
|
@ -266,7 +266,7 @@
|
|||
"errorSigningTransaction": "Une erreur s'est produite lors de la signature de la transaction",
|
||||
"estimated": "Estimé",
|
||||
"estimated_new_fee": "De nouveaux frais estimés",
|
||||
"etherscan_history": "Historique d'Etherscan",
|
||||
"etherscan_history": "Historique Etherscan",
|
||||
"event": "Événement",
|
||||
"events": "Événements",
|
||||
"exchange": "Échanger",
|
||||
|
@ -404,7 +404,7 @@
|
|||
"node_test": "Tester",
|
||||
"nodes": "Nœuds",
|
||||
"nodes_list_reset_to_default_message": "Êtes vous certain de vouloir revenir aux réglages par défaut ?",
|
||||
"none_of_selected_providers_can_exchange": "Aucun des prestataires sélectionnés ne peut effectuer cet échange",
|
||||
"none_of_selected_providers_can_exchange": "Aucun des fournisseurs sélectionnés ne peut effectuer cet échange",
|
||||
"noNFTYet": "Pas encore de NFT",
|
||||
"normal": "Normal",
|
||||
"note_optional": "Note (optionnelle)",
|
||||
|
@ -794,7 +794,7 @@
|
|||
"unconfirmed": "Solde non confirmé",
|
||||
"understand": "J'ai compris",
|
||||
"unmatched_currencies": "La devise de votre portefeuille (wallet) actuel ne correspond pas à celle du QR code scanné",
|
||||
"unspent_change": "Changement",
|
||||
"unspent_change": "Monnaie",
|
||||
"unspent_coins_details_title": "Détails des pièces (coins) non dépensées",
|
||||
"unspent_coins_title": "Pièces (coins) non dépensées",
|
||||
"unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.",
|
||||
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Menu",
|
||||
"wallet_name": "Nom du Portefeuille (Wallet)",
|
||||
"wallet_name_exists": "Un portefeuille (wallet) portant ce nom existe déjà",
|
||||
"wallet_recovery_height": "Hauteur de récupération",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Longueur de phrase secrète (seed) incorrecte",
|
||||
"wallet_seed": "Phrase secrète (seed) du portefeuille (wallet)",
|
||||
"wallet_seed_legacy": "Graine de portefeuille hérité",
|
||||
|
@ -872,4 +873,4 @@
|
|||
"you_will_get": "Convertir vers",
|
||||
"you_will_send": "Convertir depuis",
|
||||
"yy": "AA"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -836,6 +836,7 @@
|
|||
"wallet_menu": "Menu",
|
||||
"wallet_name": "Sunan walat",
|
||||
"wallet_name_exists": "Wallet mai wannan sunan ya riga ya wanzu. Da fatan za a zaɓi wani suna daban ko sake suna ɗayan walat tukuna.",
|
||||
"wallet_recovery_height": "Mai Tsaro",
|
||||
"wallet_restoration_store_incorrect_seed_length": "kalmar sirrin iri ba daidai ba",
|
||||
"wallet_seed": "kalmar sirri na walat",
|
||||
"wallet_seed_legacy": "Tallarin walat walat",
|
||||
|
|
|
@ -836,6 +836,7 @@
|
|||
"wallet_menu": "बटुआ मेनू",
|
||||
"wallet_name": "बटुए का नाम",
|
||||
"wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है",
|
||||
"wallet_recovery_height": "वसूली ऊंचाई",
|
||||
"wallet_restoration_store_incorrect_seed_length": "गलत बीज की लंबाई",
|
||||
"wallet_seed": "बटुआ का बीज",
|
||||
"wallet_seed_legacy": "विरासत बटुए बीज",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Izbornik",
|
||||
"wallet_name": "Ime novčanika",
|
||||
"wallet_name_exists": "Novčanik s tim nazivom već postoji",
|
||||
"wallet_recovery_height": "Visina oporavka",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Netočna dužina pristupnog izraza",
|
||||
"wallet_seed": "Pristupni izraz novčanika",
|
||||
"wallet_seed_legacy": "Sjeme naslijeđenog novčanika",
|
||||
|
|
|
@ -837,6 +837,7 @@
|
|||
"wallet_menu": "Menu",
|
||||
"wallet_name": "Nama Dompet",
|
||||
"wallet_name_exists": "Nama dompet sudah ada. Silakan pilih nama yang berbeda atau ganti nama dompet yang lain terlebih dahulu.",
|
||||
"wallet_recovery_height": "Tinggi pemulihan",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Panjang seed yang salah",
|
||||
"wallet_seed": "Seed dompet",
|
||||
"wallet_seed_legacy": "Biji dompet warisan",
|
||||
|
|
|
@ -837,6 +837,7 @@
|
|||
"wallet_menu": "Menù",
|
||||
"wallet_name": "Nome del Portafoglio",
|
||||
"wallet_name_exists": "Il portafoglio con quel nome è già esistito",
|
||||
"wallet_recovery_height": "Altezza di recupero",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Lunghezza seme non corretta",
|
||||
"wallet_seed": "Seme Portafoglio",
|
||||
"wallet_seed_legacy": "Seme di portafoglio legacy",
|
||||
|
|
|
@ -835,6 +835,7 @@
|
|||
"wallet_menu": "ウォレットメニュー",
|
||||
"wallet_name": "ウォレット名",
|
||||
"wallet_name_exists": "その名前のウォレットはすでに存在しています",
|
||||
"wallet_recovery_height": "回復の高さ",
|
||||
"wallet_restoration_store_incorrect_seed_length": "誤ったシード長s",
|
||||
"wallet_seed": "ウォレットシード",
|
||||
"wallet_seed_legacy": "レガシーウォレットシード",
|
||||
|
|
|
@ -835,6 +835,7 @@
|
|||
"wallet_menu": "월렛 메뉴",
|
||||
"wallet_name": "지갑 이름",
|
||||
"wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.",
|
||||
"wallet_recovery_height": "복구 높이",
|
||||
"wallet_restoration_store_incorrect_seed_length": "시드 길이가 잘못되었습니다",
|
||||
"wallet_seed": "지갑 시드",
|
||||
"wallet_seed_legacy": "레거시 지갑 시드",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "မီနူး",
|
||||
"wallet_name": "ပိုက်ဆံအိတ်နာမည",
|
||||
"wallet_name_exists": "ထိုအမည်ဖြင့် ပိုက်ဆံအိတ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ သို့မဟုတ် အခြားပိုက်ဆံအိတ်ကို ဦးစွာ အမည်ပြောင်းပါ။",
|
||||
"wallet_recovery_height": "ပြန်လည်ထူထောင်ရေးအမြင့်",
|
||||
"wallet_restoration_store_incorrect_seed_length": "မျိုးစေ့အရှည် မမှန်ပါ။",
|
||||
"wallet_seed": "ပိုက်ဆံအိတ်စေ့",
|
||||
"wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့",
|
||||
|
|
|
@ -835,6 +835,7 @@
|
|||
"wallet_menu": "Portemonnee-menu",
|
||||
"wallet_name": "Portemonnee naam",
|
||||
"wallet_name_exists": "Portemonnee met die naam bestaat al",
|
||||
"wallet_recovery_height": "Herstelhoogte",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Onjuiste zaadlengte",
|
||||
"wallet_seed": "Portemonnee zaad",
|
||||
"wallet_seed_legacy": "Legacy portemonnee zaad",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Menu portfela",
|
||||
"wallet_name": "Nazwa portfela",
|
||||
"wallet_name_exists": "Portfel o tej nazwie już istnieje",
|
||||
"wallet_recovery_height": "Wysokość odzysku",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Nieprawidłowa długość frazy seed",
|
||||
"wallet_seed": "Seed portfela",
|
||||
"wallet_seed_legacy": "Dziedziczne ziarno portfela",
|
||||
|
|
|
@ -837,6 +837,7 @@
|
|||
"wallet_menu": "Menu",
|
||||
"wallet_name": "Nome da carteira",
|
||||
"wallet_name_exists": "A carteira com esse nome já existe",
|
||||
"wallet_recovery_height": "Altura de recuperação",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Comprimento de semente incorreto",
|
||||
"wallet_seed": "Semente de carteira",
|
||||
"wallet_seed_legacy": "Semente de carteira herdada",
|
||||
|
|
|
@ -835,6 +835,7 @@
|
|||
"wallet_menu": "Меню кошелька",
|
||||
"wallet_name": "Имя кошелька",
|
||||
"wallet_name_exists": "Кошелек с таким именем уже существует",
|
||||
"wallet_recovery_height": "Высота восстановления",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Неверная длина мнемонической фразы",
|
||||
"wallet_seed": "Мнемоническая фраза кошелька",
|
||||
"wallet_seed_legacy": "Наследие семя кошелька",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "เมนู",
|
||||
"wallet_name": "ชื่อกระเป๋า",
|
||||
"wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน",
|
||||
"wallet_recovery_height": "ความสูงของการกู้คืน",
|
||||
"wallet_restoration_store_incorrect_seed_length": "ความยาวของซีดไม่ถูกต้อง",
|
||||
"wallet_seed": "ซีดของกระเป๋า",
|
||||
"wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Menu",
|
||||
"wallet_name": "Pangalan ng Wallet",
|
||||
"wallet_name_exists": "Ang isang pitaka na may pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan o palitan muna ang iba pang pitaka.",
|
||||
"wallet_recovery_height": "Taas ng pagbawi",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Maling haba ng binhi",
|
||||
"wallet_seed": "SEED ng Wallet",
|
||||
"wallet_seed_legacy": "Legacy wallet seed",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "Menü",
|
||||
"wallet_name": "Cüzdan ismi",
|
||||
"wallet_name_exists": "Bu isimde bir cüzdan zaten mevcut. Lütfen farklı bir isim seç veya önce diğer cüzdanı yeniden adlandır.",
|
||||
"wallet_recovery_height": "Kurtarma Yüksekliği",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Yanlış tohum uzunluğu",
|
||||
"wallet_seed": "Cüzdan tohumu",
|
||||
"wallet_seed_legacy": "Eski cüzdan tohumu",
|
||||
|
|
|
@ -835,6 +835,7 @@
|
|||
"wallet_menu": "Меню гаманця",
|
||||
"wallet_name": "Ім'я гаманця",
|
||||
"wallet_name_exists": "Гаманець з такою назвою вже існує",
|
||||
"wallet_recovery_height": "Висота відновлення",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Невірна довжина мнемонічної фрази",
|
||||
"wallet_seed": "Мнемонічна фраза гаманця",
|
||||
"wallet_seed_legacy": "Спадець насіння гаманця",
|
||||
|
|
|
@ -836,6 +836,7 @@
|
|||
"wallet_menu": "مینو",
|
||||
"wallet_name": "بٹوے کا نام",
|
||||
"wallet_name_exists": "اس نام کا پرس پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں یا پہلے دوسرے بٹوے کا نام تبدیل کریں۔",
|
||||
"wallet_recovery_height": "بحالی کی اونچائی",
|
||||
"wallet_restoration_store_incorrect_seed_length": "غلط بیج کی لمبائی",
|
||||
"wallet_seed": "بٹوے کا بیج",
|
||||
"wallet_seed_legacy": "میراثی پرس کا بیج",
|
||||
|
|
|
@ -835,6 +835,7 @@
|
|||
"wallet_menu": "Mẹ́nù",
|
||||
"wallet_name": "Orúkọ àpamọ́wọ́",
|
||||
"wallet_name_exists": "Ẹ ti ní àpamọ́wọ́ pẹ̀lú orúkọ̀ yẹn. Ẹ jọ̀wọ́ yàn orúkọ̀ tó yàtọ̀ tàbí pààrọ̀ orúkọ ti àpamọ́wọ́ tẹ́lẹ̀.",
|
||||
"wallet_recovery_height": "Iga Imularada",
|
||||
"wallet_restoration_store_incorrect_seed_length": "Gígùn hóró tí a máa ń lò kọ́ ni èyí",
|
||||
"wallet_seed": "Hóró àpamọ́wọ́",
|
||||
"wallet_seed_legacy": "Irugbin akole",
|
||||
|
|
|
@ -834,6 +834,7 @@
|
|||
"wallet_menu": "钱包菜单",
|
||||
"wallet_name": "钱包名称",
|
||||
"wallet_name_exists": "同名的钱包已经存在",
|
||||
"wallet_recovery_height": "恢复高度",
|
||||
"wallet_restoration_store_incorrect_seed_length": "种子长度错误",
|
||||
"wallet_seed": "钱包种子",
|
||||
"wallet_seed_legacy": "旧的钱包种子",
|
||||
|
|
|
@ -186,6 +186,7 @@ abstract class Bitcoin {
|
|||
{required String mnemonic, required Node node});
|
||||
Future<List<DerivationInfo>> getDerivationsFromMnemonic(
|
||||
{required String mnemonic, required Node node, String? passphrase});
|
||||
Map<DerivationType, List<DerivationInfo>> getElectrumDerivations();
|
||||
Future<void> setAddressType(Object wallet, dynamic option);
|
||||
ReceivePageOption getSelectedAddressType(Object wallet);
|
||||
List<ReceivePageOption> getBitcoinReceivePageOptions();
|
||||
|
@ -362,6 +363,7 @@ abstract class Monero {
|
|||
WalletCredentials createMoneroRestoreWalletFromSeedCredentials({required String name, required String password, required int height, required String mnemonic});
|
||||
WalletCredentials createMoneroNewWalletCredentials({required String name, required String language, required bool isPolyseed, String password});
|
||||
Map<String, String> getKeys(Object wallet);
|
||||
int? getRestoreHeight(Object wallet);
|
||||
Object createMoneroTransactionCreationCredentials({required List<Output> outputs, required TransactionPriority priority});
|
||||
Object createMoneroTransactionCreationCredentialsRaw({required List<OutputInfo> outputs, required TransactionPriority priority});
|
||||
String formatterMoneroAmountToString({required int amount});
|
||||
|
@ -665,6 +667,7 @@ abstract class Ethereum {
|
|||
List<Erc20Token> getERC20Currencies(WalletBase wallet);
|
||||
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token);
|
||||
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token);
|
||||
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token);
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress);
|
||||
|
||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
|
||||
|
@ -768,6 +771,7 @@ abstract class Polygon {
|
|||
List<Erc20Token> getERC20Currencies(WalletBase wallet);
|
||||
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token);
|
||||
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token);
|
||||
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token);
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress);
|
||||
|
||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
|
||||
|
|
|
@ -40,6 +40,10 @@ class SecretKey {
|
|||
SecretKey('ankrApiKey', () => ''),
|
||||
SecretKey('quantexExchangeMarkup', () => ''),
|
||||
SecretKey('seeds', () => ''),
|
||||
SecretKey('testCakePayApiKey', () => ''),
|
||||
SecretKey('cakePayApiKey', () => ''),
|
||||
SecretKey('CSRFToken', () => ''),
|
||||
SecretKey('authorization', () => ''),
|
||||
];
|
||||
|
||||
static final evmChainsSecrets = [
|
||||
|
@ -55,9 +59,10 @@ class SecretKey {
|
|||
static final nanoSecrets = [
|
||||
SecretKey('nano2ApiKey', () => ''),
|
||||
];
|
||||
|
||||
|
||||
static final tronSecrets = [
|
||||
SecretKey('tronGridApiKey', () => ''),
|
||||
SecretKey('tronNowNodesApiKey', () => ''),
|
||||
];
|
||||
|
||||
final String name;
|
||||
|
|
Loading…
Reference in a new issue