diff --git a/README.md b/README.md index 4df0642b..ccb46ec8 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,11 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader | COINUT | Yes | No | NA | | Exmo | Yes | NA | NA | | CoinbasePro | Yes | Yes | No| +| GateIO | Yes | No | NA | | Gemini | Yes | No | No | | HitBTC | Yes | Yes | No | -| Huobi.Pro | Yes | No |No | +| Huobi.Pro | Yes | No | NA | +| Huobi.Hadax | Yes | No | NA | | ItBit | Yes | NA | No | | Kraken | Yes | NA | NA | | LakeBTC | Yes | No | NA | @@ -45,6 +47,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader | Poloniex | Yes | Yes | NA | | WEX | Yes | NA | NA | | Yobit | Yes | NA | NA | +| ZB.COM | Yes | No | NA | We are aiming to support the top 20 highest volume exchanges based off the [CoinMarketCap exchange data](https://coinmarketcap.com/exchanges/volume/24-hour/). @@ -145,7 +148,7 @@ Binaries will be published once the codebase reaches a stable condition. |User|Github|Contribution Amount| |--|--|--| | thrasher- | https://github.com/thrasher- | 453 | -| shazbert | https://github.com/shazbert | 140 | +| shazbert | https://github.com/shazbert | 141 | | gloriousCode | https://github.com/gloriousCode | 122 | | 140am | https://github.com/140am | 8 | | marcofranssen | https://github.com/marcofranssen | 4 | diff --git a/common/common.go b/common/common.go index a8ec5e7c..5a625a36 100644 --- a/common/common.go +++ b/common/common.go @@ -41,6 +41,7 @@ const ( HashSHA256 HashSHA512 HashSHA512_384 + HashMD5 SatoshisPerBTC = 100000000 SatoshisPerLTC = 100000000 WeiPerEther = 1000000000000000000 @@ -121,6 +122,10 @@ func GetHMAC(hashType int, input, key []byte) []byte { { hash = sha512.New384 } + case HashMD5: + { + hash = md5.New + } } hmac := hmac.New(hash, []byte(key)) @@ -128,11 +133,24 @@ func GetHMAC(hashType int, input, key []byte) []byte { return hmac.Sum(nil) } +// Sha1ToHex takes a string, sha1 hashes it and return a hex string of the +// result +func Sha1ToHex(data string) string { + h := sha1.New() + h.Write([]byte(data)) + return hex.EncodeToString(h.Sum(nil)) +} + // HexEncodeToString takes in a hexadecimal byte array and returns a string func HexEncodeToString(input []byte) string { return hex.EncodeToString(input) } +// ByteArrayToString returns a string +func ByteArrayToString(input []byte) string { + return fmt.Sprintf("%x", input) +} + // Base64Decode takes in a Base64 string and returns a byte array and an error func Base64Decode(input string) ([]byte, error) { result, err := base64.StdEncoding.DecodeString(input) @@ -538,3 +556,61 @@ func GetOSPathSlash() string { } return "/" } + +// UnixMillis converts a UnixNano timestamp to milliseconds +func UnixMillis(t time.Time) int64 { + return t.UnixNano() / int64(time.Millisecond) +} + +// RecvWindow converts a supplied time.Duration to milliseconds +func RecvWindow(d time.Duration) int64 { + return int64(d) / int64(time.Millisecond) +} + +// FloatFromString format +func FloatFromString(raw interface{}) (float64, error) { + str, ok := raw.(string) + if !ok { + return 0, fmt.Errorf("unable to parse, value not string: %T", raw) + } + flt, err := strconv.ParseFloat(str, 64) + if err != nil { + return 0, fmt.Errorf("unable to parse, value not string: %T", raw) + } + return flt, nil +} + +// IntFromString format +func IntFromString(raw interface{}) (int, error) { + str, ok := raw.(string) + if !ok { + return 0, fmt.Errorf("unable to parse, value not string: %T", raw) + } + n, err := strconv.Atoi(str) + if err != nil { + return 0, fmt.Errorf("unable to parse as int: %T", raw) + } + return n, nil +} + +// Int64FromString format +func Int64FromString(raw interface{}) (int64, error) { + str, ok := raw.(string) + if !ok { + return 0, fmt.Errorf("unable to parse, value not string: %T", raw) + } + n, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return 0, fmt.Errorf("unable to parse as int: %T", raw) + } + return n, nil +} + +// TimeFromUnixTimestampFloat format +func TimeFromUnixTimestampFloat(raw interface{}) (time.Time, error) { + ts, ok := raw.(float64) + if !ok { + return time.Time{}, fmt.Errorf("unable to parse, value not int64: %T", raw) + } + return time.Unix(0, int64(ts)*int64(time.Millisecond)), nil +} diff --git a/communications/slack/slack_types.go b/communications/slack/slack_types.go index 572bf7cc..07358656 100644 --- a/communications/slack/slack_types.go +++ b/communications/slack/slack_types.go @@ -87,13 +87,13 @@ type Response struct { LastRead string `json:"last_read"` Members []string `json:"members"` Topic struct { - Value string `json:"string"` - Creator string `json:"string"` + Value string `json:"value"` + Creator string `json:"creator"` LastSet int64 `json:"last_set"` } `json:"topic"` Purpose struct { - Value string `json:"string"` - Creator string `json:"string"` + Value string `json:"value"` + Creator string `json:"creator"` LastSet int64 `json:"last_set"` } `json:"purpose"` } `json:"groups"` diff --git a/config/config_test.go b/config/config_test.go index 396665f1..3f50be99 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -206,7 +206,7 @@ func TestGetEnabledExchanges(t *testing.T) { } exchanges := cfg.GetEnabledExchanges() - if len(exchanges) != 26 { + if len(exchanges) != 29 { t.Error( "Test failed. TestGetEnabledExchanges. Enabled exchanges value mismatch", ) @@ -258,7 +258,7 @@ func TestGetDisabledExchanges(t *testing.T) { } func TestCountEnabledExchanges(t *testing.T) { - defaultEnabledExchanges := 26 + defaultEnabledExchanges := 29 GetConfigEnabledExchanges := GetConfig() err := GetConfigEnabledExchanges.LoadConfig(ConfigTestFile) if err != nil { diff --git a/config_example.json b/config_example.json index 51ab0b25..f887ba2c 100644 --- a/config_example.json +++ b/config_example.json @@ -92,13 +92,13 @@ { "Address": "1JCe8z4jJVNXSjohjM4i9Hh813dLCNx2Sy", "CoinType": "BTC", - "Balance": 53000.01310358, + "Balance": 53000.01324467, "Description": "" }, { "Address": "3Nxwenay9Z8Lc9JBiywExpnEFiLp6Afp8v", "CoinType": "BTC", - "Balance": 101848.28376405, + "Balance": 101848.28432707, "Description": "" }, { @@ -171,7 +171,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "ETH-BTC,LTC-BTC,BNB-BTC,NEO-BTC,QTUM-ETH,EOS-ETH,SNT-ETH,BNT-ETH,BCC-BTC,GAS-BTC,BNB-ETH,BTC-USDT,ETH-USDT,HSR-BTC,OAX-ETH,DNT-ETH,MCO-ETH,ICN-ETH,MCO-BTC,WTC-BTC,WTC-ETH,LRC-BTC,LRC-ETH,QTUM-BTC,YOYO-BTC,OMG-BTC,OMG-ETH,ZRX-BTC,ZRX-ETH,STRAT-BTC,STRAT-ETH,SNGLS-BTC,SNGLS-ETH,BQX-BTC,BQX-ETH,KNC-BTC,KNC-ETH,FUN-BTC,FUN-ETH,SNM-BTC,SNM-ETH,NEO-ETH,IOTA-BTC,IOTA-ETH,LINK-BTC,LINK-ETH,XVG-BTC,XVG-ETH,SALT-BTC,SALT-ETH,MDA-BTC,MDA-ETH,MTL-BTC,MTL-ETH,SUB-BTC,SUB-ETH,EOS-BTC,SNT-BTC,ETC-ETH,ETC-BTC,MTH-BTC,MTH-ETH,ENG-BTC,ENG-ETH,DNT-BTC,ZEC-BTC,ZEC-ETH,BNT-BTC,AST-BTC,AST-ETH,DASH-BTC,DASH-ETH,OAX-BTC,ICN-BTC,BTG-BTC,BTG-ETH,EVX-BTC,EVX-ETH,REQ-BTC,REQ-ETH,VIB-BTC,VIB-ETH,HSR-ETH,TRX-BTC,TRX-ETH,POWR-BTC,POWR-ETH,ARK-BTC,ARK-ETH,YOYO-ETH,XRP-BTC,XRP-ETH,MOD-BTC,MOD-ETH,ENJ-BTC,ENJ-ETH,STORJ-BTC,STORJ-ETH,BNB-USDT,VEN-BNB,YOYO-BNB,POWR-BNB,VEN-BTC,VEN-ETH,KMD-BTC,KMD-ETH,NULS-BNB,RCN-BTC,RCN-ETH,RCN-BNB,NULS-BTC,NULS-ETH,RDN-BTC,RDN-ETH,RDN-BNB,XMR-BTC,XMR-ETH,DLT-BNB,WTC-BNB,DLT-BTC,DLT-ETH,AMB-BTC,AMB-ETH,AMB-BNB,BCC-ETH,BCC-USDT,BCC-BNB,BAT-BTC,BAT-ETH,BAT-BNB,BCPT-BTC,BCPT-ETH,BCPT-BNB,ARN-BTC,ARN-ETH,GVT-BTC,GVT-ETH,CDT-BTC,CDT-ETH,GXS-BTC,GXS-ETH,NEO-USDT,NEO-BNB,POE-BTC,POE-ETH,QSP-BTC,QSP-ETH,QSP-BNB,BTS-BTC,BTS-ETH,BTS-BNB,XZC-BTC,XZC-ETH,XZC-BNB,LSK-BTC,LSK-ETH,LSK-BNB,TNT-BTC,TNT-ETH,FUEL-BTC,FUEL-ETH,MANA-BTC,MANA-ETH,BCD-BTC,BCD-ETH,DGD-BTC,DGD-ETH,IOTA-BNB,ADX-BTC,ADX-ETH,ADX-BNB,ADA-BTC,ADA-ETH,PPT-BTC,PPT-ETH,CMT-BTC,CMT-ETH,CMT-BNB,XLM-BTC,XLM-ETH,XLM-BNB,CND-BTC,CND-ETH,CND-BNB,LEND-BTC,LEND-ETH,WABI-BTC,WABI-ETH,WABI-BNB,LTC-ETH,LTC-USDT,LTC-BNB,TNB-BTC,TNB-ETH,WAVES-BTC,WAVES-ETH,WAVES-BNB,GTO-BTC,GTO-ETH,GTO-BNB,ICX-BTC,ICX-ETH,ICX-BNB,OST-BTC,OST-ETH,OST-BNB,ELF-BTC,ELF-ETH,AION-BTC,AION-ETH,AION-BNB,NEBL-BTC,NEBL-ETH,NEBL-BNB,BRD-BTC,BRD-ETH,BRD-BNB,MCO-BNB,EDO-BTC,EDO-ETH,WINGS-BTC,WINGS-ETH,NAV-BTC,NAV-ETH,NAV-BNB,LUN-BTC,LUN-ETH,TRIG-BTC,TRIG-ETH,TRIG-BNB,APPC-BTC,APPC-ETH,APPC-BNB,VIBE-BTC,VIBE-ETH,RLC-BTC,RLC-ETH,RLC-BNB,INS-BTC,INS-ETH,PIVX-BTC,PIVX-ETH,PIVX-BNB,IOST-BTC,IOST-ETH,CHAT-BTC,CHAT-ETH,STEEM-BTC,STEEM-ETH,STEEM-BNB,NANO-BTC,NANO-ETH,NANO-BNB,VIA-BTC,VIA-ETH,VIA-BNB,BLZ-BTC,BLZ-ETH,BLZ-BNB,AE-BTC,AE-ETH,AE-BNB,RPX-BTC,RPX-ETH,RPX-BNB,NCASH-BTC,NCASH-ETH,NCASH-BNB,POA-BTC,POA-ETH,POA-BNB,ZIL-BTC,ZIL-ETH,ZIL-BNB,ONT-BTC,ONT-ETH,ONT-BNB,STORM-BTC,STORM-ETH,STORM-BNB,QTUM-BNB,QTUM-USDT,XEM-BTC,XEM-ETH,XEM-BNB,WAN-BTC,WAN-ETH,WAN-BNB,WPR-BTC,WPR-ETH,QLC-BTC,QLC-ETH,SYS-BTC,SYS-ETH,SYS-BNB,QLC-BNB,GRS-BTC,GRS-ETH,ADA-USDT,ADA-BNB,CLOAK-BTC,CLOAK-ETH,GNT-BTC,GNT-ETH,GNT-BNB,LOOM-BTC,LOOM-ETH,LOOM-BNB,XRP-USDT,BCN-BTC,BCN-ETH,BCN-BNB,REP-BTC,REP-ETH,REP-BNB,TUSD-BTC,TUSD-ETH,TUSD-BNB,ZEN-BTC,ZEN-ETH,ZEN-BNB,SKY-BTC,SKY-ETH,SKY-BNB,EOS-USDT,EOS-BNB,CVC-BTC,CVC-ETH,CVC-BNB,THETA-BTC,THETA-ETH,THETA-BNB,XRP-BNB,TUSD-USDT,IOTA-USDT,XLM-USDT,IOTX-BTC,IOTX-ETH,QKC-BTC,QKC-ETH,AGI-BTC,AGI-ETH,AGI-BNB,NXS-BTC,NXS-ETH,NXS-BNB,ENJ-BNB,DATA-BTC,DATA-ETH,ONT-USDT,TRX-USDT,ETC-USDT,ETC-BNB,ICX-USDT,SC-BTC,SC-ETH,SC-BNB,NPXS-BTC,NPXS-ETH,VEN-USDT,KEY-BTC,KEY-ETH,NAS-BTC,NAS-ETH,NAS-BNB,MFT-BTC,MFT-ETH,MFT-BNB,DENT-BTC,DENT-ETH", + "AvailablePairs": "ETH-BTC,LTC-BTC,BNB-BTC,NEO-BTC,QTUM-ETH,EOS-ETH,SNT-ETH,BNT-ETH,BCC-BTC,GAS-BTC,BNB-ETH,BTC-USDT,ETH-USDT,HSR-BTC,OAX-ETH,DNT-ETH,MCO-ETH,ICN-ETH,MCO-BTC,WTC-BTC,WTC-ETH,LRC-BTC,LRC-ETH,QTUM-BTC,YOYO-BTC,OMG-BTC,OMG-ETH,ZRX-BTC,ZRX-ETH,STRAT-BTC,STRAT-ETH,SNGLS-BTC,SNGLS-ETH,BQX-BTC,BQX-ETH,KNC-BTC,KNC-ETH,FUN-BTC,FUN-ETH,SNM-BTC,SNM-ETH,NEO-ETH,IOTA-BTC,IOTA-ETH,LINK-BTC,LINK-ETH,XVG-BTC,XVG-ETH,SALT-BTC,SALT-ETH,MDA-BTC,MDA-ETH,MTL-BTC,MTL-ETH,SUB-BTC,SUB-ETH,EOS-BTC,SNT-BTC,ETC-ETH,ETC-BTC,MTH-BTC,MTH-ETH,ENG-BTC,ENG-ETH,DNT-BTC,ZEC-BTC,ZEC-ETH,BNT-BTC,AST-BTC,AST-ETH,DASH-BTC,DASH-ETH,OAX-BTC,ICN-BTC,BTG-BTC,BTG-ETH,EVX-BTC,EVX-ETH,REQ-BTC,REQ-ETH,VIB-BTC,VIB-ETH,HSR-ETH,TRX-BTC,TRX-ETH,POWR-BTC,POWR-ETH,ARK-BTC,ARK-ETH,YOYO-ETH,XRP-BTC,XRP-ETH,MOD-BTC,MOD-ETH,ENJ-BTC,ENJ-ETH,STORJ-BTC,STORJ-ETH,BNB-USDT,YOYO-BNB,POWR-BNB,KMD-BTC,KMD-ETH,NULS-BNB,RCN-BTC,RCN-ETH,RCN-BNB,NULS-BTC,NULS-ETH,RDN-BTC,RDN-ETH,RDN-BNB,XMR-BTC,XMR-ETH,DLT-BNB,WTC-BNB,DLT-BTC,DLT-ETH,AMB-BTC,AMB-ETH,AMB-BNB,BCC-ETH,BCC-USDT,BCC-BNB,BAT-BTC,BAT-ETH,BAT-BNB,BCPT-BTC,BCPT-ETH,BCPT-BNB,ARN-BTC,ARN-ETH,GVT-BTC,GVT-ETH,CDT-BTC,CDT-ETH,GXS-BTC,GXS-ETH,NEO-USDT,NEO-BNB,POE-BTC,POE-ETH,QSP-BTC,QSP-ETH,QSP-BNB,BTS-BTC,BTS-ETH,BTS-BNB,XZC-BTC,XZC-ETH,XZC-BNB,LSK-BTC,LSK-ETH,LSK-BNB,TNT-BTC,TNT-ETH,FUEL-BTC,FUEL-ETH,MANA-BTC,MANA-ETH,BCD-BTC,BCD-ETH,DGD-BTC,DGD-ETH,IOTA-BNB,ADX-BTC,ADX-ETH,ADX-BNB,ADA-BTC,ADA-ETH,PPT-BTC,PPT-ETH,CMT-BTC,CMT-ETH,CMT-BNB,XLM-BTC,XLM-ETH,XLM-BNB,CND-BTC,CND-ETH,CND-BNB,LEND-BTC,LEND-ETH,WABI-BTC,WABI-ETH,WABI-BNB,LTC-ETH,LTC-USDT,LTC-BNB,TNB-BTC,TNB-ETH,WAVES-BTC,WAVES-ETH,WAVES-BNB,GTO-BTC,GTO-ETH,GTO-BNB,ICX-BTC,ICX-ETH,ICX-BNB,OST-BTC,OST-ETH,OST-BNB,ELF-BTC,ELF-ETH,AION-BTC,AION-ETH,AION-BNB,NEBL-BTC,NEBL-ETH,NEBL-BNB,BRD-BTC,BRD-ETH,BRD-BNB,MCO-BNB,EDO-BTC,EDO-ETH,WINGS-BTC,WINGS-ETH,NAV-BTC,NAV-ETH,NAV-BNB,LUN-BTC,LUN-ETH,TRIG-BTC,TRIG-ETH,TRIG-BNB,APPC-BTC,APPC-ETH,APPC-BNB,VIBE-BTC,VIBE-ETH,RLC-BTC,RLC-ETH,RLC-BNB,INS-BTC,INS-ETH,PIVX-BTC,PIVX-ETH,PIVX-BNB,IOST-BTC,IOST-ETH,CHAT-BTC,CHAT-ETH,STEEM-BTC,STEEM-ETH,STEEM-BNB,NANO-BTC,NANO-ETH,NANO-BNB,VIA-BTC,VIA-ETH,VIA-BNB,BLZ-BTC,BLZ-ETH,BLZ-BNB,AE-BTC,AE-ETH,AE-BNB,RPX-BTC,RPX-ETH,RPX-BNB,NCASH-BTC,NCASH-ETH,NCASH-BNB,POA-BTC,POA-ETH,POA-BNB,ZIL-BTC,ZIL-ETH,ZIL-BNB,ONT-BTC,ONT-ETH,ONT-BNB,STORM-BTC,STORM-ETH,STORM-BNB,QTUM-BNB,QTUM-USDT,XEM-BTC,XEM-ETH,XEM-BNB,WAN-BTC,WAN-ETH,WAN-BNB,WPR-BTC,WPR-ETH,QLC-BTC,QLC-ETH,SYS-BTC,SYS-ETH,SYS-BNB,QLC-BNB,GRS-BTC,GRS-ETH,ADA-USDT,ADA-BNB,CLOAK-BTC,CLOAK-ETH,GNT-BTC,GNT-ETH,GNT-BNB,LOOM-BTC,LOOM-ETH,LOOM-BNB,XRP-USDT,BCN-BTC,BCN-ETH,BCN-BNB,REP-BTC,REP-ETH,REP-BNB,TUSD-BTC,TUSD-ETH,TUSD-BNB,ZEN-BTC,ZEN-ETH,ZEN-BNB,SKY-BTC,SKY-ETH,SKY-BNB,EOS-USDT,EOS-BNB,CVC-BTC,CVC-ETH,CVC-BNB,THETA-BTC,THETA-ETH,THETA-BNB,XRP-BNB,TUSD-USDT,IOTA-USDT,XLM-USDT,IOTX-BTC,IOTX-ETH,QKC-BTC,QKC-ETH,AGI-BTC,AGI-ETH,AGI-BNB,NXS-BTC,NXS-ETH,NXS-BNB,ENJ-BNB,DATA-BTC,DATA-ETH,ONT-USDT,TRX-USDT,ETC-USDT,ETC-BNB,ICX-USDT,SC-BTC,SC-ETH,SC-BNB,NPXS-BTC,NPXS-ETH,KEY-BTC,KEY-ETH,NAS-BTC,NAS-ETH,NAS-BNB,MFT-BTC,MFT-ETH,MFT-BNB,DENT-BTC,DENT-ETH,ARDR-BTC,ARDR-ETH,ARDR-BNB,NULS-USDT,HOT-BTC,HOT-ETH,VET-BTC,VET-ETH,VET-USDT,VET-BNB,DOCK-BTC,DOCK-ETH,POLY-BTC,POLY-BNB", "EnabledPairs": "BTC-USDT,ETH-USDT,BCC-USDT,LTC-USDT,ADA-USDT,XRP-USDT,VEN-USDT", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -206,7 +206,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC,BTCEUR,BTCJPY,XRPUSD,XRPBTC,IOTUSD,IOTBTC,IOTETH,EOSUSD,EOSBTC,EOSETH,SANUSD,SANBTC,SANETH,OMGUSD,OMGBTC,OMGETH,BCHUSD,BCHBTC,BCHETH,NEOUSD,NEOBTC,NEOETH,ETPUSD,ETPBTC,ETPETH,QTMUSD,QTMBTC,QTMETH,AVTUSD,AVTBTC,AVTETH,EDOUSD,EDOBTC,EDOETH,BTGUSD,BTGBTC,DATUSD,DATBTC,DATETH,QSHUSD,QSHBTC,QSHETH,YYWUSD,YYWBTC,YYWETH,GNTUSD,GNTBTC,GNTETH,SNTUSD,SNTBTC,SNTETH,IOTEUR,BATUSD,BATBTC,BATETH,MNAUSD,MNABTC,MNAETH,FUNUSD,FUNBTC,FUNETH,ZRXUSD,ZRXBTC,ZRXETH,TNBUSD,TNBBTC,TNBETH,SPKUSD,SPKBTC,SPKETH,TRXUSD,TRXBTC,TRXETH,RCNUSD,RCNBTC,RCNETH,RLCUSD,RLCBTC,RLCETH,AIDUSD,AIDBTC,AIDETH,SNGUSD,SNGBTC,SNGETH,REPUSD,REPBTC,REPETH,ELFUSD,ELFBTC,ELFETH,BTCGBP,ETHEUR,ETHJPY,ETHGBP,NEOEUR,NEOJPY,NEOGBP,EOSEUR,EOSJPY,EOSGBP,IOTJPY,IOTGBP,IOSUSD,IOSBTC,IOSETH,AIOUSD,AIOBTC,AIOETH,REQUSD,REQBTC,REQETH,RDNUSD,RDNBTC,RDNETH,LRCUSD,LRCBTC,LRCETH,WAXUSD,WAXBTC,WAXETH,DAIUSD,DAIBTC,DAIETH,CFIUSD,CFIBTC,CFIETH,AGIUSD,AGIBTC,AGIETH,BFTUSD,BFTBTC,BFTETH,MTNUSD,MTNBTC,MTNETH,ODEUSD,ODEBTC,ODEETH,ANTUSD,ANTBTC,ANTETH,DTHUSD,DTHBTC,DTHETH,MITUSD,MITBTC,MITETH,STJUSD,STJBTC,STJETH,XLMUSD,XLMEUR,XLMJPY,XLMGBP,XLMBTC,XLMETH,XVGUSD,XVGEUR,XVGJPY,XVGGBP,XVGBTC,XVGETH,BCIUSD,BCIBTC,MKRUSD,MKRBTC,MKRETH,VENUSD,VENBTC,VENETH,KNCUSD,KNCBTC,KNCETH,POAUSD,POABTC,POAETH,LYMUSD,LYMBTC,LYMETH,UTKUSD,UTKBTC,UTKETH,VEEUSD,VEEBTC,VEEETH,DADUSD,DADBTC,DADETH,ORSUSD,ORSBTC,ORSETH,AUCUSD,AUCBTC,AUCETH,POYUSD,POYBTC,POYETH,FSNUSD,FSNBTC,FSNETH,CBTUSD,CBTBTC,CBTETH,ZCNUSD,ZCNBTC,ZCNETH,SENUSD,SENBTC,SENETH,NCAUSD,NCABTC,NCAETH,CNDUSD,CNDBTC,CNDETH,CTXUSD,CTXBTC,CTXETH,PAIUSD,PAIBTC,SEEUSD,SEEBTC,SEEETH,ESSUSD,ESSBTC,ESSETH,ATMUSD,ATMBTC,ATMETH,HOTUSD,HOTBTC,HOTETH,DTAUSD,DTABTC,DTAETH", + "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC,BTCEUR,BTCJPY,XRPUSD,XRPBTC,IOTUSD,IOTBTC,IOTETH,EOSUSD,EOSBTC,EOSETH,SANUSD,SANBTC,SANETH,OMGUSD,OMGBTC,OMGETH,BCHUSD,BCHBTC,BCHETH,NEOUSD,NEOBTC,NEOETH,ETPUSD,ETPBTC,ETPETH,QTMUSD,QTMBTC,QTMETH,AVTUSD,AVTBTC,AVTETH,EDOUSD,EDOBTC,EDOETH,BTGUSD,BTGBTC,DATUSD,DATBTC,DATETH,QSHUSD,QSHBTC,QSHETH,YYWUSD,YYWBTC,YYWETH,GNTUSD,GNTBTC,GNTETH,SNTUSD,SNTBTC,SNTETH,IOTEUR,BATUSD,BATBTC,BATETH,MNAUSD,MNABTC,MNAETH,FUNUSD,FUNBTC,FUNETH,ZRXUSD,ZRXBTC,ZRXETH,TNBUSD,TNBBTC,TNBETH,SPKUSD,SPKBTC,SPKETH,TRXUSD,TRXBTC,TRXETH,RCNUSD,RCNBTC,RCNETH,RLCUSD,RLCBTC,RLCETH,AIDUSD,AIDBTC,AIDETH,SNGUSD,SNGBTC,SNGETH,REPUSD,REPBTC,REPETH,ELFUSD,ELFBTC,ELFETH,BTCGBP,ETHEUR,ETHJPY,ETHGBP,NEOEUR,NEOJPY,NEOGBP,EOSEUR,EOSJPY,EOSGBP,IOTJPY,IOTGBP,IOSUSD,IOSBTC,IOSETH,AIOUSD,AIOBTC,AIOETH,REQUSD,REQBTC,REQETH,RDNUSD,RDNBTC,RDNETH,LRCUSD,LRCBTC,LRCETH,WAXUSD,WAXBTC,WAXETH,DAIUSD,DAIBTC,DAIETH,CFIUSD,CFIBTC,CFIETH,AGIUSD,AGIBTC,AGIETH,BFTUSD,BFTBTC,BFTETH,MTNUSD,MTNBTC,MTNETH,ODEUSD,ODEBTC,ODEETH,ANTUSD,ANTBTC,ANTETH,DTHUSD,DTHBTC,DTHETH,MITUSD,MITBTC,MITETH,STJUSD,STJBTC,STJETH,XLMUSD,XLMEUR,XLMJPY,XLMGBP,XLMBTC,XLMETH,XVGUSD,XVGEUR,XVGJPY,XVGGBP,XVGBTC,XVGETH,BCIUSD,BCIBTC,MKRUSD,MKRBTC,MKRETH,VENUSD,VENBTC,VENETH,KNCUSD,KNCBTC,KNCETH,POAUSD,POABTC,POAETH,LYMUSD,LYMBTC,LYMETH,UTKUSD,UTKBTC,UTKETH,VEEUSD,VEEBTC,VEEETH,DADUSD,DADBTC,DADETH,ORSUSD,ORSBTC,ORSETH,AUCUSD,AUCBTC,AUCETH,POYUSD,POYBTC,POYETH,FSNUSD,FSNBTC,FSNETH,CBTUSD,CBTBTC,CBTETH,ZCNUSD,ZCNBTC,ZCNETH,SENUSD,SENBTC,SENETH,NCAUSD,NCABTC,NCAETH,CNDUSD,CNDBTC,CNDETH,CTXUSD,CTXBTC,CTXETH,PAIUSD,PAIBTC,SEEUSD,SEEBTC,SEEETH,ESSUSD,ESSBTC,ESSETH,ATMUSD,ATMBTC,ATMETH,HOTUSD,HOTBTC,HOTETH,DTAUSD,DTABTC,DTAETH,IQXUSD,IQXBTC,IQXEOS,WPRUSD,WPRBTC,WPRETH,ZILUSD,ZILBTC,ZILETH,BNTUSD,BNTBTC,BNTETH", "EnabledPairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -348,7 +348,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BTC-LTC,BTC-DOGE,BTC-VTC,BTC-PPC,BTC-FTC,BTC-RDD,BTC-NXT,BTC-DASH,BTC-POT,BTC-BLK,BTC-EMC2,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-VRC,BTC-CURE,BTC-XMR,BTC-CLOAK,BTC-KORE,BTC-XDN,BTC-TRUST,BTC-NAV,BTC-XST,BTC-VIA,BTC-PINK,BTC-IOC,BTC-CANN,BTC-SYS,BTC-NEOS,BTC-DGB,BTC-BURST,BTC-EXCL,BTC-BITS,BTC-DOPE,BTC-BLOCK,BTC-ABY,BTC-BYC,BTC-XMG,BTC-BAY,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-AEON,BTC-ETH,BTC-TX,BTC-BCY,BTC-EXP,BTC-OMNI,BTC-AMP,BTC-XLM,USDT-BTC,BTC-RVR,BTC-EMC,BTC-FCT,BTC-EGC,BTC-SLS,BTC-RADS,BTC-DCR,BTC-BSD,BTC-XVG,BTC-PIVX,BTC-MEME,BTC-STEEM,BTC-2GIVE,BTC-LSK,BTC-BRK,BTC-WAVES,BTC-LBC,BTC-SBD,BTC-BRX,BTC-ETC,ETH-ETC,BTC-STRAT,BTC-UNB,BTC-SYNX,BTC-EBST,BTC-VRM,BTC-SEQ,BTC-REP,BTC-SHIFT,BTC-ARDR,BTC-XZC,BTC-NEO,BTC-ZEC,BTC-ZCL,BTC-IOP,BTC-GOLOS,BTC-UBQ,BTC-KMD,BTC-GBG,BTC-SIB,BTC-ION,BTC-LMC,BTC-QWARK,BTC-CRW,BTC-SWT,BTC-MLN,BTC-ARK,BTC-DYN,BTC-TKS,BTC-MUSIC,BTC-DTB,BTC-INCNT,BTC-GBYTE,BTC-GNT,BTC-NXC,BTC-EDG,BTC-MORE,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-GNO,BTC-HMQ,BTC-ANT,ETH-ANT,BTC-SC,ETH-BAT,BTC-BAT,BTC-ZEN,BTC-QRL,BTC-CRB,ETH-MORE,BTC-PTOY,BTC-CFI,ETH-CFI,BTC-BNT,ETH-BNT,BTC-NMR,ETH-LTC,ETH-XRP,BTC-SNT,ETH-SNT,BTC-DCT,BTC-XEL,BTC-MCO,ETH-MCO,BTC-ADT,ETH-ADT,BTC-PAY,ETH-PAY,BTC-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-BCH,USDT-BCH,BTC-BCH,BTC-DNT,ETH-DNT,USDT-NEO,ETH-WAVES,ETH-STRAT,ETH-DGB,ETH-FCT,USDT-OMG,BTC-ADA,BTC-MANA,ETH-MANA,BTC-SALT,ETH-SALT,BTC-TIX,ETH-TIX,BTC-RCN,ETH-RCN,BTC-VIB,ETH-VIB,BTC-MER,BTC-POWR,ETH-POWR,BTC-BTG,ETH-BTG,USDT-BTG,ETH-ADA,BTC-ENG,ETH-ENG,USDT-ADA,USDT-XVG,USDT-NXT,BTC-UKG,ETH-UKG,BTC-IGNIS,BTC-SRN,ETH-SRN,BTC-WAX,ETH-WAX,BTC-ZRX,ETH-ZRX,BTC-VEE,ETH-VEE,BTC-BCPT,ETH-BCPT,BTC-TRX,ETH-TRX,BTC-TUSD,BTC-LRC,ETH-LRC,ETH-TUSD,BTC-UP,ETH-UP,BTC-DMT,ETH-DMT,USDT-TUSD,BTC-POLY,ETH-POLY,BTC-PRO,ETH-PRO,USDT-SC,USDT-TRX,BTC-BLT,ETH-BLT,BTC-STORM,ETH-STORM,BTC-AID,ETH-AID,BTC-NGC,ETH-NGC,BTC-GTO,ETH-GTO,USDT-DCR,BTC-OCN,ETH-OCN,USD-BTC,USD-USDT,USD-TUSD,BTC-TUBE,BTC-CBC,BTC-CMCT,USD-ETH,BTC-NLC2,BTC-BKX,BTC-MFT", + "AvailablePairs": "BTC-LTC,BTC-DOGE,BTC-VTC,BTC-PPC,BTC-FTC,BTC-RDD,BTC-NXT,BTC-DASH,BTC-POT,BTC-BLK,BTC-EMC2,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-VRC,BTC-CURE,BTC-XMR,BTC-CLOAK,BTC-KORE,BTC-XDN,BTC-TRUST,BTC-NAV,BTC-XST,BTC-VIA,BTC-PINK,BTC-IOC,BTC-CANN,BTC-SYS,BTC-NEOS,BTC-DGB,BTC-BURST,BTC-EXCL,BTC-BITS,BTC-DOPE,BTC-BLOCK,BTC-ABY,BTC-BYC,BTC-XMG,BTC-BAY,BTC-SPR,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-AEON,BTC-ETH,BTC-TX,BTC-BCY,BTC-EXP,BTC-OMNI,BTC-AMP,BTC-XLM,USDT-BTC,BTC-RVR,BTC-EMC,BTC-FCT,BTC-EGC,BTC-SLS,BTC-RADS,BTC-DCR,BTC-BSD,BTC-XVG,BTC-PIVX,BTC-MEME,BTC-STEEM,BTC-2GIVE,BTC-LSK,BTC-BRK,BTC-WAVES,BTC-LBC,BTC-SBD,BTC-BRX,BTC-ETC,ETH-ETC,BTC-STRAT,BTC-UNB,BTC-SYNX,BTC-EBST,BTC-VRM,BTC-SEQ,BTC-REP,BTC-SHIFT,BTC-ARDR,BTC-XZC,BTC-NEO,BTC-ZEC,BTC-ZCL,BTC-IOP,BTC-GOLOS,BTC-UBQ,BTC-KMD,BTC-GBG,BTC-SIB,BTC-ION,BTC-LMC,BTC-QWARK,BTC-CRW,BTC-SWT,BTC-MLN,BTC-ARK,BTC-DYN,BTC-TKS,BTC-MUSIC,BTC-DTB,BTC-INCNT,BTC-GBYTE,BTC-GNT,BTC-NXC,BTC-EDG,BTC-MORE,ETH-GNT,ETH-REP,USDT-ETH,BTC-WINGS,BTC-RLC,BTC-GNO,BTC-GUP,BTC-LUN,ETH-RLC,ETH-LUN,ETH-GNO,BTC-HMQ,BTC-ANT,ETH-ANT,BTC-SC,ETH-BAT,BTC-BAT,BTC-ZEN,BTC-QRL,BTC-CRB,ETH-MORE,BTC-PTOY,BTC-CFI,BTC-BNT,ETH-BNT,BTC-NMR,ETH-LTC,ETH-XRP,BTC-SNT,ETH-SNT,BTC-DCT,BTC-XEL,BTC-MCO,ETH-MCO,BTC-ADT,BTC-PAY,ETH-PAY,BTC-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-BCH,USDT-BCH,BTC-BCH,BTC-DNT,USDT-NEO,ETH-WAVES,ETH-STRAT,ETH-DGB,ETH-FCT,USDT-OMG,BTC-ADA,BTC-MANA,ETH-MANA,BTC-SALT,ETH-SALT,BTC-TIX,BTC-RCN,ETH-RCN,BTC-VIB,ETH-VIB,BTC-MER,BTC-POWR,ETH-POWR,BTC-BTG,ETH-BTG,USDT-BTG,ETH-ADA,BTC-ENG,ETH-ENG,USDT-ADA,USDT-XVG,USDT-NXT,BTC-UKG,ETH-UKG,BTC-IGNIS,BTC-SRN,ETH-SRN,BTC-WAX,ETH-WAX,BTC-ZRX,ETH-ZRX,BTC-VEE,ETH-VEE,BTC-BCPT,ETH-BCPT,BTC-TRX,ETH-TRX,BTC-TUSD,BTC-LRC,ETH-LRC,ETH-TUSD,BTC-UP,ETH-UP,BTC-DMT,ETH-DMT,USDT-TUSD,BTC-POLY,ETH-POLY,BTC-PRO,ETH-PRO,USDT-SC,USDT-TRX,BTC-BLT,ETH-BLT,BTC-STORM,ETH-STORM,BTC-AID,ETH-AID,BTC-NGC,ETH-NGC,BTC-GTO,ETH-GTO,USDT-DCR,BTC-OCN,ETH-OCN,USD-BTC,USD-USDT,USD-TUSD,BTC-TUBE,BTC-CBC,BTC-CMCT,USD-ETH,BTC-NLC2,BTC-BKX,BTC-MFT,BTC-LOOM,BTC-RFR,USDT-DGB", "EnabledPairs": "USDT-BTC", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -487,7 +487,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "STQ_EUR,ZEC_USD,XRP_USD,XLM_BTC,XLM_USD,ETC_RUB,BCH_RUB,ETH_USD,ZEC_RUB,WAVES_BTC,BTC_USD,DXT_BTC,EOS_BTC,XRP_RUB,BTC_UAH,STQ_BTC,ETC_USD,ETH_UAH,BTC_USDT,ETH_USDT,HBZ_USD,LTC_BTC,XMR_EUR,LTC_EUR,BTG_USD,DASH_RUB,ETH_BTC,ZEC_EUR,KICK_BTC,DASH_USD,ETH_LTC,ETH_RUB,USDT_USD,WAVES_RUB,BCH_ETH,ETH_PLN,ETC_BTC,BTCZ_BTC,STQ_RUB,EOS_USD,BTC_PLN,LTC_USD,KICK_ETH,DXT_USD,HBZ_ETH,ETH_EUR,XMR_USD,USDT_RUB,USD_RUB,BCH_USD,DASH_BTC,LTC_RUB,DOGE_BTC,BCH_BTC,ZEC_BTC,XRP_BTC,BTC_EUR,BTG_BTC,HBZ_BTC,XMR_BTC,BTC_RUB,XLM_RUB,STQ_USD", + "AvailablePairs": "BTCZ_BTC,EOS_USD,BTC_UAH,LTC_USD,ETH_RUB,WAVES_BTC,DXT_BTC,ETH_USD,LTC_EUR,LTC_RUB,BTC_PLN,TRX_BTC,OMG_BTC,HBZ_BTC,ZEC_BTC,DOGE_BTC,XRP_USD,BTC_USD,MNX_ETH,BTG_USD,BCH_BTC,BTG_BTC,XMR_EUR,USD_RUB,BTC_EUR,BTC_RUB,STQ_BTC,STQ_EUR,MNX_BTC,ETH_PLN,ETC_BTC,XRP_RUB,OMG_USD,DASH_BTC,ETH_LTC,XMR_BTC,ETH_USDT,DASH_RUB,ETH_EUR,ETC_USD,ETC_RUB,MNX_USD,ZEC_EUR,ZEC_RUB,OMG_ETH,XMR_USD,USDT_USD,TRX_RUB,XLM_RUB,EOS_BTC,USDT_RUB,HBZ_USD,DASH_USD,ZEC_USD,WAVES_RUB,XLM_BTC,XLM_USD,STQ_USD,STQ_RUB,XRP_BTC,BTC_USDT,KICK_BTC,KICK_ETH,TRX_USD,HBZ_ETH,BCH_ETH,LTC_BTC,ETH_UAH,DXT_USD,BCH_USD,BCH_RUB,ETH_BTC", "EnabledPairs": "BTC_USD,LTC_USD", "BaseCurrencies": "USD,EUR,RUB,PLN,UAH", "AssetTypes": "SPOT", @@ -549,6 +549,42 @@ } ] }, + { + "Name": "GateIO", + "Enabled": true, + "Verbose": false, + "Websocket": false, + "UseSandbox": false, + "RESTPollingDelay": 10, + "HTTPTimeout": 15000000000, + "AuthenticatedAPISupport": false, + "APIKey": "Key", + "APISecret": "Secret", + "AvailablePairs": "BTC_USDT,BCH_USDT,ETH_USDT,ETC_USDT,QTUM_USDT,LTC_USDT,DASH_USDT,ZEC_USDT,BTM_USDT,EOS_USDT,REQ_USDT,SNT_USDT,OMG_USDT,PAY_USDT,CVC_USDT,ZRX_USDT,TNT_USDT,XMR_USDT,XRP_USDT,DOGE_USDT,BAT_USDT,PST_USDT,BTG_USDT,DPY_USDT,LRC_USDT,STORJ_USDT,RDN_USDT,STX_USDT,KNC_USDT,LINK_USDT,CDT_USDT,AE_USDT,AE_ETH,AE_BTC,CDT_ETH,RDN_ETH,STX_ETH,KNC_ETH,LINK_ETH,REQ_ETH,RCN_ETH,TRX_ETH,ARN_ETH,KICK_ETH,BNT_ETH,VET_ETH,MCO_ETH,FUN_ETH,DATA_ETH,RLC_ETH,RLC_USDT,ZSC_ETH,WINGS_ETH,MDA_ETH,RCN_USDT,TRX_USDT,KICK_USDT,VET_USDT,MCO_USDT,FUN_USDT,DATA_USDT,ZSC_USDT,MDA_USDT,XTZ_USDT,XTZ_BTC,XTZ_ETH,GNT_USDT,GNT_ETH,GEM_USDT,GEM_ETH,RFR_USDT,RFR_ETH,DADI_USDT,DADI_ETH,ABT_USDT,ABT_ETH,LEDU_BTC,LEDU_ETH,OST_USDT,OST_ETH,XLM_USDT,XLM_ETH,XLM_BTC,MOBI_USDT,MOBI_ETH,MOBI_BTC,OCN_USDT,OCN_ETH,OCN_BTC,ZPT_USDT,ZPT_ETH,ZPT_BTC,COFI_USDT,COFI_ETH,JNT_USDT,JNT_ETH,JNT_BTC,BLZ_USDT,BLZ_ETH,GXS_USDT,GXS_BTC,MTN_USDT,MTN_ETH,RUFF_USDT,RUFF_ETH,RUFF_BTC,TNC_USDT,TNC_ETH,TNC_BTC,ZIL_USDT,ZIL_ETH,TIO_USDT,TIO_ETH,BTO_USDT,BTO_ETH,THETA_USDT,THETA_ETH,DDD_USDT,DDD_ETH,DDD_BTC,MKR_USDT,MKR_ETH,DAI_USDT,SMT_USDT,SMT_ETH,MDT_USDT,MDT_ETH,MDT_BTC,MANA_USDT,MANA_ETH,LUN_USDT,LUN_ETH,SALT_USDT,SALT_ETH,FUEL_USDT,FUEL_ETH,ELF_USDT,ELF_ETH,DRGN_USDT,DRGN_ETH,GTC_USDT,GTC_ETH,GTC_BTC,QLC_USDT,QLC_BTC,QLC_ETH,DBC_USDT,DBC_BTC,DBC_ETH,BNTY_USDT,BNTY_ETH,LEND_USDT,LEND_ETH,ICX_USDT,ICX_ETH,BTF_USDT,BTF_BTC,ADA_USDT,ADA_BTC,LSK_USDT,LSK_BTC,WAVES_USDT,WAVES_BTC,BIFI_USDT,BIFI_BTC,MDS_ETH,MDS_USDT,DGD_USDT,DGD_ETH,QASH_USDT,QASH_ETH,QASH_BTC,POWR_USDT,POWR_ETH,POWR_BTC,FIL_USDT,BCD_USDT,BCD_BTC,SBTC_USDT,SBTC_BTC,GOD_USDT,GOD_BTC,BCX_USDT,BCX_BTC,HSR_USDT,HSR_BTC,HSR_ETH,QSP_USDT,QSP_ETH,INK_BTC,INK_USDT,INK_ETH,INK_QTUM,MED_QTUM,MED_ETH,MED_USDT,BOT_QTUM,BOT_USDT,BOT_ETH,QBT_QTUM,QBT_ETH,QBT_USDT,TSL_QTUM,TSL_USDT,GNX_USDT,GNX_ETH,NEO_USDT,GAS_USDT,NEO_BTC,GAS_BTC,IOTA_USDT,IOTA_BTC,NAS_USDT,NAS_ETH,NAS_BTC,ETH_BTC,ETC_BTC,ETC_ETH,ZEC_BTC,DASH_BTC,LTC_BTC,BCH_BTC,BTG_BTC,QTUM_BTC,QTUM_ETH,XRP_BTC,DOGE_BTC,XMR_BTC,ZRX_BTC,ZRX_ETH,DNT_ETH,DPY_ETH,OAX_ETH,REP_ETH,LRC_ETH,LRC_BTC,PST_ETH,BCDN_ETH,BCDN_USDT,TNT_ETH,SNT_ETH,SNT_BTC,BTM_ETH,BTM_BTC,LLT_ETH,SNET_ETH,SNET_USDT,LLT_SNET,OMG_ETH,OMG_BTC,PAY_ETH,PAY_BTC,BAT_ETH,BAT_BTC,CVC_ETH,STORJ_ETH,STORJ_BTC,EOS_ETH,EOS_BTC,BTS_USDT,BTS_BTC,TIPS_ETH,BU_USDT,BU_ETH,XMC_USDT,XMC_BTC,PPS_USDT,BOE_ETH,BOE_USDT,PLY_ETH,MEDX_USDT,MEDX_ETH,CS_ETH,CS_USDT,MAN_ETH,MAN_USDT,REM_ETH,REM_USDT,LYM_ETH,LYM_BTC,LYM_USDT,ONT_ETH,ONT_USDT,BFT_ETH,BFT_USDT,IHT_ETH,IHT_USDT,SENC_ETH,SENC_USDT,TOMO_ETH,TOMO_USDT,ELEC_ETH,ELEC_USDT,HAV_ETH,HAV_USDT,SWTH_ETH,SWTH_USDT,NKN_ETH,NKN_USDT,SOUL_ETH,SOUL_USDT,LRN_ETH,LRN_USDT,EOSDAC_ETH,EOSDAC_USDT,ADD_ETH,IQ_ETH,MEETONE_ETH,DOCK_USDT,DOCK_ETH,GSE_USDT,GSE_ETH,RATING_USDT,RATING_ETH,HSC_USDT,HSC_ETH,GARD_USDT,GARD_ETH,FTI_USDT,FTI_ETH,SOP_ETH,SOP_USDT,LEMO_USDT,LEMO_ETH,EON_ETH,NPXS_ETH,QKC_USDT,QKC_ETH,IOTX_USDT,IOTX_ETH,RED_USDT,RED_ETH,LBA_USDT,LBA_ETH,OPEN_USDT,OPEN_ETH,MITH_USDT,MITH_ETH,SKM_USDT,SKM_ETH,XVG_USDT,XVG_BTC,NANO_USDT,NANO_BTC,NBAI_ETH,UPP_ETH,ATMI_ETH,TMT_ETH,HT_USDT,BNB_USDT,BBK_ETH,EDR_ETH,MET_ETH,MET_USDT,TCT_ETH,TCT_USDT", + "EnabledPairs": "BTC_USDT", + "BaseCurrencies": "USD", + "AssetTypes": "SPOT", + "SupportsAutoPairUpdates": true, + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + }, + "BankAccounts": [ + { + "BankName": "", + "BankAddress": "", + "AccountName": "", + "AccountNumber": "", + "SWIFTCode": "", + "IBAN": "", + "SupportedCurrencies": "" + } + ] + }, { "Name": "Gemini", "Enabled": true, @@ -594,7 +630,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BCN-BTC,BTC-USD,DASH-BTC,DOGE-BTC,DOGE-USD,DSH-BTC,EMC-BTC,ETH-BTC,FCN-BTC,LSK-BTC,LTC-BTC,LTC-USD,NXT-BTC,SBD-BTC,SC-BTC,STEEM-BTC,XDN-BTC,XEM-BTC,XMR-BTC,ARDR-BTC,ZEC-BTC,WAVES-BTC,MAID-BTC,AMP-BTC,BUS-BTC,DGD-BTC,ICN-BTC,SNGLS-BTC,1ST-BTC,TRST-BTC,TIME-BTC,GNO-BTC,REP-BTC,XMR-USD,DASH-USD,ETH-USD,NXT-USD,ZRC-BTC,BOS-BTC,DCT-BTC,ANT-BTC,AEON-BTC,GUP-BTC,PLU-BTC,LUN-BTC,TAAS-BTC,NXC-BTC,EDG-BTC,RLC-BTC,SWT-BTC,TKN-BTC,WINGS-BTC,XAUR-BTC,AE-BTC,PTOY-BTC,ZEC-USD,XEM-USD,BCN-USD,XDN-USD,MAID-USD,ETC-BTC,ETC-USD,CFI-BTC,PLBT-BTC,BNT-BTC,XDNCO-BTC,FYN-ETH,SNM-BTC,SNM-ETH,SNT-ETH,CVC-USD,PAY-ETH,OAX-ETH,OMG-ETH,BQX-ETH,XTZ-BTC,DICE-BTC,CFI-ETH,PTOY-ETH,1ST-ETH,XAUR-ETH,TAAS-ETH,TIME-ETH,DICE-ETH,SWT-ETH,XMR-ETH,ETC-ETH,DASH-ETH,ZEC-ETH,PLU-ETH,GNO-ETH,XRP-BTC,NET-ETH,STRAT-USD,STRAT-BTC,SNC-ETH,ADX-ETH,BET-ETH,EOS-ETH,DENT-ETH,SAN-ETH,EOS-BTC,EOS-USD,MNE-BTC,MSP-ETH,DDF-ETH,XTZ-ETH,XTZ-USD,UET-ETH,MYB-ETH,SUR-ETH,IXT-ETH,PLR-ETH,TIX-ETH,NDC-ETH,PRO-ETH,AVT-ETH,COSS-ETH,EVX-USD,DLT-BTC,BNT-ETH,BNT-USD,QAU-BTC,QAU-ETH,MANA-USD,DNT-BTC,FYP-BTC,OPT-BTC,TNT-ETH,IFT-BTC,STX-BTC,STX-ETH,STX-USD,TNT-USD,TNT-BTC,CAT-BTC,CAT-ETH,CAT-USD,BCH-BTC,BCH-ETH,BCH-USD,ENG-ETH,XUC-USD,SNC-BTC,SNC-USD,OAX-USD,OAX-BTC,BAS-ETH,ZRX-BTC,ZRX-ETH,ZRX-USD,RVT-BTC,ICOS-BTC,ICOS-ETH,ICOS-USD,PPC-BTC,PPC-USD,QTUM-ETH,VERI-BTC,VERI-ETH,VERI-USD,IGNIS-ETH,PRG-BTC,PRG-ETH,PRG-USD,BMC-BTC,BMC-ETH,BMC-USD,CND-BTC,CND-ETH,CND-USD,SKIN-BTC,EMGO-BTC,EMGO-USD,CDT-ETH,CDT-USD,FUN-BTC,FUN-ETH,FUN-USD,HVN-BTC,HVN-ETH,FUEL-BTC,FUEL-ETH,FUEL-USD,POE-BTC,POE-ETH,MCAP-BTC,AIR-BTC,AIR-ETH,AIR-USD,AMB-USD,AMB-ETH,AMB-BTC,NTO-BTC,ICO-BTC,PING-BTC,GAME-BTC,TKR-ETH,HPC-BTC,PPT-ETH,MTH-BTC,MTH-ETH,WMGO-BTC,WMGO-USD,LRC-BTC,LRC-ETH,ICX-BTC,ICX-ETH,NEO-BTC,NEO-ETH,NEO-USD,CSNO-BTC,ORME-BTC,ICX-USD,PIX-BTC,PIX-ETH,IND-ETH,KICK-BTC,YOYOW-BTC,MIPS-BTC,CDT-BTC,XVG-BTC,XVG-ETH,XVG-USD,DGB-BTC,DGB-ETH,DGB-USD,DCN-BTC,DCN-ETH,DCN-USD,CCT-ETH,EBET-ETH,VIBE-BTC,VOISE-BTC,ENJ-BTC,ENJ-ETH,ENJ-USD,ZSC-BTC,ZSC-ETH,ZSC-USD,ETBS-BTC,VEN-BTC,VEN-ETH,VEN-USD,ART-BTC,EVX-BTC,EVX-ETH,QVT-ETH,EBTCOLD-BTC,EBTCOLD-ETH,EBTCOLD-USD,BKB-BTC,EXN-BTC,TGT-BTC,ATS-ETH,BMT-BTC,BMT-ETH,SUB-BTC,SUB-ETH,SUB-USD,WTC-BTC,CNX-BTC,ATB-BTC,ATB-ETH,ATB-USD,ODN-BTC,BTM-BTC,BTM-ETH,BTM-USD,B2X-BTC,B2X-ETH,B2X-USD,ATM-BTC,ATM-ETH,ATM-USD,LIFE-BTC,VIB-BTC,VIB-ETH,VIB-USD,DRT-ETH,STU-USD,OMG-BTC,PAY-BTC,COSS-BTC,PPT-BTC,SNT-BTC,BTG-BTC,BTG-ETH,BTG-USD,SMART-BTC,SMART-ETH,SMART-USD,XUC-ETH,XUC-BTC,CL-BTC,CL-ETH,CL-USD,LA-ETH,CLD-BTC,CLD-ETH,CLD-USD,EDO-BTC,EDO-ETH,EDO-USD,HGT-ETH,POLL-BTC,IXT-BTC,ATS-BTC,SCL-BTC,ATL-BTC,EBTC-BTC,EBTC-ETH,EBTC-USD,ETP-BTC,ETP-ETH,ETP-USD,OTX-BTC,CDX-ETH,DRPU-BTC,NEBL-BTC,NEBL-ETH,HAC-BTC,CTX-BTC,CTX-ETH,ELE-BTC,ARN-BTC,ARN-ETH,STU-BTC,STU-ETH,GVT-ETH,INDI-BTC,BTX-BTC,LTC-ETH,BCN-ETH,MAID-ETH,NXT-ETH,STRAT-ETH,XDN-ETH,XEM-ETH,PLR-BTC,SUR-BTC,BQX-BTC,DOGE-ETH,ITS-BTC,AMM-BTC,AMM-ETH,AMM-USD,DBIX-BTC,PRE-BTC,KBR-BTC,TBT-BTC,ERO-BTC,SMS-BTC,SMS-ETH,SMS-USD,ZAP-BTC,DOV-BTC,DOV-ETH,DRPU-ETH,OTN-BTC,XRP-ETH,XRP-USD,HSR-BTC,LEND-BTC,LEND-ETH,SPF-BTC,SPF-ETH,SBTC-BTC,SBTC-ETH,WRC-BTC,WRC-ETH,WRC-USD,LOC-BTC,LOC-ETH,LOC-USD,SWFTC-BTC,SWFTC-ETH,SWFTC-USD,STAR-ETH,SBTC-USD,STORM-BTC,DIM-ETH,DIM-USD,DIM-BTC,NGC-BTC,NGC-ETH,NGC-USD,EMC-ETH,EMC-USD,MCO-BTC,MCO-ETH,MCO-USD,MANA-ETH,MANA-BTC,ECH-BTC,CPAY-ETH,DATA-BTC,DATA-ETH,DATA-USD,UTT-BTC,UTT-ETH,UTT-USD,KMD-BTC,KMD-ETH,KMD-USD,QTUM-USD,QTUM-BTC,SNT-USD,OMG-USD,EKO-BTC,EKO-ETH,ADX-BTC,ADX-USD,LSK-ETH,LSK-USD,PLR-USD,SUR-USD,BQX-USD,DRT-USD,REP-ETH,REP-USD,TIO-BTC,TIO-ETH,TIO-USD,WAX-BTC,WAX-ETH,WAX-USD,EET-BTC,EET-ETH,EET-USD,C20-BTC,C20-ETH,IDH-BTC,IDH-ETH,IPL-BTC,COV-BTC,COV-ETH,SENT-BTC,SENT-ETH,SENT-USD,SMT-BTC,SMT-ETH,SMT-USD,CVH-ETH,CVH-USD,CAS-BTC,CAS-ETH,CAS-USD,CHAT-BTC,CHAT-ETH,CHAT-USD,GRMD-BTC,AVH-BTC,TRAC-ETH,JNT-ETH,PCL-BTC,PCL-ETH,CLOUT-BTC,UTK-BTC,UTK-ETH,UTK-USD,GNX-ETH,CHSB-BTC,CHSB-ETH,AVH-ETH,DAY-BTC,DAY-ETH,DAY-USD,NEU-BTC,NEU-ETH,NEU-USD,AVH-USD,CLOUT-ETH,CLOUT-USD,TAU-BTC,MEK-BTC,FLP-BTC,FLP-ETH,FLP-USD,R-BTC,R-ETH,EKO-USD,BCPT-ETH,BCPT-USD,PKT-BTC,PKT-ETH,WLK-BTC,WLK-ETH,WLK-USD,EVN-BTC,CPG-BTC,CPG-ETH,BPTN-BTC,BPTN-ETH,BPTN-USD,BETR-BTC,BETR-ETH,ARCT-BTC,ARCT-USD,DBET-BTC,DBET-ETH,DBET-USD,RNTB-ETH,HAND-ETH,HAND-USD,BEZ-BTC,BEZ-ETH,BEZ-USD,ACO-ETH,CTE-BTC,CTE-ETH,CTE-USD,UTNP-BTC,UTNP-ETH,UTNP-USD,CPY-BTC,CPY-ETH,CHP-ETH,BCPT-BTC,ACT-BTC,ACT-ETH,ACT-USD,HIRE-ETH,ADA-BTC,ADA-ETH,ADA-USD,SIG-BTC,RPM-BTC,RPM-ETH,MTX-BTC,MTX-ETH,MTX-USD,BGG-BTC,BGG-ETH,BGG-USD,SETH-ETH,WIZ-BTC,WIZ-ETH,WIZ-USD,DADI-BTC,DADI-ETH,BDG-ETH,DATX-BTC,DATX-ETH,TRUE-BTC,DRG-BTC,DRG-ETH,BANCA-BTC,BANCA-ETH,ZAP-ETH,ZAP-USD,AUTO-BTC,NOAH-BTC,SOC-BTC,WILD-BTC,INSUR-BTC,INSUR-ETH,OCN-BTC,OCN-ETH,STQ-BTC,STQ-ETH,XLM-BTC,XLM-ETH,XLM-USD,IOTA-BTC,IOTA-ETH,IOTA-USD,DRT-BTC,MLD-BTC,MLD-ETH,MLD-USD,BETR-USD,CGC-ETH,ERT-BTC,CRPT-BTC,CRPT-USD,MESH-BTC,MESH-ETH,MESH-USD,HLW-ETH,IHT-BTC,IHT-ETH,IHT-USD,SCC-BTC,YCC-BTC,DAN-BTC,TEL-BTC,TEL-ETH,BUBO-BTC,BUBO-ETH,BUBO-USD,VIT-BTC,VIT-ETH,VIT-USD,NCT-BTC,NCT-ETH,NCT-USD,AXP-BTC,AXP-ETH,BMH-BTC,BANCA-USD,NOAH-ETH,NOAH-USD,HQX-BTC,LDC-BTC,XMO-BTC,XMO-USD,XMO-ETH,BERRY-BTC,BERRY-ETH,BERRY-USD,BSTN-BTC,BSTN-ETH,BSTN-USD,GBX-BTC,GBX-ETH,GBX-USD,SHIP-BTC,SHIP-ETH,NANO-BTC,NANO-ETH,NANO-USD,LNC-BTC,UNC-BTC,UNC-ETH,RPX-BTC,RPX-ETH,RPX-USD,KIN-ETH,ARDR-USD,DAXT-BTC,DAXT-ETH,FOTA-ETH,FOTA-BTC,SETH-BTC,CVT-BTC,CVT-ETH,CVT-USD,STQ-USD,GNT-BTC,GNT-ETH,GNT-USD,ADH-BTC,ADH-ETH,BBC-BTC,BBC-ETH,GET-BTC,MITH-BTC,MITH-ETH,MITH-USD,SUNC-ETH,DADI-USD,TKY-BTC,ACAT-BTC,ACAT-ETH,ACAT-USD,BTX-USD,TCN-BTC,VIO-ETH,WIKI-BTC,WIKI-ETH,WIKI-USD,ONT-BTC,ONT-ETH,ONT-USD,FTX-BTC,FTX-ETH,FREC-BTC,NAVI-BTC,FREC-ETH,FREC-USD,VME-ETH,NAVI-ETH,BTCP-BTC,LND-ETH,CSM-BTC,NANJ-BTC,MTC-BTC,MTC-ETH,MTC-USD,NTK-BTC,NTK-ETH,NTK-USD,AUC-BTC,AUC-ETH,CMCT-BTC,CMCT-ETH,CMCT-USD,MAN-BTC,MAN-ETH,MAN-USD,HIRE-BTC,TKA-BTC,TKA-ETH,TKA-USD,PNT-BTC,PNT-ETH,FXT-BTC,NEXO-BTC,CHX-BTC,CHX-ETH,CHX-USD,PAT-BTC,PAT-ETH,XMC-BTC,EJOY-BTC,EJOY-ETH,EJOY-USD,FXT-ETH,HERO-BTC,HERO-ETH,XMC-ETH,XMC-USD,STAK-BTC,STAK-ETH,FDZ-BTC,FDZ-ETH,FDZ-USD,SPD-BTC,SPD-ETH,LUC-BTC,MITX-BTC,TIV-BTC,B2G-BTC,B2G-USD,ZPT-BTC,ZPT-ETH,HBZ-BTC,FACE-BTC,FACE-ETH,HBZ-ETH,HBZ-USD,ZPT-USD,MORPH-BTC,MORPH-ETH,MORPH-USD,EBKC-BTC,CPT-BTC,PAT-USD,HTML-BTC,HTML-ETH,MITX-ETH,JOT-BTC,JBC-BTC,JBC-ETH,BTS-BTC,BNK-BTC,KBC-BTC,KBC-ETH,BNK-ETH,BNK-USD,TIV-ETH,TIV-USD,LUC-ETH,LUC-USD,CSM-ETH,CSM-USD,INK-BTC,IOST-BTC,INK-ETH,INK-USD,CBC-BTC,IOST-USD,COIN-BTC,ZIL-BTC,COIN-USD,COIN-ETH,PMNT-BTC,ABYSS-BTC,ABYSS-ETH,ZIL-USD,BCI-BTC,CBC-ETH,CBC-USD,PITCH-BTC,PITCH-ETH,HTML-USD,TDS-BTC,TDS-ETH,TDS-USD,SBD-ETH,SBD-USD,DPN-BTC,UUU-BTC,UUU-ETH,XBP-BTC,KRM-USD,CLN-BTC,IVY-BTC,IVY-ETH,TTU-BTC,TTU-ETH,TTU-USD,CLN-ETH,DOR-BTC,DOR-ETH,DOR-USD,ELEC-BTC,ELEC-ETH,ELEC-USD,QNTU-BTC,QNTU-ETH,QNTU-USD,IPL-ETH,IPL-USD,CENNZ-BTC,BTCP-ETH,BTCP-USD,CENNZ-ETH,SWM-BTC,MXM-BTC,MXM-ETH,SPF-USD,LCC-BTC,HGT-BTC,BTC-TUSD,XMR-TUSD,USD-TUSD,BTC-DAI,ETH-DAI,MKR-DAI,USD-DAI,MKR-BTC,MKR-ETH,MKR-USD,ETH-TUSD,ZRX-TUSD,TUSD-DAI,LTC-TUSD,EOS-DAI,NEO-TUSD,BCH-TUSD,NEO-DAI,LTC-DAI,XMR-DAI,BCH-DAI,XRP-DAI,NEXO-ETH,NEXO-USD,DWS-BTC,DWS-ETH,DWS-USD,APPC-BTC,APPC-ETH,APPC-USD,BIT-ETH,TRX-BTC,TRX-ETH,TRX-USD,SPC-BTC,SPC-ETH,SPC-USD,REX-BTC,REX-ETH,REX-USD", + "AvailablePairs": "BCN-BTC,BTC-USD,DASH-BTC,DOGE-BTC,DOGE-USD,DSH-BTC,EMC-BTC,ETH-BTC,FCN-BTC,LSK-BTC,LTC-BTC,LTC-USD,NXT-BTC,SBD-BTC,SC-BTC,STEEM-BTC,XDN-BTC,XEM-BTC,XMR-BTC,ARDR-BTC,ZEC-BTC,WAVES-BTC,MAID-BTC,AMP-BTC,BUS-BTC,DGD-BTC,ICN-BTC,SNGLS-BTC,1ST-BTC,TRST-BTC,TIME-BTC,GNO-BTC,REP-BTC,XMR-USD,DASH-USD,ETH-USD,NXT-USD,ZRC-BTC,BOS-BTC,DCT-BTC,ANT-BTC,AEON-BTC,GUP-BTC,PLU-BTC,LUN-BTC,TAAS-BTC,NXC-BTC,EDG-BTC,RLC-BTC,SWT-BTC,TKN-BTC,WINGS-BTC,XAUR-BTC,AE-BTC,PTOY-BTC,ZEC-USD,XEM-USD,BCN-USD,XDN-USD,MAID-USD,ETC-BTC,ETC-USD,CFI-BTC,PLBT-BTC,BNT-BTC,FYN-ETH,SNM-BTC,SNM-ETH,SNT-ETH,CVC-USD,PAY-ETH,OAX-ETH,OMG-ETH,BQX-ETH,XTZ-BTC,DICE-BTC,CFI-ETH,PTOY-ETH,1ST-ETH,XAUR-ETH,TAAS-ETH,TIME-ETH,DICE-ETH,SWT-ETH,XMR-ETH,ETC-ETH,DASH-ETH,ZEC-ETH,PLU-ETH,GNO-ETH,XRP-BTC,NET-ETH,STRAT-USD,STRAT-BTC,SNC-ETH,ADX-ETH,BET-ETH,EOS-ETH,DENT-ETH,SAN-ETH,EOS-BTC,EOS-USD,MNE-BTC,MSP-ETH,DDF-ETH,XTZ-ETH,XTZ-USD,UET-ETH,MYB-ETH,SUR-ETH,IXT-ETH,PLR-ETH,TIX-ETH,NDC-ETH,PRO-ETH,AVT-ETH,COSS-ETH,EVX-USD,DLT-BTC,BNT-ETH,BNT-USD,QAU-BTC,QAU-ETH,MANA-USD,DNT-BTC,FYP-BTC,OPT-BTC,TNT-ETH,IFT-BTC,STX-BTC,STX-ETH,STX-USD,TNT-USD,TNT-BTC,CAT-BTC,CAT-ETH,CAT-USD,BCH-BTC,BCH-ETH,BCH-USD,ENG-ETH,XUC-USD,SNC-BTC,SNC-USD,OAX-USD,OAX-BTC,BAS-ETH,ZRX-BTC,ZRX-ETH,ZRX-USD,RVT-BTC,ICOS-BTC,ICOS-ETH,ICOS-USD,PPC-BTC,PPC-USD,QTUM-ETH,VERI-BTC,VERI-ETH,VERI-USD,IGNIS-ETH,PRG-BTC,PRG-ETH,PRG-USD,BMC-BTC,BMC-ETH,BMC-USD,CND-BTC,CND-ETH,CND-USD,SKIN-BTC,EMGO-BTC,EMGO-USD,CDT-ETH,CDT-USD,FUN-BTC,FUN-ETH,FUN-USD,HVN-BTC,HVN-ETH,FUEL-BTC,FUEL-ETH,FUEL-USD,POE-BTC,POE-ETH,MCAP-BTC,AIR-BTC,AIR-ETH,AIR-USD,AMB-USD,AMB-ETH,AMB-BTC,NTO-BTC,ICO-BTC,PING-BTC,GAME-BTC,TKR-ETH,HPC-BTC,PPT-ETH,MTH-BTC,MTH-ETH,WMGO-BTC,WMGO-USD,LRC-BTC,LRC-ETH,ICX-BTC,ICX-ETH,NEO-BTC,NEO-ETH,NEO-USD,CSNO-BTC,ORME-BTC,ICX-USD,PIX-BTC,PIX-ETH,IND-ETH,KICK-BTC,YOYOW-BTC,MIPS-BTC,CDT-BTC,XVG-BTC,XVG-ETH,XVG-USD,DGB-BTC,DGB-ETH,DGB-USD,DCN-BTC,DCN-ETH,DCN-USD,CCT-ETH,EBET-ETH,VIBE-BTC,VOISE-BTC,ENJ-BTC,ENJ-ETH,ENJ-USD,ZSC-BTC,ZSC-ETH,ZSC-USD,ETBS-BTC,TRX-BTC,TRX-ETH,TRX-USD,VEN-BTC,VEN-ETH,VEN-USD,ART-BTC,EVX-BTC,EVX-ETH,QVT-ETH,EBTCOLD-BTC,EBTCOLD-ETH,EBTCOLD-USD,BKB-BTC,EXN-BTC,TGT-BTC,ATS-ETH,BMT-BTC,BMT-ETH,SUB-BTC,SUB-ETH,SUB-USD,WTC-BTC,CNX-BTC,ATB-BTC,ATB-ETH,ATB-USD,ODN-BTC,BTM-BTC,BTM-ETH,BTM-USD,B2X-BTC,B2X-ETH,B2X-USD,ATM-BTC,ATM-ETH,ATM-USD,LIFE-BTC,VIB-BTC,VIB-ETH,VIB-USD,DRT-ETH,STU-USD,OMG-BTC,PAY-BTC,COSS-BTC,PPT-BTC,SNT-BTC,BTG-BTC,BTG-ETH,BTG-USD,SMART-BTC,SMART-ETH,SMART-USD,XUC-ETH,XUC-BTC,CL-BTC,CL-ETH,CL-USD,LA-ETH,CLD-BTC,CLD-ETH,CLD-USD,EDO-BTC,EDO-ETH,EDO-USD,HGT-ETH,POLL-BTC,IXT-BTC,ATS-BTC,SCL-BTC,ATL-BTC,EBTC-BTC,EBTC-ETH,EBTC-USD,ETP-BTC,ETP-ETH,ETP-USD,OTX-BTC,CDX-ETH,DRPU-BTC,NEBL-BTC,NEBL-ETH,HAC-BTC,CTX-BTC,CTX-ETH,ELE-BTC,ARN-BTC,ARN-ETH,STU-BTC,STU-ETH,GVT-ETH,INDI-BTC,BTX-BTC,LTC-ETH,BCN-ETH,MAID-ETH,NXT-ETH,STRAT-ETH,XDN-ETH,XEM-ETH,PLR-BTC,SUR-BTC,BQX-BTC,DOGE-ETH,ITS-BTC,AMM-BTC,AMM-ETH,AMM-USD,DBIX-BTC,PRE-BTC,KBR-BTC,TBT-BTC,ERO-BTC,SMS-BTC,SMS-ETH,SMS-USD,ZAP-BTC,DOV-BTC,DOV-ETH,DRPU-ETH,OTN-BTC,XRP-ETH,XRP-USD,HSR-BTC,LEND-BTC,LEND-ETH,SPF-BTC,SPF-ETH,SBTC-BTC,SBTC-ETH,WRC-BTC,WRC-ETH,WRC-USD,LOC-BTC,LOC-ETH,LOC-USD,SWFTC-BTC,SWFTC-ETH,SWFTC-USD,STAR-ETH,SBTC-USD,STORM-BTC,DIM-ETH,DIM-USD,DIM-BTC,NGC-BTC,NGC-ETH,NGC-USD,EMC-ETH,EMC-USD,MCO-BTC,MCO-ETH,MCO-USD,MANA-ETH,MANA-BTC,ECH-BTC,CPAY-ETH,DATA-BTC,DATA-ETH,DATA-USD,UTT-BTC,UTT-ETH,UTT-USD,KMD-BTC,KMD-ETH,KMD-USD,QTUM-USD,QTUM-BTC,SNT-USD,OMG-USD,EKO-BTC,EKO-ETH,ADX-BTC,ADX-USD,LSK-ETH,LSK-USD,PLR-USD,SUR-USD,BQX-USD,DRT-USD,REP-ETH,REP-USD,TIO-BTC,TIO-ETH,TIO-USD,WAX-BTC,WAX-ETH,WAX-USD,EET-BTC,EET-ETH,EET-USD,C20-BTC,C20-ETH,IDH-BTC,IDH-ETH,IPL-BTC,COV-BTC,COV-ETH,SENT-BTC,SENT-ETH,SENT-USD,SMT-BTC,SMT-ETH,SMT-USD,CAS-BTC,CAS-ETH,CAS-USD,CHAT-BTC,CHAT-ETH,CHAT-USD,GRMD-BTC,AVH-BTC,TRAC-ETH,JNT-ETH,PCL-BTC,PCL-ETH,CLOUT-BTC,UTK-BTC,UTK-ETH,UTK-USD,GNX-ETH,CHSB-BTC,CHSB-ETH,AVH-ETH,DAY-BTC,DAY-ETH,DAY-USD,NEU-BTC,NEU-ETH,NEU-USD,AVH-USD,CLOUT-ETH,CLOUT-USD,TAU-BTC,MEK-BTC,FLP-BTC,FLP-ETH,FLP-USD,R-BTC,R-ETH,EKO-USD,BCPT-ETH,BCPT-USD,PKT-BTC,PKT-ETH,WLK-BTC,WLK-ETH,WLK-USD,CPG-BTC,CPG-ETH,BPTN-BTC,BPTN-ETH,BPTN-USD,BETR-BTC,BETR-ETH,ARCT-BTC,ARCT-USD,DBET-BTC,DBET-ETH,DBET-USD,RNTB-ETH,HAND-ETH,HAND-USD,ACO-ETH,CTE-BTC,CTE-ETH,CTE-USD,CPY-BTC,CPY-ETH,CHP-ETH,BCPT-BTC,ACT-BTC,ACT-ETH,ACT-USD,HIRE-ETH,ADA-BTC,ADA-ETH,ADA-USD,SIG-BTC,RPM-BTC,RPM-ETH,MTX-BTC,MTX-ETH,MTX-USD,BGG-BTC,BGG-ETH,BGG-USD,SETH-ETH,WIZ-BTC,WIZ-ETH,WIZ-USD,DADI-BTC,DADI-ETH,BDG-ETH,DATX-BTC,DATX-ETH,TRUE-BTC,DRG-BTC,DRG-ETH,BANCA-BTC,BANCA-ETH,ZAP-ETH,ZAP-USD,AUTO-BTC,NOAH-BTC,SOC-BTC,WILD-BTC,INSUR-BTC,INSUR-ETH,OCN-BTC,OCN-ETH,STQ-BTC,STQ-ETH,XLM-BTC,XLM-ETH,XLM-USD,IOTA-BTC,IOTA-ETH,IOTA-USD,DRT-BTC,MLD-BTC,MLD-ETH,MLD-USD,BETR-USD,CGC-ETH,ERT-BTC,CRPT-BTC,CRPT-USD,MESH-BTC,MESH-ETH,MESH-USD,HLW-ETH,IHT-BTC,IHT-ETH,IHT-USD,SCC-BTC,YCC-BTC,DAN-BTC,TEL-BTC,TEL-ETH,BUBO-BTC,BUBO-ETH,BUBO-USD,VIT-BTC,VIT-ETH,VIT-USD,NCT-BTC,NCT-ETH,NCT-USD,AXP-BTC,AXP-ETH,BMH-BTC,BANCA-USD,NOAH-ETH,NOAH-USD,HQX-BTC,LDC-BTC,XMO-BTC,XMO-USD,XMO-ETH,BERRY-BTC,BERRY-ETH,BERRY-USD,BSTN-BTC,BSTN-ETH,BSTN-USD,GBX-BTC,GBX-ETH,GBX-USD,SHIP-BTC,SHIP-ETH,NANO-BTC,NANO-ETH,NANO-USD,LNC-BTC,UNC-BTC,UNC-ETH,RPX-BTC,RPX-ETH,RPX-USD,KIN-ETH,ARDR-USD,DAXT-BTC,DAXT-ETH,FOTA-ETH,FOTA-BTC,SETH-BTC,CVT-BTC,CVT-ETH,CVT-USD,STQ-USD,GNT-BTC,GNT-ETH,GNT-USD,ADH-BTC,ADH-ETH,BBC-BTC,BBC-ETH,GET-BTC,MITH-BTC,MITH-ETH,MITH-USD,SUNC-ETH,DADI-USD,TKY-BTC,ACAT-BTC,ACAT-ETH,ACAT-USD,BTX-USD,TCN-BTC,VIO-ETH,WIKI-BTC,WIKI-ETH,WIKI-USD,ONT-BTC,ONT-ETH,ONT-USD,CVCOIN-BTC,CVCOIN-ETH,CVCOIN-USD,FTX-BTC,FTX-ETH,FREC-BTC,NAVI-BTC,FREC-ETH,FREC-USD,VME-ETH,NAVI-ETH,BTCP-BTC,LND-ETH,CSM-BTC,NANJ-BTC,NTK-BTC,NTK-ETH,NTK-USD,AUC-BTC,AUC-ETH,CMCT-BTC,CMCT-ETH,CMCT-USD,MAN-BTC,MAN-ETH,MAN-USD,HIRE-BTC,TKA-BTC,TKA-ETH,TKA-USD,PNT-BTC,PNT-ETH,FXT-BTC,NEXO-BTC,CHX-BTC,CHX-ETH,CHX-USD,PAT-BTC,PAT-ETH,XMC-BTC,EJOY-BTC,EJOY-ETH,EJOY-USD,FXT-ETH,HERO-BTC,HERO-ETH,XMC-ETH,XMC-USD,STAK-BTC,STAK-ETH,FDZ-BTC,FDZ-ETH,FDZ-USD,SPD-BTC,SPD-ETH,LUC-BTC,MITX-BTC,TIV-BTC,B2G-BTC,B2G-USD,ZPT-BTC,ZPT-ETH,HBZ-BTC,FACE-BTC,FACE-ETH,HBZ-ETH,HBZ-USD,ZPT-USD,MORPH-BTC,MORPH-ETH,MORPH-USD,EBKC-BTC,CPT-BTC,PAT-USD,HTML-BTC,HTML-ETH,MITX-ETH,JOT-BTC,JBC-BTC,JBC-ETH,BTS-BTC,BNK-BTC,KBC-BTC,KBC-ETH,BNK-ETH,BNK-USD,TIV-ETH,TIV-USD,LUC-ETH,LUC-USD,CSM-ETH,CSM-USD,INK-BTC,SPC-BTC,IOST-BTC,INK-ETH,INK-USD,SPC-ETH,SPC-USD,CBC-BTC,IOST-USD,COIN-BTC,ZIL-BTC,COIN-USD,COIN-ETH,PMNT-BTC,ABYSS-BTC,ABYSS-ETH,ZIL-USD,BCI-BTC,CBC-ETH,CBC-USD,PITCH-BTC,PITCH-ETH,HTML-USD,TDS-BTC,TDS-ETH,TDS-USD,SBD-ETH,SBD-USD,DPN-BTC,UUU-BTC,UUU-ETH,XBP-BTC,KRM-USD,CLN-BTC,IVY-BTC,IVY-ETH,TTU-BTC,TTU-ETH,TTU-USD,CLN-ETH,DOR-BTC,DOR-ETH,DOR-USD,ELEC-BTC,ELEC-ETH,ELEC-USD,QNTU-BTC,QNTU-ETH,QNTU-USD,IPL-ETH,IPL-USD,CENNZ-BTC,BTCP-ETH,BTCP-USD,CENNZ-ETH,SWM-BTC,MXM-BTC,MXM-ETH,SPF-USD,LCC-BTC,HGT-BTC,BTC-DAI,ETH-DAI,MKR-DAI,EOS-DAI,USD-DAI,ETH-TUSD,BTC-TUSD,LTC-TUSD,XMR-TUSD,ZRX-TUSD,NEO-TUSD,BCH-TUSD,USD-TUSD,MKR-BTC,MKR-ETH,MKR-USD,TUSD-DAI,NEO-DAI,LTC-DAI,XMR-DAI,BCH-DAI,XRP-DAI,NEXO-ETH,NEXO-USD,DWS-BTC,DWS-ETH,DWS-USD,APPC-BTC,APPC-ETH,APPC-USD,BIT-ETH,DASH-EURS,ZEC-EURS,BTC-EURS,EOS-EURS,ETH-EURS,LTC-EURS,BCH-EURS,NEO-EURS,XMR-EURS,XRP-EURS,REX-BTC,REX-ETH,REX-USD,BCD-BTC,ELF-BTC,ELF-USD,BCD-USD,HQX-ETH,HQX-USD,EBKC-ETH,EBKC-USD,EDG-ETH,EDG-USD,COSM-BTC,COSM-ETH,DCNT-BTC,DCNT-ETH,DCNT-USD,EURS-USD,EURS-TUSD,EURS-DAI,ROX-ETH,ZPR-ETH,MNX-USD,MNX-BTC,MNX-ETH", "EnabledPairs": "BTC-USD", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -630,7 +666,43 @@ "APIKey": "Key", "APISecret": "Secret", "APIAuthPEMKey": "-----BEGIN EC PRIVATE KEY-----\nJUSTADUMMY\n-----END EC PRIVATE KEY-----\n", - "AvailablePairs": "BTC-USDT,BCH-USDT,ETH-USDT,ETC-USDT,LTC-USDT,EOS-USDT,XRP-USDT,OMG-USDT,DASH-USDT,ZEC-USDT,ADA-USDT,STEEM-USDT,IOTA-USDT,OCN-USDT,SOC-USDT,CTXC-USDT,ACT-USDT,BTM-USDT,BTS-USDT,ONT-USDT,IOST-USDT,HT-USDT,TRX-USDT,DTA-USDT,NEO-USDT,QTUM-USDT,SMT-USDT,ELA-USDT,VEN-USDT,THETA-USDT,SNT-USDT,ZIL-USDT,XEM-USDT,NAS-USDT,RUFF-USDT,HSR-USDT,LET-USDT,MDS-USDT,STORJ-USDT,ELF-USDT,ITC-USDT,CVC-USDT,GNT-USDT,XMR-BTC,BCH-BTC,ETH-BTC,LTC-BTC,ETC-BTC,EOS-BTC,OMG-BTC,XRP-BTC,DASH-BTC,ZEC-BTC,ADA-BTC,STEEM-BTC,IOTA-BTC,POLY-BTC,KAN-BTC,LBA-BTC,WAN-BTC,BFT-BTC,BTM-BTC,ONT-BTC,IOST-BTC,HT-BTC,TRX-BTC,SMT-BTC,ELA-BTC,WICC-BTC,OCN-BTC,ZLA-BTC,ABT-BTC,MTX-BTC,NAS-BTC,VEN-BTC,DTA-BTC,NEO-BTC,WAX-BTC,BTS-BTC,ZIL-BTC,THETA-BTC,CTXC-BTC,SRN-BTC,XEM-BTC,ICX-BTC,DGD-BTC,CHAT-BTC,WPR-BTC,LUN-BTC,SWFTC-BTC,SNT-BTC,MEET-BTC,YEE-BTC,ELF-BTC,LET-BTC,QTUM-BTC,LSK-BTC,ITC-BTC,SOC-BTC,QASH-BTC,MDS-BTC,EKO-BTC,TOPC-BTC,MTN-BTC,ACT-BTC,HSR-BTC,STK-BTC,STORJ-BTC,GNX-BTC,DBC-BTC,SNC-BTC,CMT-BTC,TNB-BTC,RUFF-BTC,QUN-BTC,ZRX-BTC,KNC-BTC,BLZ-BTC,PROPY-BTC,RPX-BTC,APPC-BTC,AIDOC-BTC,POWR-BTC,CVC-BTC,PAY-BTC,QSP-BTC,DAT-BTC,RDN-BTC,MCO-BTC,RCN-BTC,MANA-BTC,UTK-BTC,TNT-BTC,GAS-BTC,BAT-BTC,OST-BTC,LINK-BTC,GNT-BTC,MTL-BTC,EVX-BTC,REQ-BTC,ADX-BTC,AST-BTC,ENG-BTC,SALT-BTC,EDU-BTC,WTC-BTC,BIFI-BTC,BCX-BTC,BCD-BTC,SBTC-BTC,BTG-BTC,XMR-ETH,EOS-ETH,OMG-ETH,IOTA-ETH,ADA-ETH,STEEM-ETH,POLY-ETH,KAN-ETH,LBA-ETH,WAN-ETH,BFT-ETH,ZRX-ETH,AST-ETH,KNC-ETH,ONT-ETH,HT-ETH,BTM-ETH,IOST-ETH,SMT-ETH,ELA-ETH,TRX-ETH,ABT-ETH,NAS-ETH,OCN-ETH,WICC-ETH,ZIL-ETH,CTXC-ETH,ZLA-ETH,WPR-ETH,DTA-ETH,MTX-ETH,THETA-ETH,SRN-ETH,VEN-ETH,BTS-ETH,WAX-ETH,HSR-ETH,ICX-ETH,MTN-ETH,ACT-ETH,BLZ-ETH,QASH-ETH,RUFF-ETH,CMT-ETH,ELF-ETH,MEET-ETH,SOC-ETH,QTUM-ETH,ITC-ETH,SWFTC-ETH,YEE-ETH,LSK-ETH,LUN-ETH,LET-ETH,GNX-ETH,CHAT-ETH,EKO-ETH,TOPC-ETH,DGD-ETH,STK-ETH,MDS-ETH,DBC-ETH,SNC-ETH,PAY-ETH,QUN-ETH,AIDOC-ETH,TNB-ETH,APPC-ETH,RDN-ETH,UTK-ETH,POWR-ETH,BAT-ETH,PROPY-ETH,MANA-ETH,REQ-ETH,CVC-ETH,QSP-ETH,EVX-ETH,DAT-ETH,MCO-ETH,GNT-ETH,GAS-ETH,OST-ETH,LINK-ETH,RCN-ETH,TNT-ETH,ENG-ETH,SALT-ETH,ADX-ETH,EDU-ETH,WTC-ETH,XRP-HT,IOST-HT,DASH-HT,WICC-USDT,EOS-HT,BCH-HT,LTC-HT,ETC-HT,WAVES-BTC,WAVES-ETH,HB10-USDT,CMT-USDT,DCR-BTC,DCR-ETH,PAI-BTC,PAI-ETH", + "AvailablePairs": "BTC-USDT,BCH-USDT,ETH-USDT,ETC-USDT,LTC-USDT,EOS-USDT,XRP-USDT,OMG-USDT,DASH-USDT,ZEC-USDT,ADA-USDT,STEEM-USDT,IOTA-USDT,OCN-USDT,SOC-USDT,CTXC-USDT,ACT-USDT,BTM-USDT,BTS-USDT,ONT-USDT,IOST-USDT,HT-USDT,TRX-USDT,DTA-USDT,NEO-USDT,QTUM-USDT,SMT-USDT,ELA-USDT,VEN-USDT,THETA-USDT,SNT-USDT,ZIL-USDT,XEM-USDT,NAS-USDT,RUFF-USDT,HSR-USDT,LET-USDT,MDS-USDT,STORJ-USDT,ELF-USDT,ITC-USDT,CVC-USDT,GNT-USDT,XMR-BTC,BCH-BTC,ETH-BTC,LTC-BTC,ETC-BTC,EOS-BTC,OMG-BTC,XRP-BTC,DASH-BTC,ZEC-BTC,ADA-BTC,STEEM-BTC,IOTA-BTC,POLY-BTC,KAN-BTC,LBA-BTC,WAN-BTC,BFT-BTC,BTM-BTC,ONT-BTC,IOST-BTC,HT-BTC,TRX-BTC,SMT-BTC,ELA-BTC,WICC-BTC,OCN-BTC,ZLA-BTC,ABT-BTC,MTX-BTC,NAS-BTC,VEN-BTC,DTA-BTC,NEO-BTC,WAX-BTC,BTS-BTC,ZIL-BTC,THETA-BTC,CTXC-BTC,SRN-BTC,XEM-BTC,ICX-BTC,DGD-BTC,CHAT-BTC,WPR-BTC,LUN-BTC,SWFTC-BTC,SNT-BTC,MEET-BTC,YEE-BTC,ELF-BTC,LET-BTC,QTUM-BTC,LSK-BTC,ITC-BTC,SOC-BTC,QASH-BTC,MDS-BTC,EKO-BTC,TOPC-BTC,MTN-BTC,ACT-BTC,HSR-BTC,STK-BTC,STORJ-BTC,GNX-BTC,DBC-BTC,SNC-BTC,CMT-BTC,TNB-BTC,RUFF-BTC,QUN-BTC,ZRX-BTC,KNC-BTC,BLZ-BTC,PROPY-BTC,RPX-BTC,APPC-BTC,AIDOC-BTC,POWR-BTC,CVC-BTC,PAY-BTC,QSP-BTC,DAT-BTC,RDN-BTC,MCO-BTC,RCN-BTC,MANA-BTC,UTK-BTC,TNT-BTC,GAS-BTC,BAT-BTC,OST-BTC,LINK-BTC,GNT-BTC,MTL-BTC,EVX-BTC,REQ-BTC,ADX-BTC,AST-BTC,ENG-BTC,SALT-BTC,EDU-BTC,WTC-BTC,BIFI-BTC,BCX-BTC,BCD-BTC,SBTC-BTC,BTG-BTC,XMR-ETH,EOS-ETH,OMG-ETH,IOTA-ETH,ADA-ETH,STEEM-ETH,POLY-ETH,KAN-ETH,LBA-ETH,WAN-ETH,BFT-ETH,ZRX-ETH,AST-ETH,KNC-ETH,ONT-ETH,HT-ETH,BTM-ETH,IOST-ETH,SMT-ETH,ELA-ETH,TRX-ETH,ABT-ETH,NAS-ETH,OCN-ETH,WICC-ETH,ZIL-ETH,CTXC-ETH,ZLA-ETH,WPR-ETH,DTA-ETH,MTX-ETH,THETA-ETH,SRN-ETH,VEN-ETH,BTS-ETH,WAX-ETH,HSR-ETH,ICX-ETH,MTN-ETH,ACT-ETH,BLZ-ETH,QASH-ETH,RUFF-ETH,CMT-ETH,ELF-ETH,MEET-ETH,SOC-ETH,QTUM-ETH,ITC-ETH,SWFTC-ETH,YEE-ETH,LSK-ETH,LUN-ETH,LET-ETH,GNX-ETH,CHAT-ETH,EKO-ETH,TOPC-ETH,DGD-ETH,STK-ETH,MDS-ETH,DBC-ETH,SNC-ETH,PAY-ETH,QUN-ETH,AIDOC-ETH,TNB-ETH,APPC-ETH,RDN-ETH,UTK-ETH,POWR-ETH,BAT-ETH,PROPY-ETH,MANA-ETH,REQ-ETH,CVC-ETH,QSP-ETH,EVX-ETH,DAT-ETH,MCO-ETH,GNT-ETH,GAS-ETH,OST-ETH,LINK-ETH,RCN-ETH,TNT-ETH,ENG-ETH,SALT-ETH,ADX-ETH,EDU-ETH,WTC-ETH,XRP-HT,IOST-HT,DASH-HT,WICC-USDT,EOS-HT,BCH-HT,LTC-HT,ETC-HT,WAVES-BTC,WAVES-ETH,HB10-USDT,CMT-USDT,DCR-BTC,DCR-ETH,PAI-BTC,PAI-ETH,BOX-BTC,BOX-ETH,DGB-BTC,DGB-ETH,GXS-BTC,GXS-ETH,XLM-BTC,XLM-ETH,BIX-BTC,BIX-ETH,BIX-USDT", + "EnabledPairs": "BTC-USDT", + "BaseCurrencies": "USD", + "AssetTypes": "SPOT", + "SupportsAutoPairUpdates": true, + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "-" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false + }, + "BankAccounts": [ + { + "BankName": "", + "BankAddress": "", + "AccountName": "", + "AccountNumber": "", + "SWIFTCode": "", + "IBAN": "", + "SupportedCurrencies": "" + } + ] + }, + { + "Name": "HuobiHadax", + "Enabled": true, + "Verbose": false, + "Websocket": false, + "UseSandbox": false, + "RESTPollingDelay": 10, + "HTTPTimeout": 15000000000, + "AuthenticatedAPISupport": false, + "APIKey": "Key", + "APISecret": "Secret", + "APIAuthPEMKey": "-----BEGIN EC PRIVATE KEY-----\nJUSTADUMMY\n-----END EC PRIVATE KEY-----\n", + "AvailablePairs": "BTC-USDT,BCH-USDT,ETH-USDT,ETC-USDT,LTC-USDT,EOS-USDT,XRP-USDT,OMG-USDT,DASH-USDT,ZEC-USDT,ADA-USDT,STEEM-USDT,IOTA-USDT,OCN-USDT,SOC-USDT,CTXC-USDT,ACT-USDT,BTM-USDT,BTS-USDT,ONT-USDT,IOST-USDT,HT-USDT,TRX-USDT,DTA-USDT,NEO-USDT,QTUM-USDT,SMT-USDT,ELA-USDT,VEN-USDT,THETA-USDT,SNT-USDT,ZIL-USDT,XEM-USDT,NAS-USDT,RUFF-USDT,HSR-USDT,LET-USDT,MDS-USDT,STORJ-USDT,ELF-USDT,ITC-USDT,CVC-USDT,GNT-USDT,XMR-BTC,BCH-BTC,ETH-BTC,LTC-BTC,ETC-BTC,EOS-BTC,OMG-BTC,XRP-BTC,DASH-BTC,ZEC-BTC,ADA-BTC,STEEM-BTC,IOTA-BTC,POLY-BTC,KAN-BTC,LBA-BTC,WAN-BTC,BFT-BTC,BTM-BTC,ONT-BTC,IOST-BTC,HT-BTC,TRX-BTC,SMT-BTC,ELA-BTC,WICC-BTC,OCN-BTC,ZLA-BTC,ABT-BTC,MTX-BTC,NAS-BTC,VEN-BTC,DTA-BTC,NEO-BTC,WAX-BTC,BTS-BTC,ZIL-BTC,THETA-BTC,CTXC-BTC,SRN-BTC,XEM-BTC,ICX-BTC,DGD-BTC,CHAT-BTC,WPR-BTC,LUN-BTC,SWFTC-BTC,SNT-BTC,MEET-BTC,YEE-BTC,ELF-BTC,LET-BTC,QTUM-BTC,LSK-BTC,ITC-BTC,SOC-BTC,QASH-BTC,MDS-BTC,EKO-BTC,TOPC-BTC,MTN-BTC,ACT-BTC,HSR-BTC,STK-BTC,STORJ-BTC,GNX-BTC,DBC-BTC,SNC-BTC,CMT-BTC,TNB-BTC,RUFF-BTC,QUN-BTC,ZRX-BTC,KNC-BTC,BLZ-BTC,PROPY-BTC,RPX-BTC,APPC-BTC,AIDOC-BTC,POWR-BTC,CVC-BTC,PAY-BTC,QSP-BTC,DAT-BTC,RDN-BTC,MCO-BTC,RCN-BTC,MANA-BTC,UTK-BTC,TNT-BTC,GAS-BTC,BAT-BTC,OST-BTC,LINK-BTC,GNT-BTC,MTL-BTC,EVX-BTC,REQ-BTC,ADX-BTC,AST-BTC,ENG-BTC,SALT-BTC,EDU-BTC,WTC-BTC,BIFI-BTC,BCX-BTC,BCD-BTC,SBTC-BTC,BTG-BTC,XMR-ETH,EOS-ETH,OMG-ETH,IOTA-ETH,ADA-ETH,STEEM-ETH,POLY-ETH,KAN-ETH,LBA-ETH,WAN-ETH,BFT-ETH,ZRX-ETH,AST-ETH,KNC-ETH,ONT-ETH,HT-ETH,BTM-ETH,IOST-ETH,SMT-ETH,ELA-ETH,TRX-ETH,ABT-ETH,NAS-ETH,OCN-ETH,WICC-ETH,ZIL-ETH,CTXC-ETH,ZLA-ETH,WPR-ETH,DTA-ETH,MTX-ETH,THETA-ETH,SRN-ETH,VEN-ETH,BTS-ETH,WAX-ETH,HSR-ETH,ICX-ETH,MTN-ETH,ACT-ETH,BLZ-ETH,QASH-ETH,RUFF-ETH,CMT-ETH,ELF-ETH,MEET-ETH,SOC-ETH,QTUM-ETH,ITC-ETH,SWFTC-ETH,YEE-ETH,LSK-ETH,LUN-ETH,LET-ETH,GNX-ETH,CHAT-ETH,EKO-ETH,TOPC-ETH,DGD-ETH,STK-ETH,MDS-ETH,DBC-ETH,SNC-ETH,PAY-ETH,QUN-ETH,AIDOC-ETH,TNB-ETH,APPC-ETH,RDN-ETH,UTK-ETH,POWR-ETH,BAT-ETH,PROPY-ETH,MANA-ETH,REQ-ETH,CVC-ETH,QSP-ETH,EVX-ETH,DAT-ETH,MCO-ETH,GNT-ETH,GAS-ETH,OST-ETH,LINK-ETH,RCN-ETH,TNT-ETH,ENG-ETH,SALT-ETH,ADX-ETH,EDU-ETH,WTC-ETH,XRP-HT,IOST-HT,DASH-HT,WICC-USDT,EOS-HT,BCH-HT,LTC-HT,ETC-HT,WAVES-BTC,WAVES-ETH,HB10-USDT,CMT-USDT,DCR-BTC,DCR-ETH,PAI-BTC,PAI-ETH,BOX-BTC,BOX-ETH,DGB-BTC,DGB-ETH,GXS-BTC,GXS-ETH,XLM-BTC,XLM-ETH,BIX-BTC,BIX-ETH,BIX-USDT", "EnabledPairs": "BTC-USDT", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -737,7 +809,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "NZDUSD,USDCAD,ETHBTC,BACETH,BTCAUD,BCHBTC,BTCSGD,USDHKD,AUDUSD,BTCCAD,USDCHF,USDSGD,BTCEUR,BTCNGN,BTCCHF,GBPUSD,USDNGN,BTCHKD,EURUSD,XRPBTC,BTCUSD,USDJPY,LTCBTC,BTCGBP,BTCJPY,BTCNZD", + "AvailablePairs": "USDHKD,USDCAD,BTCEUR,EURUSD,XRPBTC,ETHBTC,BTCCAD,BCHBTC,BTCJPY,USDCHF,LTCBTC,BTCSGD,BTCNGN,BTCGBP,NZDUSD,USDJPY,BTCNZD,USDSGD,BACETH,BTCUSD,BTCAUD,GBPUSD,BTCCHF,AUDUSD,USDNGN", "EnabledPairs": "BTCUSD,BTCAUD", "BaseCurrencies": "USD,EUR,HKD,AUD,GBP,NZD,JPY,SGD,NGN,CHF,CAD", "AssetTypes": "SPOT", @@ -771,7 +843,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "WAVES_ETH,MYST_USDT,SNM_USDT,LDC_USDT,TAAS_ETH,DGD_ETH,ZRX_ETH,AE_ETH,TRX_ETH,BNT_USDT,STORJ_USDT,OMG_BTC,TNT_ETH,XID_ETH,LDC_ETH,STORJ_BTC,IND_USDT,TRX_BTC,ICN_ETH,REP_USDT,REN_ETH,MANA_BTC,BMC_USDT,SNT_USDT,BCC_USDT,WPR_BTC,ENJ_USDT,GNO_BTC,STORJ_ETH,PAY_BTC,WPR_ETH,DNT_BTC,EOS_ETH,LDC_BTC,EOS_USDT,CVC_BTC,NET_USDT,MANA_ETH,IND_ETH,SRN_USDT,GNO_ETH,VEN_ETH,KNC_ETH,NET_BTC,DGD_BTC,MLN_USDT,REP_ETH,GNT_ETH,LTC_ETH,GUP_USDT,TAAS_BTC,ADX_ETH,ICN_USDT,NET_ETH,VEN_BTC,IND_BTC,AION_BTC,TIME_ETH,DASH_USDT,RLC_ETH,SAN_ETH,MGO_USDT,PTOY_USDT,SAN_BTC,BCC_BTC,DASH_ETH,LTC_USDT,MYST_BTC,MLN_ETH,TKN_ETH,MGO_BTC,SNGLS_USDT,MCO_ETH,OMG_ETH,GNT_BTC,GNT_USDT,WINGS_USDT,PRO_USDT,REQ_BTC,WINGS_BTC,BCC_ETH,MGO_ETH,STX_ETH,ENG_BTC,INS_ETH,LTC_BTC,QRL_BTC,OAX_USDT,STX_USDT,WAVES_BTC,BNT_ETH,AE_BTC,AST_ETH,INS_USDT,RLC_BTC,TKN_BTC,SNGLS_ETH,PAY_USDT,TNT_BTC,DASH_BTC,SNGLS_BTC,SNT_BTC,AE_USDT,REQ_ETH,AGI_BTC,BNT_BTC,PTOY_BTC,NEU_ETH,ADX_USDT,TRX_USDT,AION_ETH,CLN_ETH,KNC_BTC,NEU_BTC,REN_BTC,BAT_BTC,MYST_ETH,CVC_ETH,SALT_USDT,INS_BTC,AION_USDT,TKN_USDT,BAT_ETH,CFI_USDT,ZRX_BTC,TNT_USDT,SALT_BTC,DNT_ETH,ICN_BTC,SNM_ETH,PRO_ETH,TRST_ETH,PAY_ETH,PRO_BTC,CLN_USDT,EDG_USDT,GUP_BTC,ADX_BTC,RLC_USDT,WINGS_ETH,CFI_ETH,QRL_ETH,ANT_ETH,AGI_ETH,ENG_USDT,ETH_BTC,EDG_ETH,GNO_USDT,MCO_USDT,EOS_BTC,MLN_BTC,TIME_BTC,SNM_BTC,VEN_USDT,REQ_USDT,TAAS_USDT,TIME_USDT,OMG_USDT,CVC_USDT,SRN_BTC,ETH_USDT,REN_USDT,GUP_ETH,PTOY_ETH,CFI_BTC,ENJ_BTC,XID_USDT,AGI_USDT,MCO_BTC,ANT_BTC,DGD_USDT,OAX_BTC,BAT_USDT,QRL_USDT,STX_BTC,ENG_ETH,ENJ_ETH,WAVES_USDT,BMC_ETH,AST_USDT,EDG_BTC,SAN_USDT,NEU_USDT,TRST_BTC,MANA_USDT,ANT_USDT,WPR_USDT,SNT_ETH,OAX_ETH,KNC_USDT,BTC_USDT,XID_BTC,DNT_USDT,ZRX_USDT,BMC_BTC,SRN_ETH,CLN_BTC,REP_BTC,TRST_USDT,SALT_ETH,AST_BTC", + "AvailablePairs": "WAVES_USDT,REP_BTC,GNO_BTC,HOT_BTC,ENG_ETH,CLN_ETH,IND_ETH,WINGS_USDT,SNM_USDT,AE_ETH,WPR_ETH,RLC_USDT,AGI_ETH,TNT_ETH,AGI_BTC,NET_BTC,BCC_USDT,ENJ_USDT,SNGLS_ETH,STX_ETH,ZRX_ETH,DASH_BTC,CFI_USDT,NEU_USDT,BNT_USDT,CFI_ETH,ENG_BTC,AST_USDT,ICN_ETH,SNGLS_USDT,WPR_USDT,WAVES_BTC,ANT_ETH,BAT_USDT,BMC_BTC,AST_BTC,KNC_USDT,IND_USDT,TRX_USDT,INS_ETH,CLN_USDT,DASH_USDT,GUP_USDT,BNT_ETH,INS_BTC,TKN_BTC,SNT_ETH,DGD_USDT,ETH_BTC,GNO_USDT,MANA_BTC,TRX_ETH,REQ_ETH,REN_ETH,ICN_BTC,ADX_BTC,AE_BTC,TNT_BTC,AE_USDT,BMC_USDT,TTU_ETH,LTC_USDT,BCC_ETH,DNT_BTC,OMG_USDT,SALT_ETH,QRL_USDT,PTOY_USDT,LDC_ETH,BAT_BTC,SALT_USDT,GUP_ETH,SNGLS_BTC,SNM_ETH,PAY_BTC,TRST_ETH,BNT_BTC,MGO_BTC,STX_BTC,STX_USDT,AGI_USDT,TKN_ETH,STORJ_ETH,TIME_ETH,GUP_BTC,MCO_USDT,SAN_USDT,LDC_USDT,DGD_ETH,AION_BTC,REP_ETH,REP_USDT,RLC_BTC,TRST_BTC,PRO_USDT,MLN_USDT,QRL_ETH,BAT_ETH,MYST_ETH,PTOY_BTC,DGD_BTC,ICN_USDT,XID_BTC,SRN_BTC,XID_ETH,OAX_USDT,EDG_ETH,GNO_ETH,XID_USDT,ZRX_BTC,TIME_USDT,TAAS_USDT,ADX_ETH,PAY_USDT,NET_ETH,BCC_BTC,TRX_BTC,SRN_ETH,STORJ_USDT,TNT_USDT,DNT_ETH,REQ_USDT,NEU_BTC,AION_ETH,REN_BTC,ETH_USDT,SALT_BTC,EDG_USDT,QRL_BTC,MCO_BTC,MANA_USDT,BTC_USDT,TAAS_ETH,PTOY_ETH,TIME_BTC,CVC_USDT,CLN_BTC,DASH_ETH,MLN_ETH,PAY_ETH,PRO_BTC,HOT_ETH,OMG_BTC,GNT_BTC,ANT_BTC,MGO_ETH,TTU_USDT,WINGS_ETH,TAAS_BTC,SAN_ETH,KNC_ETH,WPR_BTC,LDC_BTC,ENJ_BTC,MYST_BTC,MCO_ETH,DNT_USDT,ENJ_ETH,GNT_ETH,RLC_ETH,TRST_USDT,SNT_USDT,AST_ETH,TTU_BTC,MGO_USDT,STORJ_BTC,SAN_BTC,BMC_ETH,ENG_USDT,NEU_ETH,HOT_USDT,TKN_USDT,MYST_USDT,CVC_BTC,WAVES_ETH,SNT_BTC,ADX_USDT,INS_USDT,AION_USDT,LTC_BTC,GNT_USDT,OAX_BTC,KNC_BTC,SRN_USDT,SNM_BTC,ZRX_USDT,MLN_BTC,CFI_BTC,NET_USDT,OAX_ETH,MANA_ETH,CVC_ETH,IND_BTC,LTC_ETH,EDG_BTC,PRO_ETH,WINGS_BTC,ANT_USDT,REQ_BTC,OMG_ETH,REN_USDT", "EnabledPairs": "ETH_BTC,LTC_BTC,DASH_BTC", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -952,7 +1024,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BTC_SYS,BTC_XVC,USDT_BTC,USDT_NXT,XMR_BTCD,BTC_SBD,BTC_DGB,BTC_NMC,ETH_ETC,ETH_OMG,ETH_BCH,BTC_XEM,BTC_XRP,BTC_GRC,USDT_ETC,BTC_REP,BTC_PASC,BTC_STORJ,BTC_BTM,BTC_FLO,BTC_XBC,XMR_BLK,USDT_ETH,ETH_LSK,ETH_GAS,BTC_BURST,BTC_VTC,BTC_OMNI,BTC_NXT,BTC_XMR,USDT_XRP,XMR_MAID,ETH_STEEM,BTC_BCN,BTC_FLDC,ETH_ZRX,BTC_ARDR,BTC_ZEC,USDT_LTC,ETH_GNT,BTC_XCP,XMR_DASH,BTC_BCY,BTC_STRAT,BTC_ZRX,BTC_CVC,BTC_BTCD,BTC_HUC,ETH_CVC,BTC_SC,BTC_GAME,XMR_LTC,BTC_LTC,BTC_XPM,BTC_OMG,BTC_CLAM,BTC_EMC2,USDT_XMR,BTC_FCT,BTC_LBC,ETH_ZEC,BTC_NEOS,USDT_DASH,BTC_NAV,XMR_NXT,BTC_BLK,BTC_DASH,USDT_ZEC,BTC_GNO,ETH_GNO,USDT_BCH,BTC_MAID,BTC_STR,BTC_ETH,BTC_LSK,BTC_STEEM,BTC_GNT,BTC_PPC,BTC_RIC,XMR_BCN,BTC_RADS,BTC_NXC,BTC_BTS,BTC_PINK,BTC_VIA,XMR_ZEC,BTC_VRC,USDT_STR,BTC_EXP,BTC_AMP,BTC_DCR,BTC_ETC,BTC_DOGE,BTC_POT,BTC_BCH,BTC_GAS,USDT_REP,ETH_REP", + "AvailablePairs": "USDT_STR,USDT_ETH,BTC_GNO,BTC_EOS,BTC_BLK,BTC_NXT,USDT_LTC,XMR_MAID,BTC_BURST,BTC_XVC,BTC_XEM,XMR_NXT,BTC_ETH,BTC_EXP,BTC_RADS,ETH_ETC,BTC_DOGE,BTC_HUC,USDT_ZEC,ETH_CVC,BTC_ARDR,ETH_ZEC,BTC_REP,BTC_FLDC,BTC_OMNI,BTC_VIA,ETH_STEEM,BTC_ETC,BTC_NXC,BTC_BCH,BTC_CLAM,BTC_SYS,XMR_BCN,BTC_LTC,BTC_RIC,BTC_LSK,BTC_STEEM,BTC_POT,BTC_XCP,BTC_XBC,BTC_BCY,USDT_REP,BTC_ZRX,BTC_GAS,BTC_DASH,BTC_EMC2,BTC_NAV,BTC_NEOS,BTC_AMP,ETH_BCH,BTC_STORJ,BTC_FLO,BTC_GAME,BTC_MAID,BTC_PINK,BTC_XMR,BTC_BTM,BTC_BTS,BTC_XRP,XMR_BTCD,USDT_ETC,ETH_GNT,BTC_DGB,BTC_VTC,BTC_LBC,ETH_EOS,USDT_EOS,BTC_BCN,XMR_DASH,USDT_BCH,ETH_OMG,BTC_XPM,BTC_SBD,XMR_LTC,BTC_SC,ETH_REP,ETH_ZRX,BTC_VRC,USDT_NXT,BTC_PPC,BTC_STR,USDT_BTC,USDT_DASH,USDT_XRP,ETH_LSK,BTC_BTCD,BTC_NMC,BTC_STRAT,BTC_PASC,BTC_GNT,ETH_GNO,BTC_CVC,BTC_ZEC,XMR_ZEC,XMR_BLK,BTC_FCT,BTC_DCR,BTC_OMG,ETH_GAS,BTC_GRC,USDT_XMR", "EnabledPairs": "BTC_LTC,BTC_ETH,BTC_DOGE,BTC_DASH,BTC_XRP", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -1051,6 +1123,42 @@ "SupportedCurrencies": "" } ] + }, + { + "Name": "ZB", + "Enabled": true, + "Verbose": false, + "Websocket": false, + "UseSandbox": false, + "RESTPollingDelay": 10, + "HTTPTimeout": 15000000000, + "AuthenticatedAPISupport": false, + "APIKey": "Key", + "APISecret": "Secret", + "AvailablePairs": "MITH_QC,FUN_BTC,ICX_BTC,ZB_QC,UBTC_USDT,BTC_USDT,ICX_QC,OMG_USDT,ENT_USDT,AAA_QC,QUN_BTC,TV_BTC,XLM_USDT,BCD_USDT,TOPC_QC,BCW_QC,SUB_BTC,AE_BTC,SNT_USDT,LBTC_USDT,XUC_QC,XEM_USDT,TRUE_QC,HSR_BTC,HOTC_USDT,DASH_QC,NEO_QC,DOGE_USDT,OMG_QC,XWC_USDT,EOSDAC_USDT,KAN_BTC,BCC_QC,BTN_QC,GNT_QC,BAT_QC,GNT_BTC,FUN_QC,BCD_QC,XLM_BTC,CDC_USDT,ETH_ZB,KAN_QC,RCN_QC,MITH_BTC,MCO_QC,LTC_ZB,EOS_QC,SUB_QC,QTUM_ZB,DDM_USDT,SAFE_USDT,EDO_USDT,ZRX_BTC,LTC_BTC,QTUM_BTC,HSR_USDT,GRAM_USDT,TV_QC,TRUE_BTC,SAFE_QC,ZB_BTC,ETH_USDT,CDC_QC,BAT_BTC,DOGE_QC,HSR_ZB,BCD_BTC,TOPC_USDT,XLM_QC,ETC_ZB,SNT_BTC,ETH_QC,DASH_BTC,NEO_USDT,DOGE_BTC,UBTC_QC,BTP_QC,BCC_ZB,HLC_QC,QTUM_QC,LTC_QC,KNC_QC,RCN_BTC,HLC_BTC,DASH_USDT,HPY_BTC,MTL_USDT,LBTC_QC,MTL_BTC,ADA_USDT,LBTC_BTC,HOTC_QC,BITE_BTC,ADA_BTC,SBTC_QC,SUB_USDT,SAFE_BTC,ETC_BTC,BTH_USDT,MITH_USDT,ICX_USDT,SBTC_BTC,DASH_ZB,BCC_USDT,XRP_ZB,EOS_ZB,HPY_QC,MTL_QC,XWC_BTC,BTH_BTC,CHAT_USDT,QTUM_USDT,BAT_USDT,USDT_QC,BTS_BTC,XUC_BTC,KNC_USDT,BTC_QC,KNC_BTC,CHAT_QC,BCX_USDT,BTS_ZB,BITCNY_QC,1ST_BTC,MANA_QC,RCN_USDT,ENT_QC,BDS_BTC,PDX_QC,INK_QC,XEM_QC,BTN_USDT,UBTC_BTC,XWC_QC,QUN_USDT,SNT_QC,EPC_QC,BCW_BTC,NEO_BTC,AE_QC,XEM_BTC,XRP_USDT,OMG_BTC,HLC_USDT,SBTC_USDT,GNT_USDT,CHAT_BTC,ETC_USDT,SLT_BTC,SLT_QC,GRAM_QC,BTM_QC,INK_USDT,MANA_USDT,AE_USDT,SLT_USDT,QUN_QC,FUN_USDT,BCW_USDT,ZRX_USDT,TV_USDT,EDO_QC,XRP_BTC,BTM_BTC,BTP_BTC,BCX_BTC,TRUE_USDT,EOSDAC_BTC,LTC_USDT,BDS_QC,EOS_BTC,1ST_USDT,ZB_USDT,BTN_BTC,BTM_USDT,ETC_QC,HSR_QC,MCO_BTC,HPY_USDT,TOPC_BTC,ENT_BTC,MCO_USDT,BCX_QC,DDM_QC,KAN_USDT,BTS_QC,MANA_BTC,XRP_QC,ETH_BTC,EPC_BTC,BCC_BTC,ZRX_QC,DDM_BTC,EOS_USDT,GRAM_BTC,CDC_BTC,HOTC_BTC,EDO_BTC,1ST_QC,INK_BTC,ADA_QC,BTS_USDT,BTP_USDT,BTH_QC,EOSDAC_QC", + "EnabledPairs": "BTC_USDT,ETH_USDT", + "BaseCurrencies": "USD", + "AssetTypes": "SPOT", + "SupportsAutoPairUpdates": true, + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + }, + "BankAccounts": [ + { + "BankName": "", + "BankAddress": "", + "AccountName": "", + "AccountNumber": "", + "SWIFTCode": "", + "IBAN": "", + "SupportedCurrencies": "" + } + ] } ], "BankAccounts": [ diff --git a/exchange.go b/exchange.go index 4449c9ec..41a5b00a 100644 --- a/exchange.go +++ b/exchange.go @@ -19,9 +19,11 @@ import ( "github.com/thrasher-/gocryptotrader/exchanges/coinbasepro" "github.com/thrasher-/gocryptotrader/exchanges/coinut" "github.com/thrasher-/gocryptotrader/exchanges/exmo" + "github.com/thrasher-/gocryptotrader/exchanges/gateio" "github.com/thrasher-/gocryptotrader/exchanges/gemini" "github.com/thrasher-/gocryptotrader/exchanges/hitbtc" "github.com/thrasher-/gocryptotrader/exchanges/huobi" + "github.com/thrasher-/gocryptotrader/exchanges/huobihadax" "github.com/thrasher-/gocryptotrader/exchanges/itbit" "github.com/thrasher-/gocryptotrader/exchanges/kraken" "github.com/thrasher-/gocryptotrader/exchanges/lakebtc" @@ -32,6 +34,7 @@ import ( "github.com/thrasher-/gocryptotrader/exchanges/poloniex" "github.com/thrasher-/gocryptotrader/exchanges/wex" "github.com/thrasher-/gocryptotrader/exchanges/yobit" + "github.com/thrasher-/gocryptotrader/exchanges/zb" ) // vars related to exchange functions @@ -156,12 +159,16 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error { exch = new(exmo.EXMO) case "coinbasepro": exch = new(coinbasepro.CoinbasePro) + case "gateio": + exch = new(gateio.Gateio) case "gemini": exch = new(gemini.Gemini) case "hitbtc": exch = new(hitbtc.HitBTC) case "huobi": exch = new(huobi.HUOBI) + case "huobihadax": + exch = new(huobihadax.HUOBIHADAX) case "itbit": exch = new(itbit.ItBit) case "kraken": @@ -184,6 +191,8 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error { exch = new(wex.WEX) case "yobit": exch = new(yobit.Yobit) + case "zb": + exch = new(zb.ZB) default: return ErrExchangeNotFound } diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go index f49ebc0a..68e6cb83 100644 --- a/exchanges/binance/binance.go +++ b/exchanges/binance/binance.go @@ -23,8 +23,8 @@ type Binance struct { WebsocketConn *websocket.Conn // valid string list that a required by the exchange - validLimits []string - validIntervals []string + validLimits []int + validIntervals []TimeInterval } const ( @@ -45,7 +45,10 @@ const ( // Authenticated endpoints newOrderTest = "/api/v3/order/test" newOrder = "/api/v3/order" + cancelOrder = "/api/v3/order" queryOrder = "/api/v3/order" + openOrders = "/api/v3/openOrders" + allOrders = "/api/v3/allOrders" // binance authenticated and unauthenticated limit rates // to-do @@ -130,21 +133,22 @@ func (b *Binance) GetExchangeInfo() (ExchangeInfo, error) { // GetOrderBook returns full orderbook information // +// OrderBookDataRequestParams contains the following members // symbol: string of currency pair // limit: returned limit amount -func (b *Binance) GetOrderBook(symbol string, limit int64) (OrderBook, error) { +func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error) { orderbook, resp := OrderBook{}, OrderBookData{} - if err := b.CheckLimit(limit); err != nil { + if err := b.CheckLimit(obd.Limit); err != nil { return orderbook, err } - if err := b.CheckSymbol(symbol); err != nil { + if err := b.CheckSymbol(obd.Symbol); err != nil { return orderbook, err } params := url.Values{} - params.Set("symbol", common.StringToUpper(symbol)) - params.Set("limit", strconv.FormatInt(limit, 10)) + params.Set("symbol", common.StringToUpper(obd.Symbol)) + params.Set("limit", fmt.Sprintf("%d", obd.Limit)) path := fmt.Sprintf("%s%s?%s", apiURL, orderBookDepth, params.Encode()) @@ -189,22 +193,13 @@ func (b *Binance) GetOrderBook(symbol string, limit int64) (OrderBook, error) { } // GetRecentTrades returns recent trade activity -// -// symbol: string of currency pair -// limit: returned limit amount WARNING: MAX 500! -func (b *Binance) GetRecentTrades(symbol string, limit int64) ([]RecentTrade, error) { +// limit: Up to 500 results returned +func (b *Binance) GetRecentTrades(rtr RecentTradeRequestParams) ([]RecentTrade, error) { resp := []RecentTrade{} - if err := b.CheckLimit(limit); err != nil { - return resp, err - } - if err := b.CheckSymbol(symbol); err != nil { - return resp, err - } - params := url.Values{} - params.Set("symbol", common.StringToUpper(symbol)) - params.Set("limit", strconv.FormatInt(limit, 10)) + params.Set("symbol", common.StringToUpper(rtr.Symbol)) + params.Set("limit", fmt.Sprintf("%d", rtr.Limit)) path := fmt.Sprintf("%s%s?%s", apiURL, recentTrades, params.Encode()) @@ -214,21 +209,18 @@ func (b *Binance) GetRecentTrades(symbol string, limit int64) ([]RecentTrade, er // GetHistoricalTrades returns historical trade activity // // symbol: string of currency pair -// limit: returned limit amount WARNING: MAX 500! (NOT REQUIRED) +// limit: Optional. Default 500; max 1000. // fromID: -func (b *Binance) GetHistoricalTrades(symbol string, limit, fromID int64) ([]HistoricalTrade, error) { +func (b *Binance) GetHistoricalTrades(symbol string, limit int, fromID int64) ([]HistoricalTrade, error) { resp := []HistoricalTrade{} if err := b.CheckLimit(limit); err != nil { return resp, err } - if err := b.CheckSymbol(symbol); err != nil { - return resp, err - } params := url.Values{} params.Set("symbol", common.StringToUpper(symbol)) - params.Set("limit", strconv.FormatInt(limit, 10)) + params.Set("limit", strconv.Itoa(limit)) params.Set("fromid", strconv.FormatInt(fromID, 10)) path := fmt.Sprintf("%s%s?%s", apiURL, historicalTrades, params.Encode()) @@ -239,8 +231,8 @@ func (b *Binance) GetHistoricalTrades(symbol string, limit, fromID int64) ([]His // GetAggregatedTrades returns aggregated trade activity // // symbol: string of currency pair -// limit: returned limit amount WARNING: MAX 500! -func (b *Binance) GetAggregatedTrades(symbol string, limit int64) ([]AggregatedTrade, error) { +// limit: Optional. Default 500; max 1000. +func (b *Binance) GetAggregatedTrades(symbol string, limit int) ([]AggregatedTrade, error) { resp := []AggregatedTrade{} if err := b.CheckLimit(limit); err != nil { @@ -252,36 +244,37 @@ func (b *Binance) GetAggregatedTrades(symbol string, limit int64) ([]AggregatedT params := url.Values{} params.Set("symbol", common.StringToUpper(symbol)) - params.Set("limit", strconv.FormatInt(limit, 10)) + params.Set("limit", strconv.Itoa(limit)) path := fmt.Sprintf("%s%s?%s", apiURL, aggregatedTrades, params.Encode()) return resp, b.SendHTTPRequest(path, &resp) } -// GetCandleStickData returns candle stick data +// GetSpotKline returns kline data // -// symbol: -// limit: -// interval -func (b *Binance) GetCandleStickData(symbol, interval string, limit int64) ([]CandleStick, error) { +// KlinesRequestParams supports 5 parameters +// symbol: the symbol to get the kline data for +// limit: optinal +// interval: the interval time for the data +// startTime: startTime filter for kline data +// endTime: endTime filter for the kline data +func (b *Binance) GetSpotKline(arg KlinesRequestParams) ([]CandleStick, error) { var resp interface{} var kline []CandleStick - if err := b.CheckLimit(limit); err != nil { - return kline, err - } - if err := b.CheckSymbol(symbol); err != nil { - return kline, err - } - if err := b.CheckIntervals(interval); err != nil { - return kline, err - } - params := url.Values{} - params.Set("symbol", common.StringToUpper(symbol)) - params.Set("limit", strconv.FormatInt(limit, 10)) - params.Set("interval", interval) + params.Set("symbol", arg.Symbol) + params.Set("interval", string(arg.Interval)) + if arg.Limit != 0 { + params.Set("limit", strconv.Itoa(arg.Limit)) + } + if arg.StartTime != 0 { + params.Set("startTime", strconv.FormatInt(arg.StartTime, 10)) + } + if arg.EndTime != 0 { + params.Set("endTime", strconv.FormatInt(arg.EndTime, 10)) + } path := fmt.Sprintf("%s%s?%s", apiURL, candleStick, params.Encode()) @@ -402,19 +395,31 @@ func (b *Binance) NewOrderTest() (interface{}, error) { func (b *Binance) NewOrder(o NewOrderRequest) (NewOrderResponse, error) { var resp NewOrderResponse - path := fmt.Sprintf("%s%s", apiURL, newOrderTest) + path := fmt.Sprintf("%s%s", apiURL, newOrder) params := url.Values{} params.Set("symbol", o.Symbol) - params.Set("side", o.Side) - params.Set("type", o.TradeType) - params.Set("timeInForce", o.TimeInForce) + params.Set("side", string(o.Side)) + params.Set("type", string(o.TradeType)) params.Set("quantity", strconv.FormatFloat(o.Quantity, 'f', -1, 64)) params.Set("price", strconv.FormatFloat(o.Price, 'f', -1, 64)) - params.Set("newClientOrderID", o.NewClientOrderID) - params.Set("stopPrice", strconv.FormatFloat(o.StopPrice, 'f', -1, 64)) - params.Set("icebergQty", strconv.FormatFloat(o.IcebergQty, 'f', -1, 64)) - params.Set("newOrderRespType", o.NewOrderRespType) + params.Set("timeInForce", string(o.TimeInForce)) + + if o.NewClientOrderID != "" { + params.Set("newClientOrderID", o.NewClientOrderID) + } + + if o.StopPrice != 0 { + params.Set("stopPrice", strconv.FormatFloat(o.StopPrice, 'f', -1, 64)) + } + + if o.IcebergQty != 0 { + params.Set("icebergQty", strconv.FormatFloat(o.IcebergQty, 'f', -1, 64)) + } + + if o.NewOrderRespType != "" { + params.Set("newOrderRespType", o.NewOrderRespType) + } if err := b.SendAuthHTTPRequest("POST", path, params, &resp); err != nil { return resp, err @@ -426,6 +431,71 @@ func (b *Binance) NewOrder(o NewOrderRequest) (NewOrderResponse, error) { return resp, nil } +// CancelOrder sends a cancel order to Binance +func (b *Binance) CancelOrder(symbol string, orderID int64, origClientOrderID string) (CancelOrderResponse, error) { + + var resp CancelOrderResponse + + path := fmt.Sprintf("%s%s", apiURL, cancelOrder) + + params := url.Values{} + params.Set("symbol", symbol) + + if orderID != 0 { + params.Set("orderId", strconv.FormatInt(orderID, 10)) + } + + if origClientOrderID != "" { + params.Set("origClientOrderId", origClientOrderID) + } + + if err := b.SendAuthHTTPRequest("DELETE", path, params, &resp); err != nil { + return resp, err + } + return resp, nil +} + +// OpenOrders Current open orders +// Get all open orders on a symbol. Careful when accessing this with no symbol. +func (b *Binance) OpenOrders(symbol string) ([]QueryOrderData, error) { + var resp []QueryOrderData + + path := fmt.Sprintf("%s%s", apiURL, openOrders) + + params := url.Values{} + if symbol != "" { + params.Set("symbol", common.StringToUpper(symbol)) + } + if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil { + return resp, err + } + + return resp, nil +} + +// AllOrders Get all account orders; active, canceled, or filled. +// orderId optional param +// limit optional param, default 500; max 500 +func (b *Binance) AllOrders(symbol, orderID, limit string) ([]QueryOrderData, error) { + var resp []QueryOrderData + + path := fmt.Sprintf("%s%s", apiURL, allOrders) + + params := url.Values{} + params.Set("symbol", common.StringToUpper(symbol)) + if orderID != "" { + params.Set("orderId", orderID) + } + if limit != "" { + params.Set("limit", limit) + } + if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil { + return resp, err + } + + return resp, nil +} + // QueryOrder returns information on a past order func (b *Binance) QueryOrder(symbol, origClientOrderID string, orderID int64) (QueryOrderData, error) { var resp QueryOrderData @@ -434,8 +504,12 @@ func (b *Binance) QueryOrder(symbol, origClientOrderID string, orderID int64) (Q params := url.Values{} params.Set("symbol", common.StringToUpper(symbol)) - params.Set("origClientOrderId", origClientOrderID) - params.Set("orderId", strconv.FormatInt(orderID, 10)) + if origClientOrderID != "" { + params.Set("origClientOrderId", origClientOrderID) + } + if orderID != 0 { + params.Set("orderId", strconv.FormatInt(orderID, 10)) + } if err := b.SendAuthHTTPRequest("GET", path, params, &resp); err != nil { return resp, err @@ -484,7 +558,7 @@ func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, re if params == nil { params = url.Values{} } - params.Set("recvWindow", strconv.FormatInt(5000, 10)) + params.Set("recvWindow", strconv.FormatInt(common.RecvWindow(5*time.Second), 10)) params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10)) signature := params.Encode() @@ -494,7 +568,6 @@ func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, re headers := make(map[string]string) headers["X-MBX-APIKEY"] = b.APIKey - headers["Content-Type"] = "application/x-www-form-urlencoded" if b.Verbose { log.Printf("sent path: \n%s\n", path) @@ -505,16 +578,18 @@ func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, re } // CheckLimit checks value against a variable list -func (b *Binance) CheckLimit(limit int64) error { - if !common.StringDataCompare(b.validLimits, strconv.FormatInt(limit, 10)) { - return errors.New("Incorrect limit values - valid values are 5, 10, 20, 50, 100, 500, 1000") +func (b *Binance) CheckLimit(limit int) error { + for x := range b.validLimits { + if b.validLimits[x] == limit { + return nil + } } - return nil + return errors.New("Incorrect limit values - valid values are 5, 10, 20, 50, 100, 500, 1000") } // CheckSymbol checks value against a variable list func (b *Binance) CheckSymbol(symbol string) error { - enPairs := b.GetEnabledCurrencies() + enPairs := b.GetAvailableCurrencies() for x := range enPairs { if exchange.FormatExchangeCurrency(b.Name, enPairs[x]).String() == symbol { return nil @@ -525,14 +600,32 @@ func (b *Binance) CheckSymbol(symbol string) error { // CheckIntervals checks value against a variable list func (b *Binance) CheckIntervals(interval string) error { - if !common.StringDataCompare(b.validIntervals, interval) { - return errors.New(`Incorrect interval values - valid values are "1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","12h","1d","3d","1w","1M"`) + for x := range b.validIntervals { + if TimeInterval(interval) == b.validIntervals[x] { + return nil + } } - return nil + return errors.New(`Incorrect interval values - valid values are "1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","12h","1d","3d","1w","1M"`) } // SetValues sets the default valid values func (b *Binance) SetValues() { - b.validLimits = []string{"5", "10", "20", "50", "100", "500", "1000"} - b.validIntervals = []string{"1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "8h", "12h", "1d", "3d", "1w", "1M"} + b.validLimits = []int{5, 10, 20, 50, 100, 500, 1000} + b.validIntervals = []TimeInterval{ + TimeIntervalMinute, + TimeIntervalThreeMinutes, + TimeIntervalFiveMinutes, + TimeIntervalFifteenMinutes, + TimeIntervalThirtyMinutes, + TimeIntervalHour, + TimeIntervalTwoHours, + TimeIntervalFourHours, + TimeIntervalSixHours, + TimeIntervalEightHours, + TimeIntervalTwelveHours, + TimeIntervalDay, + TimeIntervalThreeDays, + TimeIntervalWeek, + TimeIntervalMonth, + } } diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index a02a02c7..0ca6d3f1 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -43,7 +43,11 @@ func TestGetExchangeValidCurrencyPairs(t *testing.T) { func TestGetOrderBook(t *testing.T) { t.Parallel() - _, err := b.GetOrderBook("BTCUSDT", 5) + _, err := b.GetOrderBook(OrderBookDataRequestParams{ + Symbol: "BTCUSDT", + Limit: 10, + }) + if err != nil { t.Error("Test Failed - Binance GetOrderBook() error", err) } @@ -51,7 +55,12 @@ func TestGetOrderBook(t *testing.T) { func TestGetRecentTrades(t *testing.T) { t.Parallel() - _, err := b.GetRecentTrades("BTCUSDT", 5) + + _, err := b.GetRecentTrades(RecentTradeRequestParams{ + Symbol: "BTCUSDT", + Limit: 15, + }) + if err != nil { t.Error("Test Failed - Binance GetRecentTrades() error", err) } @@ -73,11 +82,15 @@ func TestGetAggregatedTrades(t *testing.T) { } } -func TestGetCandleStickData(t *testing.T) { +func TestGetSpotKline(t *testing.T) { t.Parallel() - _, err := b.GetCandleStickData("BTCUSDT", "1d", 5) + _, err := b.GetSpotKline(KlinesRequestParams{ + Symbol: "BTCUSDT", + Interval: TimeIntervalFiveMinutes, + Limit: 24, + }) if err != nil { - t.Error("Test Failed - Binance GetCandleStickData() error", err) + t.Error("Test Failed - Binance GetSpotKline() error", err) } } @@ -123,16 +136,72 @@ func TestNewOrderTest(t *testing.T) { func TestNewOrder(t *testing.T) { t.Parallel() - _, err := b.NewOrder(NewOrderRequest{}) + + if testAPIKey == "" || testAPISecret == "" { + t.Skip() + } + _, err := b.NewOrder(NewOrderRequest{ + Symbol: "BTCUSDT", + Side: BinanceRequestParamsSideSell, + TradeType: BinanceRequestParamsOrderLimit, + TimeInForce: BinanceRequestParamsTimeGTC, + Quantity: 0.01, + Price: 1536.1, + }) + if err == nil { t.Error("Test Failed - Binance NewOrder() error", err) } } +func TestCancelOrder(t *testing.T) { + t.Parallel() + + if testAPIKey == "" || testAPISecret == "" { + t.Skip() + } + + _, err := b.CancelOrder("BTCUSDT", 82584683, "") + if err == nil { + t.Error("Test Failed - Binance CancelOrder() error", err) + } +} + func TestQueryOrder(t *testing.T) { t.Parallel() - _, err := b.QueryOrder("", "", 1337) - if err == nil { + + if testAPIKey == "" || testAPISecret == "" { + t.Skip() + } + + _, err := b.QueryOrder("BTCUSDT", "", 1337) + if err != nil { t.Error("Test Failed - Binance QueryOrder() error", err) } } + +func TestOpenOrders(t *testing.T) { + t.Parallel() + + if testAPIKey == "" || testAPISecret == "" { + t.Skip() + } + + _, err := b.OpenOrders("BTCUSDT") + if err != nil { + t.Error("Test Failed - Binance OpenOrders() error", err) + } +} + +func TestAllOrders(t *testing.T) { + t.Parallel() + + if testAPIKey == "" || testAPISecret == "" { + t.Skip() + } + + _, err := b.AllOrders("BTCUSDT", "", "") + if err != nil { + t.Error("Test Failed - Binance AllOrders() error", err) + } +} diff --git a/exchanges/binance/binance_types.go b/exchanges/binance/binance_types.go index 66bdd183..380102bc 100644 --- a/exchanges/binance/binance_types.go +++ b/exchanges/binance/binance_types.go @@ -1,6 +1,5 @@ package binance - import ( "encoding/json" ) @@ -45,6 +44,12 @@ type ExchangeInfo struct { } `json:"symbols"` } +// OrderBookDataRequestParams represents Klines request data. +type OrderBookDataRequestParams struct { + Symbol string `json:"symbol"` // Required field; example LTCBTC,BTCUSDT + Limit int `json:"limit"` // Default 100; max 1000. Valid limits:[5, 10, 20, 50, 100, 500, 1000] +} + // OrderBookData is resp data from orderbook endpoint type OrderBookData struct { Code int `json:"code"` @@ -68,6 +73,12 @@ type OrderBook struct { } } +// RecentTradeRequestParams represents Klines request data. +type RecentTradeRequestParams struct { + Symbol string `json:"symbol"` // Required field. example LTCBTC, BTCUSDT + Limit int `json:"limit"` // Default 500; max 500. +} + // RecentTrade holds recent trade data type RecentTrade struct { Code int `json:"code"` @@ -75,16 +86,18 @@ type RecentTrade struct { ID int64 `json:"id"` Price float64 `json:"price,string"` Quantity float64 `json:"qty,string"` - Time int64 `json:"time"` + Time float64 `json:"time"` IsBuyerMaker bool `json:"isBuyerMaker"` IsBestMatch bool `json:"isBestMatch"` } +// MultiStreamData holds stream data type MultiStreamData struct { Stream string `json:"stream"` Data json.RawMessage `json:"data"` } +// TradeStream holds the trade stream data type TradeStream struct { EventType string `json:"e"` EventTime int64 `json:"E"` @@ -99,6 +112,7 @@ type TradeStream struct { BestMatchPrice bool `json:"M"` } +// KlineStream holds the kline stream data type KlineStream struct { EventType string `json:"e"` EventTime int64 `json:"E"` @@ -123,6 +137,7 @@ type KlineStream struct { } `json:"k"` } +// TickerStream holds the ticker stream data type TickerStream struct { EventType string `json:"e"` EventTime int64 `json:"E"` @@ -228,15 +243,21 @@ type BestPrice struct { // NewOrderRequest request type type NewOrderRequest struct { - Symbol string - Side string - TradeType string - TimeInForce string + // Symbol (currency pair to trade) + Symbol string + // Side Buy or Sell + Side RequestParamsSideType + // TradeType (market or limit order) + TradeType RequestParamsOrderType + // TimeInForce specifies how long the order remains in effect. + // Examples are (Good Till Cancel (GTC), Immediate or Cancel (IOC) and Fill Or Kill (FOK)) + TimeInForce RequestParamsTimeForceType + // Quantity Quantity float64 Price float64 NewClientOrderID string - StopPrice float64 - IcebergQty float64 + StopPrice float64 //Used with STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, and TAKE_PROFIT_LIMIT orders. + IcebergQty float64 //Used with LIMIT, STOP_LOSS_LIMIT, and TAKE_PROFIT_LIMIT to create an iceberg order. NewOrderRespType string } @@ -263,6 +284,14 @@ type NewOrderResponse struct { } `json:"fills"` } +// CancelOrderResponse is the return structured response from the exchange +type CancelOrderResponse struct { + Symbol string `json:"symbol"` + OrigClientOrderID string `json:"origClientOrderId"` + OrderID int64 `json:"orderId"` + ClientOrderID string `json:"clientOrderId"` +} + // QueryOrderData holds query order data type QueryOrderData struct { Code int `json:"code"` @@ -279,7 +308,7 @@ type QueryOrderData struct { Side string `json:"side"` StopPrice float64 `json:"stopPrice,string"` IcebergQty float64 `json:"icebergQty,string"` - Time int64 `json:"time"` + Time float64 `json:"time"` IsWorking bool `json:"isWorking"` } @@ -302,3 +331,85 @@ type Account struct { UpdateTime int64 `json:"updateTime"` Balances []Balance `json:"balances"` } + +// RequestParamsSideType trade order side (buy or sell) +type RequestParamsSideType string + +var ( + // BinanceRequestParamsSideBuy buy order type + BinanceRequestParamsSideBuy = RequestParamsSideType("BUY") + + // BinanceRequestParamsSideSell sell order type + BinanceRequestParamsSideSell = RequestParamsSideType("SELL") +) + +// RequestParamsTimeForceType Time in force +type RequestParamsTimeForceType string + +var ( + // BinanceRequestParamsTimeGTC GTC + BinanceRequestParamsTimeGTC = RequestParamsTimeForceType("GTC") + + // BinanceRequestParamsTimeIOC IOC + BinanceRequestParamsTimeIOC = RequestParamsTimeForceType("IOC") + + // BinanceRequestParamsTimeFOK FOK + BinanceRequestParamsTimeFOK = RequestParamsTimeForceType("FOK") +) + +// RequestParamsOrderType trade order type +type RequestParamsOrderType string + +var ( + // BinanceRequestParamsOrderLimit Limit order + BinanceRequestParamsOrderLimit = RequestParamsOrderType("LIMIT") + + // BinanceRequestParamsOrderMarket Market order + BinanceRequestParamsOrderMarket = RequestParamsOrderType("MARKET") + + // BinanceRequestParamsOrderStopLoss STOP_LOSS + BinanceRequestParamsOrderStopLoss = RequestParamsOrderType("STOP_LOSS") + + // BinanceRequestParamsOrderStopLossLimit STOP_LOSS_LIMIT + BinanceRequestParamsOrderStopLossLimit = RequestParamsOrderType("STOP_LOSS_LIMIT") + + // BinanceRequestParamsOrderTakeProfit TAKE_PROFIT + BinanceRequestParamsOrderTakeProfit = RequestParamsOrderType("TAKE_PROFIT") + + // BinanceRequestParamsOrderTakeProfitLimit TAKE_PROFIT_LIMIT + BinanceRequestParamsOrderTakeProfitLimit = RequestParamsOrderType("TAKE_PROFIT_LIMIT") + + // BinanceRequestParamsOrderLimitMarker LIMIT_MAKER + BinanceRequestParamsOrderLimitMarker = RequestParamsOrderType("LIMIT_MAKER") +) + +// KlinesRequestParams represents Klines request data. +type KlinesRequestParams struct { + Symbol string // Required field; example LTCBTC, BTCUSDT + Interval TimeInterval // Time interval period + Limit int // Default 500; max 500. + StartTime int64 + EndTime int64 +} + +// TimeInterval represents interval enum. +type TimeInterval string + +// Vars related to time intervals +var ( + TimeIntervalMinute = TimeInterval("1m") + TimeIntervalThreeMinutes = TimeInterval("3m") + TimeIntervalFiveMinutes = TimeInterval("5m") + TimeIntervalFifteenMinutes = TimeInterval("15m") + TimeIntervalThirtyMinutes = TimeInterval("30m") + TimeIntervalHour = TimeInterval("1h") + TimeIntervalTwoHours = TimeInterval("2h") + TimeIntervalFourHours = TimeInterval("4h") + TimeIntervalSixHours = TimeInterval("6h") + TimeIntervalEightHours = TimeInterval("8h") + TimeIntervalTwelveHours = TimeInterval("12h") + TimeIntervalDay = TimeInterval("1d") + TimeIntervalThreeDays = TimeInterval("3d") + TimeIntervalWeek = TimeInterval("1w") + TimeIntervalMonth = TimeInterval("1M") +) diff --git a/exchanges/binance/binance_websocket.go b/exchanges/binance/binance_websocket.go index 17f0979d..896cc3ef 100644 --- a/exchanges/binance/binance_websocket.go +++ b/exchanges/binance/binance_websocket.go @@ -15,6 +15,7 @@ const ( binancePingPeriod = 20 * time.Second ) +// WebsocketClient starts and handles the websocket client connection func (b *Binance) WebsocketClient() { for b.Enabled && b.Websocket { var Dialer websocket.Dialer diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 90560e23..a1f5e43a 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -106,7 +106,7 @@ func (b *Binance) GetOrderbookEx(currency pair.CurrencyPair, assetType string) ( // UpdateOrderbook updates and returns the orderbook for a currency pair func (b *Binance) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) { var orderBook orderbook.Base - orderbookNew, err := b.GetOrderBook(exchange.FormatExchangeCurrency(b.Name, p).String(), 1000) + orderbookNew, err := b.GetOrderBook(OrderBookDataRequestParams{Symbol: exchange.FormatExchangeCurrency(b.Name, p).String(), Limit: 1000}) if err != nil { return orderBook, err } diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go index 63186507..71831ff7 100644 --- a/exchanges/bitfinex/bitfinex.go +++ b/exchanges/bitfinex/bitfinex.go @@ -11,7 +11,7 @@ import ( "github.com/gorilla/websocket" "github.com/thrasher-/gocryptotrader/common" "github.com/thrasher-/gocryptotrader/config" - "github.com/thrasher-/gocryptotrader/exchanges" + exchange "github.com/thrasher-/gocryptotrader/exchanges" "github.com/thrasher-/gocryptotrader/exchanges/request" "github.com/thrasher-/gocryptotrader/exchanges/ticker" ) @@ -153,10 +153,21 @@ func (b *Bitfinex) GetPlatformStatus() (int, error) { return int(response[0].(float64)), nil } +// GetLatestSpotPrice returns latest spot price of symbol +// +// symbol: string of currency pair +func (b *Bitfinex) GetLatestSpotPrice(symbol string) (float64, error) { + res, err := b.GetTicker(symbol) + if err != nil { + return 0, err + } + return res.Mid, nil +} + // GetTicker returns ticker information -func (b *Bitfinex) GetTicker(symbol string, values url.Values) (Ticker, error) { +func (b *Bitfinex) GetTicker(symbol string) (Ticker, error) { response := Ticker{} - path := common.EncodeURLValues(bitfinexAPIURL+bitfinexTicker+symbol, values) + path := common.EncodeURLValues(bitfinexAPIURL+bitfinexTicker+symbol, url.Values{}) if err := b.SendHTTPRequest(path, &response, b.Verbose); err != nil { return response, err @@ -453,18 +464,33 @@ func (b *Bitfinex) GetSymbolsDetails() ([]SymbolDetails, error) { } // GetAccountInfo returns information about your account incl. trading fees -func (b *Bitfinex) GetAccountInfo() ([]AccountInfo, error) { - response := AccountInfoFull{} +func (b *Bitfinex) GetAccountInfo() (AccountInfo, error) { + + var result AccountInfo + + var response []interface{} + err := b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountInfo, nil, &response) - err := b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountFees, nil, &response) if err != nil { - return response.Info, err + return result, err } - if response.Message == "" { - return response.Info, errors.New(response.Message) + result = AccountInfo{} + result.MakerFees = response[0].(map[string]interface{})["maker_fees"].(string) + result.TakerFees = response[0].(map[string]interface{})["taker_fees"].(string) + + feeslist := response[0].(map[string]interface{})["fees"].([]interface{}) + for _, v := range feeslist { + item := v.(map[string]interface{}) + + result.Fees = append(result.Fees, AccountInfoFees{ + Pairs: item["pairs"].(string), + MakerFees: item["maker_fees"].(string), + TakerFees: item["taker_fees"].(string), + }) } - return response.Info, nil + + return result, nil } // GetAccountFees - NOT YET IMPLEMENTED @@ -877,7 +903,7 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[ headers["X-BFX-PAYLOAD"] = PayloadBase64 headers["X-BFX-SIGNATURE"] = common.HexEncodeToString(hmac) - b.SendPayload(method, bitfinexAPIURL+path, headers, nil, result, true, b.Verbose) + err = b.SendPayload(method, bitfinexAPIURL+path, headers, nil, result, true, b.Verbose) if err != nil { return err } diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index 33720816..e64fad5f 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -52,14 +52,22 @@ func TestGetPlatformStatus(t *testing.T) { } } +func TestGetLatestSpotPrice(t *testing.T) { + t.Parallel() + _, err := b.GetLatestSpotPrice("BTCUSD") + if err != nil { + t.Error("Bitfinex GetLatestSpotPrice error: ", err) + } +} + func TestGetTicker(t *testing.T) { t.Parallel() - _, err := b.GetTicker("BTCUSD", url.Values{}) + _, err := b.GetTicker("BTCUSD") if err != nil { t.Error("BitfinexGetTicker init error: ", err) } - _, err = b.GetTicker("wigwham", url.Values{}) + _, err = b.GetTicker("wigwham") if err == nil { t.Error("Test Failed - GetTicker() error") } diff --git a/exchanges/bitfinex/bitfinex_types.go b/exchanges/bitfinex/bitfinex_types.go index 91762a2e..c6001858 100644 --- a/exchanges/bitfinex/bitfinex_types.go +++ b/exchanges/bitfinex/bitfinex_types.go @@ -133,14 +133,17 @@ type AccountInfoFull struct { // AccountInfo general account information with fees type AccountInfo struct { + MakerFees string `json:"maker_fees"` + TakerFees string `json:"taker_fees"` + Fees []AccountInfoFees `json:"fees"` + Message string `json:"message"` +} + +// AccountInfoFees general account information with fees +type AccountInfoFees struct { + Pairs string `json:"pairs"` MakerFees string `json:"maker_fees"` TakerFees string `json:"taker_fees"` - Fees []struct { - Pairs string `json:"pairs"` - MakerFees string `json:"maker_fees"` - TakerFees string `json:"taker_fees"` - } `json:"fees"` - Message string `json:"message"` } // AccountFees stores withdrawal account fee data from Bitfinex @@ -462,3 +465,22 @@ type WebsocketTradeExecuted struct { type ErrorCapture struct { Message string `json:"message"` } + +// TimeInterval represents interval enum. +type TimeInterval string + +// TimeInvterval vars +var ( + TimeIntervalMinute = TimeInterval("1m") + TimeIntervalFiveMinutes = TimeInterval("5m") + TimeIntervalFifteenMinutes = TimeInterval("15m") + TimeIntervalThirtyMinutes = TimeInterval("30m") + TimeIntervalHour = TimeInterval("1h") + TimeIntervalThreeHours = TimeInterval("3h") + TimeIntervalSixHours = TimeInterval("6h") + TimeIntervalTwelveHours = TimeInterval("12h") + TimeIntervalDay = TimeInterval("1d") + TimeIntervalSevenDays = TimeInterval("7d") + TimeIntervalFourteenDays = TimeInterval("14d") + TimeIntervalMonth = TimeInterval("1M") +) diff --git a/exchanges/gateio/README.md b/exchanges/gateio/README.md new file mode 100644 index 00000000..434088f5 --- /dev/null +++ b/exchanges/gateio/README.md @@ -0,0 +1,9 @@ +# GoCryptoTrader package gateio + +This gateio package is part of the GoCryptoTrader codebase. + +## Gateio Exchange + +### Current Features + +Gateio 交易所的支持,支持获取K线、支持的交易对、交易市场参数、买/卖订单、取消订单 \ No newline at end of file diff --git a/exchanges/gateio/gateio.go b/exchanges/gateio/gateio.go new file mode 100644 index 00000000..1b23a771 --- /dev/null +++ b/exchanges/gateio/gateio.go @@ -0,0 +1,375 @@ +package gateio + +import ( + "encoding/json" + "errors" + "fmt" + "log" + "strconv" + "strings" + "time" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" + exchange "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/request" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +const ( + gateioTradeURL = "https://api.gateio.io" + gateioMarketURL = "https://data.gateio.io" + gateioAPIVersion = "api2/1" + + gateioSymbol = "pairs" + gateioMarketInfo = "marketinfo" + gateioKline = "candlestick2" + gateioOrder = "private" + gateioBalances = "private/balances" + gateioCancelOrder = "private/cancelOrder" + gateioTicker = "ticker" + gateioTickers = "tickers" + gateioOrderbook = "orderBook" + + gateioAuthRate = 100 + gateioUnauthRate = 100 +) + +// Gateio is the overarching type across this package +type Gateio struct { + exchange.Base +} + +// SetDefaults sets default values for the exchange +func (g *Gateio) SetDefaults() { + g.Name = "GateIO" + g.Enabled = false + g.Verbose = false + g.Websocket = false + g.RESTPollingDelay = 10 + g.RequestCurrencyPairFormat.Delimiter = "_" + g.RequestCurrencyPairFormat.Uppercase = false + g.ConfigCurrencyPairFormat.Delimiter = "_" + g.ConfigCurrencyPairFormat.Uppercase = true + g.AssetTypes = []string{ticker.Spot} + g.SupportsAutoPairUpdating = true + g.SupportsRESTTickerBatching = true + g.Requester = request.New(g.Name, request.NewRateLimit(time.Second*10, gateioAuthRate), request.NewRateLimit(time.Second*10, gateioUnauthRate), common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout)) +} + +// Setup sets user configuration +func (g *Gateio) Setup(exch config.ExchangeConfig) { + if !exch.Enabled { + g.SetEnabled(false) + } else { + g.Enabled = true + g.AuthenticatedAPISupport = exch.AuthenticatedAPISupport + g.SetAPIKeys(exch.APIKey, exch.APISecret, "", false) + g.APIAuthPEMKey = exch.APIAuthPEMKey + g.SetHTTPClientTimeout(exch.HTTPTimeout) + g.RESTPollingDelay = exch.RESTPollingDelay + g.Verbose = exch.Verbose + g.Websocket = exch.Websocket + 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) + } + err = g.SetAssetTypes() + if err != nil { + log.Fatal(err) + } + err = g.SetAutoPairDefaults() + if err != nil { + log.Fatal(err) + } + } +} + +// GetSymbols returns all supported symbols +func (g *Gateio) GetSymbols() ([]string, error) { + var result []string + + url := fmt.Sprintf("%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioSymbol) + + err := g.SendHTTPRequest(url, &result) + if err != nil { + return nil, nil + } + return result, err +} + +// GetMarketInfo returns information about all trading pairs, including +// transaction fee, minimum order quantity, price accuracy and so on +func (g *Gateio) GetMarketInfo() (MarketInfoResponse, error) { + type response struct { + Result string `json:"result"` + Pairs []interface{} `json:"pairs"` + } + + url := fmt.Sprintf("%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioMarketInfo) + + var res response + var result MarketInfoResponse + err := g.SendHTTPRequest(url, &res) + if err != nil { + return result, err + } + + result.Result = res.Result + for _, v := range res.Pairs { + item := v.(map[string]interface{}) + for itemk, itemv := range item { + pairv := itemv.(map[string]interface{}) + result.Pairs = append(result.Pairs, MarketInfoPairsResponse{ + Symbol: itemk, + DecimalPlaces: pairv["decimal_places"].(float64), + MinAmount: pairv["min_amount"].(float64), + Fee: pairv["fee"].(float64), + }) + } + } + return result, nil +} + +// GetLatestSpotPrice returns latest spot price of symbol +// updated every 10 seconds +// +// symbol: string of currency pair +func (g *Gateio) GetLatestSpotPrice(symbol string) (float64, error) { + res, err := g.GetTicker(symbol) + if err != nil { + return 0, err + } + + return res.Last, nil +} + +// GetTicker returns a ticker for the supplied symbol +// updated every 10 seconds +func (g *Gateio) GetTicker(symbol string) (TickerResponse, error) { + url := fmt.Sprintf("%s/%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioTicker, symbol) + + var res TickerResponse + err := g.SendHTTPRequest(url, &res) + if err != nil { + return res, err + } + return res, nil +} + +// GetTickers returns tickers for all symbols +func (g *Gateio) GetTickers() (map[string]TickerResponse, error) { + url := fmt.Sprintf("%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioTickers) + + resp := make(map[string]TickerResponse) + err := g.SendHTTPRequest(url, &resp) + if err != nil { + return nil, err + } + return resp, nil +} + +// GetOrderbook returns the orderbook data for a suppled symbol +func (g *Gateio) GetOrderbook(symbol string) (Orderbook, error) { + url := fmt.Sprintf("%s/%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioOrderbook, symbol) + + var resp OrderbookResponse + err := g.SendHTTPRequest(url, &resp) + if err != nil { + return Orderbook{}, err + } + + if resp.Result != "true" { + return Orderbook{}, errors.New("result was not true") + } + + var ob Orderbook + + // Asks are in reverse order + for x := len(resp.Asks) - 1; x != 0; x-- { + data := resp.Asks[x] + + price, err := strconv.ParseFloat(data[0], 64) + if err != nil { + continue + } + + amount, err := strconv.ParseFloat(data[1], 64) + if err != nil { + continue + } + + ob.Asks = append(ob.Asks, OrderbookItem{Price: price, Amount: amount}) + } + + for x := range resp.Bids { + data := resp.Bids[x] + + price, err := strconv.ParseFloat(data[0], 64) + if err != nil { + continue + } + + amount, err := strconv.ParseFloat(data[1], 64) + if err != nil { + continue + } + + ob.Bids = append(ob.Bids, OrderbookItem{Price: price, Amount: amount}) + } + + ob.Result = resp.Result + ob.Elapsed = resp.Elapsed + return ob, nil +} + +// GetSpotKline returns kline data for the most recent time period +func (g *Gateio) GetSpotKline(arg KlinesRequestParams) ([]*KLineResponse, error) { + url := fmt.Sprintf("%s/%s/%s/%s?group_sec=%d&range_hour=%d", gateioMarketURL, gateioAPIVersion, gateioKline, arg.Symbol, arg.GroupSec, arg.HourSize) + var rawKlines map[string]interface{} + err := g.SendHTTPRequest(url, &rawKlines) + if err != nil { + return nil, err + } + + var result []*KLineResponse + if rawKlines == nil || rawKlines["data"] == nil { + return nil, fmt.Errorf("rawKlines is nil. Err: %s", err) + } + + rawKlineDatasString, _ := json.Marshal(rawKlines["data"].([]interface{})) + rawKlineDatas := [][]interface{}{} + if err := json.Unmarshal(rawKlineDatasString, &rawKlineDatas); err != nil { + return nil, fmt.Errorf("rawKlines unmarshal failed. Err: %s", err) + } + + for _, k := range rawKlineDatas { + otString, _ := strconv.ParseFloat(k[0].(string), 64) + ot, err := common.TimeFromUnixTimestampFloat(otString) + if err != nil { + return nil, fmt.Errorf("cannot parse Kline.OpenTime. Err: %s", err) + } + _vol, err := common.FloatFromString(k[1]) + if err != nil { + return nil, fmt.Errorf("cannot parse Kline.Volume. Err: %s", err) + } + _id, err := common.FloatFromString(k[0]) + if err != nil { + return nil, fmt.Errorf("cannot parse Kline.Id. Err: %s", err) + } + _close, err := common.FloatFromString(k[2]) + if err != nil { + return nil, fmt.Errorf("cannot parse Kline.Close. Err: %s", err) + } + _high, err := common.FloatFromString(k[3]) + if err != nil { + return nil, fmt.Errorf("cannot parse Kline.High. Err: %s", err) + } + _low, err := common.FloatFromString(k[4]) + if err != nil { + return nil, fmt.Errorf("cannot parse Kline.Low. Err: %s", err) + } + _open, err := common.FloatFromString(k[5]) + if err != nil { + return nil, fmt.Errorf("cannot parse Kline.Open. Err: %s", err) + } + result = append(result, &KLineResponse{ + ID: _id, + KlineTime: ot, + Volume: _vol, + Close: _close, + High: _high, + Low: _low, + Open: _open, + }) + } + return result, nil +} + +// GetBalances obtains the users account balance +func (g *Gateio) GetBalances() (BalancesResponse, error) { + + var result BalancesResponse + + err := g.SendAuthenticatedHTTPRequest("POST", gateioBalances, "", &result) + if err != nil { + return result, err + } + + return result, nil +} + +// SpotNewOrder places a new order +func (g *Gateio) SpotNewOrder(arg SpotNewOrderRequestParams) (SpotNewOrderResponse, error) { + var result SpotNewOrderResponse + + // Be sure to use the correct price precision before calling this + params := fmt.Sprintf("currencyPair=%s&rate=%s&amount=%s", + arg.Symbol, + strconv.FormatFloat(arg.Price, 'f', -1, 64), + strconv.FormatFloat(arg.Amount, 'f', -1, 64), + ) + + strRequestURL := fmt.Sprintf("%s/%s", gateioOrder, arg.Type) + + err := g.SendAuthenticatedHTTPRequest("POST", strRequestURL, params, &result) + if err != nil { + return result, err + } + + return result, nil +} + +// CancelOrder cancels an order given the supplied orderID and symbol +// orderID order ID number +// symbol trade pair (ltc_btc) +func (g *Gateio) CancelOrder(orderID int64, symbol string) (bool, error) { + type response struct { + Result bool `json:"result"` + Code int `json:"code"` + Message string `json:"message"` + } + + var result response + // Be sure to use the correct price precision before calling this + params := fmt.Sprintf("orderNumber=%d¤cyPair=%s", + orderID, + symbol, + ) + err := g.SendAuthenticatedHTTPRequest("POST", gateioCancelOrder, params, &result) + if err != nil { + return false, err + } + if !result.Result { + return false, fmt.Errorf("code:%d message:%s", result.Code, result.Message) + } + + return true, nil +} + +// SendHTTPRequest sends an unauthenticated HTTP request +func (g *Gateio) SendHTTPRequest(path string, result interface{}) error { + return g.SendPayload("GET", path, nil, nil, result, false, g.Verbose) +} + +// SendAuthenticatedHTTPRequest sends authenticated requests to the Gateio API +// To use this you must setup an APIKey and APISecret from the exchange +func (g *Gateio) SendAuthenticatedHTTPRequest(method, endpoint, param string, result interface{}) error { + if !g.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, g.Name) + } + + headers := make(map[string]string) + headers["Content-Type"] = "application/x-www-form-urlencoded" + headers["key"] = g.APIKey + + hmac := common.GetHMAC(common.HashSHA512, []byte(param), []byte(g.APISecret)) + headers["sign"] = common.ByteArrayToString(hmac) + + url := fmt.Sprintf("%s/%s/%s", gateioTradeURL, gateioAPIVersion, endpoint) + + return g.SendPayload(method, url, headers, strings.NewReader(param), result, true, g.Verbose) +} diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go new file mode 100644 index 00000000..b8521b9b --- /dev/null +++ b/exchanges/gateio/gateio_test.go @@ -0,0 +1,141 @@ +package gateio + +import ( + "testing" + + "github.com/thrasher-/gocryptotrader/config" +) + +// Please supply your own APIKEYS here for due diligence testing + +const ( + apiKey = "" + apiSecret = "" +) + +var g Gateio + +func TestSetDefaults(t *testing.T) { + g.SetDefaults() +} + +func TestSetup(t *testing.T) { + cfg := config.GetConfig() + cfg.LoadConfig("../../testdata/configtest.json") + gateioConfig, err := cfg.GetExchangeConfig("GateIO") + if err != nil { + t.Error("Test Failed - GateIO Setup() init error") + } + + gateioConfig.AuthenticatedAPISupport = true + gateioConfig.APIKey = apiKey + gateioConfig.APISecret = apiSecret + + g.Setup(gateioConfig) +} + +func TestGetSymbols(t *testing.T) { + t.Parallel() + _, err := g.GetSymbols() + if err != nil { + t.Errorf("Test failed - Gateio TestGetSymbols: %s", err) + } +} + +func TestGetMarketInfo(t *testing.T) { + t.Parallel() + _, err := g.GetMarketInfo() + if err != nil { + t.Errorf("Test failed - Gateio GetMarketInfo: %s", err) + } +} + +func TestSpotNewOrder(t *testing.T) { + t.Parallel() + + if apiKey == "" || apiSecret == "" { + t.Skip() + } + + _, err := g.SpotNewOrder(SpotNewOrderRequestParams{ + Symbol: "btc_usdt", + Amount: 1.1, + Price: 10.1, + Type: SpotNewOrderRequestParamsTypeSell, + }) + if err != nil { + t.Errorf("Test failed - Gateio SpotNewOrder: %s", err) + } +} + +func TestCancelOrder(t *testing.T) { + t.Parallel() + + if apiKey == "" || apiSecret == "" { + t.Skip() + } + + _, err := g.CancelOrder(917591554, "btc_usdt") + if err != nil { + t.Errorf("Test failed - Gateio CancelOrder: %s", err) + } +} + +func TestGetBalances(t *testing.T) { + t.Parallel() + + if apiKey == "" || apiSecret == "" { + t.Skip() + } + + _, err := g.GetBalances() + if err != nil { + t.Errorf("Test failed - Gateio GetBalances: %s", err) + } +} + +func TestGetLatestSpotPrice(t *testing.T) { + t.Parallel() + _, err := g.GetLatestSpotPrice("btc_usdt") + if err != nil { + t.Errorf("Test failed - Gateio GetLatestSpotPrice: %s", err) + } +} + +func TestGetTicker(t *testing.T) { + t.Parallel() + _, err := g.GetTicker("btc_usdt") + if err != nil { + t.Errorf("Test failed - Gateio GetTicker: %s", err) + } +} + +func TestGetTickers(t *testing.T) { + t.Parallel() + _, err := g.GetTickers() + if err != nil { + t.Errorf("Test failed - Gateio GetTicker: %s", err) + } +} + +func TestGetOrderbook(t *testing.T) { + t.Parallel() + _, err := g.GetOrderbook("btc_usdt") + if err != nil { + t.Errorf("Test failed - Gateio GetTicker: %s", err) + } +} + +func TestGetSpotKline(t *testing.T) { + t.Parallel() + + _, err := g.GetSpotKline(KlinesRequestParams{ + Symbol: "btc_usdt", + GroupSec: TimeIntervalFiveMinutes, // 5 minutes or less + HourSize: 1, // 1 hour data + }) + + if err != nil { + t.Errorf("Test failed - Gateio GetSpotKline: %s", err) + } +} diff --git a/exchanges/gateio/gateio_types.go b/exchanges/gateio/gateio_types.go new file mode 100644 index 00000000..b2526246 --- /dev/null +++ b/exchanges/gateio/gateio_types.go @@ -0,0 +1,127 @@ +package gateio + +import "time" + +// SpotNewOrderRequestParamsType order type (buy or sell) +type SpotNewOrderRequestParamsType string + +var ( + // SpotNewOrderRequestParamsTypeBuy buy order + SpotNewOrderRequestParamsTypeBuy = SpotNewOrderRequestParamsType("buy") + + // SpotNewOrderRequestParamsTypeSell sell order + SpotNewOrderRequestParamsTypeSell = SpotNewOrderRequestParamsType("sell") +) + +// TimeInterval Interval represents interval enum. +type TimeInterval int + +// TimeInterval vars +var ( + TimeIntervalMinute = TimeInterval(60) + TimeIntervalThreeMinutes = TimeInterval(60 * 3) + TimeIntervalFiveMinutes = TimeInterval(60 * 5) + TimeIntervalFifteenMinutes = TimeInterval(60 * 15) + TimeIntervalThirtyMinutes = TimeInterval(60 * 30) + TimeIntervalHour = TimeInterval(60 * 60) + TimeIntervalTwoHours = TimeInterval(2 * 60 * 60) + TimeIntervalFourHours = TimeInterval(4 * 60 * 60) + TimeIntervalSixHours = TimeInterval(6 * 60 * 60) + TimeIntervalDay = TimeInterval(60 * 60 * 24) +) + +// MarketInfoResponse holds the market info data +type MarketInfoResponse struct { + Result string `json:"result"` + Pairs []MarketInfoPairsResponse `json:"pairs"` +} + +// MarketInfoPairsResponse holds the market info response data +type MarketInfoPairsResponse struct { + Symbol string + // DecimalPlaces symbol price accuracy + DecimalPlaces float64 + // MinAmount minimum order amount + MinAmount float64 + // Fee transaction fee + Fee float64 +} + +// BalancesResponse holds the user balances +type BalancesResponse struct { + Result string `json:"result"` + Available map[string]string `json:"available"` + Locked map[string]string `json:"locked"` +} + +// KlinesRequestParams represents Klines request data. +type KlinesRequestParams struct { + Symbol string // Required field; example LTCBTC,BTCUSDT + HourSize int // How many hours of data + GroupSec TimeInterval +} + +// KLineResponse holds the kline response data +type KLineResponse struct { + ID float64 + KlineTime time.Time + Open float64 + Time float64 + High float64 + Low float64 + Close float64 + Volume float64 + Amount float64 `db:"amount"` +} + +// TickerResponse holds the ticker response data +type TickerResponse struct { + Result string `json:"result"` + Volume float64 `json:"baseVolume,string"` // Trading volume + High float64 `json:"high24hr,string"` // 24 hour high price + Open float64 `json:"highestBid,string"` // Openening price + Last float64 `json:"last,string"` // Last price + Low float64 `json:"low24hr,string"` // 24 hour low price + Close float64 `json:"lowestAsk,string"` // Closing price + PercentChange float64 `json:"percentChange,string"` // Percentage change + QuoteVolume float64 `json:"quoteVolume,string"` // Quote currency volume +} + +// OrderbookResponse stores the orderbook data +type OrderbookResponse struct { + Result string `json:"result"` + Elapsed string `json:"elapsed"` + Asks [][]string + Bids [][]string +} + +// OrderbookItem stores an orderbook item +type OrderbookItem struct { + Price float64 + Amount float64 +} + +// Orderbook stores the orderbook data +type Orderbook struct { + Result string + Elapsed string + Bids []OrderbookItem + Asks []OrderbookItem +} + +// SpotNewOrderRequestParams Order params +type SpotNewOrderRequestParams struct { + Amount float64 `json:"amount"` // Order quantity + Price float64 `json:"price"` // Order price + Symbol string `json:"symbol"` // Trading pair; btc_usdt, eth_btc...... + Type SpotNewOrderRequestParamsType `json:"type"` // Order type (buy or sell), +} + +// SpotNewOrderResponse Order response +type SpotNewOrderResponse struct { + OrderNumber int64 `json:"orderNumber"` // OrderID number + Price float64 `json:"rate,string"` // Order price + LeftAmount float64 `json:"leftAmount,string"` // The remaining amount to fill + FilledAmount float64 `json:"filledAmount,string"` // The filled amount + Filledrate float64 `json:"filledRate,string"` // FilledPrice +} diff --git a/exchanges/gateio/gateio_wrapper.go b/exchanges/gateio/gateio_wrapper.go new file mode 100644 index 00000000..dbe6564f --- /dev/null +++ b/exchanges/gateio/gateio_wrapper.go @@ -0,0 +1,177 @@ +package gateio + +import ( + "errors" + "log" + "sync" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/currency/pair" + "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/orderbook" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +// Start starts the GateIO go routine +func (g *Gateio) Start(wg *sync.WaitGroup) { + wg.Add(1) + go func() { + g.Run() + wg.Done() + }() +} + +// Run implements the GateIO wrapper +func (g *Gateio) Run() { + if g.Verbose { + log.Printf("%s Websocket: %s. (url: %s).\n", g.GetName(), common.IsEnabled(g.Websocket), g.WebsocketURL) + log.Printf("%s polling delay: %ds.\n", g.GetName(), g.RESTPollingDelay) + log.Printf("%s %d currencies enabled: %s.\n", g.GetName(), len(g.EnabledPairs), g.EnabledPairs) + } + + symbols, err := g.GetSymbols() + if err != nil { + log.Printf("%s Unable to fetch symbols.\n", g.GetName()) + } else { + err = g.UpdateCurrencies(symbols, false, false) + if err != nil { + log.Printf("%s Failed to update available currencies.\n", g.GetName()) + } + } +} + +// UpdateTicker updates and returns the ticker for a currency pair +func (g *Gateio) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) { + var tickerPrice ticker.Price + result, err := g.GetTickers() + if err != nil { + return tickerPrice, err + } + + for _, x := range g.GetEnabledCurrencies() { + currency := exchange.FormatExchangeCurrency(g.Name, x).String() + var tp ticker.Price + tp.Pair = x + tp.High = result[currency].High + tp.Last = result[currency].Last + tp.Last = result[currency].Last + tp.Low = result[currency].Low + tp.Volume = result[currency].Volume + ticker.ProcessTicker(g.Name, x, tp, assetType) + } + + return ticker.GetTicker(g.Name, p, assetType) +} + +// GetTickerPrice returns the ticker for a currency pair +func (g *Gateio) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) { + tickerNew, err := ticker.GetTicker(g.GetName(), p, assetType) + if err != nil { + return g.UpdateTicker(p, assetType) + } + return tickerNew, nil +} + +// GetOrderbookEx returns orderbook base on the currency pair +func (g *Gateio) GetOrderbookEx(currency pair.CurrencyPair, assetType string) (orderbook.Base, error) { + ob, err := orderbook.GetOrderbook(g.GetName(), currency, assetType) + if err != nil { + return g.UpdateOrderbook(currency, assetType) + } + return ob, nil +} + +// UpdateOrderbook updates and returns the orderbook for a currency pair +func (g *Gateio) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) { + var orderBook orderbook.Base + currency := exchange.FormatExchangeCurrency(g.Name, p).String() + + orderbookNew, err := g.GetOrderbook(currency) + if err != nil { + return orderBook, err + } + + for x := range orderbookNew.Bids { + data := orderbookNew.Bids[x] + orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data.Amount, Price: data.Price}) + } + + for x := range orderbookNew.Asks { + data := orderbookNew.Asks[x] + orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount, Price: data.Price}) + } + + orderbook.ProcessOrderbook(g.GetName(), p, orderBook, assetType) + return orderbook.GetOrderbook(g.Name, p, assetType) +} + +// GetExchangeAccountInfo retrieves balances for all enabled currencies for the +// ZB exchange +func (g *Gateio) GetExchangeAccountInfo() (exchange.AccountInfo, error) { + var response exchange.AccountInfo + return response, errors.New("not implemented") +} + +// GetExchangeFundTransferHistory returns funding history, deposits and +// withdrawals +func (g *Gateio) GetExchangeFundTransferHistory() ([]exchange.FundHistory, error) { + var fundHistory []exchange.FundHistory + return fundHistory, errors.New("not supported on exchange") +} + +// GetExchangeHistory returns historic trade data since exchange opening. +func (g *Gateio) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} + +// SubmitExchangeOrder submits a new order +func (g *Gateio) SubmitExchangeOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) { + return 0, errors.New("not yet implemented") +} + +// ModifyExchangeOrder will allow of changing orderbook placement and limit to +// market conversion +func (g *Gateio) ModifyExchangeOrder(orderID int64, action exchange.ModifyOrder) (int64, error) { + return 0, errors.New("not yet implemented") +} + +// CancelExchangeOrder cancels an order by its corresponding ID number +func (g *Gateio) CancelExchangeOrder(orderID int64) error { + return errors.New("not yet implemented") +} + +// CancelAllExchangeOrders cancels all orders associated with a currency pair +func (g *Gateio) CancelAllExchangeOrders() error { + return errors.New("not yet implemented") +} + +// GetExchangeOrderInfo returns information on a current open order +func (g *Gateio) GetExchangeOrderInfo(orderID int64) (exchange.OrderDetail, error) { + var orderDetail exchange.OrderDetail + return orderDetail, errors.New("not yet implemented") +} + +// GetExchangeDepositAddress returns a deposit address for a specified currency +func (g *Gateio) GetExchangeDepositAddress(cryptocurrency pair.CurrencyItem) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawCryptoExchangeFunds returns a withdrawal ID when a withdrawal is +// submitted +func (g *Gateio) WithdrawCryptoExchangeFunds(address string, cryptocurrency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawFiatExchangeFunds returns a withdrawal ID when a +// withdrawal is submitted +func (g *Gateio) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawFiatExchangeFundsToInternationalBank returns a withdrawal ID when a +// withdrawal is submitted +func (g *Gateio) WithdrawFiatExchangeFundsToInternationalBank(currency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index 4c1a8e05..a1d361f6 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -17,7 +17,7 @@ import ( "github.com/thrasher-/gocryptotrader/common" "github.com/thrasher-/gocryptotrader/config" - "github.com/thrasher-/gocryptotrader/exchanges" + exchange "github.com/thrasher-/gocryptotrader/exchanges" "github.com/thrasher-/gocryptotrader/exchanges/request" "github.com/thrasher-/gocryptotrader/exchanges/ticker" ) @@ -116,17 +116,15 @@ func (h *HUOBI) GetFee() float64 { return h.Fee } -// GetKline returns kline data -func (h *HUOBI) GetKline(symbol, period, size string) ([]KlineItem, error) { +// GetSpotKline returns kline data +// KlinesRequestParams contains symbol, period and size +func (h *HUOBI) GetSpotKline(arg KlinesRequestParams) ([]KlineItem, error) { vals := url.Values{} - vals.Set("symbol", symbol) + vals.Set("symbol", arg.Symbol) + vals.Set("period", string(arg.Period)) - if period != "" { - vals.Set("period", period) - } - - if size != "" { - vals.Set("size", size) + if arg.Size != 0 { + vals.Set("size", strconv.Itoa(arg.Size)) } type response struct { @@ -165,12 +163,12 @@ func (h *HUOBI) GetMarketDetailMerged(symbol string) (DetailMerged, error) { } // GetDepth returns the depth for the specified symbol -func (h *HUOBI) GetDepth(symbol, depthType string) (Orderbook, error) { +func (h *HUOBI) GetDepth(obd OrderBookDataRequestParams) (Orderbook, error) { vals := url.Values{} - vals.Set("symbol", symbol) + vals.Set("symbol", obd.Symbol) - if depthType != "" { - vals.Set("type", depthType) + if obd.Type != OrderBookDataRequestParamsTypeNone { + vals.Set("type", string(obd.Type)) } type response struct { @@ -210,6 +208,22 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) { return result.Tick.Data, err } +// GetLatestSpotPrice returns latest spot price of symbol +// +// symbol: string of currency pair +func (h *HUOBI) GetLatestSpotPrice(symbol string) (float64, error) { + list, err := h.GetTradeHistory(symbol, "1") + + if err != nil { + return 0, err + } + if len(list) == 0 { + return 0, errors.New("The length of the list is 0") + } + + return list[0].Trades[0].Price, nil +} + // GetTradeHistory returns the trades for the specified symbol func (h *HUOBI) GetTradeHistory(symbol, size string) ([]TradeHistory, error) { vals := url.Values{} @@ -338,23 +352,23 @@ func (h *HUOBI) GetAccountBalance(accountID string) ([]AccountBalanceDetail, err return result.AccountBalanceData.AccountBalanceDetails, err } -// PlaceOrder submits an order to Huobi -func (h *HUOBI) PlaceOrder(symbol, source, accountID, orderType string, amount, price float64) (int64, error) { +// SpotNewOrder submits an order to Huobi +func (h *HUOBI) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) { vals := url.Values{} - vals.Set("account-id", accountID) - vals.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) + vals.Set("account-id", fmt.Sprintf("%d", arg.AccountID)) + vals.Set("amount", strconv.FormatFloat(arg.Amount, 'f', -1, 64)) // Only set price if order type is not equal to buy-market or sell-market - if orderType != "buy-market" && orderType != "sell-market" { - vals.Set("price", strconv.FormatFloat(price, 'f', -1, 64)) + if arg.Type != SpotNewOrderRequestTypeBuyMarket && arg.Type != SpotNewOrderRequestTypeSellMarket { + vals.Set("price", strconv.FormatFloat(arg.Price, 'f', -1, 64)) } - if source != "" { - vals.Set("source", source) + if arg.Source != "" { + vals.Set("source", arg.Source) } - vals.Set("symbol", symbol) - vals.Set("type", orderType) + vals.Set("symbol", arg.Symbol) + vals.Set("type", string(arg.Type)) type response struct { Response diff --git a/exchanges/huobi/huobi_test.go b/exchanges/huobi/huobi_test.go index 54a52fcd..26cc27cc 100644 --- a/exchanges/huobi/huobi_test.go +++ b/exchanges/huobi/huobi_test.go @@ -14,15 +14,43 @@ import ( "github.com/thrasher-/gocryptotrader/config" ) -var h HUOBI - -// Please supply your own APIKEYS here for due diligence testing - +// Please supply you own test keys here for due diligence testing. const ( apiKey = "" apiSecret = "" ) +var h HUOBI + +// getDefaultConfig returns a default huobi config +func getDefaultConfig() config.ExchangeConfig { + return config.ExchangeConfig{ + Name: "Huobi", + Enabled: true, + Verbose: true, + Websocket: false, + UseSandbox: false, + RESTPollingDelay: 10, + HTTPTimeout: 15000000000, + AuthenticatedAPISupport: true, + APIKey: "", + APISecret: "", + ClientID: "", + AvailablePairs: "BTC-USDT,BCH-USDT", + EnabledPairs: "BTC-USDT", + BaseCurrencies: "USD", + AssetTypes: "SPOT", + SupportsAutoPairUpdates: false, + ConfigCurrencyPairFormat: &config.CurrencyPairFormatConfig{ + Uppercase: true, + Delimiter: "-", + }, + RequestCurrencyPairFormat: &config.CurrencyPairFormatConfig{ + Uppercase: false, + }, + } +} + func TestSetDefaults(t *testing.T) { h.SetDefaults() } @@ -30,16 +58,16 @@ func TestSetDefaults(t *testing.T) { func TestSetup(t *testing.T) { cfg := config.GetConfig() cfg.LoadConfig("../../testdata/configtest.json") - huobiConfig, err := cfg.GetExchangeConfig("Huobi") + hConfig, err := cfg.GetExchangeConfig("Huobi") if err != nil { t.Error("Test Failed - Huobi Setup() init error") } - huobiConfig.AuthenticatedAPISupport = true - huobiConfig.APIKey = apiKey - huobiConfig.APISecret = apiSecret + hConfig.AuthenticatedAPISupport = true + hConfig.APIKey = apiKey + hConfig.APISecret = apiSecret - h.Setup(huobiConfig) + h.Setup(hConfig) } func TestGetFee(t *testing.T) { @@ -49,11 +77,15 @@ func TestGetFee(t *testing.T) { } } -func TestGetKline(t *testing.T) { +func TestGetSpotKline(t *testing.T) { t.Parallel() - _, err := h.GetKline("btcusdt", "1week", "") + _, err := h.GetSpotKline(KlinesRequestParams{ + Symbol: "btcusdt", + Period: TimeIntervalHour, + Size: 0, + }) if err != nil { - t.Errorf("Test failed - Huobi TestGetKline: %s", err) + t.Errorf("Test failed - Huobi TestGetSpotKline: %s", err) } } @@ -67,7 +99,11 @@ func TestGetMarketDetailMerged(t *testing.T) { func TestGetDepth(t *testing.T) { t.Parallel() - _, err := h.GetDepth("btcusdt", "step1") + _, err := h.GetDepth(OrderBookDataRequestParams{ + Symbol: "btcusdt", + Type: OrderBookDataRequestParamsTypeStep1, + }) + if err != nil { t.Errorf("Test failed - Huobi TestGetDepth: %s", err) } @@ -81,6 +117,14 @@ func TestGetTrades(t *testing.T) { } } +func TestGetLatestSpotPrice(t *testing.T) { + t.Parallel() + _, err := h.GetLatestSpotPrice("btcusdt") + if err != nil { + t.Errorf("Test failed - Huobi GetLatestSpotPrice: %s", err) + } +} + func TestGetTradeHistory(t *testing.T) { t.Parallel() _, err := h.GetTradeHistory("btcusdt", "50") @@ -123,14 +167,11 @@ func TestGetTimestamp(t *testing.T) { func TestGetAccounts(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { t.Skip() } - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true - _, err := h.GetAccounts() if err != nil { t.Errorf("Test failed - Huobi GetAccounts: %s", err) @@ -139,14 +180,11 @@ func TestGetAccounts(t *testing.T) { func TestGetAccountBalance(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { t.Skip() } - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true - result, err := h.GetAccounts() if err != nil { t.Errorf("Test failed - Huobi GetAccounts: %s", err) @@ -159,39 +197,29 @@ func TestGetAccountBalance(t *testing.T) { } } -func TestPlaceOrder(t *testing.T) { +func TestSpotNewOrder(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { t.Skip() } - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true - - _, err := h.GetAccounts() - if err != nil { - t.Errorf("Test failed - Huobi GetAccounts: %s", err) + arg := SpotNewOrderRequestParams{ + Symbol: "btcusdt", + AccountID: 000000, + Amount: 0.01, + Price: 10.1, + Type: SpotNewOrderRequestTypeBuyLimit, } - /* - userID := strconv.FormatInt(result[0].ID, 10) - _, err = h.PlaceOrder("ethusdt", "api", userID, "buy-limit", 10.1, 100.1) - if err != nil { - t.Errorf("Test failed - Huobi TestPlaceOrder: %s", err) - } - */ + _, err := h.SpotNewOrder(arg) + if err != nil { + t.Errorf("Test failed - Huobi SpotNewOrder: %s", err) + } } func TestCancelOrder(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { - t.Skip() - } - - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true _, err := h.CancelOrder(1337) if err == nil { @@ -201,13 +229,7 @@ func TestCancelOrder(t *testing.T) { func TestGetOrder(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { - t.Skip() - } - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true _, err := h.GetOrder(1337) if err == nil { t.Error("Test failed - Huobi TestCancelOrder: Invalid orderID returned true") @@ -216,13 +238,11 @@ func TestGetOrder(t *testing.T) { func TestGetMarginLoanOrders(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { t.Skip() } - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true _, err := h.GetMarginLoanOrders("btcusdt", "", "", "", "", "", "", "") if err != nil { t.Errorf("Test failed - Huobi TestGetMarginLoanOrders: %s", err) @@ -231,13 +251,11 @@ func TestGetMarginLoanOrders(t *testing.T) { func TestGetMarginAccountBalance(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { t.Skip() } - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true _, err := h.GetMarginAccountBalance("btcusdt") if err != nil { t.Errorf("Test failed - Huobi TestGetMarginAccountBalance: %s", err) @@ -246,13 +264,7 @@ func TestGetMarginAccountBalance(t *testing.T) { func TestCancelWithdraw(t *testing.T) { t.Parallel() - if apiKey == "" && apiSecret == "" { - t.Skip() - } - h.APIKey = apiKey - h.APISecret = apiSecret - h.AuthenticatedAPISupport = true _, err := h.CancelWithdraw(1337) if err == nil { t.Error("Test failed - Huobi TestCancelWithdraw: Invalid withdraw-ID was valid") diff --git a/exchanges/huobi/huobi_types.go b/exchanges/huobi/huobi_types.go index 34eee2fa..7828cdb4 100644 --- a/exchanges/huobi/huobi_types.go +++ b/exchanges/huobi/huobi_types.go @@ -11,7 +11,7 @@ type Response struct { // KlineItem stores a kline item type KlineItem struct { - ID int `json:"id"` + ID int64 `json:"id"` Open float64 `json:"open"` Close float64 `json:"close"` Low float64 `json:"low"` @@ -29,6 +29,26 @@ type DetailMerged struct { Bid []float64 `json:"bid"` } +// OrderBookDataRequestParamsType var for request param types +type OrderBookDataRequestParamsType string + +// vars for OrderBookDataRequestParamsTypes +var ( + OrderBookDataRequestParamsTypeNone = OrderBookDataRequestParamsType("") + OrderBookDataRequestParamsTypeStep0 = OrderBookDataRequestParamsType("step0") + OrderBookDataRequestParamsTypeStep1 = OrderBookDataRequestParamsType("step1") + OrderBookDataRequestParamsTypeStep2 = OrderBookDataRequestParamsType("step2") + OrderBookDataRequestParamsTypeStep3 = OrderBookDataRequestParamsType("step3") + OrderBookDataRequestParamsTypeStep4 = OrderBookDataRequestParamsType("step4") + OrderBookDataRequestParamsTypeStep5 = OrderBookDataRequestParamsType("step5") +) + +// OrderBookDataRequestParams represents Klines request data. +type OrderBookDataRequestParams struct { + Symbol string `json:"symbol"` // Required; example LTCBTC,BTCUSDT + Type OrderBookDataRequestParamsType `json:"type"` // step0, step1, step2, step3, step4, step5 (combined depth 0-5); when step0, no depth is merged +} + // Orderbook stores the orderbook data type Orderbook struct { ID int64 `json:"id"` @@ -172,3 +192,56 @@ type MarginAccountBalance struct { RiskRate string `json:"risk-rate"` List []AccountBalance `json:"list"` } + +// SpotNewOrderRequestParams holds the params required to place +// an order +type SpotNewOrderRequestParams struct { + AccountID int `json:"account-id"` // Account ID, obtained using the accounts method. Curency trades use the accountid of the ‘spot’ account; for loan asset transactions, please use the accountid of the ‘margin’ account. + Amount float64 `json:"amount"` // The limit price indicates the quantity of the order, the market price indicates how much to buy when the order is paid, and the market price indicates how much the coin is sold when the order is sold. + Price float64 `json:"price"` // Order price, market price does not use this parameter + Source string `json:"source"` // Order source, api: API call, margin-api: loan asset transaction + Symbol string `json:"symbol"` // The symbol to use; example btcusdt, bccbtc...... + Type SpotNewOrderRequestParamsType `json:"type"` // 订单类型, buy-market: 市价买, sell-market: 市价卖, buy-limit: 限价买, sell-limit: 限价卖 +} + +// SpotNewOrderRequestParamsType order type +type SpotNewOrderRequestParamsType string + +var ( + // SpotNewOrderRequestTypeBuyMarket buy market order + SpotNewOrderRequestTypeBuyMarket = SpotNewOrderRequestParamsType("buy-market") + + // SpotNewOrderRequestTypeSellMarket sell market order + SpotNewOrderRequestTypeSellMarket = SpotNewOrderRequestParamsType("sell-market") + + // SpotNewOrderRequestTypeBuyLimit buy limit order + SpotNewOrderRequestTypeBuyLimit = SpotNewOrderRequestParamsType("buy-limit") + + // SpotNewOrderRequestTypeSellLimit sell lmit order + SpotNewOrderRequestTypeSellLimit = SpotNewOrderRequestParamsType("sell-limit") +) + +//----------- + +// KlinesRequestParams represents Klines request data. +type KlinesRequestParams struct { + Symbol string // Symbol to be used; example btcusdt, bccbtc...... + Period TimeInterval // Kline time interval; 1min, 5min, 15min...... + Size int // Size; [1-2000] +} + +// TimeInterval base type +type TimeInterval string + +// TimeInterval vars +var ( + TimeIntervalMinute = TimeInterval("1min") + TimeIntervalFiveMinutes = TimeInterval("5min") + TimeIntervalFifteenMinutes = TimeInterval("15min") + TimeIntervalThirtyMinutes = TimeInterval("30min") + TimeIntervalHour = TimeInterval("60min") + TimeIntervalDay = TimeInterval("1day") + TimeIntervalWeek = TimeInterval("1week") + TimeIntervalMohth = TimeInterval("1mon") + TimeIntervalYear = TimeInterval("1year") +) diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index bf5659c4..c4e9368f 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -122,7 +122,10 @@ func (h *HUOBI) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orderbook // UpdateOrderbook updates and returns the orderbook for a currency pair func (h *HUOBI) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) { var orderBook orderbook.Base - orderbookNew, err := h.GetDepth(exchange.FormatExchangeCurrency(h.Name, p).String(), "step1") + orderbookNew, err := h.GetDepth(OrderBookDataRequestParams{ + Symbol: exchange.FormatExchangeCurrency(h.Name, p).String(), + Type: OrderBookDataRequestParamsTypeStep1, + }) if err != nil { return orderBook, err } diff --git a/exchanges/huobihadax/huobihadax.go b/exchanges/huobihadax/huobihadax.go new file mode 100644 index 00000000..caef7e77 --- /dev/null +++ b/exchanges/huobihadax/huobihadax.go @@ -0,0 +1,796 @@ +package huobihadax + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "log" + "net/url" + "strconv" + "time" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" + "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/request" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +const ( + huobihadaxAPIURL = "https://api.hadax.com" + huobihadaxAPIVersion = "1" + + huobihadaxMarketHistoryKline = "market/history/kline" + huobihadaxMarketDetail = "market/detail" + huobihadaxMarketDetailMerged = "market/detail/merged" + huobihadaxMarketDepth = "market/depth" + huobihadaxMarketTrade = "market/trade" + huobihadaxMarketTradeHistory = "market/history/trade" + huobihadaxSymbols = "common/symbols" + huobihadaxCurrencies = "common/currencys" + huobihadaxTimestamp = "common/timestamp" + huobihadaxAccounts = "account/accounts" + huobihadaxAccountBalance = "account/accounts/%s/balance" + huobihadaxOrderPlace = "order/orders/place" + huobihadaxOrderCancel = "order/orders/%s/submitcancel" + huobihadaxOrderCancelBatch = "order/orders/batchcancel" + huobihadaxGetOrder = "order/orders/%s" + huobihadaxGetOrderMatch = "order/orders/%s/matchresults" + huobihadaxGetOrders = "order/orders" + huobihadaxGetOrdersMatch = "orders/matchresults" + huobihadaxMarginTransferIn = "dw/transfer-in/margin" + huobihadaxMarginTransferOut = "dw/transfer-out/margin" + huobihadaxMarginOrders = "margin/orders" + huobihadaxMarginRepay = "margin/orders/%s/repay" + huobihadaxMarginLoanOrders = "margin/loan-orders" + huobihadaxMarginAccountBalance = "margin/accounts/balance" + huobihadaxWithdrawCreate = "dw/withdraw/api/create" + huobihadaxWithdrawCancel = "dw/withdraw-virtual/%s/cancel" + + huobihadaxAuthRate = 100 + huobihadaxUnauthRate = 100 +) + +// HUOBIHADAX is the overarching type across this package +type HUOBIHADAX struct { + exchange.Base +} + +// SetDefaults sets default values for the exchange +func (h *HUOBIHADAX) SetDefaults() { + h.Name = "HuobiHadax" + h.Enabled = false + h.Fee = 0 + h.Verbose = false + h.Websocket = false + h.RESTPollingDelay = 10 + h.RequestCurrencyPairFormat.Delimiter = "" + h.RequestCurrencyPairFormat.Uppercase = false + h.ConfigCurrencyPairFormat.Delimiter = "-" + h.ConfigCurrencyPairFormat.Uppercase = true + h.AssetTypes = []string{ticker.Spot} + h.SupportsAutoPairUpdating = true + h.SupportsRESTTickerBatching = false + h.Requester = request.New(h.Name, request.NewRateLimit(time.Second*10, huobihadaxAuthRate), request.NewRateLimit(time.Second*10, huobihadaxUnauthRate), common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout)) +} + +// Setup sets user configuration +func (h *HUOBIHADAX) Setup(exch config.ExchangeConfig) { + if !exch.Enabled { + h.SetEnabled(false) + } else { + h.Enabled = true + h.AuthenticatedAPISupport = exch.AuthenticatedAPISupport + h.SetAPIKeys(exch.APIKey, exch.APISecret, "", false) + h.APIAuthPEMKey = exch.APIAuthPEMKey + h.SetHTTPClientTimeout(exch.HTTPTimeout) + h.RESTPollingDelay = exch.RESTPollingDelay + h.Verbose = exch.Verbose + h.Websocket = exch.Websocket + 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) + } + err = h.SetAssetTypes() + if err != nil { + log.Fatal(err) + } + err = h.SetAutoPairDefaults() + if err != nil { + log.Fatal(err) + } + } +} + +// GetFee returns Huobi fee +func (h *HUOBIHADAX) GetFee() float64 { + return h.Fee +} + +// GetSpotKline returns kline data +// KlinesRequestParams holds the Kline request params +func (h *HUOBIHADAX) GetSpotKline(arg KlinesRequestParams) ([]KlineItem, error) { + vals := url.Values{} + vals.Set("symbol", arg.Symbol) + vals.Set("period", string(arg.Period)) + + if arg.Size != 0 { + vals.Set("size", strconv.Itoa(arg.Size)) + } + + type response struct { + Response + Data []KlineItem `json:"data"` + } + + var result response + url := fmt.Sprintf("%s/%s", huobihadaxAPIURL, huobihadaxMarketHistoryKline) + + err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result) + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Data, err +} + +// GetMarketDetailMerged returns the ticker for the specified symbol +func (h *HUOBIHADAX) GetMarketDetailMerged(symbol string) (DetailMerged, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + + type response struct { + Response + Tick DetailMerged `json:"tick"` + } + + var result response + url := fmt.Sprintf("%s/%s", huobihadaxAPIURL, huobihadaxMarketDetailMerged) + + err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result) + if result.ErrorMessage != "" { + return result.Tick, errors.New(result.ErrorMessage) + } + return result.Tick, err +} + +// GetDepth returns the depth for the specified symbol +func (h *HUOBIHADAX) GetDepth(symbol, depthType string) (Orderbook, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + + if depthType != "" { + vals.Set("type", depthType) + } + + type response struct { + Response + Depth Orderbook `json:"tick"` + } + + var result response + url := fmt.Sprintf("%s/%s", huobihadaxAPIURL, huobihadaxMarketDepth) + + err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result) + if result.ErrorMessage != "" { + return result.Depth, errors.New(result.ErrorMessage) + } + return result.Depth, err +} + +// GetTrades returns the trades for the specified symbol +func (h *HUOBIHADAX) GetTrades(symbol string) ([]Trade, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + + type response struct { + Response + Tick struct { + Data []Trade `json:"data"` + } `json:"tick"` + } + + var result response + url := fmt.Sprintf("%s/%s", huobihadaxAPIURL, huobihadaxMarketTrade) + + err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result) + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Tick.Data, err +} + +// GetLatestSpotPrice returns latest spot price of symbol +// +// symbol: string of currency pair +func (h *HUOBIHADAX) GetLatestSpotPrice(symbol string) (float64, error) { + list, err := h.GetTradeHistory(symbol, "1") + + if err != nil { + return 0, err + } + if len(list) == 0 { + return 0, errors.New("The length of the list is 0") + } + + return list[0].Trades[0].Price, nil +} + +// GetTradeHistory returns the trades for the specified symbol +func (h *HUOBIHADAX) GetTradeHistory(symbol, size string) ([]TradeHistory, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + + if size != "" { + vals.Set("size", size) + } + + type response struct { + Response + TradeHistory []TradeHistory `json:"data"` + } + + var result response + url := fmt.Sprintf("%s/%s", huobihadaxAPIURL, huobihadaxMarketTradeHistory) + + err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result) + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.TradeHistory, err +} + +// GetMarketDetail returns the ticker for the specified symbol +func (h *HUOBIHADAX) GetMarketDetail(symbol string) (Detail, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + + type response struct { + Response + Tick Detail `json:"tick"` + } + + var result response + url := fmt.Sprintf("%s/%s", huobihadaxAPIURL, huobihadaxMarketDetail) + + err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result) + if result.ErrorMessage != "" { + return result.Tick, errors.New(result.ErrorMessage) + } + return result.Tick, err +} + +// GetSymbols returns an array of symbols supported by Huobi +func (h *HUOBIHADAX) GetSymbols() ([]Symbol, error) { + type response struct { + Response + Symbols []Symbol `json:"data"` + } + + var result response + url := fmt.Sprintf("%s/v%s/%s", huobihadaxAPIURL, huobihadaxAPIVersion, huobihadaxSymbols) + + err := h.SendHTTPRequest(url, &result) + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Symbols, err +} + +// GetCurrencies returns a list of currencies supported by Huobi +func (h *HUOBIHADAX) GetCurrencies() ([]string, error) { + type response struct { + Response + Currencies []string `json:"data"` + } + + var result response + url := fmt.Sprintf("%s/v%s/%s", huobihadaxAPIURL, huobihadaxAPIVersion, huobihadaxCurrencies) + + err := h.SendHTTPRequest(url, &result) + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Currencies, err +} + +// GetTimestamp returns the Huobi server time +func (h *HUOBIHADAX) GetTimestamp() (int64, error) { + type response struct { + Response + Timestamp int64 `json:"data"` + } + + var result response + url := fmt.Sprintf("%s/v%s/%s", huobihadaxAPIURL, huobihadaxAPIVersion, huobihadaxTimestamp) + + err := h.SendHTTPRequest(url, &result) + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.Timestamp, err +} + +// GetAccounts returns the Huobi user accounts +func (h *HUOBIHADAX) GetAccounts() ([]Account, error) { + type response struct { + Response + AccountData []Account `json:"data"` + } + + var result response + err := h.SendAuthenticatedHTTPRequest("GET", huobihadaxAccounts, url.Values{}, &result) + + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.AccountData, err +} + +// GetAccountBalance returns the users Huobi account balance +func (h *HUOBIHADAX) GetAccountBalance(accountID string) ([]AccountBalanceDetail, error) { + type response struct { + Response + AccountBalanceData AccountBalance `json:"data"` + } + + var result response + endpoint := fmt.Sprintf(huobihadaxAccountBalance, accountID) + err := h.SendAuthenticatedHTTPRequest("GET", endpoint, url.Values{}, &result) + + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.AccountBalanceData.AccountBalanceDetails, err +} + +// SpotNewOrder submits an order to Huobi +func (h *HUOBIHADAX) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) { + vals := make(map[string]string) + vals["account-id"] = fmt.Sprintf("%d", arg.AccountID) + vals["amount"] = strconv.FormatFloat(arg.Amount, 'f', -1, 64) + + // Only set price if order type is not equal to buy-market or sell-market + if arg.Type != SpotNewOrderRequestTypeBuyMarket && arg.Type != SpotNewOrderRequestTypeSellMarket { + vals["price"] = strconv.FormatFloat(arg.Price, 'f', -1, 64) + } + + if arg.Source != "" { + vals["source"] = arg.Source + } + + vals["symbol"] = arg.Symbol + vals["type"] = string(arg.Type) + + type response struct { + Response + OrderID int64 `json:"data,string"` + } + + // The API indicates that for the POST request, the parameters of each method are not signed and authenticated. That is, only the AccessKeyId, SignatureMethod, SignatureVersion, and Timestamp parameters are required for the POST request. The other parameters are placed in the body. + // So re-encode the Post parameter + bytesParams, _ := json.Marshal(vals) + postBodyParams := string(bytesParams) + if h.Verbose { + fmt.Println("Post params:", postBodyParams) + } + + var result response + err := h.SendAuthenticatedHTTPPostRequest("POST", huobihadaxOrderPlace, postBodyParams, &result) + + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.OrderID, err +} + +// CancelOrder cancels an order on Huobi +func (h *HUOBIHADAX) CancelOrder(orderID int64) (int64, error) { + type response struct { + Response + OrderID int64 `json:"data,string"` + } + + var result response + endpoint := fmt.Sprintf(huobihadaxOrderCancel, strconv.FormatInt(orderID, 10)) + err := h.SendAuthenticatedHTTPRequest("POST", endpoint, url.Values{}, &result) + + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.OrderID, err +} + +// CancelOrderBatch cancels a batch of orders -- to-do +func (h *HUOBIHADAX) CancelOrderBatch(orderIDs []int64) (CancelOrderBatch, error) { + type response struct { + Status string `json:"status"` + Data CancelOrderBatch `json:"data"` + } + + // Used to send param formatting + type postBody struct { + List []int64 `json:"order-ids"` + } + + // Format to JSON + bytesParams, _ := common.JSONEncode(&postBody{List: orderIDs}) + postBodyParams := string(bytesParams) + + var result response + err := h.SendAuthenticatedHTTPPostRequest("POST", huobihadaxOrderCancelBatch, postBodyParams, &result) + + if len(result.Data.Failed) != 0 { + errJSON, _ := common.JSONEncode(result.Data.Failed) + return CancelOrderBatch{}, errors.New(string(errJSON)) + } + return result.Data, err +} + +// GetOrder returns order information for the specified order +func (h *HUOBIHADAX) GetOrder(orderID int64) (OrderInfo, error) { + type response struct { + Response + Order OrderInfo `json:"data"` + } + + var result response + endpoint := fmt.Sprintf(huobihadaxGetOrder, strconv.FormatInt(orderID, 10)) + err := h.SendAuthenticatedHTTPRequest("GET", endpoint, url.Values{}, &result) + + if result.ErrorMessage != "" { + return result.Order, errors.New(result.ErrorMessage) + } + return result.Order, err +} + +// GetOrderMatchResults returns matched order info for the specified order +func (h *HUOBIHADAX) GetOrderMatchResults(orderID int64) ([]OrderMatchInfo, error) { + type response struct { + Response + Orders []OrderMatchInfo `json:"data"` + } + + var result response + endpoint := fmt.Sprintf(huobihadaxGetOrderMatch, strconv.FormatInt(orderID, 10)) + err := h.SendAuthenticatedHTTPRequest("GET", endpoint, url.Values{}, &result) + + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Orders, err +} + +// GetOrders returns a list of orders +func (h *HUOBIHADAX) GetOrders(symbol, types, start, end, states, from, direct, size string) ([]OrderInfo, error) { + type response struct { + Response + Orders []OrderInfo `json:"data"` + } + + vals := url.Values{} + vals.Set("symbol", symbol) + vals.Set("states", states) + + if types != "" { + vals.Set("types", types) + } + + if start != "" { + vals.Set("start-date", start) + } + + if end != "" { + vals.Set("end-date", end) + } + + if from != "" { + vals.Set("from", from) + } + + if direct != "" { + vals.Set("direct", direct) + } + + if size != "" { + vals.Set("size", size) + } + + var result response + err := h.SendAuthenticatedHTTPRequest("GET", huobihadaxGetOrders, vals, &result) + + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Orders, err +} + +// GetOrdersMatch returns a list of matched orders +func (h *HUOBIHADAX) GetOrdersMatch(symbol, types, start, end, from, direct, size string) ([]OrderMatchInfo, error) { + type response struct { + Response + Orders []OrderMatchInfo `json:"data"` + } + + vals := url.Values{} + vals.Set("symbol", symbol) + + if types != "" { + vals.Set("types", types) + } + + if start != "" { + vals.Set("start-date", start) + } + + if end != "" { + vals.Set("end-date", end) + } + + if from != "" { + vals.Set("from", from) + } + + if direct != "" { + vals.Set("direct", direct) + } + + if size != "" { + vals.Set("size", size) + } + + var result response + err := h.SendAuthenticatedHTTPRequest("GET", huobihadaxGetOrdersMatch, vals, &result) + + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Orders, err +} + +// MarginTransfer transfers assets into or out of the margin account +func (h *HUOBIHADAX) MarginTransfer(symbol, currency string, amount float64, in bool) (int64, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + vals.Set("currency", currency) + vals.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) + + path := huobihadaxMarginTransferIn + if !in { + path = huobihadaxMarginTransferOut + } + + type response struct { + Response + TransferID int64 `json:"data"` + } + + var result response + err := h.SendAuthenticatedHTTPRequest("POST", path, vals, &result) + + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.TransferID, err +} + +// MarginOrder submits a margin order application +func (h *HUOBIHADAX) MarginOrder(symbol, currency string, amount float64) (int64, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + vals.Set("currency", currency) + vals.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) + + type response struct { + Response + MarginOrderID int64 `json:"data"` + } + + var result response + err := h.SendAuthenticatedHTTPRequest("POST", huobihadaxMarginOrders, vals, &result) + + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.MarginOrderID, err +} + +// MarginRepayment repays a margin amount for a margin ID +func (h *HUOBIHADAX) MarginRepayment(orderID int64, amount float64) (int64, error) { + vals := url.Values{} + vals.Set("order-id", strconv.FormatInt(orderID, 10)) + vals.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) + + type response struct { + Response + MarginOrderID int64 `json:"data"` + } + + var result response + endpoint := fmt.Sprintf(huobihadaxMarginRepay, strconv.FormatInt(orderID, 10)) + err := h.SendAuthenticatedHTTPRequest("POST", endpoint, vals, &result) + + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.MarginOrderID, err +} + +// GetMarginLoanOrders returns the margin loan orders +func (h *HUOBIHADAX) GetMarginLoanOrders(symbol, currency, start, end, states, from, direct, size string) ([]MarginOrder, error) { + vals := url.Values{} + vals.Set("symbol", symbol) + vals.Set("currency", currency) + + if start != "" { + vals.Set("start-date", start) + } + + if end != "" { + vals.Set("end-date", end) + } + + if states != "" { + vals.Set("states", states) + } + + if from != "" { + vals.Set("from", from) + } + + if direct != "" { + vals.Set("direct", direct) + } + + if size != "" { + vals.Set("size", size) + } + + type response struct { + Response + MarginLoanOrders []MarginOrder `json:"data"` + } + + var result response + err := h.SendAuthenticatedHTTPRequest("GET", huobihadaxMarginLoanOrders, vals, &result) + + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.MarginLoanOrders, err +} + +// GetMarginAccountBalance returns the margin account balances +func (h *HUOBIHADAX) GetMarginAccountBalance(symbol string) ([]MarginAccountBalance, error) { + type response struct { + Response + Balances []MarginAccountBalance `json:"data"` + } + + vals := url.Values{} + if symbol != "" { + vals.Set("symbol", symbol) + } + + var result response + err := h.SendAuthenticatedHTTPRequest("GET", huobihadaxMarginAccountBalance, vals, &result) + + if result.ErrorMessage != "" { + return nil, errors.New(result.ErrorMessage) + } + return result.Balances, err +} + +// Withdraw withdraws the desired amount and currency +func (h *HUOBIHADAX) Withdraw(address, currency, addrTag string, amount, fee float64) (int64, error) { + type response struct { + Response + WithdrawID int64 `json:"data"` + } + + vals := url.Values{} + vals.Set("address", address) + vals.Set("currency", currency) + vals.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) + + if fee != 0 { + vals.Set("fee", strconv.FormatFloat(fee, 'f', -1, 64)) + } + + if currency == "XRP" { + vals.Set("addr-tag", addrTag) + } + + var result response + err := h.SendAuthenticatedHTTPRequest("POST", huobihadaxWithdrawCreate, vals, &result) + + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.WithdrawID, err +} + +// CancelWithdraw cancels a withdraw request +func (h *HUOBIHADAX) CancelWithdraw(withdrawID int64) (int64, error) { + type response struct { + Response + WithdrawID int64 `json:"data"` + } + + vals := url.Values{} + vals.Set("withdraw-id", strconv.FormatInt(withdrawID, 10)) + + var result response + endpoint := fmt.Sprintf(huobihadaxWithdrawCancel, strconv.FormatInt(withdrawID, 10)) + err := h.SendAuthenticatedHTTPRequest("POST", endpoint, vals, &result) + + if result.ErrorMessage != "" { + return 0, errors.New(result.ErrorMessage) + } + return result.WithdrawID, err +} + +// SendHTTPRequest sends an unauthenticated HTTP request +func (h *HUOBIHADAX) SendHTTPRequest(path string, result interface{}) error { + return h.SendPayload("GET", path, nil, nil, result, false, h.Verbose) +} + +// SendAuthenticatedHTTPPostRequest sends authenticated requests to the HUOBI API +func (h *HUOBIHADAX) SendAuthenticatedHTTPPostRequest(method, endpoint, postBodyValues string, result interface{}) error { + if !h.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, h.Name) + } + + signatureParams := url.Values{} + signatureParams.Set("AccessKeyId", h.APIKey) + signatureParams.Set("SignatureMethod", "HmacSHA256") + signatureParams.Set("SignatureVersion", "2") + signatureParams.Set("Timestamp", time.Now().UTC().Format("2006-01-02T15:04:05")) + + endpoint = fmt.Sprintf("/v%s/%s", huobihadaxAPIVersion, endpoint) + payload := fmt.Sprintf("%s\napi.huobi.pro\n%s\n%s", + method, endpoint, signatureParams.Encode()) + + headers := make(map[string]string) + headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36" + headers["Content-Type"] = "application/json" + headers["Accept-Language"] = "zh-cn" + + hmac := common.GetHMAC(common.HashSHA256, []byte(payload), []byte(h.APISecret)) + signatureParams.Set("Signature", common.Base64Encode(hmac)) + + url := fmt.Sprintf("%s%s", huobihadaxAPIURL, endpoint) + url = common.EncodeURLValues(url, signatureParams) + + return h.SendPayload(method, url, headers, bytes.NewBufferString(postBodyValues), result, true, h.Verbose) +} + +// SendAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API +func (h *HUOBIHADAX) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error { + if !h.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, h.Name) + } + + values.Set("AccessKeyId", h.APIKey) + values.Set("SignatureMethod", "HmacSHA256") + values.Set("SignatureVersion", "2") + values.Set("Timestamp", time.Now().UTC().Format("2006-01-02T15:04:05")) + + endpoint = fmt.Sprintf("/v%s/%s", huobihadaxAPIVersion, endpoint) + payload := fmt.Sprintf("%s\napi.huobi.pro\n%s\n%s", + method, endpoint, values.Encode()) + + headers := make(map[string]string) + headers["Content-Type"] = "application/x-www-form-urlencoded" + + hmac := common.GetHMAC(common.HashSHA256, []byte(payload), []byte(h.APISecret)) + values.Set("Signature", common.Base64Encode(hmac)) + + url := fmt.Sprintf("%s%s", huobihadaxAPIURL, endpoint) + url = common.EncodeURLValues(url, values) + + return h.SendPayload(method, url, headers, bytes.NewBufferString(""), result, true, h.Verbose) +} diff --git a/exchanges/huobihadax/huobihadax_test.go b/exchanges/huobihadax/huobihadax_test.go new file mode 100644 index 00000000..94552450 --- /dev/null +++ b/exchanges/huobihadax/huobihadax_test.go @@ -0,0 +1,277 @@ +package huobihadax + +import ( + "fmt" + "strconv" + "testing" + + "github.com/thrasher-/gocryptotrader/config" +) + +// Please supply your own APIKEYS here for due diligence testing + +const ( + apiKey = "" + apiSecret = "" +) + +var h HUOBIHADAX + +// getDefaultConfig returns a default huobi config +func getDefaultConfig() config.ExchangeConfig { + return config.ExchangeConfig{ + Name: "huobihadax", + Enabled: true, + Verbose: true, + Websocket: false, + UseSandbox: false, + RESTPollingDelay: 10, + HTTPTimeout: 15000000000, + AuthenticatedAPISupport: true, + APIKey: "", + APISecret: "", + ClientID: "", + AvailablePairs: "BTC-USDT,BCH-USDT", + EnabledPairs: "BTC-USDT", + BaseCurrencies: "USD", + AssetTypes: "SPOT", + SupportsAutoPairUpdates: false, + ConfigCurrencyPairFormat: &config.CurrencyPairFormatConfig{ + Uppercase: true, + Delimiter: "-", + }, + RequestCurrencyPairFormat: &config.CurrencyPairFormatConfig{ + Uppercase: false, + }, + } +} + +func TestSetDefaults(t *testing.T) { + h.SetDefaults() +} + +func TestSetup(t *testing.T) { + cfg := config.GetConfig() + cfg.LoadConfig("../../testdata/configtest.json") + hadaxConfig, err := cfg.GetExchangeConfig("HuobiHadax") + if err != nil { + t.Error("Test Failed - HuobiHadax Setup() init error") + } + + hadaxConfig.AuthenticatedAPISupport = true + hadaxConfig.APIKey = apiKey + hadaxConfig.APISecret = apiSecret + + h.Setup(hadaxConfig) +} + +func TestGetFee(t *testing.T) { + t.Parallel() + if h.GetFee() != 0 { + t.Errorf("test failed - Huobi GetFee() error") + } +} + +func TestGetSpotKline(t *testing.T) { + t.Parallel() + _, err := h.GetSpotKline(KlinesRequestParams{ + Symbol: "btcusdt", + Period: TimeIntervalHour, + Size: 0, + }) + if err != nil { + t.Errorf("Test failed - Huobi TestGetSpotKline: %s", err) + } +} + +func TestGetMarketDetailMerged(t *testing.T) { + t.Parallel() + _, err := h.GetMarketDetailMerged("btcusdt") + if err != nil { + t.Errorf("Test failed - Huobi TestGetMarketDetailMerged: %s", err) + } +} + +func TestGetDepth(t *testing.T) { + t.Parallel() + _, err := h.GetDepth("btcusdt", "step1") + if err != nil { + t.Errorf("Test failed - Huobi TestGetDepth: %s", err) + } +} + +func TestGetTrades(t *testing.T) { + t.Parallel() + _, err := h.GetTrades("btcusdt") + if err != nil { + t.Errorf("Test failed - Huobi TestGetTrades: %s", err) + } +} + +func TestGetLatestSpotPrice(t *testing.T) { + t.Parallel() + _, err := h.GetLatestSpotPrice("btcusdt") + if err != nil { + t.Errorf("Test failed - Huobi GetLatestSpotPrice: %s", err) + } +} + +func TestGetTradeHistory(t *testing.T) { + t.Parallel() + _, err := h.GetTradeHistory("btcusdt", "50") + if err != nil { + t.Errorf("Test failed - Huobi TestGetTradeHistory: %s", err) + } +} + +func TestGetMarketDetail(t *testing.T) { + t.Parallel() + _, err := h.GetMarketDetail("btcusdt") + if err != nil { + t.Errorf("Test failed - Huobi TestGetTradeHistory: %s", err) + } +} + +func TestGetSymbols(t *testing.T) { + t.Parallel() + _, err := h.GetSymbols() + if err != nil { + t.Errorf("Test failed - Huobi TestGetSymbols: %s", err) + } +} + +func TestGetCurrencies(t *testing.T) { + t.Parallel() + _, err := h.GetCurrencies() + if err != nil { + t.Errorf("Test failed - Huobi TestGetCurrencies: %s", err) + } +} + +func TestGetTimestamp(t *testing.T) { + t.Parallel() + _, err := h.GetTimestamp() + if err != nil { + t.Errorf("Test failed - Huobi TestGetTimestamp: %s", err) + } +} + +func TestGetAccounts(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + _, err := h.GetAccounts() + if err != nil { + t.Errorf("Test failed - Huobi GetAccounts: %s", err) + } +} + +func TestGetAccountBalance(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + result, err := h.GetAccounts() + if err != nil { + t.Errorf("Test failed - Huobi GetAccounts: %s", err) + } + + userID := strconv.FormatInt(result[0].ID, 10) + _, err = h.GetAccountBalance(userID) + if err != nil { + t.Errorf("Test failed - Huobi GetAccountBalance: %s", err) + } +} + +func TestSpotNewOrder(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + arg := SpotNewOrderRequestParams{ + Symbol: "btcusdt", + AccountID: 000000, + Amount: 0.01, + Price: 10.1, + Type: SpotNewOrderRequestTypeBuyLimit, + } + + newOrderID, err := h.SpotNewOrder(arg) + if err != nil { + t.Errorf("Test failed - Huobi SpotNewOrder: %s", err) + } else { + fmt.Println(newOrderID) + } +} + +func TestCancelOrder(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + _, err := h.CancelOrder(1337) + if err == nil { + t.Error("Test failed - Huobi TestCancelOrder: Invalid orderID returned true") + } +} + +func TestGetOrder(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + _, err := h.GetOrder(1337) + if err == nil { + t.Error("Test failed - Huobi TestCancelOrder: Invalid orderID returned true") + } +} + +func TestGetMarginLoanOrders(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + _, err := h.GetMarginLoanOrders("btcusdt", "", "", "", "", "", "", "") + if err != nil { + t.Errorf("Test failed - Huobi TestGetMarginLoanOrders: %s", err) + } +} + +func TestGetMarginAccountBalance(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + _, err := h.GetMarginAccountBalance("btcusdt") + if err != nil { + t.Errorf("Test failed - Huobi TestGetMarginAccountBalance: %s", err) + } +} + +func TestCancelWithdraw(t *testing.T) { + t.Parallel() + + if h.APIKey == "" || h.APISecret == "" || h.APIAuthPEMKey == "" { + t.Skip() + } + + _, err := h.CancelWithdraw(1337) + if err == nil { + t.Error("Test failed - Huobi TestCancelWithdraw: Invalid withdraw-ID was valid") + } +} diff --git a/exchanges/huobihadax/huobihadax_types.go b/exchanges/huobihadax/huobihadax_types.go new file mode 100644 index 00000000..8ee867f6 --- /dev/null +++ b/exchanges/huobihadax/huobihadax_types.go @@ -0,0 +1,225 @@ +package huobihadax + +// Response stores the Huobi response information +type Response struct { + Status string `json:"status"` + Channel string `json:"ch"` + Timestamp int64 `json:"ts"` + ErrorCode string `json:"err-code"` + ErrorMessage string `json:"err-msg"` +} + +// KlineItem stores a kline item +type KlineItem struct { + ID int64 `json:"id"` + Open float64 `json:"open"` + Close float64 `json:"close"` + Low float64 `json:"low"` + High float64 `json:"high"` + Amount float64 `json:"amount"` + Vol float64 `json:"vol"` + Count int `json:"count"` +} + +// DetailMerged stores the ticker detail merged data +type DetailMerged struct { + Detail + Version int `json:"version"` + Ask []float64 `json:"ask"` + Bid []float64 `json:"bid"` +} + +// Orderbook stores the orderbook data +type Orderbook struct { + ID int64 `json:"id"` + Timetstamp int64 `json:"ts"` + Bids [][]float64 `json:"bids"` + Asks [][]float64 `json:"asks"` +} + +// Trade stores the trade data +type Trade struct { + ID float64 `json:"id"` + Price float64 `json:"price"` + Amount float64 `json:"amount"` + Direction string `json:"direction"` + Timestamp int64 `json:"ts"` +} + +// TradeHistory stores the the trade history data +type TradeHistory struct { + ID int64 `json:"id"` + Timestamp int64 `json:"ts"` + Trades []Trade `json:"data"` +} + +// Detail stores the ticker detail data +type Detail struct { + Amount float64 `json:"amount"` + Open float64 `json:"open"` + Close float64 `json:"close"` + High float64 `json:"high"` + Timestamp int64 `json:"timestamp"` + ID int `json:"id"` + Count int `json:"count"` + Low float64 `json:"low"` + Volume float64 `json:"vol"` +} + +// Symbol stores the symbol data +type Symbol struct { + BaseCurrency string `json:"base-currency"` + QuoteCurrency string `json:"quote-currency"` + PricePrecision int `json:"price-precision"` + AmountPrecision int `json:"amount-precision"` + SymbolPartition string `json:"symbol-partition"` +} + +// Account stores the account data +type Account struct { + ID int64 `json:"id"` + Type string `json:"type"` + State string `json:"working"` + UserID int64 `json:"user-id"` +} + +// AccountBalance stores the user all account balance +type AccountBalance struct { + ID int64 `json:"id"` + Type string `json:"type"` + State string `json:"state"` + AccountBalanceDetails []AccountBalanceDetail `json:"list"` +} + +// AccountBalanceDetail stores the user account balance +type AccountBalanceDetail struct { + Currency string `json:"currency"` + Type string `json:"type"` + Balance float64 `json:"balance,string"` +} + +// CancelOrderBatch stores the cancel order batch data +type CancelOrderBatch struct { + Success []string `json:"success"` + Failed []struct { + OrderID int64 `json:"order-id,string"` + ErrorCode string `json:"err-code"` + ErrorMessage string `json:"err-msg"` + } `json:"failed"` +} + +// OrderInfo stores the order info +type OrderInfo struct { + ID int `json:"id"` + Symbol string `json:"symbol"` + AccountID int `json:"account-id"` + Amount string `json:"amount"` + Price string `json:"price"` + CreatedAt int64 `json:"created-at"` + Type string `json:"type"` + FieldAmount string `json:"field-amount"` + FieldCashAmount string `json:"field-cash-amount"` + FieldFees string `json:"field-fees"` + FinishedAt int64 `json:"finished-at"` + UserID int `json:"user-id"` + Source string `json:"source"` + State string `json:"state"` + CanceledAt int `json:"canceled-at"` + Exchange string `json:"exchange"` + Batch string `json:"batch"` +} + +// OrderMatchInfo stores the order match info +type OrderMatchInfo struct { + ID int `json:"id"` + OrderID int `json:"order-id"` + MatchID int `json:"match-id"` + Symbol string `json:"symbol"` + Type string `json:"type"` + Source string `json:"source"` + Price string `json:"price"` + FilledAmount string `json:"filled-amount"` + FilledFees string `json:"filled-fees"` + CreatedAt int64 `json:"created-at"` +} + +// MarginOrder stores the margin order info +type MarginOrder struct { + Currency string `json:"currency"` + Symbol string `json:"symbol"` + AccruedAt int64 `json:"accrued-at"` + LoanAmount string `json:"loan-amount"` + LoanBalance string `json:"loan-balance"` + InterestBalance string `json:"interest-balance"` + CreatedAt int64 `json:"created-at"` + InterestAmount string `json:"interest-amount"` + InterestRate string `json:"interest-rate"` + AccountID int `json:"account-id"` + UserID int `json:"user-id"` + UpdatedAt int64 `json:"updated-at"` + ID int `json:"id"` + State string `json:"state"` +} + +// MarginAccountBalance stores the margin account balance info +type MarginAccountBalance struct { + ID int `json:"id"` + Type string `json:"type"` + State string `json:"state"` + Symbol string `json:"symbol"` + FlPrice string `json:"fl-price"` + FlType string `json:"fl-type"` + RiskRate string `json:"risk-rate"` + List []AccountBalance `json:"list"` +} + +// SpotNewOrderRequestParams holds the params required to place +// an order +type SpotNewOrderRequestParams struct { + AccountID int `json:"account-id"` // Account ID, obtained using the accounts method. Curency trades use the accountid of the ‘spot’ account; for loan asset transactions, please use the accountid of the ‘margin’ account. + Amount float64 `json:"amount"` // The limit price indicates the quantity of the order, the market price indicates how much to buy when the order is paid, and the market price indicates how much the coin is sold when the order is sold. + Price float64 `json:"price"` // Order price, market price does not use this parameter + Source string `json:"source"` // Order source, api: API call, margin-api: loan asset transaction + Symbol string `json:"symbol"` // The symbol to use; example btcusdt, bccbtc...... + Type SpotNewOrderRequestParamsType `json:"type"` // Order type as listed below (buy-market, sell-market etc) +} + +// SpotNewOrderRequestParamsType order types +type SpotNewOrderRequestParamsType string + +var ( + // SpotNewOrderRequestTypeBuyMarket buy market order + SpotNewOrderRequestTypeBuyMarket = SpotNewOrderRequestParamsType("buy-market") + + // SpotNewOrderRequestTypeSellMarket sell market order + SpotNewOrderRequestTypeSellMarket = SpotNewOrderRequestParamsType("sell-market") + + // SpotNewOrderRequestTypeBuyLimit buy limit order + SpotNewOrderRequestTypeBuyLimit = SpotNewOrderRequestParamsType("buy-limit") + + // SpotNewOrderRequestTypeSellLimit sell limit order + SpotNewOrderRequestTypeSellLimit = SpotNewOrderRequestParamsType("sell-limit") +) + +// KlinesRequestParams represents Klines request data. +type KlinesRequestParams struct { + Symbol string // Symbol; btcusdt, bccbtc...... + Period TimeInterval // Kline data time interval; 1min, 5min, 15min...... + Size int // Size [1-2000] +} + +// TimeInterval base value +type TimeInterval string + +// TimeInterval vars +var ( + TimeIntervalMinute = TimeInterval("1min") + TimeIntervalFiveMinutes = TimeInterval("5min") + TimeIntervalFifteenMinutes = TimeInterval("15min") + TimeIntervalThirtyMinutes = TimeInterval("30min") + TimeIntervalHour = TimeInterval("60min") + TimeIntervalDay = TimeInterval("1day") + TimeIntervalWeek = TimeInterval("1week") + TimeIntervalMohth = TimeInterval("1mon") + TimeIntervalYear = TimeInterval("1year") +) diff --git a/exchanges/huobihadax/huobihadax_wrapper.go b/exchanges/huobihadax/huobihadax_wrapper.go new file mode 100644 index 00000000..7069581f --- /dev/null +++ b/exchanges/huobihadax/huobihadax_wrapper.go @@ -0,0 +1,178 @@ +package huobihadax + +import ( + "errors" + "log" + "sync" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/currency/pair" + "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/orderbook" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +// Start starts the OKEX go routine +func (h *HUOBIHADAX) Start(wg *sync.WaitGroup) { + wg.Add(1) + go func() { + h.Run() + wg.Done() + }() +} + +// Run implements the OKEX wrapper +func (h *HUOBIHADAX) Run() { + if h.Verbose { + log.Printf("%s Websocket: %s. (url: %s).\n", h.GetName(), common.IsEnabled(h.Websocket), h.WebsocketURL) + log.Printf("%s polling delay: %ds.\n", h.GetName(), h.RESTPollingDelay) + log.Printf("%s %d currencies enabled: %s.\n", h.GetName(), len(h.EnabledPairs), h.EnabledPairs) + } + + exchangeProducts, err := h.GetSymbols() + if err != nil { + log.Printf("%s Failed to get available symbols.\n", h.GetName()) + } else { + var currencies []string + for x := range exchangeProducts { + newCurrency := exchangeProducts[x].BaseCurrency + "-" + exchangeProducts[x].QuoteCurrency + currencies = append(currencies, newCurrency) + } + + err = h.UpdateCurrencies(currencies, false, false) + if err != nil { + log.Printf("%s Failed to update available currencies.\n", h.GetName()) + } + } +} + +// UpdateTicker updates and returns the ticker for a currency pair +func (h *HUOBIHADAX) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) { + var tickerPrice ticker.Price + tick, err := h.GetMarketDetailMerged(exchange.FormatExchangeCurrency(h.Name, p).String()) + if err != nil { + return tickerPrice, err + } + + tickerPrice.Pair = p + tickerPrice.Low = tick.Low + tickerPrice.Last = tick.Close + tickerPrice.Volume = tick.Volume + tickerPrice.High = tick.High + tickerPrice.Ask = tick.Ask[0] + tickerPrice.Bid = tick.Bid[0] + ticker.ProcessTicker(h.GetName(), p, tickerPrice, assetType) + return ticker.GetTicker(h.Name, p, assetType) +} + +// GetTickerPrice returns the ticker for a currency pair +func (h *HUOBIHADAX) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) { + tickerNew, err := ticker.GetTicker(h.GetName(), p, assetType) + if err != nil { + return h.UpdateTicker(p, assetType) + } + return tickerNew, nil +} + +// GetOrderbookEx returns orderbook base on the currency pair +func (h *HUOBIHADAX) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orderbook.Base, error) { + ob, err := orderbook.GetOrderbook(h.GetName(), p, assetType) + if err != nil { + return h.UpdateOrderbook(p, assetType) + } + return ob, nil +} + +// UpdateOrderbook updates and returns the orderbook for a currency pair +func (h *HUOBIHADAX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) { + var orderBook orderbook.Base + orderbookNew, err := h.GetDepth(exchange.FormatExchangeCurrency(h.Name, p).String(), "step1") + if err != nil { + return orderBook, err + } + + for x := range orderbookNew.Bids { + data := orderbookNew.Bids[x] + orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data[1], Price: data[0]}) + } + + for x := range orderbookNew.Asks { + data := orderbookNew.Asks[x] + orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data[1], Price: data[0]}) + } + + orderbook.ProcessOrderbook(h.GetName(), p, orderBook, assetType) + return orderbook.GetOrderbook(h.Name, p, assetType) +} + +//GetExchangeAccountInfo retrieves balances for all enabled currencies for the +// HUOBIHADAX exchange - to-do +func (h *HUOBIHADAX) GetExchangeAccountInfo() (exchange.AccountInfo, error) { + var response exchange.AccountInfo + response.ExchangeName = h.GetName() + return response, nil +} + +// GetExchangeFundTransferHistory returns funding history, deposits and +// withdrawals +func (h *HUOBIHADAX) GetExchangeFundTransferHistory() ([]exchange.FundHistory, error) { + var fundHistory []exchange.FundHistory + return fundHistory, errors.New("not supported on exchange") +} + +// GetExchangeHistory returns historic trade data since exchange opening. +func (h *HUOBIHADAX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} + +// SubmitExchangeOrder submits a new order +func (h *HUOBIHADAX) SubmitExchangeOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) { + return 0, errors.New("not yet implemented") +} + +// ModifyExchangeOrder will allow of changing orderbook placement and limit to +// market conversion +func (h *HUOBIHADAX) ModifyExchangeOrder(orderID int64, action exchange.ModifyOrder) (int64, error) { + return 0, errors.New("not yet implemented") +} + +// CancelExchangeOrder cancels an order by its corresponding ID number +func (h *HUOBIHADAX) CancelExchangeOrder(orderID int64) error { + return errors.New("not yet implemented") +} + +// CancelAllExchangeOrders cancels all orders associated with a currency pair +func (h *HUOBIHADAX) CancelAllExchangeOrders() error { + return errors.New("not yet implemented") +} + +// GetExchangeOrderInfo returns information on a current open order +func (h *HUOBIHADAX) GetExchangeOrderInfo(orderID int64) (exchange.OrderDetail, error) { + var orderDetail exchange.OrderDetail + return orderDetail, errors.New("not yet implemented") +} + +// GetExchangeDepositAddress returns a deposit address for a specified currency +func (h *HUOBIHADAX) GetExchangeDepositAddress(cryptocurrency pair.CurrencyItem) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawCryptoExchangeFunds returns a withdrawal ID when a withdrawal is +// submitted +func (h *HUOBIHADAX) WithdrawCryptoExchangeFunds(address string, cryptocurrency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawFiatExchangeFunds returns a withdrawal ID when a +// withdrawal is submitted +func (h *HUOBIHADAX) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawFiatExchangeFundsToInternationalBank returns a withdrawal ID when a +// withdrawal is submitted +func (h *HUOBIHADAX) WithdrawFiatExchangeFundsToInternationalBank(currency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} diff --git a/exchanges/okex/okex.go b/exchanges/okex/okex.go index 4e7bc8e1..f7cd944f 100644 --- a/exchanges/okex/okex.go +++ b/exchanges/okex/okex.go @@ -49,10 +49,10 @@ const ( // Spot requests // Unauthenticated - spotPrice = "ticker" - spotDepth = "depth" - spotTrades = "trades" - spotCandstickData = "kline" + spotPrice = "ticker" + spotDepth = "depth" + spotTrades = "trades" + spotKline = "kline" // Authenticated spotUserInfo = "userinfo" @@ -608,6 +608,87 @@ func (o *OKEX) GetContractFuturesTradeHistory(symbol, date string, since int) er return nil } +// GetUserInfo returns the user info +func (o *OKEX) GetUserInfo() (SpotUserInfo, error) { + + strRequestURL := fmt.Sprintf("%s%s%s.do", apiURL, apiVersion, spotUserInfo) + + var res SpotUserInfo + err := o.SendAuthenticatedHTTPRequest(strRequestURL, url.Values{}, &res) + if err != nil { + return res, err + } + return res, nil +} + +// SpotNewOrder creates a new spot order +func (o *OKEX) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) { + type response struct { + Result bool `json:"result"` + OrderID int64 `json:"order_id"` + } + + var res response + strRequestURL := fmt.Sprintf("%s%s%s.do", apiURL, apiVersion, spotTrade) + + params := url.Values{} + params.Set("symbol", arg.Symbol) + params.Set("type", string(arg.Type)) + params.Set("price", strconv.FormatFloat(arg.Price, 'f', -1, 64)) + params.Set("amount", strconv.FormatFloat(arg.Amount, 'f', -1, 64)) + + err := o.SendAuthenticatedHTTPRequest(strRequestURL, params, &res) + if err != nil { + return res.OrderID, err + } + + return res.OrderID, nil +} + +// SpotCancelOrder cancels a spot order +// symbol such as ltc_btc +// orderID orderID +// returns orderID or an error +func (o *OKEX) SpotCancelOrder(symbol string, argOrderID int64) (int64, error) { + type response struct { + Result bool `json:"result"` + OrderID string `json:"order_id"` + ErrorCode int `json:"error_code"` + } + + var res response + strRequestURL := fmt.Sprintf("%s%s%s.do", apiURL, apiVersion, spotCancelTrade) + + params := url.Values{} + params.Set("symbol", symbol) + params.Set("order_id", strconv.FormatInt(argOrderID, 10)) + + err := o.SendAuthenticatedHTTPRequest(strRequestURL, params, &res) + var returnOrderID int64 + if err != nil && res.ErrorCode != 0 { + return returnOrderID, err + } + if res.ErrorCode != 0 { + return returnOrderID, fmt.Errorf("ErrCode:%d ErrMsg:%s", res.ErrorCode, o.ErrorCodes[strconv.Itoa(res.ErrorCode)]) + } + + returnOrderID, _ = common.Int64FromString(res.OrderID) + return returnOrderID, nil +} + +// GetLatestSpotPrice returns latest spot price of symbol +// +// symbol: string of currency pair +func (o *OKEX) GetLatestSpotPrice(symbol string) (float64, error) { + spotPrice, err := o.GetSpotTicker(symbol) + + if err != nil { + return 0, err + } + + return spotPrice.Ticker.Last, nil +} + // GetSpotTicker returns Price Ticker func (o *OKEX) GetSpotTicker(symbol string) (SpotPrice, error) { var resp SpotPrice @@ -628,13 +709,13 @@ func (o *OKEX) GetSpotTicker(symbol string) (SpotPrice, error) { } //GetSpotMarketDepth returns Market Depth -func (o *OKEX) GetSpotMarketDepth(symbol, size string) (ActualSpotDepth, error) { +func (o *OKEX) GetSpotMarketDepth(asd ActualSpotDepthRequestParams) (ActualSpotDepth, error) { resp := SpotDepth{} fullDepth := ActualSpotDepth{} values := url.Values{} - values.Set("symbol", symbol) - values.Set("size", size) + values.Set("symbol", asd.Symbol) + values.Set("size", fmt.Sprintf("%d", asd.Size)) path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, "depth", values.Encode()) @@ -685,13 +766,13 @@ func (o *OKEX) GetSpotMarketDepth(symbol, size string) (ActualSpotDepth, error) } // GetSpotRecentTrades returns recent trades -func (o *OKEX) GetSpotRecentTrades(symbol, since string) ([]ActualSpotTradeHistory, error) { +func (o *OKEX) GetSpotRecentTrades(ast ActualSpotTradeHistoryRequestParams) ([]ActualSpotTradeHistory, error) { actualTradeHistory := []ActualSpotTradeHistory{} var resp interface{} values := url.Values{} - values.Set("symbol", symbol) - values.Set("since", since) + values.Set("symbol", ast.Symbol) + values.Set("since", fmt.Sprintf("%d", ast.Since)) path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, "trades", values.Encode()) @@ -719,18 +800,21 @@ func (o *OKEX) GetSpotRecentTrades(symbol, since string) ([]ActualSpotTradeHisto return actualTradeHistory, nil } -// GetSpotCandleStick returns candlestick data -// -func (o *OKEX) GetSpotCandleStick(symbol, typeInput string, size, since int) ([]CandleStickData, error) { +// GetSpotKline returns candlestick data +func (o *OKEX) GetSpotKline(arg KlinesRequestParams) ([]CandleStickData, error) { var candleData []CandleStickData values := url.Values{} - values.Set("symbol", symbol) - values.Set("type", typeInput) - values.Set("size", strconv.FormatInt(int64(size), 10)) - values.Set("since", strconv.FormatInt(int64(since), 10)) + values.Set("symbol", arg.Symbol) + values.Set("type", string(arg.Type)) + if arg.Size != 0 { + values.Set("size", strconv.FormatInt(int64(arg.Size), 10)) + } + if arg.Since != 0 { + values.Set("since", strconv.FormatInt(int64(arg.Since), 10)) + } - path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, "kline", values.Encode()) + path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, spotKline, values.Encode()) var resp interface{} if err := o.SendHTTPRequest(path, &resp); err != nil { diff --git a/exchanges/okex/okex_test.go b/exchanges/okex/okex_test.go index c69eb8a0..6028c9fc 100644 --- a/exchanges/okex/okex_test.go +++ b/exchanges/okex/okex_test.go @@ -188,6 +188,14 @@ func TestGetContractFuturesTradeHistory(t *testing.T) { } } +func TestGetLatestSpotPrice(t *testing.T) { + t.Parallel() + _, err := o.GetLatestSpotPrice("ltc_btc") + if err != nil { + t.Error("Test failed - okex GetLatestSpotPrice() error", err) + } +} + func TestGetSpotTicker(t *testing.T) { t.Parallel() _, err := o.GetSpotTicker("ltc_btc") @@ -198,7 +206,10 @@ func TestGetSpotTicker(t *testing.T) { func TestGetSpotMarketDepth(t *testing.T) { t.Parallel() - _, err := o.GetSpotMarketDepth("eth_btc", "2") + _, err := o.GetSpotMarketDepth(ActualSpotDepthRequestParams{ + Symbol: "eth_btc", + Size: 2, + }) if err != nil { t.Error("Test failed - okex GetSpotMarketDepth() error", err) } @@ -206,16 +217,68 @@ func TestGetSpotMarketDepth(t *testing.T) { func TestGetSpotRecentTrades(t *testing.T) { t.Parallel() - _, err := o.GetSpotRecentTrades("ltc_btc", "0") + _, err := o.GetSpotRecentTrades(ActualSpotTradeHistoryRequestParams{ + Symbol: "ltc_btc", + Since: 0, + }) if err != nil { t.Error("Test failed - okex GetSpotRecentTrades() error", err) } } -func TestGetSpotCandleStick(t *testing.T) { +func TestGetSpotKline(t *testing.T) { t.Parallel() - _, err := o.GetSpotCandleStick("ltc_btc", "1min", 2, 0) + arg := KlinesRequestParams{ + Symbol: "ltc_btc", + Type: TimeIntervalFiveMinutes, + Size: 100, + } + _, err := o.GetSpotKline(arg) if err != nil { t.Error("Test failed - okex GetSpotCandleStick() error", err) } } + +func TestSpotNewOrder(t *testing.T) { + t.Parallel() + + if o.APIKey == "" || o.APISecret == "" { + t.Skip() + } + + _, err := o.SpotNewOrder(SpotNewOrderRequestParams{ + Symbol: "ltc_btc", + Amount: 1.1, + Price: 10.1, + Type: SpotNewOrderRequestTypeBuy, + }) + if err != nil { + t.Error("Test failed - okex SpotNewOrder() error", err) + } +} + +func TestSpotCancelOrder(t *testing.T) { + t.Parallel() + + if o.APIKey == "" || o.APISecret == "" { + t.Skip() + } + + _, err := o.SpotCancelOrder("ltc_btc", 519158961) + if err != nil { + t.Error("Test failed - okex SpotCancelOrder() error", err) + } +} + +func TestGetUserInfo(t *testing.T) { + t.Parallel() + + if o.APIKey == "" || o.APISecret == "" { + t.Skip() + } + + _, err := o.GetUserInfo() + if err != nil { + t.Error("Test failed - okex GetUserInfo() error", err) + } +} diff --git a/exchanges/okex/okex_types.go b/exchanges/okex/okex_types.go index b768704b..180eb7f0 100644 --- a/exchanges/okex/okex_types.go +++ b/exchanges/okex/okex_types.go @@ -135,6 +135,12 @@ type SpotDepth struct { Error interface{} `json:"error_code"` } +// ActualSpotDepthRequestParams represents Klines request data. +type ActualSpotDepthRequestParams struct { + Symbol string `json:"symbol"` // Symbol; example ltc_btc + Size int `json:"size"` // value: 1-200 +} + // ActualSpotDepth better manipulated structure to return type ActualSpotDepth struct { Asks []struct { @@ -147,6 +153,12 @@ type ActualSpotDepth struct { } } +// ActualSpotTradeHistoryRequestParams represents Klines request data. +type ActualSpotTradeHistoryRequestParams struct { + Symbol string `json:"symbol"` // Symbol; example ltc_btc + Since int `json:"since"` // TID; transaction record ID (return data does not include the current TID value, returning up to 600 items) +} + // ActualSpotTradeHistory holds contract trade history type ActualSpotTradeHistory struct { Amount float64 `json:"amount"` @@ -156,3 +168,61 @@ type ActualSpotTradeHistory struct { TID float64 `json:"tid"` Type string `json:"buy"` } + +// SpotUserInfo holds the spot user info +type SpotUserInfo struct { + Result bool `json:"result"` + Info map[string]map[string]map[string]string `json:"info"` +} + +// SpotNewOrderRequestParams holds the params for making a new spot order +type SpotNewOrderRequestParams struct { + Amount float64 `json:"amount"` // Order quantity + Price float64 `json:"price"` // Order price + Symbol string `json:"symbol"` // Symbol; example btc_usdt, eth_btc...... + Type SpotNewOrderRequestType `json:"type"` // Order type (see below) +} + +// SpotNewOrderRequestType order type +type SpotNewOrderRequestType string + +var ( + // SpotNewOrderRequestTypeBuy buy order + SpotNewOrderRequestTypeBuy = SpotNewOrderRequestType("buy") + + // SpotNewOrderRequestTypeSell sell order + SpotNewOrderRequestTypeSell = SpotNewOrderRequestType("sell") + + // SpotNewOrderRequestTypeBuyMarket buy market order + SpotNewOrderRequestTypeBuyMarket = SpotNewOrderRequestType("buy_market") + + // SpotNewOrderRequestTypeSellMarket sell market order + SpotNewOrderRequestTypeSellMarket = SpotNewOrderRequestType("sell_market") +) + +// KlinesRequestParams represents Klines request data. +type KlinesRequestParams struct { + Symbol string // Symbol; example btcusdt, bccbtc...... + Type TimeInterval // Kline data time interval; 1min, 5min, 15min...... + Size int // Size; [1-2000] + Since int64 // Since timestamp, return data after the specified timestamp (for example, 1417536000000) +} + +// TimeInterval represents interval enum. +type TimeInterval string + +// vars for time intervals +var ( + TimeIntervalMinute = TimeInterval("1min") + TimeIntervalThreeMinutes = TimeInterval("3min") + TimeIntervalFiveMinutes = TimeInterval("5min") + TimeIntervalFifteenMinutes = TimeInterval("15min") + TimeIntervalThirtyMinutes = TimeInterval("30min") + TimeIntervalHour = TimeInterval("1hour") + TimeIntervalFourHours = TimeInterval("4hour") + TimeIntervalSixHours = TimeInterval("6hour") + TimeIntervalTwelveHours = TimeInterval("12hour") + TimeIntervalDay = TimeInterval("1day") + TimeIntervalThreeDays = TimeInterval("3day") + TimeIntervalWeek = TimeInterval("1week") +) diff --git a/exchanges/okex/okex_wrapper.go b/exchanges/okex/okex_wrapper.go index f8ac9119..6c8f3afa 100644 --- a/exchanges/okex/okex_wrapper.go +++ b/exchanges/okex/okex_wrapper.go @@ -125,7 +125,10 @@ func (o *OKEX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook currency = exchange.FormatExchangeCurrency(o.Name, p).String() } - orderbookNew, err := o.GetSpotMarketDepth(currency, "200") + orderbookNew, err := o.GetSpotMarketDepth(ActualSpotDepthRequestParams{ + Symbol: currency, + Size: 200, + }) if err != nil { return orderBook, err } diff --git a/exchanges/request/request.go b/exchanges/request/request.go index d26db363..a840ac3f 100644 --- a/exchanges/request/request.go +++ b/exchanges/request/request.go @@ -245,9 +245,9 @@ func (r *Requester) DoRequest(req *http.Request, method, path string, headers ma if r.RequiresRateLimiter() { r.DecrementRequests(authRequest) } + return err } - if resp == nil { if r.RequiresRateLimiter() { r.DecrementRequests(authRequest) diff --git a/exchanges/zb/README.md b/exchanges/zb/README.md new file mode 100644 index 00000000..ef06284a --- /dev/null +++ b/exchanges/zb/README.md @@ -0,0 +1,9 @@ +# GoCryptoTrader package zb + +This zb package is part of the GoCryptoTrader codebase. + +## ZB Exchange + +### Current Features + +ZB 交易所的支持,支持获取K线、买/卖订单、取消订单 \ No newline at end of file diff --git a/exchanges/zb/zb.go b/exchanges/zb/zb.go new file mode 100644 index 00000000..c0205b2b --- /dev/null +++ b/exchanges/zb/zb.go @@ -0,0 +1,318 @@ +package zb + +import ( + "encoding/json" + "errors" + "fmt" + "log" + "net/url" + "strconv" + "strings" + "time" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" + exchange "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/request" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +const ( + zbTradeURL = "http://api.zb.com/data" + zbMarketURL = "https://trade.zb.com/api" + zbAPIVersion = "v1" + + zbAccountInfo = "getAccountInfo" + zbMarkets = "markets" + zbKline = "kline" + zbOrder = "order" + zbCancelOrder = "cancelOrder" + zbTicker = "ticker" + zbTickers = "allTicker" + zbDepth = "depth" + + zbAuthRate = 100 + zbUnauthRate = 100 +) + +// ZB is the overarching type across this package +// 47.91.169.147 api.zb.com +// 47.52.55.212 trade.zb.com +type ZB struct { + exchange.Base +} + +// SetDefaults sets default values for the exchange +func (z *ZB) SetDefaults() { + z.Name = "ZB" + z.Enabled = false + z.Fee = 0 + z.Verbose = false + z.Websocket = false + z.RESTPollingDelay = 10 + z.RequestCurrencyPairFormat.Delimiter = "_" + z.RequestCurrencyPairFormat.Uppercase = false + z.ConfigCurrencyPairFormat.Delimiter = "_" + z.ConfigCurrencyPairFormat.Uppercase = true + z.AssetTypes = []string{ticker.Spot} + z.SupportsAutoPairUpdating = true + z.SupportsRESTTickerBatching = true + z.Requester = request.New(z.Name, request.NewRateLimit(time.Second*10, zbAuthRate), request.NewRateLimit(time.Second*10, zbUnauthRate), common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout)) +} + +// Setup sets user configuration +func (z *ZB) Setup(exch config.ExchangeConfig) { + if !exch.Enabled { + z.SetEnabled(false) + } else { + z.Enabled = true + z.AuthenticatedAPISupport = exch.AuthenticatedAPISupport + z.SetAPIKeys(exch.APIKey, exch.APISecret, "", false) + z.APIAuthPEMKey = exch.APIAuthPEMKey + z.SetHTTPClientTimeout(exch.HTTPTimeout) + z.RESTPollingDelay = exch.RESTPollingDelay + z.Verbose = exch.Verbose + z.Websocket = exch.Websocket + z.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") + z.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") + z.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + err := z.SetCurrencyPairFormat() + if err != nil { + log.Fatal(err) + } + err = z.SetAssetTypes() + if err != nil { + log.Fatal(err) + } + err = z.SetAutoPairDefaults() + if err != nil { + log.Fatal(err) + } + } +} + +// SpotNewOrder submits an order to ZB +func (z *ZB) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) { + var result SpotNewOrderResponse + + vals := url.Values{} + vals.Set("accesskey", z.APIKey) + vals.Set("method", "order") + vals.Set("amount", strconv.FormatFloat(arg.Amount, 'f', -1, 64)) + vals.Set("currency", arg.Symbol) + vals.Set("price", strconv.FormatFloat(arg.Price, 'f', -1, 64)) + vals.Set("tradeType", string(arg.Type)) + + err := z.SendAuthenticatedHTTPRequest("GET", zbOrder, vals, &result) + if err != nil { + return 0, err + } + if result.Code != 1000 { + + } + newOrderID, err := strconv.ParseInt(result.ID, 10, 64) + if err != nil { + return 0, err + } + return newOrderID, nil +} + +// CancelOrder cancels an order on Huobi +func (z *ZB) CancelOrder(orderID int64, symbol string) error { + type response struct { + Code int `json:"code"` // Result code + Message string `json:"message"` // Result Message + } + + vals := url.Values{} + vals.Set("accesskey", z.APIKey) + vals.Set("method", "cancelOrder") + vals.Set("id", strconv.FormatInt(orderID, 10)) + vals.Set("currency", symbol) + + var result response + err := z.SendAuthenticatedHTTPRequest("GET", zbCancelOrder, vals, &result) + if err != nil { + return err + } + + if result.Code != 1000 { + return errors.New(result.Message) + } + return nil +} + +// GetAccountInfo returns account information including coin information +// and pricing +func (z *ZB) GetAccountInfo() (AccountsResponse, error) { + var result AccountsResponse + + vals := url.Values{} + vals.Set("accesskey", z.APIKey) + vals.Set("method", "getAccountInfo") + + err := z.SendAuthenticatedHTTPRequest("GET", zbAccountInfo, vals, &result) + if err != nil { + return result, err + } + return result, nil +} + +// GetMarkets returns market information including pricing, symbols and +// each symbols decimal precision +func (z *ZB) GetMarkets() (map[string]MarketResponseItem, error) { + url := fmt.Sprintf("%s/%s/%s", zbTradeURL, zbAPIVersion, zbMarkets) + + var res interface{} + err := z.SendHTTPRequest(url, &res) + if err != nil { + return nil, err + } + + list := res.(map[string]interface{}) + result := map[string]MarketResponseItem{} + for k, v := range list { + item := v.(map[string]interface{}) + result[k] = MarketResponseItem{ + AmountScale: item["amountScale"].(float64), + PriceScale: item["priceScale"].(float64), + } + } + return result, nil +} + +// GetLatestSpotPrice returns latest spot price of symbol +// +// symbol: string of currency pair +// 获取最新价格 +func (z *ZB) GetLatestSpotPrice(symbol string) (float64, error) { + res, err := z.GetTicker(symbol) + + if err != nil { + return 0, err + } + + return res.Ticker.Last, nil +} + +// GetTicker returns a ticker for a given symbol +func (z *ZB) GetTicker(symbol string) (TickerResponse, error) { + url := fmt.Sprintf("%s/%s/%s?market=%s", zbTradeURL, zbAPIVersion, zbTicker, symbol) + var res TickerResponse + + err := z.SendHTTPRequest(url, &res) + if err != nil { + return res, err + } + + return res, nil +} + +// GetTickers returns ticker data for all supported symbols +func (z *ZB) GetTickers() (map[string]TickerChildResponse, error) { + url := fmt.Sprintf("%s/%s/%s", zbTradeURL, zbAPIVersion, zbTickers) + resp := make(map[string]TickerChildResponse) + + err := z.SendHTTPRequest(url, &resp) + if err != nil { + return resp, err + } + + return resp, nil +} + +// GetOrderbook returns the orderbook for a given symbol +func (z *ZB) GetOrderbook(symbol string) (OrderbookResponse, error) { + url := fmt.Sprintf("%s/%s/%s?market=%s", zbTradeURL, zbAPIVersion, zbDepth, symbol) + var res OrderbookResponse + + err := z.SendHTTPRequest(url, &res) + if err != nil { + return res, err + } + + // reverse asks data + var data [][]float64 + for x := len(res.Asks) - 1; x != 0; x-- { + data = append(data, res.Asks[x]) + } + + res.Asks = data + return res, nil +} + +// GetSpotKline returns Kline data +func (z *ZB) GetSpotKline(arg KlinesRequestParams) (KLineResponse, error) { + vals := url.Values{} + vals.Set("type", string(arg.Type)) + vals.Set("market", arg.Symbol) + if arg.Since != "" { + vals.Set("since", arg.Since) + } + if arg.Size != 0 { + vals.Set("size", fmt.Sprintf("%d", arg.Size)) + } + + url := fmt.Sprintf("%s/%s/%s?%s", zbTradeURL, zbAPIVersion, zbKline, vals.Encode()) + + var res KLineResponse + var rawKlines map[string]interface{} + err := z.SendHTTPRequest(url, &rawKlines) + if err != nil { + return res, err + } + if rawKlines == nil || rawKlines["symbol"] == nil { + return res, errors.New("zb GetSpotKline rawKlines is nil") + } + + res.Symbol = rawKlines["symbol"].(string) + res.MoneyType = rawKlines["moneyType"].(string) + + rawKlineDatasString, _ := json.Marshal(rawKlines["data"].([]interface{})) + rawKlineDatas := [][]interface{}{} + if err := json.Unmarshal(rawKlineDatasString, &rawKlineDatas); err != nil { + return res, errors.New("zb rawKlines unmarshal failed") + } + for _, k := range rawKlineDatas { + ot, err := common.TimeFromUnixTimestampFloat(k[0]) + if err != nil { + return res, errors.New("zb cannot parse Kline.OpenTime") + } + res.Data = append(res.Data, &KLineResponseData{ + ID: k[0].(float64), + KlineTime: ot, + Open: k[1].(float64), + High: k[2].(float64), + Low: k[3].(float64), + Close: k[4].(float64), + Volume: k[5].(float64), + }) + } + + return res, nil +} + +// SendHTTPRequest sends an unauthenticated HTTP request +func (z *ZB) SendHTTPRequest(path string, result interface{}) error { + return z.SendPayload("GET", path, nil, nil, result, false, z.Verbose) +} + +// SendAuthenticatedHTTPRequest sends authenticated requests to the zb API +func (z *ZB) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error { + if !z.AuthenticatedAPISupport { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, z.Name) + } + + headers := make(map[string]string) + headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36" + + mapParams2Sign := url.Values{} + mapParams2Sign.Set("accesskey", z.APIKey) + mapParams2Sign.Set("method", values.Get("method")) + values.Set("sign", common.HexEncodeToString(common.GetHMAC(common.HashMD5, []byte(values.Encode()), []byte(common.Sha1ToHex(z.APISecret))))) + values.Set("reqTime", fmt.Sprintf("%d", time.Now().UnixNano()/1e6)) + + url := fmt.Sprintf("%s/%s?%s", zbMarketURL, endpoint, values.Encode()) + + return z.SendPayload(method, url, headers, strings.NewReader(""), result, true, z.Verbose) +} diff --git a/exchanges/zb/zb_test.go b/exchanges/zb/zb_test.go new file mode 100644 index 00000000..cc8f5807 --- /dev/null +++ b/exchanges/zb/zb_test.go @@ -0,0 +1,136 @@ +package zb + +import ( + "fmt" + "testing" + + "github.com/thrasher-/gocryptotrader/config" +) + +// Please supply you own test keys here for due diligence testing. +const ( + apiKey = "" + apiSecret = "" +) + +var z ZB + +func TestSetDefaults(t *testing.T) { + z.SetDefaults() +} + +func TestSetup(t *testing.T) { + cfg := config.GetConfig() + cfg.LoadConfig("../../testdata/configtest.json") + zbConfig, err := cfg.GetExchangeConfig("ZB") + if err != nil { + t.Error("Test Failed - ZB Setup() init error") + } + + zbConfig.AuthenticatedAPISupport = true + zbConfig.APIKey = apiKey + zbConfig.APISecret = apiSecret + + z.Setup(zbConfig) +} + +func TestSpotNewOrder(t *testing.T) { + t.Parallel() + + if z.APIKey == "" || z.APISecret == "" { + t.Skip() + } + + arg := SpotNewOrderRequestParams{ + Symbol: "btc_usdt", + Type: SpotNewOrderRequestParamsTypeSell, + Amount: 0.01, + Price: 10246.1, + } + orderid, err := z.SpotNewOrder(arg) + if err != nil { + t.Errorf("Test failed - ZB SpotNewOrder: %s", err) + } else { + fmt.Println(orderid) + } +} + +func TestCancelOrder(t *testing.T) { + t.Parallel() + + if z.APIKey == "" || z.APISecret == "" { + t.Skip() + } + + err := z.CancelOrder(20180629145864850, "btc_usdt") + if err != nil { + t.Errorf("Test failed - ZB CancelOrder: %s", err) + } +} + +func TestGetLatestSpotPrice(t *testing.T) { + t.Parallel() + _, err := z.GetLatestSpotPrice("btc_usdt") + if err != nil { + t.Errorf("Test failed - ZB GetLatestSpotPrice: %s", err) + } +} + +func TestGetTicker(t *testing.T) { + t.Parallel() + _, err := z.GetTicker("btc_usdt") + if err != nil { + t.Errorf("Test failed - ZB GetTicker: %s", err) + } +} + +func TestGetTickers(t *testing.T) { + t.Parallel() + _, err := z.GetTickers() + if err != nil { + t.Errorf("Test failed - ZB GetTicker: %s", err) + } +} + +func TestGetOrderbook(t *testing.T) { + t.Parallel() + _, err := z.GetOrderbook("btc_usdt") + if err != nil { + t.Errorf("Test failed - ZB GetTicker: %s", err) + } +} + +func TestGetMarkets(t *testing.T) { + t.Parallel() + _, err := z.GetMarkets() + if err != nil { + t.Errorf("Test failed - ZB GetMarkets: %s", err) + } +} + +func TestGetAccountInfo(t *testing.T) { + t.Parallel() + + if z.APIKey == "" || z.APISecret == "" { + t.Skip() + } + + _, err := z.GetAccountInfo() + if err != nil { + t.Errorf("Test failed - ZB GetAccountInfo: %s", err) + } +} + +func TestGetSpotKline(t *testing.T) { + t.Parallel() + + arg := KlinesRequestParams{ + Symbol: "btc_usdt", + Type: TimeIntervalFiveMinutes, + Size: 10, + } + _, err := z.GetSpotKline(arg) + if err != nil { + t.Errorf("Test failed - ZB GetSpotKline: %s", err) + } +} diff --git a/exchanges/zb/zb_type.go b/exchanges/zb/zb_type.go new file mode 100644 index 00000000..1ee81219 --- /dev/null +++ b/exchanges/zb/zb_type.go @@ -0,0 +1,137 @@ +package zb + +import "time" + +// OrderbookResponse holds the orderbook data for a symbol +type OrderbookResponse struct { + Timestamp int64 `json:"timestamp"` + Asks [][]float64 `json:"asks"` + Bids [][]float64 `json:"bids"` +} + +// AccountsResponseCoin holds the accounts coin details +type AccountsResponseCoin struct { + Freez string `json:"freez"` //冻结资产 + EnName string `json:"enName"` //币种英文名 + UnitDecimal int `json:"unitDecimal"` //保留小数位 + UnName string `json:"cnName"` //币种中文名 + UnitTag string `json:"unitTag"` //币种符号 + Available string `json:"available"` //可用资产 + Key string `json:"key"` //币种 +} + +// AccountsBaseResponse holds basic account details +type AccountsBaseResponse struct { + UserName string `json:"username"` //用户名 + TradePasswordEnabled bool `json:"trade_password_enabled"` //是否开通交易密码 + AuthGoogleEnabled bool `json:"auth_google_enabled"` //是否开通谷歌验证 + AuthMobileEnabled bool `json:"auth_mobile_enabled"` //是否开通手机验证 +} + +// AccountsResponse 用户基本信息 +type AccountsResponse struct { + Result struct { + Coins []AccountsResponseCoin `json:"coins"` + Base AccountsBaseResponse `json:"base"` + } `json:"result"` //用户名 + AssetPerm bool `json:"assetPerm"` //是否开通交易密码 + LeverPerm bool `json:"leverPerm"` //是否开通谷歌验证 + EntrustPerm bool `json:"entrustPerm"` //是否开通手机验证 + MoneyPerm bool `json:"moneyPerm"` // 资产列表 +} + +// MarketResponseItem stores market data +type MarketResponseItem struct { + AmountScale float64 `json:"amountScale"` + PriceScale float64 `json:"priceScale"` +} + +// TickerResponse holds the ticker response data +type TickerResponse struct { + Date string `json:"date"` + Ticker TickerChildResponse `json:"ticker"` +} + +// TickerChildResponse holds the ticker child response data +type TickerChildResponse struct { + Vol float64 `json:"vol,string"` //成交量(最近的24小时) + Last float64 `json:"last,string"` //最新成交价 + Sell float64 `json:"sell,string"` //卖一价 + Buy float64 `json:"buy,string"` //买一价 + High float64 `json:"high,string"` //最高价 + Low float64 `json:"low,string"` //最低价 +} + +// SpotNewOrderRequestParamsType ZB 交易类型 +type SpotNewOrderRequestParamsType string + +var ( + // SpotNewOrderRequestParamsTypeBuy 买 + SpotNewOrderRequestParamsTypeBuy = SpotNewOrderRequestParamsType("1") + // SpotNewOrderRequestParamsTypeSell 卖 + SpotNewOrderRequestParamsTypeSell = SpotNewOrderRequestParamsType("0") +) + +// SpotNewOrderRequestParams is the params used for placing an order +type SpotNewOrderRequestParams struct { + Amount float64 `json:"amount"` // 交易数量 + Price float64 `json:"price"` // 下单价格, + Symbol string `json:"currency"` // 交易对, btcusdt, bccbtc...... + Type SpotNewOrderRequestParamsType `json:"tradeType"` // 订单类型, buy-market: 市价买, sell-market: 市价卖, buy-limit: 限价买, sell-limit: 限价卖 +} + +// SpotNewOrderResponse stores the new order response data +type SpotNewOrderResponse struct { + Code int `json:"code"` //返回代码 + Message string `json:"message"` //提示信息 + ID string `json:"id"` //委托挂单号 +} + +// //-------------Kline + +// KlinesRequestParams represents Klines request data. +type KlinesRequestParams struct { + Symbol string //交易对, zb_qc,zb_usdt,zb_btc... + Type TimeInterval //K线类型, 1min, 3min, 15min, 30min, 1hour...... + Since string //从这个时间戳之后的 + Size int //返回数据的条数限制(默认为1000,如果返回数据多于1000条,那么只返回1000条) +} + +// KLineResponseData Kline Data +type KLineResponseData struct { + ID float64 `json:"id"` // K线ID + KlineTime time.Time `json:"klineTime"` + Open float64 `json:"open"` // 开盘价 + Close float64 `json:"close"` // 收盘价, 当K线为最晚的一根时, 时最新成交价 + Low float64 `json:"low"` // 最低价 + High float64 `json:"high"` // 最高价 + Volume float64 `json:"vol"` // 成交量 +} + +// KLineResponse K线返回类型 +type KLineResponse struct { + // Data string `json:"data"` // 买入货币 + MoneyType string `json:"moneyType"` // 卖出货币 + Symbol string `json:"symbol"` // 内容说明 + Data []*KLineResponseData `json:"data"` // KLine数据 +} + +// TimeInterval represents interval enum. +type TimeInterval string + +// TimeInterval vars +var ( + TimeIntervalMinute = TimeInterval("1min") + TimeIntervalThreeMinutes = TimeInterval("3min") + TimeIntervalFiveMinutes = TimeInterval("5min") + TimeIntervalFifteenMinutes = TimeInterval("15min") + TimeIntervalThirtyMinutes = TimeInterval("30min") + TimeIntervalHour = TimeInterval("1hour") + TimeIntervalTwoHours = TimeInterval("2hour") + TimeIntervalFourHours = TimeInterval("4hour") + TimeIntervalSixHours = TimeInterval("6hour") + TimeIntervalTwelveHours = TimeInterval("12hour") + TimeIntervalDay = TimeInterval("1day") + TimeIntervalThreeDays = TimeInterval("3day") + TimeIntervalWeek = TimeInterval("1week") +) diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go new file mode 100644 index 00000000..ac4f1593 --- /dev/null +++ b/exchanges/zb/zb_wrapper.go @@ -0,0 +1,186 @@ +package zb + +import ( + "errors" + "log" + "sync" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/currency/pair" + "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/orderbook" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +// Start starts the OKEX go routine +func (z *ZB) Start(wg *sync.WaitGroup) { + wg.Add(1) + go func() { + z.Run() + wg.Done() + }() +} + +// Run implements the OKEX wrapper +func (z *ZB) Run() { + if z.Verbose { + log.Printf("%s Websocket: %s. (url: %s).\n", z.GetName(), common.IsEnabled(z.Websocket), z.WebsocketURL) + log.Printf("%s polling delay: %ds.\n", z.GetName(), z.RESTPollingDelay) + log.Printf("%s %d currencies enabled: %s.\n", z.GetName(), len(z.EnabledPairs), z.EnabledPairs) + } + + markets, err := z.GetMarkets() + if err != nil { + log.Printf("%s Unable to fetch symbols.\n", z.GetName()) + } else { + var currencies []string + for x := range markets { + currencies = append(currencies, x) + } + + err = z.UpdateCurrencies(currencies, false, false) + if err != nil { + log.Printf("%s Failed to update available currencies.\n", z.GetName()) + } + } +} + +// UpdateTicker updates and returns the ticker for a currency pair +func (z *ZB) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) { + var tickerPrice ticker.Price + + result, err := z.GetTickers() + if err != nil { + return tickerPrice, err + } + + for _, x := range z.GetEnabledCurrencies() { + currencySplit := common.SplitStrings(exchange.FormatExchangeCurrency(z.Name, x).String(), "_") + currency := currencySplit[0] + currencySplit[1] + var tp ticker.Price + tp.Pair = x + tp.High = result[currency].High + tp.Last = result[currency].Last + tp.Ask = result[currency].Sell + tp.Bid = result[currency].Buy + tp.Last = result[currency].Last + tp.Low = result[currency].Low + tp.Volume = result[currency].Vol + ticker.ProcessTicker(z.Name, x, tp, assetType) + } + + return ticker.GetTicker(z.Name, p, assetType) +} + +// GetTickerPrice returns the ticker for a currency pair +func (z *ZB) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) { + tickerNew, err := ticker.GetTicker(z.GetName(), p, assetType) + if err != nil { + return z.UpdateTicker(p, assetType) + } + return tickerNew, nil +} + +// GetOrderbookEx returns orderbook base on the currency pair +func (z *ZB) GetOrderbookEx(currency pair.CurrencyPair, assetType string) (orderbook.Base, error) { + ob, err := orderbook.GetOrderbook(z.GetName(), currency, assetType) + if err != nil { + return z.UpdateOrderbook(currency, assetType) + } + return ob, nil +} + +// UpdateOrderbook updates and returns the orderbook for a currency pair +func (z *ZB) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) { + var orderBook orderbook.Base + currency := exchange.FormatExchangeCurrency(z.Name, p).String() + + orderbookNew, err := z.GetOrderbook(currency) + if err != nil { + return orderBook, err + } + + for x := range orderbookNew.Bids { + data := orderbookNew.Bids[x] + orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data[1], Price: data[0]}) + } + + for x := range orderbookNew.Asks { + data := orderbookNew.Asks[x] + orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data[1], Price: data[0]}) + } + + orderbook.ProcessOrderbook(z.GetName(), p, orderBook, assetType) + return orderbook.GetOrderbook(z.Name, p, assetType) +} + +// GetExchangeAccountInfo retrieves balances for all enabled currencies for the +// ZB exchange +func (z *ZB) GetExchangeAccountInfo() (exchange.AccountInfo, error) { + var response exchange.AccountInfo + return response, errors.New("not implemented") +} + +// GetExchangeFundTransferHistory returns funding history, deposits and +// withdrawals +func (z *ZB) GetExchangeFundTransferHistory() ([]exchange.FundHistory, error) { + var fundHistory []exchange.FundHistory + return fundHistory, errors.New("not supported on exchange") +} + +// GetExchangeHistory returns historic trade data since exchange opening. +func (z *ZB) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) { + var resp []exchange.TradeHistory + + return resp, errors.New("trade history not yet implemented") +} + +// SubmitExchangeOrder submits a new order +func (z *ZB) SubmitExchangeOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) { + return 0, errors.New("not yet implemented") +} + +// ModifyExchangeOrder will allow of changing orderbook placement and limit to +// market conversion +func (z *ZB) ModifyExchangeOrder(orderID int64, action exchange.ModifyOrder) (int64, error) { + return 0, errors.New("not yet implemented") +} + +// CancelExchangeOrder cancels an order by its corresponding ID number +func (z *ZB) CancelExchangeOrder(orderID int64) error { + return errors.New("not yet implemented") +} + +// CancelAllExchangeOrders cancels all orders associated with a currency pair +func (z *ZB) CancelAllExchangeOrders() error { + return errors.New("not yet implemented") +} + +// GetExchangeOrderInfo returns information on a current open order +func (z *ZB) GetExchangeOrderInfo(orderID int64) (exchange.OrderDetail, error) { + var orderDetail exchange.OrderDetail + return orderDetail, errors.New("not yet implemented") +} + +// GetExchangeDepositAddress returns a deposit address for a specified currency +func (z *ZB) GetExchangeDepositAddress(cryptocurrency pair.CurrencyItem) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawCryptoExchangeFunds returns a withdrawal ID when a withdrawal is +// submitted +func (z *ZB) WithdrawCryptoExchangeFunds(address string, cryptocurrency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawFiatExchangeFunds returns a withdrawal ID when a +// withdrawal is submitted +func (z *ZB) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} + +// WithdrawFiatExchangeFundsToInternationalBank returns a withdrawal ID when a +// withdrawal is submitted +func (z *ZB) WithdrawFiatExchangeFundsToInternationalBank(currency pair.CurrencyItem, amount float64) (string, error) { + return "", errors.New("not yet implemented") +} diff --git a/testdata/configtest.json b/testdata/configtest.json index 15e08417..13342a77 100644 --- a/testdata/configtest.json +++ b/testdata/configtest.json @@ -92,13 +92,13 @@ { "Address": "1JCe8z4jJVNXSjohjM4i9Hh813dLCNx2Sy", "CoinType": "BTC", - "Balance": 53000.01256575, + "Balance": 53000.01324467, "Description": "" }, { "Address": "3Nxwenay9Z8Lc9JBiywExpnEFiLp6Afp8v", "CoinType": "BTC", - "Balance": 103848.27285787, + "Balance": 101848.28432707, "Description": "" }, { @@ -171,7 +171,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "ETH-BTC,LTC-BTC,BNB-BTC,NEO-BTC,QTUM-ETH,EOS-ETH,SNT-ETH,BNT-ETH,BCC-BTC,GAS-BTC,BNB-ETH,BTC-USDT,ETH-USDT,HSR-BTC,OAX-ETH,DNT-ETH,MCO-ETH,ICN-ETH,MCO-BTC,WTC-BTC,WTC-ETH,LRC-BTC,LRC-ETH,QTUM-BTC,YOYO-BTC,OMG-BTC,OMG-ETH,ZRX-BTC,ZRX-ETH,STRAT-BTC,STRAT-ETH,SNGLS-BTC,SNGLS-ETH,BQX-BTC,BQX-ETH,KNC-BTC,KNC-ETH,FUN-BTC,FUN-ETH,SNM-BTC,SNM-ETH,NEO-ETH,IOTA-BTC,IOTA-ETH,LINK-BTC,LINK-ETH,XVG-BTC,XVG-ETH,SALT-BTC,SALT-ETH,MDA-BTC,MDA-ETH,MTL-BTC,MTL-ETH,SUB-BTC,SUB-ETH,EOS-BTC,SNT-BTC,ETC-ETH,ETC-BTC,MTH-BTC,MTH-ETH,ENG-BTC,ENG-ETH,DNT-BTC,ZEC-BTC,ZEC-ETH,BNT-BTC,AST-BTC,AST-ETH,DASH-BTC,DASH-ETH,OAX-BTC,ICN-BTC,BTG-BTC,BTG-ETH,EVX-BTC,EVX-ETH,REQ-BTC,REQ-ETH,VIB-BTC,VIB-ETH,HSR-ETH,TRX-BTC,TRX-ETH,POWR-BTC,POWR-ETH,ARK-BTC,ARK-ETH,YOYO-ETH,XRP-BTC,XRP-ETH,MOD-BTC,MOD-ETH,ENJ-BTC,ENJ-ETH,STORJ-BTC,STORJ-ETH,BNB-USDT,VEN-BNB,YOYO-BNB,POWR-BNB,VEN-BTC,VEN-ETH,KMD-BTC,KMD-ETH,NULS-BNB,RCN-BTC,RCN-ETH,RCN-BNB,NULS-BTC,NULS-ETH,RDN-BTC,RDN-ETH,RDN-BNB,XMR-BTC,XMR-ETH,DLT-BNB,WTC-BNB,DLT-BTC,DLT-ETH,AMB-BTC,AMB-ETH,AMB-BNB,BCC-ETH,BCC-USDT,BCC-BNB,BAT-BTC,BAT-ETH,BAT-BNB,BCPT-BTC,BCPT-ETH,BCPT-BNB,ARN-BTC,ARN-ETH,GVT-BTC,GVT-ETH,CDT-BTC,CDT-ETH,GXS-BTC,GXS-ETH,NEO-USDT,NEO-BNB,POE-BTC,POE-ETH,QSP-BTC,QSP-ETH,QSP-BNB,BTS-BTC,BTS-ETH,BTS-BNB,XZC-BTC,XZC-ETH,XZC-BNB,LSK-BTC,LSK-ETH,LSK-BNB,TNT-BTC,TNT-ETH,FUEL-BTC,FUEL-ETH,MANA-BTC,MANA-ETH,BCD-BTC,BCD-ETH,DGD-BTC,DGD-ETH,IOTA-BNB,ADX-BTC,ADX-ETH,ADX-BNB,ADA-BTC,ADA-ETH,PPT-BTC,PPT-ETH,CMT-BTC,CMT-ETH,CMT-BNB,XLM-BTC,XLM-ETH,XLM-BNB,CND-BTC,CND-ETH,CND-BNB,LEND-BTC,LEND-ETH,WABI-BTC,WABI-ETH,WABI-BNB,LTC-ETH,LTC-USDT,LTC-BNB,TNB-BTC,TNB-ETH,WAVES-BTC,WAVES-ETH,WAVES-BNB,GTO-BTC,GTO-ETH,GTO-BNB,ICX-BTC,ICX-ETH,ICX-BNB,OST-BTC,OST-ETH,OST-BNB,ELF-BTC,ELF-ETH,AION-BTC,AION-ETH,AION-BNB,NEBL-BTC,NEBL-ETH,NEBL-BNB,BRD-BTC,BRD-ETH,BRD-BNB,MCO-BNB,EDO-BTC,EDO-ETH,WINGS-BTC,WINGS-ETH,NAV-BTC,NAV-ETH,NAV-BNB,LUN-BTC,LUN-ETH,TRIG-BTC,TRIG-ETH,TRIG-BNB,APPC-BTC,APPC-ETH,APPC-BNB,VIBE-BTC,VIBE-ETH,RLC-BTC,RLC-ETH,RLC-BNB,INS-BTC,INS-ETH,PIVX-BTC,PIVX-ETH,PIVX-BNB,IOST-BTC,IOST-ETH,CHAT-BTC,CHAT-ETH,STEEM-BTC,STEEM-ETH,STEEM-BNB,NANO-BTC,NANO-ETH,NANO-BNB,VIA-BTC,VIA-ETH,VIA-BNB,BLZ-BTC,BLZ-ETH,BLZ-BNB,AE-BTC,AE-ETH,AE-BNB,RPX-BTC,RPX-ETH,RPX-BNB,NCASH-BTC,NCASH-ETH,NCASH-BNB,POA-BTC,POA-ETH,POA-BNB,ZIL-BTC,ZIL-ETH,ZIL-BNB,ONT-BTC,ONT-ETH,ONT-BNB,STORM-BTC,STORM-ETH,STORM-BNB,QTUM-BNB,QTUM-USDT,XEM-BTC,XEM-ETH,XEM-BNB,WAN-BTC,WAN-ETH,WAN-BNB,WPR-BTC,WPR-ETH,QLC-BTC,QLC-ETH,SYS-BTC,SYS-ETH,SYS-BNB,QLC-BNB,GRS-BTC,GRS-ETH,ADA-USDT,ADA-BNB,CLOAK-BTC,CLOAK-ETH,GNT-BTC,GNT-ETH,GNT-BNB,LOOM-BTC,LOOM-ETH,LOOM-BNB,XRP-USDT,BCN-BTC,BCN-ETH,BCN-BNB,REP-BTC,REP-ETH,REP-BNB,TUSD-BTC,TUSD-ETH,TUSD-BNB,ZEN-BTC,ZEN-ETH,ZEN-BNB,SKY-BTC,SKY-ETH,SKY-BNB,EOS-USDT,EOS-BNB,CVC-BTC,CVC-ETH,CVC-BNB,THETA-BTC,THETA-ETH,THETA-BNB,XRP-BNB,TUSD-USDT,IOTA-USDT,XLM-USDT,IOTX-BTC,IOTX-ETH,QKC-BTC,QKC-ETH,AGI-BTC,AGI-ETH,AGI-BNB,NXS-BTC,NXS-ETH,NXS-BNB,ENJ-BNB,DATA-BTC,DATA-ETH,ONT-USDT,TRX-USDT,ETC-USDT,ETC-BNB,ICX-USDT,SC-BTC,SC-ETH,SC-BNB,NPXS-BTC,NPXS-ETH,VEN-USDT,KEY-BTC,KEY-ETH,NAS-BTC,NAS-ETH,NAS-BNB,MFT-BTC,MFT-ETH,MFT-BNB,DENT-BTC,DENT-ETH", + "AvailablePairs": "ETH-BTC,LTC-BTC,BNB-BTC,NEO-BTC,QTUM-ETH,EOS-ETH,SNT-ETH,BNT-ETH,BCC-BTC,GAS-BTC,BNB-ETH,BTC-USDT,ETH-USDT,HSR-BTC,OAX-ETH,DNT-ETH,MCO-ETH,ICN-ETH,MCO-BTC,WTC-BTC,WTC-ETH,LRC-BTC,LRC-ETH,QTUM-BTC,YOYO-BTC,OMG-BTC,OMG-ETH,ZRX-BTC,ZRX-ETH,STRAT-BTC,STRAT-ETH,SNGLS-BTC,SNGLS-ETH,BQX-BTC,BQX-ETH,KNC-BTC,KNC-ETH,FUN-BTC,FUN-ETH,SNM-BTC,SNM-ETH,NEO-ETH,IOTA-BTC,IOTA-ETH,LINK-BTC,LINK-ETH,XVG-BTC,XVG-ETH,SALT-BTC,SALT-ETH,MDA-BTC,MDA-ETH,MTL-BTC,MTL-ETH,SUB-BTC,SUB-ETH,EOS-BTC,SNT-BTC,ETC-ETH,ETC-BTC,MTH-BTC,MTH-ETH,ENG-BTC,ENG-ETH,DNT-BTC,ZEC-BTC,ZEC-ETH,BNT-BTC,AST-BTC,AST-ETH,DASH-BTC,DASH-ETH,OAX-BTC,ICN-BTC,BTG-BTC,BTG-ETH,EVX-BTC,EVX-ETH,REQ-BTC,REQ-ETH,VIB-BTC,VIB-ETH,HSR-ETH,TRX-BTC,TRX-ETH,POWR-BTC,POWR-ETH,ARK-BTC,ARK-ETH,YOYO-ETH,XRP-BTC,XRP-ETH,MOD-BTC,MOD-ETH,ENJ-BTC,ENJ-ETH,STORJ-BTC,STORJ-ETH,BNB-USDT,YOYO-BNB,POWR-BNB,KMD-BTC,KMD-ETH,NULS-BNB,RCN-BTC,RCN-ETH,RCN-BNB,NULS-BTC,NULS-ETH,RDN-BTC,RDN-ETH,RDN-BNB,XMR-BTC,XMR-ETH,DLT-BNB,WTC-BNB,DLT-BTC,DLT-ETH,AMB-BTC,AMB-ETH,AMB-BNB,BCC-ETH,BCC-USDT,BCC-BNB,BAT-BTC,BAT-ETH,BAT-BNB,BCPT-BTC,BCPT-ETH,BCPT-BNB,ARN-BTC,ARN-ETH,GVT-BTC,GVT-ETH,CDT-BTC,CDT-ETH,GXS-BTC,GXS-ETH,NEO-USDT,NEO-BNB,POE-BTC,POE-ETH,QSP-BTC,QSP-ETH,QSP-BNB,BTS-BTC,BTS-ETH,BTS-BNB,XZC-BTC,XZC-ETH,XZC-BNB,LSK-BTC,LSK-ETH,LSK-BNB,TNT-BTC,TNT-ETH,FUEL-BTC,FUEL-ETH,MANA-BTC,MANA-ETH,BCD-BTC,BCD-ETH,DGD-BTC,DGD-ETH,IOTA-BNB,ADX-BTC,ADX-ETH,ADX-BNB,ADA-BTC,ADA-ETH,PPT-BTC,PPT-ETH,CMT-BTC,CMT-ETH,CMT-BNB,XLM-BTC,XLM-ETH,XLM-BNB,CND-BTC,CND-ETH,CND-BNB,LEND-BTC,LEND-ETH,WABI-BTC,WABI-ETH,WABI-BNB,LTC-ETH,LTC-USDT,LTC-BNB,TNB-BTC,TNB-ETH,WAVES-BTC,WAVES-ETH,WAVES-BNB,GTO-BTC,GTO-ETH,GTO-BNB,ICX-BTC,ICX-ETH,ICX-BNB,OST-BTC,OST-ETH,OST-BNB,ELF-BTC,ELF-ETH,AION-BTC,AION-ETH,AION-BNB,NEBL-BTC,NEBL-ETH,NEBL-BNB,BRD-BTC,BRD-ETH,BRD-BNB,MCO-BNB,EDO-BTC,EDO-ETH,WINGS-BTC,WINGS-ETH,NAV-BTC,NAV-ETH,NAV-BNB,LUN-BTC,LUN-ETH,TRIG-BTC,TRIG-ETH,TRIG-BNB,APPC-BTC,APPC-ETH,APPC-BNB,VIBE-BTC,VIBE-ETH,RLC-BTC,RLC-ETH,RLC-BNB,INS-BTC,INS-ETH,PIVX-BTC,PIVX-ETH,PIVX-BNB,IOST-BTC,IOST-ETH,CHAT-BTC,CHAT-ETH,STEEM-BTC,STEEM-ETH,STEEM-BNB,NANO-BTC,NANO-ETH,NANO-BNB,VIA-BTC,VIA-ETH,VIA-BNB,BLZ-BTC,BLZ-ETH,BLZ-BNB,AE-BTC,AE-ETH,AE-BNB,RPX-BTC,RPX-ETH,RPX-BNB,NCASH-BTC,NCASH-ETH,NCASH-BNB,POA-BTC,POA-ETH,POA-BNB,ZIL-BTC,ZIL-ETH,ZIL-BNB,ONT-BTC,ONT-ETH,ONT-BNB,STORM-BTC,STORM-ETH,STORM-BNB,QTUM-BNB,QTUM-USDT,XEM-BTC,XEM-ETH,XEM-BNB,WAN-BTC,WAN-ETH,WAN-BNB,WPR-BTC,WPR-ETH,QLC-BTC,QLC-ETH,SYS-BTC,SYS-ETH,SYS-BNB,QLC-BNB,GRS-BTC,GRS-ETH,ADA-USDT,ADA-BNB,CLOAK-BTC,CLOAK-ETH,GNT-BTC,GNT-ETH,GNT-BNB,LOOM-BTC,LOOM-ETH,LOOM-BNB,XRP-USDT,BCN-BTC,BCN-ETH,BCN-BNB,REP-BTC,REP-ETH,REP-BNB,TUSD-BTC,TUSD-ETH,TUSD-BNB,ZEN-BTC,ZEN-ETH,ZEN-BNB,SKY-BTC,SKY-ETH,SKY-BNB,EOS-USDT,EOS-BNB,CVC-BTC,CVC-ETH,CVC-BNB,THETA-BTC,THETA-ETH,THETA-BNB,XRP-BNB,TUSD-USDT,IOTA-USDT,XLM-USDT,IOTX-BTC,IOTX-ETH,QKC-BTC,QKC-ETH,AGI-BTC,AGI-ETH,AGI-BNB,NXS-BTC,NXS-ETH,NXS-BNB,ENJ-BNB,DATA-BTC,DATA-ETH,ONT-USDT,TRX-USDT,ETC-USDT,ETC-BNB,ICX-USDT,SC-BTC,SC-ETH,SC-BNB,NPXS-BTC,NPXS-ETH,KEY-BTC,KEY-ETH,NAS-BTC,NAS-ETH,NAS-BNB,MFT-BTC,MFT-ETH,MFT-BNB,DENT-BTC,DENT-ETH,ARDR-BTC,ARDR-ETH,ARDR-BNB,NULS-USDT,HOT-BTC,HOT-ETH,VET-BTC,VET-ETH,VET-USDT,VET-BNB,DOCK-BTC,DOCK-ETH,POLY-BTC,POLY-BNB", "EnabledPairs": "BTC-USDT", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -206,7 +206,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC,BTCEUR,BTCJPY,XRPUSD,XRPBTC,IOTUSD,IOTBTC,IOTETH,EOSUSD,EOSBTC,EOSETH,SANUSD,SANBTC,SANETH,OMGUSD,OMGBTC,OMGETH,BCHUSD,BCHBTC,BCHETH,NEOUSD,NEOBTC,NEOETH,ETPUSD,ETPBTC,ETPETH,QTMUSD,QTMBTC,QTMETH,AVTUSD,AVTBTC,AVTETH,EDOUSD,EDOBTC,EDOETH,BTGUSD,BTGBTC,DATUSD,DATBTC,DATETH,QSHUSD,QSHBTC,QSHETH,YYWUSD,YYWBTC,YYWETH,GNTUSD,GNTBTC,GNTETH,SNTUSD,SNTBTC,SNTETH,IOTEUR,BATUSD,BATBTC,BATETH,MNAUSD,MNABTC,MNAETH,FUNUSD,FUNBTC,FUNETH,ZRXUSD,ZRXBTC,ZRXETH,TNBUSD,TNBBTC,TNBETH,SPKUSD,SPKBTC,SPKETH,TRXUSD,TRXBTC,TRXETH,RCNUSD,RCNBTC,RCNETH,RLCUSD,RLCBTC,RLCETH,AIDUSD,AIDBTC,AIDETH,SNGUSD,SNGBTC,SNGETH,REPUSD,REPBTC,REPETH,ELFUSD,ELFBTC,ELFETH,BTCGBP,ETHEUR,ETHJPY,ETHGBP,NEOEUR,NEOJPY,NEOGBP,EOSEUR,EOSJPY,EOSGBP,IOTJPY,IOTGBP,IOSUSD,IOSBTC,IOSETH,AIOUSD,AIOBTC,AIOETH,REQUSD,REQBTC,REQETH,RDNUSD,RDNBTC,RDNETH,LRCUSD,LRCBTC,LRCETH,WAXUSD,WAXBTC,WAXETH,DAIUSD,DAIBTC,DAIETH,CFIUSD,CFIBTC,CFIETH,AGIUSD,AGIBTC,AGIETH,BFTUSD,BFTBTC,BFTETH,MTNUSD,MTNBTC,MTNETH,ODEUSD,ODEBTC,ODEETH,ANTUSD,ANTBTC,ANTETH,DTHUSD,DTHBTC,DTHETH,MITUSD,MITBTC,MITETH,STJUSD,STJBTC,STJETH,XLMUSD,XLMEUR,XLMJPY,XLMGBP,XLMBTC,XLMETH,XVGUSD,XVGEUR,XVGJPY,XVGGBP,XVGBTC,XVGETH,BCIUSD,BCIBTC,MKRUSD,MKRBTC,MKRETH,VENUSD,VENBTC,VENETH,KNCUSD,KNCBTC,KNCETH,POAUSD,POABTC,POAETH,LYMUSD,LYMBTC,LYMETH,UTKUSD,UTKBTC,UTKETH,VEEUSD,VEEBTC,VEEETH,DADUSD,DADBTC,DADETH,ORSUSD,ORSBTC,ORSETH,AUCUSD,AUCBTC,AUCETH,POYUSD,POYBTC,POYETH,FSNUSD,FSNBTC,FSNETH,CBTUSD,CBTBTC,CBTETH,ZCNUSD,ZCNBTC,ZCNETH,SENUSD,SENBTC,SENETH,NCAUSD,NCABTC,NCAETH,CNDUSD,CNDBTC,CNDETH,CTXUSD,CTXBTC,CTXETH,PAIUSD,PAIBTC,SEEUSD,SEEBTC,SEEETH,ESSUSD,ESSBTC,ESSETH,ATMUSD,ATMBTC,ATMETH,HOTUSD,HOTBTC,HOTETH,DTAUSD,DTABTC,DTAETH", + "AvailablePairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC,ETCBTC,ETCUSD,RRTUSD,RRTBTC,ZECUSD,ZECBTC,XMRUSD,XMRBTC,DSHUSD,DSHBTC,BTCEUR,BTCJPY,XRPUSD,XRPBTC,IOTUSD,IOTBTC,IOTETH,EOSUSD,EOSBTC,EOSETH,SANUSD,SANBTC,SANETH,OMGUSD,OMGBTC,OMGETH,BCHUSD,BCHBTC,BCHETH,NEOUSD,NEOBTC,NEOETH,ETPUSD,ETPBTC,ETPETH,QTMUSD,QTMBTC,QTMETH,AVTUSD,AVTBTC,AVTETH,EDOUSD,EDOBTC,EDOETH,BTGUSD,BTGBTC,DATUSD,DATBTC,DATETH,QSHUSD,QSHBTC,QSHETH,YYWUSD,YYWBTC,YYWETH,GNTUSD,GNTBTC,GNTETH,SNTUSD,SNTBTC,SNTETH,IOTEUR,BATUSD,BATBTC,BATETH,MNAUSD,MNABTC,MNAETH,FUNUSD,FUNBTC,FUNETH,ZRXUSD,ZRXBTC,ZRXETH,TNBUSD,TNBBTC,TNBETH,SPKUSD,SPKBTC,SPKETH,TRXUSD,TRXBTC,TRXETH,RCNUSD,RCNBTC,RCNETH,RLCUSD,RLCBTC,RLCETH,AIDUSD,AIDBTC,AIDETH,SNGUSD,SNGBTC,SNGETH,REPUSD,REPBTC,REPETH,ELFUSD,ELFBTC,ELFETH,BTCGBP,ETHEUR,ETHJPY,ETHGBP,NEOEUR,NEOJPY,NEOGBP,EOSEUR,EOSJPY,EOSGBP,IOTJPY,IOTGBP,IOSUSD,IOSBTC,IOSETH,AIOUSD,AIOBTC,AIOETH,REQUSD,REQBTC,REQETH,RDNUSD,RDNBTC,RDNETH,LRCUSD,LRCBTC,LRCETH,WAXUSD,WAXBTC,WAXETH,DAIUSD,DAIBTC,DAIETH,CFIUSD,CFIBTC,CFIETH,AGIUSD,AGIBTC,AGIETH,BFTUSD,BFTBTC,BFTETH,MTNUSD,MTNBTC,MTNETH,ODEUSD,ODEBTC,ODEETH,ANTUSD,ANTBTC,ANTETH,DTHUSD,DTHBTC,DTHETH,MITUSD,MITBTC,MITETH,STJUSD,STJBTC,STJETH,XLMUSD,XLMEUR,XLMJPY,XLMGBP,XLMBTC,XLMETH,XVGUSD,XVGEUR,XVGJPY,XVGGBP,XVGBTC,XVGETH,BCIUSD,BCIBTC,MKRUSD,MKRBTC,MKRETH,VENUSD,VENBTC,VENETH,KNCUSD,KNCBTC,KNCETH,POAUSD,POABTC,POAETH,LYMUSD,LYMBTC,LYMETH,UTKUSD,UTKBTC,UTKETH,VEEUSD,VEEBTC,VEEETH,DADUSD,DADBTC,DADETH,ORSUSD,ORSBTC,ORSETH,AUCUSD,AUCBTC,AUCETH,POYUSD,POYBTC,POYETH,FSNUSD,FSNBTC,FSNETH,CBTUSD,CBTBTC,CBTETH,ZCNUSD,ZCNBTC,ZCNETH,SENUSD,SENBTC,SENETH,NCAUSD,NCABTC,NCAETH,CNDUSD,CNDBTC,CNDETH,CTXUSD,CTXBTC,CTXETH,PAIUSD,PAIBTC,SEEUSD,SEEBTC,SEEETH,ESSUSD,ESSBTC,ESSETH,ATMUSD,ATMBTC,ATMETH,HOTUSD,HOTBTC,HOTETH,DTAUSD,DTABTC,DTAETH,IQXUSD,IQXBTC,IQXEOS,WPRUSD,WPRBTC,WPRETH,ZILUSD,ZILBTC,ZILETH,BNTUSD,BNTBTC,BNTETH", "EnabledPairs": "BTCUSD,LTCUSD,LTCBTC,ETHUSD,ETHBTC", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -357,7 +357,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BTC-LTC,BTC-DOGE,BTC-VTC,BTC-PPC,BTC-FTC,BTC-RDD,BTC-NXT,BTC-DASH,BTC-POT,BTC-BLK,BTC-EMC2,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-VRC,BTC-CURE,BTC-XMR,BTC-CLOAK,BTC-KORE,BTC-XDN,BTC-TRUST,BTC-NAV,BTC-XST,BTC-VIA,BTC-PINK,BTC-IOC,BTC-CANN,BTC-SYS,BTC-NEOS,BTC-DGB,BTC-BURST,BTC-EXCL,BTC-BITS,BTC-DOPE,BTC-BLOCK,BTC-ABY,BTC-BYC,BTC-XMG,BTC-BAY,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-AEON,BTC-ETH,BTC-TX,BTC-BCY,BTC-EXP,BTC-OMNI,BTC-AMP,BTC-XLM,USDT-BTC,BTC-RVR,BTC-EMC,BTC-FCT,BTC-EGC,BTC-SLS,BTC-RADS,BTC-DCR,BTC-BSD,BTC-XVG,BTC-PIVX,BTC-MEME,BTC-STEEM,BTC-2GIVE,BTC-LSK,BTC-BRK,BTC-WAVES,BTC-LBC,BTC-SBD,BTC-BRX,BTC-ETC,ETH-ETC,BTC-STRAT,BTC-UNB,BTC-SYNX,BTC-EBST,BTC-VRM,BTC-SEQ,BTC-REP,BTC-SHIFT,BTC-ARDR,BTC-XZC,BTC-NEO,BTC-ZEC,BTC-ZCL,BTC-IOP,BTC-GOLOS,BTC-UBQ,BTC-KMD,BTC-GBG,BTC-SIB,BTC-ION,BTC-LMC,BTC-QWARK,BTC-CRW,BTC-SWT,BTC-MLN,BTC-ARK,BTC-DYN,BTC-TKS,BTC-MUSIC,BTC-DTB,BTC-INCNT,BTC-GBYTE,BTC-GNT,BTC-NXC,BTC-EDG,BTC-MORE,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-GNO,BTC-HMQ,BTC-ANT,ETH-ANT,BTC-SC,ETH-BAT,BTC-BAT,BTC-ZEN,BTC-QRL,BTC-CRB,ETH-MORE,BTC-PTOY,BTC-CFI,ETH-CFI,BTC-BNT,ETH-BNT,BTC-NMR,ETH-LTC,ETH-XRP,BTC-SNT,ETH-SNT,BTC-DCT,BTC-XEL,BTC-MCO,ETH-MCO,BTC-ADT,ETH-ADT,BTC-PAY,ETH-PAY,BTC-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-BCH,USDT-BCH,BTC-BCH,BTC-DNT,ETH-DNT,USDT-NEO,ETH-WAVES,ETH-STRAT,ETH-DGB,ETH-FCT,USDT-OMG,BTC-ADA,BTC-MANA,ETH-MANA,BTC-SALT,ETH-SALT,BTC-TIX,ETH-TIX,BTC-RCN,ETH-RCN,BTC-VIB,ETH-VIB,BTC-MER,BTC-POWR,ETH-POWR,BTC-BTG,ETH-BTG,USDT-BTG,ETH-ADA,BTC-ENG,ETH-ENG,USDT-ADA,USDT-XVG,USDT-NXT,BTC-UKG,ETH-UKG,BTC-IGNIS,BTC-SRN,ETH-SRN,BTC-WAX,ETH-WAX,BTC-ZRX,ETH-ZRX,BTC-VEE,ETH-VEE,BTC-BCPT,ETH-BCPT,BTC-TRX,ETH-TRX,BTC-TUSD,BTC-LRC,ETH-LRC,ETH-TUSD,BTC-UP,ETH-UP,BTC-DMT,ETH-DMT,USDT-TUSD,BTC-POLY,ETH-POLY,BTC-PRO,ETH-PRO,USDT-SC,USDT-TRX,BTC-BLT,ETH-BLT,BTC-STORM,ETH-STORM,BTC-AID,ETH-AID,BTC-NGC,ETH-NGC,BTC-GTO,ETH-GTO,USDT-DCR,BTC-OCN,ETH-OCN,USD-BTC,USD-USDT,USD-TUSD,BTC-TUBE,BTC-CBC,BTC-CMCT,USD-ETH,BTC-NLC2,BTC-BKX,BTC-MFT", + "AvailablePairs": "BTC-LTC,BTC-DOGE,BTC-VTC,BTC-PPC,BTC-FTC,BTC-RDD,BTC-NXT,BTC-DASH,BTC-POT,BTC-BLK,BTC-EMC2,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-VRC,BTC-CURE,BTC-XMR,BTC-CLOAK,BTC-KORE,BTC-XDN,BTC-TRUST,BTC-NAV,BTC-XST,BTC-VIA,BTC-PINK,BTC-IOC,BTC-CANN,BTC-SYS,BTC-NEOS,BTC-DGB,BTC-BURST,BTC-EXCL,BTC-BITS,BTC-DOPE,BTC-BLOCK,BTC-ABY,BTC-BYC,BTC-XMG,BTC-BAY,BTC-SPR,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-AEON,BTC-ETH,BTC-TX,BTC-BCY,BTC-EXP,BTC-OMNI,BTC-AMP,BTC-XLM,USDT-BTC,BTC-RVR,BTC-EMC,BTC-FCT,BTC-EGC,BTC-SLS,BTC-RADS,BTC-DCR,BTC-BSD,BTC-XVG,BTC-PIVX,BTC-MEME,BTC-STEEM,BTC-2GIVE,BTC-LSK,BTC-BRK,BTC-WAVES,BTC-LBC,BTC-SBD,BTC-BRX,BTC-ETC,ETH-ETC,BTC-STRAT,BTC-UNB,BTC-SYNX,BTC-EBST,BTC-VRM,BTC-SEQ,BTC-REP,BTC-SHIFT,BTC-ARDR,BTC-XZC,BTC-NEO,BTC-ZEC,BTC-ZCL,BTC-IOP,BTC-GOLOS,BTC-UBQ,BTC-KMD,BTC-GBG,BTC-SIB,BTC-ION,BTC-LMC,BTC-QWARK,BTC-CRW,BTC-SWT,BTC-MLN,BTC-ARK,BTC-DYN,BTC-TKS,BTC-MUSIC,BTC-DTB,BTC-INCNT,BTC-GBYTE,BTC-GNT,BTC-NXC,BTC-EDG,BTC-MORE,ETH-GNT,ETH-REP,USDT-ETH,BTC-WINGS,BTC-RLC,BTC-GNO,BTC-GUP,BTC-LUN,ETH-RLC,ETH-LUN,ETH-GNO,BTC-HMQ,BTC-ANT,ETH-ANT,BTC-SC,ETH-BAT,BTC-BAT,BTC-ZEN,BTC-QRL,BTC-CRB,ETH-MORE,BTC-PTOY,BTC-CFI,BTC-BNT,ETH-BNT,BTC-NMR,ETH-LTC,ETH-XRP,BTC-SNT,ETH-SNT,BTC-DCT,BTC-XEL,BTC-MCO,ETH-MCO,BTC-ADT,BTC-PAY,ETH-PAY,BTC-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-BCH,USDT-BCH,BTC-BCH,BTC-DNT,USDT-NEO,ETH-WAVES,ETH-STRAT,ETH-DGB,ETH-FCT,USDT-OMG,BTC-ADA,BTC-MANA,ETH-MANA,BTC-SALT,ETH-SALT,BTC-TIX,BTC-RCN,ETH-RCN,BTC-VIB,ETH-VIB,BTC-MER,BTC-POWR,ETH-POWR,BTC-BTG,ETH-BTG,USDT-BTG,ETH-ADA,BTC-ENG,ETH-ENG,USDT-ADA,USDT-XVG,USDT-NXT,BTC-UKG,ETH-UKG,BTC-IGNIS,BTC-SRN,ETH-SRN,BTC-WAX,ETH-WAX,BTC-ZRX,ETH-ZRX,BTC-VEE,ETH-VEE,BTC-BCPT,ETH-BCPT,BTC-TRX,ETH-TRX,BTC-TUSD,BTC-LRC,ETH-LRC,ETH-TUSD,BTC-UP,ETH-UP,BTC-DMT,ETH-DMT,USDT-TUSD,BTC-POLY,ETH-POLY,BTC-PRO,ETH-PRO,USDT-SC,USDT-TRX,BTC-BLT,ETH-BLT,BTC-STORM,ETH-STORM,BTC-AID,ETH-AID,BTC-NGC,ETH-NGC,BTC-GTO,ETH-GTO,USDT-DCR,BTC-OCN,ETH-OCN,USD-BTC,USD-USDT,USD-TUSD,BTC-TUBE,BTC-CBC,BTC-CMCT,USD-ETH,BTC-NLC2,BTC-BKX,BTC-MFT,BTC-LOOM,BTC-RFR,USDT-DGB", "EnabledPairs": "USDT-BTC", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -533,7 +533,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "DASH_RUB,ETC_BTC,ETC_USD,LTC_RUB,XMR_EUR,XLM_USD,STQ_RUB,BCH_ETH,ETH_USD,ETH_EUR,ZEC_EUR,ZEC_RUB,KICK_ETH,HBZ_USD,ETH_UAH,LTC_BTC,BTC_USDT,XLM_BTC,BCH_RUB,LTC_USD,USDT_USD,STQ_BTC,ETH_RUB,ETH_USDT,DXT_BTC,DXT_USD,EOS_USD,LTC_EUR,ZEC_BTC,XMR_USD,BTC_PLN,DASH_USD,XMR_BTC,USD_RUB,DOGE_BTC,BCH_USD,ETH_LTC,KICK_BTC,BTC_RUB,USDT_RUB,BTC_UAH,HBZ_BTC,EOS_BTC,BTCZ_BTC,BCH_BTC,XRP_USD,XRP_RUB,BTC_USD,BTG_BTC,BTG_USD,DASH_BTC,ETH_BTC,XRP_BTC,ETH_PLN,ETC_RUB,WAVES_BTC,STQ_EUR,HBZ_ETH,BTC_EUR,XLM_RUB,STQ_USD,ZEC_USD,WAVES_RUB", + "AvailablePairs": "STQ_BTC,XRP_BTC,USDT_USD,XLM_USD,XLM_RUB,ZEC_BTC,ZEC_RUB,XMR_BTC,BCH_BTC,ETC_USD,LTC_USD,TRX_USD,DASH_BTC,BTG_USD,LTC_BTC,XRP_USD,ETH_USDT,WAVES_BTC,MNX_BTC,MNX_USD,USD_RUB,DOGE_BTC,MNX_ETH,ETH_UAH,STQ_EUR,BCH_USD,ETH_BTC,BTC_UAH,OMG_USD,ETH_EUR,ZEC_EUR,BTC_PLN,HBZ_ETH,HBZ_USD,ETC_RUB,XMR_EUR,BTC_USD,STQ_RUB,HBZ_BTC,USDT_RUB,BTC_EUR,TRX_BTC,ETC_BTC,BTCZ_BTC,DASH_RUB,WAVES_RUB,OMG_ETH,EOS_USD,DXT_BTC,DASH_USD,LTC_RUB,KICK_ETH,BTC_RUB,OMG_BTC,BTG_BTC,BCH_RUB,BCH_ETH,ETH_USD,ZEC_USD,BTC_USDT,TRX_RUB,XLM_BTC,XRP_RUB,XMR_USD,ETH_PLN,LTC_EUR,KICK_BTC,DXT_USD,ETH_RUB,ETH_LTC,EOS_BTC,STQ_USD", "EnabledPairs": "BTC_USD,LTC_USD", "BaseCurrencies": "USD,EUR,RUB,PLN,UAH", "AssetTypes": "SPOT", @@ -595,6 +595,42 @@ } ] }, + { + "Name": "GateIO", + "Enabled": true, + "Verbose": false, + "Websocket": false, + "UseSandbox": false, + "RESTPollingDelay": 10, + "HTTPTimeout": 15000000000, + "AuthenticatedAPISupport": false, + "APIKey": "Key", + "APISecret": "Secret", + "AvailablePairs": "BTC_USDT,BCH_USDT,ETH_USDT,ETC_USDT,QTUM_USDT,LTC_USDT,DASH_USDT,ZEC_USDT,BTM_USDT,EOS_USDT,REQ_USDT,SNT_USDT,OMG_USDT,PAY_USDT,CVC_USDT,ZRX_USDT,TNT_USDT,XMR_USDT,XRP_USDT,DOGE_USDT,BAT_USDT,PST_USDT,BTG_USDT,DPY_USDT,LRC_USDT,STORJ_USDT,RDN_USDT,STX_USDT,KNC_USDT,LINK_USDT,CDT_USDT,AE_USDT,AE_ETH,AE_BTC,CDT_ETH,RDN_ETH,STX_ETH,KNC_ETH,LINK_ETH,REQ_ETH,RCN_ETH,TRX_ETH,ARN_ETH,KICK_ETH,BNT_ETH,VET_ETH,MCO_ETH,FUN_ETH,DATA_ETH,RLC_ETH,RLC_USDT,ZSC_ETH,WINGS_ETH,MDA_ETH,RCN_USDT,TRX_USDT,KICK_USDT,VET_USDT,MCO_USDT,FUN_USDT,DATA_USDT,ZSC_USDT,MDA_USDT,XTZ_USDT,XTZ_BTC,XTZ_ETH,GNT_USDT,GNT_ETH,GEM_USDT,GEM_ETH,RFR_USDT,RFR_ETH,DADI_USDT,DADI_ETH,ABT_USDT,ABT_ETH,LEDU_BTC,LEDU_ETH,OST_USDT,OST_ETH,XLM_USDT,XLM_ETH,XLM_BTC,MOBI_USDT,MOBI_ETH,MOBI_BTC,OCN_USDT,OCN_ETH,OCN_BTC,ZPT_USDT,ZPT_ETH,ZPT_BTC,COFI_USDT,COFI_ETH,JNT_USDT,JNT_ETH,JNT_BTC,BLZ_USDT,BLZ_ETH,GXS_USDT,GXS_BTC,MTN_USDT,MTN_ETH,RUFF_USDT,RUFF_ETH,RUFF_BTC,TNC_USDT,TNC_ETH,TNC_BTC,ZIL_USDT,ZIL_ETH,TIO_USDT,TIO_ETH,BTO_USDT,BTO_ETH,THETA_USDT,THETA_ETH,DDD_USDT,DDD_ETH,DDD_BTC,MKR_USDT,MKR_ETH,DAI_USDT,SMT_USDT,SMT_ETH,MDT_USDT,MDT_ETH,MDT_BTC,MANA_USDT,MANA_ETH,LUN_USDT,LUN_ETH,SALT_USDT,SALT_ETH,FUEL_USDT,FUEL_ETH,ELF_USDT,ELF_ETH,DRGN_USDT,DRGN_ETH,GTC_USDT,GTC_ETH,GTC_BTC,QLC_USDT,QLC_BTC,QLC_ETH,DBC_USDT,DBC_BTC,DBC_ETH,BNTY_USDT,BNTY_ETH,LEND_USDT,LEND_ETH,ICX_USDT,ICX_ETH,BTF_USDT,BTF_BTC,ADA_USDT,ADA_BTC,LSK_USDT,LSK_BTC,WAVES_USDT,WAVES_BTC,BIFI_USDT,BIFI_BTC,MDS_ETH,MDS_USDT,DGD_USDT,DGD_ETH,QASH_USDT,QASH_ETH,QASH_BTC,POWR_USDT,POWR_ETH,POWR_BTC,FIL_USDT,BCD_USDT,BCD_BTC,SBTC_USDT,SBTC_BTC,GOD_USDT,GOD_BTC,BCX_USDT,BCX_BTC,HSR_USDT,HSR_BTC,HSR_ETH,QSP_USDT,QSP_ETH,INK_BTC,INK_USDT,INK_ETH,INK_QTUM,MED_QTUM,MED_ETH,MED_USDT,BOT_QTUM,BOT_USDT,BOT_ETH,QBT_QTUM,QBT_ETH,QBT_USDT,TSL_QTUM,TSL_USDT,GNX_USDT,GNX_ETH,NEO_USDT,GAS_USDT,NEO_BTC,GAS_BTC,IOTA_USDT,IOTA_BTC,NAS_USDT,NAS_ETH,NAS_BTC,ETH_BTC,ETC_BTC,ETC_ETH,ZEC_BTC,DASH_BTC,LTC_BTC,BCH_BTC,BTG_BTC,QTUM_BTC,QTUM_ETH,XRP_BTC,DOGE_BTC,XMR_BTC,ZRX_BTC,ZRX_ETH,DNT_ETH,DPY_ETH,OAX_ETH,REP_ETH,LRC_ETH,LRC_BTC,PST_ETH,BCDN_ETH,BCDN_USDT,TNT_ETH,SNT_ETH,SNT_BTC,BTM_ETH,BTM_BTC,LLT_ETH,SNET_ETH,SNET_USDT,LLT_SNET,OMG_ETH,OMG_BTC,PAY_ETH,PAY_BTC,BAT_ETH,BAT_BTC,CVC_ETH,STORJ_ETH,STORJ_BTC,EOS_ETH,EOS_BTC,BTS_USDT,BTS_BTC,TIPS_ETH,BU_USDT,BU_ETH,XMC_USDT,XMC_BTC,PPS_USDT,BOE_ETH,BOE_USDT,PLY_ETH,MEDX_USDT,MEDX_ETH,CS_ETH,CS_USDT,MAN_ETH,MAN_USDT,REM_ETH,REM_USDT,LYM_ETH,LYM_BTC,LYM_USDT,ONT_ETH,ONT_USDT,BFT_ETH,BFT_USDT,IHT_ETH,IHT_USDT,SENC_ETH,SENC_USDT,TOMO_ETH,TOMO_USDT,ELEC_ETH,ELEC_USDT,HAV_ETH,HAV_USDT,SWTH_ETH,SWTH_USDT,NKN_ETH,NKN_USDT,SOUL_ETH,SOUL_USDT,LRN_ETH,LRN_USDT,EOSDAC_ETH,EOSDAC_USDT,ADD_ETH,IQ_ETH,MEETONE_ETH,DOCK_USDT,DOCK_ETH,GSE_USDT,GSE_ETH,RATING_USDT,RATING_ETH,HSC_USDT,HSC_ETH,GARD_USDT,GARD_ETH,FTI_USDT,FTI_ETH,SOP_ETH,SOP_USDT,LEMO_USDT,LEMO_ETH,EON_ETH,NPXS_ETH,QKC_USDT,QKC_ETH,IOTX_USDT,IOTX_ETH,RED_USDT,RED_ETH,LBA_USDT,LBA_ETH,OPEN_USDT,OPEN_ETH,MITH_USDT,MITH_ETH,SKM_USDT,SKM_ETH,XVG_USDT,XVG_BTC,NANO_USDT,NANO_BTC,NBAI_ETH,UPP_ETH,ATMI_ETH,TMT_ETH,HT_USDT,BNB_USDT,BBK_ETH,EDR_ETH,MET_ETH,MET_USDT,TCT_ETH,TCT_USDT", + "EnabledPairs": "BTC_USDT", + "BaseCurrencies": "USD", + "AssetTypes": "SPOT", + "SupportsAutoPairUpdates": true, + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + }, + "BankAccounts": [ + { + "BankName": "", + "BankAddress": "", + "AccountName": "", + "AccountNumber": "", + "SWIFTCode": "", + "IBAN": "", + "SupportedCurrencies": "" + } + ] + }, { "Name": "Gemini", "Enabled": true, @@ -640,7 +676,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "BCN-BTC,BTC-USD,DASH-BTC,DOGE-BTC,DOGE-USD,DSH-BTC,EMC-BTC,ETH-BTC,FCN-BTC,LSK-BTC,LTC-BTC,LTC-USD,NXT-BTC,SBD-BTC,SC-BTC,STEEM-BTC,XDN-BTC,XEM-BTC,XMR-BTC,ARDR-BTC,ZEC-BTC,WAVES-BTC,MAID-BTC,AMP-BTC,BUS-BTC,DGD-BTC,ICN-BTC,SNGLS-BTC,1ST-BTC,TRST-BTC,TIME-BTC,GNO-BTC,REP-BTC,XMR-USD,DASH-USD,ETH-USD,NXT-USD,ZRC-BTC,BOS-BTC,DCT-BTC,ANT-BTC,AEON-BTC,GUP-BTC,PLU-BTC,LUN-BTC,TAAS-BTC,NXC-BTC,EDG-BTC,RLC-BTC,SWT-BTC,TKN-BTC,WINGS-BTC,XAUR-BTC,AE-BTC,PTOY-BTC,ZEC-USD,XEM-USD,BCN-USD,XDN-USD,MAID-USD,ETC-BTC,ETC-USD,CFI-BTC,PLBT-BTC,BNT-BTC,XDNCO-BTC,FYN-ETH,SNM-BTC,SNM-ETH,SNT-ETH,CVC-USD,PAY-ETH,OAX-ETH,OMG-ETH,BQX-ETH,XTZ-BTC,DICE-BTC,CFI-ETH,PTOY-ETH,1ST-ETH,XAUR-ETH,TAAS-ETH,TIME-ETH,DICE-ETH,SWT-ETH,XMR-ETH,ETC-ETH,DASH-ETH,ZEC-ETH,PLU-ETH,GNO-ETH,XRP-BTC,NET-ETH,STRAT-USD,STRAT-BTC,SNC-ETH,ADX-ETH,BET-ETH,EOS-ETH,DENT-ETH,SAN-ETH,EOS-BTC,EOS-USD,MNE-BTC,MSP-ETH,DDF-ETH,XTZ-ETH,XTZ-USD,UET-ETH,MYB-ETH,SUR-ETH,IXT-ETH,PLR-ETH,TIX-ETH,NDC-ETH,PRO-ETH,AVT-ETH,COSS-ETH,EVX-USD,DLT-BTC,BNT-ETH,BNT-USD,QAU-BTC,QAU-ETH,MANA-USD,DNT-BTC,FYP-BTC,OPT-BTC,TNT-ETH,IFT-BTC,STX-BTC,STX-ETH,STX-USD,TNT-USD,TNT-BTC,CAT-BTC,CAT-ETH,CAT-USD,BCH-BTC,BCH-ETH,BCH-USD,ENG-ETH,XUC-USD,SNC-BTC,SNC-USD,OAX-USD,OAX-BTC,BAS-ETH,ZRX-BTC,ZRX-ETH,ZRX-USD,RVT-BTC,ICOS-BTC,ICOS-ETH,ICOS-USD,PPC-BTC,PPC-USD,QTUM-ETH,VERI-BTC,VERI-ETH,VERI-USD,IGNIS-ETH,PRG-BTC,PRG-ETH,PRG-USD,BMC-BTC,BMC-ETH,BMC-USD,CND-BTC,CND-ETH,CND-USD,SKIN-BTC,EMGO-BTC,EMGO-USD,CDT-ETH,CDT-USD,FUN-BTC,FUN-ETH,FUN-USD,HVN-BTC,HVN-ETH,FUEL-BTC,FUEL-ETH,FUEL-USD,POE-BTC,POE-ETH,MCAP-BTC,AIR-BTC,AIR-ETH,AIR-USD,AMB-USD,AMB-ETH,AMB-BTC,NTO-BTC,ICO-BTC,PING-BTC,GAME-BTC,TKR-ETH,HPC-BTC,PPT-ETH,MTH-BTC,MTH-ETH,WMGO-BTC,WMGO-USD,LRC-BTC,LRC-ETH,ICX-BTC,ICX-ETH,NEO-BTC,NEO-ETH,NEO-USD,CSNO-BTC,ORME-BTC,ICX-USD,PIX-BTC,PIX-ETH,IND-ETH,KICK-BTC,YOYOW-BTC,MIPS-BTC,CDT-BTC,XVG-BTC,XVG-ETH,XVG-USD,DGB-BTC,DGB-ETH,DGB-USD,DCN-BTC,DCN-ETH,DCN-USD,CCT-ETH,EBET-ETH,VIBE-BTC,VOISE-BTC,ENJ-BTC,ENJ-ETH,ENJ-USD,ZSC-BTC,ZSC-ETH,ZSC-USD,ETBS-BTC,VEN-BTC,VEN-ETH,VEN-USD,ART-BTC,EVX-BTC,EVX-ETH,QVT-ETH,EBTCOLD-BTC,EBTCOLD-ETH,EBTCOLD-USD,BKB-BTC,EXN-BTC,TGT-BTC,ATS-ETH,BMT-BTC,BMT-ETH,SUB-BTC,SUB-ETH,SUB-USD,WTC-BTC,CNX-BTC,ATB-BTC,ATB-ETH,ATB-USD,ODN-BTC,BTM-BTC,BTM-ETH,BTM-USD,B2X-BTC,B2X-ETH,B2X-USD,ATM-BTC,ATM-ETH,ATM-USD,LIFE-BTC,VIB-BTC,VIB-ETH,VIB-USD,DRT-ETH,STU-USD,OMG-BTC,PAY-BTC,COSS-BTC,PPT-BTC,SNT-BTC,BTG-BTC,BTG-ETH,BTG-USD,SMART-BTC,SMART-ETH,SMART-USD,XUC-ETH,XUC-BTC,CL-BTC,CL-ETH,CL-USD,LA-ETH,CLD-BTC,CLD-ETH,CLD-USD,EDO-BTC,EDO-ETH,EDO-USD,HGT-ETH,POLL-BTC,IXT-BTC,ATS-BTC,SCL-BTC,ATL-BTC,EBTC-BTC,EBTC-ETH,EBTC-USD,ETP-BTC,ETP-ETH,ETP-USD,OTX-BTC,CDX-ETH,DRPU-BTC,NEBL-BTC,NEBL-ETH,HAC-BTC,CTX-BTC,CTX-ETH,ELE-BTC,ARN-BTC,ARN-ETH,STU-BTC,STU-ETH,GVT-ETH,INDI-BTC,BTX-BTC,LTC-ETH,BCN-ETH,MAID-ETH,NXT-ETH,STRAT-ETH,XDN-ETH,XEM-ETH,PLR-BTC,SUR-BTC,BQX-BTC,DOGE-ETH,ITS-BTC,AMM-BTC,AMM-ETH,AMM-USD,DBIX-BTC,PRE-BTC,KBR-BTC,TBT-BTC,ERO-BTC,SMS-BTC,SMS-ETH,SMS-USD,ZAP-BTC,DOV-BTC,DOV-ETH,DRPU-ETH,OTN-BTC,XRP-ETH,XRP-USD,HSR-BTC,LEND-BTC,LEND-ETH,SPF-BTC,SPF-ETH,SBTC-BTC,SBTC-ETH,WRC-BTC,WRC-ETH,WRC-USD,LOC-BTC,LOC-ETH,LOC-USD,SWFTC-BTC,SWFTC-ETH,SWFTC-USD,STAR-ETH,SBTC-USD,STORM-BTC,DIM-ETH,DIM-USD,DIM-BTC,NGC-BTC,NGC-ETH,NGC-USD,EMC-ETH,EMC-USD,MCO-BTC,MCO-ETH,MCO-USD,MANA-ETH,MANA-BTC,ECH-BTC,CPAY-ETH,DATA-BTC,DATA-ETH,DATA-USD,UTT-BTC,UTT-ETH,UTT-USD,KMD-BTC,KMD-ETH,KMD-USD,QTUM-USD,QTUM-BTC,SNT-USD,OMG-USD,EKO-BTC,EKO-ETH,ADX-BTC,ADX-USD,LSK-ETH,LSK-USD,PLR-USD,SUR-USD,BQX-USD,DRT-USD,REP-ETH,REP-USD,TIO-BTC,TIO-ETH,TIO-USD,WAX-BTC,WAX-ETH,WAX-USD,EET-BTC,EET-ETH,EET-USD,C20-BTC,C20-ETH,IDH-BTC,IDH-ETH,IPL-BTC,COV-BTC,COV-ETH,SENT-BTC,SENT-ETH,SENT-USD,SMT-BTC,SMT-ETH,SMT-USD,CVH-ETH,CVH-USD,CAS-BTC,CAS-ETH,CAS-USD,CHAT-BTC,CHAT-ETH,CHAT-USD,GRMD-BTC,AVH-BTC,TRAC-ETH,JNT-ETH,PCL-BTC,PCL-ETH,CLOUT-BTC,UTK-BTC,UTK-ETH,UTK-USD,GNX-ETH,CHSB-BTC,CHSB-ETH,AVH-ETH,DAY-BTC,DAY-ETH,DAY-USD,NEU-BTC,NEU-ETH,NEU-USD,AVH-USD,CLOUT-ETH,CLOUT-USD,TAU-BTC,MEK-BTC,FLP-BTC,FLP-ETH,FLP-USD,R-BTC,R-ETH,EKO-USD,BCPT-ETH,BCPT-USD,PKT-BTC,PKT-ETH,WLK-BTC,WLK-ETH,WLK-USD,EVN-BTC,CPG-BTC,CPG-ETH,BPTN-BTC,BPTN-ETH,BPTN-USD,BETR-BTC,BETR-ETH,ARCT-BTC,ARCT-USD,DBET-BTC,DBET-ETH,DBET-USD,RNTB-ETH,HAND-ETH,HAND-USD,BEZ-BTC,BEZ-ETH,BEZ-USD,ACO-ETH,CTE-BTC,CTE-ETH,CTE-USD,UTNP-BTC,UTNP-ETH,UTNP-USD,CPY-BTC,CPY-ETH,CHP-ETH,BCPT-BTC,ACT-BTC,ACT-ETH,ACT-USD,HIRE-ETH,ADA-BTC,ADA-ETH,ADA-USD,SIG-BTC,RPM-BTC,RPM-ETH,MTX-BTC,MTX-ETH,MTX-USD,BGG-BTC,BGG-ETH,BGG-USD,SETH-ETH,WIZ-BTC,WIZ-ETH,WIZ-USD,DADI-BTC,DADI-ETH,BDG-ETH,DATX-BTC,DATX-ETH,TRUE-BTC,DRG-BTC,DRG-ETH,BANCA-BTC,BANCA-ETH,ZAP-ETH,ZAP-USD,AUTO-BTC,NOAH-BTC,SOC-BTC,WILD-BTC,INSUR-BTC,INSUR-ETH,OCN-BTC,OCN-ETH,STQ-BTC,STQ-ETH,XLM-BTC,XLM-ETH,XLM-USD,IOTA-BTC,IOTA-ETH,IOTA-USD,DRT-BTC,MLD-BTC,MLD-ETH,MLD-USD,BETR-USD,CGC-ETH,ERT-BTC,CRPT-BTC,CRPT-USD,MESH-BTC,MESH-ETH,MESH-USD,HLW-ETH,IHT-BTC,IHT-ETH,IHT-USD,SCC-BTC,YCC-BTC,DAN-BTC,TEL-BTC,TEL-ETH,BUBO-BTC,BUBO-ETH,BUBO-USD,VIT-BTC,VIT-ETH,VIT-USD,NCT-BTC,NCT-ETH,NCT-USD,AXP-BTC,AXP-ETH,BMH-BTC,BANCA-USD,NOAH-ETH,NOAH-USD,HQX-BTC,LDC-BTC,XMO-BTC,XMO-USD,XMO-ETH,BERRY-BTC,BERRY-ETH,BERRY-USD,BSTN-BTC,BSTN-ETH,BSTN-USD,GBX-BTC,GBX-ETH,GBX-USD,SHIP-BTC,SHIP-ETH,NANO-BTC,NANO-ETH,NANO-USD,LNC-BTC,UNC-BTC,UNC-ETH,RPX-BTC,RPX-ETH,RPX-USD,KIN-ETH,ARDR-USD,DAXT-BTC,DAXT-ETH,FOTA-ETH,FOTA-BTC,SETH-BTC,CVT-BTC,CVT-ETH,CVT-USD,STQ-USD,GNT-BTC,GNT-ETH,GNT-USD,ADH-BTC,ADH-ETH,BBC-BTC,BBC-ETH,GET-BTC,MITH-BTC,MITH-ETH,MITH-USD,SUNC-ETH,DADI-USD,TKY-BTC,ACAT-BTC,ACAT-ETH,ACAT-USD,BTX-USD,TCN-BTC,VIO-ETH,WIKI-BTC,WIKI-ETH,WIKI-USD,ONT-BTC,ONT-ETH,ONT-USD,FTX-BTC,FTX-ETH,FREC-BTC,NAVI-BTC,FREC-ETH,FREC-USD,VME-ETH,NAVI-ETH,BTCP-BTC,LND-ETH,CSM-BTC,NANJ-BTC,MTC-BTC,MTC-ETH,MTC-USD,NTK-BTC,NTK-ETH,NTK-USD,AUC-BTC,AUC-ETH,CMCT-BTC,CMCT-ETH,CMCT-USD,MAN-BTC,MAN-ETH,MAN-USD,HIRE-BTC,TKA-BTC,TKA-ETH,TKA-USD,PNT-BTC,PNT-ETH,FXT-BTC,NEXO-BTC,CHX-BTC,CHX-ETH,CHX-USD,PAT-BTC,PAT-ETH,XMC-BTC,EJOY-BTC,EJOY-ETH,EJOY-USD,FXT-ETH,HERO-BTC,HERO-ETH,XMC-ETH,XMC-USD,STAK-BTC,STAK-ETH,FDZ-BTC,FDZ-ETH,FDZ-USD,SPD-BTC,SPD-ETH,LUC-BTC,MITX-BTC,TIV-BTC,B2G-BTC,B2G-USD,ZPT-BTC,ZPT-ETH,HBZ-BTC,FACE-BTC,FACE-ETH,HBZ-ETH,HBZ-USD,ZPT-USD,MORPH-BTC,MORPH-ETH,MORPH-USD,EBKC-BTC,CPT-BTC,PAT-USD,HTML-BTC,HTML-ETH,MITX-ETH,JOT-BTC,JBC-BTC,JBC-ETH,BTS-BTC,BNK-BTC,KBC-BTC,KBC-ETH,BNK-ETH,BNK-USD,TIV-ETH,TIV-USD,LUC-ETH,LUC-USD,CSM-ETH,CSM-USD,INK-BTC,IOST-BTC,INK-ETH,INK-USD,CBC-BTC,IOST-USD,COIN-BTC,ZIL-BTC,COIN-USD,COIN-ETH,PMNT-BTC,ABYSS-BTC,ABYSS-ETH,ZIL-USD,BCI-BTC,CBC-ETH,CBC-USD,PITCH-BTC,PITCH-ETH,HTML-USD,TDS-BTC,TDS-ETH,TDS-USD,SBD-ETH,SBD-USD,DPN-BTC,UUU-BTC,UUU-ETH,XBP-BTC,KRM-USD,CLN-BTC,IVY-BTC,IVY-ETH,TTU-BTC,TTU-ETH,TTU-USD,CLN-ETH,DOR-BTC,DOR-ETH,DOR-USD,ELEC-BTC,ELEC-ETH,ELEC-USD,QNTU-BTC,QNTU-ETH,QNTU-USD,IPL-ETH,IPL-USD,CENNZ-BTC,BTCP-ETH,BTCP-USD,CENNZ-ETH,SWM-BTC,MXM-BTC,MXM-ETH,SPF-USD,LCC-BTC,HGT-BTC,BTC-TUSD,XMR-TUSD,USD-TUSD,BTC-DAI,ETH-DAI,MKR-DAI,USD-DAI,MKR-BTC,MKR-ETH,MKR-USD,ETH-TUSD,ZRX-TUSD,TUSD-DAI,LTC-TUSD,EOS-DAI,NEO-TUSD,BCH-TUSD,NEO-DAI,LTC-DAI,XMR-DAI,BCH-DAI,XRP-DAI,NEXO-ETH,NEXO-USD,DWS-BTC,DWS-ETH,DWS-USD,APPC-BTC,APPC-ETH,APPC-USD,BIT-ETH,TRX-BTC,TRX-ETH,TRX-USD,SPC-BTC,SPC-ETH,SPC-USD,REX-BTC,REX-ETH,REX-USD", + "AvailablePairs": "BCN-BTC,BTC-USD,DASH-BTC,DOGE-BTC,DOGE-USD,DSH-BTC,EMC-BTC,ETH-BTC,FCN-BTC,LSK-BTC,LTC-BTC,LTC-USD,NXT-BTC,SBD-BTC,SC-BTC,STEEM-BTC,XDN-BTC,XEM-BTC,XMR-BTC,ARDR-BTC,ZEC-BTC,WAVES-BTC,MAID-BTC,AMP-BTC,BUS-BTC,DGD-BTC,ICN-BTC,SNGLS-BTC,1ST-BTC,TRST-BTC,TIME-BTC,GNO-BTC,REP-BTC,XMR-USD,DASH-USD,ETH-USD,NXT-USD,ZRC-BTC,BOS-BTC,DCT-BTC,ANT-BTC,AEON-BTC,GUP-BTC,PLU-BTC,LUN-BTC,TAAS-BTC,NXC-BTC,EDG-BTC,RLC-BTC,SWT-BTC,TKN-BTC,WINGS-BTC,XAUR-BTC,AE-BTC,PTOY-BTC,ZEC-USD,XEM-USD,BCN-USD,XDN-USD,MAID-USD,ETC-BTC,ETC-USD,CFI-BTC,PLBT-BTC,BNT-BTC,FYN-ETH,SNM-BTC,SNM-ETH,SNT-ETH,CVC-USD,PAY-ETH,OAX-ETH,OMG-ETH,BQX-ETH,XTZ-BTC,DICE-BTC,CFI-ETH,PTOY-ETH,1ST-ETH,XAUR-ETH,TAAS-ETH,TIME-ETH,DICE-ETH,SWT-ETH,XMR-ETH,ETC-ETH,DASH-ETH,ZEC-ETH,PLU-ETH,GNO-ETH,XRP-BTC,NET-ETH,STRAT-USD,STRAT-BTC,SNC-ETH,ADX-ETH,BET-ETH,EOS-ETH,DENT-ETH,SAN-ETH,EOS-BTC,EOS-USD,MNE-BTC,MSP-ETH,DDF-ETH,XTZ-ETH,XTZ-USD,UET-ETH,MYB-ETH,SUR-ETH,IXT-ETH,PLR-ETH,TIX-ETH,NDC-ETH,PRO-ETH,AVT-ETH,COSS-ETH,EVX-USD,DLT-BTC,BNT-ETH,BNT-USD,QAU-BTC,QAU-ETH,MANA-USD,DNT-BTC,FYP-BTC,OPT-BTC,TNT-ETH,IFT-BTC,STX-BTC,STX-ETH,STX-USD,TNT-USD,TNT-BTC,CAT-BTC,CAT-ETH,CAT-USD,BCH-BTC,BCH-ETH,BCH-USD,ENG-ETH,XUC-USD,SNC-BTC,SNC-USD,OAX-USD,OAX-BTC,BAS-ETH,ZRX-BTC,ZRX-ETH,ZRX-USD,RVT-BTC,ICOS-BTC,ICOS-ETH,ICOS-USD,PPC-BTC,PPC-USD,QTUM-ETH,VERI-BTC,VERI-ETH,VERI-USD,IGNIS-ETH,PRG-BTC,PRG-ETH,PRG-USD,BMC-BTC,BMC-ETH,BMC-USD,CND-BTC,CND-ETH,CND-USD,SKIN-BTC,EMGO-BTC,EMGO-USD,CDT-ETH,CDT-USD,FUN-BTC,FUN-ETH,FUN-USD,HVN-BTC,HVN-ETH,FUEL-BTC,FUEL-ETH,FUEL-USD,POE-BTC,POE-ETH,MCAP-BTC,AIR-BTC,AIR-ETH,AIR-USD,AMB-USD,AMB-ETH,AMB-BTC,NTO-BTC,ICO-BTC,PING-BTC,GAME-BTC,TKR-ETH,HPC-BTC,PPT-ETH,MTH-BTC,MTH-ETH,WMGO-BTC,WMGO-USD,LRC-BTC,LRC-ETH,ICX-BTC,ICX-ETH,NEO-BTC,NEO-ETH,NEO-USD,CSNO-BTC,ORME-BTC,ICX-USD,PIX-BTC,PIX-ETH,IND-ETH,KICK-BTC,YOYOW-BTC,MIPS-BTC,CDT-BTC,XVG-BTC,XVG-ETH,XVG-USD,DGB-BTC,DGB-ETH,DGB-USD,DCN-BTC,DCN-ETH,DCN-USD,CCT-ETH,EBET-ETH,VIBE-BTC,VOISE-BTC,ENJ-BTC,ENJ-ETH,ENJ-USD,ZSC-BTC,ZSC-ETH,ZSC-USD,ETBS-BTC,TRX-BTC,TRX-ETH,TRX-USD,VEN-BTC,VEN-ETH,VEN-USD,ART-BTC,EVX-BTC,EVX-ETH,QVT-ETH,EBTCOLD-BTC,EBTCOLD-ETH,EBTCOLD-USD,BKB-BTC,EXN-BTC,TGT-BTC,ATS-ETH,BMT-BTC,BMT-ETH,SUB-BTC,SUB-ETH,SUB-USD,WTC-BTC,CNX-BTC,ATB-BTC,ATB-ETH,ATB-USD,ODN-BTC,BTM-BTC,BTM-ETH,BTM-USD,B2X-BTC,B2X-ETH,B2X-USD,ATM-BTC,ATM-ETH,ATM-USD,LIFE-BTC,VIB-BTC,VIB-ETH,VIB-USD,DRT-ETH,STU-USD,OMG-BTC,PAY-BTC,COSS-BTC,PPT-BTC,SNT-BTC,BTG-BTC,BTG-ETH,BTG-USD,SMART-BTC,SMART-ETH,SMART-USD,XUC-ETH,XUC-BTC,CL-BTC,CL-ETH,CL-USD,LA-ETH,CLD-BTC,CLD-ETH,CLD-USD,EDO-BTC,EDO-ETH,EDO-USD,HGT-ETH,POLL-BTC,IXT-BTC,ATS-BTC,SCL-BTC,ATL-BTC,EBTC-BTC,EBTC-ETH,EBTC-USD,ETP-BTC,ETP-ETH,ETP-USD,OTX-BTC,CDX-ETH,DRPU-BTC,NEBL-BTC,NEBL-ETH,HAC-BTC,CTX-BTC,CTX-ETH,ELE-BTC,ARN-BTC,ARN-ETH,STU-BTC,STU-ETH,GVT-ETH,INDI-BTC,BTX-BTC,LTC-ETH,BCN-ETH,MAID-ETH,NXT-ETH,STRAT-ETH,XDN-ETH,XEM-ETH,PLR-BTC,SUR-BTC,BQX-BTC,DOGE-ETH,ITS-BTC,AMM-BTC,AMM-ETH,AMM-USD,DBIX-BTC,PRE-BTC,KBR-BTC,TBT-BTC,ERO-BTC,SMS-BTC,SMS-ETH,SMS-USD,ZAP-BTC,DOV-BTC,DOV-ETH,DRPU-ETH,OTN-BTC,XRP-ETH,XRP-USD,HSR-BTC,LEND-BTC,LEND-ETH,SPF-BTC,SPF-ETH,SBTC-BTC,SBTC-ETH,WRC-BTC,WRC-ETH,WRC-USD,LOC-BTC,LOC-ETH,LOC-USD,SWFTC-BTC,SWFTC-ETH,SWFTC-USD,STAR-ETH,SBTC-USD,STORM-BTC,DIM-ETH,DIM-USD,DIM-BTC,NGC-BTC,NGC-ETH,NGC-USD,EMC-ETH,EMC-USD,MCO-BTC,MCO-ETH,MCO-USD,MANA-ETH,MANA-BTC,ECH-BTC,CPAY-ETH,DATA-BTC,DATA-ETH,DATA-USD,UTT-BTC,UTT-ETH,UTT-USD,KMD-BTC,KMD-ETH,KMD-USD,QTUM-USD,QTUM-BTC,SNT-USD,OMG-USD,EKO-BTC,EKO-ETH,ADX-BTC,ADX-USD,LSK-ETH,LSK-USD,PLR-USD,SUR-USD,BQX-USD,DRT-USD,REP-ETH,REP-USD,TIO-BTC,TIO-ETH,TIO-USD,WAX-BTC,WAX-ETH,WAX-USD,EET-BTC,EET-ETH,EET-USD,C20-BTC,C20-ETH,IDH-BTC,IDH-ETH,IPL-BTC,COV-BTC,COV-ETH,SENT-BTC,SENT-ETH,SENT-USD,SMT-BTC,SMT-ETH,SMT-USD,CAS-BTC,CAS-ETH,CAS-USD,CHAT-BTC,CHAT-ETH,CHAT-USD,GRMD-BTC,AVH-BTC,TRAC-ETH,JNT-ETH,PCL-BTC,PCL-ETH,CLOUT-BTC,UTK-BTC,UTK-ETH,UTK-USD,GNX-ETH,CHSB-BTC,CHSB-ETH,AVH-ETH,DAY-BTC,DAY-ETH,DAY-USD,NEU-BTC,NEU-ETH,NEU-USD,AVH-USD,CLOUT-ETH,CLOUT-USD,TAU-BTC,MEK-BTC,FLP-BTC,FLP-ETH,FLP-USD,R-BTC,R-ETH,EKO-USD,BCPT-ETH,BCPT-USD,PKT-BTC,PKT-ETH,WLK-BTC,WLK-ETH,WLK-USD,CPG-BTC,CPG-ETH,BPTN-BTC,BPTN-ETH,BPTN-USD,BETR-BTC,BETR-ETH,ARCT-BTC,ARCT-USD,DBET-BTC,DBET-ETH,DBET-USD,RNTB-ETH,HAND-ETH,HAND-USD,ACO-ETH,CTE-BTC,CTE-ETH,CTE-USD,CPY-BTC,CPY-ETH,CHP-ETH,BCPT-BTC,ACT-BTC,ACT-ETH,ACT-USD,HIRE-ETH,ADA-BTC,ADA-ETH,ADA-USD,SIG-BTC,RPM-BTC,RPM-ETH,MTX-BTC,MTX-ETH,MTX-USD,BGG-BTC,BGG-ETH,BGG-USD,SETH-ETH,WIZ-BTC,WIZ-ETH,WIZ-USD,DADI-BTC,DADI-ETH,BDG-ETH,DATX-BTC,DATX-ETH,TRUE-BTC,DRG-BTC,DRG-ETH,BANCA-BTC,BANCA-ETH,ZAP-ETH,ZAP-USD,AUTO-BTC,NOAH-BTC,SOC-BTC,WILD-BTC,INSUR-BTC,INSUR-ETH,OCN-BTC,OCN-ETH,STQ-BTC,STQ-ETH,XLM-BTC,XLM-ETH,XLM-USD,IOTA-BTC,IOTA-ETH,IOTA-USD,DRT-BTC,MLD-BTC,MLD-ETH,MLD-USD,BETR-USD,CGC-ETH,ERT-BTC,CRPT-BTC,CRPT-USD,MESH-BTC,MESH-ETH,MESH-USD,HLW-ETH,IHT-BTC,IHT-ETH,IHT-USD,SCC-BTC,YCC-BTC,DAN-BTC,TEL-BTC,TEL-ETH,BUBO-BTC,BUBO-ETH,BUBO-USD,VIT-BTC,VIT-ETH,VIT-USD,NCT-BTC,NCT-ETH,NCT-USD,AXP-BTC,AXP-ETH,BMH-BTC,BANCA-USD,NOAH-ETH,NOAH-USD,HQX-BTC,LDC-BTC,XMO-BTC,XMO-USD,XMO-ETH,BERRY-BTC,BERRY-ETH,BERRY-USD,BSTN-BTC,BSTN-ETH,BSTN-USD,GBX-BTC,GBX-ETH,GBX-USD,SHIP-BTC,SHIP-ETH,NANO-BTC,NANO-ETH,NANO-USD,LNC-BTC,UNC-BTC,UNC-ETH,RPX-BTC,RPX-ETH,RPX-USD,KIN-ETH,ARDR-USD,DAXT-BTC,DAXT-ETH,FOTA-ETH,FOTA-BTC,SETH-BTC,CVT-BTC,CVT-ETH,CVT-USD,STQ-USD,GNT-BTC,GNT-ETH,GNT-USD,ADH-BTC,ADH-ETH,BBC-BTC,BBC-ETH,GET-BTC,MITH-BTC,MITH-ETH,MITH-USD,SUNC-ETH,DADI-USD,TKY-BTC,ACAT-BTC,ACAT-ETH,ACAT-USD,BTX-USD,TCN-BTC,VIO-ETH,WIKI-BTC,WIKI-ETH,WIKI-USD,ONT-BTC,ONT-ETH,ONT-USD,CVCOIN-BTC,CVCOIN-ETH,CVCOIN-USD,FTX-BTC,FTX-ETH,FREC-BTC,NAVI-BTC,FREC-ETH,FREC-USD,VME-ETH,NAVI-ETH,BTCP-BTC,LND-ETH,CSM-BTC,NANJ-BTC,NTK-BTC,NTK-ETH,NTK-USD,AUC-BTC,AUC-ETH,CMCT-BTC,CMCT-ETH,CMCT-USD,MAN-BTC,MAN-ETH,MAN-USD,HIRE-BTC,TKA-BTC,TKA-ETH,TKA-USD,PNT-BTC,PNT-ETH,FXT-BTC,NEXO-BTC,CHX-BTC,CHX-ETH,CHX-USD,PAT-BTC,PAT-ETH,XMC-BTC,EJOY-BTC,EJOY-ETH,EJOY-USD,FXT-ETH,HERO-BTC,HERO-ETH,XMC-ETH,XMC-USD,STAK-BTC,STAK-ETH,FDZ-BTC,FDZ-ETH,FDZ-USD,SPD-BTC,SPD-ETH,LUC-BTC,MITX-BTC,TIV-BTC,B2G-BTC,B2G-USD,ZPT-BTC,ZPT-ETH,HBZ-BTC,FACE-BTC,FACE-ETH,HBZ-ETH,HBZ-USD,ZPT-USD,MORPH-BTC,MORPH-ETH,MORPH-USD,EBKC-BTC,CPT-BTC,PAT-USD,HTML-BTC,HTML-ETH,MITX-ETH,JOT-BTC,JBC-BTC,JBC-ETH,BTS-BTC,BNK-BTC,KBC-BTC,KBC-ETH,BNK-ETH,BNK-USD,TIV-ETH,TIV-USD,LUC-ETH,LUC-USD,CSM-ETH,CSM-USD,INK-BTC,SPC-BTC,IOST-BTC,INK-ETH,INK-USD,SPC-ETH,SPC-USD,CBC-BTC,IOST-USD,COIN-BTC,ZIL-BTC,COIN-USD,COIN-ETH,PMNT-BTC,ABYSS-BTC,ABYSS-ETH,ZIL-USD,BCI-BTC,CBC-ETH,CBC-USD,PITCH-BTC,PITCH-ETH,HTML-USD,TDS-BTC,TDS-ETH,TDS-USD,SBD-ETH,SBD-USD,DPN-BTC,UUU-BTC,UUU-ETH,XBP-BTC,KRM-USD,CLN-BTC,IVY-BTC,IVY-ETH,TTU-BTC,TTU-ETH,TTU-USD,CLN-ETH,DOR-BTC,DOR-ETH,DOR-USD,ELEC-BTC,ELEC-ETH,ELEC-USD,QNTU-BTC,QNTU-ETH,QNTU-USD,IPL-ETH,IPL-USD,CENNZ-BTC,BTCP-ETH,BTCP-USD,CENNZ-ETH,SWM-BTC,MXM-BTC,MXM-ETH,SPF-USD,LCC-BTC,HGT-BTC,BTC-DAI,ETH-DAI,MKR-DAI,EOS-DAI,USD-DAI,ETH-TUSD,BTC-TUSD,LTC-TUSD,XMR-TUSD,ZRX-TUSD,NEO-TUSD,BCH-TUSD,USD-TUSD,MKR-BTC,MKR-ETH,MKR-USD,TUSD-DAI,NEO-DAI,LTC-DAI,XMR-DAI,BCH-DAI,XRP-DAI,NEXO-ETH,NEXO-USD,DWS-BTC,DWS-ETH,DWS-USD,APPC-BTC,APPC-ETH,APPC-USD,BIT-ETH,DASH-EURS,ZEC-EURS,BTC-EURS,EOS-EURS,ETH-EURS,LTC-EURS,BCH-EURS,NEO-EURS,XMR-EURS,XRP-EURS,REX-BTC,REX-ETH,REX-USD,BCD-BTC,ELF-BTC,ELF-USD,BCD-USD,HQX-ETH,HQX-USD,EBKC-ETH,EBKC-USD,EDG-ETH,EDG-USD,COSM-BTC,COSM-ETH,DCNT-BTC,DCNT-ETH,DCNT-USD,EURS-USD,EURS-TUSD,EURS-DAI,ROX-ETH,ZPR-ETH,MNX-USD,MNX-BTC,MNX-ETH", "EnabledPairs": "BTC-USD", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -676,7 +712,43 @@ "APIKey": "Key", "APISecret": "Secret", "APIAuthPEMKey": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIPVSj8YkpXibCAL9HwpGkDNSEXR9jcpiCthdikJqipNooAoGCCqGSM49\nAwEHoUQDQgAEHiB7q/HCqUrCNqPeTtRmKjyi2T+2O2JgoU8Mjx2R4z1h81uOZHCk\nxbsDg1fb7ACRMpKWPs59QWpQxhqMQrNw8w==\n-----END EC PRIVATE KEY-----\n", - "AvailablePairs": "BTC-USDT,BCH-USDT,ETH-USDT,ETC-USDT,LTC-USDT,EOS-USDT,XRP-USDT,OMG-USDT,DASH-USDT,ZEC-USDT,ADA-USDT,STEEM-USDT,IOTA-USDT,OCN-USDT,SOC-USDT,CTXC-USDT,ACT-USDT,BTM-USDT,BTS-USDT,ONT-USDT,IOST-USDT,HT-USDT,TRX-USDT,DTA-USDT,NEO-USDT,QTUM-USDT,SMT-USDT,ELA-USDT,VEN-USDT,THETA-USDT,SNT-USDT,ZIL-USDT,XEM-USDT,NAS-USDT,RUFF-USDT,HSR-USDT,LET-USDT,MDS-USDT,STORJ-USDT,ELF-USDT,ITC-USDT,CVC-USDT,GNT-USDT,XMR-BTC,BCH-BTC,ETH-BTC,LTC-BTC,ETC-BTC,EOS-BTC,OMG-BTC,XRP-BTC,DASH-BTC,ZEC-BTC,ADA-BTC,STEEM-BTC,IOTA-BTC,POLY-BTC,KAN-BTC,LBA-BTC,WAN-BTC,BFT-BTC,BTM-BTC,ONT-BTC,IOST-BTC,HT-BTC,TRX-BTC,SMT-BTC,ELA-BTC,WICC-BTC,OCN-BTC,ZLA-BTC,ABT-BTC,MTX-BTC,NAS-BTC,VEN-BTC,DTA-BTC,NEO-BTC,WAX-BTC,BTS-BTC,ZIL-BTC,THETA-BTC,CTXC-BTC,SRN-BTC,XEM-BTC,ICX-BTC,DGD-BTC,CHAT-BTC,WPR-BTC,LUN-BTC,SWFTC-BTC,SNT-BTC,MEET-BTC,YEE-BTC,ELF-BTC,LET-BTC,QTUM-BTC,LSK-BTC,ITC-BTC,SOC-BTC,QASH-BTC,MDS-BTC,EKO-BTC,TOPC-BTC,MTN-BTC,ACT-BTC,HSR-BTC,STK-BTC,STORJ-BTC,GNX-BTC,DBC-BTC,SNC-BTC,CMT-BTC,TNB-BTC,RUFF-BTC,QUN-BTC,ZRX-BTC,KNC-BTC,BLZ-BTC,PROPY-BTC,RPX-BTC,APPC-BTC,AIDOC-BTC,POWR-BTC,CVC-BTC,PAY-BTC,QSP-BTC,DAT-BTC,RDN-BTC,MCO-BTC,RCN-BTC,MANA-BTC,UTK-BTC,TNT-BTC,GAS-BTC,BAT-BTC,OST-BTC,LINK-BTC,GNT-BTC,MTL-BTC,EVX-BTC,REQ-BTC,ADX-BTC,AST-BTC,ENG-BTC,SALT-BTC,EDU-BTC,WTC-BTC,BIFI-BTC,BCX-BTC,BCD-BTC,SBTC-BTC,BTG-BTC,XMR-ETH,EOS-ETH,OMG-ETH,IOTA-ETH,ADA-ETH,STEEM-ETH,POLY-ETH,KAN-ETH,LBA-ETH,WAN-ETH,BFT-ETH,ZRX-ETH,AST-ETH,KNC-ETH,ONT-ETH,HT-ETH,BTM-ETH,IOST-ETH,SMT-ETH,ELA-ETH,TRX-ETH,ABT-ETH,NAS-ETH,OCN-ETH,WICC-ETH,ZIL-ETH,CTXC-ETH,ZLA-ETH,WPR-ETH,DTA-ETH,MTX-ETH,THETA-ETH,SRN-ETH,VEN-ETH,BTS-ETH,WAX-ETH,HSR-ETH,ICX-ETH,MTN-ETH,ACT-ETH,BLZ-ETH,QASH-ETH,RUFF-ETH,CMT-ETH,ELF-ETH,MEET-ETH,SOC-ETH,QTUM-ETH,ITC-ETH,SWFTC-ETH,YEE-ETH,LSK-ETH,LUN-ETH,LET-ETH,GNX-ETH,CHAT-ETH,EKO-ETH,TOPC-ETH,DGD-ETH,STK-ETH,MDS-ETH,DBC-ETH,SNC-ETH,PAY-ETH,QUN-ETH,AIDOC-ETH,TNB-ETH,APPC-ETH,RDN-ETH,UTK-ETH,POWR-ETH,BAT-ETH,PROPY-ETH,MANA-ETH,REQ-ETH,CVC-ETH,QSP-ETH,EVX-ETH,DAT-ETH,MCO-ETH,GNT-ETH,GAS-ETH,OST-ETH,LINK-ETH,RCN-ETH,TNT-ETH,ENG-ETH,SALT-ETH,ADX-ETH,EDU-ETH,WTC-ETH,XRP-HT,IOST-HT,DASH-HT,WICC-USDT,EOS-HT,BCH-HT,LTC-HT,ETC-HT,WAVES-BTC,WAVES-ETH,HB10-USDT,CMT-USDT,DCR-BTC,DCR-ETH,PAI-BTC,PAI-ETH", + "AvailablePairs": "BTC-USDT,BCH-USDT,ETH-USDT,ETC-USDT,LTC-USDT,EOS-USDT,XRP-USDT,OMG-USDT,DASH-USDT,ZEC-USDT,ADA-USDT,STEEM-USDT,IOTA-USDT,OCN-USDT,SOC-USDT,CTXC-USDT,ACT-USDT,BTM-USDT,BTS-USDT,ONT-USDT,IOST-USDT,HT-USDT,TRX-USDT,DTA-USDT,NEO-USDT,QTUM-USDT,SMT-USDT,ELA-USDT,VEN-USDT,THETA-USDT,SNT-USDT,ZIL-USDT,XEM-USDT,NAS-USDT,RUFF-USDT,HSR-USDT,LET-USDT,MDS-USDT,STORJ-USDT,ELF-USDT,ITC-USDT,CVC-USDT,GNT-USDT,XMR-BTC,BCH-BTC,ETH-BTC,LTC-BTC,ETC-BTC,EOS-BTC,OMG-BTC,XRP-BTC,DASH-BTC,ZEC-BTC,ADA-BTC,STEEM-BTC,IOTA-BTC,POLY-BTC,KAN-BTC,LBA-BTC,WAN-BTC,BFT-BTC,BTM-BTC,ONT-BTC,IOST-BTC,HT-BTC,TRX-BTC,SMT-BTC,ELA-BTC,WICC-BTC,OCN-BTC,ZLA-BTC,ABT-BTC,MTX-BTC,NAS-BTC,VEN-BTC,DTA-BTC,NEO-BTC,WAX-BTC,BTS-BTC,ZIL-BTC,THETA-BTC,CTXC-BTC,SRN-BTC,XEM-BTC,ICX-BTC,DGD-BTC,CHAT-BTC,WPR-BTC,LUN-BTC,SWFTC-BTC,SNT-BTC,MEET-BTC,YEE-BTC,ELF-BTC,LET-BTC,QTUM-BTC,LSK-BTC,ITC-BTC,SOC-BTC,QASH-BTC,MDS-BTC,EKO-BTC,TOPC-BTC,MTN-BTC,ACT-BTC,HSR-BTC,STK-BTC,STORJ-BTC,GNX-BTC,DBC-BTC,SNC-BTC,CMT-BTC,TNB-BTC,RUFF-BTC,QUN-BTC,ZRX-BTC,KNC-BTC,BLZ-BTC,PROPY-BTC,RPX-BTC,APPC-BTC,AIDOC-BTC,POWR-BTC,CVC-BTC,PAY-BTC,QSP-BTC,DAT-BTC,RDN-BTC,MCO-BTC,RCN-BTC,MANA-BTC,UTK-BTC,TNT-BTC,GAS-BTC,BAT-BTC,OST-BTC,LINK-BTC,GNT-BTC,MTL-BTC,EVX-BTC,REQ-BTC,ADX-BTC,AST-BTC,ENG-BTC,SALT-BTC,EDU-BTC,WTC-BTC,BIFI-BTC,BCX-BTC,BCD-BTC,SBTC-BTC,BTG-BTC,XMR-ETH,EOS-ETH,OMG-ETH,IOTA-ETH,ADA-ETH,STEEM-ETH,POLY-ETH,KAN-ETH,LBA-ETH,WAN-ETH,BFT-ETH,ZRX-ETH,AST-ETH,KNC-ETH,ONT-ETH,HT-ETH,BTM-ETH,IOST-ETH,SMT-ETH,ELA-ETH,TRX-ETH,ABT-ETH,NAS-ETH,OCN-ETH,WICC-ETH,ZIL-ETH,CTXC-ETH,ZLA-ETH,WPR-ETH,DTA-ETH,MTX-ETH,THETA-ETH,SRN-ETH,VEN-ETH,BTS-ETH,WAX-ETH,HSR-ETH,ICX-ETH,MTN-ETH,ACT-ETH,BLZ-ETH,QASH-ETH,RUFF-ETH,CMT-ETH,ELF-ETH,MEET-ETH,SOC-ETH,QTUM-ETH,ITC-ETH,SWFTC-ETH,YEE-ETH,LSK-ETH,LUN-ETH,LET-ETH,GNX-ETH,CHAT-ETH,EKO-ETH,TOPC-ETH,DGD-ETH,STK-ETH,MDS-ETH,DBC-ETH,SNC-ETH,PAY-ETH,QUN-ETH,AIDOC-ETH,TNB-ETH,APPC-ETH,RDN-ETH,UTK-ETH,POWR-ETH,BAT-ETH,PROPY-ETH,MANA-ETH,REQ-ETH,CVC-ETH,QSP-ETH,EVX-ETH,DAT-ETH,MCO-ETH,GNT-ETH,GAS-ETH,OST-ETH,LINK-ETH,RCN-ETH,TNT-ETH,ENG-ETH,SALT-ETH,ADX-ETH,EDU-ETH,WTC-ETH,XRP-HT,IOST-HT,DASH-HT,WICC-USDT,EOS-HT,BCH-HT,LTC-HT,ETC-HT,WAVES-BTC,WAVES-ETH,HB10-USDT,CMT-USDT,DCR-BTC,DCR-ETH,PAI-BTC,PAI-ETH,BOX-BTC,BOX-ETH,DGB-BTC,DGB-ETH,GXS-BTC,GXS-ETH,XLM-BTC,XLM-ETH,BIX-BTC,BIX-ETH,BIX-USDT", + "EnabledPairs": "BTC-USDT", + "BaseCurrencies": "USD", + "AssetTypes": "SPOT", + "SupportsAutoPairUpdates": true, + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "-" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false + }, + "BankAccounts": [ + { + "BankName": "", + "BankAddress": "", + "AccountName": "", + "AccountNumber": "", + "SWIFTCode": "", + "IBAN": "", + "SupportedCurrencies": "" + } + ] + }, + { + "Name": "HuobiHadax", + "Enabled": true, + "Verbose": false, + "Websocket": false, + "UseSandbox": false, + "RESTPollingDelay": 10, + "HTTPTimeout": 15000000000, + "AuthenticatedAPISupport": false, + "APIKey": "Key", + "APISecret": "Secret", + "APIAuthPEMKey": "-----BEGIN EC PRIVATE KEY-----\nJUSTADUMMY\n-----END EC PRIVATE KEY-----\n", + "AvailablePairs": "BTC-USDT,BCH-USDT,ETH-USDT,ETC-USDT,LTC-USDT,EOS-USDT,XRP-USDT,OMG-USDT,DASH-USDT,ZEC-USDT,ADA-USDT,STEEM-USDT,IOTA-USDT,OCN-USDT,SOC-USDT,CTXC-USDT,ACT-USDT,BTM-USDT,BTS-USDT,ONT-USDT,IOST-USDT,HT-USDT,TRX-USDT,DTA-USDT,NEO-USDT,QTUM-USDT,SMT-USDT,ELA-USDT,VEN-USDT,THETA-USDT,SNT-USDT,ZIL-USDT,XEM-USDT,NAS-USDT,RUFF-USDT,HSR-USDT,LET-USDT,MDS-USDT,STORJ-USDT,ELF-USDT,ITC-USDT,CVC-USDT,GNT-USDT,XMR-BTC,BCH-BTC,ETH-BTC,LTC-BTC,ETC-BTC,EOS-BTC,OMG-BTC,XRP-BTC,DASH-BTC,ZEC-BTC,ADA-BTC,STEEM-BTC,IOTA-BTC,POLY-BTC,KAN-BTC,LBA-BTC,WAN-BTC,BFT-BTC,BTM-BTC,ONT-BTC,IOST-BTC,HT-BTC,TRX-BTC,SMT-BTC,ELA-BTC,WICC-BTC,OCN-BTC,ZLA-BTC,ABT-BTC,MTX-BTC,NAS-BTC,VEN-BTC,DTA-BTC,NEO-BTC,WAX-BTC,BTS-BTC,ZIL-BTC,THETA-BTC,CTXC-BTC,SRN-BTC,XEM-BTC,ICX-BTC,DGD-BTC,CHAT-BTC,WPR-BTC,LUN-BTC,SWFTC-BTC,SNT-BTC,MEET-BTC,YEE-BTC,ELF-BTC,LET-BTC,QTUM-BTC,LSK-BTC,ITC-BTC,SOC-BTC,QASH-BTC,MDS-BTC,EKO-BTC,TOPC-BTC,MTN-BTC,ACT-BTC,HSR-BTC,STK-BTC,STORJ-BTC,GNX-BTC,DBC-BTC,SNC-BTC,CMT-BTC,TNB-BTC,RUFF-BTC,QUN-BTC,ZRX-BTC,KNC-BTC,BLZ-BTC,PROPY-BTC,RPX-BTC,APPC-BTC,AIDOC-BTC,POWR-BTC,CVC-BTC,PAY-BTC,QSP-BTC,DAT-BTC,RDN-BTC,MCO-BTC,RCN-BTC,MANA-BTC,UTK-BTC,TNT-BTC,GAS-BTC,BAT-BTC,OST-BTC,LINK-BTC,GNT-BTC,MTL-BTC,EVX-BTC,REQ-BTC,ADX-BTC,AST-BTC,ENG-BTC,SALT-BTC,EDU-BTC,WTC-BTC,BIFI-BTC,BCX-BTC,BCD-BTC,SBTC-BTC,BTG-BTC,XMR-ETH,EOS-ETH,OMG-ETH,IOTA-ETH,ADA-ETH,STEEM-ETH,POLY-ETH,KAN-ETH,LBA-ETH,WAN-ETH,BFT-ETH,ZRX-ETH,AST-ETH,KNC-ETH,ONT-ETH,HT-ETH,BTM-ETH,IOST-ETH,SMT-ETH,ELA-ETH,TRX-ETH,ABT-ETH,NAS-ETH,OCN-ETH,WICC-ETH,ZIL-ETH,CTXC-ETH,ZLA-ETH,WPR-ETH,DTA-ETH,MTX-ETH,THETA-ETH,SRN-ETH,VEN-ETH,BTS-ETH,WAX-ETH,HSR-ETH,ICX-ETH,MTN-ETH,ACT-ETH,BLZ-ETH,QASH-ETH,RUFF-ETH,CMT-ETH,ELF-ETH,MEET-ETH,SOC-ETH,QTUM-ETH,ITC-ETH,SWFTC-ETH,YEE-ETH,LSK-ETH,LUN-ETH,LET-ETH,GNX-ETH,CHAT-ETH,EKO-ETH,TOPC-ETH,DGD-ETH,STK-ETH,MDS-ETH,DBC-ETH,SNC-ETH,PAY-ETH,QUN-ETH,AIDOC-ETH,TNB-ETH,APPC-ETH,RDN-ETH,UTK-ETH,POWR-ETH,BAT-ETH,PROPY-ETH,MANA-ETH,REQ-ETH,CVC-ETH,QSP-ETH,EVX-ETH,DAT-ETH,MCO-ETH,GNT-ETH,GAS-ETH,OST-ETH,LINK-ETH,RCN-ETH,TNT-ETH,ENG-ETH,SALT-ETH,ADX-ETH,EDU-ETH,WTC-ETH,XRP-HT,IOST-HT,DASH-HT,WICC-USDT,EOS-HT,BCH-HT,LTC-HT,ETC-HT,WAVES-BTC,WAVES-ETH,HB10-USDT,CMT-USDT,DCR-BTC,DCR-ETH,PAI-BTC,PAI-ETH,BOX-BTC,BOX-ETH,DGB-BTC,DGB-ETH,GXS-BTC,GXS-ETH,XLM-BTC,XLM-ETH,BIX-BTC,BIX-ETH,BIX-USDT", "EnabledPairs": "BTC-USDT", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -783,7 +855,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "ETHBTC,BTCSGD,BTCNGN,BACETH,BTCUSD,BTCEUR,XRPBTC,BTCGBP,BTCNZD,LTCBTC,BTCJPY,USDHKD,BTCCHF,USDNGN,BCHBTC,NZDUSD,BTCHKD,USDSGD,AUDUSD,BTCCAD,USDCAD,BTCAUD,GBPUSD,USDCHF,EURUSD,USDJPY", + "AvailablePairs": "XRPBTC,USDCHF,BTCUSD,BTCNGN,USDCAD,BTCHKD,BCHBTC,BTCCAD,BTCNZD,BTCSGD,BTCCHF,USDSGD,USDHKD,BTCEUR,AUDUSD,BTCJPY,BACETH,LTCBTC,USDNGN,USDJPY,GBPUSD,NZDUSD,EURUSD,BTCAUD,ETHBTC,BTCGBP", "EnabledPairs": "BTCUSD,BTCAUD", "BaseCurrencies": "USD,EUR,HKD,AUD,GBP,NZD,JPY,SGD,NGN,CHF,CAD", "AssetTypes": "SPOT", @@ -817,7 +889,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "ADX_USDT,OMG_ETH,TRX_ETH,AION_USDT,REP_ETH,GUP_ETH,SNT_USDT,TNT_BTC,AGI_ETH,AST_ETH,SRN_ETH,WAVES_ETH,WINGS_ETH,PTOY_ETH,BCC_ETH,ZRX_BTC,KNC_BTC,MLN_ETH,LTC_USDT,ADX_BTC,REN_ETH,DASH_ETH,ANT_USDT,PTOY_USDT,MCO_ETH,DASH_USDT,GNT_USDT,MGO_USDT,OMG_USDT,AION_ETH,EDG_USDT,GNO_BTC,MANA_USDT,AGI_BTC,WINGS_BTC,SNGLS_ETH,BMC_ETH,WPR_ETH,MLN_USDT,TNT_ETH,MCO_USDT,PAY_ETH,NET_USDT,AST_BTC,QRL_USDT,SNM_USDT,STX_BTC,ZRX_USDT,INS_ETH,WAVES_BTC,GUP_USDT,MYST_BTC,PAY_USDT,ICN_USDT,CFI_USDT,TRX_USDT,QRL_BTC,AE_USDT,SNGLS_BTC,SNM_BTC,REQ_USDT,RLC_USDT,TKN_BTC,DGD_BTC,NEU_ETH,LDC_USDT,REP_BTC,EDG_ETH,CVC_USDT,ANT_ETH,ZRX_ETH,INS_USDT,EOS_BTC,OAX_BTC,TNT_USDT,DASH_BTC,GNO_ETH,CLN_USDT,GNO_USDT,BNT_USDT,IND_USDT,ENG_ETH,ENJ_BTC,CVC_ETH,NEU_BTC,AION_BTC,SNT_BTC,PRO_BTC,ENJ_ETH,BTC_USDT,SNGLS_USDT,SNM_ETH,WINGS_USDT,XID_USDT,IND_ETH,EDG_BTC,RLC_ETH,TAAS_ETH,TRST_BTC,GUP_BTC,VEN_BTC,SRN_BTC,VEN_USDT,REP_USDT,BAT_USDT,AE_ETH,NET_ETH,WPR_BTC,BNT_ETH,BNT_BTC,DGD_ETH,BCC_BTC,EOS_ETH,OAX_ETH,GNT_BTC,BMC_BTC,KNC_ETH,SRN_USDT,REN_USDT,DNT_USDT,BAT_ETH,ICN_BTC,ETH_USDT,TAAS_BTC,ANT_BTC,LDC_BTC,SAN_ETH,OAX_USDT,PRO_USDT,AST_USDT,INS_BTC,SNT_ETH,STORJ_ETH,DNT_BTC,ENG_USDT,LDC_ETH,PTOY_BTC,STX_ETH,STORJ_USDT,ADX_ETH,TIME_BTC,GNT_ETH,TRX_BTC,REQ_ETH,ICN_ETH,TKN_ETH,DGD_USDT,WPR_USDT,VEN_ETH,XID_ETH,NEU_USDT,OMG_BTC,SAN_USDT,CLN_ETH,REN_BTC,ENJ_USDT,MGO_ETH,MYST_ETH,CFI_BTC,STORJ_BTC,AE_BTC,SALT_BTC,SALT_ETH,ENG_BTC,AGI_USDT,TRST_USDT,TAAS_USDT,QRL_ETH,MCO_BTC,KNC_USDT,SALT_USDT,BMC_USDT,MANA_ETH,TIME_ETH,TKN_USDT,PAY_BTC,SAN_BTC,NET_BTC,IND_BTC,LTC_ETH,EOS_USDT,ETH_BTC,RLC_BTC,TRST_ETH,CLN_BTC,CFI_ETH,MANA_BTC,REQ_BTC,LTC_BTC,XID_BTC,CVC_BTC,STX_USDT,PRO_ETH,MLN_BTC,MYST_USDT,BCC_USDT,WAVES_USDT,TIME_USDT,BAT_BTC,MGO_BTC,DNT_ETH", + "AvailablePairs": "REP_BTC,MGO_USDT,IND_BTC,GUP_ETH,PAY_ETH,TRX_BTC,MYST_USDT,BMC_ETH,SALT_BTC,CLN_ETH,REP_ETH,MYST_BTC,DNT_ETH,TRST_BTC,MLN_ETH,OMG_ETH,TRX_ETH,KNC_USDT,GNO_USDT,TAAS_USDT,HOT_BTC,CVC_BTC,NET_USDT,GNO_ETH,TNT_ETH,INS_USDT,STORJ_ETH,STX_ETH,ZRX_USDT,QRL_ETH,MCO_USDT,DNT_USDT,CLN_BTC,EDG_USDT,TNT_USDT,NEU_BTC,ETH_USDT,SNT_ETH,STX_BTC,PTOY_BTC,MANA_BTC,PRO_USDT,IND_ETH,OMG_BTC,DGD_BTC,SAN_ETH,SAN_USDT,WPR_ETH,LTC_ETH,GUP_BTC,BNT_BTC,TKN_USDT,REQ_ETH,INS_ETH,TRST_USDT,MLN_USDT,WINGS_ETH,TTU_BTC,LDC_BTC,LDC_ETH,DGD_USDT,TNT_BTC,SAN_BTC,TIME_ETH,SNM_BTC,ENJ_BTC,WAVES_USDT,GUP_USDT,MCO_ETH,ZRX_BTC,WAVES_BTC,ADX_ETH,BMC_BTC,SALT_USDT,MLN_BTC,BCC_BTC,MGO_ETH,STORJ_USDT,CVC_USDT,AE_ETH,LDC_USDT,TTU_ETH,PAY_BTC,AST_ETH,PRO_BTC,SALT_ETH,WINGS_USDT,STORJ_BTC,GNT_ETH,WAVES_ETH,BAT_USDT,MGO_BTC,PAY_USDT,OMG_USDT,REP_USDT,TAAS_ETH,DASH_ETH,OAX_ETH,HOT_USDT,SNGLS_ETH,PRO_ETH,AGI_USDT,IND_USDT,ICN_BTC,ANT_BTC,SNT_USDT,OAX_USDT,DNT_BTC,TKN_BTC,MANA_ETH,INS_BTC,RLC_USDT,PTOY_ETH,MCO_BTC,MANA_USDT,EDG_ETH,AGI_BTC,ICN_USDT,GNO_BTC,KNC_ETH,REQ_BTC,ENG_USDT,SRN_ETH,ENJ_ETH,TKN_ETH,BAT_ETH,BMC_USDT,RLC_BTC,RLC_ETH,ANT_USDT,AE_BTC,HOT_ETH,TIME_USDT,ANT_ETH,ZRX_ETH,AST_USDT,DASH_BTC,BNT_USDT,DGD_ETH,AGI_ETH,QRL_USDT,CFI_USDT,ADX_USDT,REN_BTC,BAT_BTC,QRL_BTC,ADX_BTC,ENG_BTC,MYST_ETH,CFI_ETH,XID_BTC,PTOY_USDT,STX_USDT,ENG_ETH,ENJ_USDT,WINGS_BTC,EDG_BTC,TTU_USDT,TRST_ETH,SNGLS_USDT,BCC_ETH,CFI_BTC,CLN_USDT,LTC_USDT,SNGLS_BTC,TRX_USDT,WPR_USDT,DASH_USDT,NET_ETH,BCC_USDT,AE_USDT,NEU_ETH,GNT_BTC,REQ_USDT,NEU_USDT,REN_ETH,ETH_BTC,SRN_USDT,ICN_ETH,CVC_ETH,AION_BTC,TIME_BTC,BTC_USDT,XID_USDT,AST_BTC,SRN_BTC,AION_USDT,WPR_BTC,REN_USDT,LTC_BTC,SNT_BTC,XID_ETH,BNT_ETH,KNC_BTC,NET_BTC,TAAS_BTC,SNM_ETH,AION_ETH,GNT_USDT,OAX_BTC,SNM_USDT", "EnabledPairs": "ETH_BTC,LTC_BTC,DASH_BTC", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -998,7 +1070,7 @@ "AuthenticatedAPISupport": false, "APIKey": "Key", "APISecret": "Secret", - "AvailablePairs": "XMR_MAID,BTC_SBD,USDT_BCH,BTC_PPC,BTC_SYS,USDT_STR,XMR_BLK,BTC_ZEC,ETH_ZEC,BTC_STRAT,BTC_OMG,BTC_POT,BTC_LTC,BTC_NEOS,BTC_STR,BTC_XEM,BTC_XPM,USDT_DASH,XMR_LTC,BTC_FLO,BTC_FLDC,BTC_MAID,BTC_FCT,BTC_LBC,USDT_ETC,BTC_ARDR,USDT_ZEC,BTC_DGB,ETH_BCH,BTC_GNO,BTC_ETH,ETH_LSK,BTC_VRC,USDT_BTC,BTC_LSK,BTC_STEEM,ETH_ETC,ETH_REP,BTC_PASC,ETH_GNO,BTC_XVC,BTC_EMC2,BTC_XMR,USDT_NXT,USDT_ETH,BTC_CLAM,BTC_ETC,ETH_GNT,ETH_CVC,BTC_BTM,BTC_BURST,BTC_OMNI,BTC_REP,XMR_ZEC,BTC_BCH,BTC_GAS,BTC_BCN,BTC_XRP,USDT_XMR,XMR_NXT,BTC_BCY,BTC_ZRX,BTC_CVC,BTC_DASH,BTC_NXC,USDT_XRP,BTC_GAME,BTC_NAV,BTC_NXT,XMR_BTCD,XMR_DASH,BTC_EXP,ETH_OMG,BTC_BTS,BTC_PINK,BTC_VTC,ETH_STEEM,BTC_NMC,BTC_BTCD,BTC_RIC,USDT_LTC,BTC_DCR,USDT_REP,BTC_BLK,BTC_HUC,BTC_VIA,BTC_XCP,XMR_BCN,BTC_SC,BTC_RADS,BTC_STORJ,BTC_GRC,BTC_XBC,BTC_AMP,BTC_GNT,ETH_ZRX,ETH_GAS,BTC_DOGE", + "AvailablePairs": "BTC_DASH,BTC_DGB,BTC_NEOS,BTC_NXT,BTC_XRP,XMR_BCN,BTC_DCR,BTC_STRAT,BTC_EMC2,USDT_STR,USDT_BCH,USDT_XMR,BTC_FCT,BTC_BTM,BTC_HUC,BTC_XBC,USDT_ETH,BTC_STEEM,USDT_REP,BTC_CVC,ETH_GAS,BTC_PPC,BTC_XVC,BTC_VTC,BTC_XCP,BTC_XMR,USDT_DASH,BTC_ETH,ETH_LSK,ETH_STEEM,ETH_GNT,ETH_OMG,BTC_NAV,BTC_VRC,BTC_LBC,ETH_ZEC,ETH_GNO,BTC_BTCD,BTC_PINK,BTC_RIC,USDT_NXT,BTC_SBD,BTC_ARDR,BTC_ZRX,ETH_ZRX,BTC_BURST,BTC_BLK,BTC_BTS,BTC_GAME,BTC_XEM,XMR_LTC,BTC_EXP,BTC_REP,USDT_ZEC,BTC_NXC,ETH_BCH,ETH_EOS,BTC_FLO,BTC_OMNI,BTC_NMC,XMR_DASH,BTC_LSK,BTC_ETC,BTC_PASC,ETH_CVC,USDT_BTC,BTC_AMP,USDT_ETC,ETH_REP,BTC_GNO,BTC_BCH,USDT_EOS,USDT_LTC,BTC_BCY,BTC_GNT,BTC_GAS,BTC_STORJ,BTC_EOS,BTC_DOGE,BTC_FLDC,BTC_STR,USDT_XRP,XMR_BTCD,XMR_MAID,XMR_NXT,ETH_ETC,BTC_OMG,BTC_CLAM,BTC_LTC,BTC_MAID,BTC_POT,BTC_BCN,BTC_VIA,XMR_BLK,BTC_GRC,BTC_SYS,BTC_XPM,BTC_SC,BTC_RADS,BTC_ZEC,XMR_ZEC", "EnabledPairs": "BTC_LTC,BTC_ETH,BTC_DOGE,BTC_DASH,BTC_XRP", "BaseCurrencies": "USD", "AssetTypes": "SPOT", @@ -1060,6 +1132,42 @@ "SupportedCurrencies": "" } ] + }, + { + "Name": "ZB", + "Enabled": true, + "Verbose": false, + "Websocket": false, + "UseSandbox": false, + "RESTPollingDelay": 10, + "HTTPTimeout": 15000000000, + "AuthenticatedAPISupport": false, + "APIKey": "Key", + "APISecret": "Secret", + "AvailablePairs": "MITH_QC,FUN_BTC,ICX_BTC,ZB_QC,UBTC_USDT,BTC_USDT,ICX_QC,OMG_USDT,ENT_USDT,AAA_QC,QUN_BTC,TV_BTC,XLM_USDT,BCD_USDT,TOPC_QC,BCW_QC,SUB_BTC,AE_BTC,SNT_USDT,LBTC_USDT,XUC_QC,XEM_USDT,TRUE_QC,HSR_BTC,HOTC_USDT,DASH_QC,NEO_QC,DOGE_USDT,OMG_QC,XWC_USDT,EOSDAC_USDT,KAN_BTC,BCC_QC,BTN_QC,GNT_QC,BAT_QC,GNT_BTC,FUN_QC,BCD_QC,XLM_BTC,CDC_USDT,ETH_ZB,KAN_QC,RCN_QC,MITH_BTC,MCO_QC,LTC_ZB,EOS_QC,SUB_QC,QTUM_ZB,DDM_USDT,SAFE_USDT,EDO_USDT,ZRX_BTC,LTC_BTC,QTUM_BTC,HSR_USDT,GRAM_USDT,TV_QC,TRUE_BTC,SAFE_QC,ZB_BTC,ETH_USDT,CDC_QC,BAT_BTC,DOGE_QC,HSR_ZB,BCD_BTC,TOPC_USDT,XLM_QC,ETC_ZB,SNT_BTC,ETH_QC,DASH_BTC,NEO_USDT,DOGE_BTC,UBTC_QC,BTP_QC,BCC_ZB,HLC_QC,QTUM_QC,LTC_QC,KNC_QC,RCN_BTC,HLC_BTC,DASH_USDT,HPY_BTC,MTL_USDT,LBTC_QC,MTL_BTC,ADA_USDT,LBTC_BTC,HOTC_QC,BITE_BTC,ADA_BTC,SBTC_QC,SUB_USDT,SAFE_BTC,ETC_BTC,BTH_USDT,MITH_USDT,ICX_USDT,SBTC_BTC,DASH_ZB,BCC_USDT,XRP_ZB,EOS_ZB,HPY_QC,MTL_QC,XWC_BTC,BTH_BTC,CHAT_USDT,QTUM_USDT,BAT_USDT,USDT_QC,BTS_BTC,XUC_BTC,KNC_USDT,BTC_QC,KNC_BTC,CHAT_QC,BCX_USDT,BTS_ZB,BITCNY_QC,1ST_BTC,MANA_QC,RCN_USDT,ENT_QC,BDS_BTC,PDX_QC,INK_QC,XEM_QC,BTN_USDT,UBTC_BTC,XWC_QC,QUN_USDT,SNT_QC,EPC_QC,BCW_BTC,NEO_BTC,AE_QC,XEM_BTC,XRP_USDT,OMG_BTC,HLC_USDT,SBTC_USDT,GNT_USDT,CHAT_BTC,ETC_USDT,SLT_BTC,SLT_QC,GRAM_QC,BTM_QC,INK_USDT,MANA_USDT,AE_USDT,SLT_USDT,QUN_QC,FUN_USDT,BCW_USDT,ZRX_USDT,TV_USDT,EDO_QC,XRP_BTC,BTM_BTC,BTP_BTC,BCX_BTC,TRUE_USDT,EOSDAC_BTC,LTC_USDT,BDS_QC,EOS_BTC,1ST_USDT,ZB_USDT,BTN_BTC,BTM_USDT,ETC_QC,HSR_QC,MCO_BTC,HPY_USDT,TOPC_BTC,ENT_BTC,MCO_USDT,BCX_QC,DDM_QC,KAN_USDT,BTS_QC,MANA_BTC,XRP_QC,ETH_BTC,EPC_BTC,BCC_BTC,ZRX_QC,DDM_BTC,EOS_USDT,GRAM_BTC,CDC_BTC,HOTC_BTC,EDO_BTC,1ST_QC,INK_BTC,ADA_QC,BTS_USDT,BTP_USDT,BTH_QC,EOSDAC_QC", + "EnabledPairs": "BTC_USDT,ETH_USDT", + "BaseCurrencies": "USD", + "AssetTypes": "SPOT", + "SupportsAutoPairUpdates": true, + "ConfigCurrencyPairFormat": { + "Uppercase": true, + "Delimiter": "_" + }, + "RequestCurrencyPairFormat": { + "Uppercase": false, + "Delimiter": "_" + }, + "BankAccounts": [ + { + "BankName": "", + "BankAddress": "", + "AccountName": "", + "AccountNumber": "", + "SWIFTCode": "", + "IBAN": "", + "SupportedCurrencies": "" + } + ] } ], "BankAccounts": [ diff --git a/tools/documentation/root_templates/root_readme.tmpl b/tools/documentation/root_templates/root_readme.tmpl index 61ae691c..b36b8105 100644 --- a/tools/documentation/root_templates/root_readme.tmpl +++ b/tools/documentation/root_templates/root_readme.tmpl @@ -32,9 +32,11 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader | COINUT | Yes | No | NA | | Exmo | Yes | NA | NA | | CoinbasePro | Yes | Yes | No| +| GateIO | Yes | No | NA | | Gemini | Yes | No | No | | HitBTC | Yes | Yes | No | -| Huobi.Pro | Yes | No |No | +| Huobi.Pro | Yes | No | NA | +| Huobi.Hadax | Yes | No | NA | | ItBit | Yes | NA | No | | Kraken | Yes | NA | NA | | LakeBTC | Yes | No | NA | @@ -46,6 +48,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader | Poloniex | Yes | Yes | NA | | WEX | Yes | NA | NA | | Yobit | Yes | NA | NA | +| ZB.COM | Yes | No | NA | We are aiming to support the top 20 highest volume exchanges based off the [CoinMarketCap exchange data](https://coinmarketcap.com/exchanges/volume/24-hour/). diff --git a/tools/portfolio/portfolio.go b/tools/portfolio/portfolio.go index f2dc65b5..d5781b33 100644 --- a/tools/portfolio/portfolio.go +++ b/tools/portfolio/portfolio.go @@ -4,7 +4,6 @@ import ( "flag" "fmt" "log" - "net/url" "github.com/thrasher-/gocryptotrader/common" "github.com/thrasher-/gocryptotrader/config" @@ -128,7 +127,7 @@ func main() { } } else { bf := bitfinex.Bitfinex{} - ticker, errf := bf.GetTicker(y.Coin+"USD", url.Values{}) + ticker, errf := bf.GetTicker(y.Coin + "USD") if errf != nil { log.Println(errf) } else {