mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-19 05:58:50 +02:00
Merge branch 'main' into CAKE-320-add-Croatian-language
This commit is contained in:
@@ -4,23 +4,11 @@ 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:cake_wallet/core/sec_random_native.dart';
|
||||
|
||||
const segwit = '100';
|
||||
final wordlist = englishWordlist;
|
||||
|
||||
Uint8List randomBytes(int length, {bool secure = false}) {
|
||||
assert(length > 0);
|
||||
|
||||
final random = secure ? Random.secure() : Random();
|
||||
final ret = Uint8List(length);
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
ret[i] = random.nextInt(256);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
double logBase(num x, num base) => log(x) / log(base);
|
||||
|
||||
String mnemonicEncode(int i) {
|
||||
@@ -102,14 +90,15 @@ List<bool> prefixMatches(String source, List<String> prefixes) {
|
||||
return prefixes.map((prefix) => hx.startsWith(prefix.toLowerCase())).toList();
|
||||
}
|
||||
|
||||
String generateMnemonic({int strength = 132, String prefix = segwit}) {
|
||||
Future<String> generateMnemonic(
|
||||
{int strength = 264, String prefix = segwit}) async {
|
||||
final wordBitlen = logBase(wordlist.length, 2).ceil();
|
||||
final wordCount = strength / wordBitlen;
|
||||
final byteCount = ((wordCount * wordBitlen).ceil() / 8).ceil();
|
||||
var result = '';
|
||||
|
||||
do {
|
||||
final bytes = randomBytes(byteCount);
|
||||
final bytes = await secRandom(byteCount);
|
||||
maskBytes(bytes, strength);
|
||||
result = encode(bytes);
|
||||
} while (!prefixMatches(result, [prefix]).first);
|
||||
@@ -134,7 +123,7 @@ bool matchesAnyPrefix(String mnemonic) =>
|
||||
bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
|
||||
try {
|
||||
return matchesAnyPrefix(mnemonic);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class BitcoinMnemonicIsIncorrectException implements Exception {
|
||||
@override
|
||||
String toString() =>
|
||||
'Bitcoin mnemonic has incorrect format. Mnemonic should contain 12 words separated by space.';
|
||||
'Bitcoin mnemonic has incorrect format. Mnemonic should contain 24 words separated by space.';
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class BitcoinWalletService extends WalletService<
|
||||
type: WalletType.bitcoin, name: credentials.name);
|
||||
final wallet = BitcoinWalletBase.build(
|
||||
dirPath: dirPath,
|
||||
mnemonic: generateMnemonic(),
|
||||
mnemonic: await generateMnemonic(),
|
||||
password: credentials.password,
|
||||
name: credentials.name,
|
||||
walletInfo: credentials.walletInfo);
|
||||
@@ -47,7 +47,7 @@ class BitcoinWalletService extends WalletService<
|
||||
final walletPath = '$walletDirPath/$name';
|
||||
final walletJSONRaw = await read(path: walletPath, password: password);
|
||||
final walletInfo = walletInfoSource.values.firstWhere(
|
||||
(info) => info.id == WalletBase.idFor(name, WalletType.bitcoin),
|
||||
(info) => info.id == WalletBase.idFor(name, WalletType.bitcoin),
|
||||
orElse: () => null);
|
||||
final wallet = BitcoinWalletBase.fromJSON(
|
||||
password: password,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
const utils = const MethodChannel('com.cake_wallet/native_utils');
|
||||
|
||||
Future<Uint8List> secRandom(int count) async {
|
||||
try {
|
||||
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count});
|
||||
} on PlatformException catch (_) {
|
||||
return Uint8List.fromList([]);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
|
||||
CryptoCurrency.eos,
|
||||
CryptoCurrency.eth,
|
||||
CryptoCurrency.ltc,
|
||||
CryptoCurrency.nano,
|
||||
CryptoCurrency.trx,
|
||||
CryptoCurrency.usdt,
|
||||
CryptoCurrency.usdterc20,
|
||||
@@ -29,7 +28,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
|
||||
static const xmr = CryptoCurrency(title: 'XMR', raw: 0);
|
||||
static const ada = CryptoCurrency(title: 'ADA', raw: 1);
|
||||
static const bch = CryptoCurrency(title: 'BCH', raw: 2);
|
||||
static const bnb = CryptoCurrency(title: 'BNB', raw: 3);
|
||||
static const bnb = CryptoCurrency(title: 'BNB BEP2', raw: 3);
|
||||
static const btc = CryptoCurrency(title: 'BTC', raw: 4);
|
||||
static const dai = CryptoCurrency(title: 'DAI', raw: 5);
|
||||
static const dash = CryptoCurrency(title: 'DASH', raw: 6);
|
||||
@@ -90,7 +89,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
|
||||
return CryptoCurrency.ada;
|
||||
case 'bch':
|
||||
return CryptoCurrency.bch;
|
||||
case 'bnb':
|
||||
case 'bnbmainnet':
|
||||
return CryptoCurrency.bnb;
|
||||
case 'btc':
|
||||
return CryptoCurrency.btc;
|
||||
|
||||
@@ -16,7 +16,8 @@ class LanguageService {
|
||||
'ru': 'Русский (Russian)',
|
||||
'uk': 'Українська (Ukrainian)',
|
||||
'zh': '中文 (Chinese)',
|
||||
'hr': 'Hrvatski (Croatian)'
|
||||
'hr': 'Hrvatski (Croatian)',
|
||||
'it': 'Italiano (Italian)'
|
||||
};
|
||||
static final list = <String, String> {};
|
||||
|
||||
|
||||
@@ -48,7 +48,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
@override
|
||||
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to,
|
||||
bool isFixedRateMode}) async {
|
||||
final symbol = from.toString() + '_' + to.toString();
|
||||
final fromTitle = defineCurrencyTitle(from);
|
||||
final toTitle = defineCurrencyTitle(to);
|
||||
final symbol = fromTitle + '_' + toTitle;
|
||||
final url = isFixedRateMode
|
||||
? apiUri + _marketInfoUriSufix + _fixedRateUriSufix + apiKey
|
||||
: apiUri + _minAmountUriSufix + symbol;
|
||||
@@ -61,8 +63,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
final elemFrom = elem["from"] as String;
|
||||
final elemTo = elem["to"] as String;
|
||||
|
||||
if ((elemFrom == from.toString().toLowerCase()) &&
|
||||
(elemTo == to.toString().toLowerCase())) {
|
||||
if ((elemFrom == fromTitle) && (elemTo == toTitle)) {
|
||||
final min = elem["min"] as double;
|
||||
final max = elem["max"] as double;
|
||||
|
||||
@@ -84,9 +85,11 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
? apiUri + _transactionsUriSufix + _fixedRateUriSufix + apiKey
|
||||
: apiUri + _transactionsUriSufix + apiKey;
|
||||
final _request = request as ChangeNowRequest;
|
||||
final fromTitle = defineCurrencyTitle(_request.from);
|
||||
final toTitle = defineCurrencyTitle(_request.to);
|
||||
final body = {
|
||||
'from': _request.from.toString(),
|
||||
'to': _request.to.toString(),
|
||||
'from': fromTitle,
|
||||
'to': toTitle,
|
||||
'address': _request.address,
|
||||
'amount': _request.amount,
|
||||
'refundAddress': _request.refundAddress
|
||||
@@ -182,6 +185,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
final url = apiUri + _marketInfoUriSufix + _fixedRateUriSufix + apiKey;
|
||||
final response = await get(url);
|
||||
final responseJSON = json.decode(response.body) as List<dynamic>;
|
||||
final fromTitle = defineCurrencyTitle(from);
|
||||
final toTitle = defineCurrencyTitle(to);
|
||||
var rate = 0.0;
|
||||
var fee = 0.0;
|
||||
|
||||
@@ -189,8 +194,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
final elemFrom = elem["from"] as String;
|
||||
final elemTo = elem["to"] as String;
|
||||
|
||||
if ((elemFrom == to.toString().toLowerCase()) &&
|
||||
(elemTo == from.toString().toLowerCase())) {
|
||||
if ((elemFrom == toTitle) && (elemTo == fromTitle)) {
|
||||
rate = elem["rate"] as double;
|
||||
fee = elem["minerFee"] as double;
|
||||
break;
|
||||
@@ -216,22 +220,32 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
CryptoCurrency to,
|
||||
double amount,
|
||||
bool isFixedRateMode) {
|
||||
final fromTitle = defineCurrencyTitle(from);
|
||||
final toTitle = defineCurrencyTitle(to);
|
||||
|
||||
return isFixedRateMode
|
||||
? apiUri +
|
||||
_exchangeAmountUriSufix +
|
||||
_fixedRateUriSufix +
|
||||
amount.toString() +
|
||||
'/' +
|
||||
from.toString() +
|
||||
fromTitle +
|
||||
'_' +
|
||||
to.toString() +
|
||||
toTitle +
|
||||
'?api_key=' + apiKey
|
||||
: apiUri +
|
||||
_exchangeAmountUriSufix +
|
||||
amount.toString() +
|
||||
'/' +
|
||||
from.toString() +
|
||||
fromTitle +
|
||||
'_' +
|
||||
to.toString();
|
||||
toTitle;
|
||||
}
|
||||
|
||||
static String defineCurrencyTitle(CryptoCurrency currency) {
|
||||
const bnbTitle = 'bnbmainnet';
|
||||
final currencyTitle = currency == CryptoCurrency.bnb
|
||||
? bnbTitle : currency.title.toLowerCase();
|
||||
return currencyTitle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ class MoneroWalletService extends WalletService<
|
||||
final name = f.path.split('/').last;
|
||||
final newPath = newWalletDirPath + '/$name';
|
||||
final newFile = File(newPath);
|
||||
print(file.path);
|
||||
|
||||
if (!newFile.existsSync()) {
|
||||
newFile.createSync();
|
||||
}
|
||||
|
||||
+5
-3
@@ -237,9 +237,11 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||
case Routes.unlock:
|
||||
return MaterialPageRoute<void>(
|
||||
fullscreenDialog: true,
|
||||
builder: (_) => getIt.get<AuthPage>(
|
||||
param1: settings.arguments as OnAuthenticationFinished,
|
||||
param2: false));
|
||||
builder: (_) => WillPopScope(
|
||||
child: getIt.get<AuthPage>(
|
||||
param1: settings.arguments as OnAuthenticationFinished,
|
||||
param2: false),
|
||||
onWillPop: () async => false));
|
||||
|
||||
case Routes.nodeList:
|
||||
return CupertinoPageRoute<void>(
|
||||
|
||||
@@ -13,7 +13,7 @@ class PreSeedPage extends BasePage {
|
||||
imageDark = Image.asset('assets/images/pre_seed_dark.png'),
|
||||
wordsCount = type == WalletType.monero
|
||||
? 25
|
||||
: 12; // FIXME: Stupid fast implementation
|
||||
: 24; // FIXME: Stupid fast implementation
|
||||
|
||||
final Image imageDark;
|
||||
final Image imageLight;
|
||||
@@ -49,7 +49,9 @@ class PreSeedPage extends BasePage {
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 70, left: 16, right: 16),
|
||||
child: Text(
|
||||
S.of(context).pre_seed_description(wordsCount.toString()),
|
||||
S
|
||||
.of(context)
|
||||
.pre_seed_description(wordsCount.toString()),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
|
||||
@@ -110,8 +110,6 @@ abstract class AuthViewModelBase with Store {
|
||||
|
||||
if (isAuthenticated) {
|
||||
state = ExecutedSuccessfullyState();
|
||||
} else {
|
||||
state = FailureState('Failure biometric authentication');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
|
||||
@@ -59,7 +59,8 @@ abstract class ExchangeViewModelBase with Store {
|
||||
});
|
||||
receiveCurrencies = CryptoCurrency.all.where((cryptoCurrency) =>
|
||||
(cryptoCurrency != CryptoCurrency.xlm)&&
|
||||
(cryptoCurrency != CryptoCurrency.xrp)).toList();
|
||||
(cryptoCurrency != CryptoCurrency.xrp)&&
|
||||
(cryptoCurrency != CryptoCurrency.bnb)).toList();
|
||||
_defineIsReceiveAmountEditable();
|
||||
isFixedRateMode = false;
|
||||
isReceiveAmountEntered = false;
|
||||
|
||||
Reference in New Issue
Block a user