Java tutorial
/* * Copyright (C) 2015 Nu Development Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package com.nubits.nubot.options; import com.nubits.nubot.exchanges.ExchangeFacade; import com.nubits.nubot.models.CurrencyList; import com.nubits.nubot.models.CurrencyPair; import com.nubits.nubot.notifications.MailNotifications; import com.nubits.nubot.pricefeeds.FeedFacade; import com.nubits.nubot.utils.FilesystemUtils; import com.nubits.nubot.utils.Utils; import org.json.JSONException; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.Iterator; /** * ParseOptions from one JSON files */ public class ParseOptions { private static final Logger LOG = LoggerFactory.getLogger(ParseOptions.class.getName()); public static String exchangename = "exchangeName"; public static String apikey = "apiKey"; public static String apisecret = "apiSecret"; public static String mailrecipient = "mailRecipient"; public static String pair = "pair"; public static String nudip = "nudIp"; public static String priceincrement = "priceIncrement"; public static String txfee = "txfee"; public static String submitliquidity = "submitLiquidity"; public static String maxsellvolume = "maxSellVolume"; public static String maxbuyvolume = "maxBuyVolume"; public static String executeorders = "executeOrders"; public static String dualside = "dualSide"; public static String verbose = "verbose"; public static String hipchat = "hipchat"; public static String emergencytimeout = "emergencyTimeout"; public static String keepproceeds = "keepProceeds"; public static String multiplecustodians = "multipleCustodians"; public static String nubitaddress = "nubitAddress"; public static String rpcpass = "rpcPass"; public static String rpcuser = "rpcUser"; public static String nudport = "nudPort"; public static String mailnotifications = "mailnotifications"; public static String mainfeed = "mainfeed"; public static String backupfeeds = "backupFeeds"; public static String wallchangethreshold = "wallchangeThreshold"; public static String spread = "spread"; //public static String distributeliquidity = "distributeliquidity"; public static String[] allkeys = { exchangename, apikey, apisecret, mailrecipient, pair, nudip, priceincrement, txfee, submitliquidity, maxsellvolume, maxbuyvolume, executeorders, dualside, verbose, hipchat, emergencytimeout, keepproceeds, multiplecustodians, nubitaddress, rpcpass, rpcuser, nudport, mailnotifications, mainfeed, backupfeeds, wallchangethreshold, spread }; //distributeliquidity private static String[] boolkeys = { submitliquidity, hipchat, verbose, executeorders, dualside, multiplecustodians }; private static String[] comp = { exchangename, apisecret, mailrecipient, dualside, pair }; /** * parse single JSON file to NuBoptions * * @param filepath * @return * @throws NuBotConfigException */ public static NuBotOptions parseOptionsSingle(String filepath, boolean skipValidation) throws NuBotConfigException { File f = new File(filepath); if (!f.exists()) throw new NuBotConfigException("file " + f.getAbsolutePath() + " does not exist"); try { JSONObject inputJSON = parseSingleJsonFile(filepath); return parseOptionsFromJson(inputJSON, skipValidation); } catch (ParseException ex) { throw new NuBotConfigException("Parse Exception. Configuration error from single file"); } catch (Exception e) { throw new NuBotConfigException("Configuration error from single file " + e); } } public static Object getIgnoreCase(JSONObject jobj, String key) { Iterator<String> iter = jobj.keySet().iterator(); while (iter.hasNext()) { String key1 = iter.next(); if (key1.equalsIgnoreCase(key)) { return jobj.get(key1); } } return null; } public static boolean containsIgnoreCase(JSONObject jobj, String key) { Iterator<String> iter = jobj.keySet().iterator(); boolean contains = false; while (iter.hasNext()) { String key1 = iter.next(); if (key1.equalsIgnoreCase(key)) return true; } return contains; } public static boolean isValidOptions(NuBotOptions options) throws NuBotConfigException { boolean supported = ExchangeFacade.supportedExchange(options.exchangeName); LOG.trace("exchange supported? " + options.exchangeName + " " + supported); if (!supported) throw new NuBotConfigException("exchange " + options.exchangeName + " not supported"); //test if configuration is supported if (!isSupportedPair(options.getPair())) { throw new NuBotConfigException( "This bot doesn't work yet with trading pair " + options.getPair().toString()); } if (options.requiresSecondaryPegStrategy()) { if (!FeedFacade.isValidFeed(options.mainFeed)) throw new NuBotConfigException("invalid mainfeed " + options.mainFeed); for (String feed : options.backupFeeds) { if (!FeedFacade.isValidFeed(feed)) throw new NuBotConfigException("invalid feed " + feed); } if (options.wallchangeThreshold < 0) throw new NuBotConfigException("invalid " + options.wallchangeThreshold); if (options.spread < 0) throw new NuBotConfigException("invalid value for spread " + spread); } return true; } /** * the rules for valid configurations * * @param optionsJSON * @return * @throws NuBotConfigException */ public static boolean isValidJSON(JSONObject optionsJSON) throws NuBotConfigException { for (int i = 0; i < allkeys.length; i++) { if (!containsIgnoreCase(optionsJSON, allkeys[i])) throw new NuBotConfigException("necessary key: " + allkeys[i]); } for (int i = 0; i < boolkeys.length; i++) { try { boolean b = (boolean) getIgnoreCase(optionsJSON, boolkeys[i]); } catch (Exception e) { throw new NuBotConfigException("can't parse to boolean: " + boolkeys[i]); } } try { String lstr = "" + getIgnoreCase(optionsJSON, emergencytimeout); int emergencyTimeoutLong = new Integer(lstr).intValue(); } catch (Exception e) { throw new NuBotConfigException("can not cast emergencytimeout to int " + e); } try { int nudPortlong = new Integer("" + getIgnoreCase(optionsJSON, nudport)).intValue(); } catch (Exception e) { throw new NuBotConfigException("can not cast nudPortlong to long " + e); } return true; } private static ArrayList parseBackupFeeds(JSONObject optionsJSON) throws NuBotConfigException { ArrayList backupFeeds = new ArrayList<>(); //Iterate on backupFeeds JSONArray bfeeds = null; try { bfeeds = (JSONArray) getIgnoreCase(optionsJSON, backupfeeds); } catch (Exception e) { throw new NuBotConfigException("can't parse array " + e); } if (bfeeds.size() < 2) { throw new NuBotConfigException("The bot requires at least two backup data feeds to run"); } for (int i = 0; i < bfeeds.size(); i++) { try { String feedname = (String) bfeeds.get(i); if (!FeedFacade.isValidFeed(feedname)) throw new NuBotConfigException("invalid feed configured"); else backupFeeds.add(feedname); } catch (JSONException ex) { throw new NuBotConfigException("parse feeds json error" + ex); } } return backupFeeds; } private static String parseMails(JSONObject optionsJSON) throws NuBotConfigException { String tmpsendMails = (String) getIgnoreCase(optionsJSON, mailnotifications); if (tmpsendMails.equalsIgnoreCase(MailNotifications.MAIL_LEVEL_ALL) || tmpsendMails.equalsIgnoreCase(MailNotifications.MAIL_LEVEL_NONE) || tmpsendMails.equalsIgnoreCase(MailNotifications.MAIL_LEVEL_SEVERE)) { return tmpsendMails.toUpperCase(); //Convert to upper case } else { String error = "Value not accepted for \"mail-notifications\" : " + tmpsendMails + " . Admitted values : " + MailNotifications.MAIL_LEVEL_ALL + " , " + MailNotifications.MAIL_LEVEL_SEVERE + " or " + MailNotifications.MAIL_LEVEL_NONE; LOG.error(error); throw new NuBotConfigException(error); } } /** * parseOptions from JSON into NuBotOptions * makes sure the parses object is valid * * @param optionsJSON * @return */ public static NuBotOptions parseOptionsFromJson(JSONObject optionsJSON, boolean skipValidation) throws NuBotConfigException { try { isValidJSON(optionsJSON); } catch (NuBotConfigException e) { throw e; } NuBotOptions options = new NuBotOptions(); options.exchangeName = (String) getIgnoreCase(optionsJSON, exchangename); options.dualSide = (boolean) getIgnoreCase(optionsJSON, dualside); options.apiKey = (String) getIgnoreCase(optionsJSON, apikey); options.apiSecret = (String) getIgnoreCase(optionsJSON, apisecret); options.mailRecipient = (String) getIgnoreCase(optionsJSON, mailrecipient); options.pair = (String) getIgnoreCase(optionsJSON, pair); options.nudIp = (String) getIgnoreCase(optionsJSON, nudip); options.priceIncrement = Utils.getDouble(getIgnoreCase(optionsJSON, priceincrement)); options.txFee = Utils.getDouble(getIgnoreCase(optionsJSON, txfee)); options.submitLiquidity = (boolean) getIgnoreCase(optionsJSON, submitliquidity); options.maxSellVolume = Utils.getDouble(getIgnoreCase(optionsJSON, maxsellvolume)); options.maxBuyVolume = Utils.getDouble(getIgnoreCase(optionsJSON, maxbuyvolume)); options.executeOrders = (boolean) getIgnoreCase(optionsJSON, executeorders); options.verbose = (boolean) getIgnoreCase(optionsJSON, verbose); options.hipchat = (boolean) getIgnoreCase(optionsJSON, hipchat); options.emergencyTimeout = new Integer("" + getIgnoreCase(optionsJSON, emergencytimeout)).intValue(); options.keepProceeds = Utils.getDouble((getIgnoreCase(optionsJSON, keepproceeds))); options.multipleCustodians = (boolean) getIgnoreCase(optionsJSON, multiplecustodians); options.nubitAddress = (String) getIgnoreCase(optionsJSON, nubitaddress); options.rpcPass = (String) getIgnoreCase(optionsJSON, rpcpass); options.rpcUser = (String) getIgnoreCase(optionsJSON, rpcuser); options.nudPort = new Integer("" + getIgnoreCase(optionsJSON, nudport)).intValue(); //secondary LOG.trace("options requiresSecondaryPegStrategy: " + options.requiresSecondaryPegStrategy()); options.mainFeed = (String) getIgnoreCase(optionsJSON, mainfeed); options.wallchangeThreshold = Utils.getDouble(getIgnoreCase(optionsJSON, wallchangethreshold)); options.spread = Utils.getDouble(getIgnoreCase(optionsJSON, spread)); options.backupFeeds = parseBackupFeeds(optionsJSON); options.mailnotifications = parseMails(optionsJSON); if (options.spread != 0) { LOG.warn( "You are using the \"spread\" != 0 , which is not reccomented by Nu developers for purposes different from testing."); } if (!skipValidation) { try { isValidOptions(options); } catch (NuBotConfigException e) { throw e; } } else { LOG.debug("Skipping validation of configuration file."); } return options; } public static NuBotOptions parsePost(JSONObject postJson, boolean skipValidation) throws Exception { NuBotOptions newopt = null; try { //Check if NuBot has valid parameters newopt = ParseOptions.parseOptionsFromJson(postJson, skipValidation); LOG.debug("parse post opt: " + newopt); } catch (NuBotConfigException e) { throw e; } return newopt; } /** * parse single json file * * @param filepath * @return * @throws ParseException */ public static JSONObject parseSingleJsonFile(String filepath) throws ParseException { JSONParser parser = new JSONParser(); JSONObject fileJSON = (JSONObject) (parser.parse(FilesystemUtils.readFromFile(filepath))); return fileJSON; } /** * check if pair is supported * * @param pair * @return */ public static boolean isSupportedPair(CurrencyPair pair) { if (pair.equals(CurrencyList.NBT_USD) || pair.equals(CurrencyList.NBT_BTC) || pair.equals(CurrencyList.BTC_NBT) || pair.equals(CurrencyList.NBT_EUR) || pair.equals(CurrencyList.NBT_CNY) || pair.equals(CurrencyList.NBT_PPC)) { return true; } else { return false; } } }