v4.10.0 & v1.7.0 (#1113)

* New versions

* update the new version text after macos [skip ci]

* add cake-wallet headers

* add nano/banano to getAddressFromStringPattern

* Revert "Exolix integration (#1080)"

This reverts commit 9eb6867ab9.

* fix: Bug in conditions check and clean up of repeated code in switch cases (#1117)

* update build numbers [skip ci]

---------

Co-authored-by: fosse <matt.cfosse@gmail.com>
Co-authored-by: Adegoke David <64401859+Blazebrain@users.noreply.github.com>
This commit is contained in:
Omar Hatem 2023-10-09 18:18:59 +03:00 committed by GitHub
parent 5a20d342ad
commit e5408a388e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 146 additions and 554 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,9 +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

@ -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

@ -639,6 +639,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 {
@ -672,8 +673,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);
@ -693,7 +693,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', () => ''),