package ccxt // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code type bithumb struct { Exchange } func NewBithumbCore() bithumb { p := bithumb{} setDefaults(&p) return p } func (this *bithumb) Describe() interface{} { return this.DeepExtend(this.Exchange.Describe(), map[string]interface{} { "id": "bithumb", "name": "Bithumb", "countries": []interface{}{"KR"}, "rateLimit": 500, "pro": true, "has": map[string]interface{} { "CORS": true, "spot": true, "margin": false, "swap": false, "future": false, "option": false, "addMargin": false, "cancelOrder": true, "closeAllPositions": false, "closePosition": false, "createMarketOrder": true, "createOrder": true, "createReduceOnlyOrder": false, "fetchBalance": true, "fetchBorrowRateHistories": false, "fetchBorrowRateHistory": false, "fetchCrossBorrowRate": false, "fetchCrossBorrowRates": false, "fetchFundingHistory": false, "fetchFundingRate": false, "fetchFundingRateHistory": false, "fetchFundingRates": false, "fetchIndexOHLCV": false, "fetchIsolatedBorrowRate": false, "fetchIsolatedBorrowRates": false, "fetchLeverage": false, "fetchMarkets": true, "fetchMarkOHLCV": false, "fetchOHLCV": true, "fetchOpenInterestHistory": false, "fetchOpenOrders": true, "fetchOrder": true, "fetchOrderBook": true, "fetchPosition": false, "fetchPositionHistory": false, "fetchPositionMode": false, "fetchPositions": false, "fetchPositionsForSymbol": false, "fetchPositionsHistory": false, "fetchPositionsRisk": false, "fetchPremiumIndexOHLCV": false, "fetchTicker": true, "fetchTickers": true, "fetchTrades": true, "fetchTransfer": false, "fetchTransfers": false, "reduceMargin": false, "setLeverage": false, "setMarginMode": false, "setPositionMode": false, "transfer": false, "withdraw": true, }, "hostname": "bithumb.com", "urls": map[string]interface{} { "logo": "https://github.com/user-attachments/assets/c9e0eefb-4777-46b9-8f09-9d7f7c4af82d", "api": map[string]interface{} { "public": "https://api.{hostname}/public", "private": "https://api.{hostname}", }, "www": "https://www.bithumb.com", "doc": "https://apidocs.bithumb.com", "fees": "https://en.bithumb.com/customer_support/info_fee", }, "api": map[string]interface{} { "public": map[string]interface{} { "get": []interface{}{"ticker/ALL_{quoteId}", "ticker/{baseId}_{quoteId}", "orderbook/ALL_{quoteId}", "orderbook/{baseId}_{quoteId}", "transaction_history/{baseId}_{quoteId}", "network-info", "assetsstatus/multichain/ALL", "assetsstatus/multichain/{currency}", "withdraw/minimum/ALL", "withdraw/minimum/{currency}", "assetsstatus/ALL", "assetsstatus/{baseId}", "candlestick/{baseId}_{quoteId}/{interval}"}, }, "private": map[string]interface{} { "post": []interface{}{"info/account", "info/balance", "info/wallet_address", "info/ticker", "info/orders", "info/user_transactions", "info/order_detail", "trade/place", "trade/cancel", "trade/btc_withdrawal", "trade/krw_deposit", "trade/krw_withdrawal", "trade/market_buy", "trade/market_sell", "trade/stop_limit"}, }, }, "fees": map[string]interface{} { "trading": map[string]interface{} { "maker": this.ParseNumber("0.0025"), "taker": this.ParseNumber("0.0025"), }, }, "precisionMode": SIGNIFICANT_DIGITS, "features": map[string]interface{} { "spot": map[string]interface{} { "sandbox": false, "createOrder": map[string]interface{} { "marginMode": false, "triggerPrice": false, "triggerPriceType": nil, "triggerDirection": false, "stopLossPrice": false, "takeProfitPrice": false, "attachedStopLossTakeProfit": nil, "timeInForce": map[string]interface{} { "IOC": false, "FOK": false, "PO": false, "GTD": false, }, "hedged": false, "trailing": false, "leverage": false, "marketBuyRequiresPrice": false, "marketBuyByCost": false, "selfTradePrevention": false, "iceberg": false, }, "createOrders": nil, "fetchMyTrades": nil, "fetchOrder": map[string]interface{} { "marginMode": false, "trigger": false, "trailing": false, "symbolRequired": true, }, "fetchOpenOrders": map[string]interface{} { "marginMode": false, "limit": 1000, "trigger": false, "trailing": false, "symbolRequired": true, }, "fetchOrders": nil, "fetchClosedOrders": nil, "fetchOHLCV": map[string]interface{} { "limit": 1000, }, }, "swap": map[string]interface{} { "linear": nil, "inverse": nil, }, "future": map[string]interface{} { "linear": nil, "inverse": nil, }, }, "exceptions": map[string]interface{} { "Bad Request(SSL)": BadRequest, "Bad Request(Bad Method)": BadRequest, "Bad Request.(Auth Data)": AuthenticationError, "Not Member": AuthenticationError, "Invalid Apikey": AuthenticationError, "Method Not Allowed.(Access IP)": PermissionDenied, "Method Not Allowed.(BTC Adress)": InvalidAddress, "Method Not Allowed.(Access)": PermissionDenied, "Database Fail": ExchangeNotAvailable, "Invalid Parameter": BadRequest, "5600": ExchangeError, "Unknown Error": ExchangeError, "After May 23th, recent_transactions is no longer, hence users will not be able to connect to recent_transactions": ExchangeError, }, "timeframes": map[string]interface{} { "1m": "1m", "3m": "3m", "5m": "5m", "10m": "10m", "30m": "30m", "1h": "1h", "6h": "6h", "12h": "12h", "1d": "24h", }, "options": map[string]interface{} { "quoteCurrencies": map[string]interface{} { "BTC": map[string]interface{} { "limits": map[string]interface{} { "cost": map[string]interface{} { "min": 0.0002, "max": 100, }, }, }, "KRW": map[string]interface{} { "limits": map[string]interface{} { "cost": map[string]interface{} { "min": 500, "max": 5000000000, }, }, }, }, }, "commonCurrencies": map[string]interface{} { "ALT": "ArchLoot", "FTC": "FTC2", "SOC": "Soda Coin", }, }) } func (this *bithumb) SafeMarket(optionalArgs ...interface{}) interface{} { // bithumb has a different type of conflict in markets, because // their ids are the base currency (BTC for instance), so we can have // multiple "BTC" ids representing the different markets (BTC/ETH, "BTC/DOGE", etc) // since they're the same we just need to return one marketId := GetArg(optionalArgs, 0, nil) _ = marketId market := GetArg(optionalArgs, 1, nil) _ = market delimiter := GetArg(optionalArgs, 2, nil) _ = delimiter marketType := GetArg(optionalArgs, 3, nil) _ = marketType return this.Exchange.SafeMarket(marketId, market, delimiter, "spot") } func (this *bithumb) AmountToPrecision(symbol interface{}, amount interface{}) interface{} { return this.DecimalToPrecision(amount, TRUNCATE, GetValue(GetValue(GetValue(this.Markets, symbol), "precision"), "amount"), DECIMAL_PLACES) } /** * @method * @name bithumb#fetchMarkets * @description retrieves data on all markets for bithumb * @see https://apidocs.bithumb.com/v1.2.0/reference/%ED%98%84%EC%9E%AC%EA%B0%80-%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C-all * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ func (this *bithumb) FetchMarkets(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) params := GetArg(optionalArgs, 0, map[string]interface{} {}) _ = params var result interface{} = []interface{}{} var quoteCurrencies interface{} = this.SafeDict(this.Options, "quoteCurrencies", map[string]interface{} {}) var quotes interface{} = ObjectKeys(quoteCurrencies) var promises interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(quotes)); i++ { var request interface{} = map[string]interface{} { "quoteId": GetValue(quotes, i), } AppendToArray(&promises,this.PublicGetTickerALLQuoteId(this.Extend(request, params))) } results:= (<-promiseAll(promises)) PanicOnError(results) for i := 0; IsLessThan(i, GetArrayLength(quotes)); i++ { var quote interface{} = GetValue(quotes, i) var quoteId interface{} = quote var response interface{} = GetValue(results, i) var data interface{} = this.SafeDict(response, "data") var extension interface{} = this.SafeDict(quoteCurrencies, quote, map[string]interface{} {}) var currencyIds interface{} = ObjectKeys(data) for j := 0; IsLessThan(j, GetArrayLength(currencyIds)); j++ { var currencyId interface{} = GetValue(currencyIds, j) if IsTrue(IsEqual(currencyId, "date")) { continue } var market interface{} = GetValue(data, currencyId) var base interface{} = this.SafeCurrencyCode(currencyId) var active interface{} = true if IsTrue(IsArray(market)) { var numElements interface{} = GetArrayLength(market) if IsTrue(IsEqual(numElements, 0)) { active = false } } var entry interface{} = this.DeepExtend(map[string]interface{} { "id": currencyId, "symbol": Add(Add(base, "/"), quote), "base": base, "quote": quote, "settle": nil, "baseId": currencyId, "quoteId": quoteId, "settleId": nil, "type": "spot", "spot": true, "margin": false, "swap": false, "future": false, "option": false, "active": active, "contract": false, "linear": nil, "inverse": nil, "contractSize": nil, "expiry": nil, "expiryDateTime": nil, "strike": nil, "optionType": nil, "precision": map[string]interface{} { "amount": ParseInt("4"), "price": ParseInt("4"), }, "limits": map[string]interface{} { "leverage": map[string]interface{} { "min": nil, "max": nil, }, "amount": map[string]interface{} { "min": nil, "max": nil, }, "price": map[string]interface{} { "min": nil, "max": nil, }, "cost": map[string]interface{} {}, }, "created": nil, "info": market, }, extension) AppendToArray(&result,entry) } } ch <- result return nil }() return ch } func (this *bithumb) ParseBalance(response interface{}) interface{} { var result interface{} = map[string]interface{} { "info": response, } var balances interface{} = this.SafeDict(response, "data") var codes interface{} = ObjectKeys(this.Currencies) for i := 0; IsLessThan(i, GetArrayLength(codes)); i++ { var code interface{} = GetValue(codes, i) var account interface{} = this.Account() var currency interface{} = this.Currency(code) var lowerCurrencyId interface{} = this.SafeStringLower(currency, "id") AddElementToObject(account, "total", this.SafeString(balances, Add("total_", lowerCurrencyId))) AddElementToObject(account, "used", this.SafeString(balances, Add("in_use_", lowerCurrencyId))) AddElementToObject(account, "free", this.SafeString(balances, Add("available_", lowerCurrencyId))) AddElementToObject(result, code, account) } return this.SafeBalance(result) } /** * @method * @name bithumb#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @see https://apidocs.bithumb.com/v1.2.0/reference/%EB%B3%B4%EC%9C%A0%EC%9E%90%EC%82%B0-%EC%A1%B0%ED%9A%8C * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure} */ func (this *bithumb) FetchBalance(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) params := GetArg(optionalArgs, 0, map[string]interface{} {}) _ = params retRes4108 := (<-this.LoadMarkets()) PanicOnError(retRes4108) var request interface{} = map[string]interface{} { "currency": "ALL", } response:= (<-this.PrivatePostInfoBalance(this.Extend(request, params))) PanicOnError(response) ch <- this.ParseBalance(response) return nil }() return ch } /** * @method * @name bithumb#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://apidocs.bithumb.com/v1.2.0/reference/%ED%98%B8%EA%B0%80-%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int} [limit] the maximum amount of order book entries to return * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols */ func (this *bithumb) FetchOrderBook(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) limit := GetArg(optionalArgs, 0, nil) _ = limit params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes4298 := (<-this.LoadMarkets()) PanicOnError(retRes4298) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "baseId": GetValue(market, "baseId"), "quoteId": GetValue(market, "quoteId"), } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "count", limit) // default 30, max 30 } response:= (<-this.PublicGetOrderbookBaseIdQuoteId(this.Extend(request, params))) PanicOnError(response) // // { // "status":"0000", // "data":{ // "timestamp":"1587621553942", // "payment_currency":"KRW", // "order_currency":"BTC", // "bids":[ // {"price":"8652000","quantity":"0.0043"}, // {"price":"8651000","quantity":"0.0049"}, // {"price":"8650000","quantity":"8.4791"}, // ], // "asks":[ // {"price":"8654000","quantity":"0.119"}, // {"price":"8655000","quantity":"0.254"}, // {"price":"8658000","quantity":"0.119"}, // ] // } // } // var data interface{} = this.SafeDict(response, "data", map[string]interface{} {}) var timestamp interface{} = this.SafeInteger(data, "timestamp") ch <- this.ParseOrderBook(data, symbol, timestamp, "bids", "asks", "price", "quantity") return nil }() return ch } func (this *bithumb) ParseTicker(ticker interface{}, optionalArgs ...interface{}) interface{} { // // fetchTicker, fetchTickers // // { // "opening_price":"227100", // "closing_price":"228400", // "min_price":"222300", // "max_price":"230000", // "units_traded":"82618.56075337", // "acc_trade_value":"18767376138.6031", // "prev_closing_price":"227100", // "units_traded_24H":"151871.13484676", // "acc_trade_value_24H":"34247610416.8974", // "fluctate_24H":"8700", // "fluctate_rate_24H":"3.96", // "date":"1587710327264", // fetchTickers inject this // } // market := GetArg(optionalArgs, 0, nil) _ = market var timestamp interface{} = this.SafeInteger(ticker, "date") var symbol interface{} = this.SafeSymbol(nil, market) var open interface{} = this.SafeString(ticker, "opening_price") var close interface{} = this.SafeString(ticker, "closing_price") var baseVolume interface{} = this.SafeString(ticker, "units_traded_24H") var quoteVolume interface{} = this.SafeString(ticker, "acc_trade_value_24H") return this.SafeTicker(map[string]interface{} { "symbol": symbol, "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "high": this.SafeString(ticker, "max_price"), "low": this.SafeString(ticker, "min_price"), "bid": this.SafeString(ticker, "buy_price"), "bidVolume": nil, "ask": this.SafeString(ticker, "sell_price"), "askVolume": nil, "vwap": nil, "open": open, "close": close, "last": close, "previousClose": nil, "change": nil, "percentage": nil, "average": nil, "baseVolume": baseVolume, "quoteVolume": quoteVolume, "info": ticker, }, market) } /** * @method * @name bithumb#fetchTickers * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market * @see https://apidocs.bithumb.com/v1.2.0/reference/%ED%98%84%EC%9E%AC%EA%B0%80-%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C-all * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ func (this *bithumb) FetchTickers(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) symbols := GetArg(optionalArgs, 0, nil) _ = symbols params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes5238 := (<-this.LoadMarkets()) PanicOnError(retRes5238) var result interface{} = map[string]interface{} {} var quoteCurrencies interface{} = this.SafeDict(this.Options, "quoteCurrencies", map[string]interface{} {}) var quotes interface{} = ObjectKeys(quoteCurrencies) var promises interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(quotes)); i++ { var request interface{} = map[string]interface{} { "quoteId": GetValue(quotes, i), } AppendToArray(&promises,this.PublicGetTickerALLQuoteId(this.Extend(request, params))) } responses:= (<-promiseAll(promises)) PanicOnError(responses) for i := 0; IsLessThan(i, GetArrayLength(quotes)); i++ { var quote interface{} = GetValue(quotes, i) var response interface{} = GetValue(responses, i) // // { // "status":"0000", // "data":{ // "BTC":{ // "opening_price":"9045000", // "closing_price":"9132000", // "min_price":"8938000", // "max_price":"9168000", // "units_traded":"4619.79967497", // "acc_trade_value":"42021363832.5187", // "prev_closing_price":"9041000", // "units_traded_24H":"8793.5045804", // "acc_trade_value_24H":"78933458515.4962", // "fluctate_24H":"530000", // "fluctate_rate_24H":"6.16" // }, // "date":"1587710878669" // } // } // var data interface{} = this.SafeDict(response, "data", map[string]interface{} {}) var timestamp interface{} = this.SafeInteger(data, "date") var tickers interface{} = this.Omit(data, "date") var currencyIds interface{} = ObjectKeys(tickers) for j := 0; IsLessThan(j, GetArrayLength(currencyIds)); j++ { var currencyId interface{} = GetValue(currencyIds, j) var ticker interface{} = GetValue(data, currencyId) var base interface{} = this.SafeCurrencyCode(currencyId) var symbol interface{} = Add(Add(base, "/"), quote) var market interface{} = this.SafeMarket(symbol) AddElementToObject(ticker, "date", timestamp) AddElementToObject(result, symbol, this.ParseTicker(ticker, market)) } } ch <- this.FilterByArrayTickers(result, "symbol", symbols) return nil }() return ch } /** * @method * @name bithumb#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://apidocs.bithumb.com/v1.2.0/reference/%ED%98%84%EC%9E%AC%EA%B0%80-%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ func (this *bithumb) FetchTicker(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) params := GetArg(optionalArgs, 0, map[string]interface{} {}) _ = params retRes5868 := (<-this.LoadMarkets()) PanicOnError(retRes5868) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "baseId": GetValue(market, "baseId"), "quoteId": GetValue(market, "quoteId"), } response:= (<-this.PublicGetTickerBaseIdQuoteId(this.Extend(request, params))) PanicOnError(response) // // { // "status":"0000", // "data":{ // "opening_price":"227100", // "closing_price":"228400", // "min_price":"222300", // "max_price":"230000", // "units_traded":"82618.56075337", // "acc_trade_value":"18767376138.6031", // "prev_closing_price":"227100", // "units_traded_24H":"151871.13484676", // "acc_trade_value_24H":"34247610416.8974", // "fluctate_24H":"8700", // "fluctate_rate_24H":"3.96", // "date":"1587710327264" // } // } // var data interface{} = this.SafeDict(response, "data", map[string]interface{} {}) ch <- this.ParseTicker(data, market) return nil }() return ch } func (this *bithumb) ParseOHLCV(ohlcv interface{}, optionalArgs ...interface{}) interface{} { // // [ // 1576823400000, // 기준 시간 // "8284000", // 시가 // "8286000", // 종가 // "8289000", // 고가 // "8276000", // 저가 // "15.41503692" // 거래량 // ] // market := GetArg(optionalArgs, 0, nil) _ = market return []interface{}{this.SafeInteger(ohlcv, 0), this.SafeNumber(ohlcv, 1), this.SafeNumber(ohlcv, 3), this.SafeNumber(ohlcv, 4), this.SafeNumber(ohlcv, 2), this.SafeNumber(ohlcv, 5)} } /** * @method * @name bithumb#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @see https://apidocs.bithumb.com/v1.2.0/reference/candlestick-rest-api * @param {string} symbol unified symbol of the market to fetch OHLCV data for * @param {string} timeframe the length of time each candle represents * @param {int} [since] timestamp in ms of the earliest candle to fetch * @param {int} [limit] the maximum amount of candles to fetch * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume */ func (this *bithumb) FetchOHLCV(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) timeframe := GetArg(optionalArgs, 0, "1m") _ = timeframe since := GetArg(optionalArgs, 1, nil) _ = since limit := GetArg(optionalArgs, 2, nil) _ = limit params := GetArg(optionalArgs, 3, map[string]interface{} {}) _ = params retRes6508 := (<-this.LoadMarkets()) PanicOnError(retRes6508) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "baseId": GetValue(market, "baseId"), "quoteId": GetValue(market, "quoteId"), "interval": this.SafeString(this.Timeframes, timeframe, timeframe), } response:= (<-this.PublicGetCandlestickBaseIdQuoteIdInterval(this.Extend(request, params))) PanicOnError(response) // // { // "status": "0000", // "data": { // [ // 1576823400000, // 기준 시간 // "8284000", // 시가 // "8286000", // 종가 // "8289000", // 고가 // "8276000", // 저가 // "15.41503692" // 거래량 // ], // [ // 1576824000000, // 기준 시간 // "8284000", // 시가 // "8281000", // 종가 // "8289000", // 고가 // "8275000", // 저가 // "6.19584467" // 거래량 // ], // } // } // var data interface{} = this.SafeList(response, "data", []interface{}{}) ch <- this.ParseOHLCVs(data, market, timeframe, since, limit) return nil }() return ch } func (this *bithumb) ParseTrade(trade interface{}, optionalArgs ...interface{}) interface{} { // // fetchTrades (public) // // { // "transaction_date":"2020-04-23 22:21:46", // "type":"ask", // "units_traded":"0.0125", // "price":"8667000", // "total":"108337" // } // // fetchOrder (private) // // { // "transaction_date": "1572497603902030", // "price": "8601000", // "units": "0.005", // "fee_currency": "KRW", // "fee": "107.51", // "total": "43005" // } // // a workaround for their bug in date format, hours are not 0-padded market := GetArg(optionalArgs, 0, nil) _ = market var timestamp interface{} = nil var transactionDatetime interface{} = this.SafeString(trade, "transaction_date") if IsTrue(!IsEqual(transactionDatetime, nil)) { var parts interface{} = Split(transactionDatetime, " ") var numParts interface{} = GetArrayLength(parts) if IsTrue(IsGreaterThan(numParts, 1)) { var transactionDate interface{} = GetValue(parts, 0) var transactionTime interface{} = GetValue(parts, 1) if IsTrue(IsLessThan(GetLength(transactionTime), 8)) { transactionTime = Add("0", transactionTime) } timestamp = this.Parse8601(Add(Add(transactionDate, " "), transactionTime)) } else { timestamp = this.SafeIntegerProduct(trade, "transaction_date", 0.001) } } if IsTrue(!IsEqual(timestamp, nil)) { timestamp = Subtract(timestamp, Multiply(9, 3600000)) // they report UTC + 9 hours, server in Korean timezone } var typeVar interface{} = nil var side interface{} = this.SafeString(trade, "type") side = Ternary(IsTrue((IsEqual(side, "ask"))), "sell", "buy") var id interface{} = this.SafeString(trade, "cont_no") market = this.SafeMarket(nil, market) var priceString interface{} = this.SafeString(trade, "price") var amountString interface{} = this.FixCommaNumber(this.SafeString2(trade, "units_traded", "units")) var costString interface{} = this.SafeString(trade, "total") var fee interface{} = nil var feeCostString interface{} = this.SafeString(trade, "fee") if IsTrue(!IsEqual(feeCostString, nil)) { var feeCurrencyId interface{} = this.SafeString(trade, "fee_currency") var feeCurrencyCode interface{} = this.CommonCurrencyCode(feeCurrencyId) fee = map[string]interface{} { "cost": feeCostString, "currency": feeCurrencyCode, } } return this.SafeTrade(map[string]interface{} { "id": id, "info": trade, "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "symbol": GetValue(market, "symbol"), "order": nil, "type": typeVar, "side": side, "takerOrMaker": nil, "price": priceString, "amount": amountString, "cost": costString, "fee": fee, }, market) } /** * @method * @name bithumb#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://apidocs.bithumb.com/v1.2.0/reference/%EC%B5%9C%EA%B7%BC-%EC%B2%B4%EA%B2%B0-%EB%82%B4%EC%97%AD * @param {string} symbol unified symbol of the market to fetch trades for * @param {int} [since] timestamp in ms of the earliest trade to fetch * @param {int} [limit] the maximum amount of trades to fetch * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades} */ func (this *bithumb) FetchTrades(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) since := GetArg(optionalArgs, 0, nil) _ = since limit := GetArg(optionalArgs, 1, nil) _ = limit params := GetArg(optionalArgs, 2, map[string]interface{} {}) _ = params retRes7758 := (<-this.LoadMarkets()) PanicOnError(retRes7758) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "baseId": GetValue(market, "baseId"), "quoteId": GetValue(market, "quoteId"), } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "count", limit) // default 20, max 100 } response:= (<-this.PublicGetTransactionHistoryBaseIdQuoteId(this.Extend(request, params))) PanicOnError(response) // // { // "status":"0000", // "data":[ // { // "transaction_date":"2020-04-23 22:21:46", // "type":"ask", // "units_traded":"0.0125", // "price":"8667000", // "total":"108337" // }, // ] // } // var data interface{} = this.SafeList(response, "data", []interface{}{}) ch <- this.ParseTrades(data, market, since, limit) return nil }() return ch } /** * @method * @name bithumb#createOrder * @description create a trade order * @see https://apidocs.bithumb.com/v1.2.0/reference/%EC%A7%80%EC%A0%95%EA%B0%80-%EC%A3%BC%EB%AC%B8%ED%95%98%EA%B8%B0 * @see https://apidocs.bithumb.com/v1.2.0/reference/%EC%8B%9C%EC%9E%A5%EA%B0%80-%EB%A7%A4%EC%88%98%ED%95%98%EA%B8%B0 * @see https://apidocs.bithumb.com/v1.2.0/reference/%EC%8B%9C%EC%9E%A5%EA%B0%80-%EB%A7%A4%EB%8F%84%ED%95%98%EA%B8%B0 * @param {string} symbol unified symbol of the market to create an order in * @param {string} type 'market' or 'limit' * @param {string} side 'buy' or 'sell' * @param {float} amount how much of currency you want to trade in units of base currency * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *bithumb) CreateOrder(symbol interface{}, typeVar interface{}, side interface{}, amount interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) price := GetArg(optionalArgs, 0, nil) _ = price params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes8198 := (<-this.LoadMarkets()) PanicOnError(retRes8198) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "order_currency": GetValue(market, "id"), "payment_currency": GetValue(market, "quote"), "units": amount, } var method interface{} = "privatePostTradePlace" if IsTrue(IsEqual(typeVar, "limit")) { AddElementToObject(request, "price", price) AddElementToObject(request, "type", Ternary(IsTrue((IsEqual(side, "buy"))), "bid", "ask")) } else { method = Add("privatePostTradeMarket", this.Capitalize(side)) } response:= (<-this.callDynamically(method, this.Extend(request, params))) PanicOnError(response) var id interface{} = this.SafeString(response, "order_id") if IsTrue(IsEqual(id, nil)) { panic(InvalidOrder(Add(this.Id, " createOrder() did not return an order id"))) } ch <- this.SafeOrder(map[string]interface{} { "info": response, "symbol": symbol, "type": typeVar, "side": side, "id": id, }, market) return nil }() return ch } /** * @method * @name bithumb#fetchOrder * @description fetches information on an order made by the user * @see https://apidocs.bithumb.com/v1.2.0/reference/%EA%B1%B0%EB%9E%98-%EC%A3%BC%EB%AC%B8%EB%82%B4%EC%97%AD-%EC%83%81%EC%84%B8-%EC%A1%B0%ED%9A%8C * @param {string} id order id * @param {string} symbol unified symbol of the market the order was made in * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *bithumb) FetchOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) symbol := GetArg(optionalArgs, 0, nil) _ = symbol params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params if IsTrue(IsEqual(symbol, nil)) { panic(ArgumentsRequired(Add(this.Id, " fetchOrder() requires a symbol argument"))) } retRes8618 := (<-this.LoadMarkets()) PanicOnError(retRes8618) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "order_id": id, "count": 1, "order_currency": GetValue(market, "base"), "payment_currency": GetValue(market, "quote"), } response:= (<-this.PrivatePostInfoOrderDetail(this.Extend(request, params))) PanicOnError(response) // // { // "status": "0000", // "data": { // "order_date": "1603161798539254", // "type": "ask", // "order_status": "Cancel", // "order_currency": "BTC", // "payment_currency": "KRW", // "watch_price": "0", // "order_price": "13344000", // "order_qty": "0.0125", // "cancel_date": "1603161803809993", // "cancel_type": "사용자취소", // "contract": [ // { // "transaction_date": "1603161799976383", // "price": "13344000", // "units": "0.0015", // "fee_currency": "KRW", // "fee": "0", // "total": "20016" // } // ], // } // } // var data interface{} = this.SafeDict(response, "data") ch <- this.ParseOrder(this.Extend(data, map[string]interface{} { "order_id": id, }), market) return nil }() return ch } func (this *bithumb) ParseOrderStatus(status interface{}) interface{} { var statuses interface{} = map[string]interface{} { "Pending": "open", "Completed": "closed", "Cancel": "canceled", } return this.SafeString(statuses, status, status) } func (this *bithumb) ParseOrder(order interface{}, optionalArgs ...interface{}) interface{} { // // // fetchOrder // // { // "transaction_date": "1572497603668315", // "type": "bid", // "order_status": "Completed", // Completed, Cancel ... // "order_currency": "BTC", // "payment_currency": "KRW", // "watch_price": "0", // present in Cancel order // "order_price": "8601000", // "order_qty": "0.007", // "cancel_date": "", // filled in Cancel order // "cancel_type": "", // filled in Cancel order, i.e. 사용자취소 // "contract": [ // { // "transaction_date": "1572497603902030", // "price": "8601000", // "units": "0.005", // "fee_currency": "KRW", // "fee": "107.51", // "total": "43005" // }, // ] // } // // fetchOpenOrders // // { // "order_currency": "BTC", // "payment_currency": "KRW", // "order_id": "C0101000007408440032", // "order_date": "1571728739360570", // "type": "bid", // "units": "5.0", // "units_remaining": "5.0", // "price": "501000", // } // market := GetArg(optionalArgs, 0, nil) _ = market var timestamp interface{} = this.SafeIntegerProduct(order, "order_date", 0.001) var sideProperty interface{} = this.SafeString2(order, "type", "side") var side interface{} = Ternary(IsTrue((IsEqual(sideProperty, "bid"))), "buy", "sell") var status interface{} = this.ParseOrderStatus(this.SafeString(order, "order_status")) var price interface{} = this.SafeString2(order, "order_price", "price") var typeVar interface{} = "limit" if IsTrue(Precise.StringEquals(price, "0")) { typeVar = "market" } var amount interface{} = this.FixCommaNumber(this.SafeString2(order, "order_qty", "units")) var remaining interface{} = this.FixCommaNumber(this.SafeString(order, "units_remaining")) if IsTrue(IsEqual(remaining, nil)) { if IsTrue(IsEqual(status, "closed")) { remaining = "0" } else if IsTrue(!IsEqual(status, "canceled")) { remaining = amount } } var symbol interface{} = nil var baseId interface{} = this.SafeString(order, "order_currency") var quoteId interface{} = this.SafeString(order, "payment_currency") var base interface{} = this.SafeCurrencyCode(baseId) var quote interface{} = this.SafeCurrencyCode(quoteId) if IsTrue(IsTrue((!IsEqual(base, nil))) && IsTrue((!IsEqual(quote, nil)))) { symbol = Add(Add(base, "/"), quote) } if IsTrue(IsEqual(symbol, nil)) { market = this.SafeMarket(nil, market) symbol = GetValue(market, "symbol") } var id interface{} = this.SafeString(order, "order_id") var rawTrades interface{} = this.SafeList(order, "contract", []interface{}{}) return this.SafeOrder(map[string]interface{} { "info": order, "id": id, "clientOrderId": nil, "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "lastTradeTimestamp": nil, "symbol": symbol, "type": typeVar, "timeInForce": nil, "postOnly": nil, "side": side, "price": price, "triggerPrice": nil, "amount": amount, "cost": nil, "average": nil, "filled": nil, "remaining": remaining, "status": status, "fee": nil, "trades": rawTrades, }, market) } /** * @method * @name bithumb#fetchOpenOrders * @description fetch all unfilled currently open orders * @see https://apidocs.bithumb.com/v1.2.0/reference/%EA%B1%B0%EB%9E%98-%EC%A3%BC%EB%AC%B8%EB%82%B4%EC%97%AD-%EC%A1%B0%ED%9A%8C * @param {string} symbol unified market symbol * @param {int} [since] the earliest time in ms to fetch open orders for * @param {int} [limit] the maximum number of open order structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *bithumb) FetchOpenOrders(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) symbol := GetArg(optionalArgs, 0, nil) _ = symbol since := GetArg(optionalArgs, 1, nil) _ = since limit := GetArg(optionalArgs, 2, nil) _ = limit params := GetArg(optionalArgs, 3, map[string]interface{} {}) _ = params if IsTrue(IsEqual(symbol, nil)) { panic(ArgumentsRequired(Add(this.Id, " fetchOpenOrders() requires a symbol argument"))) } retRes10238 := (<-this.LoadMarkets()) PanicOnError(retRes10238) var market interface{} = this.Market(symbol) if IsTrue(IsEqual(limit, nil)) { limit = 100 } var request interface{} = map[string]interface{} { "count": limit, "order_currency": GetValue(market, "base"), "payment_currency": GetValue(market, "quote"), } if IsTrue(!IsEqual(since, nil)) { AddElementToObject(request, "after", since) } response:= (<-this.PrivatePostInfoOrders(this.Extend(request, params))) PanicOnError(response) // // { // "status": "0000", // "data": [ // { // "order_currency": "BTC", // "payment_currency": "KRW", // "order_id": "C0101000007408440032", // "order_date": "1571728739360570", // "type": "bid", // "units": "5.0", // "units_remaining": "5.0", // "price": "501000", // } // ] // } // var data interface{} = this.SafeList(response, "data", []interface{}{}) ch <- this.ParseOrders(data, market, since, limit) return nil }() return ch } /** * @method * @name bithumb#cancelOrder * @description cancels an open order * @see https://apidocs.bithumb.com/v1.2.0/reference/%EC%A3%BC%EB%AC%B8-%EC%B7%A8%EC%86%8C%ED%95%98%EA%B8%B0 * @param {string} id order id * @param {string} symbol unified symbol of the market the order was made in * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *bithumb) CancelOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) symbol := GetArg(optionalArgs, 0, nil) _ = symbol params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params if IsTrue(IsEqual(symbol, nil)) { panic(ArgumentsRequired(Add(this.Id, " cancelOrder() requires a symbol argument"))) } var side_in_params interface{} = (InOp(params, "side")) if !IsTrue(side_in_params) { panic(ArgumentsRequired(Add(this.Id, " cancelOrder() requires a `side` parameter (sell or buy)"))) } var market interface{} = this.Market(symbol) var side interface{} = Ternary(IsTrue((IsEqual(GetValue(params, "side"), "buy"))), "bid", "ask") params = this.Omit(params, []interface{}{"side", "currency"}) // https://github.com/ccxt/ccxt/issues/6771 var request interface{} = map[string]interface{} { "order_id": id, "type": side, "order_currency": GetValue(market, "base"), "payment_currency": GetValue(market, "quote"), } response:= (<-this.PrivatePostTradeCancel(this.Extend(request, params))) PanicOnError(response) // // { // 'status': 'string', // } // ch <- this.SafeOrder(map[string]interface{} { "info": response, }) return nil }() return ch } func (this *bithumb) CancelUnifiedOrder(order interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) params := GetArg(optionalArgs, 0, map[string]interface{} {}) _ = params var request interface{} = map[string]interface{} { "side": GetValue(order, "side"), } retRes110115 := (<-this.CancelOrder(GetValue(order, "id"), GetValue(order, "symbol"), this.Extend(request, params))) PanicOnError(retRes110115) ch <- retRes110115 return nil }() return ch } /** * @method * @name bithumb#withdraw * @description make a withdrawal * @see https://apidocs.bithumb.com/v1.2.0/reference/%EC%BD%94%EC%9D%B8-%EC%B6%9C%EA%B8%88%ED%95%98%EA%B8%B0-%EA%B0%9C%EC%9D%B8 * @param {string} code unified currency code * @param {float} amount the amount to withdraw * @param {string} address the address to withdraw to * @param {string} tag * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ func (this *bithumb) Withdraw(code interface{}, amount interface{}, address interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) tag := GetArg(optionalArgs, 0, nil) _ = tag params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params tagparamsVariable := this.HandleWithdrawTagAndParams(tag, params); tag = GetValue(tagparamsVariable,0); params = GetValue(tagparamsVariable,1) this.CheckAddress(address) retRes11198 := (<-this.LoadMarkets()) PanicOnError(retRes11198) var currency interface{} = this.Currency(code) var request interface{} = map[string]interface{} { "units": amount, "address": address, "currency": GetValue(currency, "id"), } if IsTrue(IsTrue(IsTrue(IsTrue(IsTrue(IsEqual(code, "XRP")) || IsTrue(IsEqual(code, "XMR"))) || IsTrue(IsEqual(code, "EOS"))) || IsTrue(IsEqual(code, "STEEM"))) || IsTrue(IsEqual(code, "TON"))) { var destination interface{} = this.SafeString(params, "destination") if IsTrue(IsTrue((IsEqual(tag, nil))) && IsTrue((IsEqual(destination, nil)))) { panic(ArgumentsRequired(Add(Add(Add(this.Id, " "), code), " withdraw() requires a tag argument or an extra destination param"))) } else if IsTrue(!IsEqual(tag, nil)) { AddElementToObject(request, "destination", tag) } } response:= (<-this.PrivatePostTradeBtcWithdrawal(this.Extend(request, params))) PanicOnError(response) // // { "status" : "0000"} // ch <- this.ParseTransaction(response, currency) return nil }() return ch } func (this *bithumb) ParseTransaction(transaction interface{}, optionalArgs ...interface{}) interface{} { // // withdraw // // { "status" : "0000"} // currency := GetArg(optionalArgs, 0, nil) _ = currency currency = this.SafeCurrency(nil, currency) return map[string]interface{} { "id": nil, "txid": nil, "timestamp": nil, "datetime": nil, "network": nil, "addressFrom": nil, "address": nil, "addressTo": nil, "amount": nil, "type": nil, "currency": GetValue(currency, "code"), "status": nil, "updated": nil, "tagFrom": nil, "tag": nil, "tagTo": nil, "comment": nil, "internal": nil, "fee": nil, "info": transaction, } } func (this *bithumb) FixCommaNumber(numberStr interface{}) interface{} { // some endpoints need this https://github.com/ccxt/ccxt/issues/11031 if IsTrue(IsEqual(numberStr, nil)) { return nil } var finalNumberStr interface{} = numberStr for IsGreaterThan(GetIndexOf(finalNumberStr, ","), OpNeg(1)) { finalNumberStr = Replace(finalNumberStr, ",", "") } return finalNumberStr } func (this *bithumb) Nonce() interface{} { return this.Milliseconds() } func (this *bithumb) Sign(path interface{}, optionalArgs ...interface{}) interface{} { api := GetArg(optionalArgs, 0, "public") _ = api method := GetArg(optionalArgs, 1, "GET") _ = method params := GetArg(optionalArgs, 2, map[string]interface{} {}) _ = params headers := GetArg(optionalArgs, 3, nil) _ = headers body := GetArg(optionalArgs, 4, nil) _ = body var endpoint interface{} = Add("/", this.ImplodeParams(path, params)) var url interface{} = Add(this.ImplodeHostname(GetValue(GetValue(this.Urls, "api"), api)), endpoint) var query interface{} = this.Omit(params, this.ExtractParams(path)) if IsTrue(IsEqual(api, "public")) { if IsTrue(GetArrayLength(ObjectKeys(query))) { url = Add(url, Add("?", this.Urlencode(query))) } } else { this.CheckRequiredCredentials() body = this.Urlencode(this.Extend(map[string]interface{} { "endpoint": endpoint, }, query)) var nonce interface{} = ToString(this.Nonce()) var auth interface{} = Add(Add(Add(Add(endpoint, "//" + "0"), body), "//" + "0"), nonce) // eslint-disable-line quotes var signature interface{} = this.Hmac(this.Encode(auth), this.Encode(this.Secret), sha512) var signature64 interface{} = this.StringToBase64(signature) headers = map[string]interface{} { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded", "Api-Key": this.ApiKey, "Api-Sign": signature64, "Api-Nonce": nonce, } } return map[string]interface{} { "url": url, "method": method, "body": body, "headers": headers, } } func (this *bithumb) HandleErrors(httpCode interface{}, reason interface{}, url interface{}, method interface{}, headers interface{}, body interface{}, response interface{}, requestHeaders interface{}, requestBody interface{}) interface{} { if IsTrue(IsEqual(response, nil)) { return nil // fallback to default error handler } if IsTrue(InOp(response, "status")) { // // {"status":"5100","message":"After May 23th, recent_transactions is no longer, hence users will not be able to connect to recent_transactions"} // var status interface{} = this.SafeString(response, "status") var message interface{} = this.SafeString(response, "message") if IsTrue(!IsEqual(status, nil)) { if IsTrue(IsEqual(status, "0000")) { return nil // no error } else if IsTrue(IsEqual(message, "거래 진행중인 내역이 존재하지 않습니다.")) { // https://github.com/ccxt/ccxt/issues/9017 return nil // no error } var feedback interface{} = Add(Add(this.Id, " "), message) this.ThrowExactlyMatchedException(this.Exceptions, status, feedback) this.ThrowExactlyMatchedException(this.Exceptions, message, feedback) panic(ExchangeError(feedback)) } } return nil } func (this *bithumb) Init(userConfig map[string]interface{}) { this.Exchange = Exchange{} this.Exchange.InitParent(userConfig, this.Describe().(map[string]interface{}), this) this.Exchange.DerivedExchange = this }