Merge branch 'main' of https://github.com/cake-tech/cake_wallet into bitcoin-derivations

This commit is contained in:
fosse 2023-10-09 11:39:54 -04:00
commit d4c8a1d8f6
34 changed files with 190 additions and 599 deletions

View file

@ -128,7 +128,6 @@ jobs:
echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart
echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart
echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
echo "const robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1,3 +1,3 @@
Fix 2FA code issue
Support getting Addresses from ENS and Mastodon
Bug fixes
Minor enhancements

View file

@ -1,4 +1,5 @@
Ethereum enhancements and bug fixes
Fix 2FA code issue
Add Nano wallet
Add WalletConnect to connect your ETH wallet with your favorite dApp
Support getting Addresses from ENS and Mastodon
Bug fixes
Minor enhancements

View file

@ -13,6 +13,11 @@ class NanoClient {
static const String DEFAULT_REPRESENTATIVE =
"nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579";
static const Map<String, String> CAKE_HEADERS = {
"Content-Type": "application/json",
"nano-app": "cake-wallet"
};
Node? _node;
Node? _powNode;
@ -37,7 +42,7 @@ class NanoClient {
Future<NanoBalance> getBalance(String address) async {
final response = await http.post(
_node!.uri,
headers: {"Content-Type": "application/json"},
headers: CAKE_HEADERS,
body: jsonEncode(
{
"action": "account_balance",
@ -57,7 +62,7 @@ class NanoClient {
try {
final response = await http.post(
_node!.uri,
headers: {"Content-Type": "application/json"},
headers: CAKE_HEADERS,
body: jsonEncode(
{
"action": "account_info",
@ -123,7 +128,7 @@ class NanoClient {
Future<String> requestWork(String hash) async {
final response = await http.post(
_powNode!.uri,
headers: {'Content-type': 'application/json'},
headers: CAKE_HEADERS,
body: json.encode(
{
"action": "work_generate",
@ -157,7 +162,6 @@ class NanoClient {
}
Future<String> processBlock(Map<String, String> block, String subtype) async {
final headers = {"Content-Type": "application/json"};
final processBody = jsonEncode({
"action": "process",
"json_block": "true",
@ -167,7 +171,7 @@ class NanoClient {
final processResponse = await http.post(
_node!.uri,
headers: headers,
headers: CAKE_HEADERS,
body: processBody,
);
@ -260,10 +264,6 @@ class NanoClient {
}) async {
bool openBlock = false;
final headers = {
"Content-Type": "application/json",
};
// first check if the account is open:
// get the account info (we need the frontier and representative):
AccountInfoResponse? infoData = await getAccountInfo(destinationAddress);
@ -335,7 +335,7 @@ class NanoClient {
});
final processResponse = await http.post(
_node!.uri,
headers: headers,
headers: CAKE_HEADERS,
body: processBody,
);
@ -351,7 +351,7 @@ class NanoClient {
required String privateKey,
}) async {
final receivableResponse = await http.post(_node!.uri,
headers: {"Content-Type": "application/json"},
headers: CAKE_HEADERS,
body: jsonEncode({
"action": "receivable",
"account": destinationAddress,
@ -401,7 +401,7 @@ class NanoClient {
Future<List<NanoTransactionModel>> fetchTransactions(String address) async {
try {
final response = await http.post(_node!.uri,
headers: {"Content-Type": "application/json"},
headers: CAKE_HEADERS,
body: jsonEncode({
"action": "account_history",
"account": address,

View file

@ -267,6 +267,10 @@ class AddressValidator extends TextValidator {
'|([^0-9a-zA-Z]|^)ltc[a-zA-Z0-9]{26,45}([^0-9a-zA-Z]|\$)';
case CryptoCurrency.eth:
return '0x[0-9a-zA-Z]{42}';
case CryptoCurrency.nano:
return 'nano_[0-9a-zA-Z]{60}';
case CryptoCurrency.banano:
return 'ban_[0-9a-zA-Z]{60}';
default:
return null;
}

View file

@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
@ -308,7 +309,7 @@ class BackupService {
if (currentPinLength != null)
await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength);
if (currentTheme != null)
if (currentTheme != null && DeviceInfo.instance.isMobile)
await _sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme);
if (exchangeStatus != null)

View file

@ -417,10 +417,6 @@ Future<void> setup({
}
if (appStore.wallet != null) {
authStore.allowed();
if (appStore.wallet!.type == WalletType.ethereum) {
getIt.get<Web3WalletService>().init();
}
return;
}
@ -441,10 +437,6 @@ Future<void> setup({
} else {
if (appStore.wallet != null) {
authStore.allowed();
if (appStore.wallet!.type == WalletType.ethereum) {
getIt.get<Web3WalletService>().init();
}
return;
}

View file

@ -6,6 +6,7 @@ class Cake2FAPresetsOptions extends EnumerableItem<int> with Serializable<int> {
static const narrow = Cake2FAPresetsOptions(title: 'Narrow', raw: 0);
static const normal = Cake2FAPresetsOptions(title: 'Normal', raw: 1);
static const aggressive = Cake2FAPresetsOptions(title: 'Aggressive', raw: 2);
static const none = Cake2FAPresetsOptions(title: 'None', raw: 3);
static Cake2FAPresetsOptions deserialize({required int raw}) {
switch (raw) {
@ -15,6 +16,8 @@ class Cake2FAPresetsOptions extends EnumerableItem<int> with Serializable<int> {
return Cake2FAPresetsOptions.normal;
case 2:
return Cake2FAPresetsOptions.aggressive;
case 3:
return Cake2FAPresetsOptions.none;
default:
throw Exception(
'Incorrect Cake 2FA Preset $raw for Cake2FAPresetOptions deserialize',

View file

@ -24,10 +24,7 @@ class ExchangeProviderDescription extends EnumerableItem<int> with Serializable<
static const trocador =
ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/images/trocador.png');
static const exolix =
ExchangeProviderDescription(title: 'Exolix', raw: 6, image: 'assets/images/exolix.png');
static const all = ExchangeProviderDescription(title: 'All trades', raw: 7, image: '');
static const all = ExchangeProviderDescription(title: 'All trades', raw: 6, image: '');
static ExchangeProviderDescription deserialize({required int raw}) {
switch (raw) {
@ -44,8 +41,6 @@ class ExchangeProviderDescription extends EnumerableItem<int> with Serializable<
case 5:
return trocador;
case 6:
return exolix;
case 7:
return all;
default:
throw Exception('Unexpected token: $raw for ExchangeProviderDescription deserialize');

View file

@ -1,294 +0,0 @@
import 'dart:convert';
import 'package:cake_wallet/exchange/trade_not_found_exeption.dart';
import 'package:http/http.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/exchange/exchange_pair.dart';
import 'package:cake_wallet/exchange/exchange_provider.dart';
import 'package:cake_wallet/exchange/limits.dart';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart';
import 'package:cake_wallet/exchange/exolix/exolix_request.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
class ExolixExchangeProvider extends ExchangeProvider {
ExolixExchangeProvider() : super(pairList: _supportedPairs());
static final apiKey = secrets.exolixApiKey;
static const apiBaseUrl = 'exolix.com';
static const transactionsPath = '/api/v2/transactions';
static const ratePath = '/api/v2/rate';
static const List<CryptoCurrency> _notSupported = [
CryptoCurrency.usdt,
CryptoCurrency.xhv,
CryptoCurrency.btt,
CryptoCurrency.firo,
CryptoCurrency.zaddr,
CryptoCurrency.xvg,
CryptoCurrency.kmd,
CryptoCurrency.paxg,
CryptoCurrency.rune,
CryptoCurrency.scrt,
CryptoCurrency.btcln,
CryptoCurrency.cro,
CryptoCurrency.ftm,
CryptoCurrency.frax,
CryptoCurrency.gusd,
CryptoCurrency.gtc,
CryptoCurrency.weth,
];
static List<ExchangePair> _supportedPairs() {
final supportedCurrencies =
CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList();
return supportedCurrencies
.map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true)))
.expand((i) => i)
.toList();
}
@override
String get title => 'Exolix';
@override
bool get isAvailable => true;
@override
bool get isEnabled => true;
@override
bool get supportsFixedRate => true;
@override
ExchangeProviderDescription get description => ExchangeProviderDescription.exolix;
@override
Future<bool> checkIsAvailable() async => true;
static String getRateType(bool isFixedRate) => isFixedRate ? 'fixed' : 'float';
@override
Future<Limits> fetchLimits(
{required CryptoCurrency from,
required CryptoCurrency to,
required bool isFixedRateMode}) async {
final params = <String, String>{
'rateType': getRateType(isFixedRateMode),
'amount': '1',
};
if (isFixedRateMode) {
params['coinFrom'] = _normalizeCurrency(to);
params['coinTo'] = _normalizeCurrency(from);
params['networkFrom'] = _networkFor(to);
params['networkTo'] = _networkFor(from);
} else {
params['coinFrom'] = _normalizeCurrency(from);
params['coinTo'] = _normalizeCurrency(to);
params['networkFrom'] = _networkFor(from);
params['networkTo'] = _networkFor(to);
}
final uri = Uri.https(apiBaseUrl, ratePath, params);
final response = await get(uri);
if (response.statusCode != 200) {
throw Exception('Unexpected http status: ${response.statusCode}');
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
return Limits(min: responseJSON['minAmount'] as double?);
}
@override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
final _request = request as ExolixRequest;
final headers = {'Content-Type': 'application/json'};
final body = <String, dynamic>{
'coinFrom': _normalizeCurrency(_request.from),
'coinTo': _normalizeCurrency(_request.to),
'networkFrom': _networkFor(_request.from),
'networkTo': _networkFor(_request.to),
'withdrawalAddress': _request.address,
'refundAddress': _request.refundAddress,
'rateType': getRateType(isFixedRateMode),
'apiToken': apiKey,
};
if (isFixedRateMode) {
body['withdrawalAmount'] = _request.toAmount;
} else {
body['amount'] = _request.fromAmount;
}
final uri = Uri.https(apiBaseUrl, transactionsPath);
final response = await post(uri, headers: headers, body: json.encode(body));
if (response.statusCode == 400) {
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final errors = responseJSON['errors'] as Map<String, String>;
final errorMessage = errors.values.join(', ');
throw Exception(errorMessage);
}
if (response.statusCode != 200 && response.statusCode != 201) {
throw Exception('Unexpected http status: ${response.statusCode}');
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final id = responseJSON['id'] as String;
final inputAddress = responseJSON['depositAddress'] as String;
final refundAddress = responseJSON['refundAddress'] as String?;
final extraId = responseJSON['depositExtraId'] as String?;
final payoutAddress = responseJSON['withdrawalAddress'] as String;
final amount = responseJSON['amount'].toString();
return Trade(
id: id,
from: _request.from,
to: _request.to,
provider: description,
inputAddress: inputAddress,
refundAddress: refundAddress,
extraId: extraId,
createdAt: DateTime.now(),
amount: amount,
state: TradeState.created,
payoutAddress: payoutAddress);
}
@override
Future<Trade> findTradeById({required String id}) async {
final findTradeByIdPath = transactionsPath + '/$id';
final uri = Uri.https(apiBaseUrl, findTradeByIdPath);
final response = await get(uri);
if (response.statusCode == 404) {
throw TradeNotFoundException(id, provider: description);
}
if (response.statusCode == 400) {
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final errors = responseJSON['errors'] as Map<String, String>;
final errorMessage = errors.values.join(', ');
throw TradeNotFoundException(id, provider: description, description: errorMessage);
}
if (response.statusCode != 200) {
throw Exception('Unexpected http status: ${response.statusCode}');
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final coinFrom = responseJSON['coinFrom']['coinCode'] as String;
final from = CryptoCurrency.fromString(coinFrom);
final coinTo = responseJSON['coinTo']['coinCode'] as String;
final to = CryptoCurrency.fromString(coinTo);
final inputAddress = responseJSON['depositAddress'] as String;
final amount = responseJSON['amount'].toString();
final status = responseJSON['status'] as String;
final state = TradeState.deserialize(raw: _prepareStatus(status));
final extraId = responseJSON['depositExtraId'] as String?;
final outputTransaction = responseJSON['hashOut']['hash'] as String?;
final payoutAddress = responseJSON['withdrawalAddress'] as String;
return Trade(
id: id,
from: from,
to: to,
provider: description,
inputAddress: inputAddress,
amount: amount,
state: state,
extraId: extraId,
outputTransaction: outputTransaction,
payoutAddress: payoutAddress);
}
@override
Future<double> fetchRate(
{required CryptoCurrency from,
required CryptoCurrency to,
required double amount,
required bool isFixedRateMode,
required bool isReceiveAmount}) async {
try {
if (amount == 0) {
return 0.0;
}
final params = <String, String>{
'coinFrom': _normalizeCurrency(from),
'coinTo': _normalizeCurrency(to),
'networkFrom': _networkFor(from),
'networkTo': _networkFor(to),
'rateType': getRateType(isFixedRateMode),
};
if (isReceiveAmount) {
params['withdrawalAmount'] = amount.toString();
} else {
params['amount'] = amount.toString();
}
final uri = Uri.https(apiBaseUrl, ratePath, params);
final response = await get(uri);
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
if (response.statusCode != 200) {
final message = responseJSON['message'] as String?;
throw Exception(message);
}
final rate = responseJSON['rate'] as double;
return rate;
} catch (e) {
print(e.toString());
return 0.0;
}
}
String _prepareStatus(String status) {
switch (status) {
case 'deleted':
case 'error':
return 'overdue';
default:
return status;
}
}
String _networkFor(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.arb:
return 'ARBITRUM';
default:
return currency.tag != null ? _normalizeTag(currency.tag!) : currency.title;
}
}
String _normalizeCurrency(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.nano:
return 'XNO';
case CryptoCurrency.bttc:
return 'BTT';
case CryptoCurrency.zec:
return 'ZEC';
default:
return currency.title;
}
}
String _normalizeTag(String tag) {
switch (tag) {
case 'POLY':
return 'Polygon';
default:
return tag;
}
}
}

View file

@ -1,20 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
class ExolixRequest extends TradeRequest {
ExolixRequest(
{required this.from,
required this.to,
required this.address,
required this.fromAmount,
required this.toAmount,
required this.refundAddress});
CryptoCurrency from;
CryptoCurrency to;
String address;
String fromAmount;
String toAmount;
String refundAddress;
}

View file

@ -35,15 +35,6 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
static const completed = TradeState(raw: 'completed', title: 'Completed');
static const settling = TradeState(raw: 'settling', title: 'Settlement in progress');
static const settled = TradeState(raw: 'settled', title: 'Settlement completed');
static const wait = TradeState(raw: 'wait', title: 'Waiting');
static const overdue = TradeState(raw: 'overdue', title: 'Overdue');
static const refund = TradeState(raw: 'refund', title: 'Refund');
static const refunded = TradeState(raw: 'refunded', title: 'Refunded');
static const confirmation = TradeState(raw: 'confirmation', title: 'Confirmation');
static const confirmed = TradeState(raw: 'confirmed', title: 'Confirmed');
static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging');
static const sending = TradeState(raw: 'sending', title: 'Sending');
static const success = TradeState(raw: 'success', title: 'Success');
static TradeState deserialize({required String raw}) {
switch (raw) {
case 'pending':
@ -86,24 +77,6 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
return failed;
case 'completed':
return completed;
case 'wait':
return wait;
case 'overdue':
return overdue;
case 'refund':
return refund;
case 'refunded':
return refunded;
case 'confirmation':
return confirmation;
case 'confirmed':
return confirmed;
case 'exchanging':
return exchanging;
case 'sending':
return sending;
case 'success':
return success;
default:
throw Exception('Unexpected token: $raw in TradeState deserialize');
}

View file

@ -178,6 +178,11 @@ class CWNano extends Nano {
BigInt getTransactionAmountRaw(TransactionInfo transactionInfo) {
return (transactionInfo as NanoTransactionInfo).amountRaw;
}
@override
String getRepresentative(Object wallet) {
return (wallet as NanoWallet).representative;
}
}
class CWNanoUtil extends NanoUtil {
@ -308,14 +313,19 @@ class CWNanoUtil extends NanoUtil {
/// @param raw 100000000000000000000000000000
/// @return Decimal value 1.000000000000000000000000000000
///
@override
Decimal getRawAsDecimal(String? raw, BigInt? rawPerCur) {
Decimal _getRawAsDecimal(String? raw, BigInt? rawPerCur) {
rawPerCur ??= rawPerNano;
final Decimal amount = Decimal.parse(raw.toString());
final Decimal result = (amount / Decimal.parse(rawPerCur.toString())).toDecimal();
return result;
}
@override
String getRawAsDecimalString(String? raw, BigInt? rawPerCur) {
final Decimal result = _getRawAsDecimal(raw, rawPerCur);
return result.toString();
}
@override
String truncateDecimal(Decimal input, {int digits = maxDecimalDigits}) {
Decimal bigger = input.shift(digits);
@ -332,7 +342,7 @@ class CWNanoUtil extends NanoUtil {
@override
String getRawAsUsableString(String? raw, BigInt rawPerCur) {
final String res =
truncateDecimal(getRawAsDecimal(raw, rawPerCur), digits: maxDecimalDigits + 9);
truncateDecimal(_getRawAsDecimal(raw, rawPerCur), digits: maxDecimalDigits + 9);
if (raw == null || raw == "0" || raw == "00000000000000000000000000000000") {
return "0";
@ -361,7 +371,7 @@ class CWNanoUtil extends NanoUtil {
@override
String getRawAccuracy(String? raw, BigInt rawPerCur) {
final String rawString = getRawAsUsableString(raw, rawPerCur);
final String rawDecimalString = getRawAsDecimal(raw, rawPerCur).toString();
final String rawDecimalString = _getRawAsDecimal(raw, rawPerCur).toString();
if (raw == null || raw.isEmpty || raw == "0") {
return "";

View file

@ -94,9 +94,6 @@ class TradeRow extends StatelessWidget {
borderRadius: BorderRadius.circular(50),
child: Image.asset('assets/images/trocador.png', width: 36, height: 36));
break;
case ExchangeProviderDescription.exolix:
image = Image.asset('assets/images/exolix.png', width: 36, height: 36);
break;
default:
image = null;
}

View file

@ -6,7 +6,6 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_nano/nano_wallet.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:cake_wallet/generated/i18n.dart';
@ -18,7 +17,7 @@ class NanoChangeRepPage extends BasePage {
NanoChangeRepPage(WalletBase wallet)
: _wallet = wallet,
_addressController = TextEditingController() {
_addressController.text = (wallet as NanoWallet).representative;
_addressController.text = nano!.getRepresentative(wallet);
}
final TextEditingController _addressController;

View file

@ -85,7 +85,7 @@ class ConnectionSyncPage extends BasePage {
);
},
),
if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[
if (dashboardViewModel.wallet.type == WalletType.ethereum && DeviceInfo.instance.isMobile) ...[
WalletConnectTile(
onTap: () async {
Navigator.of(context).push(

View file

@ -1,5 +1,8 @@
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/utils/exception_handler.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/wallet_base.dart';
@ -40,5 +43,9 @@ abstract class AppStoreBase with Store {
this.wallet?.close();
this.wallet = wallet;
this.wallet!.setExceptionHandler(ExceptionHandler.onError);
if (wallet.type == WalletType.ethereum) {
getIt.get<Web3WalletService>().init();
}
}
}

View file

@ -13,8 +13,7 @@ abstract class TradeFilterStoreBase with Store {
displaySideShift = true,
displayMorphToken = true,
displaySimpleSwap = true,
displayTrocador = true,
displayExolix = true;
displayTrocador = true;
@observable
bool displayXMRTO;
@ -34,11 +33,8 @@ abstract class TradeFilterStoreBase with Store {
@observable
bool displayTrocador;
@observable
bool displayExolix;
@computed
bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador && displayExolix;
bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador;
@action
void toggleDisplayExchange(ExchangeProviderDescription provider) {
@ -60,10 +56,7 @@ abstract class TradeFilterStoreBase with Store {
break;
case ExchangeProviderDescription.trocador:
displayTrocador = !displayTrocador;
break;
case ExchangeProviderDescription.exolix:
displayExolix = !displayExolix;
break;
break;
case ExchangeProviderDescription.all:
if (displayAllTrades) {
displayChangeNow = false;
@ -72,7 +65,6 @@ abstract class TradeFilterStoreBase with Store {
displayMorphToken = false;
displaySimpleSwap = false;
displayTrocador = false;
displayExolix = false;
} else {
displayChangeNow = true;
displaySideShift = true;
@ -80,7 +72,6 @@ abstract class TradeFilterStoreBase with Store {
displayMorphToken = true;
displaySimpleSwap = true;
displayTrocador = true;
displayExolix = true;
}
break;
}
@ -107,8 +98,7 @@ abstract class TradeFilterStoreBase with Store {
||(displaySimpleSwap &&
item.trade.provider ==
ExchangeProviderDescription.simpleSwap)
||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador)
||(displayExolix && item.trade.provider == ExchangeProviderDescription.exolix))
||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador))
.toList()
: _trades;
}

View file

@ -98,11 +98,6 @@ abstract class DashboardViewModelBase with Store {
caption: ExchangeProviderDescription.trocador.title,
onChanged: () => tradeFilterStore
.toggleDisplayExchange(ExchangeProviderDescription.trocador)),
FilterItem(
value: () => tradeFilterStore.displayExolix,
caption: ExchangeProviderDescription.exolix.title,
onChanged: () => tradeFilterStore
.toggleDisplayExchange(ExchangeProviderDescription.exolix)),
]
},
subname = '',

View file

@ -92,10 +92,8 @@ class TransactionListItem extends ActionListItem with Keyable {
break;
case WalletType.nano:
amount = calculateFiatAmountRaw(
cryptoAmount: nanoUtil!
.getRawAsDecimal(
nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano)
.toDouble(),
cryptoAmount: double.parse(nanoUtil!.getRawAsDecimalString(
nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano)),
price: price);
break;
case WalletType.ethereum:

View file

@ -1,5 +1,4 @@
import 'dart:async';
import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart';
import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart';
import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart';
import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart';
@ -54,9 +53,6 @@ abstract class ExchangeTradeViewModelBase with Store {
case ExchangeProviderDescription.trocador:
_provider = TrocadorExchangeProvider();
break;
case ExchangeProviderDescription.exolix:
_provider = ExolixExchangeProvider();
break;
}
_updateItems();

View file

@ -6,8 +6,6 @@ import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/wallet_contact.dart';
import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart';
import 'package:cake_wallet/exchange/exolix/exolix_request.dart';
import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart';
import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart';
import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart';
@ -152,7 +150,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
SideShiftExchangeProvider(),
SimpleSwapExchangeProvider(),
TrocadorExchangeProvider(useTorOnly: _useTorOnly),
ExolixExchangeProvider(),
];
@observable
@ -549,17 +546,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
amount = isFixedRateMode ? receiveAmount : depositAmount;
}
if (provider is ExolixExchangeProvider) {
request = ExolixRequest(
from: depositCurrency,
to: receiveCurrency,
fromAmount: depositAmount.replaceAll(',', '.'),
toAmount: receiveAmount.replaceAll(',', '.'),
refundAddress: depositAddress,
address: receiveAddress);
amount = isFixedRateMode ? receiveAmount : depositAmount;
}
amount = amount.replaceAll(',', '.');
if (limitsState is LimitsLoadedSuccessfully) {

View file

@ -278,7 +278,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
List<bool> conditionsList = [];
for (var output in outputs) {
final show = checkThroughChecksToDisplayTOTP(output.address);
final show = checkThroughChecksToDisplayTOTP(output.extractedAddress);
conditionsList.add(show);
}
@ -427,9 +428,14 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
}
String translateErrorMessage(String error, WalletType walletType, CryptoCurrency currency,) {
String translateErrorMessage(
String error,
WalletType walletType,
CryptoCurrency currency,
) {
if (walletType == WalletType.ethereum || walletType == WalletType.haven) {
if (error.contains('gas required exceeds allowance') || error.contains('insufficient funds for')) {
if (error.contains('gas required exceeds allowance') ||
error.contains('insufficient funds for')) {
return S.current.do_not_have_enough_gas_asset(currency.toString());
}
}

View file

@ -201,38 +201,15 @@ abstract class Setup2FAViewModelBase with Store {
@observable
ObservableList<VerboseControlSettings> selected2FASettings;
//! The code here works, but can be improved
//! Still trying out various ways to improve it
@action
void selectCakePreset(Cake2FAPresetsOptions cake2FAPreset) {
// The tabs are ordered in the format [Narrow || Normal || Verbose]
// Where Narrow = 0, Normal = 1 and Verbose = 2
switch (cake2FAPreset) {
case Cake2FAPresetsOptions.narrow:
activateCake2FANarrowPreset();
break;
case Cake2FAPresetsOptions.normal:
activateCake2FANormalPreset();
break;
case Cake2FAPresetsOptions.aggressive:
activateCake2FAAggressivePreset();
break;
default:
activateCake2FANormalPreset();
}
}
@action
void checkIfTheCurrentSettingMatchesAnyOfThePresets() {
final hasNormalPreset = checkIfTheNormalPresetIsPresent();
final hasNarrowPreset = checkIfTheNarrowPresetIsPresent();
final hasVerbosePreset = checkIfTheVerbosePresetIsPresent();
if (hasNormalPreset || hasNarrowPreset || hasVerbosePreset) {
unhighlightTabs = false;
} else {
unhighlightTabs = true;
}
if (hasNormalPreset || hasNarrowPreset || hasVerbosePreset) return;
noCake2FAPresetSelected();
}
@action
@ -288,32 +265,8 @@ abstract class Setup2FAViewModelBase with Store {
}
@action
void activateCake2FANormalPreset() {
_settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.normal;
setAllControlsToFalse();
switchShouldRequireTOTP2FAForSendsToNonContact(true);
switchShouldRequireTOTP2FAForSendsToContact(true);
switchShouldRequireTOTP2FAForSendsToInternalWallets(true);
switchShouldRequireTOTP2FAForExchangesToInternalWallets(true);
switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(true);
}
@action
void activateCake2FANarrowPreset() {
_settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.narrow;
setAllControlsToFalse();
switchShouldRequireTOTP2FAForSendsToNonContact(true);
switchShouldRequireTOTP2FAForAddingContacts(true);
switchShouldRequireTOTP2FAForCreatingNewWallet(true);
switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(true);
}
@action
void activateCake2FAAggressivePreset() {
_settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.aggressive;
setAllControlsToFalse();
switchShouldRequireTOTP2FAForAccessingWallet(true);
switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(true);
void noCake2FAPresetSelected() {
_settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.none;
}
@action
@ -330,90 +283,106 @@ abstract class Setup2FAViewModelBase with Store {
unhighlightTabs = false;
}
final Map<Cake2FAPresetsOptions, List<VerboseControlSettings>> presetsMap = {
Cake2FAPresetsOptions.normal: [
VerboseControlSettings.sendsToContacts,
VerboseControlSettings.sendsToNonContacts,
VerboseControlSettings.sendsToInternalWallets,
VerboseControlSettings.securityAndBackupSettings,
VerboseControlSettings.exchangesToInternalWallets
],
Cake2FAPresetsOptions.narrow: [
VerboseControlSettings.addingContacts,
VerboseControlSettings.sendsToNonContacts,
VerboseControlSettings.creatingNewWallets,
VerboseControlSettings.securityAndBackupSettings,
],
Cake2FAPresetsOptions.aggressive: [
VerboseControlSettings.accessWallet,
VerboseControlSettings.securityAndBackupSettings,
],
Cake2FAPresetsOptions.none: [],
};
@action
void switchShouldRequireTOTP2FAForAccessingWallet(bool value) {
_settingsStore.shouldRequireTOTP2FAForAccessingWallet = value;
if (value) {
selected2FASettings.add(VerboseControlSettings.accessWallet);
} else {
selected2FASettings.remove(VerboseControlSettings.accessWallet);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
void selectCakePreset(Cake2FAPresetsOptions preset) {
presetsMap[preset]?.forEach(toggleControl);
_settingsStore.selectedCake2FAPreset = preset;
}
@action
void toggleControl(VerboseControlSettings control, [bool value = true]) {
final methodsMap = {
VerboseControlSettings.sendsToContacts: switchShouldRequireTOTP2FAForSendsToContact,
VerboseControlSettings.accessWallet: switchShouldRequireTOTP2FAForAccessingWallet,
VerboseControlSettings.addingContacts: switchShouldRequireTOTP2FAForAddingContacts,
VerboseControlSettings.creatingNewWallets: switchShouldRequireTOTP2FAForCreatingNewWallet,
VerboseControlSettings.sendsToNonContacts: switchShouldRequireTOTP2FAForSendsToNonContact,
VerboseControlSettings.sendsToInternalWallets:
switchShouldRequireTOTP2FAForSendsToInternalWallets,
VerboseControlSettings.securityAndBackupSettings:
switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
VerboseControlSettings.exchangesToInternalWallets:
switchShouldRequireTOTP2FAForExchangesToInternalWallets,
};
methodsMap[control]?.call(value);
}
@action
void switchShouldRequireTOTP2FAForSendsToContact(bool value) {
_settingsStore.shouldRequireTOTP2FAForSendsToContact = value;
if (value) {
selected2FASettings.add(VerboseControlSettings.sendsToContacts);
} else {
selected2FASettings.remove(VerboseControlSettings.sendsToContacts);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
updateSelectedSettings(VerboseControlSettings.sendsToContacts, value);
}
@action
void switchShouldRequireTOTP2FAForAccessingWallet(bool value) {
_settingsStore.shouldRequireTOTP2FAForAccessingWallet = value;
updateSelectedSettings(VerboseControlSettings.accessWallet, value);
}
@action
void switchShouldRequireTOTP2FAForSendsToNonContact(bool value) {
_settingsStore.shouldRequireTOTP2FAForSendsToNonContact = value;
if (value) {
selected2FASettings.add(VerboseControlSettings.sendsToNonContacts);
} else {
selected2FASettings.remove(VerboseControlSettings.sendsToNonContacts);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
updateSelectedSettings(VerboseControlSettings.sendsToNonContacts, value);
}
@action
void switchShouldRequireTOTP2FAForSendsToInternalWallets(bool value) {
_settingsStore.shouldRequireTOTP2FAForSendsToInternalWallets = value;
if (value) {
selected2FASettings.add(VerboseControlSettings.sendsToInternalWallets);
} else {
selected2FASettings.remove(VerboseControlSettings.sendsToInternalWallets);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
updateSelectedSettings(VerboseControlSettings.sendsToInternalWallets, value);
}
@action
void switchShouldRequireTOTP2FAForExchangesToInternalWallets(bool value) {
_settingsStore.shouldRequireTOTP2FAForExchangesToInternalWallets = value;
if (value) {
selected2FASettings.add(VerboseControlSettings.exchangesToInternalWallets);
} else {
selected2FASettings.remove(VerboseControlSettings.exchangesToInternalWallets);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
updateSelectedSettings(VerboseControlSettings.exchangesToInternalWallets, value);
}
@action
void switchShouldRequireTOTP2FAForAddingContacts(bool value) {
_settingsStore.shouldRequireTOTP2FAForAddingContacts = value;
if (value)
selected2FASettings.add(VerboseControlSettings.addingContacts);
else {
selected2FASettings.remove(VerboseControlSettings.addingContacts);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
updateSelectedSettings(VerboseControlSettings.addingContacts, value);
}
@action
void switchShouldRequireTOTP2FAForCreatingNewWallet(bool value) {
_settingsStore.shouldRequireTOTP2FAForCreatingNewWallets = value;
if (value) {
selected2FASettings.add(VerboseControlSettings.creatingNewWallets);
} else {
selected2FASettings.remove(VerboseControlSettings.creatingNewWallets);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
updateSelectedSettings(VerboseControlSettings.creatingNewWallets, value);
}
@action
void switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(bool value) {
_settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings = value;
if (value)
selected2FASettings.add(VerboseControlSettings.securityAndBackupSettings);
else {
selected2FASettings.remove(VerboseControlSettings.securityAndBackupSettings);
updateSelectedSettings(VerboseControlSettings.securityAndBackupSettings, value);
}
@action
void updateSelectedSettings(VerboseControlSettings control, bool value) {
if (value) {
selected2FASettings.add(control);
} else {
selected2FASettings.remove(control);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
}

View file

@ -53,11 +53,6 @@ abstract class SupportViewModelBase with Store {
icon: 'assets/images/simpleSwap.png',
linkTitle: 'support@simpleswap.io',
link: 'mailto:support@simpleswap.io'),
LinkListItem(
title: 'Exolix',
icon: 'assets/images/exolix.png',
linkTitle: 'support@exolix.com',
link: 'mailto:support@exolix.com'),
if (!isMoneroOnly) ... [
LinkListItem(
title: 'Wyre',

View file

@ -2,7 +2,6 @@ import 'dart:async';
import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart';
import 'package:cake_wallet/exchange/exchange_provider.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart';
import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart';
import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart';
import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart';
@ -55,9 +54,6 @@ abstract class TradeDetailsViewModelBase with Store {
case ExchangeProviderDescription.trocador:
_provider = TrocadorExchangeProvider();
break;
case ExchangeProviderDescription.exolix:
_provider = ExolixExchangeProvider();
break;
}
_updateItems();
@ -161,12 +157,6 @@ abstract class TradeDetailsViewModelBase with Store {
items.add(StandartListItem(
title: '${trade.providerName} ${S.current.password}', value: trade.password ?? ''));
}
if (trade.provider == ExchangeProviderDescription.exolix) {
final buildURL = 'https://exolix.com/transaction/${trade.id.toString()}';
items.add(
TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL)));
}
}
void _launchUrl(String url) {

View file

@ -689,7 +689,7 @@
"support_title_guides": "Cake Wallet guides",
"support_description_guides": "Documentation and support for common issues",
"support_title_other_links": "Other support links",
"support_description_other_links": "Join our communities or reach us our our partners through other methods",
"support_description_other_links": "Join our communities or reach us or our partners through other methods",
"choose_derivation": "Choose Wallet Derivation",
"new_first_wallet_text": "Keep your crypto safe, piece of cake",
"select_destination": "Please select destination for the backup file.",

View file

@ -21,7 +21,7 @@
"contact_name": "Nom de Contact",
"reset": "Réinitialiser",
"save": "Sauvegarder",
"address_remove_contact": "Supprimer contact",
"address_remove_contact": "Supprimer le contact",
"address_remove_content": "Êtes vous certain de vouloir supprimer le contact sélectionné ?",
"authenticated": "Authentifié",
"authentication": "Authentification",
@ -67,8 +67,8 @@
"min_value": "Min: ${value} ${currency}",
"max_value": "Max: ${value} ${currency}",
"change_currency": "Changer de Devise",
"overwrite_amount": "Écraser montant",
"qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous écraser la valeur actuelle ?",
"overwrite_amount": "Remplacer le montant",
"qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous remplacer la valeur actuelle ?",
"copy_id": "Copier l'ID",
"exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.",
"trade_id": "ID d'échange :",
@ -109,7 +109,7 @@
"nodes": "Nœuds",
"node_reset_settings_title": "Réinitialisation des réglages",
"nodes_list_reset_to_default_message": "Êtes vous certain de vouloir revenir aux réglages par défaut ?",
"change_current_node": "Êtes vous certain de vouloir changer le nœud actuel vers ${node} ?",
"change_current_node": "Êtes vous certain de vouloir changer le nœud actuel pour ${node} ?",
"change": "Changer",
"remove_node": "Supprimer le nœud",
"remove_node_message": "Êtes vous certain de vouloir supprimer le nœud sélectionné ?",
@ -269,7 +269,7 @@
"error_text_address": "L'adresse du portefeuille (wallet) doit correspondre au type de\ncryptomonnaie",
"error_text_node_address": "Merci d'entrer une adresse IPv4",
"error_text_node_port": "Le port d'un nœud doit être un nombre compris entre 0 et 65535",
"error_text_node_proxy_address": "Veuillez saisir <adresse IPv4> :<port>, par exemple 127.0.0.1:9050",
"error_text_node_proxy_address": "Veuillez saisir <adresse IPv4>:<port>, par exemple 127.0.0.1:9050",
"error_text_payment_id": "Un ID de paiement ne peut être constitué que de 16 à 64 caractères hexadécimaux",
"error_text_xmr": "La valeur de XMR dépasse le solde disponible.\nLa partie décimale doit comporter au plus 12 chiffres",
"error_text_fiat": "La valeur du montant ne peut dépasser le solde disponible.\nLa partie décimale doit comporter au plus 2 chiffres",
@ -350,7 +350,7 @@
"seed_alert_yes": "Oui, je suis sûr",
"exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé",
"pre_seed_title": "IMPORTANT",
"pre_seed_description": "Sur la page suivante vous allez voir une série de ${words} mots. Ils constituent votre phrase secrète (seed) unique et privé et sont le SEUL moyen de restaurer votre portefeuille (wallet) en cas de perte ou de dysfonctionnement. Il est de VOTRE responsabilité d'écrire cette série de mots et de les stocker dans un lieu sûr en dehors de l'application Cake Wallet.",
"pre_seed_description": "Sur la page suivante vous allez voir une série de ${words} mots. Ils constituent votre phrase secrète (seed) unique et privée et sont le SEUL moyen de restaurer votre portefeuille (wallet) en cas de perte ou de dysfonctionnement. Il est de VOTRE responsabilité d'écrire cette série de mots et de la stocker dans un lieu sûr en dehors de l'application Cake Wallet.",
"pre_seed_button_text": "J'ai compris. Montrez moi ma phrase secrète (seed)",
"xmr_to_error": "Erreur XMR.TO",
"xmr_to_error_description": "Montant invalide. La partie décimale doit contenir au plus 8 chiffres",
@ -409,15 +409,15 @@
"unspent_coins_details_title": "Détails des pièces (coins) non dépensées",
"freeze": "Geler",
"frozen": "Gelées",
"coin_control": "Contrôle des pièces (optionnel)",
"coin_control": "Contrôle optionnel des pièces (coins)",
"address_detected": "Adresse détectée",
"address_from_domain": "Cette adresse est issue de ${domain} sur Unstoppable Domains",
"add_receiver": "Ajouter un autre bénéficiaire (optionnel)",
"manage_yats": "Gérer les Yats",
"yat_alert_title": "Envoyez et recevez des cryptos plus facilement avec Yat",
"yat_alert_content": "Les utilisateurs de Cake Wallet peuvent maintenant envoyer et recevoir leurs monnaies favories avec un utilisateur unique en son genre basé sur les emojis.",
"get_your_yat": "Obtenez votre Yat",
"connect_an_existing_yat": "Connectez un Yat existant",
"yat_alert_content": "Les utilisateurs de Cake Wallet peuvent maintenant envoyer et recevoir leurs monnaies favorites avec un utilisateur unique en son genre basé sur les emojis.",
"get_your_yat": "Obtenir votre Yat",
"connect_an_existing_yat": "Connecter un Yat existant",
"connect_yats": "Connecter Yats",
"yat_address": "Adresse Yat",
"yat": "Yat",
@ -427,13 +427,13 @@
"choose_address": "\n\nMerci de choisir l'adresse :",
"yat_popup_title": "L'adresse de votre portefeuille (wallet) peut être emojifiée.",
"yat_popup_content": "Vous pouvez à présent envoyer et recevoir des cryptos dans Cake Wallet à l'aide de votre Yat - un nom d'utilisateur court à base d'emoji. Gérér les Yats à tout moment depuis l'écran de paramétrage",
"second_intro_title": "Une adresse emoji pour les gouverner tous",
"second_intro_title": "Une adresse emoji pour les gouverner toutes",
"second_intro_content": "Votre Yat est une seule et unique adresse emoji qui remplace toutes vos longues adresses hexadécimales pour toutes vos cryptomonnaies.",
"third_intro_title": "Yat joue bien avec les autres",
"third_intro_title": "Yat est universel",
"third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !",
"learn_more": "En savoir plus",
"search": "Chercher",
"search_language": "Recherche une langue",
"search_language": "Rechercher une langue",
"search_currency": "Rechercher une devise",
"new_template": "Nouveau Modèle",
"electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner",
@ -514,8 +514,8 @@
"active_cards": "Cartes actives",
"delete_account": "Supprimer le compte",
"cards": "Cartes",
"active": "Actif",
"redeemed": "racheté",
"active": "Actives,
"redeemed": "Converties",
"gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici",
"gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici",
"logout": "Déconnexion",
@ -523,7 +523,7 @@
"percentageOf": "sur ${amount}",
"is_percentage": "est",
"search_category": "Catégorie de recherche",
"mark_as_redeemed": "Marquer comme échangé",
"mark_as_redeemed": "Marquer comme convertie",
"more_options": "Plus d'options",
"awaiting_payment_confirmation": "En attente de confirmation de paiement",
"transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.",
@ -544,7 +544,7 @@
"cake_pay_learn_more": "Achetez et utilisez instantanément des cartes-cadeaux dans l'application !\nBalayer de gauche à droite pour en savoir plus.",
"automatic": "Automatique",
"fixed_pair_not_supported": "Cette paire fixe n'est pas prise en charge avec les échanges sélectionnés",
"variable_pair_not_supported": "Cette paire de variables n'est pas prise en charge avec les échanges sélectionnés",
"variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés",
"none_of_selected_providers_can_exchange": "Aucun des prestataires sélectionnés ne peut effectuer cet échange",
"choose_one": "Choisissez-en un",
"choose_from_available_options": "Choisissez parmi les options disponibles :",
@ -634,7 +634,7 @@
"setup_totp_recommended": "Configurer TOTP (recommandé)",
"disable_buy": "Désactiver l'action d'achat",
"disable_sell": "Désactiver l'action de vente",
"cake_2fa_preset": "Gâteau 2FA prédéfini",
"cake_2fa_preset": "Cake 2FA prédéfini",
"monero_dark_theme": "Thème sombre Monero",
"bitcoin_dark_theme": "Thème sombre Bitcoin",
"bitcoin_light_theme": "Thème léger Bitcoin",
@ -644,33 +644,33 @@
"auto_generate_subaddresses": "Générer automatiquement des sous-adresses",
"narrow": "Étroit",
"normal": "Normal",
"aggressive": "Trop zélé",
"aggressive": "Agressif",
"require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille",
"require_for_sends_to_non_contacts": "Exiger pour les envois à des non-contacts",
"require_for_sends_to_non_contacts": "Exiger pour les envois hors contacts",
"require_for_sends_to_contacts": "Exiger pour les envois aux contacts",
"require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles internes",
"require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles internes",
"require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles (wallets) internes",
"require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles (wallets) internes",
"require_for_adding_contacts": "Requis pour ajouter des contacts",
"require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles",
"require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles (wallets)",
"require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde",
"available_balance_description": "Le solde disponible est le montant que vous pouvez dépenser immédiatement. Il est calculé en soustrayant le solde gelé du solde total.",
"syncing_wallet_alert_title": "Votre portefeuille est en cours de synchronisation",
"syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être complets tant qu'il n'y a pas « SYNCHRONISÉ » en haut. Cliquez/appuyez pour en savoir plus.",
"syncing_wallet_alert_title": "Votre portefeuille (wallet) est en cours de synchronisation",
"syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être à jour tant que la mention « SYNCHRONISÉ » n'apparaît en haut de l'écran. Cliquez/appuyez pour en savoir plus.",
"home_screen_settings": "Paramètres de l'écran d'accueil",
"sort_by": "Trier par",
"search_add_token": "Rechercher / Ajouter un jeton",
"edit_token": "Modifier le jeton",
"search_add_token": "Rechercher / Ajouter un token",
"edit_token": "Modifier le token",
"warning": "Avertissement",
"add_token_warning": "Ne modifiez pas ou n'ajoutez pas de jetons comme indiqué par les escrocs.\nConfirmez toujours les adresses de jeton auprès de sources fiables !",
"add_token_disclaimer_check": "J'ai confirmé l'adresse et les informations du contrat de jeton en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.",
"token_contract_address": "Adresse du contrat de jeton",
"token_name": "Nom du jeton, par exemple : Tether",
"token_symbol": "Symbole de jeton, par exemple : USDT",
"token_decimal": "Décimal de jeton",
"add_token_warning": "Ne modifiez pas ou n'ajoutez pas de tokens comme pourraient vous le suggérer des escrocs.\nConfirmez toujours les adresses de token auprès de sources fiables !",
"add_token_disclaimer_check": "J'ai confirmé l'adresse et les informations du contrat de token en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.",
"token_contract_address": "Adresse du contrat de token",
"token_name": "Nom du token, par exemple : Tether",
"token_symbol": "Symbole de token, par exemple : USDT",
"token_decimal": "Décimales de token",
"field_required": "Ce champ est obligatoire",
"pin_at_top": "épingler ${token} en haut",
"invalid_input": "Entrée invalide",
"fiat_balance": "Fiat Balance",
"fiat_balance": "Solde fiat",
"gross_balance": "Solde brut",
"alphabetical": "Alphabétique",
"generate_name": "Générer un nom",
@ -685,19 +685,19 @@
"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.",
"manage_pow_nodes": "Gérer les nœuds PoW",
"support_title_live_chat": "Support en direct",
"support_description_live_chat": "GRATUIT ET RAPIDE! Des représentants de soutien formé sont disponibles pour aider",
"support_title_guides": "Guides de portefeuille à gâteau",
"support_description_guides": "Documentation et soutien aux problèmes communs",
"support_description_live_chat": "GRATUIT ET RAPIDE ! Des représentants de soutien formé sont disponibles pour aider",
"support_title_guides": "Guides de Cake Wallet",
"support_description_guides": "Documentation et support pour les problèmes communs",
"support_title_other_links": "Autres liens d'assistance",
"support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes",
"choose_derivation": "Choisissez la dérivation du portefeuille",
"support_description_other_links": "Rejoignez nos communautés ou contactez-nous ou nos partenaires à travers d'autres méthodes",
"choose_derivation": "Choisissez le chemin de dérivation du portefeuille",
"new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité",
"select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.",
"save_to_downloads": "Enregistrer dans les téléchargements",
"select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.",
"onramper_option_description": "Achetez rapidement la crypto avec de nombreux méthodes de paiement. Disponible dans la plupart des pays. Les écarts et les frais varient.",
"onramper_option_description": "Achetez rapidement des cryptomonnaies avec de nombreuses méthodes de paiement. Disponible dans la plupart des pays. Les spreads et les frais peuvent varier.",
"default_buy_provider": "Fournisseur d'achat par défaut",
"ask_each_time": "Demandez à chaque fois",
"ask_each_time": "Demander à chaque fois",
"buy_provider_unavailable": "Fournisseur actuellement indisponible.",
"signTransaction": "Signer une transaction",
"errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification",
@ -709,9 +709,9 @@
"reject": "Rejeter",
"approve": "Approuver",
"expiresOn": "Expire le",
"walletConnect": "PortefeuilleConnect",
"walletConnect": "WalletConnect",
"nullURIError": "L'URI est nul",
"connectWalletPrompt": "Connectez votre portefeuille avec WalletConnect pour effectuer des transactions",
"connectWalletPrompt": "Connectez votre portefeuille (wallet) avec WalletConnect pour effectuer des transactions",
"newConnection": "Nouvelle connexion",
"activeConnectionsPrompt": "Les connexions actives apparaîtront ici",
"deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à",

View file

@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.6.2"
MONERO_COM_BUILD_NUMBER=58
MONERO_COM_VERSION="1.7.0"
MONERO_COM_BUILD_NUMBER=61
MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app"
MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.9.2"
CAKEWALLET_BUILD_NUMBER=171
CAKEWALLET_VERSION="4.10.0"
CAKEWALLET_BUILD_NUMBER=175
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet"

View file

@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_IOS_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.6.2"
MONERO_COM_BUILD_NUMBER=56
MONERO_COM_VERSION="1.7.0"
MONERO_COM_BUILD_NUMBER=59
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.9.2"
CAKEWALLET_BUILD_NUMBER=185
CAKEWALLET_VERSION="4.10.0"
CAKEWALLET_BUILD_NUMBER=189
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
HAVEN_NAME="Haven"

View file

@ -15,8 +15,8 @@ if [ -n "$1" ]; then
fi
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.2.2"
CAKEWALLET_BUILD_NUMBER=33
CAKEWALLET_VERSION="1.3.0"
CAKEWALLET_BUILD_NUMBER=36
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then

View file

@ -650,6 +650,7 @@ abstract class Nano {
Future<void> changeRep(Object wallet, String address);
Future<void> updateTransactions(Object wallet);
BigInt getTransactionAmountRaw(TransactionInfo transactionInfo);
String getRepresentative(Object wallet);
}
abstract class NanoAccountList {
@ -683,8 +684,7 @@ abstract class NanoUtil {
BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000");
BigInt rawPerXMR = BigInt.parse("1000000000000");
BigInt convertXMRtoNano = BigInt.parse("1000000000000000000");
Decimal getRawAsDecimal(String? raw, BigInt? rawPerCur);
String truncateDecimal(Decimal input, {int digits = maxDecimalDigits});
String getRawAsDecimalString(String? raw, BigInt? rawPerCur);
String getRawAsUsableString(String? raw, BigInt rawPerCur);
String getRawAccuracy(String? raw, BigInt rawPerCur);
String getAmountAsRaw(String amount, BigInt rawPerCur);
@ -704,7 +704,7 @@ abstract class NanoUtil {
}
""";
const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil = CWNanoUtil();\n';
const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil;\n';
const nanoCWDefinition = 'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n';
final output = '$nanoCommonHeaders\n' +

View file

@ -32,7 +32,6 @@ class SecretKey {
SecretKey('fiatApiKey', () => ''),
SecretKey('payfuraApiKey', () => ''),
SecretKey('chatwootWebsiteToken', () => ''),
SecretKey('exolixApiKey', () => ''),
SecretKey('robinhoodApplicationId', () => ''),
SecretKey('robinhoodCIdApiSecret', () => ''),
SecretKey('walletConnectProjectId', () => ''),