mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Remove Liqui exchange from GCT
This commit is contained in:
@@ -40,7 +40,6 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
| ItBit | Yes | NA | No |
|
||||
| Kraken | Yes | NA | NA |
|
||||
| LakeBTC | Yes | No | NA |
|
||||
| Liqui | Yes | No | NA |
|
||||
| LocalBitcoins | Yes | NA | NA |
|
||||
| OKCoin China | Yes | Yes | No |
|
||||
| OKCoin International | Yes | Yes | No |
|
||||
|
||||
@@ -8,6 +8,12 @@ import (
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
// Default number of enabled exchanges. Modify this whenever an exchange is
|
||||
// added or removed
|
||||
defaultEnabledExchanges = 29
|
||||
)
|
||||
|
||||
func TestGetCurrencyConfig(t *testing.T) {
|
||||
cfg := GetConfig()
|
||||
err := cfg.LoadConfig(ConfigTestFile)
|
||||
@@ -408,7 +414,7 @@ func TestGetEnabledExchanges(t *testing.T) {
|
||||
}
|
||||
|
||||
exchanges := cfg.GetEnabledExchanges()
|
||||
if len(exchanges) != 30 {
|
||||
if len(exchanges) != defaultEnabledExchanges {
|
||||
t.Error(
|
||||
"Test failed. TestGetEnabledExchanges. Enabled exchanges value mismatch",
|
||||
)
|
||||
@@ -460,7 +466,6 @@ func TestGetDisabledExchanges(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCountEnabledExchanges(t *testing.T) {
|
||||
defaultEnabledExchanges := 30
|
||||
GetConfigEnabledExchanges := GetConfig()
|
||||
err := GetConfigEnabledExchanges.LoadConfig(ConfigTestFile)
|
||||
if err != nil {
|
||||
@@ -489,7 +494,7 @@ func TestGetConfigCurrencyPairFormat(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
exchFmt, err := cfg.GetConfigCurrencyPairFormat("Liqui")
|
||||
exchFmt, err := cfg.GetConfigCurrencyPairFormat("Yobit")
|
||||
if !exchFmt.Uppercase || exchFmt.Delimiter != "_" {
|
||||
t.Errorf(
|
||||
"Test failed. TestGetConfigCurrencyPairFormat. Invalid values",
|
||||
@@ -513,7 +518,7 @@ func TestGetRequestCurrencyPairFormat(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
exchFmt, err := cfg.GetRequestCurrencyPairFormat("Liqui")
|
||||
exchFmt, err := cfg.GetRequestCurrencyPairFormat("Bitfinex")
|
||||
if exchFmt.Uppercase || exchFmt.Delimiter != "_" || exchFmt.Separator != "-" {
|
||||
t.Errorf(
|
||||
"Test failed. TestGetRequestCurrencyPairFormat. Invalid values",
|
||||
|
||||
@@ -986,48 +986,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Liqui",
|
||||
"enabled": true,
|
||||
"verbose": false,
|
||||
"websocket": false,
|
||||
"useSandbox": false,
|
||||
"restPollingDelay": 10,
|
||||
"httpTimeout": 15000000000,
|
||||
"httpUserAgent": "",
|
||||
"authenticatedApiSupport": false,
|
||||
"apiKey": "Key",
|
||||
"apiSecret": "Secret",
|
||||
"apiUrl": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API",
|
||||
"apiUrlSecondary": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API",
|
||||
"proxyAddress": "",
|
||||
"websocketUrl": "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API",
|
||||
"availablePairs": "ANT_ETH,BNT_ETH,HOT_ETH,OAX_ETH,AST_BTC,SALT_ETH,LTC_BTC,ETH_BTC,GNO_USDT,SAN_ETH,RLC_ETH,STORJ_BTC,WPR_BTC,OMG_ETH,INS_ETH,AION_ETH,PRO_BTC,KNC_USDT,DASH_ETH,SNT_BTC,AION_USDT,ADX_BTC,MANA_ETH,WINGS_BTC,ETH_USDT,GUP_ETH,CVC_USDT,OAX_BTC,AGI_ETH,TTU_ETH,SNT_ETH,TNT_USDT,LTC_USDT,RLC_BTC,TRST_USDT,SNT_USDT,OMG_USDT,BCHABC_USDT,REP_ETH,ADX_USDT,DGD_USDT,GNO_BTC,SNGLS_USDT,AION_BTC,WINGS_ETH,ENJ_ETH,DASH_BTC,WPR_USDT,TRST_BTC,OMG_BTC,TRX_BTC,STORJ_USDT,BMC_USDT,CLN_USDT,IND_BTC,ENG_BTC,AST_ETH,DGD_ETH,LDC_ETH,ENJ_USDT,TNT_ETH,TRX_ETH,DGD_BTC,ENG_ETH,SALT_BTC,CLN_BTC,GNO_ETH,TRST_ETH,ANT_BTC,ANT_USDT,PRO_USDT,GUP_USDT,SNGLS_BTC,MANA_BTC,CVC_BTC,SALT_USDT,BTC_USDT,TNT_BTC,BNT_USDT,PAY_USDT,WINGS_USDT,BMC_BTC,ENG_USDT,GNT_USDT,OAX_USDT,GUP_BTC,GNT_BTC,SRN_ETH,TTU_USDT,GNT_ETH,REP_USDT,RLC_USDT,SAN_BTC,BCHABC_ETH,MANA_USDT,PRO_ETH,TRX_USDT,CLN_ETH,LDC_USDT,AGI_BTC,INS_BTC,STORJ_ETH,PAY_ETH,LDC_BTC,CVC_ETH,INS_USDT,SAN_USDT,ENJ_BTC,AGI_USDT,TTU_BTC,BNT_BTC,IND_ETH,IND_USDT,AST_USDT,WPR_ETH,HOT_BTC,REP_BTC,SNGLS_ETH,ADX_ETH,BMC_ETH,KNC_BTC,DASH_USDT,BCHABC_BTC,KNC_ETH,LTC_ETH,HOT_USDT,PAY_BTC",
|
||||
"enabledPairs": "ETH_BTC,LTC_BTC,DASH_BTC",
|
||||
"baseCurrencies": "USD",
|
||||
"assetTypes": "SPOT",
|
||||
"supportsAutoPairUpdates": true,
|
||||
"configCurrencyPairFormat": {
|
||||
"uppercase": true,
|
||||
"delimiter": "_"
|
||||
},
|
||||
"requestCurrencyPairFormat": {
|
||||
"uppercase": false,
|
||||
"delimiter": "_",
|
||||
"separator": "-"
|
||||
},
|
||||
"bankAccounts": [
|
||||
{
|
||||
"bankName": "",
|
||||
"bankAddress": "",
|
||||
"accountName": "",
|
||||
"accountNumber": "",
|
||||
"swiftCode": "",
|
||||
"iban": "",
|
||||
"supportedCurrencies": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LocalBitcoins",
|
||||
"enabled": true,
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/itbit"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/kraken"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/lakebtc"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/liqui"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/localbitcoins"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/okcoin"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/okex"
|
||||
@@ -178,8 +177,6 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error {
|
||||
exch = new(kraken.Kraken)
|
||||
case "lakebtc":
|
||||
exch = new(lakebtc.LakeBTC)
|
||||
case "liqui":
|
||||
exch = new(liqui.Liqui)
|
||||
case "localbitcoins":
|
||||
exch = new(localbitcoins.LocalBitcoins)
|
||||
case "okcoin china":
|
||||
|
||||
@@ -589,7 +589,7 @@ func TestGetAndFormatExchangeCurrencies(t *testing.T) {
|
||||
pairs = append(pairs, pair.NewCurrencyPairDelimiter("BTC_USD", "_"))
|
||||
pairs = append(pairs, pair.NewCurrencyPairDelimiter("LTC_BTC", "_"))
|
||||
|
||||
actual, err := GetAndFormatExchangeCurrencies("Liqui", pairs)
|
||||
actual, err := GetAndFormatExchangeCurrencies("Yobit", pairs)
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Exchange TestGetAndFormatExchangeCurrencies error %s", err)
|
||||
}
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
# GoCryptoTrader package Liqui
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/liqui)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
|
||||
|
||||
This liqui package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://gocryptotrader.herokuapp.com/)
|
||||
|
||||
## Liqui Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST Support
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var l exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Liqui" {
|
||||
l = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := l.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := l.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := l.GetAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := l.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := l.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := l.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := l.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
|
||||
## Contribution
|
||||
|
||||
Please feel free to submit any pull requests or suggest any desired features to be added.
|
||||
|
||||
When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
@@ -1,348 +0,0 @@
|
||||
package liqui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"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"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
liquiAPIPublicURL = "https://api.Liqui.io/api"
|
||||
liquiAPIPrivateURL = "https://api.Liqui.io/tapi"
|
||||
liquiAPIPublicVersion = "3"
|
||||
liquiAPIPrivateVersion = "1"
|
||||
liquiInfo = "info"
|
||||
liquiTicker = "ticker"
|
||||
liquiDepth = "depth"
|
||||
liquiTrades = "trades"
|
||||
liquiAccountInfo = "getInfo"
|
||||
liquiTrade = "Trade"
|
||||
liquiActiveOrders = "ActiveOrders"
|
||||
liquiOrderInfo = "OrderInfo"
|
||||
liquiCancelOrder = "CancelOrder"
|
||||
liquiTradeHistory = "TradeHistory"
|
||||
liquiWithdrawCoin = "WithdrawCoin"
|
||||
|
||||
liquiAuthRate = 0
|
||||
liquiUnauthRate = 1
|
||||
)
|
||||
|
||||
// Liqui is the overarching type across the liqui package
|
||||
type Liqui struct {
|
||||
exchange.Base
|
||||
Ticker map[string]Ticker
|
||||
Info Info
|
||||
}
|
||||
|
||||
// SetDefaults sets current default values for liqui
|
||||
func (l *Liqui) SetDefaults() {
|
||||
l.Name = "Liqui"
|
||||
l.Enabled = false
|
||||
l.Fee = 0.25
|
||||
l.Verbose = false
|
||||
l.RESTPollingDelay = 10
|
||||
l.Ticker = make(map[string]Ticker)
|
||||
l.APIWithdrawPermissions = exchange.WithdrawCryptoWithAPIPermission |
|
||||
exchange.NoFiatWithdrawals
|
||||
l.RequestCurrencyPairFormat.Delimiter = "_"
|
||||
l.RequestCurrencyPairFormat.Uppercase = false
|
||||
l.RequestCurrencyPairFormat.Separator = "-"
|
||||
l.ConfigCurrencyPairFormat.Delimiter = "_"
|
||||
l.ConfigCurrencyPairFormat.Uppercase = true
|
||||
l.AssetTypes = []string{ticker.Spot}
|
||||
l.SupportsAutoPairUpdating = true
|
||||
l.SupportsRESTTickerBatching = true
|
||||
l.Requester = request.New(l.Name,
|
||||
request.NewRateLimit(time.Second, liquiAuthRate),
|
||||
request.NewRateLimit(time.Second, liquiUnauthRate),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
l.APIUrlDefault = liquiAPIPublicURL
|
||||
l.APIUrl = l.APIUrlDefault
|
||||
l.APIUrlSecondaryDefault = liquiAPIPrivateURL
|
||||
l.APIUrlSecondary = l.APIUrlSecondaryDefault
|
||||
l.WebsocketInit()
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters for liqui
|
||||
func (l *Liqui) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
l.SetEnabled(false)
|
||||
} else {
|
||||
l.Enabled = true
|
||||
l.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
l.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
l.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
l.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
l.RESTPollingDelay = exch.RESTPollingDelay
|
||||
l.Verbose = exch.Verbose
|
||||
l.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
l.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
l.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
err := l.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = l.SetAssetTypes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = l.SetAutoPairDefaults()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = l.SetAPIURL(exch)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = l.SetClientProxyAddress(exch.ProxyAddress)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetAvailablePairs returns all available pairs
|
||||
func (l *Liqui) GetAvailablePairs(nonHidden bool) []string {
|
||||
var pairs []string
|
||||
for x, y := range l.Info.Pairs {
|
||||
if nonHidden && y.Hidden == 1 || x == "" {
|
||||
continue
|
||||
}
|
||||
pairs = append(pairs, common.StringToUpper(x))
|
||||
}
|
||||
return pairs
|
||||
}
|
||||
|
||||
// GetInfo provides all the information about currently active pairs, such as
|
||||
// the maximum number of digits after the decimal point, the minimum price, the
|
||||
// maximum price, the minimum transaction size, whether the pair is hidden, the
|
||||
// commission for each pair.
|
||||
func (l *Liqui) GetInfo() (Info, error) {
|
||||
resp := Info{}
|
||||
req := fmt.Sprintf("%s/%s/%s/", l.APIUrl, liquiAPIPublicVersion, liquiInfo)
|
||||
|
||||
return resp, l.SendHTTPRequest(req, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns information about currently active pairs, such as: the
|
||||
// maximum price, the minimum price, average price, trade volume, trade volume
|
||||
// in currency, the last trade, Buy and Sell price. All information is provided
|
||||
// over the past 24 hours.
|
||||
//
|
||||
// currencyPair - example "eth_btc"
|
||||
func (l *Liqui) GetTicker(currencyPair string) (map[string]Ticker, error) {
|
||||
type Response struct {
|
||||
Data map[string]Ticker
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
response := Response{Data: make(map[string]Ticker)}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", l.APIUrl, liquiAPIPublicVersion, liquiTicker, currencyPair)
|
||||
|
||||
return response.Data, l.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetDepth information about active orders on the pair. Additionally it accepts
|
||||
// an optional GET-parameter limit, which indicates how many orders should be
|
||||
// displayed (150 by default). Is set to less than 2000.
|
||||
func (l *Liqui) GetDepth(currencyPair string) (Orderbook, error) {
|
||||
type Response struct {
|
||||
Data map[string]Orderbook
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
response := Response{Data: make(map[string]Orderbook)}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", l.APIUrl, liquiAPIPublicVersion, liquiDepth, currencyPair)
|
||||
|
||||
return response.Data[currencyPair], l.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetTrades returns information about the last trades. Additionally it accepts
|
||||
// an optional GET-parameter limit, which indicates how many orders should be
|
||||
// displayed (150 by default). The maximum allowable value is 2000.
|
||||
func (l *Liqui) GetTrades(currencyPair string) ([]Trades, error) {
|
||||
type Response struct {
|
||||
Data map[string][]Trades
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
response := Response{Data: make(map[string][]Trades)}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", l.APIUrl, liquiAPIPublicVersion, liquiTrades, currencyPair)
|
||||
|
||||
return response.Data[currencyPair], l.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetAccountInformation returns information about the user’s current balance, API-key
|
||||
// privileges, the number of open orders and Server Time. To use this method you
|
||||
// need a privilege of the key info.
|
||||
func (l *Liqui) GetAccountInformation() (AccountInfo, error) {
|
||||
var result AccountInfo
|
||||
|
||||
return result,
|
||||
l.SendAuthenticatedHTTPRequest(liquiAccountInfo, url.Values{}, &result)
|
||||
}
|
||||
|
||||
// Trade creates orders on the exchange.
|
||||
// to-do: convert orderid to int64
|
||||
func (l *Liqui) Trade(pair, orderType string, amount, price float64) (float64, error) {
|
||||
req := url.Values{}
|
||||
req.Add("pair", pair)
|
||||
req.Add("type", orderType)
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("rate", strconv.FormatFloat(price, 'f', -1, 64))
|
||||
var result Trade
|
||||
|
||||
err := l.SendAuthenticatedHTTPRequest(liquiTrade, req, &result)
|
||||
if result.Success == 0 {
|
||||
return -1, errors.New(result.Error)
|
||||
}
|
||||
return result.OrderID, err
|
||||
}
|
||||
|
||||
// GetOpenOrders returns the list of your active orders.
|
||||
func (l *Liqui) GetOpenOrders(pair string) (map[string]ActiveOrders, error) {
|
||||
result := make(map[string]ActiveOrders)
|
||||
|
||||
req := url.Values{}
|
||||
req.Add("pair", pair)
|
||||
|
||||
return result, l.SendAuthenticatedHTTPRequest(liquiActiveOrders, req, &result)
|
||||
}
|
||||
|
||||
// GetOrderInfoByID returns the information on particular order.
|
||||
func (l *Liqui) GetOrderInfoByID(OrderID int64) (map[string]OrderInfo, error) {
|
||||
result := make(map[string]OrderInfo)
|
||||
|
||||
req := url.Values{}
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
|
||||
return result, l.SendAuthenticatedHTTPRequest(liquiOrderInfo, req, &result)
|
||||
}
|
||||
|
||||
// CancelExistingOrder method is used for order cancelation.
|
||||
func (l *Liqui) CancelExistingOrder(OrderID int64) error {
|
||||
req := url.Values{}
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
var result CancelOrder
|
||||
|
||||
err := l.SendAuthenticatedHTTPRequest(liquiCancelOrder, req, &result)
|
||||
if result.Success == 0 {
|
||||
return errors.New(result.Error)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTradeHistory returns trade history
|
||||
func (l *Liqui) GetTradeHistory(vals url.Values, pair string) (map[string]TradeHistory, error) {
|
||||
result := make(map[string]TradeHistory)
|
||||
|
||||
if pair != "" {
|
||||
vals.Add("pair", pair)
|
||||
}
|
||||
|
||||
return result, l.SendAuthenticatedHTTPRequest(liquiTradeHistory, vals, &result)
|
||||
}
|
||||
|
||||
// WithdrawCoins is designed for cryptocurrency withdrawals.
|
||||
// API mentions that this isn't active now, but will be soon - you must provide the first 8 characters of the key
|
||||
// in your ticket to support.
|
||||
func (l *Liqui) WithdrawCoins(coin string, amount float64, address string) (WithdrawCoins, error) {
|
||||
req := url.Values{}
|
||||
req.Add("coinName", coin)
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("address", address)
|
||||
|
||||
var result WithdrawCoins
|
||||
err := l.SendAuthenticatedHTTPRequest(liquiWithdrawCoin, req, &result)
|
||||
if err != nil {
|
||||
return WithdrawCoins{}, err
|
||||
}
|
||||
if len(result.Error) > 0 {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (l *Liqui) SendHTTPRequest(path string, result interface{}) error {
|
||||
return l.SendPayload("GET", path, nil, nil, result, false, l.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request to liqui
|
||||
func (l *Liqui) SendAuthenticatedHTTPRequest(method string, values url.Values, result interface{}) (err error) {
|
||||
if !l.AuthenticatedAPISupport {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, l.Name)
|
||||
}
|
||||
|
||||
if l.Nonce.Get() == 0 {
|
||||
l.Nonce.Set(time.Now().Unix())
|
||||
} else {
|
||||
l.Nonce.Inc()
|
||||
}
|
||||
values.Set("nonce", l.Nonce.String())
|
||||
values.Set("method", method)
|
||||
|
||||
encoded := values.Encode()
|
||||
hmac := common.GetHMAC(common.HashSHA512, []byte(encoded), []byte(l.APISecret))
|
||||
|
||||
if l.Verbose {
|
||||
log.Debugf("Sending POST request to %s calling method %s with params %s\n",
|
||||
l.APIUrlSecondary, method, encoded)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["Key"] = l.APIKey
|
||||
headers["Sign"] = common.HexEncodeToString(hmac)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
return l.SendPayload("POST",
|
||||
l.APIUrlSecondary, headers,
|
||||
strings.NewReader(encoded),
|
||||
result,
|
||||
true,
|
||||
l.Verbose)
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
func (l *Liqui) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
|
||||
var fee float64
|
||||
switch feeBuilder.FeeType {
|
||||
case exchange.CryptocurrencyTradeFee:
|
||||
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
|
||||
case exchange.CryptocurrencyWithdrawalFee:
|
||||
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
|
||||
}
|
||||
|
||||
if fee < 0 {
|
||||
fee = 0
|
||||
}
|
||||
|
||||
return fee, nil
|
||||
}
|
||||
|
||||
func getCryptocurrencyWithdrawalFee(currency string) float64 {
|
||||
return WithdrawalFees[currency]
|
||||
}
|
||||
|
||||
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float64) {
|
||||
if isMaker {
|
||||
fee = 0.001
|
||||
} else {
|
||||
fee = 0.0025
|
||||
}
|
||||
return fee * purchasePrice * amount
|
||||
}
|
||||
@@ -1,411 +0,0 @@
|
||||
package liqui
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
"github.com/thrasher-/gocryptotrader/currency/symbol"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
var l Liqui
|
||||
|
||||
const (
|
||||
apiKey = ""
|
||||
apiSecret = ""
|
||||
canManipulateRealOrders = false
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
liquiConfig, err := cfg.GetExchangeConfig("Liqui")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui Setup() init error")
|
||||
}
|
||||
liquiConfig.AuthenticatedAPISupport = true
|
||||
liquiConfig.APIKey = apiKey
|
||||
liquiConfig.APISecret = apiSecret
|
||||
|
||||
l.Setup(liquiConfig)
|
||||
}
|
||||
|
||||
func TestGetAvailablePairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
v := l.GetAvailablePairs(false)
|
||||
if len(v) != 0 {
|
||||
t.Error("Test Failed - liqui GetFee() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := l.GetInfo()
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui GetInfo() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := l.GetTicker("eth_btc")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui GetTicker() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDepth(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := l.GetDepth("eth_btc")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui GetDepth() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := l.GetTrades("eth_btc")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui GetTrades() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthRequests(t *testing.T) {
|
||||
if l.APIKey != "" && l.APISecret != "" {
|
||||
_, err := l.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - liqui GetAccountInfo() error", err)
|
||||
}
|
||||
|
||||
_, err = l.Trade("", "", 0, 1)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - liqui Trade() error", err)
|
||||
}
|
||||
|
||||
_, err = l.GetOpenOrders("eth_btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - liqui GetActiveOrders() error", err)
|
||||
}
|
||||
|
||||
_, err = l.GetOrderInfo(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - liqui GetOrderInfo() error", err)
|
||||
}
|
||||
|
||||
err = l.CancelExistingOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - liqui CancelExistingOrder() error", err)
|
||||
}
|
||||
|
||||
_, err = l.GetTradeHistory(url.Values{}, "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - liqui GetTradeHistory() error", err)
|
||||
}
|
||||
|
||||
_, err = l.WithdrawCoins("btc", 1337, "someaddr")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - liqui WithdrawCoins() error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTicker(t *testing.T) {
|
||||
p := pair.NewCurrencyPairDelimiter("ETH_BTC", "_")
|
||||
_, err := l.UpdateTicker(p, "SPOT")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui UpdateTicker() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateOrderbook(t *testing.T) {
|
||||
p := pair.NewCurrencyPairDelimiter("ETH_BTC", "_")
|
||||
_, err := l.UpdateOrderbook(p, "SPOT")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui UpdateOrderbook() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func setFeeBuilder() exchange.FeeBuilder {
|
||||
return exchange.FeeBuilder{
|
||||
Amount: 1,
|
||||
Delimiter: "-",
|
||||
FeeType: exchange.CryptocurrencyTradeFee,
|
||||
FirstCurrency: symbol.LTC,
|
||||
SecondCurrency: symbol.BTC,
|
||||
IsMaker: false,
|
||||
PurchasePrice: 1,
|
||||
CurrencyItem: symbol.USD,
|
||||
BankTransactionType: exchange.WireTransfer,
|
||||
}
|
||||
}
|
||||
func TestGetFee(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
var feeBuilder = setFeeBuilder()
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
|
||||
t.Error(err)
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.0025), resp)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee High quantity
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.Amount = 1000
|
||||
feeBuilder.PurchasePrice = 1000
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(2500) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(2000), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee IsMaker
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.IsMaker = true
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.001), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee Negative purchase price
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.PurchasePrice = -1000
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
// CryptocurrencyWithdrawalFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0.01) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.01), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CryptocurrencyWithdrawalFee Invalid currency
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FirstCurrency = "hello"
|
||||
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CyptocurrencyDepositFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// InternationalBankDepositFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.InternationalBankDepositFee
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// InternationalBankWithdrawalFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
|
||||
feeBuilder.CurrencyItem = symbol.USD
|
||||
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
expectedResult := exchange.WithdrawCryptoWithAPIPermissionText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := l.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = exchange.GetOrdersRequest{
|
||||
OrderType: exchange.AnyOrderType,
|
||||
Currencies: []pair.CurrencyPair{pair.NewCurrencyPair(symbol.BTC, symbol.USDT)},
|
||||
}
|
||||
|
||||
_, err := l.GetActiveOrders(getOrdersRequest)
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not get open orders: %s", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = exchange.GetOrdersRequest{
|
||||
OrderType: exchange.AnyOrderType,
|
||||
}
|
||||
|
||||
_, err := l.GetOrderHistory(getOrdersRequest)
|
||||
if err != common.ErrFunctionNotSupported {
|
||||
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
func areTestAPIKeysSet() bool {
|
||||
if l.APIKey != "" && l.APIKey != "Key" &&
|
||||
l.APISecret != "" && l.APISecret != "Secret" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var p = pair.CurrencyPair{
|
||||
Delimiter: "",
|
||||
FirstCurrency: symbol.BTC,
|
||||
SecondCurrency: symbol.EUR,
|
||||
}
|
||||
response, err := l.SubmitOrder(p, exchange.BuyOrderSide, exchange.MarketOrderType, 1, 10, "hi")
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := pair.NewCurrencyPair(symbol.LTC, symbol.BTC)
|
||||
var orderCancellation = exchange.OrderCancellation{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
AccountID: "1",
|
||||
CurrencyPair: currencyPair,
|
||||
}
|
||||
|
||||
err := l.CancelOrder(orderCancellation)
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not cancel orders: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := pair.NewCurrencyPair(symbol.LTC, symbol.BTC)
|
||||
var orderCancellation = exchange.OrderCancellation{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
AccountID: "1",
|
||||
CurrencyPair: currencyPair,
|
||||
}
|
||||
|
||||
resp, err := l.CancelAllOrders(orderCancellation)
|
||||
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not cancel orders: %v", err)
|
||||
}
|
||||
|
||||
if len(resp.OrderStatus) > 0 {
|
||||
t.Errorf("%v orders failed to cancel", len(resp.OrderStatus))
|
||||
}
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
_, err := l.ModifyOrder(exchange.ModifyOrder{})
|
||||
if err == nil {
|
||||
t.Error("Test failed - ModifyOrder() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
var withdrawCryptoRequest = exchange.WithdrawRequest{
|
||||
Amount: 100,
|
||||
Currency: symbol.LTC,
|
||||
Address: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
Description: "WITHDRAW IT ALL",
|
||||
}
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
_, err := l.WithdrawCryptocurrencyFunds(withdrawCryptoRequest)
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Withdraw failed to be placed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var withdrawFiatRequest = exchange.WithdrawRequest{}
|
||||
|
||||
_, err := l.WithdrawFiatFunds(withdrawFiatRequest)
|
||||
if err != common.ErrFunctionNotSupported {
|
||||
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
l.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var withdrawFiatRequest = exchange.WithdrawRequest{}
|
||||
|
||||
_, err := l.WithdrawFiatFundsToInternationalBank(withdrawFiatRequest)
|
||||
if err != common.ErrFunctionNotSupported {
|
||||
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
|
||||
}
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
package liqui
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency/symbol"
|
||||
|
||||
// Info holds the current pair information as well as server time
|
||||
type Info struct {
|
||||
ServerTime int64 `json:"server_time"`
|
||||
Pairs map[string]PairData `json:"pairs"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// PairData is a sub-type for Info
|
||||
type PairData struct {
|
||||
DecimalPlaces int `json:"decimal_places"`
|
||||
MinPrice float64 `json:"min_price"`
|
||||
MaxPrice float64 `json:"max_price"`
|
||||
MinAmount float64 `json:"min_amount"`
|
||||
Hidden int `json:"hidden"`
|
||||
Fee float64 `json:"fee"`
|
||||
}
|
||||
|
||||
// Ticker contains ticker information
|
||||
type Ticker struct {
|
||||
High float64
|
||||
Low float64
|
||||
Avg float64
|
||||
Vol float64
|
||||
VolumeCurrency float64
|
||||
Last float64
|
||||
Buy float64
|
||||
Sell float64
|
||||
Updated int64
|
||||
}
|
||||
|
||||
// Orderbook references both ask and bid sides
|
||||
type Orderbook struct {
|
||||
Asks [][]float64 `json:"asks"`
|
||||
Bids [][]float64 `json:"bids"`
|
||||
}
|
||||
|
||||
// Trades contains trade information
|
||||
type Trades struct {
|
||||
Type string `json:"type"`
|
||||
Price float64 `json:"bid"`
|
||||
Amount float64 `json:"amount"`
|
||||
TID int64 `json:"tid"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// AccountInfo contains full account details information
|
||||
type AccountInfo struct {
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Rights struct {
|
||||
Info bool `json:"info"`
|
||||
Trade bool `json:"trade"`
|
||||
Withdraw bool `json:"withdraw"`
|
||||
} `json:"rights"`
|
||||
ServerTime float64 `json:"server_time"`
|
||||
TransactionCount int `json:"transaction_count"`
|
||||
OpenOrders int `json:"open_orders"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// ActiveOrders holds active order information
|
||||
type ActiveOrders struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"sell"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
TimestampCreated float64 `json:"time_created"`
|
||||
Status int `json:"status"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// OrderInfo holds specific order information
|
||||
type OrderInfo struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"sell"`
|
||||
StartAmount float64 `json:"start_amount"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
TimestampCreated float64 `json:"time_created"`
|
||||
Status int `json:"status"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// CancelOrder holds cancelled order information
|
||||
type CancelOrder struct {
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// Trade holds trading information
|
||||
type Trade struct {
|
||||
Received float64 `json:"received"`
|
||||
Remains float64 `json:"remains"`
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// TradeHistory contains trade history data
|
||||
type TradeHistory struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"type"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
OrderID float64 `json:"order_id"`
|
||||
MyOrder int `json:"is_your_order"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// Response is a generalized return type
|
||||
type Response struct {
|
||||
Return interface{} `json:"return"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// WithdrawCoins shows the amount of coins withdrawn from liqui not yet available
|
||||
type WithdrawCoins struct {
|
||||
TID int64 `json:"tId"`
|
||||
AmountSent float64 `json:"amountSent"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// WithdrawalFees the large list of predefined withdrawal fees
|
||||
// Prone to change
|
||||
var WithdrawalFees = map[string]float64{
|
||||
symbol.ZRX: 5,
|
||||
symbol.ADX: 10,
|
||||
symbol.AE: 2,
|
||||
symbol.AION: 5,
|
||||
symbol.AST: 25,
|
||||
symbol.ANT: 2,
|
||||
symbol.REP: 0.15,
|
||||
symbol.BNT: 1.5,
|
||||
symbol.BAT: 20,
|
||||
symbol.BTC: 0.001,
|
||||
symbol.BCH: 0.007,
|
||||
symbol.BMC: 7,
|
||||
symbol.BCAP: 2,
|
||||
symbol.TIME: 0.5,
|
||||
symbol.CVC: 15,
|
||||
symbol.CFI: 100,
|
||||
symbol.CLN: 100,
|
||||
symbol.DASH: 0.003,
|
||||
symbol.MANA: 40,
|
||||
symbol.DGD: 0.05,
|
||||
symbol.DNT: 100,
|
||||
symbol.EDG: 15,
|
||||
symbol.ENG: 3,
|
||||
symbol.ENJ: 50,
|
||||
symbol.EOS: 0.5,
|
||||
symbol.ETH: 0.01,
|
||||
symbol.FIRST: 5,
|
||||
symbol.GNO: 0.1,
|
||||
symbol.GNT: 15,
|
||||
symbol.GOLOS: 0.01,
|
||||
symbol.GBG: 0.01,
|
||||
symbol.HMQ: 20,
|
||||
symbol.ICN: 7,
|
||||
symbol.RLC: 5,
|
||||
symbol.INCNT: 1,
|
||||
symbol.IND: 70,
|
||||
symbol.INS: 7,
|
||||
symbol.KNC: 4,
|
||||
symbol.LDC: 1000,
|
||||
symbol.LTC: 0.01,
|
||||
symbol.LUN: 0.5,
|
||||
symbol.GUP: 40,
|
||||
symbol.MLN: 0.2,
|
||||
symbol.MGO: 20,
|
||||
symbol.MCO: 0.7,
|
||||
symbol.MYST: 20,
|
||||
symbol.NEU: 7,
|
||||
symbol.NET: 10,
|
||||
symbol.OAX: 10,
|
||||
symbol.OMG: 0.5,
|
||||
symbol.PTOY: 50,
|
||||
symbol.PLU: 0.5,
|
||||
symbol.PRO: 7,
|
||||
symbol.QTUM: 0.2,
|
||||
symbol.QRL: 10,
|
||||
symbol.REN: 100,
|
||||
symbol.REQ: 50,
|
||||
symbol.ROUND: 100,
|
||||
symbol.SALT: 4,
|
||||
symbol.SAN: 4,
|
||||
symbol.SNGLS: 80,
|
||||
symbol.AGI: 50,
|
||||
symbol.SRN: 30,
|
||||
symbol.SNM: 25,
|
||||
symbol.XID: 50,
|
||||
symbol.SNT: 50,
|
||||
symbol.STEEM: 0.01,
|
||||
symbol.SBD: 0.01,
|
||||
symbol.STORJ: 7,
|
||||
symbol.STX: 20,
|
||||
symbol.TAAS: 2,
|
||||
symbol.PAY: 5,
|
||||
symbol.USDT: 20,
|
||||
symbol.TNT: 100,
|
||||
symbol.TKN: 5,
|
||||
symbol.TRX: 100,
|
||||
symbol.VEN: 3,
|
||||
symbol.VSL: 30,
|
||||
symbol.WAVES: 0.01,
|
||||
symbol.WPR: 100,
|
||||
symbol.TRST: 100,
|
||||
symbol.WINGS: 20,
|
||||
symbol.XXX: 0.01,
|
||||
symbol.XZC: 0.01,
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
package liqui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Start starts the Liqui go routine
|
||||
func (l *Liqui) Start(wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
l.Run()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// Run implements the Liqui wrapper
|
||||
func (l *Liqui) Run() {
|
||||
if l.Verbose {
|
||||
log.Debugf("%s polling delay: %ds.\n", l.GetName(), l.RESTPollingDelay)
|
||||
log.Debugf("%s %d currencies enabled: %s.\n", l.GetName(), len(l.EnabledPairs), l.EnabledPairs)
|
||||
}
|
||||
|
||||
var err error
|
||||
l.Info, err = l.GetInfo()
|
||||
if err != nil {
|
||||
log.Errorf("%s Unable to fetch info.\n", l.GetName())
|
||||
} else {
|
||||
exchangeProducts := l.GetAvailablePairs(true)
|
||||
err = l.UpdateCurrencies(exchangeProducts, false, false)
|
||||
if err != nil {
|
||||
log.Errorf("%s Failed to get config.\n", l.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (l *Liqui) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
pairsString, err := exchange.GetAndFormatExchangeCurrencies(l.Name,
|
||||
l.GetEnabledCurrencies())
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
result, err := l.GetTicker(pairsString.String())
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range l.GetEnabledCurrencies() {
|
||||
currency := exchange.FormatExchangeCurrency(l.Name, x).String()
|
||||
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(l.Name, x, tp, assetType)
|
||||
}
|
||||
|
||||
return ticker.GetTicker(l.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func (l *Liqui) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
tickerNew, err := ticker.GetTicker(l.Name, p, assetType)
|
||||
if err != nil {
|
||||
return l.UpdateTicker(p, assetType)
|
||||
}
|
||||
return tickerNew, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns orderbook base on the currency pair
|
||||
func (l *Liqui) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
ob, err := orderbook.GetOrderbook(l.Name, p, assetType)
|
||||
if err != nil {
|
||||
return l.UpdateOrderbook(p, assetType)
|
||||
}
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (l *Liqui) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
orderbookNew, err := l.GetDepth(exchange.FormatExchangeCurrency(l.Name, p).String())
|
||||
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(l.Name, p, orderBook, assetType)
|
||||
return orderbook.GetOrderbook(l.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Liqui exchange
|
||||
func (l *Liqui) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
response.Exchange = l.GetName()
|
||||
accountBalance, err := l.GetAccountInformation()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
for x, y := range accountBalance.Funds {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
exchangeCurrency.CurrencyName = common.StringToUpper(x)
|
||||
exchangeCurrency.TotalValue = y
|
||||
exchangeCurrency.Hold = 0
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (l *Liqui) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
var fundHistory []exchange.FundHistory
|
||||
return fundHistory, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
func (l *Liqui) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
|
||||
var resp []exchange.TradeHistory
|
||||
|
||||
return resp, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (l *Liqui) SubmitOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
response, err := l.Trade(p.Pair().String(), orderType.ToString(), amount, price)
|
||||
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (l *Liqui) ModifyOrder(action exchange.ModifyOrder) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// CancelOrder cancels an order by its corresponding ID number
|
||||
func (l *Liqui) CancelOrder(order exchange.OrderCancellation) error {
|
||||
orderIDInt, err := strconv.ParseInt(order.OrderID, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return l.CancelExistingOrder(orderIDInt)
|
||||
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
func (l *Liqui) CancelAllOrders(orderCancellation exchange.OrderCancellation) (exchange.CancelAllOrdersResponse, error) {
|
||||
cancelAllOrdersResponse := exchange.CancelAllOrdersResponse{
|
||||
OrderStatus: make(map[string]string),
|
||||
}
|
||||
activeOrders, err := l.GetOpenOrders("")
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
for activeOrder := range activeOrders {
|
||||
orderIDInt, err := strconv.ParseInt(activeOrder, 10, 64)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
err = l.CancelExistingOrder(orderIDInt)
|
||||
if err != nil {
|
||||
cancelAllOrdersResponse.OrderStatus[activeOrder] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
return cancelAllOrdersResponse, nil
|
||||
}
|
||||
|
||||
// GetOrderInfo returns information on a current open order
|
||||
func (l *Liqui) GetOrderInfo(orderID int64) (exchange.OrderDetail, error) {
|
||||
var orderDetail exchange.OrderDetail
|
||||
return orderDetail, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
func (l *Liqui) GetDepositAddress(cryptocurrency pair.CurrencyItem, accountID string) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (l *Liqui) WithdrawCryptocurrencyFunds(withdrawRequest exchange.WithdrawRequest) (string, error) {
|
||||
resp, err := l.WithdrawCoins(withdrawRequest.Currency.String(), withdrawRequest.Amount, withdrawRequest.Address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", resp.TID), nil
|
||||
}
|
||||
|
||||
// WithdrawFiatFunds returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (l *Liqui) WithdrawFiatFunds(withdrawRequest exchange.WithdrawRequest) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (l *Liqui) WithdrawFiatFundsToInternationalBank(withdrawRequest exchange.WithdrawRequest) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (l *Liqui) GetWebsocket() (*exchange.Websocket, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetFeeByType returns an estimate of fee based on type of transaction
|
||||
func (l *Liqui) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
|
||||
return l.GetFee(feeBuilder)
|
||||
}
|
||||
|
||||
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
|
||||
func (l *Liqui) GetWithdrawCapabilities() uint32 {
|
||||
return l.GetWithdrawPermissions()
|
||||
}
|
||||
|
||||
// GetActiveOrders retrieves any orders that are active/open
|
||||
func (l *Liqui) GetActiveOrders(getOrdersRequest exchange.GetOrdersRequest) ([]exchange.OrderDetail, error) {
|
||||
if len(getOrdersRequest.Currencies) <= 0 {
|
||||
return nil, errors.New("Currency must be supplied")
|
||||
}
|
||||
|
||||
var orders []exchange.OrderDetail
|
||||
for _, currency := range getOrdersRequest.Currencies {
|
||||
resp, err := l.GetOpenOrders(exchange.FormatExchangeCurrency(l.Name, currency).String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for ID, order := range resp {
|
||||
symbol := pair.NewCurrencyPairDelimiter(order.Pair, l.ConfigCurrencyPairFormat.Delimiter)
|
||||
orderDate := time.Unix(int64(order.TimestampCreated), 0)
|
||||
side := exchange.OrderSide(strings.ToUpper(order.Type))
|
||||
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
Amount: order.Amount,
|
||||
ID: ID,
|
||||
Price: order.Rate,
|
||||
OrderSide: side,
|
||||
OrderDate: orderDate,
|
||||
Exchange: l.Name,
|
||||
CurrencyPair: symbol,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
exchange.FilterOrdersByTickRange(&orders, getOrdersRequest.StartTicks, getOrdersRequest.EndTicks)
|
||||
exchange.FilterOrdersBySide(&orders, getOrdersRequest.OrderSide)
|
||||
|
||||
return orders, nil
|
||||
}
|
||||
|
||||
// GetOrderHistory retrieves account order information
|
||||
// Can Limit response to specific order status
|
||||
func (l *Liqui) GetOrderHistory(getOrdersRequest exchange.GetOrdersRequest) ([]exchange.OrderDetail, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
42
testdata/configtest.json
vendored
42
testdata/configtest.json
vendored
@@ -998,48 +998,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Liqui",
|
||||
"enabled": true,
|
||||
"verbose": false,
|
||||
"websocket": false,
|
||||
"useSandbox": false,
|
||||
"restPollingDelay": 10,
|
||||
"httpTimeout": 15000000000,
|
||||
"httpUserAgent": "",
|
||||
"authenticatedApiSupport": false,
|
||||
"apiKey": "Key",
|
||||
"apiSecret": "Secret",
|
||||
"apiUrl": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API",
|
||||
"apiUrlSecondary": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API",
|
||||
"proxyAddress": "",
|
||||
"websocketUrl": "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API",
|
||||
"availablePairs": "BMC_ETH,OAX_BTC,OMG_USDT,DGD_BTC,MANA_USDT,LTC_USDT,TRST_BTC,ETH_USDT,STORJ_BTC,KNC_BTC,STORJ_USDT,GNT_ETH,LTC_ETH,DASH_ETH,AST_BTC,WPR_BTC,PRO_USDT,ANT_USDT,SNGLS_USDT,OAX_ETH,MANA_ETH,IND_USDT,ENG_BTC,DASH_USDT,REP_BTC,BCHABC_ETH,MANA_BTC,WPR_ETH,GNO_ETH,DGD_USDT,BCHABC_BTC,BNT_BTC,HOT_ETH,CLN_USDT,HOT_USDT,GNO_BTC,KNC_ETH,AST_ETH,CLN_BTC,RLC_USDT,GUP_BTC,BNT_ETH,LDC_USDT,GNT_USDT,CVC_USDT,BMC_BTC,WPR_USDT,SALT_BTC,TTU_BTC,ANT_BTC,DGD_ETH,AION_USDT,GUP_USDT,ADX_USDT,AGI_BTC,GNT_BTC,IND_ETH,CLN_ETH,ENG_USDT,PRO_BTC,TRX_BTC,INS_ETH,LDC_ETH,RLC_ETH,SNT_BTC,TNT_ETH,SAN_USDT,PAY_USDT,REP_ETH,SNGLS_ETH,CVC_BTC,IND_BTC,HOT_BTC,LDC_BTC,AION_BTC,SAN_BTC,TNT_BTC,ENG_ETH,WINGS_ETH,SNT_ETH,ENJ_BTC,ENJ_ETH,SALT_USDT,SNT_USDT,WINGS_USDT,ENJ_USDT,SNGLS_BTC,SRN_ETH,BTC_USDT,ADX_ETH,BMC_USDT,TRX_USDT,OMG_BTC,TRST_USDT,TNT_USDT,BNT_USDT,REP_USDT,OMG_ETH,SAN_ETH,ADX_BTC,RLC_BTC,TTU_USDT,ANT_ETH,TRX_ETH,TTU_ETH,INS_USDT,AGI_USDT,GUP_ETH,PAY_ETH,ETH_BTC,KNC_USDT,CVC_ETH,BCHABC_USDT,INS_BTC,TRST_ETH,PAY_BTC,PRO_ETH,LTC_BTC,WINGS_BTC,STORJ_ETH,SALT_ETH,AION_ETH,AST_USDT,GNO_USDT,AGI_ETH,DASH_BTC,OAX_USDT",
|
||||
"enabledPairs": "ETH_BTC,LTC_BTC,DASH_BTC",
|
||||
"baseCurrencies": "USD",
|
||||
"assetTypes": "SPOT",
|
||||
"supportsAutoPairUpdates": true,
|
||||
"configCurrencyPairFormat": {
|
||||
"uppercase": true,
|
||||
"delimiter": "_"
|
||||
},
|
||||
"requestCurrencyPairFormat": {
|
||||
"uppercase": false,
|
||||
"delimiter": "_",
|
||||
"separator": "-"
|
||||
},
|
||||
"bankAccounts": [
|
||||
{
|
||||
"bankName": "",
|
||||
"bankAddress": "",
|
||||
"accountName": "",
|
||||
"accountNumber": "",
|
||||
"swiftCode": "",
|
||||
"iban": "",
|
||||
"supportedCurrencies": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LocalBitcoins",
|
||||
"enabled": true,
|
||||
|
||||
@@ -68,7 +68,6 @@ const (
|
||||
itbit = "..%s..%sexchanges%sitbit%s"
|
||||
kraken = "..%s..%sexchanges%skraken%s"
|
||||
lakebtc = "..%s..%sexchanges%slakebtc%s"
|
||||
liqui = "..%s..%sexchanges%sliqui%s"
|
||||
localbitcoins = "..%s..%sexchanges%slocalbitcoins%s"
|
||||
okcoin = "..%s..%sexchanges%sokcoin%s"
|
||||
okex = "..%s..%sexchanges%sokex%s"
|
||||
@@ -243,7 +242,6 @@ func addPaths() {
|
||||
codebasePaths["exchanges itbit"] = fmt.Sprintf(itbit, path, path, path, path)
|
||||
codebasePaths["exchanges kraken"] = fmt.Sprintf(kraken, path, path, path, path)
|
||||
codebasePaths["exchanges lakebtc"] = fmt.Sprintf(lakebtc, path, path, path, path)
|
||||
codebasePaths["exchanges liqui"] = fmt.Sprintf(liqui, path, path, path, path)
|
||||
codebasePaths["exchanges localbitcoins"] = fmt.Sprintf(localbitcoins, path, path, path, path)
|
||||
codebasePaths["exchanges okcoin"] = fmt.Sprintf(okcoin, path, path, path, path)
|
||||
codebasePaths["exchanges okex"] = fmt.Sprintf(okex, path, path, path, path)
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
{{define "exchanges liqui" -}}
|
||||
{{template "header" .}}
|
||||
## Liqui Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST Support
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var l exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Liqui" {
|
||||
l = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := l.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := l.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := l.GetAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := l.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := l.GetOrderBook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// GetUserInfo returns account info
|
||||
accountInfo, err := l.GetUserInfo(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := l.Trade(...)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
{{template "contributions"}}
|
||||
{{template "donations"}}
|
||||
{{end}}
|
||||
@@ -41,7 +41,6 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
|
||||
| ItBit | Yes | NA | No |
|
||||
| Kraken | Yes | NA | NA |
|
||||
| LakeBTC | Yes | No | NA |
|
||||
| Liqui | Yes | No | NA |
|
||||
| LocalBitcoins | Yes | NA | NA |
|
||||
| OKCoin China | Yes | Yes | No |
|
||||
| OKCoin International | Yes | Yes | No |
|
||||
|
||||
Reference in New Issue
Block a user