mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 07:26:47 +00:00
* Initial commit * Updates signature for all withdrawal methods to use new withdrawRequest struct type * Implements crypto withdraw features & tests for Alphapoint, ANX, Binance, Bitfinex, Bitflyer, Bithumb, Bitmex, Bitstamp, Bittrex, BTCC, BTCmarkets, CoinbasePro, Coinut. Updates WithdrawRequest type with more members. Breaking change to update real order testing for increased code coverage * Updates all realOrder tests to run when no API key is present. Updates exchange functions to handle errors better * Implements crypto withdrawals for Exmo, GateIO, Gemini, HitBTC, Huobi, HuobiHadax, Kraken, LakeBTC, Liqui, Localbitcoins, OKCoin, OKEX, Poloniex, Wex, Yobit and ZB. Updates real order test formatting for all real order tests * Update alphapoint. Fixes anx typos. Adds function WithdrawFiatFundsToInternationalBank to exchange wrapper interface. Adds WithdrawFiatFundsToInternationalBank to alphapoint, bitmex, coinbasepro. Updates Kraken to use TradePassword property * Reverts alphapoint to use ErrNotYetImplemented * Fixes line spacing and removes unnecessary line
659 lines
19 KiB
Go
659 lines
19 KiB
Go
package bithumb
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"net/url"
|
|
"reflect"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/thrasher-/gocryptotrader/common"
|
|
"github.com/thrasher-/gocryptotrader/config"
|
|
"github.com/thrasher-/gocryptotrader/currency/symbol"
|
|
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
|
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
|
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
|
)
|
|
|
|
const (
|
|
apiURL = "https://api.bithumb.com"
|
|
|
|
noError = "0000"
|
|
|
|
// Public API
|
|
requestsPerSecondPublicAPI = 20
|
|
|
|
publicTicker = "/public/ticker/"
|
|
publicOrderBook = "/public/orderbook/"
|
|
publicTransactionHistory = "/public/transaction_history/"
|
|
|
|
// Private API
|
|
requestsPerSecondPrivateAPI = 10
|
|
|
|
privateAccInfo = "/info/account"
|
|
privateAccBalance = "/info/balance"
|
|
privateWalletAdd = "/info/wallet_address"
|
|
privateTicker = "/info/ticker"
|
|
privateOrders = "/info/orders"
|
|
privateUserTrans = "/info/user_transactions"
|
|
privatePlaceTrade = "/trade/place"
|
|
privateOrderDetail = "/info/order_detail"
|
|
privateCancelTrade = "/trade/cancel"
|
|
privateBTCWithdraw = "/trade/btc_withdrawal"
|
|
privateKRWDeposit = "/trade/krw_deposit"
|
|
privateKRWWithdraw = "/trade/krw_withdrawal"
|
|
privateMarketBuy = "/trade/market_buy"
|
|
privateMarketSell = "/trade/market_sell"
|
|
|
|
bithumbAuthRate = 10
|
|
bithumbUnauthRate = 20
|
|
)
|
|
|
|
// Bithumb is the overarching type across the Bithumb package
|
|
type Bithumb struct {
|
|
exchange.Base
|
|
}
|
|
|
|
// SetDefaults sets the basic defaults for Bithumb
|
|
func (b *Bithumb) SetDefaults() {
|
|
b.Name = "Bithumb"
|
|
b.Enabled = false
|
|
b.Verbose = false
|
|
b.RESTPollingDelay = 10
|
|
b.APIWithdrawPermissions = exchange.AutoWithdrawCrypto | exchange.AutoWithdrawFiat
|
|
b.RequestCurrencyPairFormat.Delimiter = ""
|
|
b.RequestCurrencyPairFormat.Uppercase = true
|
|
b.ConfigCurrencyPairFormat.Delimiter = ""
|
|
b.ConfigCurrencyPairFormat.Uppercase = true
|
|
b.ConfigCurrencyPairFormat.Index = "KRW"
|
|
b.AssetTypes = []string{ticker.Spot}
|
|
b.SupportsAutoPairUpdating = true
|
|
b.SupportsRESTTickerBatching = true
|
|
b.Requester = request.New(b.Name,
|
|
request.NewRateLimit(time.Second, bithumbAuthRate),
|
|
request.NewRateLimit(time.Second, bithumbUnauthRate),
|
|
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
|
b.APIUrlDefault = apiURL
|
|
b.APIUrl = b.APIUrlDefault
|
|
b.WebsocketInit()
|
|
}
|
|
|
|
// Setup takes in the supplied exchange configuration details and sets params
|
|
func (b *Bithumb) Setup(exch config.ExchangeConfig) {
|
|
if !exch.Enabled {
|
|
b.SetEnabled(false)
|
|
} else {
|
|
b.Enabled = true
|
|
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
|
b.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
|
b.SetHTTPClientTimeout(exch.HTTPTimeout)
|
|
b.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
|
b.RESTPollingDelay = exch.RESTPollingDelay
|
|
b.Verbose = exch.Verbose
|
|
b.Websocket.SetEnabled(exch.Websocket)
|
|
b.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
|
b.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
|
b.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
|
err := b.SetCurrencyPairFormat()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
err = b.SetAssetTypes()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
err = b.SetAutoPairDefaults()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
err = b.SetAPIURL(exch)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
err = b.SetClientProxyAddress(exch.ProxyAddress)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetTradablePairs returns a list of tradable currencies
|
|
func (b *Bithumb) GetTradablePairs() ([]string, error) {
|
|
result, err := b.GetAllTickers()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var currencies []string
|
|
for x := range result {
|
|
currencies = append(currencies, x)
|
|
}
|
|
return currencies, nil
|
|
}
|
|
|
|
// GetTicker returns ticker information
|
|
//
|
|
// symbol e.g. "btc"
|
|
func (b *Bithumb) GetTicker(symbol string) (Ticker, error) {
|
|
response := Ticker{}
|
|
path := fmt.Sprintf("%s%s%s", b.APIUrl, publicTicker, common.StringToUpper(symbol))
|
|
|
|
err := b.SendHTTPRequest(path, &response)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
|
|
if response.Status != noError {
|
|
return response, errors.New(response.Message)
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
// GetAllTickers returns all ticker information
|
|
func (b *Bithumb) GetAllTickers() (map[string]Ticker, error) {
|
|
type Response struct {
|
|
ActionStatus
|
|
Data map[string]interface{}
|
|
}
|
|
|
|
response := Response{}
|
|
path := fmt.Sprintf("%s%s%s", b.APIUrl, publicTicker, "all")
|
|
|
|
err := b.SendHTTPRequest(path, &response)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if response.Status != noError {
|
|
return nil, errors.New(response.Message)
|
|
}
|
|
|
|
result := make(map[string]Ticker)
|
|
for k, v := range response.Data {
|
|
if k == "date" {
|
|
continue
|
|
}
|
|
|
|
if reflect.TypeOf(v).String() != "map[string]interface {}" {
|
|
continue
|
|
}
|
|
|
|
data := v.(map[string]interface{})
|
|
var t Ticker
|
|
t.AveragePrice, _ = strconv.ParseFloat(data["average_price"].(string), 64)
|
|
t.BuyPrice, _ = strconv.ParseFloat(data["buy_price"].(string), 64)
|
|
t.ClosingPrice, _ = strconv.ParseFloat(data["closing_price"].(string), 64)
|
|
t.MaxPrice, _ = strconv.ParseFloat(data["max_price"].(string), 64)
|
|
t.MinPrice, _ = strconv.ParseFloat(data["min_price"].(string), 64)
|
|
t.OpeningPrice, _ = strconv.ParseFloat(data["opening_price"].(string), 64)
|
|
t.SellPrice, _ = strconv.ParseFloat(data["sell_price"].(string), 64)
|
|
t.UnitsTraded, _ = strconv.ParseFloat(data["units_traded"].(string), 64)
|
|
t.Volume1Day, _ = strconv.ParseFloat(data["volume_1day"].(string), 64)
|
|
t.Volume7Day, _ = strconv.ParseFloat(data["volume_7day"].(string), 64)
|
|
result[k] = t
|
|
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// GetOrderBook returns current orderbook
|
|
//
|
|
// symbol e.g. "btc"
|
|
func (b *Bithumb) GetOrderBook(symbol string) (Orderbook, error) {
|
|
response := Orderbook{}
|
|
path := fmt.Sprintf("%s%s%s", b.APIUrl, publicOrderBook, common.StringToUpper(symbol))
|
|
|
|
err := b.SendHTTPRequest(path, &response)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
|
|
if response.Status != noError {
|
|
return response, errors.New(response.Message)
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
// GetTransactionHistory returns recent transactions
|
|
//
|
|
// symbol e.g. "btc"
|
|
func (b *Bithumb) GetTransactionHistory(symbol string) (TransactionHistory, error) {
|
|
response := TransactionHistory{}
|
|
path := fmt.Sprintf("%s%s%s", b.APIUrl, publicTransactionHistory, common.StringToUpper(symbol))
|
|
|
|
err := b.SendHTTPRequest(path, &response)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
|
|
if response.Status != noError {
|
|
return response, errors.New(response.Message)
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
// GetAccountInformation returns account information by singular currency
|
|
func (b *Bithumb) GetAccountInformation(currency string) (Account, error) {
|
|
response := Account{}
|
|
|
|
val := url.Values{}
|
|
if currency != "" {
|
|
val.Set("currency", currency)
|
|
}
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateAccInfo, val, &response)
|
|
}
|
|
|
|
// GetAccountBalance returns customer wallet information
|
|
func (b *Bithumb) GetAccountBalance(c string) (FullBalance, error) {
|
|
var response Balance
|
|
var fullBalance = FullBalance{
|
|
make(map[string]float64),
|
|
make(map[string]float64),
|
|
make(map[string]float64),
|
|
make(map[string]float64),
|
|
make(map[string]float64),
|
|
}
|
|
|
|
vals := url.Values{}
|
|
if c != "" {
|
|
vals.Set("currency", c)
|
|
}
|
|
|
|
err := b.SendAuthenticatedHTTPRequest(privateAccBalance, vals, &response)
|
|
if err != nil {
|
|
return fullBalance, err
|
|
}
|
|
|
|
// Added due to increasing of the usuable currencies on exchange, usually
|
|
// without notificatation, so we dont need to update structs later on
|
|
for tag, datum := range response.Data {
|
|
splitTag := common.SplitStrings(tag, "_")
|
|
c := splitTag[len(splitTag)-1]
|
|
var val float64
|
|
if reflect.TypeOf(datum).String() != "float64" {
|
|
val, err = strconv.ParseFloat(datum.(string), 64)
|
|
if err != nil {
|
|
return fullBalance, err
|
|
}
|
|
} else {
|
|
val = datum.(float64)
|
|
}
|
|
|
|
switch splitTag[0] {
|
|
case "available":
|
|
fullBalance.Available[c] = val
|
|
|
|
case "in":
|
|
fullBalance.InUse[c] = val
|
|
|
|
case "total":
|
|
fullBalance.Total[c] = val
|
|
|
|
case "misu":
|
|
fullBalance.Misu[c] = val
|
|
|
|
case "xcoin":
|
|
fullBalance.Xcoin[c] = val
|
|
|
|
default:
|
|
return fullBalance, fmt.Errorf("GetAccountBalance error tag name %s unhandled",
|
|
splitTag)
|
|
}
|
|
}
|
|
|
|
return fullBalance, nil
|
|
}
|
|
|
|
// GetWalletAddress returns customer wallet address
|
|
//
|
|
// currency e.g. btc, ltc or "", will default to btc without currency specified
|
|
func (b *Bithumb) GetWalletAddress(currency string) (WalletAddressRes, error) {
|
|
response := WalletAddressRes{}
|
|
params := url.Values{}
|
|
params.Set("currency", common.StringToUpper(currency))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateWalletAdd, params, &response)
|
|
}
|
|
|
|
// GetLastTransaction returns customer last transaction
|
|
func (b *Bithumb) GetLastTransaction() (LastTransactionTicker, error) {
|
|
response := LastTransactionTicker{}
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateTicker, nil, &response)
|
|
}
|
|
|
|
// GetOrders returns order list
|
|
//
|
|
// orderID: order number registered for purchase/sales
|
|
// transactionType: transaction type(bid : purchase, ask : sell)
|
|
// count: Value : 1 ~1000 (default : 100)
|
|
// after: YYYY-MM-DD hh:mm:ss's UNIX Timestamp
|
|
// (2014-11-28 16:40:01 = 1417160401000)
|
|
func (b *Bithumb) GetOrders(orderID, transactionType, count, after, currency string) (Orders, error) {
|
|
response := Orders{}
|
|
|
|
params := url.Values{}
|
|
params.Set("order_id", orderID)
|
|
params.Set("type", transactionType)
|
|
params.Set("count", count)
|
|
params.Set("after", after)
|
|
params.Set("currency", common.StringToUpper(currency))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateOrders, params, &response)
|
|
}
|
|
|
|
// GetUserTransactions returns customer transactions
|
|
func (b *Bithumb) GetUserTransactions() (UserTransactions, error) {
|
|
response := UserTransactions{}
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateUserTrans, nil, &response)
|
|
}
|
|
|
|
// PlaceTrade executes a trade order
|
|
//
|
|
// orderCurrency: BTC, ETH, DASH, LTC, ETC, XRP, BCH, XMR, ZEC, QTUM, BTG, EOS
|
|
// (default value: BTC)
|
|
// transactionType: Transaction type(bid : purchase, ask : sales)
|
|
// units: Order quantity
|
|
// price: Transaction amount per currency
|
|
func (b *Bithumb) PlaceTrade(orderCurrency, transactionType string, units float64, price int64) (OrderPlace, error) {
|
|
response := OrderPlace{}
|
|
|
|
params := url.Values{}
|
|
params.Set("order_currency", common.StringToUpper(orderCurrency))
|
|
params.Set("Payment_currency", "KRW")
|
|
params.Set("type", common.StringToUpper(transactionType))
|
|
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
|
params.Set("price", strconv.FormatInt(price, 10))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privatePlaceTrade, params, &response)
|
|
}
|
|
|
|
// ModifyTrade modifies an order already on the exchange books
|
|
func (b *Bithumb) ModifyTrade(orderID, orderCurrency, transactionType string, units float64, price int64) (OrderPlace, error) {
|
|
response := OrderPlace{}
|
|
|
|
params := url.Values{}
|
|
params.Set("order_currency", common.StringToUpper(orderCurrency))
|
|
params.Set("Payment_currency", "KRW")
|
|
params.Set("type", common.StringToUpper(transactionType))
|
|
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
|
params.Set("price", strconv.FormatInt(price, 10))
|
|
params.Set("order_id", orderID)
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privatePlaceTrade, params, &response)
|
|
}
|
|
|
|
// GetOrderDetails returns specific order details
|
|
//
|
|
// orderID: Order number registered for purchase/sales
|
|
// transactionType: Transaction type(bid : purchase, ask : sales)
|
|
// currency: BTC, ETH, DASH, LTC, ETC, XRP, BCH, XMR, ZEC, QTUM, BTG, EOS
|
|
// (default value: BTC)
|
|
func (b *Bithumb) GetOrderDetails(orderID, transactionType, currency string) (OrderDetails, error) {
|
|
response := OrderDetails{}
|
|
|
|
params := url.Values{}
|
|
params.Set("order_id", common.StringToUpper(orderID))
|
|
params.Set("type", common.StringToUpper(transactionType))
|
|
params.Set("currency", common.StringToUpper(currency))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateOrderDetail, params, &response)
|
|
}
|
|
|
|
// CancelTrade cancels a customer purchase/sales transaction
|
|
// transactionType: Transaction type(bid : purchase, ask : sales)
|
|
// orderID: Order number registered for purchase/sales
|
|
// currency: BTC, ETH, DASH, LTC, ETC, XRP, BCH, XMR, ZEC, QTUM, BTG, EOS
|
|
// (default value: BTC)
|
|
func (b *Bithumb) CancelTrade(transactionType, orderID, currency string) (ActionStatus, error) {
|
|
response := ActionStatus{}
|
|
|
|
params := url.Values{}
|
|
params.Set("order_id", common.StringToUpper(orderID))
|
|
params.Set("type", common.StringToUpper(transactionType))
|
|
params.Set("currency", common.StringToUpper(currency))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateCancelTrade, nil, &response)
|
|
}
|
|
|
|
// WithdrawCrypto withdraws a customer currency to an address
|
|
//
|
|
// address: Currency withdrawing address
|
|
// destination: Currency withdrawal Destination Tag (when withdraw XRP) OR
|
|
// Currency withdrawal Payment Id (when withdraw XMR)
|
|
// currency: BTC, ETH, DASH, LTC, ETC, XRP, BCH, XMR, ZEC, QTUM
|
|
// (default value: BTC)
|
|
// units: Quantity to withdraw currency
|
|
func (b *Bithumb) WithdrawCrypto(address, destination, currency string, units float64) (ActionStatus, error) {
|
|
response := ActionStatus{}
|
|
|
|
params := url.Values{}
|
|
params.Set("address", address)
|
|
if len(destination) > 0 {
|
|
params.Set("destination", destination)
|
|
}
|
|
params.Set("currency", common.StringToUpper(currency))
|
|
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateBTCWithdraw, params, &response)
|
|
}
|
|
|
|
// RequestKRWDepositDetails returns Bithumb banking details for deposit
|
|
// information
|
|
func (b *Bithumb) RequestKRWDepositDetails() (KRWDeposit, error) {
|
|
response := KRWDeposit{}
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateKRWDeposit, nil, &response)
|
|
}
|
|
|
|
// RequestKRWWithdraw allows a customer KRW withdrawal request
|
|
//
|
|
// bank: Bankcode with bank name e.g. (bankcode)_(bankname)
|
|
// account: Withdrawing bank account number
|
|
// price: Withdrawing amount
|
|
func (b *Bithumb) RequestKRWWithdraw(bank, account string, price int64) (ActionStatus, error) {
|
|
response := ActionStatus{}
|
|
|
|
params := url.Values{}
|
|
params.Set("bank", bank)
|
|
params.Set("account", account)
|
|
params.Set("price", strconv.FormatInt(price, 10))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateKRWWithdraw, params, &response)
|
|
}
|
|
|
|
// MarketBuyOrder initiates a buy order through available order books
|
|
//
|
|
// currency: BTC, ETH, DASH, LTC, ETC, XRP, BCH, XMR, ZEC, QTUM, BTG, EOS
|
|
// (default value: BTC)
|
|
// units: Order quantity
|
|
func (b *Bithumb) MarketBuyOrder(currency string, units float64) (MarketBuy, error) {
|
|
response := MarketBuy{}
|
|
|
|
params := url.Values{}
|
|
params.Set("currency", common.StringToUpper(currency))
|
|
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateMarketBuy, params, &response)
|
|
}
|
|
|
|
// MarketSellOrder initiates a sell order through available order books
|
|
//
|
|
// currency: BTC, ETH, DASH, LTC, ETC, XRP, BCH, XMR, ZEC, QTUM, BTG, EOS
|
|
// (default value: BTC)
|
|
// units: Order quantity
|
|
func (b *Bithumb) MarketSellOrder(currency string, units float64) (MarketSell, error) {
|
|
response := MarketSell{}
|
|
|
|
params := url.Values{}
|
|
params.Set("currency", common.StringToUpper(currency))
|
|
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
|
|
|
return response,
|
|
b.SendAuthenticatedHTTPRequest(privateMarketSell, params, &response)
|
|
}
|
|
|
|
// SendHTTPRequest sends an unauthenticated HTTP request
|
|
func (b *Bithumb) SendHTTPRequest(path string, result interface{}) error {
|
|
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
|
}
|
|
|
|
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bithumb
|
|
func (b *Bithumb) SendAuthenticatedHTTPRequest(path string, params url.Values, result interface{}) error {
|
|
if !b.AuthenticatedAPISupport {
|
|
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
|
|
}
|
|
|
|
if params == nil {
|
|
params = url.Values{}
|
|
}
|
|
|
|
if b.Nonce.Get() == 0 {
|
|
b.Nonce.Set(time.Now().UnixNano() / int64(time.Millisecond))
|
|
} else {
|
|
b.Nonce.Inc()
|
|
}
|
|
|
|
params.Set("endpoint", path)
|
|
payload := params.Encode()
|
|
hmacPayload := path + string(0) + payload + string(0) + b.Nonce.String()
|
|
hmac := common.GetHMAC(common.HashSHA512,
|
|
[]byte(hmacPayload),
|
|
[]byte(b.APISecret))
|
|
hmacStr := common.HexEncodeToString(hmac)
|
|
|
|
headers := make(map[string]string)
|
|
headers["Api-Key"] = b.APIKey
|
|
headers["Api-Sign"] = common.Base64Encode([]byte(hmacStr))
|
|
headers["Api-Nonce"] = b.Nonce.String()
|
|
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
|
|
|
var intermediary json.RawMessage
|
|
|
|
errCapture := struct {
|
|
Status string `json:"status"`
|
|
Message string `json:"message"`
|
|
}{}
|
|
|
|
err := b.SendPayload("POST",
|
|
b.APIUrl+path,
|
|
headers,
|
|
bytes.NewBufferString(payload),
|
|
&intermediary,
|
|
true,
|
|
b.Verbose)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = common.JSONDecode(intermediary, &errCapture)
|
|
if err == nil {
|
|
if errCapture.Status != "" && errCapture.Status != "0000" {
|
|
return fmt.Errorf("SendAuthenticatedHTTPRequest error Code:%s Message:%s",
|
|
errCapture.Status,
|
|
errCode[errCapture.Status])
|
|
}
|
|
}
|
|
|
|
return common.JSONDecode(intermediary, result)
|
|
}
|
|
|
|
// GetFee returns an estimate of fee based on type of transaction
|
|
func (b *Bithumb) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
|
|
var fee float64
|
|
|
|
switch feeBuilder.FeeType {
|
|
case exchange.CryptocurrencyTradeFee:
|
|
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
|
|
case exchange.CyptocurrencyDepositFee:
|
|
fee = getDepositFee(feeBuilder.FirstCurrency, feeBuilder.Amount)
|
|
case exchange.CryptocurrencyWithdrawalFee:
|
|
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
|
|
case exchange.InternationalBankWithdrawalFee:
|
|
fee = getWithdrawalFee(feeBuilder.CurrencyItem)
|
|
}
|
|
if fee < 0 {
|
|
fee = 0
|
|
}
|
|
return fee, nil
|
|
}
|
|
|
|
// calculateTradingFee returns fee when performing a trade
|
|
func calculateTradingFee(purchasePrice float64, amount float64) float64 {
|
|
fee := 0.0015
|
|
|
|
return fee * amount * purchasePrice
|
|
}
|
|
|
|
// getDepositFee returns fee on a currency when depositing small amounts to bithumb
|
|
func getDepositFee(currency string, amount float64) float64 {
|
|
var fee float64
|
|
|
|
switch currency {
|
|
case symbol.BTC:
|
|
if amount <= 0.005 {
|
|
fee = 0.001
|
|
}
|
|
case symbol.LTC:
|
|
if amount <= 0.3 {
|
|
fee = 0.01
|
|
}
|
|
case symbol.DASH:
|
|
if amount <= 0.04 {
|
|
fee = 0.01
|
|
}
|
|
case symbol.BCH:
|
|
if amount <= 0.03 {
|
|
fee = 0.001
|
|
}
|
|
case symbol.ZEC:
|
|
if amount <= 0.02 {
|
|
fee = 0.001
|
|
}
|
|
case symbol.BTG:
|
|
if amount <= 0.15 {
|
|
fee = 0.001
|
|
}
|
|
}
|
|
|
|
return fee
|
|
}
|
|
|
|
// getWithdrawalFee returns fee on a currency when withdrawing out of bithumb
|
|
func getWithdrawalFee(currency string) float64 {
|
|
return WithdrawalFees[currency]
|
|
}
|
|
|
|
var errCode = map[string]string{
|
|
"5100": "Bad Request",
|
|
"5200": "Not Member",
|
|
"5300": "Invalid Apikey",
|
|
"5302": "Method Not Allowed",
|
|
"5400": "Database Fail",
|
|
"5500": "Invalid Parameter",
|
|
"5600": "CUSTOM NOTICE (상황별 에러 메시지 출력) usually means transaction not allowed",
|
|
"5900": "Unknown Error",
|
|
}
|