coinmarketcap for exchange rates (#304)

This commit is contained in:
m2049r 2018-06-10 10:56:46 +02:00 committed by GitHub
parent 843566b820
commit 37244cb9e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 205 additions and 120 deletions

View File

@ -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());

View File

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

View File

@ -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());
}

View File

@ -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());
}
}

View File

@ -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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,19 +197,49 @@ 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" +
" \"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" +
"}";
}