coinmarketcap for exchange rates (#304)

merge-requests/3/head
m2049r 6 years ago committed by GitHub
parent 843566b820
commit 37244cb9e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -43,9 +43,7 @@ import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
import com.m2049r.xmrwallet.service.exchange.kraken.ExchangeApiImpl;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.OkHttpClientSingleton;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.text.NumberFormat;
@ -152,7 +150,7 @@ public class WalletFragment extends Fragment
// at this point selection is XMR in case of error
String displayB;
double amountA = Double.parseDouble(Wallet.getDisplayAmount(unlockedBalance)); // crash if this fails!
if (!"XMR".equals(balanceCurrency)) { // not XMR
if (!Helper.CRYPTO.equals(balanceCurrency)) { // not XMR
double amountB = amountA * balanceRate;
displayB = Helper.getFormattedAmount(amountB, false);
} else { // XMR
@ -161,10 +159,10 @@ public class WalletFragment extends Fragment
tvBalance.setText(displayB);
}
String balanceCurrency = "XMR";
String balanceCurrency = Helper.CRYPTO;
double balanceRate = 1.0;
private final ExchangeApi exchangeApi = new ExchangeApiImpl(OkHttpClientSingleton.getOkHttpClient());
private final ExchangeApi exchangeApi = Helper.getExchangeApi();
void refreshBalance() {
if (sCurrency.getSelectedItemPosition() == 0) { // XMR
@ -172,9 +170,10 @@ public class WalletFragment extends Fragment
tvBalance.setText(Helper.getFormattedAmount(amountXmr, true));
} else { // not XMR
String currency = (String) sCurrency.getSelectedItem();
Timber.d(currency);
if (!currency.equals(balanceCurrency) || (balanceRate <= 0)) {
showExchanging();
exchangeApi.queryExchangeRate("XMR", currency,
exchangeApi.queryExchangeRate(Helper.CRYPTO, currency,
new ExchangeCallback() {
@Override
public void onSuccess(final ExchangeRate exchangeRate) {
@ -230,10 +229,10 @@ public class WalletFragment extends Fragment
public void exchange(final ExchangeRate exchangeRate) {
hideExchanging();
if (!"XMR".equals(exchangeRate.getBaseCurrency())) {
if (!Helper.CRYPTO.equals(exchangeRate.getBaseCurrency())) {
Timber.e("Not XMR");
sCurrency.setSelection(0, true);
balanceCurrency = "XMR";
balanceCurrency = Helper.CRYPTO;
balanceRate = 1.0;
} else {
int spinnerPosition = ((ArrayAdapter) sCurrency.getAdapter()).getPosition(exchangeRate.getQuoteCurrency());

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 m2049r et al.
* Copyright (c) 2017-2018 m2049r et al.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.m2049r.xmrwallet.service.exchange.kraken;
package com.m2049r.xmrwallet.service.exchange.coinmarketcap;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
@ -23,6 +23,7 @@ import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeException;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
import com.m2049r.xmrwallet.util.Helper;
import org.json.JSONArray;
import org.json.JSONException;
@ -37,6 +38,7 @@ import okhttp3.Request;
import okhttp3.Response;
public class ExchangeApiImpl implements ExchangeApi {
static final String CRYPTO_ID = "328";
@NonNull
private final OkHttpClient okHttpClient;
@ -52,7 +54,7 @@ public class ExchangeApiImpl implements ExchangeApi {
}
public ExchangeApiImpl(@NonNull final OkHttpClient okHttpClient) {
this(okHttpClient, HttpUrl.parse("https://api.kraken.com/0/public/Ticker"));
this(okHttpClient, HttpUrl.parse("https://api.coinmarketcap.com/v2/ticker/"));
}
@Override
@ -67,12 +69,12 @@ public class ExchangeApiImpl implements ExchangeApi {
boolean inverse = false;
String fiat = null;
if (baseCurrency.equals("XMR")) {
if (baseCurrency.equals(Helper.CRYPTO)) {
fiat = quoteCurrency;
inverse = false;
}
if (quoteCurrency.equals("XMR")) {
if (quoteCurrency.equals(Helper.CRYPTO)) {
fiat = baseCurrency;
inverse = true;
}
@ -85,7 +87,8 @@ public class ExchangeApiImpl implements ExchangeApi {
final boolean swapAssets = inverse;
final HttpUrl url = baseUrl.newBuilder()
.addQueryParameter("pair", "XMR" + fiat)
.addEncodedPathSegments(CRYPTO_ID + "/")
.addQueryParameter("convert", fiat)
.build();
final Request httpRequest = createHttpRequest(url);
@ -101,12 +104,12 @@ public class ExchangeApiImpl implements ExchangeApi {
if (response.isSuccessful()) {
try {
final JSONObject json = new JSONObject(response.body().string());
final JSONArray jsonError = json.getJSONArray("error");
if (jsonError.length() > 0) {
final String errorMsg = jsonError.getString(0);
callback.onError(new ExchangeException(response.code(), errorMsg));
final JSONObject metadata = json.getJSONObject("metadata");
if (!metadata.isNull("error")) {
final String errorMsg = metadata.getString("error");
callback.onError(new ExchangeException(response.code(), (String) errorMsg));
} else {
final JSONObject jsonResult = json.getJSONObject("result");
final JSONObject jsonResult = json.getJSONObject("data");
reportSuccess(jsonResult, swapAssets, callback);
}
} catch (JSONException ex) {
@ -130,7 +133,6 @@ public class ExchangeApiImpl implements ExchangeApi {
}
}
private Request createHttpRequest(final HttpUrl url) {
return new Request.Builder()
.url(url)

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 m2049r et al.
* Copyright (c) 2017-2018 m2049r et al.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.m2049r.xmrwallet.service.exchange.kraken;
package com.m2049r.xmrwallet.service.exchange.coinmarketcap;
import android.support.annotation.NonNull;
@ -25,6 +25,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -37,7 +38,7 @@ class ExchangeRateImpl implements ExchangeRate {
@Override
public String getServiceName() {
return "kraken.com";
return "coinmarketcap.com";
}
@Override
@ -64,29 +65,21 @@ class ExchangeRateImpl implements ExchangeRate {
ExchangeRateImpl(final JSONObject jsonObject, final boolean swapAssets) throws JSONException, ExchangeException {
try {
final String key = jsonObject.keys().next(); // we expect only one
Pattern pattern = Pattern.compile("^X(.*?)Z(.*?)$");
Matcher matcher = pattern.matcher(key);
if (matcher.find()) {
this.baseCurrency = swapAssets ? matcher.group(2) : matcher.group(1);
this.quoteCurrency = swapAssets ? matcher.group(1) : matcher.group(2);
} else {
throw new ExchangeException("no pair returned!");
}
JSONObject pair = jsonObject.getJSONObject(key);
JSONArray close = pair.getJSONArray("c");
String closePrice = close.getString(0);
if (closePrice != null) {
try {
double rate = Double.parseDouble(closePrice);
this.rate = swapAssets ? (1 / rate) : rate;
} catch (NumberFormatException ex) {
throw new ExchangeException(ex.getLocalizedMessage());
}
} else {
throw new ExchangeException("no close price returned!");
final String baseC = jsonObject.getString("symbol");
final JSONObject quotes = jsonObject.getJSONObject("quotes");
final Iterator<String> keys = quotes.keys();
String key = null;
// get key which is not USD unless it is the only one
while (keys.hasNext()) {
key = keys.next();
if (!key.equals("USD")) break;
}
final String quoteC = key;
baseCurrency = swapAssets ? quoteC : baseC;
quoteCurrency = swapAssets ? baseC : quoteC;
JSONObject quote = quotes.getJSONObject(key);
double price = quote.getDouble("price");
this.rate = swapAssets ? (1d / price) : price;
} catch (NoSuchElementException ex) {
throw new ExchangeException(ex.getLocalizedMessage());
}

@ -56,6 +56,7 @@ import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi;
import java.io.File;
import java.io.IOException;
@ -72,6 +73,8 @@ import okhttp3.HttpUrl;
import timber.log.Timber;
public class Helper {
static public final String CRYPTO = "XMR";
static private final String WALLET_DIR = "monerujo" + (BuildConfig.DEBUG ? "-debug" : "");
static private final String HOME_DIR = "monero" + (BuildConfig.DEBUG ? "-debug" : "");
@ -523,4 +526,9 @@ public class Helper {
return false;
}
}
static public ExchangeApi getExchangeApi() {
return new com.m2049r.xmrwallet.service.exchange.coinmarketcap.ExchangeApiImpl(OkHttpClientSingleton.getOkHttpClient());
}
}

@ -36,9 +36,7 @@ import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
import com.m2049r.xmrwallet.service.exchange.kraken.ExchangeApiImpl;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.OkHttpClientSingleton;
import java.util.Locale;
@ -250,7 +248,7 @@ public class ExchangeTextView extends LinearLayout
}
}
private final ExchangeApi exchangeApi = new ExchangeApiImpl(OkHttpClientSingleton.getOkHttpClient());
private final ExchangeApi exchangeApi = Helper.getExchangeApi();
void startExchange() {
showProgress();
@ -458,4 +456,4 @@ public class ExchangeTextView extends LinearLayout
tvAmountA.setText(null);
doExchange();
}
}
}

@ -42,9 +42,7 @@ import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeRate;
import com.m2049r.xmrwallet.service.exchange.kraken.ExchangeApiImpl;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.OkHttpClientSingleton;
import java.util.Locale;
@ -315,12 +313,13 @@ public class ExchangeView extends LinearLayout
}
}
private final ExchangeApi exchangeApi = new ExchangeApiImpl(OkHttpClientSingleton.getOkHttpClient());
private final ExchangeApi exchangeApi = Helper.getExchangeApi();
void startExchange() {
showProgress();
String currencyA = (String) sCurrencyA.getSelectedItem();
String currencyB = (String) sCurrencyB.getSelectedItem();
exchangeApi.queryExchangeRate(currencyA, currencyB,
new ExchangeCallback() {
@Override

@ -29,11 +29,10 @@
von Transaktionen lokal gesammelt und verarbeitet und verschlüsselt in das Monero-Netzwerk übertragen.
</p>
<p>Andere persönliche Daten werden von der App nicht gesammelt.</p>
<p>Wenn du den USD/EUR Umrechner (optional) nutzt fragt Monerujo
den aktuellen Kurs über die öffentliche Schnittstelle von kraken.com ab.
Siehe dir ihre Datenschutzerklärung unter https://www.kraken.com/legal/privacy für
Details darüber an, wie Daten in deinen Anfragen gesammelt werden (insbesondere der
Abschnitt "Information We Collect Automatically").</p>
<p>Wenn du den Umrechner (optional) nutzt fragt Monerujo
den aktuellen Kurs über die öffentliche Schnittstelle von coinmarketcap.com ab.
Siehe dir ihre Datenschutzerklärung unter https://coinmarketcap.com/privacy für
Details darüber an, wie Daten in deinen Anfragen gesammelt werden.</p>
<p>Wenn du die App zum Bezahlen an BTC-Adressen verwendest, verwendest du den Dienst XMR.TO.
Weitere Informationen findest du in den Datenschutzerklärung unter https://xmr.to/.
Monerujo schickt dem Anbieter die BTC Zieladresse und den Betrag.

@ -29,11 +29,10 @@
Monero de forma cifrada.
</p>
<p>Otros datos personales no son recopilados por la app.</p>
<p>Si utiliza la funcionalidad de cambio USD/EUR (opcional), monerujo obtiene la tasa
de cambio a través de la API pública de kraken.com.
Vea su política de privadad en https://www.kraken.com/legal/privacy para conocer más
detalles acerca de como se recopilan los datos de sus peticiones (especialmente la sección
"Innformation We Collect Automatically").</p>
<p>Si utiliza la funcionalidad de cambio (opcional), monerujo obtiene la tasa
de cambio a través de la API pública de coinmarketcap.com.
Vea su política de privadad en https://coinmarketcap.com/privacy para conocer más
detalles acerca de como se recopilan los datos de sus peticiones.</p>
<h2>Permisos de la App</h2>
<ul>
<li>INTERNET : Conectar a la red de Monero a través de un Daemon Nodo de Monero</li>

@ -31,11 +31,10 @@
réseau Monero sous une forme chiffrée.
</p>
<p>Aucune autre donnée personnelle nest collectée par lapplication.</p>
<p>Si vous utilisez la fonction (optionnelle) de change USD/EUR, monerujo récupère le
taux de change via lAPI publique de kraken.com.
Consultez leur politique de confidentialité sur https://www.kraken.com/legal/privacy
pour des détails sur la façon dont les données de vos requêtes sont collectées
(particulièrement la rubrique "Information We Collect Automatically").</p>
<p>Si vous utilisez la fonction (optionnelle) de change, monerujo récupère le
taux de change via lAPI publique de coinmarketcap.com.
Consultez leur politique de confidentialité sur https://coinmarketcap.com/privacy
pour des détails sur la façon dont les données de vos requêtes sont collectées.</p>
<p>Si vous utilisez lapplication pour payer à une adresse BTC, vous utiliserez
le service XMR.TO. Consultez leur politique de confidentialité sur https://xmr.to/
pour plus de détails. Monerujo leur transmet ladresse de destination BTC et le
@ -64,4 +63,4 @@
</p>
]]></string>
</resources>
</resources>

@ -15,35 +15,35 @@
<string name="privacy_policy"><![CDATA[
<h1>Politica per la Privacy</h1>
<p>Questa pagina ti informa sulla nostra politica riguardante la raccolta, l'utilizzo e la rivelazione di informazioni personali che riceviamo dagli utenti della nostra app (monerujo: Portafoglio Monero).
<p>Questa pagina ti informa sulla nostra politica riguardante la raccolta, l\'utilizzo e la rivelazione di informazioni personali che riceviamo dagli utenti della nostra app (monerujo: Portafoglio Monero).
</p>
<p>Usando questa app, acconsenti alla raccolta e all'utilizzo delle informazioni in accordo con questa politica.
<p>Usando questa app, acconsenti alla raccolta e all\'utilizzo delle informazioni in accordo con questa politica.
</p>
<h2>Dati raccolti</h2>
<p>Per "dato personale" si intende ogni tipo di dato grazie al quale è possibile identificare un individuo.
</p>
<p>Le chiavi e gli indirizzi pubblici di Monero vengono raccolti e processati dall'app localmente con lo scopo di processare le transazioni e vengono trasmessi all'interno della rete Monero in modo cifrato.
<p>Le chiavi e gli indirizzi pubblici di Monero vengono raccolti e processati dall\'app localmente con lo scopo di processare le transazioni e vengono trasmessi all\'interno della rete Monero in modo cifrato.
</p>
<p>Altri dati personali non sono raccolti dall'app.</p>
<p>Se usi la funzionalità (opzionale) del cambio USD/EUR, monerujo recupera il tasso di cambio attraverso le API pubbliche di kraken.com.
Controlla la loro politica per la privacy (in lingua inglese) su https://www.kraken.com/legal/privacy per conoscere i dettagli su come vengono raccolti i dati nelle tue richieste (specialmente la sezione "Information We Collect Automatically" - "Informazioni che raccogliamo in modo automatico).</p>
<p>Altri dati personali non sono raccolti dall\'app.</p>
<p>Se usi la funzionalità (opzionale) del cambio, monerujo recupera il tasso di cambio attraverso le API pubbliche di coinmarketcap.com.
Controlla la loro politica per la privacy (in lingua inglese) su https://coinmarketcap.com/privacy per conoscere i dettagli su come vengono raccolti i dati nelle tue richieste.</p>
<p>Se utilizzi l'app per effettuare pagamenti ad indirizzi BTC, stai usando il servizio XMR.TO.
Controlla la loro politica per la privacy (in lingua inglese) su https://xmr.to/ per conoscere i dettagli. Monerujo invia a loro l'indirizzo di destinazione BTC e l'ammontare della transazione. Anche il tuo IP potrebbe essere raccolto.</p>
<h2>Permessi app</h2>
<ul>
<li>INTERNET : Connessione alla rete Monero attraverso un nodo </li>
<li>READ_EXTERNAL_STORAGE : Legge i file di portafoglio salvati all'interno del dispositivo</li>
<li>WRITE_EXTERNAL_STORAGE : Scrive i file di portafoglio salvati all'interno del dispositivo</li>
<li>READ_EXTERNAL_STORAGE : Legge i file di portafoglio salvati all\'interno del dispositivo</li>
<li>WRITE_EXTERNAL_STORAGE : Scrive i file di portafoglio salvati all\'interno del dispositivo</li>
<li>WAKE_LOCK : Tiene il dispositivo sveglio durante la sincronizzazione</li>
<li>CAMERA : Scansione codici QR di indirizzi Monero</li>
</ul>
<h2>Modifica a questa Politica per la Privacy</h2>
<p>Potremmo aggiorare questa politica per la privacy di volta in volta. Ti invieremo una notifica su ciò che è cambiato pubblicando la nuova politica per la privacy all'interno dell'app e sul sito (www.monerujo.io)
<p>Potremmo aggiorare questa politica per la privacy di volta in volta. Ti invieremo una notifica su ciò che è cambiato pubblicando la nuova politica per la privacy all\'interno dell\'app e sul sito (www.monerujo.io)
Sei invitato a rivedere periodicamente questa politica per la privacy per controllarne i cambiamenti.
<p>Questa politica per la privacy è stata aggiornata il 10 novembre 2017.
</p>
<h2>Contattaci</h2>
<p>Se hai dubbi o domande sulla nostra politica per la privacy, oppure su come i tuoi dati vengono raccolti e processati, contattaci all'indirizzo email privacy@monerujo.io.
<p>Se hai dubbi o domande sulla nostra politica per la privacy, oppure su come i tuoi dati vengono raccolti e processati, contattaci all\'indirizzo email privacy@monerujo.io.
</p>
]]></string>
</resources>

@ -30,11 +30,10 @@
in encrypted form.
</p>
<p>Other personal data is not collected by the app.</p>
<p>If you use the USD/EUR exchange (optional) functionality, monerujo fetches the exchange
rate through the public API of kraken.com.
See their privacy policy at https://www.kraken.com/legal/privacy for
details on how data in your requests is collected (especially the
section "Information We Collect Automatically").</p>
<p>If you use the exchange (optional) functionality, monerujo fetches the exchange
rate through the public API of coinmarketcap.com.
See their privacy policy at https://coinmarketcap.com/privacy for
details on how data in your requests is collected.</p>
<p>If you use the app to pay to BTC addresses, you will be using the XMR.TO service.
See their privacy policy at https://xmr.to/ for details. Monerujo send them the BTC
destination address and amount. Your IP will also be collectable.</p>
@ -59,4 +58,4 @@
please e-mail privacy@monerujo.io.
</p>
]]></string>
</resources>
</resources>

@ -22,9 +22,9 @@
<p>Monerujo 只会在本地端使用您的 Monero 私钥以及公开地址执行必要的处理,并在加密后发送至
Monero 网络进行交易。</p>
<p>其他个人信息都不会被 monerujo 收集。</p>
<p>如果你使用 USD/EUR 外汇的功能(可选用)monerujo 將通过 kraken.com 的公开
API 抓取当前汇率。如果你想了解自己被收集的信息如何被使用,请访问 https://www.kraken.com/legal/privacy
查看他们的隐私政策特別是「Information We Collect Automatically」章节</p>
<p>如果你使用外汇的功能(可选用)monerujo 將通过 coinmarketcap.com 的公开
API 抓取当前汇率。如果你想了解自己被收集的信息如何被使用,请访问 https://coinmarketcap.com/privacy
查看他们的隐私政策。</p>
<p>如果你想使用本 App 支付款项至比特币地址,您将使用 XMR.TO 所提供的服务。Monerujo
将发送比特币的目标地址以及金额至 XMR.TO您的 IP 在此时也可能会被收集。详情请至 https://xmr.to/
查看他们的隐私政策。</p>

@ -22,9 +22,9 @@
<p>Monerujo 只會在本地端使用您的 Monero 金鑰以及公開地址執行必要的處理,並在加密後發送至
Monero 網路進行交易。</p>
<p>其餘的個人資料都不會被 monerujo 收集。</p>
<p>倘若您有使用 USD/EUR 匯兌的功能(可選用)monerujo 將透過 kraken.com 的公開
API 抓取目前的匯率。若欲了解您要求的資料會如何被收集及使用,請至 https://www.kraken.com/legal/privacy
觀看他們的隱私權政策特別是「Information We Collect Automatically」章節</p>
<p>倘若您有使用匯兌的功能(可選用)monerujo 將透過 coinmarketcap.com 的公開
API 抓取目前的匯率。若欲了解您要求的資料會如何被收集及使用,請至 https://coinmarketcap.com/privacy
觀看他們的隱私權政策。</p>
<p>若您想使用本 App 支付款項至 BTC 位址,您將使用 XMR.TO 所提供的服務。Monerujo
將發送 BTC 目標位址以及金額至 XMR.TO您的 IP 在此時也可能會被收集。詳情請至 https://xmr.to/
觀看他們的隱私權政策。</p>

@ -30,11 +30,10 @@
in encrypted form.
</p>
<p>Other personal data is not collected by the app.</p>
<p>If you use the USD/EUR exchange (optional) functionality, monerujo fetches the exchange
rate through the public API of kraken.com.
See their privacy policy at https://www.kraken.com/legal/privacy for
details on how data in your requests is collected (especially the
section "Information We Collect Automatically").</p>
<p>If you use the exchange (optional) functionality, monerujo fetches the exchange
rate through the public API of coinmarketcap.com.
See their privacy policy at https://coinmarketcap.com/privacy for
details on how data in your requests is collected.</p>
<p>If you use the app to pay to BTC addresses, you will be using the XMR.TO service.
See their privacy policy at https://xmr.to/ for details. Monerujo send them the BTC
destination address and amount. Your IP will also be collectable.</p>
@ -624,4 +623,4 @@
<p>DISCLAIMER<br />
THE FONT SOFTWARE IS PROVIDED &#8220;AS IS&#8221;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.</p>
]]></string>
</resources>
</resources>

@ -321,6 +321,37 @@
<item>XMR</item>
<item>EUR</item>
<item>USD</item>
<item>JPY</item>
<item>GBP</item>
<item>CHF</item>
<item>CAD</item>
<item>AUD</item>
<item>ZAR</item>
<item>BRL</item>
<item>CLP</item>
<item>CNY</item>
<item>CZK</item>
<item>DKK</item>
<item>HKD</item>
<item>HUF</item>
<item>IDR</item>
<item>ILS</item>
<item>INR</item>
<item>KRW</item>
<item>MXN</item>
<item>MYR</item>
<item>NOK</item>
<item>NZD</item>
<item>PHP</item>
<item>PKR</item>
<item>PLN</item>
<item>RUB</item>
<item>SEK</item>
<item>SGD</item>
<item>THB</item>
<item>TRY</item>
<item>TWD</item>
</string-array>
<string name="fab_create_new">Create new wallet</string>

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 m2049r et al.
* Copyright (c) 2017-2018 m2049r et al.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.m2049r.xmrwallet.service.exchange.kraken;
package com.m2049r.xmrwallet.service.exchange.coinmarketcap;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeApi;
import com.m2049r.xmrwallet.service.exchange.api.ExchangeCallback;
@ -73,7 +73,7 @@ public class ExchangeRateTest {
public void queryExchangeRate_shouldBeGetMethod()
throws InterruptedException, TimeoutException {
exchangeApi.queryExchangeRate("XMR", "USD", mockExchangeCallback);
exchangeApi.queryExchangeRate("XMR", "EUR", mockExchangeCallback);
RecordedRequest request = mockWebServer.takeRequest();
assertEquals("GET", request.getMethod());
@ -83,18 +83,46 @@ public class ExchangeRateTest {
public void queryExchangeRate_shouldHavePairInUrl()
throws InterruptedException, TimeoutException {
exchangeApi.queryExchangeRate("XMR", "USD", mockExchangeCallback);
exchangeApi.queryExchangeRate("XMR", "EUR", mockExchangeCallback);
RecordedRequest request = mockWebServer.takeRequest();
assertEquals("/?pair=XMRUSD", request.getPath());
assertEquals("/328/?convert=EUR", request.getPath());
}
@Test
public void queryExchangeRate_wasSuccessfulShouldRespondWithRate()
throws InterruptedException, JSONException, TimeoutException {
final String base = "XMR";
final String quote = "EUR";
final double rate = 1.56;
MockResponse jsonMockResponse = new MockResponse().setBody(
createMockExchangeRateResponse(base, quote, rate));
mockWebServer.enqueue(jsonMockResponse);
exchangeApi.queryExchangeRate(base, quote, new ExchangeCallback() {
@Override
public void onSuccess(final ExchangeRate exchangeRate) {
waiter.assertEquals(exchangeRate.getBaseCurrency(), base);
waiter.assertEquals(exchangeRate.getQuoteCurrency(), quote);
waiter.assertEquals(exchangeRate.getRate(), rate);
waiter.resume();
}
@Override
public void onError(final Exception e) {
waiter.fail(e);
waiter.resume();
}
});
waiter.await();
}
@Test
public void queryExchangeRate_wasSuccessfulShouldRespondWithRateUSD()
throws InterruptedException, JSONException, TimeoutException {
final String base = "XMR";
final String quote = "USD";
final double rate = 100;
final double rate = 1.56;
MockResponse jsonMockResponse = new MockResponse().setBody(
createMockExchangeRateResponse(base, quote, rate));
mockWebServer.enqueue(jsonMockResponse);
@ -121,6 +149,7 @@ public class ExchangeRateTest {
public void queryExchangeRate_wasNotSuccessfulShouldCallOnError()
throws InterruptedException, JSONException, TimeoutException {
mockWebServer.enqueue(new MockResponse().setResponseCode(500));
exchangeApi.queryExchangeRate("XMR", "USD", new ExchangeCallback() {
@Override
public void onSuccess(final ExchangeRate exchangeRate) {
@ -142,9 +171,10 @@ public class ExchangeRateTest {
@Test
public void queryExchangeRate_unknownAssetShouldCallOnError()
throws InterruptedException, JSONException, TimeoutException {
mockWebServer.enqueue(new MockResponse().
setResponseCode(200).
setBody("{\"error\":[\"EQuery:Unknown asset pair\"]}"));
MockResponse jsonMockResponse = new MockResponse().setBody(
createMockExchangeRateErrorResponse());
mockWebServer.enqueue(jsonMockResponse);
exchangeApi.queryExchangeRate("XMR", "ABC", new ExchangeCallback() {
@Override
public void onSuccess(final ExchangeRate exchangeRate) {
@ -157,7 +187,7 @@ public class ExchangeRateTest {
waiter.assertTrue(e instanceof ExchangeException);
ExchangeException ex = (ExchangeException) e;
waiter.assertTrue(ex.getCode() == 200);
waiter.assertEquals(ex.getErrorMsg(), "EQuery:Unknown asset pair");
waiter.assertEquals(ex.getErrorMsg(), "id not found");
waiter.resume();
}
@ -167,20 +197,50 @@ public class ExchangeRateTest {
private String createMockExchangeRateResponse(final String base, final String quote, final double rate) {
return "{\n" +
" \"error\":[],\n" +
" \"result\":{\n" +
" \"X" + base + "Z" + quote + "\":{\n" +
" \"a\":[\"" + rate + "\",\"322\",\"322.000\"],\n" +
" \"b\":[\"" + rate + "\",\"76\",\"76.000\"],\n" +
" \"c\":[\"" + rate + "\",\"2.90000000\"],\n" +
" \"v\":[\"4559.03962053\",\"5231.33235586\"],\n" +
" \"p\":[\"" + rate + "\",\"" + rate + "\"],\n" +
" \"t\":[801,1014],\n" +
" \"l\":[\"" + (rate * 0.8) + "\",\"" + rate + "\"],\n" +
" \"h\":[\"" + (rate * 1.2) + "\",\"" + rate + "\"],\n" +
" \"o\":\"" + rate + "\"\n" +
" }\n" +
" }\n" +
" \"data\": {\n" +
" \"id\": 328, \n" +
" \"name\": \"Monero\", \n" +
" \"symbol\": \"" + base + "\", \n" +
" \"website_slug\": \"monero\", \n" +
" \"rank\": 12, \n" +
" \"circulating_supply\": 16112286.0, \n" +
" \"total_supply\": 16112286.0, \n" +
" \"max_supply\": null, \n" +
" \"quotes\": {\n" +
" \"USD\": {\n" +
" \"price\": " + rate + ", \n" +
" \"volume_24h\": 35763700.0, \n" +
" \"market_cap\": 2559791130.0, \n" +
" \"percent_change_1h\": -0.16, \n" +
" \"percent_change_24h\": -3.46, \n" +
" \"percent_change_7d\": 1.49\n" +
" }, \n" +
(!"USD".equals(quote) ? (
" \"" + quote + "\": {\n" +
" \"price\": " + rate + ", \n" +
" \"volume_24h\": 30377728.701265607, \n" +
" \"market_cap\": 2174289586.0, \n" +
" \"percent_change_1h\": -0.16, \n" +
" \"percent_change_24h\": -3.46, \n" +
" \"percent_change_7d\": 1.49\n" +
" }\n") : "") +
" }, \n" +
" \"last_updated\": 1528492746\n" +
" }, \n" +
" \"metadata\": {\n" +
" \"timestamp\": 1528492705, \n" +
" \"error\": null\n" +
" }\n" +
"}";
}
private String createMockExchangeRateErrorResponse() {
return "{\n" +
" \"data\": null, \n" +
" \"metadata\": {\n" +
" \"timestamp\": 1525137187, \n" +
" \"error\": \"id not found\"\n" +
" }\n" +
"}";
}
}
Loading…
Cancel
Save