de.schildbach.wallet.goldcoin.ExchangeRatesProvider.java Source code

Java tutorial

Introduction

Here is the source code for de.schildbach.wallet.goldcoin.ExchangeRatesProvider.java

Source

/*
 * Copyright 2011-2013 the original author or authors.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.schildbach.wallet.goldcoin;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.URL;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.Date;

import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.format.DateUtils;

import com.google.goldcoin.core.Utils;

import de.schildbach.wallet.goldcoin.util.IOUtils;

/**
 * @author Andreas Schildbach
 */
public class ExchangeRatesProvider extends ContentProvider {
    public static class ExchangeRate {
        public ExchangeRate(final String currencyCode, final BigInteger rate, final String source) {
            this.currencyCode = currencyCode;
            this.rate = rate;
            this.source = source;
        }

        public final String currencyCode;
        public final BigInteger rate;
        public final String source;
    }

    public static final String KEY_CURRENCY_CODE = "currency_code";
    private static final String KEY_RATE = "rate";
    private static final String KEY_SOURCE = "source";

    private Map<String, ExchangeRate> exchangeRates = null;
    private long lastUpdated = 0;

    private static final long UPDATE_FREQ_MS = DateUtils.HOUR_IN_MILLIS;
    private static final int TIMEOUT_MS = 15 * (int) DateUtils.SECOND_IN_MILLIS;

    @Override
    public boolean onCreate() {
        return true;
    }

    public static Uri contentUri(final String packageName) {
        return Uri.parse("content://" + packageName + '.' + "exchange_rates");
    }

    @Override
    public Cursor query(final Uri uri, final String[] projection, final String selection,
            final String[] selectionArgs, final String sortOrder) {
        final long now = System.currentTimeMillis();

        if (exchangeRates == null || now - lastUpdated > UPDATE_FREQ_MS) {
            Map<String, ExchangeRate> newExchangeRates = getBitcoinCharts();//getLitecoinCharts();

            if (exchangeRates == null && newExchangeRates == null)
                newExchangeRates = getBlockchainInfo();

            if (newExchangeRates == null)
                newExchangeRates = getLitecoinCharts();

            if (newExchangeRates != null) {
                exchangeRates = newExchangeRates;
                lastUpdated = now;
            }
        }

        if (exchangeRates == null)
            return null;

        final MatrixCursor cursor = new MatrixCursor(
                new String[] { BaseColumns._ID, KEY_CURRENCY_CODE, KEY_RATE, KEY_SOURCE });

        if (selection == null) {
            for (final Map.Entry<String, ExchangeRate> entry : exchangeRates.entrySet()) {
                final ExchangeRate rate = entry.getValue();
                cursor.newRow().add(entry.getKey().hashCode()).add(rate.currencyCode).add(rate.rate.longValue())
                        .add(rate.source);
            }
        } else if (selection.equals(KEY_CURRENCY_CODE)) {
            final String code = selectionArgs[0];
            final ExchangeRate rate = exchangeRates.get(code);
            try {
                cursor.newRow().add(code.hashCode()).add(rate.currencyCode).add(rate.rate.longValue())
                        .add(rate.source);
            } catch (NullPointerException e) {
                Log.e("GoldCoin", "Unable to add an exchange rate.  NullPointerException.");
            }
        }

        return cursor;
    }

    public static ExchangeRate getExchangeRate(final Cursor cursor) {
        final String currencyCode = cursor
                .getString(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_CURRENCY_CODE));
        final BigInteger rate = BigInteger
                .valueOf(cursor.getLong(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_RATE)));
        final String source = cursor.getString(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_SOURCE));

        return new ExchangeRate(currencyCode, rate, source);
    }

    @Override
    public Uri insert(final Uri uri, final ContentValues values) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int update(final Uri uri, final ContentValues values, final String selection,
            final String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getType(final Uri uri) {
        throw new UnsupportedOperationException();
    }

    private static Double lastLitecoinValue = 0.0;
    private static long lastLitecoinValueCheck = 0;

    private static Double getGoldCoinValueLTC() {
        Date date = new Date();
        long now = date.getTime();

        if ((now < (lastLitecoinValueCheck + 10 * 60)) && lastLitecoinValue > 0.0)
            return lastLitecoinValue;

        //final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();
        // Keep the LTC rate around for a bit
        Double ltcRate = 0.0;
        String currencyCryptsy = "LTC";
        String urlCryptsy = "http://pubapi.cryptsy.com/api.php?method=marketdata";

        try {
            // final String currencyCode = currencies[i];
            final URL URLCryptsy = new URL(urlCryptsy);
            final URLConnection connectionCryptsy = URLCryptsy.openConnection();
            connectionCryptsy.setConnectTimeout(TIMEOUT_MS);
            connectionCryptsy.setReadTimeout(TIMEOUT_MS);
            connectionCryptsy.connect();

            final StringBuilder contentCryptsy = new StringBuilder();

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connectionCryptsy.getInputStream(), 1024));
                IOUtils.copy(reader, contentCryptsy);
                final JSONObject head = new JSONObject(contentCryptsy.toString());
                JSONObject returnObject = head.getJSONObject("return");
                JSONObject markets = returnObject.getJSONObject("markets");
                JSONObject GLD = markets.getJSONObject("GLD");

                Double lastTrade = GLD.getDouble("lasttradeprice");

                //String euros = String.format("%.7f", lastTrade);
                // Fix things like 3,1250
                //euros = euros.replace(",", ".");
                //rates.put(currencyCryptsy, new ExchangeRate(currencyCryptsy, Utils.toNanoCoins(euros), URLCryptsy.getHost()));
                if (currencyCryptsy.equalsIgnoreCase("LTC"))
                    ltcRate = lastTrade;

                lastLitecoinValue = ltcRate;
                lastLitecoinValueCheck = now;
            } finally {
                if (reader != null)
                    reader.close();
            }
            return ltcRate;
        } catch (final IOException x) {
            x.printStackTrace();
        } catch (final JSONException x) {
            x.printStackTrace();
        }

        return null;
    }

    private static Double lastBitcoinValue = 0.0;
    private static long lastBitcoinValueCheck = 0;

    private static Object getGoldCoinValueBTC() {
        Date date = new Date();
        long now = date.getTime();

        if ((now < (lastBitcoinValueCheck + 10 * 60)) && lastBitcoinValue > 0.0)
            return lastBitcoinValue;

        //final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();
        // Keep the LTC rate around for a bit
        Double btcRate = 0.0;
        String currencyCryptsy = "BTC";
        String urlCryptsy2 = "http://pubapi.cryptsy.com/api.php?method=marketdata";
        String urlCryptsy = "http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=30";

        try {
            // final String currencyCode = currencies[i];
            final URL URLCryptsy = new URL(urlCryptsy);
            final URLConnection connectionCryptsy = URLCryptsy.openConnection();
            connectionCryptsy.setConnectTimeout(TIMEOUT_MS * 2);
            connectionCryptsy.setReadTimeout(TIMEOUT_MS * 2);
            connectionCryptsy.connect();

            final StringBuilder contentCryptsy = new StringBuilder();

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connectionCryptsy.getInputStream(), 1024));
                IOUtils.copy(reader, contentCryptsy);
                final JSONObject head = new JSONObject(contentCryptsy.toString());
                JSONObject returnObject = head.getJSONObject("return");
                JSONObject markets = returnObject.getJSONObject("markets");
                JSONObject GLD = markets.getJSONObject("GLD");

                JSONArray recenttrades = GLD.getJSONArray("recenttrades");

                double btcTraded = 0.0;
                double gldTraded = 0.0;

                for (int i = 0; i < recenttrades.length(); ++i) {
                    JSONObject trade = (JSONObject) recenttrades.get(i);

                    btcTraded += trade.getDouble("total");
                    gldTraded += trade.getDouble("quantity");

                }

                Double averageTrade = btcTraded / gldTraded;

                //Double lastTrade = GLD.getDouble("lasttradeprice");

                //String euros = String.format("%.7f", averageTrade);
                // Fix things like 3,1250
                //euros = euros.replace(",", ".");
                //rates.put(currencyCryptsy, new ExchangeRate(currencyCryptsy, Utils.toNanoCoins(euros), URLCryptsy.getHost()));
                if (currencyCryptsy.equalsIgnoreCase("BTC"))
                    btcRate = averageTrade;

                lastBitcoinValue = btcRate;
                lastBitcoinValueCheck = now;
            } finally {
                if (reader != null)
                    reader.close();
            }
            return btcRate;
        } catch (final IOException x) {
            x.printStackTrace();
        } catch (final JSONException x) {
            x.printStackTrace();
        }

        return null;
    }

    private static Object getGoldCoinValueBTC_ccex() {
        Date date = new Date();
        long now = date.getTime();

        if ((now < (lastBitcoinValueCheck + 10 * 60)) && lastBitcoinValue > 0.0)
            return lastBitcoinValue;

        //final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();
        // Keep the LTC rate around for a bit
        Double btcRate = 0.0;
        String currencyCryptsy = "BTC";
        String urlCryptsy = "https://c-cex.com/t/gld-btc.json";

        try {
            // final String currencyCode = currencies[i];
            final URL URLCryptsy = new URL(urlCryptsy);
            final URLConnection connectionCryptsy = URLCryptsy.openConnection();
            connectionCryptsy.setConnectTimeout(TIMEOUT_MS * 2);
            connectionCryptsy.setReadTimeout(TIMEOUT_MS * 2);
            connectionCryptsy.connect();

            final StringBuilder contentCryptsy = new StringBuilder();

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connectionCryptsy.getInputStream(), 1024));
                IOUtils.copy(reader, contentCryptsy);
                final JSONObject head = new JSONObject(contentCryptsy.toString());

                //JSONObject returnObject = head.getJSONObject("return");
                //JSONObject markets = returnObject.getJSONObject("markets");
                JSONObject GLD = head.getJSONObject("ticker");

                //JSONArray recenttrades = GLD.getJSONArray("recenttrades");

                double btcTraded = 0.0;
                double gldTraded = 0.0;

                /*for(int i = 0; i < recenttrades.length(); ++i)
                {
                JSONObject trade = (JSONObject)recenttrades.get(i);
                    
                btcTraded += trade.getDouble("total");
                gldTraded += trade.getDouble("quantity");
                    
                }
                    
                Double averageTrade = btcTraded / gldTraded;
                */

                Double averageTrade = head.getDouble("buy");

                //Double lastTrade = GLD.getDouble("lasttradeprice");

                //String euros = String.format("%.7f", averageTrade);
                // Fix things like 3,1250
                //euros = euros.replace(",", ".");
                //rates.put(currencyCryptsy, new ExchangeRate(currencyCryptsy, Utils.toNanoCoins(euros), URLCryptsy.getHost()));
                if (currencyCryptsy.equalsIgnoreCase("BTC"))
                    btcRate = averageTrade;

                lastBitcoinValue = btcRate;
                lastBitcoinValueCheck = now;
            } finally {
                if (reader != null)
                    reader.close();
            }
            return btcRate;
        } catch (final IOException x) {
            x.printStackTrace();
        } catch (final JSONException x) {
            x.printStackTrace();
        }

        return null;
    }

    private static Object getCoinValueBTC_cryptopia() {
        //final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();
        // Keep the LTC rate around for a bit
        Double btcRate = 0.0;
        String currency = "BTC";
        String url = "https://www.cryptopia.co.nz/api/GetMarket/2623";

        try {
            // final String currencyCode = currencies[i];
            final URL URL_bter = new URL(url);
            final HttpURLConnection connection = (HttpURLConnection) URL_bter.openConnection();
            connection.setConnectTimeout(Constants.HTTP_TIMEOUT_MS * 2);
            connection.setReadTimeout(Constants.HTTP_TIMEOUT_MS * 2);
            connection.connect();

            final StringBuilder content = new StringBuilder();

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connection.getInputStream(), 1024));
                IOUtils.copy(reader, content);
                final JSONObject head = new JSONObject(content.toString());

                /*{
                   "Success":true,
                      "Message":null,
                      "Data":{
                 "TradePairId":100,
                 "Label":"LTC/BTC",
                 "AskPrice":0.00006000,
                 "BidPrice":0.02000000,
                 "Low":0.00006000,
                 "High":0.00006000,
                 "Volume":1000.05639978,
                 "LastPrice":0.00006000,
                 "LastVolume":499.99640000,
                 "BuyVolume":67003436.37658233,
                 "SellVolume":67003436.37658233,
                 "Change":-400.00000000
                      }
                }*/
                String result = head.getString("Success");
                if (result.equals("true")) {
                    JSONObject dataObject = head.getJSONObject("Data");

                    Double averageTrade = Double.valueOf(0.0);
                    if (dataObject.get("Label").equals("GLD/BTC"))
                        averageTrade = dataObject.getDouble("LastPrice");

                    if (currency.equalsIgnoreCase("BTC"))
                        btcRate = averageTrade;
                }
                return btcRate;
            } finally {
                if (reader != null)
                    reader.close();
            }

        } catch (final IOException x) {
            x.printStackTrace();
        } catch (final JSONException x) {
            x.printStackTrace();
        }

        return null;
    }

    private static Map<String, ExchangeRate> getLitecoinChartsOld() {
        final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();
        // Keep the BTC rate around for a bit
        Double ltcRate = getGoldCoinValueLTC();

        Double btcRate = 0.0;
        try {
            String currencies[] = { "USD", "BTC" };//, "RUR"};
            String urls[] = { "https://btc-e.com/api/2/14/ticker", "https://btc-e.com/api/2/10/ticker",
                    "https://btc-e.com/api/2/ltc_rur/ticker" };
            for (int i = 0; i < currencies.length; ++i) {
                final String currencyCode = currencies[i];
                final URL URL = new URL(urls[i]);
                final URLConnection connection = URL.openConnection();
                connection.setConnectTimeout(TIMEOUT_MS);
                connection.setReadTimeout(TIMEOUT_MS);
                connection.connect();
                final StringBuilder content = new StringBuilder();

                Reader reader = null;
                try {
                    reader = new InputStreamReader(new BufferedInputStream(connection.getInputStream(), 1024));
                    IOUtils.copy(reader, content);
                    final JSONObject head = new JSONObject(content.toString());
                    JSONObject ticker = head.getJSONObject("ticker");
                    Double avg = ticker.getDouble("avg") * ltcRate;
                    String euros = String.format("%.7f", avg);
                    // Fix things like 3,1250
                    euros = euros.replace(",", ".");
                    rates.put(currencyCode,
                            new ExchangeRate(currencyCode, Utils.toNanoCoins(euros), URL.getHost()));
                    if (currencyCode.equalsIgnoreCase("BTC"))
                        btcRate = avg;
                } finally {
                    if (reader != null)
                        reader.close();
                }
            }
            // Handle LTC/EUR special since we have to do maths
            final URL URL = new URL("https://btc-e.com/api/2/btc_eur/ticker");
            final URLConnection connection = URL.openConnection();
            connection.setConnectTimeout(TIMEOUT_MS);
            connection.setReadTimeout(TIMEOUT_MS);
            connection.connect();
            final StringBuilder content = new StringBuilder();

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connection.getInputStream(), 1024));
                IOUtils.copy(reader, content);
                final JSONObject head = new JSONObject(content.toString());
                JSONObject ticker = head.getJSONObject("ticker");
                Double avg = ticker.getDouble("avg");
                // This is bitcoins priced in euros.  We want GLD!
                avg *= btcRate;
                String s_avg = String.format("%.8f", avg).replace(',', '.');
                rates.put("EUR", new ExchangeRate("EUR", Utils.toNanoCoins(s_avg), URL.getHost()));

                //Add LTC information
                s_avg = String.format("%.8f", ltcRate);
                rates.put("LTC",
                        new ExchangeRate("LTC", Utils.toNanoCoins(s_avg.replace(",", ".")), URL.getHost()));
            } finally {
                if (reader != null)
                    reader.close();
            }
            return rates;
        } catch (final IOException x) {
            x.printStackTrace();
        } catch (final JSONException x) {
            x.printStackTrace();
        }

        return null;
    }

    private static Map<String, ExchangeRate> getLitecoinCharts() {
        final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();
        // Keep the BTC rate around for a bit
        Double btcRate = 0.0;

        Object result = getGoldCoinValueBTC();

        if (result == null) {
            return null;
        }

        else
            btcRate = (Double) result;

        //Double btcRate = 0.0;
        try {
            rates.put("BTC", new ExchangeRate("BTC",
                    Utils.toNanoCoins(String.format("%.8f", btcRate).replace(",", ".")), "pubapi.cryptsy.com"));
            String currencies[] = { "USD" };//, "BTC"};//, "RUR"};
            String urls[] = { "https://btc-e.com/api/2/1/ticker" };//, "https://btc-e.com/api/2/14/ticker", "https://btc-e.com/api/2/ltc_rur/ticker"};
            for (int i = 0; i < currencies.length; ++i) {
                final String currencyCode = currencies[i];
                final URL URL = new URL(urls[i]);
                final URLConnection connection = URL.openConnection();
                connection.setConnectTimeout(TIMEOUT_MS);
                connection.setReadTimeout(TIMEOUT_MS);
                connection.connect();
                final StringBuilder content = new StringBuilder();

                Reader reader = null;
                try {
                    reader = new InputStreamReader(new BufferedInputStream(connection.getInputStream(), 1024));
                    IOUtils.copy(reader, content);
                    final JSONObject head = new JSONObject(content.toString());
                    JSONObject ticker = head.getJSONObject("ticker");
                    Double avg = ticker.getDouble("avg") * btcRate;
                    String euros = String.format("%.8f", avg);
                    // Fix things like 3,1250
                    euros = euros.replace(",", ".");
                    rates.put(currencyCode,
                            new ExchangeRate(currencyCode, Utils.toNanoCoins(euros), URL.getHost()));
                    if (currencyCode.equalsIgnoreCase("BTC"))
                        btcRate = avg;
                } finally {
                    if (reader != null)
                        reader.close();
                }
            }
            // Handle LTC/EUR special since we have to do maths
            final URL URL = new URL("https://btc-e.com/api/2/btc_eur/ticker");
            final URLConnection connection = URL.openConnection();
            connection.setConnectTimeout(TIMEOUT_MS);
            connection.setReadTimeout(TIMEOUT_MS);
            connection.connect();
            final StringBuilder content = new StringBuilder();

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connection.getInputStream(), 1024));
                IOUtils.copy(reader, content);
                final JSONObject head = new JSONObject(content.toString());
                JSONObject ticker = head.getJSONObject("ticker");
                Double avg = ticker.getDouble("avg");
                // This is bitcoins priced in euros.  We want GLD!
                avg *= btcRate;
                String s_avg = String.format("%.8f", avg).replace(',', '.');
                rates.put("EUR", new ExchangeRate("EUR", Utils.toNanoCoins(s_avg), URL.getHost()));

                //Add LTC information
                //s_avg = String.format("%.8f", ltcRate);
                //rates.put("LTC", new ExchangeRate("LTC", Utils.toNanoCoins(s_avg), URL.getHost()));
            } finally {
                if (reader != null)
                    reader.close();
            }
            return rates;
        } catch (final IOException x) {
            x.printStackTrace();
        } catch (final JSONException x) {
            x.printStackTrace();
        }

        return null;
    }

    private static Map<String, ExchangeRate> getBitcoinCharts() {
        try {
            // double btcRate = getGoldCoinValueBTC();     //NullPointerException???
            Double btcRate = 0.0;

            Object result = getGoldCoinValueBTC_ccex();

            if (result == null) {
                result = getCoinValueBTC_cryptopia();
                if (result == null)
                    return null;
                else
                    btcRate = (Double) result;
            }

            else
                btcRate = (Double) result;

            final URL URL = new URL("http://api.bitcoincharts.com/v1/weighted_prices.json");
            final HttpURLConnection connection = (HttpURLConnection) URL.openConnection();
            connection.setConnectTimeout(Constants.HTTP_TIMEOUT_MS);
            connection.setReadTimeout(Constants.HTTP_TIMEOUT_MS);
            connection.connect();

            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
                return null;

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connection.getInputStream(), 1024));
                final StringBuilder content = new StringBuilder();
                IOUtils.copy(reader, content);

                final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();

                //Add Bitcoin information
                rates.put("BTC", new ExchangeRate("BTC",
                        Utils.toNanoCoins(String.format("%.8f", btcRate).replace(",", ".")), "pubapi.cryptsy.com"));

                final JSONObject head = new JSONObject(content.toString());
                for (final Iterator<String> i = head.keys(); i.hasNext();) {
                    final String currencyCode = i.next();
                    if (!"timestamp".equals(currencyCode)) {
                        final JSONObject o = head.getJSONObject(currencyCode);

                        String rate = o.optString("24h", null);
                        if (rate == null)
                            rate = o.optString("7d", null);
                        if (rate == null)
                            rate = o.optString("30d", null);

                        double rateForBTC = Double.parseDouble(rate);

                        rate = String.format("%.8f", rateForBTC * btcRate);

                        if (rate != null)
                            rates.put(currencyCode, new ExchangeRate(currencyCode,
                                    Utils.toNanoCoins(rate.replace(",", ".")), URL.getHost()));
                    }
                }

                return rates;
            } finally {
                if (reader != null)
                    reader.close();
            }
        } catch (final IOException x) {
            // log.debug("problem reading exchange rates", x);
            x.printStackTrace();
        } catch (final JSONException x) {
            //log.debug("problem reading exchange rates", x);
            x.printStackTrace();
        }

        return null;
    }

    private static Map<String, ExchangeRate> getBlockchainInfo() {
        try {
            //double btcRate = getGoldCoinValueBTC();

            Double btcRate = 0.0;

            Object result = getGoldCoinValueBTC();

            if (result == null)
                return null;

            else
                btcRate = (Double) result;

            final URL URL = new URL("https://blockchain.info/ticker");
            final URLConnection connection = URL.openConnection();
            connection.setConnectTimeout(TIMEOUT_MS);
            connection.setReadTimeout(TIMEOUT_MS);
            connection.connect();
            final StringBuilder content = new StringBuilder();

            Reader reader = null;
            try {
                reader = new InputStreamReader(new BufferedInputStream(connection.getInputStream(), 1024));
                IOUtils.copy(reader, content);

                final Map<String, ExchangeRate> rates = new TreeMap<String, ExchangeRate>();

                //Add Bitcoin information
                rates.put("BTC", new ExchangeRate("BTC",
                        Utils.toNanoCoins(String.format("%.8f", btcRate).replace(",", ".")), "pubapi.cryptsy.com"));

                final JSONObject head = new JSONObject(content.toString());
                for (final Iterator<String> i = head.keys(); i.hasNext();) {
                    final String currencyCode = i.next();
                    final JSONObject o = head.getJSONObject(currencyCode);
                    double gldInCurrency = o.getDouble("15m") * btcRate;
                    final String rate = String.format("%.8f", gldInCurrency); //o.optString("15m", null);

                    if (rate != null)
                        rates.put(currencyCode, new ExchangeRate(currencyCode,
                                Utils.toNanoCoins(rate.replace(",", ".")), URL.getHost()));
                }

                return rates;
            } finally {
                if (reader != null)
                    reader.close();
            }
        } catch (final IOException x) {
            x.printStackTrace();
        } catch (final JSONException x) {
            x.printStackTrace();
        }

        return null;
    }

    // https://bitmarket.eu/api/ticker
}