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 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 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 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 robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
echo "const robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> 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 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 Bug fixes
Minor enhancements Minor enhancements

View file

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

View file

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

View file

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

View file

@ -417,10 +417,6 @@ Future<void> setup({
} }
if (appStore.wallet != null) { if (appStore.wallet != null) {
authStore.allowed(); authStore.allowed();
if (appStore.wallet!.type == WalletType.ethereum) {
getIt.get<Web3WalletService>().init();
}
return; return;
} }
@ -441,10 +437,6 @@ Future<void> setup({
} else { } else {
if (appStore.wallet != null) { if (appStore.wallet != null) {
authStore.allowed(); authStore.allowed();
if (appStore.wallet!.type == WalletType.ethereum) {
getIt.get<Web3WalletService>().init();
}
return; 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 narrow = Cake2FAPresetsOptions(title: 'Narrow', raw: 0);
static const normal = Cake2FAPresetsOptions(title: 'Normal', raw: 1); static const normal = Cake2FAPresetsOptions(title: 'Normal', raw: 1);
static const aggressive = Cake2FAPresetsOptions(title: 'Aggressive', raw: 2); static const aggressive = Cake2FAPresetsOptions(title: 'Aggressive', raw: 2);
static const none = Cake2FAPresetsOptions(title: 'None', raw: 3);
static Cake2FAPresetsOptions deserialize({required int raw}) { static Cake2FAPresetsOptions deserialize({required int raw}) {
switch (raw) { switch (raw) {
@ -15,6 +16,8 @@ class Cake2FAPresetsOptions extends EnumerableItem<int> with Serializable<int> {
return Cake2FAPresetsOptions.normal; return Cake2FAPresetsOptions.normal;
case 2: case 2:
return Cake2FAPresetsOptions.aggressive; return Cake2FAPresetsOptions.aggressive;
case 3:
return Cake2FAPresetsOptions.none;
default: default:
throw Exception( throw Exception(
'Incorrect Cake 2FA Preset $raw for Cake2FAPresetOptions deserialize', 'Incorrect Cake 2FA Preset $raw for Cake2FAPresetOptions deserialize',

View file

@ -24,10 +24,7 @@ class ExchangeProviderDescription extends EnumerableItem<int> with Serializable<
static const trocador = static const trocador =
ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/images/trocador.png'); ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/images/trocador.png');
static const exolix = static const all = ExchangeProviderDescription(title: 'All trades', raw: 6, image: '');
ExchangeProviderDescription(title: 'Exolix', raw: 6, image: 'assets/images/exolix.png');
static const all = ExchangeProviderDescription(title: 'All trades', raw: 7, image: '');
static ExchangeProviderDescription deserialize({required int raw}) { static ExchangeProviderDescription deserialize({required int raw}) {
switch (raw) { switch (raw) {
@ -44,8 +41,6 @@ class ExchangeProviderDescription extends EnumerableItem<int> with Serializable<
case 5: case 5:
return trocador; return trocador;
case 6: case 6:
return exolix;
case 7:
return all; return all;
default: default:
throw Exception('Unexpected token: $raw for ExchangeProviderDescription deserialize'); 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 completed = TradeState(raw: 'completed', title: 'Completed');
static const settling = TradeState(raw: 'settling', title: 'Settlement in progress'); static const settling = TradeState(raw: 'settling', title: 'Settlement in progress');
static const settled = TradeState(raw: 'settled', title: 'Settlement completed'); 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}) { static TradeState deserialize({required String raw}) {
switch (raw) { switch (raw) {
case 'pending': case 'pending':
@ -86,24 +77,6 @@ class TradeState extends EnumerableItem<String> with Serializable<String> {
return failed; return failed;
case 'completed': case 'completed':
return 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: default:
throw Exception('Unexpected token: $raw in TradeState deserialize'); throw Exception('Unexpected token: $raw in TradeState deserialize');
} }

View file

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

View file

@ -94,9 +94,6 @@ class TradeRow extends StatelessWidget {
borderRadius: BorderRadius.circular(50), borderRadius: BorderRadius.circular(50),
child: Image.asset('assets/images/trocador.png', width: 36, height: 36)); child: Image.asset('assets/images/trocador.png', width: 36, height: 36));
break; break;
case ExchangeProviderDescription.exolix:
image = Image.asset('assets/images/exolix.png', width: 36, height: 36);
break;
default: default:
image = null; 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:cake_wallet/utils/show_pop_up.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_nano/nano_wallet.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
@ -18,7 +17,7 @@ class NanoChangeRepPage extends BasePage {
NanoChangeRepPage(WalletBase wallet) NanoChangeRepPage(WalletBase wallet)
: _wallet = wallet, : _wallet = wallet,
_addressController = TextEditingController() { _addressController = TextEditingController() {
_addressController.text = (wallet as NanoWallet).representative; _addressController.text = nano!.getRepresentative(wallet);
} }
final TextEditingController _addressController; 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( WalletConnectTile(
onTap: () async { onTap: () async {
Navigator.of(context).push( 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:cake_wallet/utils/exception_handler.dart';
import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cw_core/balance.dart'; import 'package:cw_core/balance.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
@ -40,5 +43,9 @@ abstract class AppStoreBase with Store {
this.wallet?.close(); this.wallet?.close();
this.wallet = wallet; this.wallet = wallet;
this.wallet!.setExceptionHandler(ExceptionHandler.onError); 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, displaySideShift = true,
displayMorphToken = true, displayMorphToken = true,
displaySimpleSwap = true, displaySimpleSwap = true,
displayTrocador = true, displayTrocador = true;
displayExolix = true;
@observable @observable
bool displayXMRTO; bool displayXMRTO;
@ -34,11 +33,8 @@ abstract class TradeFilterStoreBase with Store {
@observable @observable
bool displayTrocador; bool displayTrocador;
@observable
bool displayExolix;
@computed @computed
bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador && displayExolix; bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador;
@action @action
void toggleDisplayExchange(ExchangeProviderDescription provider) { void toggleDisplayExchange(ExchangeProviderDescription provider) {
@ -60,10 +56,7 @@ abstract class TradeFilterStoreBase with Store {
break; break;
case ExchangeProviderDescription.trocador: case ExchangeProviderDescription.trocador:
displayTrocador = !displayTrocador; displayTrocador = !displayTrocador;
break; break;
case ExchangeProviderDescription.exolix:
displayExolix = !displayExolix;
break;
case ExchangeProviderDescription.all: case ExchangeProviderDescription.all:
if (displayAllTrades) { if (displayAllTrades) {
displayChangeNow = false; displayChangeNow = false;
@ -72,7 +65,6 @@ abstract class TradeFilterStoreBase with Store {
displayMorphToken = false; displayMorphToken = false;
displaySimpleSwap = false; displaySimpleSwap = false;
displayTrocador = false; displayTrocador = false;
displayExolix = false;
} else { } else {
displayChangeNow = true; displayChangeNow = true;
displaySideShift = true; displaySideShift = true;
@ -80,7 +72,6 @@ abstract class TradeFilterStoreBase with Store {
displayMorphToken = true; displayMorphToken = true;
displaySimpleSwap = true; displaySimpleSwap = true;
displayTrocador = true; displayTrocador = true;
displayExolix = true;
} }
break; break;
} }
@ -107,8 +98,7 @@ abstract class TradeFilterStoreBase with Store {
||(displaySimpleSwap && ||(displaySimpleSwap &&
item.trade.provider == item.trade.provider ==
ExchangeProviderDescription.simpleSwap) ExchangeProviderDescription.simpleSwap)
||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) ||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador))
||(displayExolix && item.trade.provider == ExchangeProviderDescription.exolix))
.toList() .toList()
: _trades; : _trades;
} }

View file

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

View file

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

View file

@ -1,5 +1,4 @@
import 'dart:async'; 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/sideshift/sideshift_exchange_provider.dart';
import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart';
import 'package:cake_wallet/exchange/trocador/trocador_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: case ExchangeProviderDescription.trocador:
_provider = TrocadorExchangeProvider(); _provider = TrocadorExchangeProvider();
break; break;
case ExchangeProviderDescription.exolix:
_provider = ExolixExchangeProvider();
break;
} }
_updateItems(); _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/exchange_api_mode.dart';
import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/wallet_contact.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_exchange_provider.dart';
import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart';
import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart';
@ -152,7 +150,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
SideShiftExchangeProvider(), SideShiftExchangeProvider(),
SimpleSwapExchangeProvider(), SimpleSwapExchangeProvider(),
TrocadorExchangeProvider(useTorOnly: _useTorOnly), TrocadorExchangeProvider(useTorOnly: _useTorOnly),
ExolixExchangeProvider(),
]; ];
@observable @observable
@ -549,17 +546,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
amount = isFixedRateMode ? receiveAmount : depositAmount; 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(',', '.'); amount = amount.replaceAll(',', '.');
if (limitsState is LimitsLoadedSuccessfully) { if (limitsState is LimitsLoadedSuccessfully) {

View file

@ -278,7 +278,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
List<bool> conditionsList = []; List<bool> conditionsList = [];
for (var output in outputs) { for (var output in outputs) {
final show = checkThroughChecksToDisplayTOTP(output.address);
final show = checkThroughChecksToDisplayTOTP(output.extractedAddress);
conditionsList.add(show); 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 (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()); return S.current.do_not_have_enough_gas_asset(currency.toString());
} }
} }

View file

@ -201,38 +201,15 @@ abstract class Setup2FAViewModelBase with Store {
@observable @observable
ObservableList<VerboseControlSettings> selected2FASettings; 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 @action
void checkIfTheCurrentSettingMatchesAnyOfThePresets() { void checkIfTheCurrentSettingMatchesAnyOfThePresets() {
final hasNormalPreset = checkIfTheNormalPresetIsPresent(); final hasNormalPreset = checkIfTheNormalPresetIsPresent();
final hasNarrowPreset = checkIfTheNarrowPresetIsPresent(); final hasNarrowPreset = checkIfTheNarrowPresetIsPresent();
final hasVerbosePreset = checkIfTheVerbosePresetIsPresent(); final hasVerbosePreset = checkIfTheVerbosePresetIsPresent();
if (hasNormalPreset || hasNarrowPreset || hasVerbosePreset) { if (hasNormalPreset || hasNarrowPreset || hasVerbosePreset) return;
unhighlightTabs = false;
} else { noCake2FAPresetSelected();
unhighlightTabs = true;
}
} }
@action @action
@ -288,32 +265,8 @@ abstract class Setup2FAViewModelBase with Store {
} }
@action @action
void activateCake2FANormalPreset() { void noCake2FAPresetSelected() {
_settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.normal; _settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.none;
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);
} }
@action @action
@ -330,90 +283,106 @@ abstract class Setup2FAViewModelBase with Store {
unhighlightTabs = false; 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 @action
void switchShouldRequireTOTP2FAForAccessingWallet(bool value) { void selectCakePreset(Cake2FAPresetsOptions preset) {
_settingsStore.shouldRequireTOTP2FAForAccessingWallet = value; presetsMap[preset]?.forEach(toggleControl);
if (value) { _settingsStore.selectedCake2FAPreset = preset;
selected2FASettings.add(VerboseControlSettings.accessWallet); }
} else {
selected2FASettings.remove(VerboseControlSettings.accessWallet); @action
} void toggleControl(VerboseControlSettings control, [bool value = true]) {
checkIfTheCurrentSettingMatchesAnyOfThePresets(); 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 @action
void switchShouldRequireTOTP2FAForSendsToContact(bool value) { void switchShouldRequireTOTP2FAForSendsToContact(bool value) {
_settingsStore.shouldRequireTOTP2FAForSendsToContact = value; _settingsStore.shouldRequireTOTP2FAForSendsToContact = value;
if (value) { updateSelectedSettings(VerboseControlSettings.sendsToContacts, value);
selected2FASettings.add(VerboseControlSettings.sendsToContacts); }
} else {
selected2FASettings.remove(VerboseControlSettings.sendsToContacts); @action
} void switchShouldRequireTOTP2FAForAccessingWallet(bool value) {
checkIfTheCurrentSettingMatchesAnyOfThePresets(); _settingsStore.shouldRequireTOTP2FAForAccessingWallet = value;
updateSelectedSettings(VerboseControlSettings.accessWallet, value);
} }
@action @action
void switchShouldRequireTOTP2FAForSendsToNonContact(bool value) { void switchShouldRequireTOTP2FAForSendsToNonContact(bool value) {
_settingsStore.shouldRequireTOTP2FAForSendsToNonContact = value; _settingsStore.shouldRequireTOTP2FAForSendsToNonContact = value;
if (value) { updateSelectedSettings(VerboseControlSettings.sendsToNonContacts, value);
selected2FASettings.add(VerboseControlSettings.sendsToNonContacts);
} else {
selected2FASettings.remove(VerboseControlSettings.sendsToNonContacts);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
} }
@action @action
void switchShouldRequireTOTP2FAForSendsToInternalWallets(bool value) { void switchShouldRequireTOTP2FAForSendsToInternalWallets(bool value) {
_settingsStore.shouldRequireTOTP2FAForSendsToInternalWallets = value; _settingsStore.shouldRequireTOTP2FAForSendsToInternalWallets = value;
if (value) { updateSelectedSettings(VerboseControlSettings.sendsToInternalWallets, value);
selected2FASettings.add(VerboseControlSettings.sendsToInternalWallets);
} else {
selected2FASettings.remove(VerboseControlSettings.sendsToInternalWallets);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
} }
@action @action
void switchShouldRequireTOTP2FAForExchangesToInternalWallets(bool value) { void switchShouldRequireTOTP2FAForExchangesToInternalWallets(bool value) {
_settingsStore.shouldRequireTOTP2FAForExchangesToInternalWallets = value; _settingsStore.shouldRequireTOTP2FAForExchangesToInternalWallets = value;
if (value) { updateSelectedSettings(VerboseControlSettings.exchangesToInternalWallets, value);
selected2FASettings.add(VerboseControlSettings.exchangesToInternalWallets);
} else {
selected2FASettings.remove(VerboseControlSettings.exchangesToInternalWallets);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
} }
@action @action
void switchShouldRequireTOTP2FAForAddingContacts(bool value) { void switchShouldRequireTOTP2FAForAddingContacts(bool value) {
_settingsStore.shouldRequireTOTP2FAForAddingContacts = value; _settingsStore.shouldRequireTOTP2FAForAddingContacts = value;
if (value) updateSelectedSettings(VerboseControlSettings.addingContacts, value);
selected2FASettings.add(VerboseControlSettings.addingContacts);
else {
selected2FASettings.remove(VerboseControlSettings.addingContacts);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
} }
@action @action
void switchShouldRequireTOTP2FAForCreatingNewWallet(bool value) { void switchShouldRequireTOTP2FAForCreatingNewWallet(bool value) {
_settingsStore.shouldRequireTOTP2FAForCreatingNewWallets = value; _settingsStore.shouldRequireTOTP2FAForCreatingNewWallets = value;
if (value) { updateSelectedSettings(VerboseControlSettings.creatingNewWallets, value);
selected2FASettings.add(VerboseControlSettings.creatingNewWallets);
} else {
selected2FASettings.remove(VerboseControlSettings.creatingNewWallets);
}
checkIfTheCurrentSettingMatchesAnyOfThePresets();
} }
@action @action
void switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(bool value) { void switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(bool value) {
_settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings = value; _settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings = value;
if (value) updateSelectedSettings(VerboseControlSettings.securityAndBackupSettings, value);
selected2FASettings.add(VerboseControlSettings.securityAndBackupSettings); }
else {
selected2FASettings.remove(VerboseControlSettings.securityAndBackupSettings); @action
void updateSelectedSettings(VerboseControlSettings control, bool value) {
if (value) {
selected2FASettings.add(control);
} else {
selected2FASettings.remove(control);
} }
checkIfTheCurrentSettingMatchesAnyOfThePresets(); checkIfTheCurrentSettingMatchesAnyOfThePresets();
} }

View file

@ -53,11 +53,6 @@ abstract class SupportViewModelBase with Store {
icon: 'assets/images/simpleSwap.png', icon: 'assets/images/simpleSwap.png',
linkTitle: 'support@simpleswap.io', linkTitle: 'support@simpleswap.io',
link: 'mailto: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) ... [ if (!isMoneroOnly) ... [
LinkListItem( LinkListItem(
title: 'Wyre', 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/changenow/changenow_exchange_provider.dart';
import 'package:cake_wallet/exchange/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/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/morphtoken/morphtoken_exchange_provider.dart';
import 'package:cake_wallet/exchange/sideshift/sideshift_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/simpleswap/simpleswap_exchange_provider.dart';
@ -55,9 +54,6 @@ abstract class TradeDetailsViewModelBase with Store {
case ExchangeProviderDescription.trocador: case ExchangeProviderDescription.trocador:
_provider = TrocadorExchangeProvider(); _provider = TrocadorExchangeProvider();
break; break;
case ExchangeProviderDescription.exolix:
_provider = ExolixExchangeProvider();
break;
} }
_updateItems(); _updateItems();
@ -161,12 +157,6 @@ abstract class TradeDetailsViewModelBase with Store {
items.add(StandartListItem( items.add(StandartListItem(
title: '${trade.providerName} ${S.current.password}', value: trade.password ?? '')); 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) { void _launchUrl(String url) {

View file

@ -689,7 +689,7 @@
"support_title_guides": "Cake Wallet guides", "support_title_guides": "Cake Wallet guides",
"support_description_guides": "Documentation and support for common issues", "support_description_guides": "Documentation and support for common issues",
"support_title_other_links": "Other support links", "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", "choose_derivation": "Choose Wallet Derivation",
"new_first_wallet_text": "Keep your crypto safe, piece of cake", "new_first_wallet_text": "Keep your crypto safe, piece of cake",
"select_destination": "Please select destination for the backup file.", "select_destination": "Please select destination for the backup file.",

View file

@ -21,7 +21,7 @@
"contact_name": "Nom de Contact", "contact_name": "Nom de Contact",
"reset": "Réinitialiser", "reset": "Réinitialiser",
"save": "Sauvegarder", "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é ?", "address_remove_content": "Êtes vous certain de vouloir supprimer le contact sélectionné ?",
"authenticated": "Authentifié", "authenticated": "Authentifié",
"authentication": "Authentification", "authentication": "Authentification",
@ -67,8 +67,8 @@
"min_value": "Min: ${value} ${currency}", "min_value": "Min: ${value} ${currency}",
"max_value": "Max: ${value} ${currency}", "max_value": "Max: ${value} ${currency}",
"change_currency": "Changer de Devise", "change_currency": "Changer de Devise",
"overwrite_amount": "Écraser montant", "overwrite_amount": "Remplacer le montant",
"qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous écraser la valeur actuelle ?", "qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous remplacer la valeur actuelle ?",
"copy_id": "Copier l'ID", "copy_id": "Copier l'ID",
"exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.", "exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.",
"trade_id": "ID d'échange :", "trade_id": "ID d'échange :",
@ -109,7 +109,7 @@
"nodes": "Nœuds", "nodes": "Nœuds",
"node_reset_settings_title": "Réinitialisation des réglages", "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 ?", "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", "change": "Changer",
"remove_node": "Supprimer le nœud", "remove_node": "Supprimer le nœud",
"remove_node_message": "Êtes vous certain de vouloir supprimer le nœud sélectionné ?", "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_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_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_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_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_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", "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", "seed_alert_yes": "Oui, je suis sûr",
"exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé", "exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé",
"pre_seed_title": "IMPORTANT", "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)", "pre_seed_button_text": "J'ai compris. Montrez moi ma phrase secrète (seed)",
"xmr_to_error": "Erreur XMR.TO", "xmr_to_error": "Erreur XMR.TO",
"xmr_to_error_description": "Montant invalide. La partie décimale doit contenir au plus 8 chiffres", "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", "unspent_coins_details_title": "Détails des pièces (coins) non dépensées",
"freeze": "Geler", "freeze": "Geler",
"frozen": "Gelées", "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_detected": "Adresse détectée",
"address_from_domain": "Cette adresse est issue de ${domain} sur Unstoppable Domains", "address_from_domain": "Cette adresse est issue de ${domain} sur Unstoppable Domains",
"add_receiver": "Ajouter un autre bénéficiaire (optionnel)", "add_receiver": "Ajouter un autre bénéficiaire (optionnel)",
"manage_yats": "Gérer les Yats", "manage_yats": "Gérer les Yats",
"yat_alert_title": "Envoyez et recevez des cryptos plus facilement avec Yat", "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.", "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": "Obtenez votre Yat", "get_your_yat": "Obtenir votre Yat",
"connect_an_existing_yat": "Connectez un Yat existant", "connect_an_existing_yat": "Connecter un Yat existant",
"connect_yats": "Connecter Yats", "connect_yats": "Connecter Yats",
"yat_address": "Adresse Yat", "yat_address": "Adresse Yat",
"yat": "Yat", "yat": "Yat",
@ -427,13 +427,13 @@
"choose_address": "\n\nMerci de choisir l'adresse :", "choose_address": "\n\nMerci de choisir l'adresse :",
"yat_popup_title": "L'adresse de votre portefeuille (wallet) peut être emojifiée.", "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", "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.", "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 !", "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", "learn_more": "En savoir plus",
"search": "Chercher", "search": "Chercher",
"search_language": "Recherche une langue", "search_language": "Rechercher une langue",
"search_currency": "Rechercher une devise", "search_currency": "Rechercher une devise",
"new_template": "Nouveau Modèle", "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", "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", "active_cards": "Cartes actives",
"delete_account": "Supprimer le compte", "delete_account": "Supprimer le compte",
"cards": "Cartes", "cards": "Cartes",
"active": "Actif", "active": "Actives,
"redeemed": "racheté", "redeemed": "Converties",
"gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici", "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", "gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici",
"logout": "Déconnexion", "logout": "Déconnexion",
@ -523,7 +523,7 @@
"percentageOf": "sur ${amount}", "percentageOf": "sur ${amount}",
"is_percentage": "est", "is_percentage": "est",
"search_category": "Catégorie de recherche", "search_category": "Catégorie de recherche",
"mark_as_redeemed": "Marquer comme échangé", "mark_as_redeemed": "Marquer comme convertie",
"more_options": "Plus d'options", "more_options": "Plus d'options",
"awaiting_payment_confirmation": "En attente de confirmation de paiement", "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.", "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.", "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", "automatic": "Automatique",
"fixed_pair_not_supported": "Cette paire fixe n'est pas prise en charge avec les échanges sélectionnés", "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", "none_of_selected_providers_can_exchange": "Aucun des prestataires sélectionnés ne peut effectuer cet échange",
"choose_one": "Choisissez-en un", "choose_one": "Choisissez-en un",
"choose_from_available_options": "Choisissez parmi les options disponibles :", "choose_from_available_options": "Choisissez parmi les options disponibles :",
@ -634,7 +634,7 @@
"setup_totp_recommended": "Configurer TOTP (recommandé)", "setup_totp_recommended": "Configurer TOTP (recommandé)",
"disable_buy": "Désactiver l'action d'achat", "disable_buy": "Désactiver l'action d'achat",
"disable_sell": "Désactiver l'action de vente", "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", "monero_dark_theme": "Thème sombre Monero",
"bitcoin_dark_theme": "Thème sombre Bitcoin", "bitcoin_dark_theme": "Thème sombre Bitcoin",
"bitcoin_light_theme": "Thème léger Bitcoin", "bitcoin_light_theme": "Thème léger Bitcoin",
@ -644,33 +644,33 @@
"auto_generate_subaddresses": "Générer automatiquement des sous-adresses", "auto_generate_subaddresses": "Générer automatiquement des sous-adresses",
"narrow": "Étroit", "narrow": "Étroit",
"normal": "Normal", "normal": "Normal",
"aggressive": "Trop zélé", "aggressive": "Agressif",
"require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", "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_contacts": "Exiger pour les envois aux contacts",
"require_for_sends_to_internal_wallets": "Exiger pour les envois 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 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_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", "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.", "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_title": "Votre portefeuille (wallet) 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_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", "home_screen_settings": "Paramètres de l'écran d'accueil",
"sort_by": "Trier par", "sort_by": "Trier par",
"search_add_token": "Rechercher / Ajouter un jeton", "search_add_token": "Rechercher / Ajouter un token",
"edit_token": "Modifier le jeton", "edit_token": "Modifier le token",
"warning": "Avertissement", "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_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 jeton en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.", "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 jeton", "token_contract_address": "Adresse du contrat de token",
"token_name": "Nom du jeton, par exemple : Tether", "token_name": "Nom du token, par exemple : Tether",
"token_symbol": "Symbole de jeton, par exemple : USDT", "token_symbol": "Symbole de token, par exemple : USDT",
"token_decimal": "Décimal de jeton", "token_decimal": "Décimales de token",
"field_required": "Ce champ est obligatoire", "field_required": "Ce champ est obligatoire",
"pin_at_top": "épingler ${token} en haut", "pin_at_top": "épingler ${token} en haut",
"invalid_input": "Entrée invalide", "invalid_input": "Entrée invalide",
"fiat_balance": "Fiat Balance", "fiat_balance": "Solde fiat",
"gross_balance": "Solde brut", "gross_balance": "Solde brut",
"alphabetical": "Alphabétique", "alphabetical": "Alphabétique",
"generate_name": "Générer un nom", "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.", "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", "manage_pow_nodes": "Gérer les nœuds PoW",
"support_title_live_chat": "Support en direct", "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_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_title_guides": "Guides de Cake Wallet",
"support_description_guides": "Documentation et soutien aux problèmes communs", "support_description_guides": "Documentation et support pour les problèmes communs",
"support_title_other_links": "Autres liens d'assistance", "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", "support_description_other_links": "Rejoignez nos communautés ou contactez-nous ou nos partenaires à travers d'autres méthodes",
"choose_derivation": "Choisissez la dérivation du portefeuille", "choose_derivation": "Choisissez le chemin de dérivation du portefeuille",
"new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité",
"select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.", "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.",
"save_to_downloads": "Enregistrer dans les téléchargements", "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.", "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", "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.", "buy_provider_unavailable": "Fournisseur actuellement indisponible.",
"signTransaction": "Signer une transaction", "signTransaction": "Signer une transaction",
"errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification", "errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification",
@ -709,9 +709,9 @@
"reject": "Rejeter", "reject": "Rejeter",
"approve": "Approuver", "approve": "Approuver",
"expiresOn": "Expire le", "expiresOn": "Expire le",
"walletConnect": "PortefeuilleConnect", "walletConnect": "WalletConnect",
"nullURIError": "L'URI est nul", "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", "newConnection": "Nouvelle connexion",
"activeConnectionsPrompt": "Les connexions actives apparaîtront ici", "activeConnectionsPrompt": "Les connexions actives apparaîtront ici",
"deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à", "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 APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.6.2" MONERO_COM_VERSION="1.7.0"
MONERO_COM_BUILD_NUMBER=58 MONERO_COM_BUILD_NUMBER=61
MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_PACKAGE="com.monero.app"
MONERO_COM_SCHEME="monero.com" MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.9.2" CAKEWALLET_VERSION="4.10.0"
CAKEWALLET_BUILD_NUMBER=171 CAKEWALLET_BUILD_NUMBER=175
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet" CAKEWALLET_SCHEME="cakewallet"

View file

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

View file

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

View file

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

View file

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