From 612b5647fc5ccf78bfd29c492c86cf393dc11425 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Wed, 29 Jan 2020 20:36:54 +0200 Subject: [PATCH 01/22] CWA-169 | added morph images to assets, added morph contact to settings page and morph link to disclaimer page --- assets/images/2.0x/morph_icon.png | Bin 0 -> 1741 bytes assets/images/3.0x/morph_icon.png | Bin 0 -> 2685 bytes assets/images/morph_icon.png | Bin 0 -> 895 bytes .../screens/disclaimer/disclaimer_page.dart | 22 ++++++++++++++++++ lib/src/screens/settings/settings.dart | 8 +++++++ 5 files changed, 30 insertions(+) create mode 100644 assets/images/2.0x/morph_icon.png create mode 100644 assets/images/3.0x/morph_icon.png create mode 100644 assets/images/morph_icon.png diff --git a/assets/images/2.0x/morph_icon.png b/assets/images/2.0x/morph_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a897a73b13895ce7d93f1ddedd502e8a27d1886e GIT binary patch literal 1741 zcmV;;1~U1HP)K~#7F%~@M) zR7Dv6X3pMd#V%ARN;Hc^5vo!Wh!R3936TUJEElyv1Y&$KURppC9z@GEyjdO;@Ik>; zfkdQ$iHQ%ErL^2qy2V}yAS{aEQV6G%ZtLzjXPi0hw%gr3yJxm#>DRP7oilUx|K|Vx zx%@*g3@GuIc%4d431e(J2=NhyA_n3Gm^a#n073pd$O{2RXh7F>f3>yS!q!4Nm|k@w2+W z!ftb01WLW7K8?^rymb+>0Pc+-_r^Rs-k|9kEcTYJ)~M2$E#n3FsQMg~HZJilD@oT@ zN%c@jh7j@~~_MfRmW& zelghA)7+HsD89lBSfTlcIn!hYRWpnk@qwKX#5$!lBhYvOuS3j)aTp|_KHaB{{6_|Y z2|OOaHA_oYy*eFn1F7{+*QT)*rT5Re+=1~=J$w=#55=0#a9g_BkUx%M(>51o&WzyNKNL4_Xx5GS z+8{m@As>T~?WtZI3MrU7zXxuQff=*Aq3Hxy+MF0p_$Dd%e1j7O;|*aQem%-?>7rrX zfghZncTe6yQ^_Za>wi&P|J!YrDfd~)iV)s<|35h08J~v+Va{9!Hg2XEGbU;|VhaV9*V;p+n0>$0-^zlZR zQAF)-lN;)DIDy!Oo8Z|gJy^S?3r{{RAKWhPy|PbTSh6@SPzgb;KmF*NVDM4Gn9okz z_J0|!UUVna=NE*{;C^+!eNT)VPq1~X6R*rlB(7@&=Njz2ixE;p`73;|iH3St()yfS z4J$slhlQm*d;n9&#gwTEHf?obqJ`I*TY&o=_B_hJ$(!~>7K^}17c>j+iZ$nrx4W>i zJd9C~C2#ZkLI*Z{L6P^k^$6FUuqmHj$Pwtc%W%2X!(C_HX4c#etl83uvEv4eq@3NV z_gq-Ll9;oY6~dar4U1QWFnf*zQ=Ze!x^$>JE;pNr>;+#35RmB<>SSmO zIMdoA9v`V1g}T}ZZr>I&M(PeBJ}7}kxzXn{XppZ1BnU~I{KJz*4h+9nkH+N|1D*E` z?B2y-XsNx{*uW48ORgt8&q@hlO_0RJ76o0M$r z7$k9}O~IXZN6ZTiv^I@K%@Ma{pPM&yRQ;eMHlD?_TYn-0`7l-~K1~9e;o1So=~U+) zZ>;OvTJRz5xaY!8-?-BD^Vb-ttsOA9y`ADhOBk{c@)4gV0aHdmB_whFY~LQ3OX9$H zxlr%eJ0Dc-)zN;Zw|wff0Vb^;?1?70`o)@w7lN0ZT<>o9e;b9SdWY?PoqR3Xy;Db+ zPn&heGYDROhY&3f8Zw^P5~-C6NWk2E5)lGf%32sk1-}4EPC#JknB`f$3y^`hBs_R; z-=x^Og!#_Fj75-?QkJ0VjLnO$Oh~*m_cW`8?!sGK8zU-5$_#DUA@#ti`1+)oBc41B zOdIu*C>CQRfb0ICdSG|5N0zCt*6u(3BZ5R+(8eR}#BJWzQ1U%5X8X=Shm8m2X59!>X=?#9DkSZOY0ZhX+ z^z4XUT-Zg%$xV|84{%0kS;h;W*ah?7Obm}=ShBPIWGK(G5?Um(eQ^mhRU{A0^Ect= jSV99~z3XtMM#tiRt$3K3*$s7!00000NkvXXu0mjfRA4jX literal 0 HcmV?d00001 diff --git a/assets/images/3.0x/morph_icon.png b/assets/images/3.0x/morph_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..db98d49da84ddf84192f2d49f622b766254a126c GIT binary patch literal 2685 zcmV-@3WD{CP)_zgomx8%DFh1?N@$%?#{oiH+d-=YDnt8M z!<5$2jzj1agBsg79j4kk0|_CG36X@vD3sy}NL2{g{2;&XcAww3`N1W*%kA#HgCu+g z<}P=8Z+AcY`Tl%wm*F}hH;^0fdNYDB_+kMg2*!d;AX|PXfME2t3JfMg-W5y5$}VHo9Q`oR!Vh?EdCoD`9RRAPXv z*IEwjM+%^nAW4jeXB5z|o0TZV0mwu{%ry5$fMS)ZQbN#;BxWQAi6UQB2n9%*puCxD zbLfEfjdZd%8WvFu1*I)7y^bW{njonfjb{|n0GlzcA&Meq_x3WqOot1&B4|}$RnXx4 z@OV>AJV-Sern$t8Z{lzWX;KlcotP-(NRSGG9?nm!2&~S9LugJm&YQ8ifG$S~y-mZ! zLmFdj)tvNsZOz?H)pmbmo1nZIYYORF?81ZxdvK0_E^F>-I$~#QTLf9knH1yh(yD z=NfN=xCF^0a3Y0rx9Cp+(zlKA{b;PnTARy+IXV4KJjC%wF%`sx`CHs%pq9zLSf)0L zAeryn45l>_mZ>3abBxcgVWQPoDF8*au36EA?JxyJIM2U{$&m<*RM9YkNKWfv6TY;R zx3iVO>vM3doEJpFO0tk@6%*Ty$dv%ly?(H=j3kZ-%brha}2-gOd~^Un^%&GxnJ$Xmgie>>mB2VB&r>ex5ker9w+ninpB$#94$8;48U>*&CDXm z(0C3Uz=)WruS%zPv~!~A_Rkym>8>_>DcezdDJ4kH(<_>q49*_ zXq-Vavj}oxUW2Hu@X-NW^YK$|iQtK?m+|$7!njeGk;U=L=X_YWpl|3ic>(LG|JmE? zKtZ@>W_;kU95}@JGr-3e{n0~Oa{m60JFt91A2g5SZf;TtenG?b9UjaI4p)jG2^}qu zz%dxhmS)Cfj~OmtngVsld@;rq_{PH>cTzEx2}+7=p!)qzHa<%X9s59o;s4K$BgBVc(HLKN4j6`XY{^m zYx*yyD{${(PW~qdm-zIe!1)i-h@V(jh(hZfeRyhDC*~}Ga-^kmJh{n>ycPYbjSYsX zN@vbF8UiB7X^d>R1UWJsx6CY_zhRg%HH^o9uH&1zy-|?!50`l#aq38a{WMLo*?=Lm>?xomWJVTullEXsq#|r^h+p(s?g7j&jF1m9Q4WQusq)G=Ya1ph z<=~&Ep#945EB|Uq1n17#caef|y!ReWY_+N*hz_ovhv5s+TURSUW8uS78ZKQ*oLLJ? zWegQ>Wa4D?Xd-%h4gCIh2EB6FRpilQYWw1^>Lum8OfS~S4=Hohra@*_WurC|9G_hD z;vWan<8E`|Tm&UAQNd{=UF+%QWSR=wy+Rz3FV>!!5M@w^+M~YyM%oxx-Y_`+x+j31 zuCdke?>8f8I3dT9PCNd#CmRJiJCdutqCxJjSiV{Wg-xH*8$m99$Z#RlKP?m!6rB#0 z`f>LC#3v*j_n-ELq3d$2SP_z0zPz#mNyviXcx)s))r>5UC*aUmxE3 zoBgCxZ#A)ZuOWMY~@6c}WZrG+<`RqM3df_~1-*G-KAul>H?GmoCB; zN?$gp5bYl;8s!yzPz6$d=rz4$$mI+XWSJRI1cj)t_DAm-wNJV2{;-Ea zf6q1bU2fIzzC!aNODc~3d-(bw)3+N6Rn$aiSA=f z*dMk0k$+wr)oKr75`mdUL8<;q!Xn*P1G%}Usd`TOm*v|WOa_={VX6M|Z|rPpyTjhx z-B>;ul+>>rd*oQ#!yyK4(cDLGC)$m6Ix|JCY@<5)k^2V=Fm_l~ww-FoP~IP{uET=` zBxH083;%rLS84U18i*o8bkBGDM403sZW36tj4@F(-qa*j!v*r4n$$=rnu(TIN{Jan%I-i}8CaE1U4ix2;}Knqv9hq) zwO=JMgGd=cgRmkVC724y(rKLfRFV>nloK=(D`&1-Og++Uxkwv~XVd(5fTqa;u^tmB rU#;aiOoZe@0=bSLjIL0sNr}d1+KfuC4Vtvo00000NkvXXu0mjf3cm_y literal 0 HcmV?d00001 diff --git a/assets/images/morph_icon.png b/assets/images/morph_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b019b864eb6520fdf0b72898d92376b4019774 GIT binary patch literal 895 zcmV-_1AzRAP)Te zqKhPiT>$oohcpO2O{6#iJUHmkUV4&okeRW`)?^PVN)LpnLJE+=y&=v!%!HKPhQ_?+ zR!&Nv+;#>jLPlB6h^`f9m2SFyuJNP-jd?BYa`{6!%tZQ-d#JY9T0(BW%b6gcN4`zI zKM+;PldMKh63#*R&Y3bLuf>LgffnSvLeB})XCcP!9w506n@ZH94=55n`w{h=Js-r@ zrh>&eN{jL6F@~a3Dn^F43|o+IF!+4$g1TI}ACxf@^Nlr-a#89>|K3(ER+x=DK7jnav zS3tPap`!W{Gi)QHi9yIL+8Io+vLvwRwixsL!VqqCt)i?_;P?pz?d=MRPR6WX0cNK| zW>jEO#bf4}nXtsob8AA;8_@Z@m-(U_N)ITq&41&GMO zg51)LB=|CH4Sy#`v*CQdb7k{xfwzu`#MBIuBEb0|b7;MqlyaIam>$c((k}}Jo>>!o zulqw-Tnyp!M{{!hjnI2hOtWLM*&(fdM1 { static const xmrtoUrl = 'https://xmr.to/app_static/html/tos.html'; static const changenowUrl = 'https://changenow.io/terms-of-use'; + static const morphUrl = 'http://morphtoken.com/terms'; final bool _isAccepted; bool _checked = false; @@ -197,6 +198,27 @@ class DisclaimerBodyState extends State { )) ], ), + SizedBox( + height: 16.0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: GestureDetector( + onTap: () => launchUrl(morphUrl), + child: Text( + morphUrl, + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.blue, + fontSize: 14.0, + fontWeight: FontWeight.normal, + decoration: TextDecoration.underline), + ), + )) + ], + ), SizedBox( height: 16.0, ) diff --git a/lib/src/screens/settings/settings.dart b/lib/src/screens/settings/settings.dart index 72602c4d8..b2f53bfea 100644 --- a/lib/src/screens/settings/settings.dart +++ b/lib/src/screens/settings/settings.dart @@ -51,12 +51,14 @@ class SettingsFormState extends State { final _twitterImage = Image.asset('assets/images/Twitter.png'); final _changeNowImage = Image.asset('assets/images/change_now.png'); final _xmrBtcImage = Image.asset('assets/images/xmr_btc.png'); + final _morphImage = Image.asset('assets/images/morph_icon.png'); final _emailUrl = 'mailto:support@cakewallet.io'; final _telegramUrl = 'https:t.me/cakewallet_bot'; final _twitterUrl = 'https:twitter.com/CakewalletXMR'; final _changeNowUrl = 'mailto:support@changenow.io'; final _xmrToUrl = 'mailto:support@xmr.to'; + final _morphUrl = 'mailto:support@morphtoken.com'; final _items = List(); @@ -267,6 +269,12 @@ class SettingsFormState extends State { link: 'support@xmr.to', image: _xmrBtcImage, attribute: Attributes.link), + SettingsItem( + onTaped: () => _launchUrl(_morphUrl), + title: 'MorphToken', + link: 'support@morphtoken.com', + image: _morphImage, + attribute: Attributes.link), SettingsItem( onTaped: () { Navigator.push( From c1a7ee01649da87218c1263035589803966af6d3 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Thu, 30 Jan 2020 20:23:36 +0200 Subject: [PATCH 02/22] CWA-169 | created MorphToken exchange provider and MorphToken request (also this provider added to exchange provider description, exchange page, exchange store, router) --- lib/router.dart | 4 +- .../exchange_provider_description.dart | 4 + .../morphtoken_exchange_provider.dart | 167 ++++++++++++++++++ .../morphtoken/morphtoken_request.dart | 18 ++ lib/src/screens/exchange/exchange_page.dart | 3 + lib/src/stores/exchange/exchange_store.dart | 11 ++ 6 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart create mode 100644 lib/src/domain/exchange/morphtoken/morphtoken_request.dart diff --git a/lib/router.dart b/lib/router.dart index c10ebea12..1698737c6 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -16,6 +16,7 @@ import 'package:cake_wallet/src/domain/services/wallet_service.dart'; import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/exchange/changenow/changenow_exchange_provider.dart'; import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; +import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart'; import 'package:cake_wallet/src/domain/common/node.dart'; import 'package:cake_wallet/src/domain/monero/transaction_description.dart'; import 'package:cake_wallet/src/domain/exchange/trade.dart'; @@ -453,7 +454,8 @@ class Router { trades: trades, providerList: [ xmrtoprovider, - ChangeNowExchangeProvider() + ChangeNowExchangeProvider(), + MorphTokenExchangeProvider() ], walletStore: walletStore); }), diff --git a/lib/src/domain/exchange/exchange_provider_description.dart b/lib/src/domain/exchange/exchange_provider_description.dart index 0ae388848..67a2565d8 100644 --- a/lib/src/domain/exchange/exchange_provider_description.dart +++ b/lib/src/domain/exchange/exchange_provider_description.dart @@ -8,6 +8,8 @@ class ExchangeProviderDescription extends EnumerableItem static const xmrto = ExchangeProviderDescription(title: 'XMR.TO', raw: 0); static const changeNow = ExchangeProviderDescription(title: 'ChangeNOW', raw: 1); + static const morphToken = + ExchangeProviderDescription(title: 'MorphToken', raw: 2); static ExchangeProviderDescription deserialize({int raw}) { switch (raw) { @@ -15,6 +17,8 @@ class ExchangeProviderDescription extends EnumerableItem return xmrto; case 1: return changeNow; + case 2: + return morphToken; default: return null; } diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart new file mode 100644 index 000000000..ed06462a7 --- /dev/null +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -0,0 +1,167 @@ +import 'dart:convert'; +import 'package:cake_wallet/src/domain/exchange/trade_not_found_exeption.dart'; +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart'; +import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_pair.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart'; +import 'package:cake_wallet/src/domain/exchange/limits.dart'; +import 'package:cake_wallet/src/domain/exchange/trade.dart'; +import 'package:cake_wallet/src/domain/exchange/trade_request.dart'; +import 'package:cake_wallet/src/domain/exchange/trade_state.dart'; +import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_request.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart'; + +class MorphTokenExchangeProvider extends ExchangeProvider { + MorphTokenExchangeProvider() + : super( + pairList: CryptoCurrency.all + .map((i) { + return CryptoCurrency.all.map((k) { + if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) { + return ExchangePair(from: i, to: k, reverse: false); + } + + if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) { + return null; + } + + return ExchangePair(from: i, to: k, reverse: true); + }).where((c) => c != null); + }) + .expand((i) => i) + .toList()); + + static const apiUri = 'https://api.morphtoken.com'; + static const _morphURISuffix = '/morph'; + static const _limitsURISuffix = '/limits'; + static const _ratesURISuffix = '/rates'; + static const weight = 10000; + + @override + String get title => 'MorphToken'; + + @override + ExchangeProviderDescription get description => + ExchangeProviderDescription.morphToken; + + @override + Future fetchLimits({CryptoCurrency from, CryptoCurrency to}) async { + final url = apiUri + _limitsURISuffix; + final headers = {'Content-type': 'application/json'}; + final body = + json.encode({ + "input": { + "asset": from.toString() + }, + "output": [{ + "asset": to.toString(), + "weight": weight + }]}); + final response = + await post(url.toString(), headers: headers, body: json.encode(body)); + final responseJSON = json.decode(response.body) as Map; + + final min = responseJSON['input']['limits']['min'] as double; + final max = responseJSON['input']['limits']['max'] as double; + + return Limits(min: min, max: max); + } + + @override + Future createTrade({TradeRequest request}) async { + const url = apiUri + _morphURISuffix; + final _request = request as MorphTokenRequest; + final body = { + "input": { + "asset": _request.from.toString(), + "refund": _request.refundAddress + }, + "output": [{ + "asset": _request.to.toString(), + "weight": weight, + "address": _request.address + }] + }; + + final response = await post(url, + headers: {'Content-Type': 'application/json'}, body: json.encode(body)); + + if (response.statusCode != 200) { + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['description'] as String; + + throw TradeNotCreatedException(description, description: error); + } + + throw TradeNotCreatedException(description); + } + + final responseJSON = json.decode(response.body) as Map; + final id = responseJSON['id'] as String; + + return Trade( + id: id, + provider: description, + from: _request.from, + to: _request.to, + state: TradeState.created, + amount: _request.amount, + createdAt: DateTime.now()); + } + + @override + Future findTradeById({@required String id}) async { + final url = apiUri + _morphURISuffix + '/' + id; + final response = await get(url); + + if (response.statusCode != 200) { + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['description'] as String; + + throw TradeNotFoundException(id, + provider: description, description: error); + } + + throw TradeNotFoundException(id, provider: description); + } + + final responseJSON = json.decode(response.body) as Map; + final fromCurrency = responseJSON['input']['asset'] as String; + final from = CryptoCurrency.fromString(fromCurrency); + final toCurrency = responseJSON['output']['asset'] as String; + final to = CryptoCurrency.fromString(toCurrency); + final inputAddress = responseJSON['input']['refund_address'] as String; + final outputWeight = responseJSON['output']['weight'].toString(); + final status = responseJSON['state'] as String; + final state = TradeState.deserialize(raw: status); + final extraId = responseJSON['id'] as String; + final outputTransaction = responseJSON['deposit_address'] as String; + + return Trade( + id: id, + from: from, + to: to, + provider: description, + inputAddress: inputAddress, + amount: outputWeight, + state: state, + extraId: extraId, + outputTransaction: outputTransaction); + } + + @override + Future calculateAmount( + {CryptoCurrency from, CryptoCurrency to, double amount}) async { + final url = apiUri + _ratesURISuffix; + final response = await get(url); + final responseJSON = json.decode(response.body) as Map; + final rate = responseJSON['data'][from.toString()][to.toString()] as String; + final estimatedAmount = double.parse(rate) * amount; + + return estimatedAmount; + } +} diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_request.dart b/lib/src/domain/exchange/morphtoken/morphtoken_request.dart new file mode 100644 index 000000000..f034372d9 --- /dev/null +++ b/lib/src/domain/exchange/morphtoken/morphtoken_request.dart @@ -0,0 +1,18 @@ +import 'package:flutter/foundation.dart'; +import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; +import 'package:cake_wallet/src/domain/exchange/trade_request.dart'; + +class MorphTokenRequest extends TradeRequest { + MorphTokenRequest( + {@required this.from, + @required this.to, + @required this.address, + @required this.amount, + @required this.refundAddress}); + + CryptoCurrency from; + CryptoCurrency to; + String address; + String amount; + String refundAddress; +} diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index a5cb2b55c..ce533c3cd 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -278,6 +278,9 @@ class ExchangeFormState extends State { case ExchangeProviderDescription.changeNow: imageSrc = 'assets/images/change_now.png'; break; + case ExchangeProviderDescription.morphToken: + imageSrc = 'assets/images/morph_icon.png'; + break; } return Padding( diff --git a/lib/src/stores/exchange/exchange_store.dart b/lib/src/stores/exchange/exchange_store.dart index a0cf932e4..832187757 100644 --- a/lib/src/stores/exchange/exchange_store.dart +++ b/lib/src/stores/exchange/exchange_store.dart @@ -8,6 +8,8 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart'; import 'package:cake_wallet/src/domain/exchange/trade_request.dart'; import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_trade_request.dart'; +import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart'; +import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_request.dart'; import 'package:cake_wallet/src/domain/exchange/trade.dart'; import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart'; @@ -161,6 +163,15 @@ abstract class ExchangeStoreBase with Store { address: receiveAddress); } + if (provider is MorphTokenExchangeProvider) { + request = MorphTokenRequest( + from: depositCurrency, + to: receiveCurrency, + amount: depositAmount, + refundAddress: depositAddress, + address: receiveAddress); + } + try { tradeState = TradeIsCreating(); final trade = await provider.createTrade(request: request); From 6333b9a6ffea62b518a4973886337dab5beed89d Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Fri, 31 Jan 2020 10:45:32 +0200 Subject: [PATCH 03/22] CWA-169 | created exchange pairs for crypto currencies --- .../morphtoken_exchange_provider.dart | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index ed06462a7..4018d0d14 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -16,22 +16,43 @@ import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart' class MorphTokenExchangeProvider extends ExchangeProvider { MorphTokenExchangeProvider() : super( - pairList: CryptoCurrency.all - .map((i) { - return CryptoCurrency.all.map((k) { - if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) { - return ExchangePair(from: i, to: k, reverse: false); - } + pairList: [ + ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.btc), + ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.eth), + ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.bch), + ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.ltc), + ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.dash), - if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) { - return null; - } + ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.btc), + ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.eth), + ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.bch), + ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.ltc), + ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.xmr), - return ExchangePair(from: i, to: k, reverse: true); - }).where((c) => c != null); - }) - .expand((i) => i) - .toList()); + ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.btc), + ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.eth), + ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.bch), + ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.dash), + ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.xmr), + + ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.btc), + ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.eth), + ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.ltc), + ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.dash), + ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.xmr), + + ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.btc), + ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.bch), + ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.ltc), + ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.dash), + ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.xmr), + + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.eth), + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.bch), + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.ltc), + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.dash), + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.xmr), + ]); static const apiUri = 'https://api.morphtoken.com'; static const _morphURISuffix = '/morph'; From 4ce032f183a63e6fd21911cfe9c6202e16971ed2 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Mon, 3 Feb 2020 23:20:14 +0200 Subject: [PATCH 04/22] CWA-169 | got trade amount from hive in morphtoken exchange provider --- .../morphtoken_exchange_provider.dart | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index 4018d0d14..5b9cdf08f 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'package:hive/hive.dart'; import 'package:cake_wallet/src/domain/exchange/trade_not_found_exeption.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; @@ -156,11 +157,17 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final toCurrency = responseJSON['output']['asset'] as String; final to = CryptoCurrency.fromString(toCurrency); final inputAddress = responseJSON['input']['refund_address'] as String; - final outputWeight = responseJSON['output']['weight'].toString(); final status = responseJSON['state'] as String; final state = TradeState.deserialize(raw: status); - final extraId = responseJSON['id'] as String; - final outputTransaction = responseJSON['deposit_address'] as String; + + String amount = ""; + final trades = Hive.box(Trade.boxName).values; + for (final trade in trades) { + if (trade.id == id) { + amount = trade.amount; + break; + } + } return Trade( id: id, @@ -168,10 +175,10 @@ class MorphTokenExchangeProvider extends ExchangeProvider { to: to, provider: description, inputAddress: inputAddress, - amount: outputWeight, + amount: amount, state: state, - extraId: extraId, - outputTransaction: outputTransaction); + extraId: null, + outputTransaction: null); } @override From 22cf5ca08b924b135595a5c2ef066a8cff97a770 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Tue, 4 Feb 2020 18:47:42 +0200 Subject: [PATCH 05/22] CWA-169 | got hive box as dependency for MorphTokenExchangeProvider class, removed extraId from Trade --- .../exchange/morphtoken/morphtoken_exchange_provider.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index 5b9cdf08f..363f37ba4 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -55,6 +55,8 @@ class MorphTokenExchangeProvider extends ExchangeProvider { ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.xmr), ]); + final trades = Hive.box(Trade.boxName); + static const apiUri = 'https://api.morphtoken.com'; static const _morphURISuffix = '/morph'; static const _limitsURISuffix = '/limits'; @@ -158,11 +160,10 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final to = CryptoCurrency.fromString(toCurrency); final inputAddress = responseJSON['input']['refund_address'] as String; final status = responseJSON['state'] as String; - final state = TradeState.deserialize(raw: status); + final state = TradeState.deserialize(raw: status.toLowerCase()); String amount = ""; - final trades = Hive.box(Trade.boxName).values; - for (final trade in trades) { + for (final trade in trades.values) { if (trade.id == id) { amount = trade.amount; break; @@ -177,7 +178,6 @@ class MorphTokenExchangeProvider extends ExchangeProvider { inputAddress: inputAddress, amount: amount, state: state, - extraId: null, outputTransaction: null); } From b8887daff4599ddd114de1bc54ad3e5e3bb74000 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Wed, 5 Feb 2020 19:30:42 +0200 Subject: [PATCH 06/22] CWA-169 | removed xmr-btc pair, fixed fetchLimits and findTradeById methods in MorphTokenExchangeProvider class --- .../morphtoken_exchange_provider.dart | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index 363f37ba4..28cd0db6e 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -18,7 +18,6 @@ class MorphTokenExchangeProvider extends ExchangeProvider { MorphTokenExchangeProvider() : super( pairList: [ - ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.btc), ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.eth), ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.bch), ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.ltc), @@ -51,8 +50,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider { ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.eth), ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.bch), ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.ltc), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.dash), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.xmr), + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.dash) ]); final trades = Hive.box(Trade.boxName); @@ -84,13 +82,13 @@ class MorphTokenExchangeProvider extends ExchangeProvider { "weight": weight }]}); final response = - await post(url.toString(), headers: headers, body: json.encode(body)); + await post(url, headers: headers, body: body); final responseJSON = json.decode(response.body) as Map; - final min = responseJSON['input']['limits']['min'] as double; - final max = responseJSON['input']['limits']['max'] as double; + final min = responseJSON['input']['limits']['min'] as int; + final max = responseJSON['input']['limits']['max'] as int; - return Limits(min: min, max: max); + return Limits(min: min.toDouble(), max: max.toDouble()); } @override @@ -155,9 +153,9 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final fromCurrency = responseJSON['input']['asset'] as String; - final from = CryptoCurrency.fromString(fromCurrency); + final from = CryptoCurrency.fromString(fromCurrency.toLowerCase()); final toCurrency = responseJSON['output']['asset'] as String; - final to = CryptoCurrency.fromString(toCurrency); + final to = CryptoCurrency.fromString(toCurrency.toLowerCase()); final inputAddress = responseJSON['input']['refund_address'] as String; final status = responseJSON['state'] as String; final state = TradeState.deserialize(raw: status.toLowerCase()); @@ -177,8 +175,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider { provider: description, inputAddress: inputAddress, amount: amount, - state: state, - outputTransaction: null); + state: state); } @override From e4d46000822a6b82fcd27473fdb38e90d1545082 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Wed, 5 Feb 2020 20:51:02 +0200 Subject: [PATCH 07/22] CWA-169 | fixed getting toCurrency and inputAddress from response in findTradeById method --- .../exchange/morphtoken/morphtoken_exchange_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index 28cd0db6e..0637607df 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -154,9 +154,9 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final fromCurrency = responseJSON['input']['asset'] as String; final from = CryptoCurrency.fromString(fromCurrency.toLowerCase()); - final toCurrency = responseJSON['output']['asset'] as String; + final toCurrency = responseJSON['output'][0]['asset'] as String; final to = CryptoCurrency.fromString(toCurrency.toLowerCase()); - final inputAddress = responseJSON['input']['refund_address'] as String; + final inputAddress = responseJSON['input']['deposit_address'] as String; final status = responseJSON['state'] as String; final state = TradeState.deserialize(raw: status.toLowerCase()); From 2373b06d520abdb60f4593e6e6024fd04c47d4b5 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Wed, 5 Feb 2020 22:00:00 +0200 Subject: [PATCH 08/22] CWA-169 | added MorphTokenExchangeProvider to exchange trade store --- lib/src/stores/exchange_trade/exchange_trade_store.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/stores/exchange_trade/exchange_trade_store.dart b/lib/src/stores/exchange_trade/exchange_trade_store.dart index 6e6cb2536..008d763f5 100644 --- a/lib/src/stores/exchange_trade/exchange_trade_store.dart +++ b/lib/src/stores/exchange_trade/exchange_trade_store.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart'; import 'package:cake_wallet/src/domain/exchange/changenow/changenow_exchange_provider.dart'; import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; +import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart'; import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; part 'exchange_trade_store.g.dart'; @@ -25,6 +26,9 @@ abstract class ExchangeTradeStoreBase with Store { case ExchangeProviderDescription.changeNow: _provider = ChangeNowExchangeProvider(); break; + case ExchangeProviderDescription.morphToken: + _provider = MorphTokenExchangeProvider(); + break; } _updateTrade(); From 95222ecbae74ff7b49abbec76cb624271a70b722 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Wed, 5 Feb 2020 22:54:55 +0200 Subject: [PATCH 09/22] CWA-169 | added MorphTokenExchangeProvider to dashboard page, trade filter store. Added morph icon to trade row --- lib/src/screens/dashboard/dashboard_page.dart | 23 ++++++++++++++++++- lib/src/screens/dashboard/trade_row.dart | 3 +++ .../action_list/trade_filter_store.dart | 14 +++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 5d2e80361..e13a25161 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -480,7 +480,28 @@ class DashboardPageBodyState extends State { ExchangeProviderDescription .changeNow), ) - ]))) + ]))), + PopupMenuItem( + value: 5, + child: Observer( + builder: (_) => Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text('MorphToken'), + Checkbox( + value: actionListStore + .tradeFilterStore + .displayMorphToken, + onChanged: (value) => + actionListStore + .tradeFilterStore + .toggleDisplayExchange( + ExchangeProviderDescription + .morphToken), + ) + ]))) ], child: Text(S.of(context).filters, style: TextStyle( diff --git a/lib/src/screens/dashboard/trade_row.dart b/lib/src/screens/dashboard/trade_row.dart index c3e88c8e2..75a3371bd 100644 --- a/lib/src/screens/dashboard/trade_row.dart +++ b/lib/src/screens/dashboard/trade_row.dart @@ -82,6 +82,9 @@ class TradeRow extends StatelessWidget { case ExchangeProviderDescription.changeNow: image = Image.asset('assets/images/change_now.png'); break; + case ExchangeProviderDescription.morphToken: + image = Image.asset('assets/images/morph_icon.png'); + break; default: image = null; } diff --git a/lib/src/stores/action_list/trade_filter_store.dart b/lib/src/stores/action_list/trade_filter_store.dart index 3576e459f..4577038e3 100644 --- a/lib/src/stores/action_list/trade_filter_store.dart +++ b/lib/src/stores/action_list/trade_filter_store.dart @@ -11,6 +11,7 @@ abstract class TradeFilterStoreBase with Store { TradeFilterStoreBase( {this.displayXMRTO = true, this.displayChangeNow = true, + this.displayMorphToken = true, this.walletStore}); @observable @@ -19,6 +20,9 @@ abstract class TradeFilterStoreBase with Store { @observable bool displayChangeNow; + @observable + bool displayMorphToken; + WalletStore walletStore; @action @@ -30,13 +34,16 @@ abstract class TradeFilterStoreBase with Store { case ExchangeProviderDescription.xmrto: displayXMRTO = !displayXMRTO; break; + case ExchangeProviderDescription.morphToken: + displayMorphToken = !displayMorphToken; + break; } } List filtered({List trades}) { final _trades = trades.where((item) => item.trade.walletId == walletStore.id).toList(); - final needToFilter = !displayChangeNow || !displayXMRTO; + final needToFilter = !displayChangeNow || !displayXMRTO || !displayMorphToken; return needToFilter ? trades @@ -45,7 +52,10 @@ abstract class TradeFilterStoreBase with Store { item.trade.provider == ExchangeProviderDescription.xmrto) || (displayChangeNow && item.trade.provider == - ExchangeProviderDescription.changeNow)) + ExchangeProviderDescription.changeNow) || + (displayMorphToken && + item.trade.provider == + ExchangeProviderDescription.morphToken)) .toList() : _trades; } From 348d1080c9c8523ea83887dee641819007eeb764 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Thu, 6 Feb 2020 20:30:32 +0200 Subject: [PATCH 10/22] CWA-169 | added call of loadLimits() to changeProvider() and reset() in exchange store. Added btc-xmr pair, added conversion units to crypto amounts to fetchLimits() in MorphTokenExchangeProvider --- .../morphtoken_exchange_provider.dart | 25 +++++++++++++++++-- lib/src/stores/exchange/exchange_store.dart | 2 ++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index 0637607df..b18782ade 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -13,6 +13,7 @@ import 'package:cake_wallet/src/domain/exchange/trade_state.dart'; import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_request.dart'; import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart'; +import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart'; class MorphTokenExchangeProvider extends ExchangeProvider { MorphTokenExchangeProvider() @@ -50,7 +51,8 @@ class MorphTokenExchangeProvider extends ExchangeProvider { ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.eth), ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.bch), ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.ltc), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.dash) + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.dash), + ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.xmr) ]); final trades = Hive.box(Trade.boxName); @@ -70,6 +72,8 @@ class MorphTokenExchangeProvider extends ExchangeProvider { @override Future fetchLimits({CryptoCurrency from, CryptoCurrency to}) async { + const ethereumAmountDivider = 1000000000000000000; + const defaultAmountDivider = 100000000; final url = apiUri + _limitsURISuffix; final headers = {'Content-type': 'application/json'}; final body = @@ -87,8 +91,25 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final min = responseJSON['input']['limits']['min'] as int; final max = responseJSON['input']['limits']['max'] as int; + double minDouble; + double maxDouble; - return Limits(min: min.toDouble(), max: max.toDouble()); + switch (from) { + case CryptoCurrency.xmr: + minDouble = moneroAmountToDouble(amount: min); + maxDouble = moneroAmountToDouble(amount: max); + break; + case CryptoCurrency.eth: + minDouble = min/ethereumAmountDivider; + maxDouble = max/ethereumAmountDivider; + break; + default: + minDouble = min/defaultAmountDivider; + maxDouble = max/defaultAmountDivider; + break; + } + + return Limits(min: minDouble, max: maxDouble); } @override diff --git a/lib/src/stores/exchange/exchange_store.dart b/lib/src/stores/exchange/exchange_store.dart index 832187757..4e65048b0 100644 --- a/lib/src/stores/exchange/exchange_store.dart +++ b/lib/src/stores/exchange/exchange_store.dart @@ -79,6 +79,7 @@ abstract class ExchangeStoreBase with Store { this.provider = provider; depositAmount = ''; receiveAmount = ''; + loadLimits(); } @action @@ -192,6 +193,7 @@ abstract class ExchangeStoreBase with Store { provider = XMRTOExchangeProvider(); depositCurrency = CryptoCurrency.xmr; receiveCurrency = CryptoCurrency.btc; + loadLimits(); } List providersForCurrentPair() { From fd964d68bf6dc0b30a525b2fd49014bfe768b7b0 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Fri, 7 Feb 2020 00:47:21 +0200 Subject: [PATCH 11/22] CWA-169 | added limits check to createTrade() and format to amounts in exchange store --- lib/src/stores/exchange/exchange_store.dart | 54 ++++++++++++++++----- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/lib/src/stores/exchange/exchange_store.dart b/lib/src/stores/exchange/exchange_store.dart index 4e65048b0..8f0526050 100644 --- a/lib/src/stores/exchange/exchange_store.dart +++ b/lib/src/stores/exchange/exchange_store.dart @@ -15,6 +15,8 @@ import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart'; import 'package:cake_wallet/src/stores/exchange/limits_state.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/domain/exchange/limits.dart'; +import 'package:intl/intl.dart'; part 'exchange_store.g.dart'; @@ -33,6 +35,7 @@ abstract class ExchangeStoreBase with Store { receiveCurrency = initialReceiveCurrency; limitsState = LimitsInitialState(); tradeState = ExchangeTradeStateInitial(); + _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12; loadLimits(); } @@ -74,6 +77,10 @@ abstract class ExchangeStoreBase with Store { WalletStore walletStore; + Limits limits; + + NumberFormat _cryptoNumberFormat; + @action void changeProvider({ExchangeProvider provider}) { this.provider = provider; @@ -108,7 +115,7 @@ abstract class ExchangeStoreBase with Store { provider .calculateAmount( from: depositCurrency, to: receiveCurrency, amount: _amount) - .then((amount) => amount.toString()) + .then((amount) => _cryptoNumberFormat.format(amount).toString().replaceAll(RegExp("\\,"), "")) .then((amount) => depositAmount = amount); } @@ -125,7 +132,7 @@ abstract class ExchangeStoreBase with Store { provider .calculateAmount( from: depositCurrency, to: receiveCurrency, amount: _amount) - .then((amount) => amount.toString()) + .then((amount) => _cryptoNumberFormat.format(amount).toString().replaceAll(RegExp("\\,"), "")) .then((amount) => receiveAmount = amount); } @@ -134,7 +141,7 @@ abstract class ExchangeStoreBase with Store { limitsState = LimitsIsLoading(); try { - final limits = await provider.fetchLimits( + limits = await provider.fetchLimits( from: depositCurrency, to: receiveCurrency); limitsState = LimitsLoadedSuccessfully(limits: limits); } catch (e) { @@ -145,6 +152,8 @@ abstract class ExchangeStoreBase with Store { @action Future createTrade() async { TradeRequest request; + String amount; + CryptoCurrency currency; if (provider is XMRTOExchangeProvider) { request = XMRTOTradeRequest( @@ -153,6 +162,8 @@ abstract class ExchangeStoreBase with Store { amount: receiveAmount, address: receiveAddress, refundAddress: depositAddress); + amount = receiveAmount; + currency = receiveCurrency; } if (provider is ChangeNowExchangeProvider) { @@ -162,6 +173,8 @@ abstract class ExchangeStoreBase with Store { amount: depositAmount, refundAddress: depositAddress, address: receiveAddress); + amount = depositAmount; + currency = depositCurrency; } if (provider is MorphTokenExchangeProvider) { @@ -171,17 +184,36 @@ abstract class ExchangeStoreBase with Store { amount: depositAmount, refundAddress: depositAddress, address: receiveAddress); + amount = depositAmount; + currency = depositCurrency; } - try { - tradeState = TradeIsCreating(); - final trade = await provider.createTrade(request: request); - trade.walletId = walletStore.id; - await trades.add(trade); - tradeState = TradeIsCreatedSuccessfully(trade: trade); - } catch (e) { - tradeState = TradeIsCreatedFailure(error: e.toString()); + if (limitsState is LimitsLoadedSuccessfully) { + if (double.parse(amount) < limits.min) { + final error = "Trade for ${provider.description} is not created. " + "Amount is less then minimal: ${limits.min} ${currency.toString()}"; + tradeState = TradeIsCreatedFailure(error: error); + } else if (limits.max != null && double.parse(amount) > limits.max) { + final error = "Trade for ${provider.description} is not created. " + "Amount is more then maximum: ${limits.max} ${currency.toString()}"; + tradeState = TradeIsCreatedFailure(error: error); + } else { + try { + tradeState = TradeIsCreating(); + final trade = await provider.createTrade(request: request); + trade.walletId = walletStore.id; + await trades.add(trade); + tradeState = TradeIsCreatedSuccessfully(trade: trade); + } catch (e) { + tradeState = TradeIsCreatedFailure(error: e.toString()); + } + } + } else { + final error = "Trade for ${provider.description} is not created. " + "Limits loading failed"; + tradeState = TradeIsCreatedFailure(error: error); } + } @action From d6cf32c764836ae07dc08c4a853f4a46b9ac8bb7 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Fri, 7 Feb 2020 12:06:13 +0200 Subject: [PATCH 12/22] CWA-169 | fixed limits for ethereum in MorphTokenExchangeProvider --- .../morphtoken_exchange_provider.dart | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index b18782ade..b609d18ec 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -90,26 +90,34 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final min = responseJSON['input']['limits']['min'] as int; - final max = responseJSON['input']['limits']['max'] as int; - double minDouble; - double maxDouble; + int max; + double ethMax; + + if (from == CryptoCurrency.eth) { + ethMax = responseJSON['input']['limits']['max'] as double; + } else { + max = responseJSON['input']['limits']['max'] as int; + } + + double minFormatted; + double maxFormatted; switch (from) { case CryptoCurrency.xmr: - minDouble = moneroAmountToDouble(amount: min); - maxDouble = moneroAmountToDouble(amount: max); + minFormatted = moneroAmountToDouble(amount: min); + maxFormatted = moneroAmountToDouble(amount: max); break; case CryptoCurrency.eth: - minDouble = min/ethereumAmountDivider; - maxDouble = max/ethereumAmountDivider; + minFormatted = min/ethereumAmountDivider; + maxFormatted = ethMax/ethereumAmountDivider; break; default: - minDouble = min/defaultAmountDivider; - maxDouble = max/defaultAmountDivider; + minFormatted = min/defaultAmountDivider; + maxFormatted = max/defaultAmountDivider; break; } - return Limits(min: minDouble, max: maxDouble); + return Limits(min: minFormatted, max: maxFormatted); } @override From 7c83a71916763d10d42d71318a3fea9c5a4fea9c Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Fri, 7 Feb 2020 13:07:58 +0200 Subject: [PATCH 13/22] CWA-169 | added processing state to TradeState --- lib/src/domain/exchange/trade_state.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/src/domain/exchange/trade_state.dart b/lib/src/domain/exchange/trade_state.dart index 2487ae89c..0a94cf4c0 100644 --- a/lib/src/domain/exchange/trade_state.dart +++ b/lib/src/domain/exchange/trade_state.dart @@ -26,6 +26,7 @@ class TradeState extends EnumerableItem with Serializable { static const created = TradeState(raw: 'created', title: 'Created'); static const finished = TradeState(raw: 'finished', title: 'Finished'); static const waiting = TradeState(raw: 'waiting', title: 'Waiting'); + static const processing = TradeState(raw: 'processing', title: 'Processing'); static TradeState deserialize({String raw}) { switch (raw) { @@ -59,6 +60,8 @@ class TradeState extends EnumerableItem with Serializable { return finished; case 'waiting': return waiting; + case 'processing': + return processing; default: return null; } From ad241ca1dbd78f2f0da44810229c3c2f4636f59d Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Fri, 7 Feb 2020 14:06:15 +0200 Subject: [PATCH 14/22] CWA-169 | created check_amount then added to transaction_info and to trade --- lib/src/domain/common/check_amount.dart | 8 ++++++++ lib/src/domain/common/transaction_info.dart | 5 +++-- lib/src/domain/exchange/trade.dart | 3 +++ lib/src/screens/dashboard/dashboard_page.dart | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 lib/src/domain/common/check_amount.dart diff --git a/lib/src/domain/common/check_amount.dart b/lib/src/domain/common/check_amount.dart new file mode 100644 index 000000000..77e0e5a62 --- /dev/null +++ b/lib/src/domain/common/check_amount.dart @@ -0,0 +1,8 @@ +String checkAmount(String amount) { + if (!amount.contains('.')) { + return amount + '.00'; + } else if (amount.endsWith('.')) { + return amount + '00'; + } + return amount; +} \ No newline at end of file diff --git a/lib/src/domain/common/transaction_info.dart b/lib/src/domain/common/transaction_info.dart index 08fcd2372..e72f022d0 100644 --- a/lib/src/domain/common/transaction_info.dart +++ b/lib/src/domain/common/transaction_info.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart'; import 'package:cw_monero/structs/transaction_info_row.dart'; import 'package:cake_wallet/src/domain/common/parseBoolFromString.dart'; import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; +import 'package:cake_wallet/src/domain/common/check_amount.dart'; class TransactionInfo { TransactionInfo(this.id, this.height, this.direction, this.date, @@ -40,9 +41,9 @@ class TransactionInfo { String _fiatAmount; - String amountFormatted() => '${moneroAmountToString(amount: amount)} XMR'; + String amountFormatted() => '${checkAmount(moneroAmountToString(amount: amount))} XMR'; String fiatAmount() => _fiatAmount ?? ''; - void changeFiatAmount(String amount) => _fiatAmount = amount; + void changeFiatAmount(String amount) => _fiatAmount = checkAmount(amount); } diff --git a/lib/src/domain/exchange/trade.dart b/lib/src/domain/exchange/trade.dart index 3554d340a..9f3f1cb77 100644 --- a/lib/src/domain/exchange/trade.dart +++ b/lib/src/domain/exchange/trade.dart @@ -2,6 +2,7 @@ import 'package:hive/hive.dart'; import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/domain/exchange/trade_state.dart'; +import 'package:cake_wallet/src/domain/common/check_amount.dart'; part 'trade.g.dart'; @@ -101,4 +102,6 @@ class Trade extends HiveObject { 'wallet_id': walletId }; } + + String amountFormatted() => checkAmount(amount); } diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index e13a25161..23d5a3f8f 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -577,7 +577,7 @@ class DashboardPageBodyState extends State { final formattedAmount = trade.amount != null ? savedDisplayMode == BalanceDisplayMode.hiddenBalance ? '---' - : trade.amount + : trade.amountFormatted() : trade.amount; return TradeRow( From d80123d960014d62279339ab257e53ce88122a23 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Fri, 7 Feb 2020 15:14:06 +0200 Subject: [PATCH 15/22] CWA-169 | translated error messages for limits --- lib/generated/i18n.dart | 63 +++++++++++++++++++++ lib/src/stores/exchange/exchange_store.dart | 16 ++---- res/values/strings_de.arb | 3 + res/values/strings_en.arb | 3 + res/values/strings_es.arb | 3 + res/values/strings_hi.arb | 3 + res/values/strings_ja.arb | 3 + res/values/strings_ko.arb | 3 + res/values/strings_nl.arb | 3 + res/values/strings_pl.arb | 3 + res/values/strings_pt.arb | 3 + res/values/strings_ru.arb | 3 + res/values/strings_zh.arb | 3 + 13 files changed, 102 insertions(+), 10 deletions(-) diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart index c47b8cb4e..9b2e695af 100644 --- a/lib/generated/i18n.dart +++ b/lib/generated/i18n.dart @@ -271,6 +271,9 @@ class S implements WidgetsLocalizations { String change_language_to(String language) => "Change language to ${language}?"; String commit_transaction_amount_fee(String amount, String fee) => "Commit transaction\nAmount: ${amount}\nFee: ${fee}"; String copied_key_to_clipboard(String key) => "Copied ${key} to Clipboard"; + String error_text_limits_loading_failed(String provider) => "Trade for ${provider} is not created. Limits loading failed"; + String error_text_maximum_limit(String provider, String max, String currency) => "Trade for ${provider} is not created. Amount is more then maximum: ${max} ${currency}"; + String error_text_minimal_limit(String provider, String min, String currency) => "Trade for ${provider} is not created. Amount is less then minimal: ${min} ${currency}"; String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "By pressing confirm, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown above. Or you can send from your external wallet to the above address/QR code.\n\nPlease press confirm to continue or go back to change the amounts.\n\n"; String exchange_result_description(String fetchingLabel, String from) => "Please send ${fetchingLabel} ${from} to the address shown above.\n\n"; String failed_authentication(String state_error) => "Failed authentication. ${state_error}"; @@ -802,6 +805,8 @@ class $de extends S { @override String router_no_route(String name) => "Keine Route definiert für ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "Handel für ${provider} wird nicht erstellt. Menge ist weniger als minimal: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "Handel ${tradeId} von ${title} nicht gefunden."; @override String transaction_details_copied(String title) => "${title} in die Zwischenablage kopiert"; @@ -820,6 +825,8 @@ class $de extends S { @override String max_value(String value, String currency) => "Max: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "Handel für ${provider} wird nicht erstellt. Menge ist mehr als maximal: ${max} ${currency}"; + @override String min_value(String value, String currency) => "Mindest: ${value} ${currency}"; @override String failed_authentication(String state_error) => "Authentifizierung fehlgeschlagen. ${state_error}"; @@ -828,6 +835,8 @@ class $de extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Durch Drücken von Bestätigen wird gesendet ${fetchingLabel} ${from} von Ihrer Brieftasche aus angerufen ${walletName} an die oben angegebene Adresse. Oder Sie können von Ihrem externen Portemonnaie an die oben angegebene Adresse / QR-Code senden.\n\nBitte bestätigen Sie, um fortzufahren, oder gehen Sie zurück, um die Beträge zu änderns.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "Handel für ${provider} wird nicht erstellt. Das Laden der Limits ist fehlgeschlagen"; + @override String exchange_result_description(String fetchingLabel, String from) => "Bitte senden ${fetchingLabel} ${from} an die oben angegebene Adresse.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "Transaktion festschreiben\nMenge: ${amount}\nGebühr: ${fee}"; @@ -1350,6 +1359,8 @@ class $hi extends S { @override String router_no_route(String name) => "के लिए कोई मार्ग निर्धारित नहीं है ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि कम है तो न्यूनतम: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "व्यापार ${tradeId} of ${title} नहीं मिला."; @override String transaction_details_copied(String title) => "${title} क्लिपबोर्ड पर नकल"; @@ -1368,6 +1379,8 @@ class $hi extends S { @override String max_value(String value, String currency) => "मैक्स: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि अधिक है तो अधिकतम: ${max} ${currency}"; + @override String min_value(String value, String currency) => "मिन: ${value} ${currency}"; @override String failed_authentication(String state_error) => "प्रमाणीकरण विफल. ${state_error}"; @@ -1376,6 +1389,8 @@ class $hi extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "पुष्टि दबाकर, आप भेज रहे होंगे ${fetchingLabel} ${from} अपने बटुए से ${walletName} ऊपर दिखाए गए पते पर। या आप अपने बाहरी वॉलेट से उपरोक्त पते / क्यूआर कोड पर भेज सकते हैं।\n\nकृपया जारी रखने या राशि बदलने के लिए वापस जाने के लिए पुष्टि करें दबाएं.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "व्यापार ${provider} के लिए नहीं बनाया गया है। लोडिंग की सीमाएं विफल रहीं"; + @override String exchange_result_description(String fetchingLabel, String from) => "कृपया भेजें ${fetchingLabel} ${from} ऊपर दिखाए गए पते पर\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "लेन-देन करें\nरकम: ${amount}\nशुल्क: ${fee}"; @@ -1898,6 +1913,8 @@ class $ru extends S { @override String router_no_route(String name) => "Экран не найден ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "Сделка для ${provider} не создана. Сумма меньше минимальной: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "Сделка ${tradeId} ${title} не найдена."; @override String transaction_details_copied(String title) => "${title} скопировано в буфер обмена"; @@ -1916,6 +1933,8 @@ class $ru extends S { @override String max_value(String value, String currency) => "Макс: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "Сделка для ${provider} не создана. Сумма больше максимальной: ${max} ${currency}"; + @override String min_value(String value, String currency) => "Мин: ${value} ${currency}"; @override String failed_authentication(String state_error) => "Ошибка аутентификации. ${state_error}"; @@ -1924,6 +1943,8 @@ class $ru extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Нажимая подтвердить, Вы отправите ${fetchingLabel} ${from} с Вашего кошелька ${walletName} на адрес указанный выше. Или Вы можете отправить со своего внешнего кошелька на вышеуказанный адрес / QR-код.\n\nПожалуйста, нажмите подтвердить для продолжения или вернитесь назад для изменения суммы.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "Сделка для ${provider} не создана. Ошибка загрузки лимитов"; + @override String exchange_result_description(String fetchingLabel, String from) => "Пожалуйста отправьте ${fetchingLabel} ${from} на адрес, указанный выше.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "Подтвердить транзакцию \nСумма: ${amount}\nСбор: ${fee}"; @@ -2446,6 +2467,8 @@ class $ko extends S { @override String router_no_route(String name) => "에 정의 된 경로가 없습니다 ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "거래 ${provider} 가 생성되지 않습니다. 금액이 최소보다 적습니다. ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "무역 ${tradeId} 의 ${title} 찾을 수 없습니다."; @override String transaction_details_copied(String title) => "${title} 클립 보드에 복사"; @@ -2464,6 +2487,8 @@ class $ko extends S { @override String max_value(String value, String currency) => "맥스: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "거래 ${provider} 가 생성되지 않습니다. 금액이 최대 값보다 많습니다. ${max} ${currency}"; + @override String min_value(String value, String currency) => "최소: ${value} ${currency}"; @override String failed_authentication(String state_error) => "인증 실패. ${state_error}"; @@ -2472,6 +2497,8 @@ class $ko extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "확인을 누르면 전송됩니다 ${fetchingLabel} ${from} 지갑에서 ${walletName} 위에 표시된 주소로. 또는 외부 지갑에서 위의 주소 / QR 코드로 보낼 수 있습니다.\n\n확인을 눌러 계속하거나 금액을 변경하려면 돌아가십시오.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "거래 ${provider} 가 생성되지 않습니다. 로딩 실패"; + @override String exchange_result_description(String fetchingLabel, String from) => "보내주세요 ${fetchingLabel} ${from} 위에 표시된 주소로.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "커밋 거래\n양: ${amount}\n보수: ${fee}"; @@ -2994,6 +3021,8 @@ class $pt extends S { @override String router_no_route(String name) => "Nenhuma rota definida para ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "A troca por ${provider} não é criada. O valor é menor que o mínimo: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "A troca ${tradeId} de ${title} não foi encontrada."; @override String transaction_details_copied(String title) => "${title} copiados para a área de transferência"; @@ -3012,6 +3041,8 @@ class $pt extends S { @override String max_value(String value, String currency) => "Máx: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "A troca por ${provider} não é criada. O valor é superior ao máximo: ${max} ${currency}"; + @override String min_value(String value, String currency) => "Mín: ${value} ${currency}"; @override String failed_authentication(String state_error) => "Falha na autenticação. ${state_error}"; @@ -3020,6 +3051,8 @@ class $pt extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Ao confirmar, você enviará ${fetchingLabel} ${from} da sua carteira ${walletName} para o endereço exibido acima. Você também pode enviar com uma carteira externa para o endereço/código QR acima.\n\nPressione Confirmar para continuar ou volte para alterar os valores.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "A troca por ${provider} não é criada. Falha no carregamento dos limites"; + @override String exchange_result_description(String fetchingLabel, String from) => "Por favor, envie ${fetchingLabel} ${from} para o endereço mostrado acima.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "Confirmar transação\nQuantia: ${amount}\nTaxa: ${fee}"; @@ -3542,6 +3575,8 @@ class $ja extends S { @override String router_no_route(String name) => "ルートが定義されていません ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "${provider} の取引は作成されません。 金額は最小額より少ない: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "トレード ${tradeId} of ${title} 見つかりません"; @override String transaction_details_copied(String title) => "${title} クリップボードにコピーしました"; @@ -3560,6 +3595,8 @@ class $ja extends S { @override String max_value(String value, String currency) => "マックス: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "${provider} の取引は作成されません。 金額は最大値を超えています: ${max} ${currency}"; + @override String min_value(String value, String currency) => "分: ${value} ${currency}"; @override String failed_authentication(String state_error) => "認証失敗. ${state_error}"; @@ -3568,6 +3605,8 @@ class $ja extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "確認を押すと、送信されます ${fetchingLabel} ${from} と呼ばれるあなたの財布から ${walletName} 上記のアドレスへ. または、外部ウォレットから上記のアドレス/ QRコードに送信できます.\n\n確認を押して続行するか、戻って金額を変更してください.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "${provider} の取引は作成されません。 制限の読み込みに失敗しました"; + @override String exchange_result_description(String fetchingLabel, String from) => "送信してください ${fetchingLabel} ${from} 上記のアドレスへ.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "トランザクションをコミット\n量: ${amount}\n費用: ${fee}"; @@ -4094,6 +4133,8 @@ class $pl extends S { @override String router_no_route(String name) => "Brak zdefiniowanej trasy dla ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "Wymiana dla ${provider} nie została utworzona. Kwota jest mniejsza niż minimalna: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "Handel ${tradeId} of ${title} nie znaleziono."; @override String transaction_details_copied(String title) => "${title} skopiowane do schowka"; @@ -4112,6 +4153,8 @@ class $pl extends S { @override String max_value(String value, String currency) => "Max: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "Wymiana dla ${provider} nie została utworzona. Kwota jest większa niż maksymalna: ${max} ${currency}"; + @override String min_value(String value, String currency) => "Min: ${value} ${currency}"; @override String failed_authentication(String state_error) => "Nieudane uwierzytelnienie. ${state_error}"; @@ -4120,6 +4163,8 @@ class $pl extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Naciskając Potwierdź, wyślesz ${fetchingLabel} ${from} z twojego portfela ${walletName} z twojego portfela. Lub możesz wysłać z zewnętrznego portfela na powyższy adres / kod QR.\n\nNaciśnij Potwierdź, aby kontynuować lub wróć, aby zmienić kwoty.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "Wymiana dla ${provider} nie została utworzona. Ładowanie limitów nie powiodło się"; + @override String exchange_result_description(String fetchingLabel, String from) => "Proszę wyślij ${fetchingLabel} ${from} na adres podany powyżej.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "Zatwierdź transakcję\nIlość: ${amount}\nOpłata: ${fee}"; @@ -4642,6 +4687,8 @@ class $es extends S { @override String router_no_route(String name) => "No hay ruta definida para ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "El comercio por ${provider} no se crea. La cantidad es menos que mínima: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "Comercio ${tradeId} de ${title} no encontrado."; @override String transaction_details_copied(String title) => "${title} Copiado al portapapeles"; @@ -4660,6 +4707,8 @@ class $es extends S { @override String max_value(String value, String currency) => "Max: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "El comercio por ${provider} no se crea. La cantidad es más que el máximo: ${max} ${currency}"; + @override String min_value(String value, String currency) => "Min: ${value} ${currency}"; @override String failed_authentication(String state_error) => "Autenticación fallida. ${state_error}"; @@ -4668,6 +4717,8 @@ class $es extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Al presionar confirmar, enviará ${fetchingLabel} ${from} desde su billetera llamada ${walletName} a la dirección que se muestra arriba. O puede enviar desde su billetera externa a la dirección / código QR anterior.\n\nPresione confirmar para continuar o regrese para cambiar los montos.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "El comercio por ${provider} no se crea. Límites de carga fallidos"; + @override String exchange_result_description(String fetchingLabel, String from) => "Envíe ${fetchingLabel} ${from} a la dirección que se muestra arriba.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}"; @@ -5190,6 +5241,8 @@ class $nl extends S { @override String router_no_route(String name) => "Geen route gedefinieerd voor ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "Ruil voor ${provider} is niet gemaakt. Bedrag is minder dan minimaal: ${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "Handel ${tradeId} van ${title} niet gevonden."; @override String transaction_details_copied(String title) => "${title} gekopieerd naar het klembord"; @@ -5208,6 +5261,8 @@ class $nl extends S { @override String max_value(String value, String currency) => "Max: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "Ruil voor ${provider} is niet gemaakt. Bedrag is meer dan maximaal: ${max} ${currency}"; + @override String min_value(String value, String currency) => "Min: ${value} ${currency}"; @override String failed_authentication(String state_error) => "Mislukte authenticatie. ${state_error}"; @@ -5216,6 +5271,8 @@ class $nl extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "Door op bevestigen te drukken, wordt u verzonden ${fetchingLabel} ${from} uit je portemonnee genoemd ${walletName} naar bovenstaand adres. Of u kunt uw externe portemonnee naar bovenstaand adres / QR-code sturen.\n\nDruk op bevestigen om door te gaan of terug te gaan om de bedragen te wijzigen.\n\n"; @override + String error_text_limits_loading_failed(String provider) => "Ruil voor ${provider} is niet gemaakt. Beperkingen laden mislukt"; + @override String exchange_result_description(String fetchingLabel, String from) => "Zend alstublieft ${fetchingLabel} ${from} naar bovenstaand adres.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "Verricht transactie\nBedrag: ${amount}\nhonorarium: ${fee}"; @@ -5738,6 +5795,8 @@ class $zh extends S { @override String router_no_route(String name) => "未定义路线 ${name}"; @override + String error_text_minimal_limit(String provider, String min, String currency) => "未創建 ${provider} 交易。 金額少於最小值:${min} ${currency}"; + @override String trade_id_not_found(String tradeId, String title) => "贸易方式 ${tradeId} 的 ${title} 未找到."; @override String transaction_details_copied(String title) => "${title} 复制到剪贴板"; @@ -5756,6 +5815,8 @@ class $zh extends S { @override String max_value(String value, String currency) => "最高: ${value} ${currency}"; @override + String error_text_maximum_limit(String provider, String max, String currency) => "未創建 ${provider} 交易。 金額大於最大值:${max} ${currency}"; + @override String min_value(String value, String currency) => "敏: ${value} ${currency}"; @override String failed_authentication(String state_error) => "身份验证失败. ${state_error}"; @@ -5764,6 +5825,8 @@ class $zh extends S { @override String exchange_result_confirm(String fetchingLabel, String from, String walletName) => "点击确认 您将发送 ${fetchingLabel} ${from} 从你的钱包里 ${walletName} 到上面显示的地址. 或者,您也可以从外部钱包发送上述地址/ QR码。\n\n请按确认继续或返回以更改金额\n\n"; @override + String error_text_limits_loading_failed(String provider) => "未創建 ${provider} 交易。 限制加載失敗"; + @override String exchange_result_description(String fetchingLabel, String from) => "请发送 ${fetchingLabel} ${from} 到上面显示的地址.\n\n'"; @override String commit_transaction_amount_fee(String amount, String fee) => "提交交易\n量: ${amount}\nFee: ${fee}"; diff --git a/lib/src/stores/exchange/exchange_store.dart b/lib/src/stores/exchange/exchange_store.dart index 8f0526050..189bbea8a 100644 --- a/lib/src/stores/exchange/exchange_store.dart +++ b/lib/src/stores/exchange/exchange_store.dart @@ -188,15 +188,13 @@ abstract class ExchangeStoreBase with Store { currency = depositCurrency; } - if (limitsState is LimitsLoadedSuccessfully) { + if (limitsState is LimitsLoadedSuccessfully && amount != null) { if (double.parse(amount) < limits.min) { - final error = "Trade for ${provider.description} is not created. " - "Amount is less then minimal: ${limits.min} ${currency.toString()}"; - tradeState = TradeIsCreatedFailure(error: error); + tradeState = TradeIsCreatedFailure(error: S.current.error_text_minimal_limit("${provider.description}", + "${limits.min}", currency.toString())); } else if (limits.max != null && double.parse(amount) > limits.max) { - final error = "Trade for ${provider.description} is not created. " - "Amount is more then maximum: ${limits.max} ${currency.toString()}"; - tradeState = TradeIsCreatedFailure(error: error); + tradeState = TradeIsCreatedFailure(error: S.current.error_text_maximum_limit("${provider.description}", + "${limits.max}", currency.toString())); } else { try { tradeState = TradeIsCreating(); @@ -209,9 +207,7 @@ abstract class ExchangeStoreBase with Store { } } } else { - final error = "Trade for ${provider.description} is not created. " - "Limits loading failed"; - tradeState = TradeIsCreatedFailure(error: error); + tradeState = TradeIsCreatedFailure(error: S.current.error_text_limits_loading_failed("${provider.description}")); } } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8dd44f7b6..4a2e6f016 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "Der Wallet darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein", "error_text_keys" : "Walletschlüssel können nur 64 hexadezimale Zeichen enthalten", "error_text_crypto_currency" : "Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 12 sein.", + "error_text_minimal_limit" : "Handel für ${provider} wird nicht erstellt. Menge ist weniger als minimal: ${min} ${currency}", + "error_text_maximum_limit" : "Handel für ${provider} wird nicht erstellt. Menge ist mehr als maximal: ${max} ${currency}", + "error_text_limits_loading_failed" : "Handel für ${provider} wird nicht erstellt. Das Laden der Limits ist fehlgeschlagen", "auth_store_ban_timeout" : "Auszeit verbieten", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3e878bbc3..14fea0623 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "Wallet name can only contain letters, numbers\nand must be between 1 and 15 characters long", "error_text_keys" : "Wallet keys can only contain 64 chars in hex", "error_text_crypto_currency" : "The number of fraction digits\nmust be less or equal to 12", + "error_text_minimal_limit" : "Trade for ${provider} is not created. Amount is less then minimal: ${min} ${currency}", + "error_text_maximum_limit" : "Trade for ${provider} is not created. Amount is more then maximum: ${max} ${currency}", + "error_text_limits_loading_failed" : "Trade for ${provider} is not created. Limits loading failed", "auth_store_ban_timeout" : "ban_timeout", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 3d8e9472d..2d3cbd590 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "El nombre de la billetera solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud", "error_text_keys" : "Las llaves de billetera solo pueden contener 64 caracteres en hexadecimal", "error_text_crypto_currency" : "El número de dígitos fraccionarios \ndebe ser menor o igual a 12", + "error_text_minimal_limit" : "El comercio por ${provider} no se crea. La cantidad es menos que mínima: ${min} ${currency}", + "error_text_maximum_limit" : "El comercio por ${provider} no se crea. La cantidad es más que el máximo: ${max} ${currency}", + "error_text_limits_loading_failed" : "El comercio por ${provider} no se crea. Límites de carga fallidos", "auth_store_ban_timeout" : "prohibición de tiempo de espera", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 712bc9082..f7ea5339a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "वॉलेट नाम में केवल अक्षर, संख्याएं हो सकती हैं\nऔर 1 और 15 वर्णों के बीच लंबा होना चाहिए", "error_text_keys" : "वॉलेट कीज़ में हेक्स में केवल 64 वर्ण हो सकते हैं", "error_text_crypto_currency" : "अंश अंकों की संख्या\n12 से कम या इसके बराबर होना चाहिए", + "error_text_minimal_limit" : "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि कम है तो न्यूनतम: ${min} ${currency}", + "error_text_maximum_limit" : "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि अधिक है तो अधिकतम: ${max} ${currency}", + "error_text_limits_loading_failed" : "व्यापार ${provider} के लिए नहीं बनाया गया है। लोडिंग की सीमाएं विफल रहीं", "auth_store_ban_timeout" : "समय की पाबंदी", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 0dd826a09..f2908ef67 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "ウォレット名には文字のみを含めることができます\n1〜15文字である必要があります", "error_text_keys" : "ウォレットキーには、16進数で64文字しか含めることができません", "error_text_crypto_currency" : "小数桁数\n12以下でなければなりません", + "error_text_minimal_limit" : "${provider} の取引は作成されません。 金額は最小額より少ない: ${min} ${currency}", + "error_text_maximum_limit" : "${provider} の取引は作成されません。 金額は最大値を超えています: ${max} ${currency}", + "error_text_limits_loading_failed" : "${provider} の取引は作成されません。 制限の読み込みに失敗しました", "auth_store_ban_timeout" : "禁止タイムアウト", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 1be04579d..0a27b29dd 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "지갑 이름은 문자, 숫자 만 포함 할 수 있습니다\n1 ~ 15 자 사이 여야합니다", "error_text_keys" : "지갑 키는 16 진수로 64 자만 포함 할 수 있습니다", "error_text_crypto_currency" : "소수 자릿수\n12 이하 여야합니다", + "error_text_minimal_limit" : "거래 ${provider} 가 생성되지 않습니다. 금액이 최소보다 적습니다. ${min} ${currency}", + "error_text_maximum_limit" : "거래 ${provider} 가 생성되지 않습니다. 금액이 최대 값보다 많습니다. ${max} ${currency}", + "error_text_limits_loading_failed" : "거래 ${provider} 가 생성되지 않습니다. 로딩 실패", "auth_store_ban_timeout" : "타임 아웃 금지", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 7690fd275..bef66eda6 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "Naam portemonnee kan alleen letters, cijfers bevatten\nen moet tussen de 1 en 15 tekens lang zijn", "error_text_keys" : "Portefeuillesleutels kunnen maximaal 64 tekens bevatten in hexadecimale volgorde", "error_text_crypto_currency" : "Het aantal breukcijfers\nmoet kleiner zijn dan of gelijk zijn aan 12", + "error_text_minimal_limit" : "Ruil voor ${provider} is niet gemaakt. Bedrag is minder dan minimaal: ${min} ${currency}", + "error_text_maximum_limit" : "Ruil voor ${provider} is niet gemaakt. Bedrag is meer dan maximaal: ${max} ${currency}", + "error_text_limits_loading_failed" : "Ruil voor ${provider} is niet gemaakt. Beperkingen laden mislukt", "auth_store_ban_timeout" : "time-out verbieden", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index fdbd6df3f..aa0dbdbb2 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "Nazwa portfela może zawierać tylko litery i cyfry\ni musi mieć od 1 do 15 znaków", "error_text_keys" : "Klucze portfela mogą zawierać tylko 64 znaki w systemie szesnastkowym", "error_text_crypto_currency" : "Liczba cyfr ułamkowych\nmusi być mniejsza lub równa 12", + "error_text_minimal_limit" : "Wymiana dla ${provider} nie została utworzona. Kwota jest mniejsza niż minimalna: ${min} ${currency}", + "error_text_maximum_limit" : "Wymiana dla ${provider} nie została utworzona. Kwota jest większa niż maksymalna: ${max} ${currency}", + "error_text_limits_loading_failed" : "Wymiana dla ${provider} nie została utworzona. Ładowanie limitów nie powiodło się", "auth_store_ban_timeout" : "przekroczenie limitu czasu", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 366ec1e81..a100c8898 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "O nome da carteira só pode conter letras, números\ne deve ter entre 1 e 15 caracteres", "error_text_keys" : "As chaves da carteira podem conter apenas 64 caracteres em hexadecimal", "error_text_crypto_currency" : "O número de dígitos decimais\ndeve ser menor ou igual a 12", + "error_text_minimal_limit" : "A troca por ${provider} não é criada. O valor é menor que o mínimo: ${min} ${currency}", + "error_text_maximum_limit" : "A troca por ${provider} não é criada. O valor é superior ao máximo: ${max} ${currency}", + "error_text_limits_loading_failed" : "A troca por ${provider} não é criada. Falha no carregamento dos limites", "auth_store_ban_timeout" : "ban_timeout", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 3e5ededb0..b76d6a1f1 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "Имя кошелька может содержать только буквы, цифры\nи может быть от 1 до 15 символов в длину", "error_text_keys" : "Ключи кошелька могут содержать только 64 символа в hex", "error_text_crypto_currency" : "Количество цифр после запятой\nдолжно быть меньше или равно 12", + "error_text_minimal_limit" : "Сделка для ${provider} не создана. Сумма меньше минимальной: ${min} ${currency}", + "error_text_maximum_limit" : "Сделка для ${provider} не создана. Сумма больше максимальной: ${max} ${currency}", + "error_text_limits_loading_failed" : "Сделка для ${provider} не создана. Ошибка загрузки лимитов", "auth_store_ban_timeout" : "ban_timeout", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 451168f6b..c631e8950 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -278,6 +278,9 @@ "error_text_wallet_name" : "钱包名称只能包含字母,数字\n且必须介于1到15个字符之间", "error_text_keys" : "钱包密钥只能包含16个字符的十六进制字符", "error_text_crypto_currency" : "小数位数\n必须小于或等于12", + "error_text_minimal_limit" : "未創建 ${provider} 交易。 金額少於最小值:${min} ${currency}", + "error_text_maximum_limit" : "未創建 ${provider} 交易。 金額大於最大值:${max} ${currency}", + "error_text_limits_loading_failed" : "未創建 ${provider} 交易。 限制加載失敗", "auth_store_ban_timeout" : "禁止超时", From eb875b1321c604dc6bd782fed1a827fa8d47aa53 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Fri, 7 Feb 2020 15:34:00 +0200 Subject: [PATCH 16/22] CWA-169 | added try-catch to calculateAmount() in MorphTokenExchangeProvider --- .../exchange/morphtoken/morphtoken_exchange_provider.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index b609d18ec..55df4d26e 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -214,8 +214,12 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final response = await get(url); final responseJSON = json.decode(response.body) as Map; final rate = responseJSON['data'][from.toString()][to.toString()] as String; - final estimatedAmount = double.parse(rate) * amount; - return estimatedAmount; + try { + final estimatedAmount = double.parse(rate) * amount; + return estimatedAmount; + } catch(e) { + return 0.0; + } } } From 163d1c48a440dfa464cad9182ba36bab25939e7e Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Mon, 10 Feb 2020 19:50:00 +0200 Subject: [PATCH 17/22] CWA-169 | added tag to body of createTrade(), created crypto_amount_format, bitcoin_amount_format, bitcoin_cash_amount_format, dash_amount_format, ethereum_amount_format, litecoin_amount_format, changed monero_amount_format, added setup_locator for inject the box --- lib/main.dart | 3 ++ .../domain/bitcoin/bitcoin_amount_format.dart | 6 +++ .../bitcoin_cash_amount_format.dart | 6 +++ .../domain/common/crypto_amount_format.dart | 1 + lib/src/domain/common/setup_locator.dart | 7 ++++ lib/src/domain/dash/dash_amount_format.dart | 6 +++ .../ethereum/ethereum_amount_format.dart | 6 +++ .../morphtoken_exchange_provider.dart | 39 +++++++++++++------ .../litecoin/litecoin_amount_format.dart | 6 +++ .../domain/monero/monero_amount_format.dart | 5 ++- pubspec.lock | 7 ++++ pubspec.yaml | 1 + 12 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 lib/src/domain/bitcoin/bitcoin_amount_format.dart create mode 100644 lib/src/domain/bitcoin_cash/bitcoin_cash_amount_format.dart create mode 100644 lib/src/domain/common/crypto_amount_format.dart create mode 100644 lib/src/domain/common/setup_locator.dart create mode 100644 lib/src/domain/dash/dash_amount_format.dart create mode 100644 lib/src/domain/ethereum/ethereum_amount_format.dart create mode 100644 lib/src/domain/litecoin/litecoin_amount_format.dart diff --git a/lib/main.dart b/lib/main.dart index 2cf7e5911..18da983f6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -35,6 +35,7 @@ import 'package:cake_wallet/src/domain/common/wallet_type.dart'; import 'package:cake_wallet/src/domain/services/wallet_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/domain/common/language.dart'; +import 'package:cake_wallet/src/domain/common/setup_locator.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -65,6 +66,8 @@ void main() async { await Hive.openBox(Trade.boxName, encryptionKey: tradesBoxKey); final walletInfoSource = await Hive.openBox(WalletInfo.boxName); + setupLocator(trades); + final sharedPreferences = await SharedPreferences.getInstance(); final walletService = WalletService(); final walletListService = WalletListService( diff --git a/lib/src/domain/bitcoin/bitcoin_amount_format.dart b/lib/src/domain/bitcoin/bitcoin_amount_format.dart new file mode 100644 index 000000000..c816dedc2 --- /dev/null +++ b/lib/src/domain/bitcoin/bitcoin_amount_format.dart @@ -0,0 +1,6 @@ +import 'package:cake_wallet/src/domain/common/crypto_amount_format.dart'; + +const bitcoinAmountDivider = 100000000; + +double bitcoinAmountToDouble({int amount}) => + cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider); \ No newline at end of file diff --git a/lib/src/domain/bitcoin_cash/bitcoin_cash_amount_format.dart b/lib/src/domain/bitcoin_cash/bitcoin_cash_amount_format.dart new file mode 100644 index 000000000..bbb0192c8 --- /dev/null +++ b/lib/src/domain/bitcoin_cash/bitcoin_cash_amount_format.dart @@ -0,0 +1,6 @@ +import 'package:cake_wallet/src/domain/common/crypto_amount_format.dart'; + +const bitcoinCashAmountDivider = 100000000; + +double bitcoinCashAmountToDouble({int amount}) => + cryptoAmountToDouble(amount: amount, divider: bitcoinCashAmountDivider); \ No newline at end of file diff --git a/lib/src/domain/common/crypto_amount_format.dart b/lib/src/domain/common/crypto_amount_format.dart new file mode 100644 index 000000000..649ac45f5 --- /dev/null +++ b/lib/src/domain/common/crypto_amount_format.dart @@ -0,0 +1 @@ +double cryptoAmountToDouble({num amount, num divider}) => amount / divider; \ No newline at end of file diff --git a/lib/src/domain/common/setup_locator.dart b/lib/src/domain/common/setup_locator.dart new file mode 100644 index 000000000..f9c991596 --- /dev/null +++ b/lib/src/domain/common/setup_locator.dart @@ -0,0 +1,7 @@ +import 'package:get_it/get_it.dart'; + +GetIt locator = GetIt.instance; + +void setupLocator(T instance) { + locator.registerSingleton(instance); +} \ No newline at end of file diff --git a/lib/src/domain/dash/dash_amount_format.dart b/lib/src/domain/dash/dash_amount_format.dart new file mode 100644 index 000000000..3f1632cd6 --- /dev/null +++ b/lib/src/domain/dash/dash_amount_format.dart @@ -0,0 +1,6 @@ +import 'package:cake_wallet/src/domain/common/crypto_amount_format.dart'; + +const dashAmountDivider = 100000000; + +double dashAmountToDouble({int amount}) => + cryptoAmountToDouble(amount: amount, divider: dashAmountDivider); \ No newline at end of file diff --git a/lib/src/domain/ethereum/ethereum_amount_format.dart b/lib/src/domain/ethereum/ethereum_amount_format.dart new file mode 100644 index 000000000..644153a22 --- /dev/null +++ b/lib/src/domain/ethereum/ethereum_amount_format.dart @@ -0,0 +1,6 @@ +import 'package:cake_wallet/src/domain/common/crypto_amount_format.dart'; + +const ethereumAmountDivider = 1000000000000000000; + +double ethereumAmountToDouble({num amount}) => + cryptoAmountToDouble(amount: amount, divider: ethereumAmountDivider); \ No newline at end of file diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index 55df4d26e..e90b924d7 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -14,6 +14,12 @@ import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_request.da import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart'; import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart'; +import 'package:cake_wallet/src/domain/bitcoin/bitcoin_amount_format.dart'; +import 'package:cake_wallet/src/domain/bitcoin_cash/bitcoin_cash_amount_format.dart'; +import 'package:cake_wallet/src/domain/dash/dash_amount_format.dart'; +import 'package:cake_wallet/src/domain/ethereum/ethereum_amount_format.dart'; +import 'package:cake_wallet/src/domain/litecoin/litecoin_amount_format.dart'; +import 'package:cake_wallet/src/domain/common/setup_locator.dart'; class MorphTokenExchangeProvider extends ExchangeProvider { MorphTokenExchangeProvider() @@ -55,7 +61,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider { ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.xmr) ]); - final trades = Hive.box(Trade.boxName); + final trades = locator.get>(); static const apiUri = 'https://api.morphtoken.com'; static const _morphURISuffix = '/morph'; @@ -72,8 +78,6 @@ class MorphTokenExchangeProvider extends ExchangeProvider { @override Future fetchLimits({CryptoCurrency from, CryptoCurrency to}) async { - const ethereumAmountDivider = 1000000000000000000; - const defaultAmountDivider = 100000000; final url = apiUri + _limitsURISuffix; final headers = {'Content-type': 'application/json'}; final body = @@ -107,13 +111,25 @@ class MorphTokenExchangeProvider extends ExchangeProvider { minFormatted = moneroAmountToDouble(amount: min); maxFormatted = moneroAmountToDouble(amount: max); break; - case CryptoCurrency.eth: - minFormatted = min/ethereumAmountDivider; - maxFormatted = ethMax/ethereumAmountDivider; + case CryptoCurrency.btc: + minFormatted = bitcoinAmountToDouble(amount: min); + maxFormatted = bitcoinAmountToDouble(amount: max); break; - default: - minFormatted = min/defaultAmountDivider; - maxFormatted = max/defaultAmountDivider; + case CryptoCurrency.bch: + minFormatted = bitcoinCashAmountToDouble(amount: min); + maxFormatted = bitcoinCashAmountToDouble(amount: max); + break; + case CryptoCurrency.dash: + minFormatted = dashAmountToDouble(amount: min); + maxFormatted = dashAmountToDouble(amount: max); + break; + case CryptoCurrency.eth: + minFormatted = ethereumAmountToDouble(amount: min); + maxFormatted = ethereumAmountToDouble(amount: ethMax); + break; + case CryptoCurrency.ltc: + minFormatted = litecoinAmountToDouble(amount: min); + maxFormatted = litecoinAmountToDouble(amount: max); break; } @@ -133,7 +149,8 @@ class MorphTokenExchangeProvider extends ExchangeProvider { "asset": _request.to.toString(), "weight": weight, "address": _request.address - }] + }], + "tag": "cakewallet" }; final response = await post(url, @@ -190,7 +207,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final state = TradeState.deserialize(raw: status.toLowerCase()); String amount = ""; - for (final trade in trades.values) { + for (final trade in trades.values.toList()) { if (trade.id == id) { amount = trade.amount; break; diff --git a/lib/src/domain/litecoin/litecoin_amount_format.dart b/lib/src/domain/litecoin/litecoin_amount_format.dart new file mode 100644 index 000000000..f030f5e34 --- /dev/null +++ b/lib/src/domain/litecoin/litecoin_amount_format.dart @@ -0,0 +1,6 @@ +import 'package:cake_wallet/src/domain/common/crypto_amount_format.dart'; + +const litecoinAmountDivider = 100000000; + +double litecoinAmountToDouble({int amount}) => + cryptoAmountToDouble(amount: amount, divider: litecoinAmountDivider); \ No newline at end of file diff --git a/lib/src/domain/monero/monero_amount_format.dart b/lib/src/domain/monero/monero_amount_format.dart index 3eb54d880..7dfb7142b 100644 --- a/lib/src/domain/monero/monero_amount_format.dart +++ b/lib/src/domain/monero/monero_amount_format.dart @@ -1,4 +1,5 @@ import 'package:intl/intl.dart'; +import 'package:cake_wallet/src/domain/common/crypto_amount_format.dart'; const moneroAmountLength = 12; const moneroAmountDivider = 1000000000000; @@ -7,6 +8,6 @@ final moneroAmountFormat = NumberFormat() ..minimumFractionDigits = 1; String moneroAmountToString({int amount}) => - moneroAmountFormat.format(amount / moneroAmountDivider); + moneroAmountFormat.format(cryptoAmountToDouble(amount: amount, divider: moneroAmountDivider)); -double moneroAmountToDouble({int amount}) => amount / moneroAmountDivider; +double moneroAmountToDouble({int amount}) => cryptoAmountToDouble(amount: amount, divider: moneroAmountDivider); diff --git a/pubspec.lock b/pubspec.lock index d4adb3dbb..2c3b118d1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -301,6 +301,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.19" + get_it: + dependency: "direct main" + description: + name: get_it + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" glob: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e20521171..002f95960 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,6 +46,7 @@ dependencies: hive: ^1.2.0 hive_flutter: ^0.2.1 package_info: ^0.4.0+13 + get_it: ^3.1.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. From fdeb66e6433ab772d8bd07f1c7ff3fa7dc0736ff Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Mon, 10 Feb 2020 21:35:44 +0200 Subject: [PATCH 18/22] CWA-169 | removed setup_locator and got the box as parameter in MorphTokenExchangeProvider --- lib/main.dart | 3 --- lib/router.dart | 5 +++-- lib/src/domain/common/setup_locator.dart | 7 ------- .../exchange/morphtoken/morphtoken_exchange_provider.dart | 5 ++--- lib/src/stores/exchange_trade/exchange_trade_store.dart | 7 +++++-- pubspec.lock | 7 ------- pubspec.yaml | 1 - 7 files changed, 10 insertions(+), 25 deletions(-) delete mode 100644 lib/src/domain/common/setup_locator.dart diff --git a/lib/main.dart b/lib/main.dart index 18da983f6..2cf7e5911 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -35,7 +35,6 @@ import 'package:cake_wallet/src/domain/common/wallet_type.dart'; import 'package:cake_wallet/src/domain/services/wallet_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/domain/common/language.dart'; -import 'package:cake_wallet/src/domain/common/setup_locator.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -66,8 +65,6 @@ void main() async { await Hive.openBox(Trade.boxName, encryptionKey: tradesBoxKey); final walletInfoSource = await Hive.openBox(WalletInfo.boxName); - setupLocator(trades); - final sharedPreferences = await SharedPreferences.getInstance(); final walletService = WalletService(); final walletListService = WalletListService( diff --git a/lib/router.dart b/lib/router.dart index 1698737c6..03c7e477a 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -395,7 +395,8 @@ class Router { ProxyProvider( update: (_, settingsStore, __) => ExchangeTradeStore( trade: settings.arguments as Trade, - walletStore: walletStore), + walletStore: walletStore, + trades: trades), ), ProxyProvider( update: (_, settingsStore, __) => SendStore( @@ -455,7 +456,7 @@ class Router { providerList: [ xmrtoprovider, ChangeNowExchangeProvider(), - MorphTokenExchangeProvider() + MorphTokenExchangeProvider(trades: trades) ], walletStore: walletStore); }), diff --git a/lib/src/domain/common/setup_locator.dart b/lib/src/domain/common/setup_locator.dart deleted file mode 100644 index f9c991596..000000000 --- a/lib/src/domain/common/setup_locator.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:get_it/get_it.dart'; - -GetIt locator = GetIt.instance; - -void setupLocator(T instance) { - locator.registerSingleton(instance); -} \ No newline at end of file diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index e90b924d7..af26e7203 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -19,10 +19,9 @@ import 'package:cake_wallet/src/domain/bitcoin_cash/bitcoin_cash_amount_format.d import 'package:cake_wallet/src/domain/dash/dash_amount_format.dart'; import 'package:cake_wallet/src/domain/ethereum/ethereum_amount_format.dart'; import 'package:cake_wallet/src/domain/litecoin/litecoin_amount_format.dart'; -import 'package:cake_wallet/src/domain/common/setup_locator.dart'; class MorphTokenExchangeProvider extends ExchangeProvider { - MorphTokenExchangeProvider() + MorphTokenExchangeProvider({@required this.trades}) : super( pairList: [ ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.eth), @@ -61,7 +60,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider { ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.xmr) ]); - final trades = locator.get>(); + Box trades; static const apiUri = 'https://api.morphtoken.com'; static const _morphURISuffix = '/morph'; diff --git a/lib/src/stores/exchange_trade/exchange_trade_store.dart b/lib/src/stores/exchange_trade/exchange_trade_store.dart index 008d763f5..f65357faa 100644 --- a/lib/src/stores/exchange_trade/exchange_trade_store.dart +++ b/lib/src/stores/exchange_trade/exchange_trade_store.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart'; import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; +import 'package:hive/hive.dart'; part 'exchange_trade_store.g.dart'; @@ -15,7 +16,7 @@ class ExchangeTradeStore = ExchangeTradeStoreBase with _$ExchangeTradeStore; abstract class ExchangeTradeStoreBase with Store { ExchangeTradeStoreBase( - {@required this.trade, @required WalletStore walletStore}) { + {@required this.trade, @required WalletStore walletStore, @required this.trades}) { isSendable = trade.from == walletStore.type || trade.provider == ExchangeProviderDescription.xmrto; @@ -27,7 +28,7 @@ abstract class ExchangeTradeStoreBase with Store { _provider = ChangeNowExchangeProvider(); break; case ExchangeProviderDescription.morphToken: - _provider = MorphTokenExchangeProvider(); + _provider = MorphTokenExchangeProvider(trades: trades); break; } @@ -45,6 +46,8 @@ abstract class ExchangeTradeStoreBase with Store { Timer _timer; + Box trades; + @override void dispose() { super.dispose(); diff --git a/pubspec.lock b/pubspec.lock index 2c3b118d1..d4adb3dbb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -301,13 +301,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.19" - get_it: - dependency: "direct main" - description: - name: get_it - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" glob: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 002f95960..e20521171 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,7 +46,6 @@ dependencies: hive: ^1.2.0 hive_flutter: ^0.2.1 package_info: ^0.4.0+13 - get_it: ^3.1.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. From 30a7e5c4c8b01f4c69816d678bc311f9e7825e6e Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Tue, 11 Feb 2020 21:30:46 +0200 Subject: [PATCH 19/22] CWA-169 | changed order of definition of properties in ExchangeTradeStore --- lib/src/stores/exchange_trade/exchange_trade_store.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/stores/exchange_trade/exchange_trade_store.dart b/lib/src/stores/exchange_trade/exchange_trade_store.dart index f65357faa..26e75977a 100644 --- a/lib/src/stores/exchange_trade/exchange_trade_store.dart +++ b/lib/src/stores/exchange_trade/exchange_trade_store.dart @@ -42,12 +42,12 @@ abstract class ExchangeTradeStoreBase with Store { @observable bool isSendable; + Box trades; + ExchangeProvider _provider; Timer _timer; - Box trades; - @override void dispose() { super.dispose(); From d88945411f8a46ea9a70fc1437515f9a452fb769 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Tue, 11 Feb 2020 22:50:10 +0200 Subject: [PATCH 20/22] CWA-169 | renamed checkAmount() to formatAmount() --- .../domain/common/{check_amount.dart => format_amount.dart} | 2 +- lib/src/domain/common/transaction_info.dart | 6 +++--- lib/src/domain/exchange/trade.dart | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename lib/src/domain/common/{check_amount.dart => format_amount.dart} (79%) diff --git a/lib/src/domain/common/check_amount.dart b/lib/src/domain/common/format_amount.dart similarity index 79% rename from lib/src/domain/common/check_amount.dart rename to lib/src/domain/common/format_amount.dart index 77e0e5a62..88e8c1651 100644 --- a/lib/src/domain/common/check_amount.dart +++ b/lib/src/domain/common/format_amount.dart @@ -1,4 +1,4 @@ -String checkAmount(String amount) { +String formatAmount(String amount) { if (!amount.contains('.')) { return amount + '.00'; } else if (amount.endsWith('.')) { diff --git a/lib/src/domain/common/transaction_info.dart b/lib/src/domain/common/transaction_info.dart index e72f022d0..e2daaec7a 100644 --- a/lib/src/domain/common/transaction_info.dart +++ b/lib/src/domain/common/transaction_info.dart @@ -2,7 +2,7 @@ import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart'; import 'package:cw_monero/structs/transaction_info_row.dart'; import 'package:cake_wallet/src/domain/common/parseBoolFromString.dart'; import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; -import 'package:cake_wallet/src/domain/common/check_amount.dart'; +import 'package:cake_wallet/src/domain/common/format_amount.dart'; class TransactionInfo { TransactionInfo(this.id, this.height, this.direction, this.date, @@ -41,9 +41,9 @@ class TransactionInfo { String _fiatAmount; - String amountFormatted() => '${checkAmount(moneroAmountToString(amount: amount))} XMR'; + String amountFormatted() => '${formatAmount(moneroAmountToString(amount: amount))} XMR'; String fiatAmount() => _fiatAmount ?? ''; - void changeFiatAmount(String amount) => _fiatAmount = checkAmount(amount); + void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); } diff --git a/lib/src/domain/exchange/trade.dart b/lib/src/domain/exchange/trade.dart index 9f3f1cb77..8aa9f0472 100644 --- a/lib/src/domain/exchange/trade.dart +++ b/lib/src/domain/exchange/trade.dart @@ -2,7 +2,7 @@ import 'package:hive/hive.dart'; import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/domain/exchange/trade_state.dart'; -import 'package:cake_wallet/src/domain/common/check_amount.dart'; +import 'package:cake_wallet/src/domain/common/format_amount.dart'; part 'trade.g.dart'; @@ -103,5 +103,5 @@ class Trade extends HiveObject { }; } - String amountFormatted() => checkAmount(amount); + String amountFormatted() => formatAmount(amount); } From a6fae629176ea2763754d10c5ad34041eb53d018 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Wed, 12 Feb 2020 14:31:26 +0200 Subject: [PATCH 21/22] CWA-169 | added DateFormat to trade.createdAt in Trade Details page --- lib/src/screens/trade_details/trade_details_page.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index f60aae071..8aaf1ced4 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/src/stores/exchange_trade/exchange_trade_store.dart' import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_row.dart'; +import 'package:intl/intl.dart'; class TradeDetailsPage extends BasePage { @override @@ -16,6 +17,8 @@ class TradeDetailsPage extends BasePage { @override bool get isModalBackButton => true; + final createdAtFormat = DateFormat('yyyy-MM-dd HH:mm:ss'); + @override Widget body(BuildContext context) { final exchangeStore = Provider.of(context); @@ -43,7 +46,7 @@ class TradeDetailsPage extends BasePage { if (trade.createdAt != null) { items.add(StandartListItem( title: S.of(context).trade_details_created_at, - value: trade.createdAt.toString())); + value: createdAtFormat.format(trade.createdAt).toString())); } if (trade.from != null && trade.to != null) { From d7d03b4d2f73eb5c971bae570cc376a5602fc8c7 Mon Sep 17 00:00:00 2001 From: Oleksandr Sobol Date: Wed, 12 Feb 2020 15:28:30 +0200 Subject: [PATCH 22/22] CWA-169 | added trades to exchange trade store in router --- lib/router.dart | 4 +++- .../exchange/morphtoken/morphtoken_exchange_provider.dart | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/router.dart b/lib/router.dart index 03c7e477a..bca3bebce 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -418,7 +418,9 @@ class Router { return MultiProvider(providers: [ ProxyProvider( update: (_, settingsStore, __) => ExchangeTradeStore( - trade: settings.arguments as Trade, walletStore: walletStore), + trade: settings.arguments as Trade, + walletStore: walletStore, + trades: trades), ) ], child: TradeDetailsPage()); }); diff --git a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart index af26e7203..b150ebce1 100644 --- a/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart +++ b/lib/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart @@ -206,7 +206,7 @@ class MorphTokenExchangeProvider extends ExchangeProvider { final state = TradeState.deserialize(raw: status.toLowerCase()); String amount = ""; - for (final trade in trades.values.toList()) { + for (final trade in trades.values) { if (trade.id == id) { amount = trade.amount; break;