balance = balanceManager.getTotalBalance();
+
+ if(balanceManager.getTotalBalance().size() < 0)
+ {
+ for(int i = 0; i < balanceManager.getTotalBalance().size(); i++)
+ {
+ balance.get(i).updateDayPriceHistory(getApplicationContext(), new Currency.CurrencyCallBack() {
+ @Override
+ public void onSuccess(Currency currency) {
+ currency.updateName(getApplicationContext(), new Currency.CurrencyCallBack() {
+ @Override
+ public void onSuccess(Currency currency) {
+ countCoins(true, false);
+ }
+ });
+ }
+ });
+ }
+ }
+ else
+ {
+ countCoins(false, false);
+ }
+ }
+
+ public void onError(String error)
+ {
+ switch (error)
+ {
+ case "com.android.volley.AuthFailureError":
+ preferencesManager.disableHitBTC();
+ Snackbar.make(findViewById(R.id.currencyListLayout), "HitBTC synchronization error : Invalid keys", Snackbar.LENGTH_LONG)
+ .show();
+ refreshLayout.setRefreshing(false);
+ updateAll();
+ break;
+ default:
+ updateAll();
+ }
+ //updateAll();
+ }
+ });
+
+ balanceManager.updateDetails(new BalanceManager.IconCallBack() {
+ @Override
+ public void onSuccess()
+ {
+ countCoins(false, true);
+ }
+ });
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result)
+ {
+
+ }
+ }
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/Activities/RecordTransactionActivity.java b/app/src/main/java/com/nauk/coinfolio/Activities/RecordTransactionActivity.java
new file mode 100644
index 0000000..10aa791
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/Activities/RecordTransactionActivity.java
@@ -0,0 +1,43 @@
+package com.nauk.coinfolio.Activities;
+
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.nauk.coinfolio.DataManagers.DatabaseManager;
+import com.nauk.coinfolio.R;
+
+public class RecordTransactionActivity extends AppCompatActivity {
+
+ String coin;
+ String symbol;
+ TextView symbolTxtView;
+ Button validateButton;
+ DatabaseManager databaseManager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_record_transaction);
+
+ Intent intent = getIntent();
+ coin = intent.getStringExtra("coin");
+ symbol = intent.getStringExtra("symbol");
+
+ setTitle("Add " + coin + " transaction");
+
+ databaseManager = new DatabaseManager(this);
+
+ validateButton = findViewById(R.id.validateButton);
+
+ validateButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ //databaseManager.addCurrencyToManualCurrency();
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/Activities/SettingsActivity.java b/app/src/main/java/com/nauk/coinfolio/Activities/SettingsActivity.java
new file mode 100644
index 0000000..f17cd3e
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/Activities/SettingsActivity.java
@@ -0,0 +1,290 @@
+package com.nauk.coinfolio.Activities;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.support.v7.app.ActionBar;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.preference.RingtonePreference;
+import android.text.TextUtils;
+import android.view.MenuItem;
+
+import com.nauk.coinfolio.R;
+
+import java.util.List;
+
+/**
+ * A {@link PreferenceActivity} that presents a set of application settings. On
+ * handset devices, settings are presented as a single list. On tablets,
+ * settings are split by category, with category headers shown to the left of
+ * the list of settings.
+ *
+ * See
+ * Android Design: Settings for design guidelines and the Settings
+ * API Guide for more information on developing a Settings UI.
+ */
+public class SettingsActivity extends AppCompatPreferenceActivity {
+
+ /**
+ * A preference value change listener that updates the preference's summary
+ * to reflect its new value.
+ */
+ private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object value) {
+ String stringValue = value.toString();
+
+ if (preference instanceof ListPreference) {
+ // For list preferences, look up the correct display value in
+ // the preference's 'entries' list.
+ ListPreference listPreference = (ListPreference) preference;
+ int index = listPreference.findIndexOfValue(stringValue);
+
+ // Set the summary to reflect the new value.
+ preference.setSummary(
+ index >= 0
+ ? listPreference.getEntries()[index]
+ : null);
+
+ } else if (preference instanceof RingtonePreference) {
+ // For ringtone preferences, look up the correct display value
+ // using RingtoneManager.
+ if (TextUtils.isEmpty(stringValue)) {
+ // Empty values correspond to 'silent' (no ringtone).
+ preference.setSummary(R.string.pref_ringtone_silent);
+
+ } else {
+ Ringtone ringtone = RingtoneManager.getRingtone(
+ preference.getContext(), Uri.parse(stringValue));
+
+ if (ringtone == null) {
+ // Clear the summary if there was a lookup error.
+ preference.setSummary(null);
+ } else {
+ // Set the summary to reflect the new ringtone display
+ // name.
+ String name = ringtone.getTitle(preference.getContext());
+ preference.setSummary(name);
+ }
+ }
+ } else {
+ // For all other preferences, set the summary to the value's
+ // simple string representation.
+ preference.setSummary(stringValue);
+ }
+ return true;
+ }
+ };
+
+ /**
+ * Helper method to determine if the device has an extra-large screen. For
+ * example, 10" tablets are extra-large.
+ */
+ private static boolean isXLargeTablet(Context context) {
+ return (context.getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Binds a preference's summary to its value. More specifically, when the
+ * preference's value is changed, its summary (line of text below the
+ * preference title) is updated to reflect the value. The summary is also
+ * immediately updated upon calling this method. The exact display format is
+ * dependent on the type of preference.
+ *
+ * @see #sBindPreferenceSummaryToValueListener
+ */
+ private static void bindPreferenceSummaryToValue(Preference preference) {
+ // Set the listener to watch for value changes.
+ preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
+
+ // Trigger the listener immediately with the preference's
+ // current value.
+ sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
+ PreferenceManager
+ .getDefaultSharedPreferences(preference.getContext())
+ .getString(preference.getKey(), ""));
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setupActionBar();
+ }
+
+ /**
+ * Set up the {@link android.app.ActionBar}, if the API is available.
+ */
+ private void setupActionBar() {
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ // Show the Up button in the action bar.
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onIsMultiPane() {
+ return isXLargeTablet(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public void onBuildHeaders(List target) {
+ loadHeadersFromResource(R.xml.pref_headers, target);
+ }
+
+ /**
+ * This method stops fragment injection in malicious applications.
+ * Make sure to deny any unknown fragments here.
+ */
+ protected boolean isValidFragment(String fragmentName) {
+ return PreferenceFragment.class.getName().equals(fragmentName)
+ //|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
+ || DataSyncPreferenceFragment.class.getName().equals(fragmentName)
+ || NotificationPreferenceFragment.class.getName().equals(fragmentName)
+ || ExchangePreferenceFragment.class.getName().equals(fragmentName);
+ }
+
+ /**
+ * This fragment shows general preferences only. It is used when the
+ * activity is showing a two-pane settings UI.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class GeneralPreferenceFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_general);
+ setHasOptionsMenu(true);
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+ // to their values. When their values change, their summaries are
+ // updated to reflect the new value, per the Android Design
+ // guidelines.
+ bindPreferenceSummaryToValue(findPreference("example_text"));
+ bindPreferenceSummaryToValue(findPreference("example_list"));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ //startActivity(new Intent(getActivity(), SettingsActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class ExchangePreferenceFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_exchange);
+ setHasOptionsMenu(true);
+
+ bindPreferenceSummaryToValue(findPreference("hitbtc_publickey"));
+ bindPreferenceSummaryToValue(findPreference("hitbtc_privatekey"));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ //startActivity(new Intent(getActivity(), SettingsActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ /**
+ * This fragment shows notification preferences only. It is used when the
+ * activity is showing a two-pane settings UI.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class NotificationPreferenceFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_notification);
+ setHasOptionsMenu(true);
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+ // to their values. When their values change, their summaries are
+ // updated to reflect the new value, per the Android Design
+ // guidelines.
+ bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ startActivity(new Intent(getActivity(), SettingsActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ /**
+ * This fragment shows data and sync preferences only. It is used when the
+ * activity is showing a two-pane settings UI.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class DataSyncPreferenceFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_data_sync);
+ setHasOptionsMenu(true);
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+ // to their values. When their values change, their summaries are
+ // updated to reflect the new value, per the Android Design
+ // guidelines.
+ bindPreferenceSummaryToValue(findPreference("sync_frequency"));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ startActivity(new Intent(getActivity(), SettingsActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/DataManagers/BalanceManager.java b/app/src/main/java/com/nauk/coinfolio/DataManagers/BalanceManager.java
new file mode 100644
index 0000000..eb34738
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/DataManagers/BalanceManager.java
@@ -0,0 +1,293 @@
+package com.nauk.coinfolio.DataManagers;
+
+import android.os.StrictMode;
+import android.util.Base64;
+import android.util.Log;
+
+import com.android.volley.AuthFailureError;
+import com.android.volley.Request;
+import com.android.volley.RequestQueue;
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+import com.android.volley.toolbox.JsonArrayRequest;
+import com.android.volley.toolbox.StringRequest;
+import com.android.volley.toolbox.Volley;
+import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
+import com.nauk.coinfolio.R;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * Created by Tiji on 25/12/2017.
+ */
+
+public class BalanceManager {
+
+ private String publicHitKey;
+ private String publicBinanceKey;
+ private String publicPoloniex;
+ private String privateHitKey;
+ private String privateBinanceKey;
+ private String privatePoloniex;
+ final private String hitBalanceUrl = "https://api.hitbtc.com/api/2/trading/balance";
+ final private String detailUrl = "https://www.cryptocompare.com/api/data/coinlist/";
+ final private String binanceBalanceUrl = "https://api.binance.com/api/v3/account";
+ final private String binanceTimeUrl = "https://api.binance.com/api/v1/time";
+ private RequestQueue requestQueue;
+ private List hitBalance;
+ private List otherBalances;
+ private List totalBalance;
+ private android.content.Context context;
+ private Map iconUrlList;
+ private Map coinList;
+ private PreferencesManager preferenceManager;
+
+ public BalanceManager(android.content.Context context)
+ {
+ this.context = context;
+ preferenceManager = new PreferencesManager(context);
+ requestQueue = Volley.newRequestQueue(context);
+ hitBalance = new ArrayList();
+ otherBalances = new ArrayList();
+ }
+
+ public List getCurrenciesName()
+ {
+ return new ArrayList<>(coinList.values());
+ }
+
+ public List getCurrenciesSymbol()
+ {
+ return new ArrayList<>(coinList.keySet());
+ }
+
+ public void updateExchangeKeys()
+ {
+ publicHitKey = preferenceManager.getHitBTCPublicKey();
+ privateHitKey = preferenceManager.getHitBTCPrivateKey();
+ }
+
+ public boolean isHitBTCConfigured()
+ {
+ boolean isConfigured = true;
+
+ if(publicHitKey == null || privateHitKey == null)
+ {
+ isConfigured = false;
+ }
+
+ return isConfigured;
+ }
+
+ public void setPublicHitKey(String newKey)
+ {
+ publicHitKey = newKey;
+ }
+
+ public void setPrivateHitKey(String newKey)
+ {
+ privateHitKey = newKey;
+ }
+
+ public List getTotalBalance()
+ {
+ return totalBalance;
+ }
+
+ public List getHitBalance()
+ {
+ return hitBalance;
+ }
+
+ public List getOtherBalances()
+ {
+ return otherBalances;
+ }
+
+ public void updateTotalBalance(final VolleyCallBack callBack)
+ {
+ if(privateHitKey != null && publicHitKey != null && preferenceManager.isHitBTCActivated())
+ {
+ updateHitBalance(callBack);
+ }
+ else
+ {
+ hitBalance = new ArrayList();
+ refreshAllBalances(callBack);
+ }
+ }
+
+ private void updateHitBalance(final VolleyCallBack callBack)
+ {
+ JsonArrayRequest arrReq = new JsonArrayRequest(Request.Method.GET, hitBalanceUrl,
+ new Response.Listener() {
+ @Override
+ public void onResponse(JSONArray response) {
+ if (response.length() > 0) {
+
+ parseHitBalance(response);
+ refreshAllBalances(callBack);
+
+ } else {
+ //No balance
+ }
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e(context.getResources().getString(R.string.debug_volley), "API Error : " + error.toString() + ":");
+ callBack.onError(error.toString());
+ }
+ }
+ ) {
+ @Override
+ public Map getHeaders()throws AuthFailureError {
+ Map headers = new HashMap<>();
+ String credentials = publicHitKey + ":" + privateHitKey;
+ String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
+ headers.put("Content-Type", "application/json");
+ headers.put("Authorization", auth);
+
+ return headers;
+ }
+ };
+
+ requestQueue.add(arrReq);
+ }
+
+ private void parseHitBalance(JSONArray response)
+ {
+ hitBalance = new ArrayList<>();
+
+ for (int i = 0; i < response.length(); i++)
+ {
+ try {
+ JSONObject jsonObj = response.getJSONObject(i);
+
+ if(Float.parseFloat(jsonObj.getString("available")) > 0)
+ {
+ hitBalance.add(new Currency(jsonObj.getString("currency"), Double.parseDouble(jsonObj.getString("available"))));
+ }
+
+ } catch (JSONException e) {
+ Log.e(context.getResources().getString(R.string.debug_volley), "Invalid JSON Object");
+ }
+ }
+ }
+
+ private void refreshAllBalances(final VolleyCallBack callBack)
+ {
+ totalBalance = new ArrayList<>();
+
+ totalBalance.addAll(hitBalance);
+
+ for(int i = 0; i < otherBalances.size(); i++)
+ {
+ boolean isIn = false;
+
+ for(int j = 0; j < totalBalance.size(); j++)
+ {
+ if(otherBalances.get(i).getSymbol().equals(totalBalance.get(j).getSymbol()))
+ {
+ totalBalance.get(j).setBalance(totalBalance.get(j).getBalance() + otherBalances.get(i).getBalance());
+
+ isIn = true;
+ }
+ }
+
+ if(!isIn)
+ {
+ totalBalance.add(otherBalances.get(i));
+ }
+ }
+
+ callBack.onSuccess();
+ }
+
+ public interface VolleyCallBack {
+ void onSuccess();
+ void onError(String error);
+ }
+
+ public interface IconCallBack {
+ void onSuccess();
+ }
+
+ public void sortCoins()
+ {
+ for(int i = 0; i < totalBalance.size(); i++)
+ {
+ for(int j = i; j < totalBalance.size(); j++)
+ {
+ if(totalBalance.get(j).getBalance() * totalBalance.get(j).getValue() > totalBalance.get(i).getBalance() * totalBalance.get(i).getValue())
+ {
+ Currency temp = totalBalance.get(j);
+ totalBalance.set(j, totalBalance.get(i));
+ totalBalance.set(i, temp);
+ }
+ }
+ }
+ }
+
+ public void updateDetails(final IconCallBack callBack)
+ {
+ StringRequest strRequest = new StringRequest(Request.Method.GET, detailUrl,
+ new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ if (response.length() > 0) {
+ processDetailResult(response, callBack);
+ }
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+
+ }
+ });
+
+ requestQueue.add(strRequest);
+ }
+
+ public String getIconUrl(String symbol)
+ {
+ return iconUrlList.get(symbol);
+ }
+
+ private void processDetailResult(String response, final IconCallBack callBack)
+ {
+ response = response.substring(response.indexOf("\"Data\"") + 7, response.lastIndexOf("},\"Type\":100}"));
+ String[] tab = response.split(Pattern.quote("},"));
+
+ iconUrlList = new HashMap<>();
+ coinList = new HashMap<>();
+
+ for(int i = 0; i < tab.length; i++)
+ {
+ tab[i] = tab[i].substring(tab[i].indexOf("\":{")+2, tab[i].length()) + "}";
+ try {
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);
+ JSONObject jsonObject = new JSONObject(tab[i]);
+
+ iconUrlList.put(jsonObject.getString("Symbol"), "https://www.cryptocompare.com" + jsonObject.getString("ImageUrl") + "?width=50");
+
+ coinList.put(jsonObject.getString("Symbol"), jsonObject.getString("CoinName"));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ callBack.onSuccess();
+ }
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/Currency.java b/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/Currency.java
new file mode 100644
index 0000000..bb3401c
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/Currency.java
@@ -0,0 +1,154 @@
+package com.nauk.coinfolio.DataManagers.CurrencyData;
+
+import android.graphics.Bitmap;
+
+import java.util.List;
+
+/**
+ * Created by Tiji on 25/12/2017.
+ */
+
+public class Currency {
+
+ private String name;
+ private String symbol;
+ private double value;
+ private double balance;
+ private float dayFluctuationPercentage;
+ private double dayFluctuation;
+ private List dayPriceHistory;
+ private CurrencyDataRetriver dataRetriver;
+ private Bitmap icon;
+
+ public Currency(String symbol, double balance)
+ {
+ this.symbol = symbol;
+ this.balance = balance;
+ }
+
+ public Currency(String symbol, String name, double balance)
+ {
+ this.symbol = symbol;
+ this.name = name;
+ this.balance = balance;
+ }
+
+ public Currency(String name, String symbol)
+ {
+ this.name = name;
+ this.symbol = symbol;
+ }
+
+ public void updateDayPriceHistory(android.content.Context context, final CurrencyCallBack callBack)
+ {
+ dataRetriver = new CurrencyDataRetriver(context);
+ dataRetriver.updateLastDayHistory(symbol, new CurrencyDataRetriver.DataChartCallBack() {
+ @Override
+ public void onSuccess(List dataChart) {
+ setDayPriceHistory(dataChart);
+ updateDayFluctuation();
+
+ setValue(dataChart.get(dataChart.size() - 1).getClose());
+
+ callBack.onSuccess(Currency.this);
+ }
+ });
+ }
+
+ public void updateName(android.content.Context context, final CurrencyCallBack callBack)
+ {
+ dataRetriver = new CurrencyDataRetriver(context);
+ dataRetriver.updateCurrencyName(symbol, new CurrencyDataRetriver.NameCallBack() {
+ @Override
+ public void onSuccess(String name) {
+ if(name != null)
+ {
+ setName(name);
+ }
+ else
+ {
+ setName("NameNotFound");
+ }
+
+ callBack.onSuccess(Currency.this);
+ }
+ });
+ }
+
+ public List getDayPriceHistory()
+ {
+ return dayPriceHistory;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String newName)
+ {
+ name = newName;
+ }
+
+ public String getSymbol()
+ {
+ return symbol;
+ }
+
+ public double getValue()
+ {
+ return value;
+ }
+
+ public void setValue(double newValue)
+ {
+ value = newValue;
+ }
+
+ public double getBalance()
+ {
+ return balance;
+ }
+
+ public float getDayFluctuationPercentage()
+ {
+ return dayFluctuationPercentage;
+ }
+
+ public double getDayFluctuation()
+ {
+ return dayFluctuation;
+ }
+
+ public void setBalance(double newBalance)
+ {
+ balance = newBalance;
+ }
+
+ private void setDayPriceHistory(List newDataChart)
+ {
+ dayPriceHistory = newDataChart;
+ }
+
+ public void setIcon(Bitmap newIcon)
+ {
+ icon = newIcon;
+ }
+
+ public Bitmap getIcon()
+ {
+ return icon;
+ }
+
+ private void updateDayFluctuation()
+ {
+ dayFluctuation = dayPriceHistory.get(dayPriceHistory.size() - 1).getOpen() - dayPriceHistory.get(0).getOpen();
+
+ dayFluctuationPercentage = (float) (dayFluctuation / dayPriceHistory.get(0).getOpen() * 100);
+ }
+
+ public interface CurrencyCallBack {
+ void onSuccess(Currency currency);
+ }
+
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/CurrencyDataChart.java b/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/CurrencyDataChart.java
new file mode 100644
index 0000000..df11263
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/CurrencyDataChart.java
@@ -0,0 +1,38 @@
+package com.nauk.coinfolio.DataManagers.CurrencyData;
+
+/**
+ * Created by Tiji on 05/01/2018.
+ */
+
+public class CurrencyDataChart {
+
+ long timestamp;
+ double close;
+ double high;
+ double low;
+ double open;
+
+ public CurrencyDataChart(long timestamp, double close, double high, double low, double open)
+ {
+ this.timestamp = timestamp;
+ this.close = close;
+ this.high = high;
+ this.low = low;
+ this.open = open;
+ }
+
+ public double getOpen()
+ {
+ return open;
+ }
+
+ public double getClose()
+ {
+ return close;
+ }
+
+ public long getTimestamp()
+ {
+ return timestamp;
+ }
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/CurrencyDataRetriver.java b/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/CurrencyDataRetriver.java
new file mode 100644
index 0000000..421e240
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/DataManagers/CurrencyData/CurrencyDataRetriver.java
@@ -0,0 +1,169 @@
+package com.nauk.coinfolio.DataManagers.CurrencyData;
+
+import android.util.Log;
+
+import com.android.volley.Request;
+import com.android.volley.RequestQueue;
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+import com.android.volley.toolbox.StringRequest;
+import com.android.volley.toolbox.Volley;
+import com.nauk.coinfolio.R;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Created by Tiji on 05/01/2018.
+ */
+
+public class CurrencyDataRetriver {
+
+ String minuteHistoryUrl = "https://min-api.cryptocompare.com/data/histominute";
+ String hourHistoryUrl = "https://min-api.cryptocompare.com/data/histohour";
+ String dayHistoryUrl = "https://min-api.cryptocompare.com/data/histoday";
+ String nameUrl = "https://api.hitbtc.com/api/2/public/currency/";
+
+ RequestQueue requestQueue;
+
+ android.content.Context context;
+
+ public CurrencyDataRetriver(android.content.Context context)
+ {
+ this.context = context;
+
+ requestQueue = Volley.newRequestQueue(context);
+ }
+
+ public void updateLastHourHistory(String symbolCurrencyFrom, String symbolCyrrencyTo, final DataChartCallBack callBack)
+ {
+ final String requestUrl = minuteHistoryUrl + "?fsym=" + symbolCurrencyFrom + "&tsym=" + symbolCyrrencyTo + "&limit=60";
+
+ StringRequest stringRequest = new StringRequest(Request.Method.GET, requestUrl,
+ new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ callBack.onSuccess(processHourResult(response));
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+
+ }
+ });
+
+ requestQueue.add(stringRequest);
+ }
+
+ public void updateCurrencyName(String symbol, final NameCallBack callBack)
+ {
+ final String requestUrl = nameUrl + symbol;
+
+ StringRequest stringRequest = new StringRequest(Request.Method.GET, requestUrl,
+ new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ response = response.substring(response.indexOf(",") + 13);
+ response = response.substring(0, response.indexOf(",") - 1);
+
+ callBack.onSuccess(response);
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ callBack.onSuccess(null);
+ }
+ });
+
+ requestQueue.add(stringRequest);
+ }
+
+ public void updateLastDayHistory(String symbolCurrencyFrom, String symbolCyrrencyTo, final DataChartCallBack callBack)
+ {
+ final String requestUrl = minuteHistoryUrl + "?fsym=" + symbolCurrencyFrom + "&tsym=" + symbolCyrrencyTo + "&limit=1440";
+
+ StringRequest stringRequest = new StringRequest(Request.Method.GET, requestUrl,
+ new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ callBack.onSuccess(processHourResult(response));
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+
+ }
+ });
+
+ requestQueue.add(stringRequest);
+ }
+
+ private List processHourResult(String response)
+ {
+ List dataChart = new ArrayList<>();
+
+ response = response.substring(response.indexOf("Data\":[{") + 7, response.lastIndexOf("}],\"TimeTo"));
+ String[] tab = response.split(Pattern.quote("},{"));
+ for(int i = 0; i < tab.length; i++)
+ {
+
+ if(i == 0)
+ {
+ tab[i] = tab[i] + "}";
+ }
+ else
+ {
+ tab[i] = "{" + tab[i] + "}";
+ }
+
+ try {
+ JSONObject jsonObject = new JSONObject(tab[i]);
+
+ long timestamp = Long.parseLong(jsonObject.getString("time"));
+ double close = Double.parseDouble(jsonObject.getString("close"));
+ double high = Double.parseDouble(jsonObject.getString("high"));
+ double low = Double.parseDouble(jsonObject.getString("low"));
+ double open = Double.parseDouble(jsonObject.getString("open"));
+
+ dataChart.add(new CurrencyDataChart(timestamp, close, high, low, open));
+
+ } catch (JSONException e) {
+ Log.d(context.getResources().getString(R.string.debug_volley), "API Request error: " + e + " index: " + i);
+ }
+ }
+
+ return dataChart;
+ }
+
+ public void updateLastHourHistory(String symbolCurrencyFrom, final DataChartCallBack callBack)
+ {
+ updateLastHourHistory(symbolCurrencyFrom, "USD", callBack);
+ }
+
+ public void updateLastDayHistory(String symbolCurrencyFrom, final DataChartCallBack callBack)
+ {
+ if(!symbolCurrencyFrom.equals("USD"))
+ {
+ updateLastDayHistory(symbolCurrencyFrom, "USD", callBack);
+ }
+ }
+
+ public interface DataChartCallBack {
+ void onSuccess(List dataChart);
+ }
+
+ public interface CurrencyDetailCallBack {
+ void onSuccess();
+ }
+
+ public interface NameCallBack {
+ void onSuccess(String name);
+ }
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/DataManagers/DatabaseManager.java b/app/src/main/java/com/nauk/coinfolio/DataManagers/DatabaseManager.java
new file mode 100644
index 0000000..01aa8c6
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/DataManagers/DatabaseManager.java
@@ -0,0 +1,113 @@
+package com.nauk.coinfolio.DataManagers;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Guitoune on 14/01/2018.
+ */
+
+public class DatabaseManager extends SQLiteOpenHelper{
+
+ private static final int DATABASE_VERSION = 4;
+
+ private static final String DATABASE_NAME = "Currencies.db";
+
+ private static final String TABLE_MANUAL_CURRENCIES = "ManualCurrencies";
+ private static final String TABLE_EXCHANGE_KEYS = "ExchangeKeys";
+
+ private static final String KEY_CURRENCY_ID = "idCurrency";
+ private static final String KEY_CURRENCY_SYMBOL = "symbol";
+ private static final String KEY_CURRENCY_NAME = "name";
+ private static final String KEY_CURRENCY_BALANCE = "balance";
+ private static final String KEY_CURRENCY_DATE = "addDate";
+ private static final String KEY_CURRENCY_PURCHASED_PRICE = "purchasedPrice";
+ private static final String KEY_CURRENCY_IS_MINED = "isMined";
+
+ private static final String KEY_EXCHANGE_ID = "idExchange";
+ private static final String KEY_EXCHANGE_NAME = "name";
+ private static final String KEY_EXCHANGE_PUBLIC_KEY = "publicKey";
+ private static final String KEY_EXCHANGE_SECRET_KEY = "secretKey";
+
+ public DatabaseManager(Context context)
+ {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db)
+ {
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_MANUAL_CURRENCIES + "("
+ + KEY_CURRENCY_ID + " INTEGER PRIMARY KEY,"
+ + KEY_CURRENCY_SYMBOL + " VARCHAR(4),"
+ + KEY_CURRENCY_NAME + " VARCHAR(45),"
+ + KEY_CURRENCY_BALANCE + " TEXT,"
+ + KEY_CURRENCY_DATE + " DATE,"
+ + KEY_CURRENCY_PURCHASED_PRICE + " TEXT,"
+ + KEY_CURRENCY_IS_MINED + " INTEGER"
+ + ");");
+
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_EXCHANGE_KEYS + "("
+ + KEY_EXCHANGE_ID + " INTEGER PRIMARY KEY,"
+ + KEY_EXCHANGE_NAME + " TEXT,"
+ + KEY_EXCHANGE_PUBLIC_KEY + " TEXT,"
+ + KEY_EXCHANGE_SECRET_KEY + " TEXT"
+ + ");");
+
+ //loadSample(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
+ {
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_MANUAL_CURRENCIES);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_EXCHANGE_KEYS);
+
+ onCreate(db);
+ }
+
+ public void addCurrencyToManualCurrency(String symbol, double balance)
+ {
+ SQLiteDatabase db = this.getWritableDatabase();
+ ContentValues values = new ContentValues();
+
+ values.put(KEY_CURRENCY_SYMBOL, symbol);
+ values.put(KEY_CURRENCY_BALANCE, balance);
+ //values.put(KEY_CURRENCY_DATE, getDate());
+ //values.put(KEY_CURRENCY_PURCHASED_PRICE, something);
+
+ db.insert(TABLE_MANUAL_CURRENCIES, null, values);
+ db.close();
+ }
+
+ public List getAllCurrencyFromManualCurrency()
+ {
+ String searchQuerry = "SELECT * FROM " + TABLE_MANUAL_CURRENCIES;
+ SQLiteDatabase db = this.getWritableDatabase();
+ Cursor resultatList = db.rawQuery(searchQuerry, null);
+
+ List currencyList = new ArrayList<>();
+
+ while(resultatList.moveToNext())
+ {
+ //Currency currency = new Currency(resultatList.getString(1), resultatList.getString(2));
+ Log.d("CrystalVault", "Database result : " + resultatList.getString(1) + " " + resultatList.getString(2) + " " + resultatList.getCount());
+ //currencyList.add(new Currency(resultatList.getString(1), resultatList.getDouble(2)));
+ }
+
+ resultatList.close();
+
+ db.close();
+
+ return currencyList;
+ }
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/DataManagers/PreferencesManager.java b/app/src/main/java/com/nauk/coinfolio/DataManagers/PreferencesManager.java
new file mode 100644
index 0000000..be1fb1b
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/DataManagers/PreferencesManager.java
@@ -0,0 +1,68 @@
+package com.nauk.coinfolio.DataManagers;
+
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+/**
+ * Created by Guitoune on 09/01/2018.
+ */
+
+public class PreferencesManager {
+
+ private static final String currencyListFile = "CustomCurrencies";
+ private static final String preferencesFile = "Preferences";
+ private SharedPreferences settingPreferences;
+ private SharedPreferences currencyList;
+ private SharedPreferences preferencesList;
+ android.content.Context context;
+
+ public PreferencesManager(android.content.Context context)
+ {
+ this.context = context;
+ settingPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+ currencyList = context.getSharedPreferences(currencyListFile, 0);
+ preferencesList = context.getSharedPreferences(preferencesFile, 0);
+ }
+
+ public void addCurrency(String symbol, double balance)
+ {
+ SharedPreferences.Editor editor = currencyList.edit();
+ editor.putString(symbol, String.valueOf(balance));
+ editor.apply();
+ }
+
+ public void setDetailOption(boolean isExtended)
+ {
+ SharedPreferences.Editor editor = preferencesList.edit();
+ editor.putBoolean("DetailOption", isExtended);
+ editor.apply();
+ }
+
+ public boolean getDetailOption()
+ {
+ return preferencesList.getBoolean("DetailOption", true);
+ }
+
+ public String getHitBTCPublicKey()
+ {
+ return settingPreferences.getString("hitbtc_publickey", null);
+ }
+
+ public String getHitBTCPrivateKey()
+ {
+ return settingPreferences.getString("hitbtc_privatekey", null);
+ }
+
+ public boolean isHitBTCActivated()
+ {
+ return settingPreferences.getBoolean("enable_hitbtc", false);
+ }
+
+ public void disableHitBTC()
+ {
+ SharedPreferences.Editor editor = settingPreferences.edit();
+ editor.putBoolean("enable_hitbtc", false);
+ editor.apply();
+ }
+
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/LayoutManagers/CurrencyAdapter.java b/app/src/main/java/com/nauk/coinfolio/LayoutManagers/CurrencyAdapter.java
new file mode 100644
index 0000000..fda78eb
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/LayoutManagers/CurrencyAdapter.java
@@ -0,0 +1,104 @@
+package com.nauk.coinfolio.LayoutManagers;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.Filter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
+import com.nauk.coinfolio.R;
+
+/**
+ * Created by Guitoune on 17/01/2018.
+ */
+
+public class CurrencyAdapter extends ArrayAdapter {
+
+ private ArrayList Currencys, tempCurrency, suggestions;
+ private Context context;
+
+ public CurrencyAdapter(Context context, ArrayList objects) {
+ super(context, android.R.layout.simple_list_item_1, objects);
+ this.Currencys = objects;
+ this.tempCurrency = new ArrayList(objects);
+ this.suggestions = new ArrayList(objects);
+
+ this.context = context;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ Currency currency = getItem(position);
+ if (convertView == null) {
+ convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom_row, parent, false);
+ }
+ TextView currencyName = (TextView) convertView.findViewById(R.id.currencyName);
+ TextView currencySymbol = (TextView) convertView.findViewById(R.id.currencySymbol);
+ if (currencyName != null)
+ currencyName.setText(currency.getName());
+ if(currencySymbol != null)
+ {
+ currencySymbol.setText(currency.getSymbol());
+ }
+ // Now assign alternate color for rows
+ if (position % 2 == 0)
+ convertView.setBackgroundColor(context.getResources().getColor(R.color.listBackground));
+ else
+ convertView.setBackgroundColor(context.getResources().getColor(R.color.listBackground2));
+
+ return convertView;
+ }
+
+
+ @Override
+ public Filter getFilter() {
+ return myFilter;
+ }
+
+ Filter myFilter = new Filter() {
+ @Override
+ public CharSequence convertResultToString(Object resultValue) {
+ Currency currency = (Currency) resultValue;
+ return currency.getName();
+ }
+
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+ if (constraint != null) {
+ suggestions.clear();
+
+ String temp = constraint.toString().toLowerCase();
+ for (Currency currency : tempCurrency) {
+ if (currency.getName().toLowerCase().startsWith(temp)
+ || currency.getSymbol().toLowerCase().startsWith(temp)) {
+ suggestions.add(currency);
+ }
+ }
+
+ FilterResults filterResults = new FilterResults();
+ filterResults.values = suggestions;
+ filterResults.count = suggestions.size();
+ return filterResults;
+ } else {
+ return new FilterResults();
+ }
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint, FilterResults results) {
+ ArrayList c = (ArrayList) results.values;
+ if (results != null && results.count > 0) {
+ clear();
+ for (Currency currency : c) {
+ add(currency);
+ notifyDataSetChanged();
+ }
+ }
+ }
+ };
+}
diff --git a/app/src/main/java/com/nauk/coinfolio/LayoutManagers/HomeLayoutGenerator.java b/app/src/main/java/com/nauk/coinfolio/LayoutManagers/HomeLayoutGenerator.java
new file mode 100644
index 0000000..591a9ae
--- /dev/null
+++ b/app/src/main/java/com/nauk/coinfolio/LayoutManagers/HomeLayoutGenerator.java
@@ -0,0 +1,334 @@
+package com.nauk.coinfolio.LayoutManagers;
+
+import android.animation.AnimatorInflater;
+import android.animation.StateListAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.support.design.widget.Snackbar;
+import android.support.v7.widget.CardView;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.db.chart.model.LineSet;
+import com.db.chart.renderer.AxisRenderer;
+import com.db.chart.view.LineChartView;
+import com.nauk.coinfolio.DataManagers.CurrencyData.Currency;
+import com.nauk.coinfolio.DataManagers.CurrencyData.CurrencyDataChart;
+import com.nauk.coinfolio.R;
+
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+
+import static java.lang.Math.abs;
+
+/**
+ * Created by Tiji on 05/01/2018.
+ */
+
+public class HomeLayoutGenerator {
+
+ android.content.Context context;
+
+ public HomeLayoutGenerator(Context context)
+ {
+ this.context = context;
+ }
+
+ public CardView getInfoLayout(Currency currency, int chartColor)
+ {
+ CardView mainCard = new CardView(context);
+ LinearLayout mainLinear = new LinearLayout(context);
+ View separationLine = new View(context);
+ LinearLayout chartLayout = new LinearLayout(context);
+ LinearLayout infoLayout = new LinearLayout(context);
+ LinearLayout separatorLayout = new LinearLayout(context);
+ TextView separatorTextView = new TextView(context);
+
+ StateListAnimator stateListAnimator = AnimatorInflater.loadStateListAnimator(context, R.drawable.cardview_animator);
+ mainCard.setStateListAnimator(stateListAnimator);
+
+ /*int[] attrs = new int[] { R.attr.selectableItemBackground };
+ TypedArray ta = context.obtainStyledAttributes(attrs);
+ Drawable drawable = ta.getDrawable(0);
+ ta.recycle();
+
+ mainCard.setBackground(drawable);*/
+
+ mainCard.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ view.animate();
+ Snackbar.make(view, "This feature is not yet available...", Snackbar.LENGTH_LONG)
+ .show();
+ }
+ });
+ mainCard.setClickable(true);
+
+ CardView.LayoutParams paramsCard = new CardView.LayoutParams(CardView.LayoutParams.MATCH_PARENT, CardView.LayoutParams.WRAP_CONTENT);
+ paramsCard.setMargins(10, 10, 10, 30);
+
+ LinearLayout.LayoutParams paramsInfo = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ paramsInfo.setMargins(10, 10, 10, 10);
+
+ chartLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ LinearLayout.LayoutParams separatorParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 3);
+ separatorParams.gravity = Gravity.CENTER_VERTICAL;
+ separatorParams.setMargins(10, 0, 10, 0);
+
+ separationLine.setLayoutParams(separatorParams);
+ separationLine.setBackgroundColor(context.getResources().getColor(R.color.separationLine));
+
+ LinearLayout.LayoutParams separatorLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ separatorLayoutParams.setMargins(10, 0, 10, 0);
+ separatorLayout.setLayoutParams(separatorLayoutParams);
+
+ separatorTextView.setText("Day history");
+ separatorTextView.setTextSize(context.getResources().getDimension(R.dimen.secondaryText));
+
+ separatorLayout.addView(separatorTextView);
+ separatorLayout.addView(separationLine);
+ separatorLayout.setTag("separator_layout");
+
+ infoLayout.setLayoutParams(paramsInfo);
+ infoLayout.setOrientation(LinearLayout.VERTICAL);
+
+ mainLinear.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ mainLinear.setOrientation(LinearLayout.VERTICAL);
+
+ mainCard.setLayoutParams(paramsCard);
+ mainCard.setRadius(8);
+
+ infoLayout.addView(topLayoutGenerator(currency.getName(), currency.getSymbol(), currency.getValue(), currency.getIcon()));
+ infoLayout.addView(bottomLayoutGenerator(currency.getSymbol(), currency.getBalance(), currency.getValue() * currency.getBalance(), currency.getDayFluctuationPercentage(), currency.getDayFluctuation()));
+
+ mainLinear.addView(infoLayout);
+
+ LineChartView lineChartView = chartGenerator(currency.getDayPriceHistory(), chartColor);
+ chartLayout.setTag("chart_layout");
+ chartLayout.addView(lineChartView);
+ lineChartView.show();
+ mainLinear.addView(separatorLayout);
+ mainLinear.addView(chartLayout);
+
+ mainCard.addView(mainLinear);
+
+ return mainCard;
+ }
+
+ private LinearLayout topLayoutGenerator(String name, String symbol, double value, Bitmap logo)
+ {
+ LinearLayout mainLayout = new LinearLayout(context);
+ TextView nameTextView = new TextView(context);
+ TextView symbolTextView = new TextView(context);
+ TextView valueTextView = new TextView(context);
+ ImageView currencyIcon = new ImageView(context);
+
+ mainLayout.setOrientation(LinearLayout.HORIZONTAL);
+ mainLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ iconParams.setMargins(5, 5, 5, 5);
+ currencyIcon.setLayoutParams(iconParams);
+ currencyIcon.setImageBitmap(logo);
+
+ nameTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ nameTextView.setTextSize(context.getResources().getDimension(R.dimen.mainText));
+ nameTextView.setTextColor(context.getResources().getColor(R.color.mainTextViewColor));
+ nameTextView.setGravity(Gravity.LEFT);
+ nameTextView.setText(name);
+
+ symbolTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ symbolTextView.setTextSize(context.getResources().getDimension(R.dimen.secondaryText));
+ symbolTextView.setTextColor(context.getResources().getColor(R.color.secondaryTextViewColor));
+ symbolTextView.setGravity(Gravity.LEFT);
+ symbolTextView.setText(" (" + symbol + ")");
+
+ valueTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ valueTextView.setTextSize(context.getResources().getDimension(R.dimen.mainText));
+ valueTextView.setTextColor(context.getResources().getColor(R.color.secondaryTextViewColor));
+ valueTextView.setGravity(Gravity.RIGHT);
+ valueTextView.setText("US$" + value);
+
+ mainLayout.addView(currencyIcon);
+ mainLayout.addView(nameTextView);
+ mainLayout.addView(symbolTextView);
+ mainLayout.addView(valueTextView);
+
+ return mainLayout;
+ }
+
+ private LinearLayout bottomLayoutGenerator(String symbol, double owned, double value, float percentageFluctuation, double fluctuation)
+ {
+ LinearLayout mainLayout = new LinearLayout(context);
+ LinearLayout secondaryLayout = new LinearLayout(context);
+ TextView ownedTextView = new TextView(context);
+ TextView valueTextView = new TextView(context);
+ TextView percentageFluctuationTextView = new TextView(context);
+ TextView fluctuationTextView = new TextView(context);
+
+ mainLayout.setOrientation(LinearLayout.HORIZONTAL);
+ mainLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ secondaryLayout.setOrientation(LinearLayout.HORIZONTAL);
+ secondaryLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ secondaryLayout.setGravity(Gravity.RIGHT);
+
+ ownedTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ ownedTextView.setTextSize(context.getResources().getDimension(R.dimen.mainText));
+ ownedTextView.setTextColor(context.getResources().getColor(R.color.mainTextViewColor));
+ ownedTextView.setGravity(Gravity.LEFT);
+ ownedTextView.setText(numberConformer(owned) + symbol);
+
+ valueTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ valueTextView.setTextSize(context.getResources().getDimension(R.dimen.secondaryText));
+ valueTextView.setTextColor(context.getResources().getColor(R.color.secondaryTextViewColor));
+ valueTextView.setGravity(Gravity.LEFT);
+ valueTextView.setText(" (" + numberConformer(value) + "$)");
+
+ percentageFluctuationTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ percentageFluctuationTextView.setTextSize(context.getResources().getDimension(R.dimen.mainText));
+ if(percentageFluctuation > 0)
+ {
+ percentageFluctuationTextView.setTextColor(context.getResources().getColor(R.color.increase));
+ }
+ else
+ {
+ percentageFluctuationTextView.setTextColor(context.getResources().getColor(R.color.decrease));
+ }
+ //percentageFluctuationTextView.setGravity(Gravity.RIGHT);
+ percentageFluctuationTextView.setText(numberConformer(percentageFluctuation) + "%");
+
+ fluctuationTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ fluctuationTextView.setTextSize(context.getResources().getDimension(R.dimen.secondaryText));
+ if(fluctuation > 0)
+ {
+ fluctuationTextView.setTextColor(context.getResources().getColor(R.color.increase));
+ }
+ else
+ {
+ fluctuationTextView.setTextColor(context.getResources().getColor(R.color.decrease));
+ }
+ //fluctuationTextView.setGravity(Gravity.RIGHT);
+ fluctuationTextView.setText(" (" + numberConformer(fluctuation) + "$)");
+
+ secondaryLayout.addView(percentageFluctuationTextView);
+ secondaryLayout.addView(fluctuationTextView);
+
+ mainLayout.addView(ownedTextView);
+ mainLayout.addView(valueTextView);
+ mainLayout.addView(secondaryLayout);
+ //mainLayout.addView(percentageFluctuationTextView);
+ //mainLayout.addView(fluctuationTextView);
+
+ return mainLayout;
+ }
+
+ private LineChartView chartGenerator(List dataChartList, int chartColor)
+ {
+ LineChartView chartView = new LineChartView(context);
+ LineSet lineSet = new LineSet();
+ double valMin;
+ double valMax;
+ int counter = 0;
+ Calendar calendar = Calendar.getInstance(Locale.FRANCE);
+ String hour;
+ String minute;
+
+ valMin = dataChartList.get(0).getOpen();
+ valMax = dataChartList.get(0).getOpen();
+ for(int i = 1; i < dataChartList.size(); i++)
+ {
+ if(valMax < dataChartList.get(i).getOpen())
+ {
+ valMax = dataChartList.get(i).getOpen();
+ }
+
+ if(valMin > dataChartList.get(i).getOpen())
+ {
+ valMin = dataChartList.get(i).getOpen();
+ }
+ }
+
+ chartView.setAxisBorderValues((float) valMin, (float) valMax);
+ chartView.setYLabels(AxisRenderer.LabelPosition.NONE);
+ chartView.setYAxis(false);
+ chartView.setXAxis(false);
+
+ for(int i = 0; i < dataChartList.size(); i+=10)
+ {
+ if(counter == 30)
+ {
+ calendar.setTimeInMillis(dataChartList.get(i).getTimestamp()*1000);
+
+ hour = String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
+ minute = String.valueOf(calendar.get(Calendar.MINUTE));
+
+ if(hour.length() < 2)
+ {
+ hour = "0" + hour;
+ }
+
+ if(minute.length() < 2)
+ {
+ minute = "0" + minute;
+ }
+
+ lineSet.addPoint(hour + ":" + minute, (float) dataChartList.get(i).getOpen());
+ counter = 0;
+ }
+ else
+ {
+ counter++;
+ lineSet.addPoint("", (float) dataChartList.get(i).getOpen());
+ }
+
+
+ }
+
+ lineSet.setSmooth(true);
+ lineSet.setThickness(4);
+ lineSet.setFill(getColorWithAplha(chartColor, 0.5f));
+ lineSet.setColor(chartColor);
+
+ chartView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 500));
+
+ chartView.setTag("Chart");
+
+ chartView.addData(lineSet);
+
+ return chartView;
+ }
+
+ private int getColorWithAplha(int color, float ratio)
+ {
+ int transColor;
+ int alpha = Math.round(Color.alpha(color) * ratio);
+ int r = Color.red(color);
+ int g = Color.green(color);
+ int b = Color.blue(color);
+ transColor = Color.argb(alpha, r, g, b);
+ return transColor ;
+ }
+
+ private String numberConformer(double number)
+ {
+ String str;
+
+ if(abs(number) > 1)
+ {
+ str = String.format("%.2f", number);
+ }
+ else
+ {
+ str = String.format("%.4f", number);
+ }
+
+ return str;
+ }
+}
diff --git a/app/src/main/res/anim/fade_in_dialog.xml b/app/src/main/res/anim/fade_in_dialog.xml
new file mode 100644
index 0000000..05d2699
--- /dev/null
+++ b/app/src/main/res/anim/fade_in_dialog.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/fade_out_dialog.xml b/app/src/main/res/anim/fade_out_dialog.xml
new file mode 100644
index 0000000..979ccb4
--- /dev/null
+++ b/app/src/main/res/anim/fade_out_dialog.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/zoom_in.xml b/app/src/main/res/anim/zoom_in.xml
new file mode 100644
index 0000000..3272b05
--- /dev/null
+++ b/app/src/main/res/anim/zoom_in.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/zoom_out.xml b/app/src/main/res/anim/zoom_out.xml
new file mode 100644
index 0000000..52dbe8c
--- /dev/null
+++ b/app/src/main/res/anim/zoom_out.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/cardview_animator.xml b/app/src/main/res/drawable/cardview_animator.xml
new file mode 100644
index 0000000..7306f5c
--- /dev/null
+++ b/app/src/main/res/drawable/cardview_animator.xml
@@ -0,0 +1,16 @@
+
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/crystal_background.xml b/app/src/main/res/drawable/crystal_background.xml
new file mode 100644
index 0000000..5b604b8
--- /dev/null
+++ b/app/src/main/res/drawable/crystal_background.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/crystal_cave.png b/app/src/main/res/drawable/crystal_cave.png
new file mode 100644
index 0000000..ac3b31c
Binary files /dev/null and b/app/src/main/res/drawable/crystal_cave.png differ
diff --git a/app/src/main/res/drawable/gradient_background.xml b/app/src/main/res/drawable/gradient_background.xml
new file mode 100644
index 0000000..fae6990
--- /dev/null
+++ b/app/src/main/res/drawable/gradient_background.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/gradient_button.xml b/app/src/main/res/drawable/gradient_button.xml
new file mode 100644
index 0000000..dae2bff
--- /dev/null
+++ b/app/src/main/res/drawable/gradient_button.xml
@@ -0,0 +1,18 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_add_black_24dp.xml b/app/src/main/res/drawable/ic_add_black_24dp.xml
new file mode 100644
index 0000000..0258249
--- /dev/null
+++ b/app/src/main/res/drawable/ic_add_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_chevron_right_black_24dp.xml b/app/src/main/res/drawable/ic_chevron_right_black_24dp.xml
new file mode 100644
index 0000000..2483512
--- /dev/null
+++ b/app/src/main/res/drawable/ic_chevron_right_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_details_black_24dp.xml b/app/src/main/res/drawable/ic_details_black_24dp.xml
new file mode 100644
index 0000000..573bdb5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_details_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_developer_board_black_24dp.xml b/app/src/main/res/drawable/ic_developer_board_black_24dp.xml
new file mode 100644
index 0000000..27d3805
--- /dev/null
+++ b/app/src/main/res/drawable/ic_developer_board_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_info_black_24dp.xml b/app/src/main/res/drawable/ic_info_black_24dp.xml
new file mode 100644
index 0000000..34b8202
--- /dev/null
+++ b/app/src/main/res/drawable/ic_info_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..d5fccc5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/app/src/main/res/drawable/ic_notifications_black_24dp.xml
new file mode 100644
index 0000000..e3400cf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_notifications_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_settings_black_24dp.xml b/app/src/main/res/drawable/ic_settings_black_24dp.xml
new file mode 100644
index 0000000..dd6cf1c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_settings_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_sync_black_24dp.xml b/app/src/main/res/drawable/ic_sync_black_24dp.xml
new file mode 100644
index 0000000..5a283aa
--- /dev/null
+++ b/app/src/main/res/drawable/ic_sync_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_unfold_less_black_24dp.xml b/app/src/main/res/drawable/ic_unfold_less_black_24dp.xml
new file mode 100644
index 0000000..1be5b9b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_unfold_less_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/icon_crystalvault_background.xml b/app/src/main/res/drawable/icon_crystalvault_background.xml
new file mode 100644
index 0000000..01f0af0
--- /dev/null
+++ b/app/src/main/res/drawable/icon_crystalvault_background.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ripple_animation.xml b/app/src/main/res/drawable/ripple_animation.xml
new file mode 100644
index 0000000..289d7e6
--- /dev/null
+++ b/app/src/main/res/drawable/ripple_animation.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_corners.xml b/app/src/main/res/drawable/rounded_corners.xml
new file mode 100644
index 0000000..6f1db34
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_corners.xml
@@ -0,0 +1,15 @@
+
+
+ -
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/soft_gradient.xml b/app/src/main/res/drawable/soft_gradient.xml
new file mode 100644
index 0000000..590cad2
--- /dev/null
+++ b/app/src/main/res/drawable/soft_gradient.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_add_currency.xml b/app/src/main/res/layout/activity_add_currency.xml
new file mode 100644
index 0000000..00488bf
--- /dev/null
+++ b/app/src/main/res/layout/activity_add_currency.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_currency_summary.xml b/app/src/main/res/layout/activity_currency_summary.xml
new file mode 100644
index 0000000..764889a
--- /dev/null
+++ b/app/src/main/res/layout/activity_currency_summary.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_record_transaction.xml b/app/src/main/res/layout/activity_record_transaction.xml
new file mode 100644
index 0000000..1509b01
--- /dev/null
+++ b/app/src/main/res/layout/activity_record_transaction.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/content_currency_summary.xml b/app/src/main/res/layout/content_currency_summary.xml
new file mode 100644
index 0000000..df4ee54
--- /dev/null
+++ b/app/src/main/res/layout/content_currency_summary.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/custom_row.xml b/app/src/main/res/layout/custom_row.xml
new file mode 100644
index 0000000..2329b3c
--- /dev/null
+++ b/app/src/main/res/layout/custom_row.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/textview_autocompletion.xml b/app/src/main/res/layout/textview_autocompletion.xml
new file mode 100644
index 0000000..2de6c2c
--- /dev/null
+++ b/app/src/main/res/layout/textview_autocompletion.xml
@@ -0,0 +1,10 @@
+
diff --git a/app/src/main/res/menu/search_inflater.xml b/app/src/main/res/menu/search_inflater.xml
new file mode 100644
index 0000000..b754f62
--- /dev/null
+++ b/app/src/main/res/menu/search_inflater.xml
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/icon_crystalvault.xml b/app/src/main/res/mipmap-anydpi-v26/icon_crystalvault.xml
new file mode 100644
index 0000000..4a0745c
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/icon_crystalvault.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/icon_crystalvault_round.xml b/app/src/main/res/mipmap-anydpi-v26/icon_crystalvault_round.xml
new file mode 100644
index 0000000..4a0745c
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/icon_crystalvault_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a2f5908
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1b52399
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_crystalvault.png b/app/src/main/res/mipmap-hdpi/icon_crystalvault.png
new file mode 100644
index 0000000..b1ce2a5
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_crystalvault.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_crystalvault_foreground.png b/app/src/main/res/mipmap-hdpi/icon_crystalvault_foreground.png
new file mode 100644
index 0000000..499c869
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_crystalvault_foreground.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icon_crystalvault_round.png b/app/src/main/res/mipmap-hdpi/icon_crystalvault_round.png
new file mode 100644
index 0000000..7b0e948
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon_crystalvault_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ff10afd
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..115a4c7
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_crystalvault.png b/app/src/main/res/mipmap-mdpi/icon_crystalvault.png
new file mode 100644
index 0000000..37b56d4
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_crystalvault.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_crystalvault_foreground.png b/app/src/main/res/mipmap-mdpi/icon_crystalvault_foreground.png
new file mode 100644
index 0000000..18590bf
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_crystalvault_foreground.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_crystalvault_round.png b/app/src/main/res/mipmap-mdpi/icon_crystalvault_round.png
new file mode 100644
index 0000000..6ec6114
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_crystalvault_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..dcd3cd8
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..459ca60
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_crystalvault.png b/app/src/main/res/mipmap-xhdpi/icon_crystalvault.png
new file mode 100644
index 0000000..3f9e88f
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_crystalvault.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_crystalvault_foreground.png b/app/src/main/res/mipmap-xhdpi/icon_crystalvault_foreground.png
new file mode 100644
index 0000000..1d876e0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_crystalvault_foreground.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_crystalvault_round.png b/app/src/main/res/mipmap-xhdpi/icon_crystalvault_round.png
new file mode 100644
index 0000000..49f84dc
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_crystalvault_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8ca12fe
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..8e19b41
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_crystalvault.png b/app/src/main/res/mipmap-xxhdpi/icon_crystalvault.png
new file mode 100644
index 0000000..cf6f0d1
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_crystalvault.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_crystalvault_foreground.png b/app/src/main/res/mipmap-xxhdpi/icon_crystalvault_foreground.png
new file mode 100644
index 0000000..85ce1a7
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_crystalvault_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_crystalvault_round.png b/app/src/main/res/mipmap-xxhdpi/icon_crystalvault_round.png
new file mode 100644
index 0000000..09d9fa6
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_crystalvault_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b824ebd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..4c19a13
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault.png b/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault.png
new file mode 100644
index 0000000..98c253c
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault_foreground.png b/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault_foreground.png
new file mode 100644
index 0000000..c89f9b2
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault_round.png b/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault_round.png
new file mode 100644
index 0000000..1e61b8e
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icon_crystalvault_round.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..991f12c
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,14 @@
+
+
+ #000046
+ #111124
+ #1CB5E0
+ #FF000000
+ #FF222222
+ #00000000
+ #FFED143D
+ #FF00E000
+ #FFEEEEEE
+ #FFFFFFFF
+ #FF999999
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..72b40bd
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,7 @@
+
+ 180dp
+ 16dp
+ 16dp
+ 6dp
+ 5dp
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..6198ca5
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,119 @@
+
+ Coinfolio
+ Settings
+ Fais un don wallah
+ CrystalVault_debug
+ CrystalVault_debugVolley
+ Switch view
+ Settings
+
+
+
+
+ General
+
+ Enable social recommendations
+ Recommendations for people to contact
+ based on your message history
+
+
+ Display name
+ John Smith
+
+ Add friends to messages
+
+ - Always
+ - When possible
+ - Never
+
+
+ - 1
+ - 0
+ - -1
+
+
+
+ Data & sync
+
+ Sync frequency
+
+ - 15 minutes
+ - 30 minutes
+ - 1 hour
+ - 3 hours
+ - 6 hours
+ - Never
+
+
+ - 15
+ - 30
+ - 60
+ - 180
+ - 360
+ - -1
+
+
+
+ - Entry 1
+ - Entry 2
+ - Entry 3
+
+
+
+ - 1
+ - 2
+ - 3
+
+
+
+
+ System sync settings
+
+
+ Notifications
+
+ New message notifications
+
+ Ringtone
+ Silent
+
+ Vibrate
+
+
+
+ Exchanges settings
+
+
+ Enable synchronization
+ Public key
+ Private key
+ HitBTC
+
+
+ Enable synchronization
+ Public key
+ Private key
+ GDAX
+
+
+ Enable synchronization
+ Public key
+ Private key
+ Binance
+
+
+ Enable synchronization
+ Public key
+ Private key
+ Poloniex
+
+
+ Enable synchronization
+ Public key
+ Private key
+ Kraken
+
+
+ Amount
+ Purchased prive
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..679f95f
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/pref_data_sync.xml b/app/src/main/res/xml/pref_data_sync.xml
new file mode 100644
index 0000000..6bd9192
--- /dev/null
+++ b/app/src/main/res/xml/pref_data_sync.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/pref_exchange.xml b/app/src/main/res/xml/pref_exchange.xml
new file mode 100644
index 0000000..8bb55d2
--- /dev/null
+++ b/app/src/main/res/xml/pref_exchange.xml
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml
new file mode 100644
index 0000000..36569d6
--- /dev/null
+++ b/app/src/main/res/xml/pref_general.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/pref_headers.xml b/app/src/main/res/xml/pref_headers.xml
new file mode 100644
index 0000000..5ca4a5f
--- /dev/null
+++ b/app/src/main/res/xml/pref_headers.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/pref_notification.xml b/app/src/main/res/xml/pref_notification.xml
new file mode 100644
index 0000000..e5a319e
--- /dev/null
+++ b/app/src/main/res/xml/pref_notification.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/test/java/com/nauk/coinfolio/ExampleUnitTest.java b/app/src/test/java/com/nauk/coinfolio/ExampleUnitTest.java
new file mode 100644
index 0000000..ebb36e7
--- /dev/null
+++ b/app/src/test/java/com/nauk/coinfolio/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.nauk.coinfolio;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..e6b32bc
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,27 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.0.1'
+
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..aac7c9b
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..7bf5f5c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 25 21:39:15 CET 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/library/Binance/.gitignore b/library/Binance/.gitignore
new file mode 100644
index 0000000..c8e0416
--- /dev/null
+++ b/library/Binance/.gitignore
@@ -0,0 +1,131 @@
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+# https://github.com/github/gitignore/blob/master/Scala.gitignore
+*.class
+*.log
+
+# sbt specific
+.cache
+.history
+.lib/
+dist/*
+target/
+lib_managed/
+src_managed/
+project/boot/
+project/plugins/project/
+
+# Scala-IDE specific
+.scala_dependencies
+.worksheet
+
+**/.cache-main
+
+# https://github.com/github/gitignore/blob/master/Global/Eclipse.gitignore
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+# Eclipse Core
+.project
+.classpath
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# JDT-specific (Eclipse Java Development Tools)
+**/.classpath
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# IntelliJ
+.idea
+*.iml
+
+# Mongo Explorer plugin:
+.idea/mongoSettings.xml
+
+## File-based project format:
+*.iws
+
+## Plugin-specific files:
+
+# IntelliJ
+/out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# https://github.com/github/gitignore/blob/master/Maven.gitignore
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+
+# test
+test-output
\ No newline at end of file
diff --git a/library/Binance/CONTRIBUTING.md b/library/Binance/CONTRIBUTING.md
new file mode 100644
index 0000000..3f682e1
--- /dev/null
+++ b/library/Binance/CONTRIBUTING.md
@@ -0,0 +1,92 @@
+# Contributing
+
+When contributing to this repository, please first discuss the change you wish to make via issue,
+email, or any other method with the owners of this repository before making a change.
+
+Please note we have a code of conduct, please follow it in all your interactions with the project.
+
+## Pull Request Process
+
+1. Ensure any install or build dependencies are removed before the end of the layer when doing a
+ build.
+2. Update the README.md with details of changes to the interface, this includes new environment
+ variables, exposed ports, useful file locations and container parameters.
+3. Increase the version numbers in any examples files and the README.md to the new version that this
+ Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
+4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
+ do not have permission to do that, you may request the second reviewer to merge it for you.
+
+## Code of Conduct
+
+### Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+### Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+### Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+### Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+### Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+### Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
\ No newline at end of file
diff --git a/library/Binance/README.md b/library/Binance/README.md
new file mode 100644
index 0000000..83694d0
--- /dev/null
+++ b/library/Binance/README.md
@@ -0,0 +1,107 @@
+# Java client for [Binance API](https://www.binance.com/restapipub.html)
+
+## Synopsis
+Client for accessing Binance API using Java. An [async](src/main/java/com/github/johnsiu/binance/httpclients/AsyncBinanceClient.java) and a [sync](src/main/java/com/github/johnsiu/binance/httpclients/BinanceClient.java) versions of the client are available.
+
+## Installation
+
+Add the bintray repo to the pom of your maven project:
+
+```xml
+
+
+ bintray-johnsiu-maven-repo
+ https://dl.bintray.com/johnsiu/maven-repo
+
+
+ ```
+then, add the dependency:
+```xml
+
+ com.github.johnsiu
+ binance-java-client
+ 1.0.1
+
+ ```
+
+## Usage
+
+### Creating an instance of the async client using Guice
+```java
+ Injector injector = Guice.createInjector(new BinanceClientModule());
+ AsyncBinanceClient asyncClient = injector.getInstance(AsyncBinanceClient.class);
+```
+### Creating an instance of the sync client using Guice
+```java
+ Injector injector = Guice.createInjector(new BinanceClientModule());
+ BinanceClient client = injector.getInstance(BinanceClient.class);
+```
+
+### Getting latest price of a symbol
+```java
+ Ticker ticker = client.getTicker("ETHBTC"));
+ double price = ticker.getLastPrice();
+```
+### Getting depth of a symbol
+```java
+ Depth depth = client.getDepth("ETHBTC"));
+```
+### Placing a LIMIT order
+```java
+ Keys keys = new Keys("YOUR_API_KEY", "YOUR_SECRET_KEY");
+ double quantity = 1;
+ double price = 0.020041;
+ Order order = client.placeLimitOrder(keys, "MCOETH", OrderSide.BUY, TimeInForce.GTC, quantity, price);
+```
+
+### Placing a MARKET order
+```java
+ double quantity = 1;
+ Order order = client.placeMarketOrder(keys, "MCOETH", OrderSide.SELL, quantity);
+```
+### Checking an order’s status
+```java
+ OrderStatus orderStatus = client.checkOrderStatus(keys, order);
+```
+
+### Cancelling an order
+```java
+ CancelOrder cancelOrder = client.cancelOrder(keys, order);
+ // or
+ CancelOrder cancelOrder = client.cancelOrder(keys, orderStatus);
+
+```
+
+### Getting a list of open orders
+```java
+ List openOrders = client.getOpenOrders(keys, "MCOETH");
+```
+
+### Getting a list of current position
+```java
+ Account account = client.getAccount(keys);
+ Map balances = account.getBalances();
+```
+
+### Exception handling
+```java
+ try {
+ Depth depth = client.getDepth("invalid symbol"));
+ } catch (ClientErrorException e) {
+ int httpStatusCode = e.getHttpStatusCode();
+ String errorCode = e.getErrorDetails().getCode();
+ String errorMessage = e.getErrorDetails().getMsg();
+ }
+```
+
+## Contributing
+
+Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
+
+## Versioning
+
+We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/johnsiu/binance-java-client/tags).
+
+## License
+
+This project is released into the public domain - see the [UNLICENSE](UNLICENSE) file for details.
\ No newline at end of file
diff --git a/library/Binance/UNLICENSE b/library/Binance/UNLICENSE
new file mode 100644
index 0000000..00d2e13
--- /dev/null
+++ b/library/Binance/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
\ No newline at end of file
diff --git a/library/Binance/pom.xml b/library/Binance/pom.xml
new file mode 100644
index 0000000..3a4fbc9
--- /dev/null
+++ b/library/Binance/pom.xml
@@ -0,0 +1,83 @@
+
+
+ 4.0.0
+
+ com.github.johnsiu
+ binance-java-client
+ 1.0.1
+
+
+ 2.9.1
+
+
+
+
+ bintray-repo-binance-java-client
+ https://api.bintray.com/maven/johnsiu/maven-repo/binance-java-client/;publish=1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+ verify
+
+ jar-no-fork
+
+
+
+
+
+
+
+
+
+ org.asynchttpclient
+ async-http-client
+ 2.0.37
+
+
+ com.google.guava
+ guava
+ 23.1-jre
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson-version}
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson-version}
+
+
+ com.google.inject
+ guice
+ 4.1.0
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
\ No newline at end of file
diff --git a/library/Binance/src/main/java/com/github/johnsiu/binance/deser/BalanceMapDeserializer.java b/library/Binance/src/main/java/com/github/johnsiu/binance/deser/BalanceMapDeserializer.java
new file mode 100644
index 0000000..688115b
--- /dev/null
+++ b/library/Binance/src/main/java/com/github/johnsiu/binance/deser/BalanceMapDeserializer.java
@@ -0,0 +1,29 @@
+package com.github.johnsiu.binance.deser;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.github.johnsiu.binance.models.Account.Balance;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Jackson deserializer for turning an array of balances into a map of asset to balance.
+ */
+public class BalanceMapDeserializer extends JsonDeserializer