diff --git a/config/config.go b/config/config.go index 1409efbe..531d3127 100644 --- a/config/config.go +++ b/config/config.go @@ -78,7 +78,9 @@ type Post struct { // CurrencyPairFormatConfig stores the users preferred currency pair display type CurrencyPairFormatConfig struct { Uppercase bool - Delimiter string + Delimiter string `json:",omitempty"` + Separator string `json:",omitempty"` + Index string `json:",omitempty"` } // Config is the overarching object that holds all the information for @@ -96,18 +98,20 @@ type Config struct { // ExchangeConfig holds all the information needed for each enabled Exchange. type ExchangeConfig struct { - Name string - Enabled bool - Verbose bool - Websocket bool - RESTPollingDelay time.Duration - AuthenticatedAPISupport bool - APIKey string - APISecret string - ClientID string `json:",omitempty"` - AvailablePairs string - EnabledPairs string - BaseCurrencies string + Name string + Enabled bool + Verbose bool + Websocket bool + RESTPollingDelay time.Duration + AuthenticatedAPISupport bool + APIKey string + APISecret string + ClientID string `json:",omitempty"` + AvailablePairs string + EnabledPairs string + BaseCurrencies string + ConfigCurrencyPairFormat *CurrencyPairFormatConfig `json:"ConfigCurrencyPairFormat"` + RequestCurrencyPairFormat *CurrencyPairFormatConfig `json:"RequestCurrencyPairFormat"` } // GetConfigEnabledExchanges returns the number of exchanges that are enabled. diff --git a/config_example.dat b/config_example.dat index 65d01df0..401ce0ad 100644 --- a/config_example.dat +++ b/config_example.dat @@ -11,22 +11,26 @@ { "Address": "1JCe8z4jJVNXSjohjM4i9Hh813dLCNx2Sy", "CoinType": "BTC", - "Balance": 124178.0002442 + "Balance": 124178.00647714, + "Description": "" }, { "Address": "3Nxwenay9Z8Lc9JBiywExpnEFiLp6Afp8v", "CoinType": "BTC", - "Balance": 103439.83659727 + "Balance": 107843.84030984, + "Description": "" }, { "Address": "LgY8ahfHRhvjVQC1zJnBhFMG5pCTMuKRqh", "CoinType": "LTC", - "Balance": 3.00000005e+06 + "Balance": 100000.052, + "Description": "" }, { "Address": "0xb794f5ea0ba39494ce839613fffba74279579268", "CoinType": "ETH", - "Balance": 5.774999820458524e+06 + "Balance": 3.224999915984445e+24, + "Description": "" } ] }, @@ -58,10 +62,17 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCUSD,BTCHKD,BTCEUR,BTCCAD,BTCAUD,BTCSGD,BTCJPY,BTCGBP,BTCNZD,LTCBTC,DOGEBTC,STRBTC,XRPBTC", "EnabledPairs": "BTCUSD,BTCHKD,BTCEUR,BTCCAD,BTCAUD,BTCSGD,BTCJPY,BTCGBP,BTCNZD,LTCBTC,DOGEBTC,STRBTC,XRPBTC", - "BaseCurrencies": "USD,HKD,EUR,CAD,AUD,SGD,JPY,GBP,NZD" + "BaseCurrencies": "USD,HKD,EUR,CAD,AUD,SGD,JPY,GBP,NZD", + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Index": "BTC" + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Index": "BTC" + } }, { "Name": "Bitfinex", @@ -72,10 +83,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", - "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,BFXUSD,BFXBTC,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC", + "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC,BCCBTC,BCUBTC,BCCUSD,BCUUSD,XRPUSD,XRPBTC,IOTUSD,IOTBTC,IOTETH,EOSUSD,EOSBTC,EOSETH,SANUSD,SANBTC,SANETH,OMGUSD,OMGBTC,OMGETH,BCHUSD,BCHBTC,BCHETH", "EnabledPairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Bitstamp", @@ -89,7 +105,13 @@ "ClientID": "ClientID", "AvailablePairs": "BTCUSD,BTCEUR,EURUSD,XRPUSD,XRPEUR", "EnabledPairs": "BTCUSD,BTCEUR,EURUSD,XRPUSD,XRPEUR", - "BaseCurrencies": "USD,EUR" + "BaseCurrencies": "USD,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Bittrex", @@ -100,10 +122,17 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", - "AvailablePairs": "BTCLTC,BTCDOGE,BTCVTC,BTCPPC,BTCFTC,BTCRDD,BTCNXT,BTCDASH,BTCPOT,BTCBLK,BTCEMC2,BTCXMY,BTCAUR,BTCEFL,BTCGLD,BTCSLR,BTCPTC,BTCGRS,BTCNLG,BTCRBY,BTCXWC,BTCMONA,BTCTHC,BTCENRG,BTCERC,BTCNAUT,BTCVRC,BTCCURE,BTCXBB,BTCXMR,BTCCLOAK,BTCSTART,BTCKORE,BTCXDN,BTCTRUST,BTCNAV,BTCXST,BTCBTCD,BTCVIA,BTCUNO,BTCPINK,BTCIOC,BTCCANN,BTCSYS,BTCNEOS,BTCDGB,BTCBURST,BTCEXCL,BTCSWIFT,BTCDOPE,BTCBLOCK,BTCABY,BTCBYC,BTCXMG,BTCBLITZ,BTCBAY,BTCBTS,BTCFAIR,BTCSPR,BTCVTR,BTCXRP,BTCGAME,BTCCOVAL,BTCNXS,BTCXCP,BTCBITB,BTCGEO,BTCFLDC,BTCGRC,BTCFLO,BTCNBT,BTCMUE,BTCXEM,BTCCLAM,BTCDMD,BTCGAM,BTCSPHR,BTCOK,BTCSNRG,BTCPKB,BTCCPC,BTCAEON,BTCETH,BTCGCR,BTCTX,BTCBCY,BTCEXP,BTCINFX,BTCOMNI,BTCAMP,BTCAGRS,BTCXLM,BTCBTA,USDTBTC,BITCNYBTC,BTCCLUB,BTCVOX,BTCEMC,BTCFCT,BTCMAID,BTCEGC,BTCSLS,BTCRADS,BTCDCR,BTCSAFEX,BTCBSD,BTCXVG,BTCPIVX,BTCXVC,BTCMEME,BTCSTEEM,BTC2GIVE,BTCLSK,BTCPDC,BTCBRK,BTCDGD,ETHDGD,BTCWAVES,BTCRISE,BTCLBC,BTCSBD,BTCBRX,BTCDRACO,BTCETC,ETHETC,BTCSTRAT,BTCUNB,BTCSYNX,BTCTRIG,BTCEBST,BTCVRM,BTCSEQ,BTCXAUR,BTCSNGLS,BTCREP,BTCSHIFT,BTCARDR,BTCXZC,BTCNEO,BTCZEC,BTCZCL,BTCIOP,BTCDAR,BTCGOLOS,BTCHKG,BTCUBQ,BTCKMD,BTCGBG,BTCSIB,BTCION,BTCLMC,BTCQWARK,BTCCRW,BTCSWT,BTCTIME,BTCMLN,BTCARK,BTCDYN,BTCTKS,BTCMUSIC,BTCDTB,BTCINCNT,BTCGBYTE,BTCGNT,BTCNXC,BTCEDG,BTCLGD,BTCTRST,ETHGNT,ETHREP,USDTETH,ETHWINGS,BTCWINGS,BTCRLC,BTCGNO,BTCGUP,BTCLUN,ETHGUP,ETHRLC,ETHLUN,ETHSNGLS,ETHGNO,BTCAPX,BTCTKN,ETHTKN,BTCHMQ,ETHHMQ,BTCANT,ETHTRST,ETHANT,BTCSC,ETHBAT,BTCBAT,BTCZEN,BTC1ST,BTCQRL,ETH1ST,ETHQRL,BTCCRB,ETHCRB,ETHLGD,BTCPTOY,ETHPTOY,BTCMYST,ETHMYST,BTCCFI,ETHCFI,BTCBNT,ETHBNT,BTCNMR,ETHNMR,ETHTIME,ETHLTC,ETHXRP,BTCSNT,ETHSNT,BTCDCT,BTCXEL,BTCMCO,ETHMCO,BTCADT,ETHADT,BTCFUN,ETHFUN,BTCPAY,ETHPAY,BTCMTL,ETHMTL,BTCSTORJ,ETHSTORJ,BTCADX,ETHADX,ETHDASH,ETHSC,ETHZEC,USDTZEC,USDTLTC,USDTETC,USDTXRP,BTCOMG,ETHOMG,BTCCVC,ETHCVC,BTCPART,BTCQTUM,ETHQTUM,ETHXMR,ETHXEM,ETHXLM,ETHNEO,USDTXMR,USDTDASH,ETHBCC,USDTBCC,BTCBCC,USDTNEO,ETHWAVES,ETHSTRAT,ETHDGB,ETHFCT,ETHBTS", - "EnabledPairs": "BTCLTC,BTCDOGE,BTCDASH", - "BaseCurrencies": "USD" + "AvailablePairs": "BTC-LTC,BTC-DOGE,BTC-VTC,BTC-PPC,BTC-FTC,BTC-RDD,BTC-NXT,BTC-DASH,BTC-POT,BTC-BLK,BTC-XMY,BTC-AUR,BTC-EFL,BTC-GLD,BTC-SLR,BTC-PTC,BTC-GRS,BTC-NLG,BTC-RBY,BTC-XWC,BTC-MONA,BTC-THC,BTC-ENRG,BTC-ERC,BTC-NAUT,BTC-VRC,BTC-CURE,BTC-XBB,BTC-XMR,BTC-CLOAK,BTC-START,BTC-KORE,BTC-XDN,BTC-TRUST,BTC-NAV,BTC-XST,BTC-BTCD,BTC-VIA,BTC-UNO,BTC-PINK,BTC-IOC,BTC-CANN,BTC-SYS,BTC-NEOS,BTC-DGB,BTC-BURST,BTC-EXCL,BTC-SWIFT,BTC-DOPE,BTC-BLOCK,BTC-ABY,BTC-BYC,BTC-XMG,BTC-BLITZ,BTC-BAY,BTC-BTS,BTC-FAIR,BTC-SPR,BTC-VTR,BTC-XRP,BTC-GAME,BTC-COVAL,BTC-NXS,BTC-XCP,BTC-BITB,BTC-GEO,BTC-FLDC,BTC-GRC,BTC-FLO,BTC-NBT,BTC-MUE,BTC-XEM,BTC-CLAM,BTC-DMD,BTC-GAM,BTC-SPHR,BTC-OK,BTC-SNRG,BTC-PKB,BTC-CPC,BTC-AEON,BTC-ETH,BTC-GCR,BTC-TX,BTC-BCY,BTC-EXP,BTC-INFX,BTC-OMNI,BTC-AMP,BTC-AGRS,BTC-XLM,BTC-BTA,USDT-BTC,BITCNY-BTC,BTC-CLUB,BTC-VOX,BTC-EMC,BTC-FCT,BTC-MAID,BTC-EGC,BTC-SLS,BTC-RADS,BTC-DCR,BTC-SAFEX,BTC-BSD,BTC-XVG,BTC-PIVX,BTC-XVC,BTC-MEME,BTC-STEEM,BTC-2GIVE,BTC-LSK,BTC-PDC,BTC-BRK,BTC-DGD,ETH-DGD,BTC-WAVES,BTC-RISE,BTC-LBC,BTC-SBD,BTC-BRX,BTC-DRACO,BTC-ETC,ETH-ETC,BTC-STRAT,BTC-UNB,BTC-SYNX,BTC-TRIG,BTC-EBST,BTC-VRM,BTC-SEQ,BTC-XAUR,BTC-SNGLS,BTC-REP,BTC-SHIFT,BTC-ARDR,BTC-XZC,BTC-NEO,BTC-ZEC,BTC-ZCL,BTC-IOP,BTC-DAR,BTC-GOLOS,BTC-HKG,BTC-UBQ,BTC-KMD,BTC-GBG,BTC-SIB,BTC-ION,BTC-LMC,BTC-QWARK,BTC-CRW,BTC-SWT,BTC-TIME,BTC-MLN,BTC-ARK,BTC-DYN,BTC-TKS,BTC-MUSIC,BTC-DTB,BTC-INCNT,BTC-GBYTE,BTC-GNT,BTC-NXC,BTC-EDG,BTC-LGD,BTC-TRST,ETH-GNT,ETH-REP,USDT-ETH,ETH-WINGS,BTC-WINGS,BTC-RLC,BTC-GNO,BTC-GUP,BTC-LUN,ETH-GUP,ETH-RLC,ETH-LUN,ETH-SNGLS,ETH-GNO,BTC-APX,BTC-TKN,ETH-TKN,BTC-HMQ,ETH-HMQ,BTC-ANT,ETH-TRST,ETH-ANT,BTC-SC,ETH-BAT,BTC-BAT,BTC-ZEN,BTC-1ST,BTC-QRL,ETH-1ST,ETH-QRL,BTC-CRB,ETH-CRB,ETH-LGD,BTC-PTOY,ETH-PTOY,BTC-MYST,ETH-MYST,BTC-CFI,ETH-CFI,BTC-BNT,ETH-BNT,BTC-NMR,ETH-NMR,ETH-TIME,ETH-LTC,ETH-XRP,BTC-SNT,ETH-SNT,BTC-DCT,BTC-XEL,BTC-MCO,ETH-MCO,BTC-ADT,ETH-ADT,BTC-FUN,ETH-FUN,BTC-PAY,ETH-PAY,BTC-MTL,ETH-MTL,BTC-STORJ,ETH-STORJ,BTC-ADX,ETH-ADX,ETH-DASH,ETH-SC,ETH-ZEC,USDT-ZEC,USDT-LTC,USDT-ETC,USDT-XRP,BTC-OMG,ETH-OMG,BTC-CVC,ETH-CVC,BTC-PART,BTC-QTUM,ETH-QTUM,ETH-XMR,ETH-XEM,ETH-XLM,ETH-NEO,USDT-XMR,USDT-DASH,ETH-BCC,USDT-BCC,BTC-BCC,USDT-NEO,ETH-WAVES,ETH-STRAT,ETH-DGB,ETH-FCT,ETH-BTS", + "EnabledPairs": "USDT-BTC", + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "-" + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "-" + } }, { "Name": "BTCC", @@ -114,10 +143,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCCNY,LTCCNY,LTCBTC", "EnabledPairs": "BTCCNY,LTCCNY,LTCBTC", - "BaseCurrencies": "CNY" + "BaseCurrencies": "CNY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false + } }, { "Name": "BTCE", @@ -128,10 +162,17 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCUSD,BTCRUR,BTCEUR,LTCBTC,LTCUSD,LTCRUR,LTCEUR,NMCBTC,NMCUSD,NVCBTC,NVCUSD,USDRUR,EURUSD,EURRUR,PPCBTC,PPCUSD", "EnabledPairs": "BTCUSD,BTCRUR,BTCEUR,LTCBTC,LTCUSD,LTCRUR,LTCEUR,NMCBTC,NMCUSD,NVCBTC,NVCUSD,USDRUR,EURUSD,EURRUR,PPCBTC,PPCUSD", - "BaseCurrencies": "USD,RUR,EUR" + "BaseCurrencies": "USD,RUR,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_", + "Separator": "-" + } }, { "Name": "BTC Markets", @@ -142,10 +183,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", - "AvailablePairs": "LTC,BTC", - "EnabledPairs": "LTC,BTC", - "BaseCurrencies": "AUD" + "AvailablePairs": "LTCAUD,BTCAUD", + "EnabledPairs": "LTCAUD,BTCAUD", + "BaseCurrencies": "AUD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "COINUT", @@ -159,7 +205,13 @@ "ClientID": "ClientID", "AvailablePairs": "LTCBTC,ETCBTC,ETHBTC", "EnabledPairs": "LTCBTC,ETCBTC,ETHBTC", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "GDAX", @@ -171,9 +223,16 @@ "APIKey": "Key", "APISecret": "Secret", "ClientID": "ClientID", - "AvailablePairs": "BTCGBP,BTCEUR,ETHUSD,ETHBTC,LTCUSD,LTCBTC,BTCUSD", + "AvailablePairs": "LTCEUR,LTCBTC,BTCGBP,BTCEUR,ETHEUR,ETHBTC,LTCUSD,BTCUSD,ETHUSD", "EnabledPairs": "BTCUSD,BTCGBP,BTCEUR", - "BaseCurrencies": "USD,GBP,EUR" + "BaseCurrencies": "USD,GBP,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "-" + } }, { "Name": "Gemini", @@ -184,10 +243,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCUSD,ETHBTC,ETHUSD", "EnabledPairs": "BTCUSD", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Huobi", @@ -198,10 +262,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCCNY,LTCCNY", "EnabledPairs": "BTCCNY,LTCCNY", - "BaseCurrencies": "CNY" + "BaseCurrencies": "CNY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false + } }, { "Name": "ITBIT", @@ -215,7 +284,13 @@ "ClientID": "ClientID", "AvailablePairs": "XBTUSD,XBTSGD,XBTEUR", "EnabledPairs": "XBTUSD,XBTSGD,XBTEUR", - "BaseCurrencies": "USD,SGD,EUR" + "BaseCurrencies": "USD,SGD,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Kraken", @@ -226,10 +301,16 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", - "AvailablePairs": "ETCUSD,ICNETH,REPXBT,ZECXBT,ETHXBT,ETHXBT.d,ETHGBP,LTCXBT,XBTGBP.d,XDGXBT,XMRUSD,ZECUSD,ETCETH,ETHJPY,XBTCAD.d,XBTJPY.d,XBTUSD.d,XLMXBT,XLMEUR,XLMUSD,XMREUR,ETCXBT,ETHCAD.d,ETHEUR.d,ETHJPY.d,XBTEUR.d,ETHEUR,ETHGBP.d,ICNXBT,LTCEUR,REPEUR,XBTGBP,XBTJPY,ETHUSD,ETHUSD.d,LTCUSD,REPETH,XBTUSD,XMRXBT,ETCEUR,ETHCAD,REPUSD,XBTCAD,XBTEUR,XRPXBT,ZECEUR", + "AvailablePairs": "XBTUSD,ZECEUR,REPETH,XBTJPY,ETHEUR.D,LTCXBT,GNOXBT,ETHCAD.D,ETHEUR,ETHUSD,ICNXBT,XDGXBT,BCHUSD,DASHEUR,ETHJPY.D,MLNXBT,XBTCAD,GNOETH,ETCUSD,REPXBT,ETCXBT,ICNETH,ETHXBT,XBTJPY.D,XMREUR,XRPUSD,ZECXBT,ETHCAD,XBTGBP.D,MLNETH,BCHEUR,ETCEUR,XBTEUR,XLMXBT,XRPXBT,ETCETH,REPEUR,XMRUSD,ZECUSD,USDTUSD,ETHXBT.D,ETHJPY,ETHUSD.D,XBTUSD.D,LTCUSD,XBTCAD.D,BCHXBT,DASHUSD,EOSXBT,ETHGBP.D,XMRXBT,XRPEUR,DASHXBT,EOSETH,LTCEUR,XBTEUR.D", "EnabledPairs": "ETCUSD,XBTUSD,ETHUSD", - "BaseCurrencies": "EUR,USD,CAD,GBP,JPY" + "BaseCurrencies": "EUR,USD,CAD,GBP,JPY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Separator": "," + } }, { "Name": "LakeBTC", @@ -240,10 +321,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCUSD,BTCEUR,USDHKD,AUDUSD,BTCGBP,BTCNZD,USDJPY,BTCSGD,BTCNGN,EURUSD,USDSGD,NZDUSD,USDNGN,USDCHF,BTCJPY,BTCAUD,BTCCAD,BTCCHF,GBPUSD,USDCAD", "EnabledPairs": "BTCUSD,BTCAUD", - "BaseCurrencies": "USD,EUR,HKD,AUD,GBP,NZD,JPY,SGD,NGN,CHF,CAD" + "BaseCurrencies": "USD,EUR,HKD,AUD,GBP,NZD,JPY,SGD,NGN,CHF,CAD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Liqui", @@ -254,10 +340,18 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", - "AvailablePairs": "TIME_BTC,ETH_BTC,GNT_BTC,WAVES_BTC,ICN_BTC,1ST_BTC,WINGS_BTC,MLN_BTC,ROUND_BTC,VSL_BTC,LTC_BTC,DCT_BTC,INCNT_BTC,PLU_BTC,DASH_BTC", + "AvailablePairs": "SAN_BTC,OAX_BTC,VSL_BTC,PLU_USDT,GUP_ETH,SNT_ETH,EOS_ETH,ICN_USDT,CVC_USDT,DASH_BTC,DASH_USDT,WINGS_USDT,LUN_ETH,CFI_USDT,OAX_USDT,BCAP_ETH,MCO_BTC,STORJ_BTC,ICN_BTC,LTC_ETH,TAAS_BTC,BNT_ETH,QTUM_ETH,REP_ETH,RLC_BTC,HMQ_ETH,TIME_ETH,QRL_USDT,PTOY_USDT,LTC_BTC,GNT_BTC,RLC_USDT,SNT_BTC,RLC_ETH,TRST_USDT,MCO_ETH,ADX_BTC,VSL_USDT,TRST_ETH,DGD_USDT,BCC_ETH,SNM_ETH,DNT_ETH,GNT_ETH,TAAS_USDT,HMQ_USDT,BAT_ETH,STORJ_ETH,ADX_ETH,OMG_USDT,TIME_BTC,PLU_ETH,WINGS_ETH,SNGLS_BTC,CFI_ETH,SAN_ETH,DNT_USDT,STX_ETH,WAVES_BTC,1ST_ETH,INCNT_ETH,MYST_USDT,PTOY_ETH,MLN_USDT,QRL_BTC,ADX_USDT,PAY_ETH,STX_BTC,QTUM_BTC,CVC_ETH,STX_USDT,MLN_BTC,ICN_ETH,BTC_USDT,TRST_BTC,SNM_BTC,NET_BTC,CVC_BTC,OAX_ETH,1ST_BTC,GNT_USDT,GUP_BTC,BAT_USDT,BNT_USDT,STORJ_USDT,PLU_BTC,DASH_ETH,BCAP_USDT,QRL_ETH,PTOY_BTC,PAY_BTC,ZRX_ETH,ZRX_USDT,LTC_USDT,GNO_BTC,TKN_BTC,HMQ_BTC,MCO_USDT,GUP_USDT,BCC_BTC,XID_BTC,ETH_USDT,INCNT_USDT,GNO_USDT,CFI_BTC,WAVES_USDT,QTUM_USDT,NET_USDT,DNT_BTC,ROUND_ETH,REP_BTC,TKN_USDT,XID_USDT,DGD_ETH,MYST_ETH,SNT_USDT,PAY_USDT,BCC_USDT,ROUND_BTC,ANT_ETH,OMG_ETH,NET_ETH,DGD_BTC,SAN_USDT,WINGS_BTC,VSL_ETH,ROUND_USDT,LUN_BTC,LUN_USDT,EDG_USDT,ANT_USDT,EOS_USDT,ETH_BTC,INCNT_BTC,WAVES_ETH,TIME_USDT,EDG_BTC,XID_ETH,SNGLS_USDT,SNM_USDT,OMG_BTC,GNO_ETH,MGO_ETH,MGO_USDT,MYST_BTC,ZRX_BTC,BNT_BTC,MGO_BTC,SNGLS_ETH,1ST_USDT,EDG_ETH,REP_USDT,BCAP_BTC,ANT_BTC,MLN_ETH,TAAS_ETH,TKN_ETH,BAT_BTC,EOS_BTC", "EnabledPairs": "ETH_BTC,LTC_BTC,DASH_BTC", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_", + "Separator": "-" + } }, { "Name": "LocalBitcoins", @@ -268,10 +362,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCARS,BTCAUD,BTCBRL,BTCCAD,BTCCHF,BTCCZK,BTCDKK,BTCEUR,BTCGBP,BTCHKD,BTCILS,BTCINR,BTCMXN,BTCNOK,BTCNZD,BTCPLN,BTCRUB,BTCSEK,BTCSGD,BTCTHB,BTCUSD,BTCZAR", "EnabledPairs": "BTCARS,BTCAUD,BTCBRL,BTCCAD,BTCCHF,BTCCZK,BTCDKK,BTCEUR,BTCGBP,BTCHKD,BTCILS,BTCINR,BTCMXN,BTCNOK,BTCNZD,BTCPLN,BTCRUB,BTCSEK,BTCSGD,BTCTHB,BTCUSD,BTCZAR", - "BaseCurrencies": "ARS,AUD,BRL,CAD,CHF,CZK,DKK,EUR,GBP,HKD,ILS,INR,MXN,NOK,NZD,PLN,RUB,SEK,SGD,THB,USD,ZAR" + "BaseCurrencies": "ARS,AUD,BRL,CAD,CHF,CZK,DKK,EUR,GBP,HKD,ILS,INR,MXN,NOK,NZD,PLN,RUB,SEK,SGD,THB,USD,ZAR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "OKCOIN China", @@ -282,10 +381,16 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCCNY,LTCCNY", "EnabledPairs": "BTCCNY,LTCCNY", - "BaseCurrencies": "CNY" + "BaseCurrencies": "CNY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + } }, { "Name": "OKCOIN International", @@ -296,10 +401,16 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTCUSD,LTCUSD", "EnabledPairs": "BTCUSD,LTCUSD", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + } }, { "Name": "Poloniex", @@ -310,10 +421,17 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "ClientID": "", "AvailablePairs": "BTC_XUSD,BTC_FCT,BTC_MMNXT,BTC_NMC,BTC_BITUSD,BTC_RDD,BTC_XMR,BTC_XST,BTC_DSH,BTC_MAID,BTC_DGB,BTC_NEOS,BTC_BLK,BTC_NAUT,BTC_NBT,BTC_XCP,BTC_STR,BTC_BTCD,BTC_GRC,BTC_HUC,BTC_BBR,BTC_XDN,BTC_INDEX,BTC_IOC,BTC_SWARM,BTC_EMC2,BTC_MCN,BTC_NOXT,BTC_MINT,BTC_PTS,BTC_SC,BTC_GEO,BTC_XRP,BTC_FLO,BTC_BITS,BTC_HYP,BTC_XCR,BTC_LTBC,BTC_SYS,BTC_GMC,BTC_ETH,BTC_SYNC,BTC_GAP,BTC_BCN,BTC_C2,BTC_PINK,BTC_FIBRE,BTC_POT,BTC_QTL,BTC_SDC,BTC_XC,BTC_DASH,BTC_SILK,BTC_CLAM,BTC_NAV,BTC_PIGGY,BTC_BCY,BTC_MIL,BTC_XCN,BTC_YACC,BTC_BTS,BTC_QBK,BTC_SJCX,BTC_LQD,BTC_BURST,BTC_RIC,BTC_VRC,BTC_LTC,BTC_XPB,BTC_GRS,BTC_XCH,BTC_ARCH,BTC_QORA,BTC_HZ,BTC_NSR,BTC_XPM,BTC_BITCNY,BTC_EXE,BTC_XMG,BTC_BTC,BTC_BTM,BTC_NOBL,BTC_NXT,BTC_DOGE,BTC_CURE,BTC_MNTA,BTC_ADN,BTC_EXP,BTC_VTC,BTC_FLDC,BTC_MRS,BTC_MYR,BTC_OMNI,BTC_VNL,BTC_USDT,BTC_NOTE,BTC_WDC,BTC_BELA,BTC_VIA,BTC_CGA,BTC_DIEM,BTC_IFC,BTC_XDP,BTC_BLOCK,BTC_MMC,BTC_1CR,BTC_UNITY,BTC_XBC,BTC_GEMZ,BTC_FLT,BTC_PPC,BTC_XEM,BTC_RBY,BTC_CNMT,BTC_ABY,XMR_XDN,XMR_IFC,XMR_DIEM,XMR_BBR,XMR_DSH,XMR_BCN,XMR_LTC,XMR_MAID,XMR_DASH,XMR_BTCD,XMR_HYP,XMR_BLK,XMR_QORA,XMR_MNTA,XMR_NXT,USDT_BTC,USDT_ETH,USDT_XRP,USDT_DASH,USDT_LTC,USDT_NXT,USDT_XMR,USDT_STR", "EnabledPairs": "BTC_LTC,BTC_ETH,BTC_DOGE,BTC_DASH,BTC_XRP", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + } } ] -} +} \ No newline at end of file diff --git a/currency/pair/pair.go b/currency/pair/pair.go index 3e0c8b3e..3b105ba0 100644 --- a/currency/pair/pair.go +++ b/currency/pair/pair.go @@ -1,6 +1,8 @@ package pair -import "strings" +import ( + "strings" +) // CurrencyItem is an exported string with methods to manipulate the data instead // of using array/slice access modifiers @@ -43,7 +45,7 @@ func (c CurrencyPair) Pair() CurrencyItem { return c.FirstCurrency + CurrencyItem(c.Delimiter) + c.SecondCurrency } -// Display formats and returns the currency based on user preferences, +// Display formats and returns the currency based on user preferences, // overriding the default Pair() display func (c CurrencyPair) Display(delimiter string, uppercase bool) CurrencyItem { var pair CurrencyItem @@ -79,6 +81,16 @@ func NewCurrencyPair(firstCurrency, secondCurrency string) CurrencyPair { } } +// NewCurrencyPairFromIndex returns a CurrencyPair via a currency string and +// specific index +func NewCurrencyPairFromIndex(currency, index string) CurrencyPair { + i := strings.Index(currency, index) + if i == 0 { + return NewCurrencyPair(currency[0:len(index)], currency[len(index):]) + } + return NewCurrencyPair(currency[0:i], currency[i:]) +} + // NewCurrencyPairFromString converts currency string into a new CurrencyPair // with or without delimeter func NewCurrencyPairFromString(currency string) CurrencyPair { diff --git a/currency/pair/pair_test.go b/currency/pair/pair_test.go index 91abf22a..e787bba2 100644 --- a/currency/pair/pair_test.go +++ b/currency/pair/pair_test.go @@ -140,6 +140,26 @@ func TestNewCurrencyPairDelimiter(t *testing.T) { } } +// NewCurrencyPairFromIndex returns a CurrencyPair via a currency string and +// specific index +func TestNewCurrencyPairFromIndex(t *testing.T) { + t.Parallel() + currency := "BTCUSD" + index := "BTC" + + pair := NewCurrencyPairFromIndex(currency, index) + pair.Delimiter = "-" + actual := pair.Pair() + + expected := CurrencyItem("BTC-USD") + if actual != expected { + t.Errorf( + "Test failed. Pair(): %s was not equal to expected value: %s", + actual, expected, + ) + } +} + func TestNewCurrencyPairFromString(t *testing.T) { t.Parallel() pairStr := "BTC-USD" diff --git a/exchanges/anx/anx.go b/exchanges/anx/anx.go index 92f25b89..9688fbab 100644 --- a/exchanges/anx/anx.go +++ b/exchanges/anx/anx.go @@ -39,6 +39,12 @@ func (a *ANX) SetDefaults() { a.Verbose = false a.Websocket = false a.RESTPollingDelay = 10 + a.RequestCurrencyPairFormat.Delimiter = "" + a.RequestCurrencyPairFormat.Uppercase = true + a.RequestCurrencyPairFormat.Index = "BTC" + a.ConfigCurrencyPairFormat.Delimiter = "" + a.ConfigCurrencyPairFormat.Uppercase = true + a.ConfigCurrencyPairFormat.Index = "BTC" } //Setup is run on startup to setup exchange with config values @@ -55,6 +61,10 @@ func (a *ANX) Setup(exch config.ExchangeConfig) { a.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") a.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") a.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := a.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/anx/anx_types.go b/exchanges/anx/anx_types.go index 49b6956f..784fe4e9 100644 --- a/exchanges/anx/anx_types.go +++ b/exchanges/anx/anx_types.go @@ -30,11 +30,10 @@ type ANXOrderResponse struct { } type ANXTickerComponent struct { - Currency string `json:"currency"` - Display string `json:"display"` - DisplayShort string `json:"display_short"` - Value float64 `json:"value,string"` - ValueInt int64 `json:"value_int,string"` + Currency string `json:"currency"` + Display string `json:"display"` + DisplayShort string `json:"display_short"` + Value string `json:"value"` } type ANXTicker struct { diff --git a/exchanges/anx/anx_wrapper.go b/exchanges/anx/anx_wrapper.go index 6584a5ac..23e8795a 100644 --- a/exchanges/anx/anx_wrapper.go +++ b/exchanges/anx/anx_wrapper.go @@ -2,6 +2,7 @@ package anx import ( "log" + "strconv" "time" "github.com/thrasher-/gocryptotrader/currency/pair" @@ -22,8 +23,9 @@ func (a *ANX) Run() { } for a.Enabled { - for _, x := range a.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := a.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := a.GetTickerPrice(currency) if err != nil { @@ -51,12 +53,60 @@ func (a *ANX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { } tickerPrice.Pair = p - tickerPrice.Ask = tick.Data.Buy.Value - tickerPrice.Bid = tick.Data.Sell.Value - tickerPrice.Low = tick.Data.Low.Value - tickerPrice.Last = tick.Data.Last.Value - tickerPrice.Volume = tick.Data.Vol.Value - tickerPrice.High = tick.Data.High.Value + + if tick.Data.Sell.Value != "" { + tickerPrice.Ask, err = strconv.ParseFloat(tick.Data.Sell.Value, 64) + if err != nil { + return tickerPrice, err + } + } else { + tickerPrice.Ask = 0 + } + + if tick.Data.Buy.Value != "" { + tickerPrice.Bid, err = strconv.ParseFloat(tick.Data.Buy.Value, 64) + if err != nil { + return tickerPrice, err + } + } else { + tickerPrice.Bid = 0 + } + + if tick.Data.Low.Value != "" { + tickerPrice.Low, err = strconv.ParseFloat(tick.Data.Low.Value, 64) + if err != nil { + return tickerPrice, err + } + } else { + tickerPrice.Low = 0 + } + + if tick.Data.Last.Value != "" { + tickerPrice.Last, err = strconv.ParseFloat(tick.Data.Last.Value, 64) + if err != nil { + return tickerPrice, err + } + } else { + tickerPrice.Last = 0 + } + + if tick.Data.Vol.Value != "" { + tickerPrice.Volume, err = strconv.ParseFloat(tick.Data.Vol.Value, 64) + if err != nil { + return tickerPrice, err + } + } else { + tickerPrice.Volume = 0 + } + + if tick.Data.High.Value != "" { + tickerPrice.High, err = strconv.ParseFloat(tick.Data.High.Value, 64) + if err != nil { + return tickerPrice, err + } + } else { + tickerPrice.High = 0 + } ticker.ProcessTicker(a.GetName(), p, tickerPrice) return tickerPrice, nil } diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go index f18e8bb5..f1e14800 100644 --- a/exchanges/bitfinex/bitfinex.go +++ b/exchanges/bitfinex/bitfinex.go @@ -81,6 +81,10 @@ func (b *Bitfinex) SetDefaults() { b.Websocket = false b.RESTPollingDelay = 10 b.WebsocketSubdChannels = make(map[int]WebsocketChanInfo) + b.RequestCurrencyPairFormat.Delimiter = "" + b.RequestCurrencyPairFormat.Uppercase = true + b.ConfigCurrencyPairFormat.Delimiter = "" + b.ConfigCurrencyPairFormat.Uppercase = true } // Setup takes in the supplied exchange configuration details and sets params @@ -97,6 +101,10 @@ func (b *Bitfinex) Setup(exch config.ExchangeConfig) { b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := b.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 65730c16..95268ce7 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -33,15 +33,16 @@ func (b *Bitfinex) Run() { if err != nil { log.Printf("%s Failed to get available symbols.\n", b.GetName()) } else { - err = b.UpdateAvailableCurrencies(exchangeProducts) + err = b.UpdateAvailableCurrencies(exchangeProducts, false) if err != nil { log.Printf("%s Failed to get config.\n", b.GetName()) } } for b.Enabled { - for _, x := range b.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := b.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := b.GetTickerPrice(currency) if err != nil { diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index 8c4c3688..0cf02579 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -55,6 +55,10 @@ func (b *Bitstamp) SetDefaults() { b.Verbose = false b.Websocket = false b.RESTPollingDelay = 10 + b.RequestCurrencyPairFormat.Delimiter = "" + b.RequestCurrencyPairFormat.Uppercase = true + b.ConfigCurrencyPairFormat.Delimiter = "" + b.ConfigCurrencyPairFormat.Uppercase = true } func (b *Bitstamp) Setup(exch config.ExchangeConfig) { @@ -70,6 +74,10 @@ func (b *Bitstamp) Setup(exch config.ExchangeConfig) { b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := b.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index 76710f91..bae10f95 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -28,8 +28,9 @@ func (b *Bitstamp) Run() { } for b.Enabled { - for _, x := range b.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := b.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := b.GetTickerPrice(currency) if err != nil { diff --git a/exchanges/bittrex/bittrex.go b/exchanges/bittrex/bittrex.go index cdcb857a..b5ffd7a9 100644 --- a/exchanges/bittrex/bittrex.go +++ b/exchanges/bittrex/bittrex.go @@ -66,6 +66,10 @@ func (b *Bittrex) SetDefaults() { b.Verbose = false b.Websocket = false b.RESTPollingDelay = 10 + b.RequestCurrencyPairFormat.Delimiter = "-" + b.RequestCurrencyPairFormat.Uppercase = true + b.ConfigCurrencyPairFormat.Delimiter = "-" + b.ConfigCurrencyPairFormat.Uppercase = true } // Setup method sets current configuration details if enabled @@ -82,6 +86,10 @@ func (b *Bittrex) Setup(exch config.ExchangeConfig) { b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := b.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go index 7689a478..645ddf30 100644 --- a/exchanges/bittrex/bittrex_wrapper.go +++ b/exchanges/bittrex/bittrex_wrapper.go @@ -28,24 +28,37 @@ func (b *Bittrex) Run() { if err != nil { log.Printf("%s Failed to get available symbols.\n", b.GetName()) } else { + forceUpgrade := false + if !common.DataContains(b.EnabledPairs, "-") || !common.DataContains(b.AvailablePairs, "-") { + forceUpgrade = true + } var currencies []string for x := range exchangeProducts { if !exchangeProducts[x].IsActive { continue } - currencies = append(currencies, - common.ReplaceString(exchangeProducts[x].MarketName, "-", "", -1)) + currencies = append(currencies, exchangeProducts[x].MarketName) } - err = b.UpdateAvailableCurrencies(currencies) + + if forceUpgrade { + enabledPairs := []string{"USDT-BTC"} + log.Println("WARNING: Available pairs for Bittrex reset due to config upgrade, please enable the ones you would like again") + + err = b.UpdateEnabledCurrencies(enabledPairs, true) + if err != nil { + log.Printf("%s Failed to get config.\n", b.GetName()) + } + } + err = b.UpdateAvailableCurrencies(currencies, forceUpgrade) if err != nil { log.Printf("%s Failed to get config.\n", b.GetName()) } } for b.Enabled { - for _, x := range b.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) - currency.Delimiter = "-" + pairs := b.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := b.GetTickerPrice(currency) if err != nil { @@ -87,7 +100,7 @@ func (b *Bittrex) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error } var tickerPrice ticker.TickerPrice - tick, err := b.GetMarketSummary(p.Pair().Lower().String()) + tick, err := b.GetMarketSummary(exchange.FormatExchangeCurrency(b.GetName(), p).String()) if err != nil { return tickerPrice, err } @@ -108,7 +121,7 @@ func (b *Bittrex) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, } var orderBook orderbook.OrderbookBase - orderbookNew, err := b.GetOrderbook(p.Pair().Lower().String()) + orderbookNew, err := b.GetOrderbook(exchange.FormatExchangeCurrency(b.GetName(), p).String()) if err != nil { return orderBook, err } diff --git a/exchanges/btcc/btcc.go b/exchanges/btcc/btcc.go index 802f114c..86afe3cd 100644 --- a/exchanges/btcc/btcc.go +++ b/exchanges/btcc/btcc.go @@ -53,6 +53,10 @@ func (b *BTCC) SetDefaults() { b.Verbose = false b.Websocket = false b.RESTPollingDelay = 10 + b.RequestCurrencyPairFormat.Delimiter = "" + b.RequestCurrencyPairFormat.Uppercase = false + b.ConfigCurrencyPairFormat.Delimiter = "" + b.ConfigCurrencyPairFormat.Uppercase = true } //Setup is run on startup to setup exchange with config values @@ -69,6 +73,10 @@ func (b *BTCC) Setup(exch config.ExchangeConfig) { b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := b.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/btcc/btcc_wrapper.go b/exchanges/btcc/btcc_wrapper.go index bccf0296..45a24c90 100644 --- a/exchanges/btcc/btcc_wrapper.go +++ b/exchanges/btcc/btcc_wrapper.go @@ -28,8 +28,9 @@ func (b *BTCC) Run() { } for b.Enabled { - for _, x := range b.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := b.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := b.GetTickerPrice(currency) if err != nil { @@ -51,7 +52,7 @@ func (b *BTCC) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { } var tickerPrice ticker.TickerPrice - tick, err := b.GetTicker(p.Pair().Lower().String()) + tick, err := b.GetTicker(exchange.FormatExchangeCurrency(b.GetName(), p).String()) if err != nil { return tickerPrice, err } @@ -74,7 +75,7 @@ func (b *BTCC) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, err } var orderBook orderbook.OrderbookBase - orderbookNew, err := b.GetOrderBook(p.Pair().Lower().String(), 100) + orderbookNew, err := b.GetOrderBook(exchange.FormatExchangeCurrency(b.GetName(), p).String(), 100) if err != nil { return orderBook, err } diff --git a/exchanges/btce/btce.go b/exchanges/btce/btce.go index f96819c3..bebd3674 100644 --- a/exchanges/btce/btce.go +++ b/exchanges/btce/btce.go @@ -48,6 +48,11 @@ func (b *BTCE) SetDefaults() { b.Websocket = false b.RESTPollingDelay = 10 b.Ticker = make(map[string]BTCeTicker) + b.RequestCurrencyPairFormat.Delimiter = "_" + b.RequestCurrencyPairFormat.Uppercase = false + b.RequestCurrencyPairFormat.Separator = "-" + b.ConfigCurrencyPairFormat.Delimiter = "" + b.ConfigCurrencyPairFormat.Uppercase = true } func (b *BTCE) Setup(exch config.ExchangeConfig) { @@ -63,7 +68,10 @@ func (b *BTCE) Setup(exch config.ExchangeConfig) { b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") - + err := b.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/btce/btce_wrapper.go b/exchanges/btce/btce_wrapper.go index c3d6bed9..786fe23c 100644 --- a/exchanges/btce/btce_wrapper.go +++ b/exchanges/btce/btce_wrapper.go @@ -24,16 +24,17 @@ func (b *BTCE) Run() { log.Printf("%s %d currencies enabled: %s.\n", b.GetName(), len(b.EnabledPairs), b.EnabledPairs) } - pairs := []string{} - for _, x := range b.EnabledPairs { - x = common.StringToLower(x[0:3] + "_" + x[3:6]) - pairs = append(pairs, x) + pairs := b.GetEnabledCurrencies() + pairsCollated, err := exchange.GetAndFormatExchangeCurrencies(b.Name, pairs) + if err != nil { + log.Println(err) + b.Enabled = false + return } - pairsString := common.JoinStrings(pairs, "-") for b.Enabled { go func() { - ticker, err := b.GetTicker(pairsString) + ticker, err := b.GetTicker(pairsCollated.String()) if err != nil { log.Println(err) return @@ -51,9 +52,9 @@ func (b *BTCE) Run() { func (b *BTCE) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice - tick, ok := b.Ticker[p.Pair().Lower().String()] + tick, ok := b.Ticker[exchange.FormatExchangeCurrency(b.Name, p).String()] if !ok { - return tickerPrice, errors.New("Unable to get currency.") + return tickerPrice, errors.New("unable to get currency") } tickerPrice.Pair = p tickerPrice.Ask = tick.Buy @@ -73,7 +74,7 @@ func (b *BTCE) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, err } var orderBook orderbook.OrderbookBase - orderbookNew, err := b.GetDepth(p.Pair().Lower().String()) + orderbookNew, err := b.GetDepth(exchange.FormatExchangeCurrency(b.Name, p).String()) if err != nil { return orderBook, err } diff --git a/exchanges/btcmarkets/btcmarkets.go b/exchanges/btcmarkets/btcmarkets.go index 6f7fe3fb..0760585b 100644 --- a/exchanges/btcmarkets/btcmarkets.go +++ b/exchanges/btcmarkets/btcmarkets.go @@ -38,6 +38,10 @@ func (b *BTCMarkets) SetDefaults() { b.Websocket = false b.RESTPollingDelay = 10 b.Ticker = make(map[string]BTCMarketsTicker) + b.RequestCurrencyPairFormat.Delimiter = "" + b.RequestCurrencyPairFormat.Uppercase = true + b.ConfigCurrencyPairFormat.Delimiter = "" + b.ConfigCurrencyPairFormat.Uppercase = true } func (b *BTCMarkets) Setup(exch config.ExchangeConfig) { @@ -53,7 +57,10 @@ func (b *BTCMarkets) Setup(exch config.ExchangeConfig) { b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") - + err := b.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index 2ba3ed2f..ea480f0c 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -4,6 +4,8 @@ import ( "log" "time" + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/currency" "github.com/thrasher-/gocryptotrader/currency/pair" "github.com/thrasher-/gocryptotrader/exchanges" @@ -22,9 +24,36 @@ func (b *BTCMarkets) Run() { log.Printf("%s %d currencies enabled: %s.\n", b.GetName(), len(b.EnabledPairs), b.EnabledPairs) } + if !common.DataContains(b.EnabledPairs, "AUD") || !common.DataContains(b.EnabledPairs, "AUD") { + enabledPairs := []string{} + for x := range b.EnabledPairs { + enabledPairs = append(enabledPairs, b.EnabledPairs[x]+"AUD") + } + + availablePairs := []string{} + for x := range b.AvailablePairs { + availablePairs = append(availablePairs, b.AvailablePairs[x]+"AUD") + } + + log.Println("BTCMarkets: Upgrading available and enabled pairs") + + err := b.UpdateEnabledCurrencies(enabledPairs, true) + if err != nil { + log.Printf("%s Failed to get config.\n", b.GetName()) + return + } + + err = b.UpdateAvailableCurrencies(availablePairs, true) + if err != nil { + log.Printf("%s Failed to get config.\n", b.GetName()) + return + } + } + for b.Enabled { - for _, x := range b.EnabledPairs { - curr := pair.NewCurrencyPair(x, "AUD") + pairs := b.GetEnabledCurrencies() + for x := range pairs { + curr := pairs[x] go func() { ticker, err := b.GetTickerPrice(curr) if err != nil { diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go index 5d262881..a26d966c 100644 --- a/exchanges/coinut/coinut.go +++ b/exchanges/coinut/coinut.go @@ -48,6 +48,10 @@ func (c *COINUT) SetDefaults() { c.Verbose = false c.Websocket = false c.RESTPollingDelay = 10 + c.RequestCurrencyPairFormat.Delimiter = "" + c.RequestCurrencyPairFormat.Uppercase = true + c.ConfigCurrencyPairFormat.Delimiter = "" + c.ConfigCurrencyPairFormat.Uppercase = true } func (c *COINUT) Setup(exch config.ExchangeConfig) { @@ -63,6 +67,10 @@ func (c *COINUT) Setup(exch config.ExchangeConfig) { c.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") c.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") c.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := c.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index 66dcd242..96c65c86 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -40,14 +40,15 @@ func (c *COINUT) Run() { currencies = append(currencies, x) } - err = c.UpdateAvailableCurrencies(currencies) + err = c.UpdateAvailableCurrencies(currencies, false) if err != nil { log.Printf("%s Failed to get config.\n", c.GetName()) } for c.Enabled { - for _, x := range c.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := c.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := c.GetTickerPrice(currency) if err != nil { @@ -62,8 +63,8 @@ func (c *COINUT) Run() { } } -//GetExchangeAccountInfo : Retrieves balances for all enabled currencies for the COINUT exchange -func (e *COINUT) GetExchangeAccountInfo() (exchange.AccountInfo, error) { +// GetExchangeAccountInfo : Retrieves balances for all enabled currencies for the COINUT exchange +func (c *COINUT) GetExchangeAccountInfo() (exchange.AccountInfo, error) { var response exchange.AccountInfo /* response.ExchangeName = e.GetName() diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 3eb08590..fc13269d 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -51,6 +51,8 @@ type Base struct { EnabledPairs []string WebsocketURL string APIUrl string + RequestCurrencyPairFormat config.CurrencyPairFormatConfig + ConfigCurrencyPairFormat config.CurrencyPairFormatConfig } // IBotExchange enforces standard functions for all exchanges supported in @@ -63,11 +65,51 @@ type IBotExchange interface { IsEnabled() bool GetTickerPrice(currency pair.CurrencyPair) (ticker.TickerPrice, error) GetOrderbookEx(currency pair.CurrencyPair) (orderbook.OrderbookBase, error) - GetEnabledCurrencies() []string + GetEnabledCurrencies() []pair.CurrencyPair GetExchangeAccountInfo() (AccountInfo, error) GetAuthenticatedAPISupport() bool } +// SetCurrencyPairFormat checks the exchange request and config currency pair +// formats and sets it to a default setting if it doesn't exist +func (e *Base) SetCurrencyPairFormat() error { + cfg := config.GetConfig() + exch, err := cfg.GetExchangeConfig(e.Name) + if err != nil { + return err + } + + update := false + if exch.RequestCurrencyPairFormat == nil { + exch.RequestCurrencyPairFormat = &config.CurrencyPairFormatConfig{ + Delimiter: e.RequestCurrencyPairFormat.Delimiter, + Uppercase: e.RequestCurrencyPairFormat.Uppercase, + Separator: e.RequestCurrencyPairFormat.Separator, + Index: e.RequestCurrencyPairFormat.Index, + } + update = true + } else { + e.RequestCurrencyPairFormat = *exch.RequestCurrencyPairFormat + } + + if exch.ConfigCurrencyPairFormat == nil { + exch.ConfigCurrencyPairFormat = &config.CurrencyPairFormatConfig{ + Delimiter: e.ConfigCurrencyPairFormat.Delimiter, + Uppercase: e.ConfigCurrencyPairFormat.Uppercase, + Separator: e.ConfigCurrencyPairFormat.Separator, + Index: e.ConfigCurrencyPairFormat.Index, + } + update = true + } else { + e.ConfigCurrencyPairFormat = *exch.ConfigCurrencyPairFormat + } + + if update { + return cfg.UpdateExchangeConfig(exch) + } + return nil +} + // GetAuthenticatedAPISupport returns whether the exchange supports // authenticated API requests func (e *Base) GetAuthenticatedAPISupport() bool { @@ -81,14 +123,135 @@ func (e *Base) GetName() string { // GetEnabledCurrencies is a method that returns the enabled currency pairs of // the exchange base -func (e *Base) GetEnabledCurrencies() []string { - return e.EnabledPairs +func (e *Base) GetEnabledCurrencies() []pair.CurrencyPair { + var pairs []pair.CurrencyPair + for x := range e.EnabledPairs { + var currencyPair pair.CurrencyPair + if e.RequestCurrencyPairFormat.Delimiter != "" { + if e.ConfigCurrencyPairFormat.Delimiter != "" { + if e.ConfigCurrencyPairFormat.Delimiter == e.RequestCurrencyPairFormat.Delimiter { + currencyPair = pair.NewCurrencyPairDelimiter(e.EnabledPairs[x], + e.RequestCurrencyPairFormat.Delimiter) + } else { + currencyPair = pair.NewCurrencyPairDelimiter(e.EnabledPairs[x], + e.ConfigCurrencyPairFormat.Delimiter) + currencyPair.Delimiter = "-" + } + } else { + if e.ConfigCurrencyPairFormat.Index != "" { + currencyPair = pair.NewCurrencyPairFromIndex(e.EnabledPairs[x], + e.ConfigCurrencyPairFormat.Index) + } else { + currencyPair = pair.NewCurrencyPair(e.EnabledPairs[x][0:3], + e.EnabledPairs[x][3:]) + } + } + } else { + if e.ConfigCurrencyPairFormat.Delimiter != "" { + currencyPair = pair.NewCurrencyPairDelimiter(e.EnabledPairs[x], + e.ConfigCurrencyPairFormat.Delimiter) + } else { + if e.ConfigCurrencyPairFormat.Index != "" { + currencyPair = pair.NewCurrencyPairFromIndex(e.EnabledPairs[x], + e.ConfigCurrencyPairFormat.Index) + } else { + currencyPair = pair.NewCurrencyPair(e.EnabledPairs[x][0:3], + e.EnabledPairs[x][3:]) + } + } + } + pairs = append(pairs, currencyPair) + } + return pairs } // GetAvailableCurrencies is a method that returns the available currency pairs // of the exchange base -func (e *Base) GetAvailableCurrencies() []string { - return e.AvailablePairs +func (e *Base) GetAvailableCurrencies() []pair.CurrencyPair { + var pairs []pair.CurrencyPair + for x := range e.AvailablePairs { + var currencyPair pair.CurrencyPair + if e.RequestCurrencyPairFormat.Delimiter != "" { + if e.ConfigCurrencyPairFormat.Delimiter != "" { + if e.ConfigCurrencyPairFormat.Delimiter == e.RequestCurrencyPairFormat.Delimiter { + currencyPair = pair.NewCurrencyPairDelimiter(e.AvailablePairs[x], + e.RequestCurrencyPairFormat.Delimiter) + } else { + currencyPair = pair.NewCurrencyPairDelimiter(e.AvailablePairs[x], + e.ConfigCurrencyPairFormat.Delimiter) + currencyPair.Delimiter = "-" + } + } else { + if e.ConfigCurrencyPairFormat.Index != "" { + currencyPair = pair.NewCurrencyPairFromIndex(e.AvailablePairs[x], + e.ConfigCurrencyPairFormat.Index) + } else { + currencyPair = pair.NewCurrencyPair(e.AvailablePairs[x][0:3], + e.AvailablePairs[x][3:]) + } + } + } else { + if e.ConfigCurrencyPairFormat.Delimiter != "" { + currencyPair = pair.NewCurrencyPairDelimiter(e.AvailablePairs[x], + e.ConfigCurrencyPairFormat.Delimiter) + } else { + if e.ConfigCurrencyPairFormat.Index != "" { + currencyPair = pair.NewCurrencyPairFromIndex(e.AvailablePairs[x], + e.ConfigCurrencyPairFormat.Index) + } else { + currencyPair = pair.NewCurrencyPair(e.AvailablePairs[x][0:3], + e.AvailablePairs[x][3:]) + } + } + } + pairs = append(pairs, currencyPair) + } + return pairs +} + +// GetExchangeFormatCurrencySeperator returns whether or not a specific +// exchange contains a separator used for API requests +func GetExchangeFormatCurrencySeperator(exchName string) bool { + cfg := config.GetConfig() + exch, err := cfg.GetExchangeConfig(exchName) + if err != nil { + return false + } + + if exch.RequestCurrencyPairFormat.Separator != "" { + return true + } + return false +} + +// GetAndFormatExchangeCurrencies returns a pair.CurrencyItem string containing +// the exchanges formatted currency pairs +func GetAndFormatExchangeCurrencies(exchName string, pairs []pair.CurrencyPair) (pair.CurrencyItem, error) { + var currencyItems pair.CurrencyItem + cfg := config.GetConfig() + exch, err := cfg.GetExchangeConfig(exchName) + if err != nil { + return currencyItems, err + } + + for x := range pairs { + currencyItems += FormatExchangeCurrency(exchName, pairs[x]) + if x == len(pairs)-1 { + continue + } + currencyItems += pair.CurrencyItem(exch.RequestCurrencyPairFormat.Separator) + } + return currencyItems, nil +} + +// FormatExchangeCurrency is a method that formats and returns a currency pair +// based on the user currency display preferences +func FormatExchangeCurrency(exchName string, p pair.CurrencyPair) pair.CurrencyItem { + cfg := config.GetConfig() + exch, _ := cfg.GetExchangeConfig(exchName) + + return p.Display(exch.RequestCurrencyPairFormat.Delimiter, + exch.RequestCurrencyPairFormat.Uppercase) } // FormatCurrency is a method that formats and returns a currency pair @@ -126,20 +289,50 @@ func (e *Base) SetAPIKeys(APIKey, APISecret, ClientID string, b64Decode bool) { } } -// UpdateAvailableCurrencies is a method that sets new pairs to the current -// exchange -func (e *Base) UpdateAvailableCurrencies(exchangeProducts []string) error { +// UpdateEnabledCurrencies is a method that sets new pairs to the current +// exchange. Setting force to true upgrades the enabled currencies +func (e *Base) UpdateEnabledCurrencies(exchangeProducts []string, force bool) error { exchangeProducts = common.SplitStrings(common.StringToUpper(common.JoinStrings(exchangeProducts, ",")), ",") - diff := common.StringSliceDifference(e.AvailablePairs, exchangeProducts) - if len(diff) > 0 { + diff := common.StringSliceDifference(e.EnabledPairs, exchangeProducts) + if force || len(diff) > 0 { cfg := config.GetConfig() exch, err := cfg.GetExchangeConfig(e.Name) if err != nil { return err } - log.Printf("%s Updating available pairs. Difference: %s.\n", e.Name, diff) - exch.AvailablePairs = common.JoinStrings(exchangeProducts, ",") - cfg.UpdateExchangeConfig(exch) + + if force { + log.Printf("%s forced update of enabled pairs.", e.Name) + } else { + log.Printf("%s Updating available pairs. Difference: %s.\n", e.Name, diff) + } + exch.EnabledPairs = common.JoinStrings(exchangeProducts, ",") + e.EnabledPairs = exchangeProducts + return cfg.UpdateExchangeConfig(exch) + } + return nil +} + +// UpdateAvailableCurrencies is a method that sets new pairs to the current +// exchange. Setting force to true upgrades the available currencies +func (e *Base) UpdateAvailableCurrencies(exchangeProducts []string, force bool) error { + exchangeProducts = common.SplitStrings(common.StringToUpper(common.JoinStrings(exchangeProducts, ",")), ",") + diff := common.StringSliceDifference(e.AvailablePairs, exchangeProducts) + if force || len(diff) > 0 { + cfg := config.GetConfig() + exch, err := cfg.GetExchangeConfig(e.Name) + if err != nil { + return err + } + + if force { + log.Printf("%s forced update of available pairs.", e.Name) + } else { + log.Printf("%s Updating available pairs. Difference: %s.\n", e.Name, diff) + } + exch.AvailablePairs = common.JoinStrings(exchangeProducts, ",") + e.AvailablePairs = exchangeProducts + return cfg.UpdateExchangeConfig(exch) } return nil } diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index bc17f371..a3bff955 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -3,9 +3,8 @@ package exchange import ( "testing" - "github.com/thrasher-/gocryptotrader/currency/pair" - "github.com/thrasher-/gocryptotrader/config" + "github.com/thrasher-/gocryptotrader/currency/pair" ) func TestGetName(t *testing.T) { @@ -19,6 +18,29 @@ func TestGetName(t *testing.T) { } } +func TestSetCurrencyPairFormat(t *testing.T) { + cfg := config.GetConfig() + err := cfg.LoadConfig(config.ConfigTestFile) + if err != nil { + t.Fatalf("Failed to load config file. Error: %s", err) + } + + exch, err := cfg.GetExchangeConfig("GDAX") + if err != nil { + t.Fatalf("Failed to load GDAX exchange config. Error: %s", err) + } + + exch.RequestCurrencyPairFormat = nil + exch.ConfigCurrencyPairFormat = nil + + err = cfg.UpdateExchangeConfig(exch) + if err != nil { + t.Fatalf("Failed to update GDAX config. Error: %s", err) + } + + // to-do +} + func TestGetEnabledCurrencies(t *testing.T) { enabledPairs := []string{"BTCUSD", "BTCAUD", "LTCUSD", "LTCAUD"} GetEnabledCurrencies := Base{ @@ -27,7 +49,7 @@ func TestGetEnabledCurrencies(t *testing.T) { } enCurr := GetEnabledCurrencies.GetEnabledCurrencies() - if enCurr[0] != "BTCUSD" { + if enCurr[0].Pair().String() != "BTCUSD" { t.Error("Test Failed - Exchange GetEnabledCurrencies() incorrect string") } } @@ -40,11 +62,75 @@ func TestGetAvailableCurrencies(t *testing.T) { } enCurr := GetEnabledCurrencies.GetAvailableCurrencies() - if enCurr[0] != "BTCUSD" { + if enCurr[0].Pair().String() != "BTCUSD" { t.Error("Test Failed - Exchange GetAvailableCurrencies() incorrect string") } } +func TestGetExchangeFormatCurrencySeperator(t *testing.T) { + cfg := config.GetConfig() + err := cfg.LoadConfig(config.ConfigTestFile) + if err != nil { + t.Fatalf("Failed to load config file. Error: %s", err) + } + + expected := true + actual := GetExchangeFormatCurrencySeperator("BTCE") + + if expected != actual { + t.Errorf("Test failed - TestGetExchangeFormatCurrencySeperator expected %v != actual %v", + expected, actual) + } + + expected = false + actual = GetExchangeFormatCurrencySeperator("LocalBitcoins") + + if expected != actual { + t.Errorf("Test failed - TestGetExchangeFormatCurrencySeperator expected %v != actual %v", + expected, actual) + } +} + +func TestGetAndFormatExchangeCurrencies(t *testing.T) { + cfg := config.GetConfig() + err := cfg.LoadConfig(config.ConfigTestFile) + if err != nil { + t.Fatalf("Failed to load config file. Error: %s", err) + } + + var pairs []pair.CurrencyPair + pairs = append(pairs, pair.NewCurrencyPairDelimiter("BTC_USD", "_")) + pairs = append(pairs, pair.NewCurrencyPairDelimiter("LTC_BTC", "_")) + + actual, err := GetAndFormatExchangeCurrencies("Liqui", pairs) + if err != nil { + t.Errorf("Test failed - Exchange TestGetAndFormatExchangeCurrencies error %s", err) + } + expected := pair.CurrencyItem("btc_usd-ltc_btc") + + if actual.String() != expected.String() { + t.Errorf("Test failed - Exchange TestGetAndFormatExchangeCurrencies %s != %s", + actual, expected) + } +} + +func TestFormatExchangeCurrency(t *testing.T) { + cfg := config.GetConfig() + err := cfg.LoadConfig(config.ConfigTestFile) + if err != nil { + t.Fatalf("Failed to load config file. Error: %s", err) + } + + pair := pair.NewCurrencyPair("BTC", "USD") + expected := "BTC-USD" + actual := FormatExchangeCurrency("GDAX", pair) + + if actual.String() != expected { + t.Errorf("Test failed - Exchange TestFormatExchangeCurrency %s != %s", + actual, expected) + } +} + func TestFormatCurrency(t *testing.T) { cfg := config.GetConfig() err := cfg.LoadConfig(config.ConfigTestFile) @@ -97,6 +183,23 @@ func TestSetAPIKeys(t *testing.T) { SetAPIKeys.SetAPIKeys("RocketMan", "Digereedoo", "007", true) } +func TestUpdateEnabledCurrencies(t *testing.T) { + cfg := config.GetConfig() + err := cfg.LoadConfig(config.ConfigTestFile) + UAC := Base{Name: "ANX"} + enabledCurrencies := []string{"ltc", "btc", "usd", "aud"} + + if err != nil { + t.Error( + "Test Failed - Exchange UpdateEnabledCurrencies() did not set correct values", + ) + } + err2 := UAC.UpdateEnabledCurrencies(enabledCurrencies, false) + if err2 != nil { + t.Errorf("Test Failed - Exchange UpdateEnabledCurrencies() error: %s", err2) + } +} + func TestUpdateAvailableCurrencies(t *testing.T) { cfg := config.GetConfig() err := cfg.LoadConfig(config.ConfigTestFile) @@ -108,7 +211,7 @@ func TestUpdateAvailableCurrencies(t *testing.T) { "Test Failed - Exchange UpdateAvailableCurrencies() did not set correct values", ) } - err2 := UAC.UpdateAvailableCurrencies(exchangeProducts) + err2 := UAC.UpdateAvailableCurrencies(exchangeProducts, false) if err2 != nil { t.Errorf("Test Failed - Exchange UpdateAvailableCurrencies() error: %s", err2) } diff --git a/exchanges/gdax/gdax.go b/exchanges/gdax/gdax.go index 7c73f68d..04a2d361 100644 --- a/exchanges/gdax/gdax.go +++ b/exchanges/gdax/gdax.go @@ -46,6 +46,10 @@ func (g *GDAX) SetDefaults() { g.Verbose = false g.Websocket = false g.RESTPollingDelay = 10 + g.RequestCurrencyPairFormat.Delimiter = "-" + g.RequestCurrencyPairFormat.Uppercase = true + g.ConfigCurrencyPairFormat.Delimiter = "" + g.ConfigCurrencyPairFormat.Uppercase = true } func (g *GDAX) Setup(exch config.ExchangeConfig) { @@ -61,6 +65,10 @@ func (g *GDAX) Setup(exch config.ExchangeConfig) { g.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") g.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") g.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := g.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/gdax/gdax_wrapper.go b/exchanges/gdax/gdax_wrapper.go index 88d41e43..6c519990 100644 --- a/exchanges/gdax/gdax_wrapper.go +++ b/exchanges/gdax/gdax_wrapper.go @@ -37,16 +37,16 @@ func (g *GDAX) Run() { currencies = append(currencies, x.ID[0:3]+x.ID[4:]) } } - err = g.UpdateAvailableCurrencies(currencies) + err = g.UpdateAvailableCurrencies(currencies, false) if err != nil { log.Printf("%s Failed to get config.\n", g.GetName()) } } for g.Enabled { - for _, x := range g.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) - currency.Delimiter = "-" + pairs := g.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := g.GetTickerPrice(currency) @@ -88,12 +88,12 @@ func (g *GDAX) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { } var tickerPrice ticker.TickerPrice - tick, err := g.GetTicker(p.Pair().String()) + tick, err := g.GetTicker(exchange.FormatExchangeCurrency(g.Name, p).String()) if err != nil { return ticker.TickerPrice{}, err } - stats, err := g.GetStats(p.Pair().String()) + stats, err := g.GetStats(exchange.FormatExchangeCurrency(g.Name, p).String()) if err != nil { return ticker.TickerPrice{}, err diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go index 654347da..638ebd6c 100644 --- a/exchanges/gemini/gemini.go +++ b/exchanges/gemini/gemini.go @@ -45,6 +45,10 @@ func (g *Gemini) SetDefaults() { g.Verbose = false g.Websocket = false g.RESTPollingDelay = 10 + g.RequestCurrencyPairFormat.Delimiter = "" + g.RequestCurrencyPairFormat.Uppercase = true + g.ConfigCurrencyPairFormat.Delimiter = "" + g.ConfigCurrencyPairFormat.Uppercase = true } func (g *Gemini) Setup(exch config.ExchangeConfig) { @@ -60,6 +64,10 @@ func (g *Gemini) Setup(exch config.ExchangeConfig) { g.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") g.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") g.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := g.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index 272f5eb9..4e266d66 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -26,15 +26,16 @@ func (g *Gemini) Run() { if err != nil { log.Printf("%s Failed to get available symbols.\n", g.GetName()) } else { - err = g.UpdateAvailableCurrencies(exchangeProducts) + err = g.UpdateAvailableCurrencies(exchangeProducts, false) if err != nil { log.Printf("%s Failed to get config.\n", g.GetName()) } } for g.Enabled { - for _, x := range g.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := g.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := g.GetTickerPrice(currency) if err != nil { diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index f3edab71..a4d65a93 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -29,6 +29,10 @@ func (h *HUOBI) SetDefaults() { h.Verbose = false h.Websocket = false h.RESTPollingDelay = 10 + h.RequestCurrencyPairFormat.Delimiter = "" + h.RequestCurrencyPairFormat.Uppercase = false + h.ConfigCurrencyPairFormat.Delimiter = "" + h.ConfigCurrencyPairFormat.Uppercase = true } func (h *HUOBI) Setup(exch config.ExchangeConfig) { @@ -44,6 +48,10 @@ func (h *HUOBI) Setup(exch config.ExchangeConfig) { h.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") h.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") h.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := h.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index a17c28d2..9324b984 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -29,8 +29,9 @@ func (h *HUOBI) Run() { } for h.Enabled { - for _, x := range h.EnabledPairs { - curr := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := h.GetEnabledCurrencies() + for x := range pairs { + curr := pairs[x] go func() { ticker, err := h.GetTickerPrice(curr) if err != nil { diff --git a/exchanges/itbit/itbit.go b/exchanges/itbit/itbit.go index 47a97532..ae2f1b94 100644 --- a/exchanges/itbit/itbit.go +++ b/exchanges/itbit/itbit.go @@ -31,6 +31,10 @@ func (i *ItBit) SetDefaults() { i.Verbose = false i.Websocket = false i.RESTPollingDelay = 10 + i.RequestCurrencyPairFormat.Delimiter = "" + i.RequestCurrencyPairFormat.Uppercase = true + i.ConfigCurrencyPairFormat.Delimiter = "" + i.ConfigCurrencyPairFormat.Uppercase = true } func (i *ItBit) Setup(exch config.ExchangeConfig) { @@ -46,6 +50,10 @@ func (i *ItBit) Setup(exch config.ExchangeConfig) { i.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") i.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") i.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := i.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index deb80fa2..d444c024 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -22,8 +22,9 @@ func (i *ItBit) Run() { } for i.Enabled { - for _, x := range i.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := i.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := i.GetTickerPrice(currency) if err != nil { diff --git a/exchanges/kraken/kraken.go b/exchanges/kraken/kraken.go index 0be7fe3c..ee99b2b4 100644 --- a/exchanges/kraken/kraken.go +++ b/exchanges/kraken/kraken.go @@ -55,6 +55,11 @@ func (k *Kraken) SetDefaults() { k.Websocket = false k.RESTPollingDelay = 10 k.Ticker = make(map[string]KrakenTicker) + k.RequestCurrencyPairFormat.Delimiter = "" + k.RequestCurrencyPairFormat.Uppercase = true + k.RequestCurrencyPairFormat.Separator = "," + k.ConfigCurrencyPairFormat.Delimiter = "" + k.ConfigCurrencyPairFormat.Uppercase = true } func (k *Kraken) Setup(exch config.ExchangeConfig) { @@ -70,6 +75,10 @@ func (k *Kraken) Setup(exch config.ExchangeConfig) { k.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") k.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") k.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := k.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index 7c5626bc..356f7380 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -4,7 +4,6 @@ import ( "log" "time" - "github.com/thrasher-/gocryptotrader/common" "github.com/thrasher-/gocryptotrader/currency/pair" "github.com/thrasher-/gocryptotrader/exchanges" "github.com/thrasher-/gocryptotrader/exchanges/orderbook" @@ -30,21 +29,28 @@ func (k *Kraken) Run() { for _, v := range assetPairs { exchangeProducts = append(exchangeProducts, v.Altname) } - err = k.UpdateAvailableCurrencies(exchangeProducts) + err = k.UpdateAvailableCurrencies(exchangeProducts, false) if err != nil { log.Printf("%s Failed to get config.\n", k.GetName()) } } for k.Enabled { - err := k.GetTicker(common.JoinStrings(k.EnabledPairs, ",")) + pairs := k.GetEnabledCurrencies() + pairsCollated, err := exchange.GetAndFormatExchangeCurrencies(k.Name, pairs) + if err != nil { + log.Println(err) + continue + } + err = k.GetTicker(pairsCollated.String()) if err != nil { log.Println(err) } else { - for _, x := range k.EnabledPairs { - ticker := k.Ticker[x] - log.Printf("Kraken %s Last %f High %f Low %f Volume %f\n", x, ticker.Last, ticker.High, ticker.Low, ticker.Volume) - stats.AddExchangeInfo(k.GetName(), x[0:3], x[3:], ticker.Last, ticker.Volume) + for _, x := range pairs { + ticker := k.Ticker[x.Pair().String()] + log.Printf("Kraken %s Last %f High %f Low %f Volume %f\n", exchange.FormatCurrency(x).String(), ticker.Last, ticker.High, ticker.Low, ticker.Volume) + stats.AddExchangeInfo(k.GetName(), x.GetFirstCurrency().String(), x.GetSecondCurrency().String(), + ticker.Last, ticker.Volume) } } time.Sleep(time.Second * k.RESTPollingDelay) diff --git a/exchanges/lakebtc/lakebtc.go b/exchanges/lakebtc/lakebtc.go index 97121ecb..79c0a9c9 100644 --- a/exchanges/lakebtc/lakebtc.go +++ b/exchanges/lakebtc/lakebtc.go @@ -42,6 +42,10 @@ func (l *LakeBTC) SetDefaults() { l.Verbose = false l.Websocket = false l.RESTPollingDelay = 10 + l.RequestCurrencyPairFormat.Delimiter = "" + l.RequestCurrencyPairFormat.Uppercase = true + l.ConfigCurrencyPairFormat.Delimiter = "" + l.ConfigCurrencyPairFormat.Uppercase = true } func (l *LakeBTC) Setup(exch config.ExchangeConfig) { @@ -57,6 +61,10 @@ func (l *LakeBTC) Setup(exch config.ExchangeConfig) { l.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") l.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") l.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := l.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/lakebtc/lakebtc_wrapper.go b/exchanges/lakebtc/lakebtc_wrapper.go index a2a1f920..8bf35b45 100644 --- a/exchanges/lakebtc/lakebtc_wrapper.go +++ b/exchanges/lakebtc/lakebtc_wrapper.go @@ -23,8 +23,9 @@ func (l *LakeBTC) Run() { } for l.Enabled { - for _, x := range l.EnabledPairs { - currency := pair.NewCurrencyPair(x[0:3], x[3:]) + pairs := l.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] ticker, err := l.GetTickerPrice(currency) if err != nil { log.Println(err) diff --git a/exchanges/liqui/liqui.go b/exchanges/liqui/liqui.go index 15ecdcd2..9c0578e5 100644 --- a/exchanges/liqui/liqui.go +++ b/exchanges/liqui/liqui.go @@ -46,6 +46,11 @@ func (l *Liqui) SetDefaults() { l.Websocket = false l.RESTPollingDelay = 10 l.Ticker = make(map[string]LiquiTicker) + l.RequestCurrencyPairFormat.Delimiter = "_" + l.RequestCurrencyPairFormat.Uppercase = false + l.RequestCurrencyPairFormat.Separator = "-" + l.ConfigCurrencyPairFormat.Delimiter = "_" + l.ConfigCurrencyPairFormat.Uppercase = true } func (l *Liqui) Setup(exch config.ExchangeConfig) { @@ -61,6 +66,10 @@ func (l *Liqui) Setup(exch config.ExchangeConfig) { l.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") l.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") l.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := l.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/liqui/liqui_wrapper.go b/exchanges/liqui/liqui_wrapper.go index 634fc1f4..6ad4a709 100644 --- a/exchanges/liqui/liqui_wrapper.go +++ b/exchanges/liqui/liqui_wrapper.go @@ -29,23 +29,23 @@ func (l *Liqui) Run() { log.Printf("%s Unable to fetch info.\n", l.GetName()) } else { exchangeProducts := l.GetAvailablePairs(true) - err = l.UpdateAvailableCurrencies(exchangeProducts) + err = l.UpdateAvailableCurrencies(exchangeProducts, false) if err != nil { log.Printf("%s Failed to get config.\n", l.GetName()) } } - pairs := []string{} - for _, x := range l.EnabledPairs { - currencies := common.SplitStrings(x, "_") - x = common.StringToLower(currencies[0]) + "_" + common.StringToLower(currencies[1]) - pairs = append(pairs, x) + pairsString, err := exchange.GetAndFormatExchangeCurrencies(l.Name, + l.GetEnabledCurrencies()) + if err != nil { + log.Println(err) + l.Enabled = false + return } - pairsString := common.JoinStrings(pairs, "-") for l.Enabled { go func() { - ticker, err := l.GetTicker(pairsString) + ticker, err := l.GetTicker(pairsString.String()) if err != nil { log.Println(err) return @@ -63,9 +63,9 @@ func (l *Liqui) Run() { func (l *Liqui) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { var tickerPrice ticker.TickerPrice - tick, ok := l.Ticker[p.Pair().Lower().String()] + tick, ok := l.Ticker[exchange.FormatExchangeCurrency(l.Name, p).String()] if !ok { - return tickerPrice, errors.New("Unable to get currency.") + return tickerPrice, errors.New("unable to get currency") } tickerPrice.Pair = p tickerPrice.Ask = tick.Buy @@ -85,7 +85,7 @@ func (l *Liqui) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, er } var orderBook orderbook.OrderbookBase - orderbookNew, err := l.GetDepth(p.Pair().Lower().String()) + orderbookNew, err := l.GetDepth(exchange.FormatExchangeCurrency(l.Name, p).String()) if err != nil { return orderBook, err } diff --git a/exchanges/localbitcoins/localbitcoins.go b/exchanges/localbitcoins/localbitcoins.go index d657869e..5370503e 100644 --- a/exchanges/localbitcoins/localbitcoins.go +++ b/exchanges/localbitcoins/localbitcoins.go @@ -38,6 +38,10 @@ func (l *LocalBitcoins) SetDefaults() { l.Verbose = false l.Websocket = false l.RESTPollingDelay = 10 + l.RequestCurrencyPairFormat.Delimiter = "" + l.RequestCurrencyPairFormat.Uppercase = true + l.ConfigCurrencyPairFormat.Delimiter = "" + l.ConfigCurrencyPairFormat.Uppercase = true } func (l *LocalBitcoins) Setup(exch config.ExchangeConfig) { @@ -53,6 +57,10 @@ func (l *LocalBitcoins) Setup(exch config.ExchangeConfig) { l.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") l.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") l.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := l.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index a4642ba2..9d891da1 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -22,8 +22,9 @@ func (l *LocalBitcoins) Run() { } for l.Enabled { - for _, x := range l.EnabledPairs { - currency := pair.NewCurrencyPair("BTC", x[3:]) + pairs := l.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] ticker, err := l.GetTickerPrice(currency) if err != nil { diff --git a/exchanges/okcoin/okcoin.go b/exchanges/okcoin/okcoin.go index 0f2994aa..47ed673e 100644 --- a/exchanges/okcoin/okcoin.go +++ b/exchanges/okcoin/okcoin.go @@ -78,6 +78,13 @@ type OKCoin struct { WebsocketConn *websocket.Conn } +func (o *OKCoin) setCurrencyPairFormats() { + o.RequestCurrencyPairFormat.Delimiter = "_" + o.RequestCurrencyPairFormat.Uppercase = false + o.ConfigCurrencyPairFormat.Delimiter = "" + o.ConfigCurrencyPairFormat.Uppercase = true +} + func (o *OKCoin) SetDefaults() { o.SetErrorDefaults() o.SetWebsocketErrorDefaults() @@ -92,10 +99,12 @@ func (o *OKCoin) SetDefaults() { o.Name = "OKCOIN International" o.WebsocketURL = OKCOIN_WEBSOCKET_URL okcoinDefaultsSet = true + o.setCurrencyPairFormats() } else { o.APIUrl = OKCOIN_API_URL_CHINA o.Name = "OKCOIN China" o.WebsocketURL = OKCOIN_WEBSOCKET_URL_CHINA + o.setCurrencyPairFormats() } } @@ -112,6 +121,10 @@ func (o *OKCoin) Setup(exch config.ExchangeConfig) { o.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") o.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") o.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := o.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/okcoin/okcoin_wrapper.go b/exchanges/okcoin/okcoin_wrapper.go index 7e869fa6..6677276f 100644 --- a/exchanges/okcoin/okcoin_wrapper.go +++ b/exchanges/okcoin/okcoin_wrapper.go @@ -29,14 +29,14 @@ func (o *OKCoin) Run() { } for o.Enabled { - for _, x := range o.EnabledPairs { - curr := pair.NewCurrencyPair(x[0:3], x[3:]) - curr.Delimiter = "_" + pairs := o.GetEnabledCurrencies() + for x := range pairs { + curr := pairs[x] if o.APIUrl == OKCOIN_API_URL { for _, y := range o.FuturesValues { futuresValue := y go func() { - ticker, err := o.GetFuturesTicker(curr.Pair().Lower().String(), futuresValue) + ticker, err := o.GetFuturesTicker(exchange.FormatExchangeCurrency(o.Name, curr).String(), futuresValue) if err != nil { log.Println(err) return @@ -81,7 +81,7 @@ func (o *OKCoin) GetTickerPrice(currency pair.CurrencyPair) (ticker.TickerPrice, } var tickerPrice ticker.TickerPrice - tick, err := o.GetTicker(currency.Pair().Lower().String()) + tick, err := o.GetTicker(exchange.FormatExchangeCurrency(o.Name, currency).String()) if err != nil { return tickerPrice, err } @@ -103,7 +103,7 @@ func (o *OKCoin) GetOrderbookEx(currency pair.CurrencyPair) (orderbook.Orderbook } var orderBook orderbook.OrderbookBase - orderbookNew, err := o.GetOrderBook(currency.Pair().Lower().String(), 200, false) + orderbookNew, err := o.GetOrderBook(exchange.FormatExchangeCurrency(o.Name, currency).String(), 200, false) if err != nil { return orderBook, err } diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index 0ce8e3b0..e34cde58 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "log" "net/url" "strconv" "time" @@ -57,6 +58,10 @@ func (p *Poloniex) SetDefaults() { p.Verbose = false p.Websocket = false p.RESTPollingDelay = 10 + p.RequestCurrencyPairFormat.Delimiter = "_" + p.RequestCurrencyPairFormat.Uppercase = true + p.ConfigCurrencyPairFormat.Delimiter = "_" + p.ConfigCurrencyPairFormat.Uppercase = true } func (p *Poloniex) Setup(exch config.ExchangeConfig) { @@ -72,6 +77,10 @@ func (p *Poloniex) Setup(exch config.ExchangeConfig) { p.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") p.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") p.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := p.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } } } diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index 1c4220f3..bccc8597 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -28,8 +28,9 @@ func (p *Poloniex) Run() { } for p.Enabled { - for _, x := range p.EnabledPairs { - currency := pair.NewCurrencyPairDelimiter(x, "_") + pairs := p.GetEnabledCurrencies() + for x := range pairs { + currency := pairs[x] go func() { ticker, err := p.GetTickerPrice(currency) if err != nil { diff --git a/testdata/configtest.dat b/testdata/configtest.dat index 9757e8c9..731df5bc 100644 --- a/testdata/configtest.dat +++ b/testdata/configtest.dat @@ -11,26 +11,26 @@ { "Address": "1JCe8z4jJVNXSjohjM4i9Hh813dLCNx2Sy", "CoinType": "BTC", - "Balance": 124178.0002442, - "Decscription": "" + "Balance": 124178.00647714, + "Description": "" }, { "Address": "3Nxwenay9Z8Lc9JBiywExpnEFiLp6Afp8v", "CoinType": "BTC", - "Balance": 103439.83659727, - "Decscription": "" + "Balance": 107843.84030984, + "Description": "" }, { "Address": "LgY8ahfHRhvjVQC1zJnBhFMG5pCTMuKRqh", "CoinType": "LTC", - "Balance": 3000000.05, - "Decscription": "" + "Balance": 100000.052, + "Description": "" }, { "Address": "0xb794f5ea0ba39494ce839613fffba74279579268", "CoinType": "ETH", - "Balance": 5774999.820458524, - "Decscription": "" + "Balance": 3.224999915984445e+24, + "Description": "" } ] }, @@ -64,7 +64,15 @@ "APISecret": "Secret", "AvailablePairs": "BTCUSD,BTCHKD,BTCEUR,BTCCAD,BTCAUD,BTCSGD,BTCJPY,BTCGBP,BTCNZD,LTCBTC,DOGEBTC,STRBTC,XRPBTC", "EnabledPairs": "BTCUSD,BTCHKD,BTCEUR,BTCCAD,BTCAUD,BTCSGD,BTCJPY,BTCGBP,BTCNZD,LTCBTC,DOGEBTC,STRBTC,XRPBTC", - "BaseCurrencies": "USD,HKD,EUR,CAD,AUD,SGD,JPY,GBP,NZD" + "BaseCurrencies": "USD,HKD,EUR,CAD,AUD,SGD,JPY,GBP,NZD", + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Index": "BTC" + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Index": "BTC" + } }, { "Name": "Bitfinex", @@ -75,9 +83,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,BFXUSD,BFXBTC,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC", + "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC,BCCBTC,BCUBTC,BCCUSD,BCUUSD,XRPUSD,XRPBTC,IOTUSD,IOTBTC,IOTETH,EOSUSD,EOSBTC,EOSETH,SANUSD,SANBTC,SANETH,OMGUSD,OMGBTC,OMGETH,BCHUSD,BCHBTC,BCHETH", "EnabledPairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Bitstamp", @@ -91,7 +105,13 @@ "ClientID": "ClientID", "AvailablePairs": "BTCUSD,BTCEUR,EURUSD,XRPUSD,XRPEUR", "EnabledPairs": "BTCUSD,BTCEUR,EURUSD,XRPUSD,XRPEUR", - "BaseCurrencies": "USD,EUR" + "BaseCurrencies": "USD,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "BTCC", @@ -104,7 +124,13 @@ "APISecret": "Secret", "AvailablePairs": "BTCCNY,LTCCNY,LTCBTC", "EnabledPairs": "BTCCNY,LTCCNY,LTCBTC", - "BaseCurrencies": "CNY" + "BaseCurrencies": "CNY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false + } }, { "Name": "BTCE", @@ -117,7 +143,15 @@ "APISecret": "Secret", "AvailablePairs": "BTCUSD,BTCRUR,BTCEUR,LTCBTC,LTCUSD,LTCRUR,LTCEUR,NMCBTC,NMCUSD,NVCBTC,NVCUSD,USDRUR,EURUSD,EURRUR,PPCBTC,PPCUSD", "EnabledPairs": "BTCUSD,BTCRUR,BTCEUR,LTCBTC,LTCUSD,LTCRUR,LTCEUR,NMCBTC,NMCUSD,NVCBTC,NVCUSD,USDRUR,EURUSD,EURRUR,PPCBTC,PPCUSD", - "BaseCurrencies": "USD,RUR,EUR" + "BaseCurrencies": "USD,RUR,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_", + "Separator": "-" + } }, { "Name": "BTC Markets", @@ -128,9 +162,15 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "LTC,BTC", - "EnabledPairs": "LTC,BTC", - "BaseCurrencies": "AUD" + "AvailablePairs": "LTCAUD,BTCAUD", + "EnabledPairs": "LTCAUD,BTCAUD", + "BaseCurrencies": "AUD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "GDAX", @@ -142,9 +182,16 @@ "APIKey": "Key", "APISecret": "Secret", "ClientID": "ClientID", - "AvailablePairs": "BTCGBP,BTCEUR,ETHUSD,ETHBTC,LTCUSD,LTCBTC,BTCUSD", + "AvailablePairs": "LTCEUR,LTCBTC,BTCGBP,BTCEUR,ETHEUR,ETHBTC,LTCUSD,BTCUSD,ETHUSD", "EnabledPairs": "BTCUSD,BTCGBP,BTCEUR", - "BaseCurrencies": "USD,GBP,EUR" + "BaseCurrencies": "USD,GBP,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "-" + } }, { "Name": "Gemini", @@ -157,7 +204,13 @@ "APISecret": "Secret", "AvailablePairs": "BTCUSD,ETHBTC,ETHUSD", "EnabledPairs": "BTCUSD", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Huobi", @@ -170,7 +223,13 @@ "APISecret": "Secret", "AvailablePairs": "BTCCNY,LTCCNY", "EnabledPairs": "BTCCNY,LTCCNY", - "BaseCurrencies": "CNY" + "BaseCurrencies": "CNY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false + } }, { "Name": "ITBIT", @@ -184,7 +243,13 @@ "ClientID": "ClientID", "AvailablePairs": "XBTUSD,XBTSGD,XBTEUR", "EnabledPairs": "XBTUSD,XBTSGD,XBTEUR", - "BaseCurrencies": "USD,SGD,EUR" + "BaseCurrencies": "USD,SGD,EUR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Kraken", @@ -195,9 +260,16 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "ETCUSD,ICNETH,REPXBT,ZECXBT,ETHXBT,ETHXBT.d,ETHGBP,LTCXBT,XBTGBP.d,XDGXBT,XMRUSD,ZECUSD,ETCETH,ETHJPY,XBTCAD.d,XBTJPY.d,XBTUSD.d,XLMXBT,XLMEUR,XLMUSD,XMREUR,ETCXBT,ETHCAD.d,ETHEUR.d,ETHJPY.d,XBTEUR.d,ETHEUR,ETHGBP.d,ICNXBT,LTCEUR,REPEUR,XBTGBP,XBTJPY,ETHUSD,ETHUSD.d,LTCUSD,REPETH,XBTUSD,XMRXBT,ETCEUR,ETHCAD,REPUSD,XBTCAD,XBTEUR,XRPXBT,ZECEUR", + "AvailablePairs": "REPETH,ZECXBT,ETCUSD,ETHCAD,ETCEUR,ETHXBT.D,XBTJPY.D,EOSXBT,USDTUSD,LTCEUR,XBTUSD,ETHUSD,XBTEUR.D,BCHEUR,GNOXBT,ICNXBT,XBTEUR,ZECUSD,ETCXBT,ICNETH,LTCXBT,XRPXBT,ZECEUR,DASHUSD,ETHEUR.D,ETHJPY.D,LTCUSD,XMRXBT,BCHXBT,ETHJPY,GNOETH,XDGXBT,ETHCAD.D,XRPUSD,ETHEUR,XMRUSD,MLNETH,REPEUR,XBTCAD.D,XRPEUR,BCHUSD,ETHXBT,XBTJPY,XBTUSD.D,XLMXBT,DASHXBT,XBTGBP.D,MLNXBT,REPXBT,XBTCAD,DASHEUR,ETHGBP.D,ETHUSD.D,XMREUR,EOSETH,ETCETH", "EnabledPairs": "ETCUSD,XBTUSD,ETHUSD", - "BaseCurrencies": "EUR,USD,CAD,GBP,JPY" + "BaseCurrencies": "EUR,USD,CAD,GBP,JPY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Separator": "," + } }, { "Name": "LakeBTC", @@ -210,7 +282,13 @@ "APISecret": "Secret", "AvailablePairs": "BTCUSD,BTCEUR,USDHKD,AUDUSD,BTCGBP,BTCNZD,USDJPY,BTCSGD,BTCNGN,EURUSD,USDSGD,NZDUSD,USDNGN,USDCHF,BTCJPY,BTCAUD,BTCCAD,BTCCHF,GBPUSD,USDCAD", "EnabledPairs": "BTCUSD,BTCAUD", - "BaseCurrencies": "USD,EUR,HKD,AUD,GBP,NZD,JPY,SGD,NGN,CHF,CAD" + "BaseCurrencies": "USD,EUR,HKD,AUD,GBP,NZD,JPY,SGD,NGN,CHF,CAD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "Liqui", @@ -221,9 +299,18 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "TIME_BTC,ETH_BTC,GNT_BTC,WAVES_BTC,ICN_BTC,1ST_BTC,WINGS_BTC,MLN_BTC,ROUND_BTC,VSL_BTC,LTC_BTC,DCT_BTC,INCNT_BTC,PLU_BTC,DASH_BTC", + "AvailablePairs": "XID_BTC,OAX_ETH,LTC_BTC,TIME_BTC,GNT_ETH,LUN_BTC,HMQ_ETH,EOS_USDT,NET_ETH,DASH_BTC,ETH_USDT,VSL_USDT,BAT_ETH,OMG_ETH,SAN_ETH,DGD_ETH,STX_ETH,LTC_USDT,TAAS_USDT,BAT_USDT,QRL_USDT,EOS_BTC,NET_USDT,GNT_BTC,ANT_BTC,ANT_USDT,SNGLS_ETH,CFI_ETH,CFI_USDT,PLU_ETH,BTC_USDT,ROUND_USDT,GNO_USDT,ZRX_USDT,ROUND_BTC,ICN_ETH,WAVES_USDT,OMG_BTC,QTUM_BTC,LTC_ETH,EDG_USDT,WINGS_ETH,TKN_BTC,CVC_USDT,REP_USDT,RLC_BTC,GNO_BTC,ADX_USDT,OMG_USDT,PLU_BTC,EDG_BTC,BNT_ETH,OAX_BTC,STX_BTC,BAT_BTC,BCC_USDT,VSL_ETH,REP_ETH,HMQ_BTC,SNT_ETH,ZRX_BTC,MLN_ETH,LUN_ETH,TKN_ETH,CFI_BTC,DGD_USDT,DNT_ETH,STORJ_ETH,TAAS_BTC,HMQ_USDT,BCAP_BTC,BNT_USDT,MYST_BTC,SNM_BTC,ADX_ETH,CVC_BTC,WAVES_BTC,TRST_ETH,PLU_USDT,GNT_USDT,REP_BTC,QRL_BTC,MGO_USDT,BCC_ETH,ZRX_ETH,ICN_BTC,MLN_BTC,RLC_USDT,TAAS_ETH,PAY_BTC,SAN_USDT,WINGS_BTC,1ST_ETH,LUN_USDT,QRL_ETH,SNGLS_USDT,GUP_BTC,PTOY_USDT,MCO_USDT,ICN_USDT,INCNT_USDT,STORJ_USDT,INCNT_BTC,DASH_ETH,GUP_ETH,SNT_BTC,SNT_USDT,ADX_BTC,DGD_BTC,BCC_BTC,VSL_BTC,WINGS_USDT,GUP_USDT,MYST_USDT,PAY_USDT,XID_USDT,MYST_ETH,SNGLS_BTC,SNM_ETH,CVC_ETH,PTOY_BTC,SNM_USDT,1ST_BTC,TIME_ETH,1ST_USDT,MLN_USDT,RLC_ETH,BCAP_ETH,XID_ETH,QTUM_ETH,WAVES_ETH,GNO_ETH,BCAP_USDT,SAN_BTC,TIME_USDT,STORJ_BTC,QTUM_USDT,ROUND_ETH,EDG_ETH,PTOY_ETH,TKN_USDT,BNT_BTC,MGO_BTC,PAY_ETH,INCNT_ETH,DASH_USDT,MCO_BTC,OAX_USDT,DNT_BTC,DNT_USDT,MCO_ETH,EOS_ETH,ETH_BTC,TRST_BTC,TRST_USDT,ANT_ETH,MGO_ETH,NET_BTC,STX_USDT", "EnabledPairs": "ETH_BTC,LTC_BTC,DASH_BTC", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_", + "Separator": "-" + } }, { "Name": "LocalBitcoins", @@ -236,7 +323,13 @@ "APISecret": "Secret", "AvailablePairs": "BTCARS,BTCAUD,BTCBRL,BTCCAD,BTCCHF,BTCCZK,BTCDKK,BTCEUR,BTCGBP,BTCHKD,BTCILS,BTCINR,BTCMXN,BTCNOK,BTCNZD,BTCPLN,BTCRUB,BTCSEK,BTCSGD,BTCTHB,BTCUSD,BTCZAR", "EnabledPairs": "BTCARS,BTCAUD,BTCBRL,BTCCAD,BTCCHF,BTCCZK,BTCDKK,BTCEUR,BTCGBP,BTCHKD,BTCILS,BTCINR,BTCMXN,BTCNOK,BTCNZD,BTCPLN,BTCRUB,BTCSEK,BTCSGD,BTCTHB,BTCUSD,BTCZAR", - "BaseCurrencies": "ARS,AUD,BRL,CAD,CHF,CZK,DKK,EUR,GBP,HKD,ILS,INR,MXN,NOK,NZD,PLN,RUB,SEK,SGD,THB,USD,ZAR" + "BaseCurrencies": "ARS,AUD,BRL,CAD,CHF,CZK,DKK,EUR,GBP,HKD,ILS,INR,MXN,NOK,NZD,PLN,RUB,SEK,SGD,THB,USD,ZAR", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": true + } }, { "Name": "OKCOIN China", @@ -249,7 +342,14 @@ "APISecret": "Secret", "AvailablePairs": "BTCCNY,LTCCNY", "EnabledPairs": "BTCCNY,LTCCNY", - "BaseCurrencies": "CNY" + "BaseCurrencies": "CNY", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + } }, { "Name": "OKCOIN International", @@ -262,7 +362,14 @@ "APISecret": "Secret", "AvailablePairs": "BTCUSD,LTCUSD", "EnabledPairs": "BTCUSD,LTCUSD", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + } }, { "Name": "Poloniex", @@ -275,7 +382,15 @@ "APISecret": "Secret", "AvailablePairs": "BTC_XUSD,BTC_FCT,BTC_MMNXT,BTC_NMC,BTC_BITUSD,BTC_RDD,BTC_XMR,BTC_XST,BTC_DSH,BTC_MAID,BTC_DGB,BTC_NEOS,BTC_BLK,BTC_NAUT,BTC_NBT,BTC_XCP,BTC_STR,BTC_BTCD,BTC_GRC,BTC_HUC,BTC_BBR,BTC_XDN,BTC_INDEX,BTC_IOC,BTC_SWARM,BTC_EMC2,BTC_MCN,BTC_NOXT,BTC_MINT,BTC_PTS,BTC_SC,BTC_GEO,BTC_XRP,BTC_FLO,BTC_BITS,BTC_HYP,BTC_XCR,BTC_LTBC,BTC_SYS,BTC_GMC,BTC_ETH,BTC_SYNC,BTC_GAP,BTC_BCN,BTC_C2,BTC_PINK,BTC_FIBRE,BTC_POT,BTC_QTL,BTC_SDC,BTC_XC,BTC_DASH,BTC_SILK,BTC_CLAM,BTC_NAV,BTC_PIGGY,BTC_BCY,BTC_MIL,BTC_XCN,BTC_YACC,BTC_BTS,BTC_QBK,BTC_SJCX,BTC_LQD,BTC_BURST,BTC_RIC,BTC_VRC,BTC_LTC,BTC_XPB,BTC_GRS,BTC_XCH,BTC_ARCH,BTC_QORA,BTC_HZ,BTC_NSR,BTC_XPM,BTC_BITCNY,BTC_EXE,BTC_XMG,BTC_BTC,BTC_BTM,BTC_NOBL,BTC_NXT,BTC_DOGE,BTC_CURE,BTC_MNTA,BTC_ADN,BTC_EXP,BTC_VTC,BTC_FLDC,BTC_MRS,BTC_MYR,BTC_OMNI,BTC_VNL,BTC_USDT,BTC_NOTE,BTC_WDC,BTC_BELA,BTC_VIA,BTC_CGA,BTC_DIEM,BTC_IFC,BTC_XDP,BTC_BLOCK,BTC_MMC,BTC_1CR,BTC_UNITY,BTC_XBC,BTC_GEMZ,BTC_FLT,BTC_PPC,BTC_XEM,BTC_RBY,BTC_CNMT,BTC_ABY,XMR_XDN,XMR_IFC,XMR_DIEM,XMR_BBR,XMR_DSH,XMR_BCN,XMR_LTC,XMR_MAID,XMR_DASH,XMR_BTCD,XMR_HYP,XMR_BLK,XMR_QORA,XMR_MNTA,XMR_NXT,USDT_BTC,USDT_ETH,USDT_XRP,USDT_DASH,USDT_LTC,USDT_NXT,USDT_XMR,USDT_STR", "EnabledPairs": "BTC_LTC,BTC_ETH,BTC_DOGE,BTC_DASH,BTC_XRP", - "BaseCurrencies": "USD" + "BaseCurrencies": "USD", + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + } } ] } \ No newline at end of file diff --git a/ticker_routes.go b/ticker_routes.go index 4ec16ea3..3d7e1ded 100644 --- a/ticker_routes.go +++ b/ticker_routes.go @@ -62,15 +62,13 @@ func getAllActiveTickersResponse(w http.ResponseWriter, r *http.Request) { "Getting enabled currencies for '" + individualBot.GetName() + "'", ) currencies := individualBot.GetEnabledCurrencies() - log.Println(currencies) - for _, currency := range currencies { - tickerPrice, err := individualBot.GetTickerPrice( - pair.NewCurrencyPairFromString(currency), - ) + for x := range currencies { + currency := currencies[x] + + tickerPrice, err := individualBot.GetTickerPrice(currency) if err != nil { continue } - log.Println(tickerPrice) individualExchange.ExchangeValues = append( individualExchange.ExchangeValues, tickerPrice,