Merge branch 'main' into CAKE-284-add-support-to-the-main-menu

# Conflicts:
#	lib/view_model/settings/settings_view_model.dart
This commit is contained in:
OleksandrSobol 2021-03-01 19:51:08 +02:00
commit 5b242002d1
25 changed files with 594 additions and 221 deletions

View file

@ -1,74 +1,113 @@
Privacy Policy
Last modified: January 28, 2021
Introduction
Cake Technologies Inc. ("Company" or "We") respect your privacy and are committed to protecting it through our compliance with this policy.
This policy describes the types of information we may collect from you or that you may provide when you use the App (our "App") and our practices for collecting, using, maintaining, protecting, and disclosing that information.
This policy applies to information we collect:
On this App.
In email, text, and other electronic messages between you and this App.
It does not apply to information collected by:
Us offline or through any other means, including on any other App operated by Company or any third party (including our affiliates and subsidiaries)]; or
Any third party (including our affiliates and subsidiaries), including through any application or content (including advertising) that may link to or be accessible from or on the App.
Please read this policy carefully to understand our policies and practices regarding your information and how we will treat it. If you do not agree with our policies and practices, you have the choice to not use the App. By accessing or using this App, you agree to this privacy policy. This policy may change from time to time. Your continued use of this App after we make changes is deemed to be acceptance of those changes, so please check the policy periodically for updates.
Definitions
"App" means the software program provided by the Company, downloaded by You on any electronic device, named Cake Wallet.
"Device" means any device that can access the App, such as a cell phone or tablet device.
"Node" means a full Monero or Bitcoin Node, which transmits data to your App for processing and synchronization, and to which your Device transmits transactions which you would like to submit to the Monero or Bitcoin networks.
"Cake Wallet Nodes" refers to the set of cryptocurrency nodes operated and maintained by Cake Technologies.
"Service" refers to the App.
"Third-party Service" refers to any service integrated into the Cake Wallet Application. This includes ChangeNow and XMR.to.
"Usage Data" refers to data collected automatically about your usage of an Application.
"You" means the individual, group, corporation, or any other entity accessing or using the Service.
Last modified: February 23, 2021
Introduction
============
Cake Technologies Inc. ("Company" or "We") respect your privacy and are committed to protecting it through our compliance with this policy.
This policy describes the types of information we may collect from you or that you may provide when you use the App (our "App") and our practices for collecting, using, maintaining, protecting, and disclosing that information.
This policy applies to information we collect:
- On this App.
- In email, text, and other electronic messages between you and this App.
It does not apply to information collected by:
- Us offline or through any other means, including on any other App operated by Company or any third party (including our affiliates and subsidiaries)]; or
- Any third party (including our affiliates and subsidiaries), including through any application or content (including advertising) that may link to or be accessible from or on the App.
Please read this policy carefully to understand our policies and practices regarding your information and how we will treat it. If you do not agree with our policies and practices, you have the choice to not use the App. By accessing or using this App, you agree to this privacy policy. This policy may change from time to time. Your continued use of this App after we make changes is deemed to be acceptance of those changes, so please check the policy periodically for updates.
Definitions
-----------
- "App" means the software program provided by the Company, downloaded by You on any electronic device, named Cake Wallet.
- "Device" means any device that can access the App, such as a cell phone or tablet device.
- "Node" means a full Monero or Bitcoin Node, which transmits data to your App for processing and synchronization, and to which your Device transmits transactions which you would like to submit to the Monero or Bitcoin networks.
- "Cake Wallet Nodes" refers to the set of cryptocurrency nodes operated and maintained by Cake Technologies.
- "Service" refers to the App.
- "Third-party Service" refers to any service integrated into the Cake Wallet Application. This includes ChangeNow.
- "Usage Data" refers to data collected automatically about your usage of an Application.
- "You" means the individual, group, corporation, or any other entity accessing or using the Service.
Information We Collect About You and How We Collect It
We collect several types of information from and about users of our App, including information:
By which you may be personally identified, such as name, e-mail address, or and a/any other identifier by which you may be contacted online or offline ("personal information" or "Personal Data”), ONLY when you provide it to us;
Device IP address, the block height to which your wallet is synchronized, and any transactions which you use our Node to submit to the Monero or Bitcoin networks.
We collect this information:
Directly from you when you provide it to us.
Automatically as you use the App, if you use one of the Cake Wallet Nodes. Information collected automatically may include IP address and block height.
Usage Data (including the date and time at which you use an application, the duration of using it, and other metadata) is NOT collected by Cake Technologies through the usage of the App. Cake Technologies has no reason to care about any aspect of your continued usage of our App. We believe that this data is your own property and that we have no right to collect it.
Personal information is received by Cake Technologies ONLY in the event that you choose to provide it to us. This is provided either by synchronizing your wallet using the Nodes maintained by Cake Technologies, or by voluntarily contacting Cake Technologies regarding support, questions or suggestions. You also have the right to choose not to provide data to Cake Technologies, by choosing a different Node. The option to do so is provided by default with a list of Nodes, but Cake Wallet also provides the ability to add another Node not listed, or use your own Node.
Data relating to your funds, and their security and privacy, remains on your device at ALL times. Your private keys, seeds, backup files, and wallet passcode are your own responsibility. This data is not received, collected, or stored by Cake Technologies at any time, for any reason.
Personal Data collected through the Cake Wallet Nodes is limited to your device's IP address, the block height to which your wallet is synchronized, and any transactions which you use our Node to submit to the Monero or Bitcoin networks.
Personal Data received by Cake Technologies in this manner is not stored for any length of time, and thus Cake Technologies is both unwilling to and incapable of sharing this data, or using it for any purpose beyond ensuring your appropriate connection to our Nodes.
If you decide to use a Node offered by any third party, some of which we offer by default in the Cake Wallet Application, said third party will receive this Personal Data instead of Cake Technologies. We take no responsibility for the actions of any third-party Node offered within the Application.
------------------------------------------------------
We collect several types of information from and about users of our App, including information:
- By which you may be personally identified, such as name, e-mail address, or and a/any other identifier by which you may be contacted online or offline ("personal information" or "Personal Data”), ONLY when you provide it to us;
- Device IP address, the block height to which your wallet is synchronized, and any transactions which you use our Node to submit to the Monero or Bitcoin networks.
We collect this information:
- Directly from you when you provide it to us.
- Automatically as you use the App, if you use one of the Cake Wallet Nodes. Information collected automatically may include IP address and block height.
Usage Data (including the date and time at which you use an application, the duration of using it, and other metadata) is NOT collected by Cake Technologies through the usage of the App. Cake Technologies has no reason to care about any aspect of your continued usage of our App. We believe that this data is your own property and that we have no right to collect it.
Personal information is received by Cake Technologies ONLY in the event that you choose to provide it to us. This is provided either by synchronizing your wallet using the Nodes maintained by Cake Technologies, or by voluntarily contacting Cake Technologies regarding support, questions or suggestions. You also have the right to choose not to provide data to Cake Technologies, by choosing a different Node. The option to do so is provided by default with a list of Nodes, but Cake Wallet also provides the ability to add another Node not listed, or use your own Node.
Data relating to your funds, and their security and privacy, remains on your device at ALL times. Your private keys, seeds, backup files, and wallet passcode are your own responsibility. This data is not received, collected, or stored by Cake Technologies at any time, for any reason.
Personal Data collected through the Cake Wallet Nodes is limited to your device's IP address, the block height to which your wallet is synchronized, and any transactions which you use our Node to submit to the Monero or Bitcoin networks. Personal Data received by Cake Technologies in this manner is not stored for any length of time, and thus Cake Technologies is both unwilling to and incapable of sharing this data, or using it for any purpose beyond ensuring your appropriate connection to our Nodes.
If you decide to use a Node offered by any third party, some of which we offer by default in the Cake Wallet Application, said third party will receive this Personal Data instead of Cake Technologies. We take no responsibility for the actions of any third-party Node offered within the Application. If you decide to synchronize your Wallet using your own Node, neither Cake Technologies nor any third party will have access to this Personal Data.
In any of these situations, Cake Technologies takes no responsibility for interception of this data by any outside individual, group, corporation, or institution. You should understand this and take any and all appropriate actions to secure your own data.
If you decide to synchronize your Wallet using your own Node, neither Cake Technologies nor any third party will have access to this Personal Data.
In any of these situations, Cake Technologies takes no responsibility for interception of this data by any outside individual, group, corporation, or institution. You should understand this and take any and all appropriate actions to secure your own data.
How We Use Your Information
We use information that we collect about you or that you provide to us, including any personal information:
To present our App and its contents to you.
To allow you to sync using the closest geographical Node: In the event that you choose to synchronize your wallet using the Node maintained by Cake Technologies, we determine your location using your IP address to redirect your Wallet to the fastest possible Node.
To contact you: In the event that you contact Cake Technologies first, we will use the Personal Data with which you provide us, to contact you by email, Telegram, Reddit, or any other means.
To manage your requests: To attend and manage your requests to us.
For any other purpose with your consent.
---------------------------
We use information that we collect about you or that you provide to us, including any personal information:
- To present our App and its contents to you.
- To allow you to sync using the closest geographical Node: In the event that you choose to synchronize your wallet using the Node maintained by Cake Technologies, we determine your location using your IP address to redirect your Wallet to the fastest possible Node.
- To contact you: In the event that you contact Cake Technologies first, we will use the Personal Data with which you provide us, to contact you by email, Telegram, Reddit, or any other means.
- To manage your requests: To attend and manage your requests to us.
- For any other purpose with your consent.
Transfer of Your Personal Data
Personal Data received by the Cake Wallet Nodes, or voluntarily submitted to Cake Technologies through e-mail, Telegram, Reddit, or any other method, may be transferred to computers located outside of your governmental jurisdiction, where the data protection laws may differ from yours.
Your consent to this Privacy Policy, and your submission of such information, represents your agreement to this transfer.
Cake Technologies will take all necessary steps to ensure that your data is treated securely and in accordance with this Privacy Policy. No transfer of your Personal Data will take place to an organization or a country, unless there are adequate controls in place to protect the security of your data.
------------------------------
Personal Data received by the Cake Wallet Nodes, or voluntarily submitted to Cake Technologies through e-mail, Telegram, Reddit, or any other method, may be transferred to computers located outside of your governmental jurisdiction, where the data protection laws may differ from yours. Your consent to this Privacy Policy, and your submission of such information, represents your agreement to this transfer.
Cake Technologies will take all necessary steps to ensure that your data is treated securely and in accordance with this Privacy Policy. No transfer of your Personal Data will take place to an organization or a country, unless there are adequate controls in place to protect the security of your data.
Disclosure of Your Information
We may disclose aggregated information about our users, and information that does not identify any individual, without restriction. For example, we may, from time to time, disclose the number of users who have downloaded our Application.
We may disclose personal information that we collect or you provide as described in this privacy policy:
To our subsidiaries and affiliates.
To contractors, service providers, and other third parties we use to support our business and who are bound by contractual obligations to keep personal information confidential and use it only for the purposes for which we disclose it to them.
To a buyer or other successor in the event of a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Cake Technology's assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which personal information held by Cake Technology about our App users is among the assets transferred. However, we will provide notice before this Personal Data is transferred and becomes subject to a different Privacy Policy.
To fulfill the purpose for which you provide it.
For any other purpose disclosed by us when you provide the information.
With your consent.
We may also disclose your personal information:
To comply with any court order, law, or legal process, including to respond to any government or regulatory request.
To enforce or apply our terms of use and other agreements, including for billing and collection purposes.
If we believe disclosure is necessary or appropriate to protect the rights, property, or safety of Cake Technologies, our customers, or others.
Cake Technologies is incapable of providing any authority or government agency with data received by the Cake Wallet Nodes, because we do not store this data.
Under certain circumstances, Cake Technologies may be required by authorities to disclose Personal Data which you voluntarily provide us, including your e-mail address, Telegram username, or Reddit username. WE STRONGLY RECOMMEND THAT YOU DO NOT TRANSMIT ANY PERSONALLY IDENTIFIABLE INFORMATION TO US VIA THESE OR ANY OTHER METHODS.
------------------------------
We may disclose aggregated information about our users, and information that does not identify any individual, without restriction. For example, we may, from time to time, disclose the number of users who have downloaded our Application.
We may disclose personal information that we collect or you provide as described in this privacy policy:
- To our subsidiaries and affiliates.
- To contractors, service providers, and other third parties we use to support our business and who are bound by contractual obligations to keep personal information confidential and use it only for the purposes for which we disclose it to them.
- To a buyer or other successor in the event of a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Cake Technology's assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which personal information held by Cake Technology about our App users is among the assets transferred. However, we will provide notice before this Personal Data is transferred and becomes subject to a different Privacy Policy.
- To fulfill the purpose for which you provide it.
- For any other purpose disclosed by us when you provide the information.
- With your consent.
We may also disclose your personal information:
- To comply with any court order, law, or legal process, including to respond to any government or regulatory request.
- To enforce or apply our terms of use and other agreements, including for billing and collection purposes.
- If we believe disclosure is necessary or appropriate to protect the rights, property, or safety of Cake Technologies, our customers, or others.
Cake Technologies is incapable of providing any authority or government agency with data received by the Cake Wallet Nodes, because we do not store this data.
Under certain circumstances, Cake Technologies may be required by authorities to disclose Personal Data which you voluntarily provide us, including your e-mail address, Telegram username, or Reddit username. WE STRONGLY RECOMMEND THAT YOU DO NOT TRANSMIT ANY PERSONALLY IDENTIFIABLE INFORMATION TO US VIA THESE OR ANY OTHER METHODS.
Data Security
You are responsible for your personal data, including all data related to the safety of your funds. You should take all appropriate action to protect this data. Cake Technologies cannot recover any data related to your funds in the event that you lose or give away this data. Cake Technologies strongly recommends that you take action to secure your funds, by writing down your seeds or keys, storing encrypted backups, and never sharing this information.
Cake Technologies undertakes any and all reasonable steps possible to secure any data that you voluntarily transmit to us. However, we cannot guarantee that any outside system used to transmit this data is entirely secure and, as such, we recommend that you exercise caution when voluntarily transmitting data to us.
-------------
You are responsible for your personal data, including all data related to the safety of your funds. You should take all appropriate action to protect this data. Cake Technologies cannot recover any data related to your funds in the event that you lose or give away this data. Cake Technologies strongly recommends that you take action to secure your funds, by writing down your seeds or keys, storing encrypted backups, and never sharing this information.
Cake Technologies undertakes any and all reasonable steps possible to secure any data that you voluntarily transmit to us. However, we cannot guarantee that any outside system used to transmit this data is entirely secure and, as such, we recommend that you exercise caution when voluntarily transmitting data to us.
Links to Other Websites
The App may contain links to other websites that are not operated by us. If you click on a third-party link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit. We have no control over and assume no responsibility for the content, privacy policies or practices of any third-party sites or services.
-----------------------
The App may contain links to other websites that are not operated by us. If you click on a third-party link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit. We have no control over and assume no responsibility for the content, privacy policies or practices of any third-party sites or services.
Changes to Our Privacy Policy
It is our policy to post any changes we make to our privacy policy on this page. If we make material changes to how we treat our users' personal information, we will notify you through a notice on the App. The date the privacy policy was last revised is identified at the top of this document. You are responsible for periodically visiting our App and this privacy policy to check for any changes to our Privacy Policy.
Contact Us
-----------------------------
It is our policy to post any changes we make to our privacy policy on this page. If we make material changes to how we treat our users' personal information, we will notify you through a notice on the App. The date the privacy policy was last revised is identified at the top of this document. You are responsible for periodically visiting our App and this privacy policy to check for any changes to our Privacy Policy.
Contact Us
----------
If you have any questions about this Privacy Policy, you are encouraged to contact us by email at info@cakewallet.com.

View file

@ -15,7 +15,8 @@ class AddressValidator extends TextValidator {
case CryptoCurrency.xmr:
return '[0-9a-zA-Z]';
case CryptoCurrency.ada:
return '[0-9a-zA-Z]';
return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
case CryptoCurrency.bch:
return '[0-9a-zA-Z]';
case CryptoCurrency.bnb:
@ -54,7 +55,7 @@ class AddressValidator extends TextValidator {
case CryptoCurrency.xmr:
return [95, 106];
case CryptoCurrency.ada:
return [59, 92, 104, 105];
return null;
case CryptoCurrency.bch:
return [42];
case CryptoCurrency.bnb:

View file

@ -29,6 +29,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
static const _exchangeAmountUriSufix = '/exchange-amount/';
static const _transactionsUriSufix = '/transactions/';
static const _minAmountUriSufix = '/min-amount/';
static const _marketInfoUriSufix = '/market-info/';
static const _fixedRateUriSufix = 'fixed-rate/';
@override
String get title => 'ChangeNOW';
@ -44,19 +46,43 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
Future<bool> checkIsAvailable() async => true;
@override
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to,
bool isFixedRateMode}) async {
final symbol = from.toString() + '_' + to.toString();
final url = apiUri + _minAmountUriSufix + symbol;
final url = isFixedRateMode
? apiUri + _marketInfoUriSufix + _fixedRateUriSufix + apiKey
: apiUri + _minAmountUriSufix + symbol;
final response = await get(url);
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final min = responseJSON['minAmount'] as double;
return Limits(min: min, max: null);
if (isFixedRateMode) {
final responseJSON = json.decode(response.body) as List<dynamic>;
for (var elem in responseJSON) {
final elemFrom = elem["from"] as String;
final elemTo = elem["to"] as String;
if ((elemFrom == from.toString().toLowerCase()) &&
(elemTo == to.toString().toLowerCase())) {
final min = elem["min"] as double;
final max = elem["max"] as double;
return Limits(min: min, max: max);
}
}
return Limits(min: 0, max: 0);
} else {
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final min = responseJSON['minAmount'] as double;
return Limits(min: min, max: null);
}
}
@override
Future<Trade> createTrade({TradeRequest request}) async {
const url = apiUri + _transactionsUriSufix + apiKey;
Future<Trade> createTrade({TradeRequest request, bool isFixedRateMode}) async {
final url = isFixedRateMode
? apiUri + _transactionsUriSufix + _fixedRateUriSufix + apiKey
: apiUri + _transactionsUriSufix + apiKey;
final _request = request as ChangeNowRequest;
final body = {
'from': _request.from.toString(),
@ -127,17 +153,35 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
final state = TradeState.deserialize(raw: status);
final extraId = responseJSON['payinExtraId'] as String;
final outputTransaction = responseJSON['payoutHash'] as String;
final expiredAtRaw = responseJSON['validUntil'] as String;
final expiredAt = expiredAtRaw != null
? DateTime.parse(expiredAtRaw).toLocal()
: null;
return Trade(
id: id,
from: from,
to: to,
provider: description,
inputAddress: inputAddress,
amount: expectedSendAmount,
state: state,
extraId: extraId,
outputTransaction: outputTransaction);
if (expiredAt != null) {
return Trade(
id: id,
from: from,
to: to,
provider: description,
inputAddress: inputAddress,
amount: expectedSendAmount,
state: state,
extraId: extraId,
expiredAt: expiredAt,
outputTransaction: outputTransaction);
} else {
return Trade(
id: id,
from: from,
to: to,
provider: description,
inputAddress: inputAddress,
amount: expectedSendAmount,
state: state,
extraId: extraId,
outputTransaction: outputTransaction);
}
}
@override
@ -145,18 +189,54 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
{CryptoCurrency from,
CryptoCurrency to,
double amount,
bool isFixedRateMode,
bool isReceiveAmount}) async {
final url = apiUri +
_exchangeAmountUriSufix +
amount.toString() +
'/' +
from.toString() +
'_' +
to.toString();
final response = await get(url);
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final estimatedAmount = responseJSON['estimatedAmount'] as double;
if (isReceiveAmount && isFixedRateMode) {
final url = apiUri + _marketInfoUriSufix + _fixedRateUriSufix + apiKey;
final response = await get(url);
final responseJSON = json.decode(response.body) as List<dynamic>;
var rate = 0.0;
var fee = 0.0;
return estimatedAmount;
for (var elem in responseJSON) {
final elemFrom = elem["from"] as String;
final elemTo = elem["to"] as String;
if ((elemFrom == to.toString().toLowerCase()) &&
(elemTo == from.toString().toLowerCase())) {
rate = elem["rate"] as double;
fee = elem["minerFee"] as double;
break;
}
}
final estimatedAmount = (amount == 0.0)||(rate == 0.0) ? 0.0
: (amount + fee)/rate;
return estimatedAmount;
} else {
final url = isFixedRateMode
? apiUri +
_exchangeAmountUriSufix +
_fixedRateUriSufix +
amount.toString() +
'/' +
from.toString() +
'_' +
to.toString() +
'?api_key=' + apiKey
: apiUri +
_exchangeAmountUriSufix +
amount.toString() +
'/' +
from.toString() +
'_' +
to.toString();
final response = await get(url);
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
final estimatedAmount = responseJSON['estimatedAmount'] as double;
return estimatedAmount;
}
}
}

View file

@ -17,10 +17,11 @@ abstract class ExchangeProvider {
@override
String toString() => title;
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to});
Future<Trade> createTrade({TradeRequest request});
Future<Limits> fetchLimits(
{CryptoCurrency from, CryptoCurrency to, bool isFixedRateMode});
Future<Trade> createTrade({TradeRequest request, bool isFixedRateMode});
Future<Trade> findTradeById({@required String id});
Future<double> calculateAmount(
{CryptoCurrency from, CryptoCurrency to, double amount, bool isReceiveAmount});
Future<double> calculateAmount({CryptoCurrency from, CryptoCurrency to,
double amount, bool isFixedRateMode, bool isReceiveAmount});
Future<bool> checkIsAvailable();
}

View file

@ -71,7 +71,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider {
Future<bool> checkIsAvailable() async => true;
@override
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to, bool isFixedRateMode}) async {
final url = apiUri + _limitsURISuffix;
final headers = {'Content-type': 'application/json'};
final body = json.encode({
@ -100,7 +100,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({TradeRequest request}) async {
Future<Trade> createTrade({TradeRequest request, bool isFixedRateMode}) async {
const url = apiUri + _morphURISuffix;
final _request = request as MorphTokenRequest;
final body = {
@ -191,7 +191,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider {
@override
Future<double> calculateAmount(
{CryptoCurrency from, CryptoCurrency to, double amount,
{CryptoCurrency from, CryptoCurrency to, double amount, bool isFixedRateMode,
bool isReceiveAmount}) async {
final url = apiUri + _ratesURISuffix;
final response = await get(url);

View file

@ -58,7 +58,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
}
@override
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to}) async {
Future<Limits> fetchLimits({CryptoCurrency from, CryptoCurrency to, bool isFixedRateMode}) async {
final url = originalApiUri + _orderParameterUriSuffix;
final response = await get(url);
final correction = 0.001;
@ -91,7 +91,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
}
@override
Future<Trade> createTrade({TradeRequest request}) async {
Future<Trade> createTrade({TradeRequest request, bool isFixedRateMode}) async {
final _request = request as XMRTOTradeRequest;
final url = originalApiUri + _orderCreateUriSuffix;
final _amount =
@ -188,6 +188,7 @@ class XMRTOExchangeProvider extends ExchangeProvider {
{CryptoCurrency from,
CryptoCurrency to,
double amount,
bool isFixedRateMode,
bool isReceiveAmount}) async {
if (from != CryptoCurrency.xmr && to != CryptoCurrency.btc) {
return 0;

View file

@ -35,7 +35,7 @@ class S implements WidgetsLocalizations {
String get all => "ALL";
String get amount => "Amount: ";
String get amount_is_estimate => "The receive amount is an estimate";
String get amount_is_guaranteed => "In xmr.to, to receive a guaranteed BTC amount, enter the BTC amount and not the XMR amount above";
String get amount_is_guaranteed => "The receive amount is guaranteed";
String get auth_store_ban_timeout => "ban_timeout";
String get auth_store_banned_for => "Banned for ";
String get auth_store_banned_minutes => " minutes";
@ -395,6 +395,10 @@ class S implements WidgetsLocalizations {
String get confirmed => 'Confirmed';
String get unconfirmed => 'Unconfirmed';
String get displayable => 'Displayable';
String get fixed_rate => 'Fixed rate';
String get fixed_rate_alert => 'You will be able to enter receive amount when fixed rate mode is checked. Do you want to switch to fixed rate mode?';
String get xlm_extra_info => 'Please dont forget to specify the Memo ID while sending the XLM transaction for the exchange';
String get xrp_extra_info => 'Please dont forget to specify the Destination Tag while sending the XRP transaction for the exchange';
}
class $de extends S {
@ -536,7 +540,7 @@ class $de extends S {
@override
String get receive => "Erhalten";
@override
String get amount_is_guaranteed => "Geben Sie in xmr.to den BTC-Betrag und nicht den oben genannten XMR-Betrag ein, um einen garantierten BTC-Betrag zu erhalten";
String get amount_is_guaranteed => "Der Empfangsbetrag ist garantiert";
@override
String get auth_store_banned_for => "Gebannt für ";
@override
@ -1151,6 +1155,14 @@ class $de extends S {
String get unconfirmed => 'Unbestätigt';
@override
String get displayable => 'Anzeigebar';
@override
String get fixed_rate => 'Fester Zinssatz';
@override
String get fixed_rate_alert => 'Sie können den Empfangsbetrag eingeben, wenn der Festpreismodus aktiviert ist. Möchten Sie in den Festpreismodus wechseln?';
@override
String get xlm_extra_info => 'Bitte vergessen Sie nicht, die Memo-ID anzugeben, während Sie die XLM-Transaktion für den Austausch senden';
@override
String get xrp_extra_info => 'Bitte vergessen Sie nicht, das Ziel-Tag anzugeben, während Sie die XRP-Transaktion für den Austausch senden';
}
class $hi extends S {
@ -1292,7 +1304,7 @@ class $hi extends S {
@override
String get receive => "प्राप्त करना";
@override
String get amount_is_guaranteed => "Xmr.to में, गारंटीशुदा BTC राशि प्राप्त करने के लिए, BTC राशि दर्ज करें और ऊपर XMR राशि नही";
String get amount_is_guaranteed => "प्राप्त राशि की गारंटी है";
@override
String get auth_store_banned_for => "के लिए प्रतिबंधित है ";
@override
@ -1907,6 +1919,14 @@ class $hi extends S {
String get unconfirmed => 'अपुष्ट';
@override
String get displayable => 'प्रदर्शन योग्य';
@override
String get fixed_rate => 'निर्धारित दर';
@override
String get fixed_rate_alert => 'फिक्स्ड रेट मोड की जांच करने पर आप प्राप्त राशि दर्ज कर पाएंगे। क्या आप निश्चित दर मोड पर स्विच करना चाहते हैं?';
@override
String get xlm_extra_info => 'एक्सचेंज के लिए XLM ट्रांजेक्शन भेजते समय मेमो आईडी निर्दिष्ट करना न भूलें';
@override
String get xrp_extra_info => 'एक्सचेंज के लिए एक्सआरपी लेनदेन भेजते समय कृपया गंतव्य टैग निर्दिष्ट करना न भूलें';
}
class $ru extends S {
@ -2048,7 +2068,7 @@ class $ru extends S {
@override
String get receive => "Получить";
@override
String get amount_is_guaranteed => "В xmr.to, чтобы получить гарантированную сумму BTC, введите сумму BTC, а не сумму XMR выше";
String get amount_is_guaranteed => "Полученная сумма гарантирована";
@override
String get auth_store_banned_for => "Заблокировано на ";
@override
@ -2663,6 +2683,14 @@ class $ru extends S {
String get unconfirmed => 'Неподтвержденный';
@override
String get displayable => 'Отображаемый';
@override
String get fixed_rate => 'Фиксированная ставка';
@override
String get fixed_rate_alert => 'Вы сможете ввести сумму получения тогда, когда будет установлен режим фиксированной ставки. Вы хотите перейти в режим фиксированной ставки?';
@override
String get xlm_extra_info => 'Не забудьте указать Memo ID (памятка) при отправке транзакции XLM для обмена';
@override
String get xrp_extra_info => 'Не забудьте указать целевой тег при отправке транзакции XRP для обмена';
}
class $ko extends S {
@ -2804,7 +2832,7 @@ class $ko extends S {
@override
String get receive => "받다";
@override
String get amount_is_guaranteed => "xmr.to에서 보장 된 BTC 금액을 받으려면 위의 XMR 금액이 아닌 BTC 금액을 입력하십시오.";
String get amount_is_guaranteed => "수령 금액이 보장됩니다.";
@override
String get auth_store_banned_for => "금지";
@override
@ -3419,6 +3447,14 @@ class $ko extends S {
String get unconfirmed => '미확인';
@override
String get displayable => '표시 가능';
@override
String get fixed_rate => '고정 비율';
@override
String get fixed_rate_alert => '고정 금리 모드 체크시 수취 금액 입력이 가능합니다. 고정 속도 모드로 전환 하시겠습니까?';
@override
String get xlm_extra_info => '교환을 위해 XLM 거래를 보낼 때 메모 ID를 지정하는 것을 잊지 마십시오';
@override
String get xrp_extra_info => '교환을 위해 XRP 트랜잭션을 보내는 동안 대상 태그를 지정하는 것을 잊지 마십시오';
}
class $pt extends S {
@ -3560,7 +3596,7 @@ class $pt extends S {
@override
String get receive => "Receber";
@override
String get amount_is_guaranteed => "Em xmr.to, para receber um valor BTC garantido, insira o valor BTC e não o valor XMR acima";
String get amount_is_guaranteed => "O valor recebido é garantido";
@override
String get auth_store_banned_for => "Banido por";
@override
@ -4175,6 +4211,14 @@ class $pt extends S {
String get unconfirmed => 'Não confirmado';
@override
String get displayable => 'Exibível';
@override
String get fixed_rate => 'Taxa fixa';
@override
String get fixed_rate_alert => 'Você poderá inserir a quantia recebida quando o modo de taxa fixa estiver marcado. Quer mudar para o modo de taxa fixa?';
@override
String get xlm_extra_info => 'Não se esqueça de especificar o Memo ID ao enviar a transação XLM para a troca';
@override
String get xrp_extra_info => 'Não se esqueça de especificar a etiqueta de destino ao enviar a transação XRP para a troca';
}
class $uk extends S {
@ -4316,7 +4360,7 @@ class $uk extends S {
@override
String get receive => "Отримати";
@override
String get amount_is_guaranteed => "У xmr.to, щоб отримати гарантовану суму BTC, введіть суму BTC, а не XMR вище";
String get amount_is_guaranteed => "Отримана сума є гарантованою";
@override
String get auth_store_banned_for => "Заблоковано на ";
@override
@ -4931,6 +4975,14 @@ class $uk extends S {
String get unconfirmed => 'Непідтверджений';
@override
String get displayable => 'Відображуваний';
@override
String get fixed_rate => 'Фіксована ставка';
@override
String get fixed_rate_alert => 'Ви зможете ввести суму отримання тоді, коли буде встановлений режим фіксованої ставки. Ви хочете перейти в режим фіксованої ставки?';
@override
String get xlm_extra_info => "Будь ласка, не забудьте вказати ідентифікатор пам'ятки під час надсилання транзакції XLM для обміну";
@override
String get xrp_extra_info => 'Будь ласка, не забудьте вказати тег призначення під час надсилання XRP-транзакції для обміну';
}
class $ja extends S {
@ -5072,7 +5124,7 @@ class $ja extends S {
@override
String get receive => "受け取る";
@override
String get amount_is_guaranteed => "xmr.toで、保証されたBTC金額を受け取るには、上記のXMR金額ではなく、BTC金額を入力します";
String get amount_is_guaranteed => "受け取り金額は保証されています";
@override
String get auth_store_banned_for => "禁止されています ";
@override
@ -5687,6 +5739,14 @@ class $ja extends S {
String get unconfirmed => '未確認';
@override
String get displayable => '表示可能';
@override
String get fixed_rate => '固定金利';
@override
String get fixed_rate_alert => '固定金利モードにチェックを入れると、受取額を入力できるようになります。 固定金利モードに切り替えますか?';
@override
String get xlm_extra_info => '交換用のXLMトランザクションを送信するときに、メモIDを指定することを忘れないでください';
@override
String get xrp_extra_info => '取引所のXRPトランザクションを送信するときに、宛先タグを指定することを忘れないでください';
}
class $en extends S {
@ -5832,7 +5892,7 @@ class $pl extends S {
@override
String get receive => "Otrzymać";
@override
String get amount_is_guaranteed => "W xmr.to, aby otrzymać gwarantowaną kwotę BTC, wprowadź kwotę BTC, a nie kwotę XMR powyżej";
String get amount_is_guaranteed => "Otrzymana kwota jest gwarantowana";
@override
String get auth_store_banned_for => "Bzbanowany za ";
@override
@ -6447,6 +6507,14 @@ class $pl extends S {
String get unconfirmed => 'niepotwierdzony';
@override
String get displayable => 'Wyświetlane';
@override
String get fixed_rate => 'Stała stawka';
@override
String get fixed_rate_alert => 'Będziesz mógł wprowadzić kwotę otrzymaną, gdy zaznaczony jest tryb stałej stawki. Czy chcesz przejść do trybu stałej stawki?';
@override
String get xlm_extra_info => 'Nie zapomnij podać identyfikatora notatki podczas wysyłania transakcji XLM do wymiany';
@override
String get xrp_extra_info => 'Nie zapomnij podać tagu docelowego podczas wysyłania transakcji XRP do wymiany';
}
class $es extends S {
@ -6588,7 +6656,7 @@ class $es extends S {
@override
String get receive => "Recibir";
@override
String get amount_is_guaranteed => "En xmr.to, para recibir una cantidad BTC garantizada, ingrese la cantidad BTC y no la cantidad XMR arriba";
String get amount_is_guaranteed => "La cantidad recibida está garantizada";
@override
String get auth_store_banned_for => "Prohibido para ";
@override
@ -7203,6 +7271,14 @@ class $es extends S {
String get unconfirmed => 'inconfirmado';
@override
String get displayable => 'Visualizable';
@override
String get fixed_rate => 'Tipo de interés fijo';
@override
String get fixed_rate_alert => 'Podrá ingresar la cantidad recibida cuando el modo de tarifa fija esté marcado. ¿Quieres cambiar al modo de tarifa fija?';
@override
String get xlm_extra_info => 'No olvide especificar el ID de nota al enviar la transacción XLM para el intercambio';
@override
String get xrp_extra_info => 'No olvide especificar la etiqueta de destino al enviar la transacción XRP para el intercambio';
}
class $nl extends S {
@ -7344,7 +7420,7 @@ class $nl extends S {
@override
String get receive => "Krijgen";
@override
String get amount_is_guaranteed => "Om een gegarandeerd BTC-bedrag te ontvangen, voert u in xmr.to het BTC-bedrag in en niet het bovenstaande XMR-bedrag";
String get amount_is_guaranteed => "Het ontvangen bedrag is gegarandeerd";
@override
String get auth_store_banned_for => "Verboden voor ";
@override
@ -7959,6 +8035,14 @@ class $nl extends S {
String get unconfirmed => 'niet bevestigd';
@override
String get displayable => 'Weer te geven';
@override
String get fixed_rate => 'Vast tarief';
@override
String get fixed_rate_alert => 'U kunt het ontvangen bedrag invoeren wanneer de modus voor vaste tarieven is aangevinkt. Wilt u overschakelen naar de vaste-tariefmodus?';
@override
String get xlm_extra_info => 'Vergeet niet om de Memo-ID op te geven tijdens het verzenden van de XLM-transactie voor de uitwisseling';
@override
String get xrp_extra_info => 'Vergeet niet om de Destination Tag op te geven tijdens het verzenden van de XRP-transactie voor de uitwisseling';
}
class $zh extends S {
@ -8100,7 +8184,7 @@ class $zh extends S {
@override
String get receive => "接收";
@override
String get amount_is_guaranteed => "在xmr.to中要接收保证的BTC数量请输入BTC数量而不要输入上方的XMR数量";
String get amount_is_guaranteed => "接收金額有保證";
@override
String get auth_store_banned_for => "禁止 ";
@override
@ -8715,6 +8799,14 @@ class $zh extends S {
String get unconfirmed => '未经证实';
@override
String get displayable => '可显示';
@override
String get fixed_rate => '固定利率';
@override
String get fixed_rate_alert => '選中固定費率模式後,您將可以輸入接收金額。 您要切換到固定速率模式嗎?';
@override
String get xlm_extra_info => '發送用於交換的XLM交易時請不要忘記指定備忘錄ID';
@override
String get xrp_extra_info => '發送用於交換的XRP交易時請不要忘記指定目標標記';
}
class GeneratedLocalizationsDelegate extends LocalizationsDelegate<S> {

View file

@ -1,6 +1,8 @@
import 'dart:ui';
import 'package:cake_wallet/entities/sync_status.dart';
import 'package:cake_wallet/entities/wallet_type.dart';
import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart';
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
import 'package:dotted_border/dotted_border.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -37,6 +39,7 @@ class ExchangePage extends BasePage {
final ExchangeViewModel exchangeViewModel;
final depositKey = GlobalKey<ExchangeCardState>();
final receiveKey = GlobalKey<ExchangeCardState>();
final checkBoxKey = GlobalKey<StandardCheckboxState>();
final _formKey = GlobalKey<FormState>();
final _depositAmountFocus = FocusNode();
final _receiveAmountFocus = FocusNode();
@ -115,7 +118,7 @@ class ExchangePage extends BasePage {
key: _formKey,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: Column(
content: Observer(builder: (_) => Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(bottom: 32),
@ -165,22 +168,22 @@ class ExchangePage extends BasePage {
hasAllAmount: exchangeViewModel.hasAllAmount,
allAmount: exchangeViewModel.hasAllAmount
? () => exchangeViewModel
.calculateDepositAllAmount()
.calculateDepositAllAmount()
: null,
amountFocusNode: _depositAmountFocus,
key: depositKey,
title: S.of(context).you_will_send,
initialCurrency:
exchangeViewModel.depositCurrency,
exchangeViewModel.depositCurrency,
initialWalletName: depositWalletName,
initialAddress:
exchangeViewModel.depositCurrency ==
exchangeViewModel.wallet.currency
? exchangeViewModel.wallet.address
: exchangeViewModel.depositAddress,
exchangeViewModel.depositCurrency ==
exchangeViewModel.wallet.currency
? exchangeViewModel.wallet.address
: exchangeViewModel.depositAddress,
initialIsAmountEditable: true,
initialIsAddressEditable:
exchangeViewModel.isDepositAddressEnabled,
exchangeViewModel.isDepositAddressEnabled,
isAmountEstimated: false,
hasRefundAddress: true,
currencies: CryptoCurrency.all,
@ -211,7 +214,7 @@ class ExchangePage extends BasePage {
imageArrow: arrowBottomPurple,
currencyButtonColor: Colors.transparent,
addressButtonsColor:
Theme.of(context).focusColor,
Theme.of(context).focusColor,
borderColor: Theme.of(context)
.primaryTextTheme
.body2
@ -225,52 +228,65 @@ class ExchangePage extends BasePage {
),
Padding(
padding:
EdgeInsets.only(top: 29, left: 24, right: 24),
EdgeInsets.only(top: 29, left: 24, right: 24),
child: Observer(
builder: (_) => ExchangeCard(
amountFocusNode: _receiveAmountFocus,
key: receiveKey,
title: S.of(context).you_will_get,
initialCurrency:
exchangeViewModel.receiveCurrency,
initialWalletName: receiveWalletName,
initialAddress: exchangeViewModel
.receiveCurrency ==
exchangeViewModel.wallet.currency
? exchangeViewModel.wallet.address
: exchangeViewModel.receiveAddress,
initialIsAmountEditable: exchangeViewModel
.provider is XMRTOExchangeProvider
? true
: false,
initialIsAddressEditable:
exchangeViewModel
.isReceiveAddressEnabled,
isAmountEstimated: true,
currencies: CryptoCurrency.all,
onCurrencySelected: (currency) =>
exchangeViewModel
.changeReceiveCurrency(
currency: currency),
imageArrow: arrowBottomCakeGreen,
currencyButtonColor: Colors.transparent,
addressButtonsColor:
Theme.of(context).focusColor,
borderColor: Theme.of(context)
.primaryTextTheme
.body2
.decorationColor,
currencyValueValidator: AmountValidator(
type: exchangeViewModel.wallet.type),
addressTextFieldValidator:
AddressValidator(
type: exchangeViewModel
.receiveCurrency),
)),
amountFocusNode: _receiveAmountFocus,
key: receiveKey,
title: S.of(context).you_will_get,
initialCurrency:
exchangeViewModel.receiveCurrency,
initialWalletName: receiveWalletName,
initialAddress: exchangeViewModel
.receiveCurrency ==
exchangeViewModel.wallet.currency
? exchangeViewModel.wallet.address
: exchangeViewModel.receiveAddress,
initialIsAmountEditable: exchangeViewModel
.isReceiveAmountEditable,
initialIsAddressEditable:
exchangeViewModel
.isReceiveAddressEnabled,
isAmountEstimated: true,
currencies: CryptoCurrency.all,
onCurrencySelected: (currency) =>
exchangeViewModel
.changeReceiveCurrency(
currency: currency),
imageArrow: arrowBottomCakeGreen,
currencyButtonColor: Colors.transparent,
addressButtonsColor:
Theme.of(context).focusColor,
borderColor: Theme.of(context)
.primaryTextTheme
.body2
.decorationColor,
currencyValueValidator: AmountValidator(
type: exchangeViewModel.wallet.type),
addressTextFieldValidator:
AddressValidator(
type: exchangeViewModel
.receiveCurrency),
)),
)
],
),
),
if (exchangeViewModel.isReceiveAmountEditable) Padding(
padding: EdgeInsets.only(top: 12, left: 24),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
StandardCheckbox(
key: checkBoxKey,
value: exchangeViewModel.isFixedRateMode,
caption: S.of(context).fixed_rate,
onChanged: (value) =>
exchangeViewModel.isFixedRateMode = value,
),
],
)
),
Padding(
padding: EdgeInsets.only(top: 30, left: 24, bottom: 24),
child: Row(
@ -302,7 +318,7 @@ class ExchangePage extends BasePage {
.pushNamed(Routes.exchangeTemplate),
child: Container(
padding:
EdgeInsets.only(left: 1, right: 10),
EdgeInsets.only(left: 1, right: 10),
child: DottedBorder(
borderType: BorderType.RRect,
dashPattern: [6, 4],
@ -369,23 +385,23 @@ class ExchangePage extends BasePage {
.of(context)
.confirm_delete_template,
rightButtonText:
S.of(context).delete,
S.of(context).delete,
leftButtonText:
S.of(context).cancel,
S.of(context).cancel,
actionRightButton: () {
Navigator.of(
dialogContext)
dialogContext)
.pop();
exchangeViewModel
.removeTemplate(
template:
template);
template:
template);
exchangeViewModel
.updateTemplate();
},
actionLeftButton: () =>
Navigator.of(
dialogContext)
dialogContext)
.pop());
});
},
@ -395,15 +411,14 @@ class ExchangePage extends BasePage {
],
)))
],
),
)),
bottomSectionPadding:
EdgeInsets.only(left: 24, right: 24, bottom: 24),
bottomSection: Column(children: <Widget>[
Padding(
padding: EdgeInsets.only(bottom: 15),
child: Observer(builder: (_) {
final description =
exchangeViewModel.provider is XMRTOExchangeProvider
final description = exchangeViewModel.isFixedRateMode
? S.of(context).amount_is_guaranteed
: S.of(context).amount_is_estimate;
return Center(
@ -464,17 +479,9 @@ class ExchangePage extends BasePage {
currency: CryptoCurrency.fromString(template.receiveCurrency));
switch (template.provider) {
case 'XMR.TO':
exchangeViewModel.changeProvider(
provider: exchangeViewModel.providerList[0]);
break;
case 'ChangeNOW':
exchangeViewModel.changeProvider(
provider: exchangeViewModel.providerList[1]);
break;
case 'MorphToken':
exchangeViewModel.changeProvider(
provider: exchangeViewModel.providerList[2]);
provider: exchangeViewModel.providerList[0]);
break;
}
@ -482,6 +489,7 @@ class ExchangePage extends BasePage {
exchangeViewModel.depositAddress = template.depositAddress;
exchangeViewModel.receiveAddress = template.receiveAddress;
exchangeViewModel.isReceiveAmountEntered = false;
exchangeViewModel.isFixedRateMode = false;
}
void _setReactions(
@ -566,10 +574,10 @@ class ExchangePage extends BasePage {
receiveKey.currentState.isAddressEditable(isEditable: isEnabled);
});
reaction((_) => exchangeViewModel.provider, (ExchangeProvider provider) {
provider is XMRTOExchangeProvider
? receiveKey.currentState.isAmountEditable(isEditable: true)
: receiveKey.currentState.isAmountEditable(isEditable: false);
reaction((_) => exchangeViewModel.isReceiveAmountEditable,
(bool isReceiveAmountEditable) {
receiveKey.currentState
.isAmountEditable(isEditable: isReceiveAmountEditable);
});
reaction((_) => exchangeViewModel.tradeState, (ExchangeTradeState state) {
@ -647,6 +655,45 @@ class ExchangePage extends BasePage {
}
});
_receiveAmountFocus.addListener(() {
if (_receiveAmountFocus.hasFocus && !exchangeViewModel.isFixedRateMode) {
showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: S.of(context).exchange,
alertContent: S.of(context).fixed_rate_alert,
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).ok,
actionLeftButton: () {
FocusScope.of(context).unfocus();
Navigator.of(context).pop();
},
actionRightButton: () {
exchangeViewModel.isFixedRateMode = true;
checkBoxKey.currentState
.changeValue(exchangeViewModel.isFixedRateMode);
Navigator.of(context).pop();
});
});
}
});
reaction((_) => exchangeViewModel.isFixedRateMode, (bool isFixedRateMode) {
if ((_receiveAmountFocus.hasFocus ||
exchangeViewModel.isReceiveAmountEntered) && !isFixedRateMode) {
FocusScope.of(context).unfocus();
receiveAmountController.text = '';
} else {
exchangeViewModel.changeDepositAmount(
amount: depositAmountController.text);
}
checkBoxKey.currentState
.changeValue(exchangeViewModel.isFixedRateMode);
exchangeViewModel.loadLimits();
});
_isReactionsSet = true;
}

View file

@ -28,9 +28,11 @@ void showInformation(
final information = exchangeTradeViewModel.isSendable
? S.current.exchange_result_confirm(
trade.amount ?? fetchingLabel, trade.from.toString(), walletName)
trade.amount ?? fetchingLabel, trade.from.toString(), walletName) +
exchangeTradeViewModel.extraInfo
: S.current.exchange_result_description(
trade.amount ?? fetchingLabel, trade.from.toString());
trade.amount ?? fetchingLabel, trade.from.toString()) +
exchangeTradeViewModel.extraInfo;
showPopUp<void>(
context: context,
@ -148,6 +150,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Theme.of(context)
.accentTextTheme
.subtitle

View file

@ -48,6 +48,7 @@ class QRWidget extends StatelessWidget {
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Theme.of(context).accentTextTheme.
display3.backgroundColor
)

View file

@ -4,9 +4,10 @@ import 'package:flutter/material.dart';
class StandardCheckbox extends StatefulWidget {
StandardCheckbox({
Key key,
@required this.value,
this.caption = '',
@required this.onChanged});
@required this.onChanged}) : super(key: key);
final bool value;
final String caption;
@ -24,6 +25,10 @@ class StandardCheckboxState extends State<StandardCheckbox> {
String caption;
Function(bool) onChanged;
void changeValue(bool newValue) {
setState(() => value = newValue);
}
@override
Widget build(BuildContext context) {
return GestureDetector(

View file

@ -59,6 +59,13 @@ abstract class ExchangeTradeViewModelBase with Store {
@observable
bool isSendable;
@computed
String get extraInfo => trade.from == CryptoCurrency.xlm
? '\n\n' + S.current.xlm_extra_info
: trade.from == CryptoCurrency.xrp
? '\n\n' + S.current.xrp_extra_info
: '';
@observable
ObservableList<ExchangeTradeItem> items;

View file

@ -57,7 +57,8 @@ abstract class ExchangeViewModelBase with Store {
_onPairChange();
}
});
_defineIsReceiveAmountEditable();
isFixedRateMode = false;
isReceiveAmountEntered = false;
loadLimits();
}
@ -106,6 +107,12 @@ abstract class ExchangeViewModelBase with Store {
@observable
bool isReceiveAmountEntered;
@observable
bool isReceiveAmountEditable;
@observable
bool isFixedRateMode;
@computed
SyncStatus get status => wallet.syncStatus;
@ -127,12 +134,15 @@ abstract class ExchangeViewModelBase with Store {
this.provider = provider;
depositAmount = '';
receiveAmount = '';
isFixedRateMode = false;
_defineIsReceiveAmountEditable();
loadLimits();
}
@action
void changeDepositCurrency({CryptoCurrency currency}) {
depositCurrency = currency;
isFixedRateMode = false;
_onPairChange();
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
@ -141,6 +151,7 @@ abstract class ExchangeViewModelBase with Store {
@action
void changeReceiveCurrency({CryptoCurrency currency}) {
receiveCurrency = currency;
isFixedRateMode = false;
_onPairChange();
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
@ -160,9 +171,10 @@ abstract class ExchangeViewModelBase with Store {
provider
.calculateAmount(
from: depositCurrency,
to: receiveCurrency,
from: receiveCurrency,
to: depositCurrency,
amount: _amount,
isFixedRateMode: isFixedRateMode,
isReceiveAmount: true)
.then((amount) => _cryptoNumberFormat
.format(amount)
@ -187,6 +199,7 @@ abstract class ExchangeViewModelBase with Store {
from: depositCurrency,
to: receiveCurrency,
amount: _amount,
isFixedRateMode: isFixedRateMode,
isReceiveAmount: false)
.then((amount) => _cryptoNumberFormat
.format(amount)
@ -200,8 +213,8 @@ abstract class ExchangeViewModelBase with Store {
limitsState = LimitsIsLoading();
try {
limits = await provider.fetchLimits(
from: depositCurrency, to: receiveCurrency);
limits = await provider.fetchLimits(from: depositCurrency,
to: receiveCurrency, isFixedRateMode: isFixedRateMode);
limitsState = LimitsLoadedSuccessfully(limits: limits);
} catch (e) {
limitsState = LimitsLoadedFailure(error: e.toString());
@ -265,7 +278,8 @@ abstract class ExchangeViewModelBase with Store {
} else {
try {
tradeState = TradeIsCreating();
final trade = await provider.createTrade(request: request);
final trade = await provider.createTrade(request: request,
isFixedRateMode: isFixedRateMode);
trade.walletId = wallet.id;
tradesStore.setTrade(trade);
await trades.add(trade);
@ -285,15 +299,15 @@ abstract class ExchangeViewModelBase with Store {
@action
void reset() {
_initialPairBasedOnWallet();
isReceiveAmountEntered = false;
depositAmount = '';
receiveAmount = '';
depositCurrency = CryptoCurrency.xmr;
receiveCurrency = CryptoCurrency.btc;
depositAddress = depositCurrency == wallet.currency ? wallet.address : '';
receiveAddress = receiveCurrency == wallet.currency ? wallet.address : '';
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
isFixedRateMode = false;
_onPairChange();
}
@ -364,7 +378,7 @@ abstract class ExchangeViewModelBase with Store {
}
}
depositAddress = depositCurrency == wallet.currency ? wallet.address : '';
_defineIsReceiveAmountEditable();
depositAmount = '';
receiveAmount = '';
loadLimits();
@ -389,4 +403,14 @@ abstract class ExchangeViewModelBase with Store {
break;
}
}
void _defineIsReceiveAmountEditable() {
if ((provider is ChangeNowExchangeProvider)
&&(depositCurrency == CryptoCurrency.xmr)
&&(receiveCurrency == CryptoCurrency.btc)) {
isReceiveAmountEditable = true;
} else {
isReceiveAmountEditable = false;
}
}
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Wechseln Sie den Exchange-Anbieter",
"you_will_send" : "Konvertieren von",
"you_will_get" : "Konvertieren zu",
"amount_is_guaranteed" : "Geben Sie in xmr.to den BTC-Betrag und nicht den oben genannten XMR-Betrag ein, um einen garantierten BTC-Betrag zu erhalten",
"amount_is_guaranteed" : "Der Empfangsbetrag ist garantiert",
"amount_is_estimate" : "Der empfangene Betrag ist eine Schätzung",
"powered_by" : "Unterstützt von ${title}",
"error" : "Error",
@ -456,5 +456,11 @@
"enter_backup_password" : "Geben Sie hier das Sicherungskennwort ein",
"select_backup_file" : "Wählen Sie die Sicherungsdatei",
"import" : "Importieren",
"please_select_backup_file" : "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein."
"please_select_backup_file" : "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein.",
"fixed_rate" : "Fester Zinssatz",
"fixed_rate_alert" : "Sie können den Empfangsbetrag eingeben, wenn der Festpreismodus aktiviert ist. Möchten Sie in den Festpreismodus wechseln?",
"xlm_extra_info" : "Bitte vergessen Sie nicht, die Memo-ID anzugeben, während Sie die XLM-Transaktion für den Austausch senden",
"xrp_extra_info" : "Bitte vergessen Sie nicht, das Ziel-Tag anzugeben, während Sie die XRP-Transaktion für den Austausch senden"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Change Exchange Provider",
"you_will_send" : "Convert from",
"you_will_get" : "Convert to",
"amount_is_guaranteed" : "In xmr.to, to receive a guaranteed BTC amount, enter the BTC amount and not the XMR amount above",
"amount_is_guaranteed" : "The receive amount is guaranteed",
"amount_is_estimate" : "The receive amount is an estimate",
"powered_by" : "Powered by ${title}",
"error" : "Error",
@ -456,5 +456,11 @@
"enter_backup_password" : "Enter backup password here",
"select_backup_file" : "Select backup file",
"import" : "Import",
"please_select_backup_file" : "Please select backup file and enter backup password."
"please_select_backup_file" : "Please select backup file and enter backup password.",
"fixed_rate" : "Fixed rate",
"fixed_rate_alert" : "You will be able to enter receive amount when fixed rate mode is checked. Do you want to switch to fixed rate mode?",
"xlm_extra_info" : "Please dont forget to specify the Memo ID while sending the XLM transaction for the exchange",
"xrp_extra_info" : "Please dont forget to specify the Destination Tag while sending the XRP transaction for the exchange"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Cambiar proveedor de intercambio",
"you_will_send" : "Convertir de",
"you_will_get" : "Convertir a",
"amount_is_guaranteed" : "En xmr.to, para recibir una cantidad BTC garantizada, ingrese la cantidad BTC y no la cantidad XMR arriba",
"amount_is_guaranteed" : "La cantidad recibida está garantizada",
"amount_is_estimate" : "El monto recibido es un estimado",
"powered_by" : "Energizado por ${title}",
"error" : "Error",
@ -456,5 +456,11 @@
"enter_backup_password" : "Ingrese la contraseña de respaldo aquí",
"select_backup_file" : "Seleccionar archivo de respaldo",
"import" : "Importar",
"please_select_backup_file" : "Seleccione el archivo de respaldo e ingrese la contraseña de respaldo."
"please_select_backup_file" : "Seleccione el archivo de respaldo e ingrese la contraseña de respaldo.",
"fixed_rate" : "Tipo de interés fijo",
"fixed_rate_alert" : "Podrá ingresar la cantidad recibida cuando el modo de tarifa fija esté marcado. ¿Quieres cambiar al modo de tarifa fija?",
"xlm_extra_info" : "No olvide especificar el ID de nota al enviar la transacción XLM para el intercambio",
"xrp_extra_info" : "No olvide especificar la etiqueta de destino al enviar la transacción XRP para el intercambio"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "एक्सचेंज प्रदाता बदलें",
"you_will_send" : "से रूपांतरित करें",
"you_will_get" : "में बदलें",
"amount_is_guaranteed" : "Xmr.to में, गारंटीशुदा BTC राशि प्राप्त करने के लिए, BTC राशि दर्ज करें और ऊपर XMR राशि नहीं",
"amount_is_guaranteed" : "प्राप्त राशि की गारंटी है",
"amount_is_estimate" : "प्राप्त राशि एक अनुमान है",
"powered_by" : "द्वारा संचालित ${title}",
"error" : "त्रुटि",
@ -456,5 +456,11 @@
"enter_backup_password" : "यहां बैकअप पासवर्ड डालें",
"select_backup_file" : "बैकअप फ़ाइल का चयन करें",
"import" : "आयात",
"please_select_backup_file" : "कृपया बैकअप फ़ाइल चुनें और बैकअप पासवर्ड डालें।"
"please_select_backup_file" : "कृपया बैकअप फ़ाइल चुनें और बैकअप पासवर्ड डालें।",
"fixed_rate" : "निर्धारित दर",
"fixed_rate_alert" : "फिक्स्ड रेट मोड की जांच करने पर आप प्राप्त राशि दर्ज कर पाएंगे। क्या आप निश्चित दर मोड पर स्विच करना चाहते हैं?",
"xlm_extra_info" : "एक्सचेंज के लिए XLM ट्रांजेक्शन भेजते समय मेमो आईडी निर्दिष्ट करना न भूलें",
"xrp_extra_info" : "एक्सचेंज के लिए एक्सआरपी लेनदेन भेजते समय कृपया गंतव्य टैग निर्दिष्ट करना न भूलें"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Exchangeプロバイダーの変更",
"you_will_send" : "から変換",
"you_will_get" : "に変換",
"amount_is_guaranteed" : "xmr.toで、保証されたBTC金額を受け取るには、上記のXMR金額ではなく、BTC金額を入力します",
"amount_is_guaranteed" : "受け取り金額は保証されています",
"amount_is_estimate" : "受け取り金額は見積もりです",
"powered_by" : "搭載 ${title}",
"error" : "エラー",
@ -456,5 +456,11 @@
"enter_backup_password" : "ここにバックアップパスワードを入力してください",
"select_backup_file" : "バックアップファイルを選択",
"import" : "インポート",
"please_select_backup_file" : "バックアップファイルを選択し、バックアップパスワードを入力してください。"
"please_select_backup_file" : "バックアップファイルを選択し、バックアップパスワードを入力してください。",
"fixed_rate" : "固定金利",
"fixed_rate_alert" : "固定金利モードにチェックを入れると、受取額を入力できるようになります。 固定金利モードに切り替えますか?",
"xlm_extra_info" : "交換用のXLMトランザクションを送信するときに、メモIDを指定することを忘れないでください",
"xrp_extra_info" : "取引所のXRPトランザクションを送信するときに、宛先タグを指定することを忘れないでください"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "교환 공급자 변경",
"you_will_send" : "다음에서 변환",
"you_will_get" : "로 변환하다",
"amount_is_guaranteed" : "xmr.to에서 보장 된 BTC 금액을 받으려면 위의 XMR 금액이 아닌 BTC 금액을 입력하십시오.",
"amount_is_guaranteed" : "수령 금액이 보장됩니다.",
"amount_is_estimate" : "수신 금액은 견적입니다",
"powered_by" : "에 의해 구동 ${title}",
"error" : "오류",
@ -456,5 +456,11 @@
"enter_backup_password" : "여기에 백업 비밀번호를 입력하세요.",
"select_backup_file" : "백업 파일 선택",
"import" : "수입",
"please_select_backup_file" : "백업 파일을 선택하고 백업 암호를 입력하십시오."
"please_select_backup_file" : "백업 파일을 선택하고 백업 암호를 입력하십시오.",
"fixed_rate" : "고정 비율",
"fixed_rate_alert" : "고정 금리 모드 체크시 수취 금액 입력이 가능합니다. 고정 속도 모드로 전환 하시겠습니까?",
"xlm_extra_info" : "교환을 위해 XLM 거래를 보낼 때 메모 ID를 지정하는 것을 잊지 마십시오",
"xrp_extra_info" : "교환을 위해 XRP 트랜잭션을 보내는 동안 대상 태그를 지정하는 것을 잊지 마십시오"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Wijzig Exchange Provider",
"you_will_send" : "Converteren van",
"you_will_get" : "Converteren naar",
"amount_is_guaranteed" : "Om een gegarandeerd BTC-bedrag te ontvangen, voert u in xmr.to het BTC-bedrag in en niet het bovenstaande XMR-bedrag",
"amount_is_guaranteed" : "Het ontvangen bedrag is gegarandeerd",
"amount_is_estimate" : "Het ontvangen bedrag is een schatting",
"powered_by" : "Aangedreven door ${title}",
"error" : "Fout",
@ -456,5 +456,11 @@
"enter_backup_password" : "Voer hier een back-upwachtwoord in",
"select_backup_file" : "Selecteer een back-upbestand",
"import" : "Importeren",
"please_select_backup_file" : "Selecteer een back-upbestand en voer een back-upwachtwoord in."
"please_select_backup_file" : "Selecteer een back-upbestand en voer een back-upwachtwoord in.",
"fixed_rate" : "Vast tarief",
"fixed_rate_alert" : "U kunt het ontvangen bedrag invoeren wanneer de modus voor vaste tarieven is aangevinkt. Wilt u overschakelen naar de vaste-tariefmodus?",
"xlm_extra_info" : "Vergeet niet om de Memo-ID op te geven tijdens het verzenden van de XLM-transactie voor de uitwisseling",
"xrp_extra_info" : "Vergeet niet om de Destination Tag op te geven tijdens het verzenden van de XRP-transactie voor de uitwisseling"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Zmień dostawcę programu Exchange",
"you_will_send" : "Konwertuj z",
"you_will_get" : "Konwertuj na",
"amount_is_guaranteed" : "W xmr.to, aby otrzymać gwarantowaną kwotę BTC, wprowadź kwotę BTC, a nie kwotę XMR powyżej",
"amount_is_guaranteed" : "Otrzymana kwota jest gwarantowana",
"amount_is_estimate" : "Otrzymana kwota jest wartością szacunkową",
"powered_by" : "Zasilany przez ${title}",
"error" : "Błąd",
@ -456,5 +456,11 @@
"enter_backup_password" : "Wprowadź tutaj hasło zapasowe",
"select_backup_file" : "Wybierz plik kopii zapasowej",
"import" : "Import",
"please_select_backup_file" : "Wybierz plik kopii zapasowej i wprowadź hasło zapasowe."
"please_select_backup_file" : "Wybierz plik kopii zapasowej i wprowadź hasło zapasowe.",
"fixed_rate" : "Stała stawka",
"fixed_rate_alert" : "Będziesz mógł wprowadzić kwotę otrzymaną, gdy zaznaczony jest tryb stałej stawki. Czy chcesz przejść do trybu stałej stawki?",
"xlm_extra_info" : "Nie zapomnij podać identyfikatora notatki podczas wysyłania transakcji XLM do wymiany",
"xrp_extra_info" : "Nie zapomnij podać tagu docelowego podczas wysyłania transakcji XRP do wymiany"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Alterar o provedor de troca",
"you_will_send" : "Converter de",
"you_will_get" : "Converter para",
"amount_is_guaranteed" : "Em xmr.to, para receber um valor BTC garantido, insira o valor BTC e não o valor XMR acima",
"amount_is_guaranteed" : "O valor recebido é garantido",
"amount_is_estimate" : "O valor a ser recebido informado acima é uma estimativa",
"powered_by" : "Troca realizada por ${title}",
"error" : "Erro",
@ -456,5 +456,11 @@
"enter_backup_password" : "Digite a senha de backup aqui",
"select_backup_file" : "Selecione o arquivo de backup",
"import" : "Importar",
"please_select_backup_file" : "Selecione o arquivo de backup e insira a senha de backup."
"please_select_backup_file" : "Selecione o arquivo de backup e insira a senha de backup.",
"fixed_rate" : "Taxa fixa",
"fixed_rate_alert" : "Você poderá inserir a quantia recebida quando o modo de taxa fixa estiver marcado. Quer mudar para o modo de taxa fixa?",
"xlm_extra_info" : "Não se esqueça de especificar o Memo ID ao enviar a transação XLM para a troca",
"xrp_extra_info" : "Não se esqueça de especificar a etiqueta de destino ao enviar a transação XRP para a troca"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Изменить провайдера обмена",
"you_will_send" : "Конвертировать из",
"you_will_get" : "Конвертировать в",
"amount_is_guaranteed" : "В xmr.to, чтобы получить гарантированную сумму BTC, введите сумму BTC, а не сумму XMR выше",
"amount_is_guaranteed" : "Полученная сумма гарантирована",
"amount_is_estimate" : "Полученная сумма является приблизительной",
"powered_by" : "Используя ${title}",
"error" : "Ошибка",
@ -456,5 +456,11 @@
"enter_backup_password" : "Введите пароль резервной копии",
"select_backup_file" : "Выберите файл резервной копии",
"import" : "Импортировать",
"please_select_backup_file" : "Выберите файл резервной копии и введите пароль резервной копии."
"please_select_backup_file" : "Выберите файл резервной копии и введите пароль резервной копии.",
"fixed_rate" : "Фиксированная ставка",
"fixed_rate_alert" : "Вы сможете ввести сумму получения тогда, когда будет установлен режим фиксированной ставки. Вы хотите перейти в режим фиксированной ставки?",
"xlm_extra_info" : "Не забудьте указать Memo ID (памятка) при отправке транзакции XLM для обмена",
"xrp_extra_info" : "Не забудьте указать целевой тег при отправке транзакции XRP для обмена"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "Змінити провайдера обміну",
"you_will_send" : "Конвертувати з",
"you_will_get" : "Конвертувати в",
"amount_is_guaranteed" : "У xmr.to, щоб отримати гарантовану суму BTC, введіть суму BTC, а не XMR вище",
"amount_is_guaranteed" : "Отримана сума є гарантованою",
"amount_is_estimate" : "Отримана сума є приблизною",
"powered_by" : "Використовуючи ${title}",
"error" : "Помилка",
@ -456,5 +456,11 @@
"enter_backup_password" : "Введіть пароль резервної копії",
"select_backup_file" : "Виберіть файл резервної копії",
"import" : "Імпортувати",
"please_select_backup_file" : "Виберіть файл резервної копії та введіть пароль резервної копії."
"please_select_backup_file" : "Виберіть файл резервної копії та введіть пароль резервної копії.",
"fixed_rate" : "Фіксована ставка",
"fixed_rate_alert" : "Ви зможете ввести суму отримання тоді, коли буде встановлений режим фіксованої ставки. Ви хочете перейти в режим фіксованої ставки?",
"xlm_extra_info" : "Будь ласка, не забудьте вказати ідентифікатор пам'ятки під час надсилання транзакції XLM для обміну",
"xrp_extra_info" : "Будь ласка, не забудьте вказати тег призначення під час надсилання XRP-транзакції для обміну"
}

View file

@ -65,7 +65,7 @@
"change_exchange_provider" : "更改交易所提供商",
"you_will_send" : "從轉換",
"you_will_get" : "轉換成",
"amount_is_guaranteed" : "在xmr.to中要接收保证的BTC数量请输入BTC数量而不要输入上方的XMR数量",
"amount_is_guaranteed" : "接收金額有保證",
"amount_is_estimate" : "收款金额为估算值",
"powered_by" : "供电 ${title}",
"error" : "错误",
@ -456,5 +456,11 @@
"enter_backup_password" : "在此處輸入備用密碼",
"select_backup_file" : "選擇備份文件",
"import" : "進口",
"please_select_backup_file" : "請選擇備份文件,然後輸入備份密碼。"
"please_select_backup_file" : "請選擇備份文件,然後輸入備份密碼。",
"fixed_rate" : "固定利率",
"fixed_rate_alert" : "選中固定費率模式後,您將可以輸入接收金額。 您要切換到固定速率模式嗎?",
"xlm_extra_info" : "發送用於交換的XLM交易時請不要忘記指定備忘錄ID",
"xrp_extra_info" : "發送用於交換的XRP交易時請不要忘記指定目標標記"
}