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 exmo struct { Exchange } func NewExmoCore() exmo { p := exmo{} setDefaults(&p) return p } func (this *exmo) Describe() interface{} { return this.DeepExtend(this.Exchange.Describe(), map[string]interface{} { "id": "exmo", "name": "EXMO", "countries": []interface{}{"LT"}, "rateLimit": 100, "version": "v1.1", "has": map[string]interface{} { "CORS": nil, "spot": true, "margin": true, "swap": false, "future": false, "option": false, "addMargin": true, "cancelOrder": true, "cancelOrders": false, "createDepositAddress": false, "createMarketBuyOrder": true, "createMarketBuyOrderWithCost": true, "createMarketOrderWithCost": true, "createOrder": true, "createStopLimitOrder": true, "createStopMarketOrder": true, "createStopOrder": true, "editOrder": true, "fetchAccounts": false, "fetchBalance": true, "fetchCanceledOrders": true, "fetchCurrencies": true, "fetchDeposit": true, "fetchDepositAddress": true, "fetchDepositAddresses": false, "fetchDepositAddressesByNetwork": false, "fetchDeposits": true, "fetchDepositsWithdrawals": true, "fetchDepositWithdrawFee": "emulated", "fetchDepositWithdrawFees": true, "fetchFundingHistory": false, "fetchFundingRate": false, "fetchFundingRateHistory": false, "fetchFundingRates": false, "fetchIndexOHLCV": false, "fetchMarginMode": false, "fetchMarkets": true, "fetchMarkOHLCV": false, "fetchMyTrades": true, "fetchOHLCV": true, "fetchOpenInterestHistory": false, "fetchOpenOrders": true, "fetchOrder": "emulated", "fetchOrderBook": true, "fetchOrderBooks": true, "fetchOrderTrades": true, "fetchPosition": false, "fetchPositionHistory": false, "fetchPositionMode": false, "fetchPositions": false, "fetchPositionsHistory": false, "fetchPositionsRisk": false, "fetchPremiumIndexOHLCV": false, "fetchTicker": true, "fetchTickers": true, "fetchTrades": true, "fetchTradingFee": false, "fetchTradingFees": true, "fetchTransactionFees": true, "fetchTransactions": "emulated", "fetchTransfer": false, "fetchTransfers": false, "fetchWithdrawal": true, "fetchWithdrawals": true, "reduceMargin": true, "setMargin": false, "transfer": false, "withdraw": true, }, "timeframes": map[string]interface{} { "1m": "1", "5m": "5", "15m": "15", "30m": "30", "45m": "45", "1h": "60", "2h": "120", "3h": "180", "4h": "240", "1d": "D", "1w": "W", "1M": "M", }, "urls": map[string]interface{} { "logo": "https://user-images.githubusercontent.com/1294454/27766491-1b0ea956-5eda-11e7-9225-40d67b481b8d.jpg", "api": map[string]interface{} { "public": "https://api.exmo.com", "private": "https://api.exmo.com", "web": "https://exmo.me", }, "www": "https://exmo.me", "referral": "https://exmo.me/?ref=131685", "doc": []interface{}{"https://exmo.me/en/api_doc?ref=131685"}, "fees": "https://exmo.com/en/docs/fees", }, "api": map[string]interface{} { "web": map[string]interface{} { "get": []interface{}{"ctrl/feesAndLimits", "en/docs/fees"}, }, "public": map[string]interface{} { "get": []interface{}{"currency", "currency/list/extended", "order_book", "pair_settings", "ticker", "trades", "candles_history", "required_amount", "payments/providers/crypto/list"}, }, "private": map[string]interface{} { "post": []interface{}{"user_info", "order_create", "order_cancel", "stop_market_order_create", "stop_market_order_cancel", "user_open_orders", "user_trades", "user_cancelled_orders", "order_trades", "deposit_address", "withdraw_crypt", "withdraw_get_txid", "excode_create", "excode_load", "code_check", "wallet_history", "wallet_operations", "margin/user/order/create", "margin/user/order/update", "margin/user/order/cancel", "margin/user/position/close", "margin/user/position/margin_add", "margin/user/position/margin_remove", "margin/currency/list", "margin/pair/list", "margin/settings", "margin/funding/list", "margin/user/info", "margin/user/order/list", "margin/user/order/history", "margin/user/order/trades", "margin/user/order/max_quantity", "margin/user/position/list", "margin/user/position/margin_remove_info", "margin/user/position/margin_add_info", "margin/user/wallet/list", "margin/user/wallet/history", "margin/user/trade/list", "margin/trades", "margin/liquidation/feed"}, }, }, "fees": map[string]interface{} { "trading": map[string]interface{} { "feeSide": "get", "tierBased": true, "percentage": true, "maker": this.ParseNumber("0.004"), "taker": this.ParseNumber("0.004"), }, "transaction": map[string]interface{} { "tierBased": false, "percentage": false, }, }, "options": map[string]interface{} { "networks": map[string]interface{} { "ETH": "ERC20", "TRX": "TRC20", }, "fetchTradingFees": map[string]interface{} { "method": "fetchPrivateTradingFees", }, "margin": map[string]interface{} { "fillResponseFromRequest": true, }, }, "features": map[string]interface{} { "spot": map[string]interface{} { "sandbox": false, "createOrder": map[string]interface{} { "marginMode": true, "triggerPrice": true, "triggerPriceType": nil, "triggerDirection": false, "stopLossPrice": false, "takeProfitPrice": false, "attachedStopLossTakeProfit": nil, "timeInForce": map[string]interface{} { "IOC": true, "FOK": true, "PO": true, "GTD": true, }, "hedged": false, "selfTradePrevention": false, "trailing": false, "leverage": true, "marketBuyByCost": true, "marketBuyRequiresPrice": false, "iceberg": false, }, "createOrders": nil, "fetchMyTrades": map[string]interface{} { "marginMode": true, "limit": 100, "daysBack": nil, "untilDays": nil, "symbolRequired": true, }, "fetchOrder": map[string]interface{} { "marginMode": false, "trigger": false, "trailing": false, "symbolRequired": false, }, "fetchOpenOrders": map[string]interface{} { "marginMode": false, "limit": nil, "trigger": false, "trailing": false, "symbolRequired": false, }, "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, }, }, "commonCurrencies": map[string]interface{} { "GMT": "GMT Token", }, "precisionMode": TICK_SIZE, "exceptions": map[string]interface{} { "exact": map[string]interface{} { "140333": InvalidOrder, "140434": BadRequest, "40005": AuthenticationError, "40009": InvalidNonce, "40015": ExchangeError, "40016": OnMaintenance, "40017": AuthenticationError, "40032": PermissionDenied, "40033": PermissionDenied, "40034": RateLimitExceeded, "50052": InsufficientFunds, "50054": InsufficientFunds, "50304": OrderNotFound, "50173": OrderNotFound, "50277": InvalidOrder, "50319": InvalidOrder, "50321": InvalidOrder, "50381": InvalidOrder, }, "broad": map[string]interface{} { "range period is too long": BadRequest, "invalid syntax": BadRequest, "API rate limit exceeded": RateLimitExceeded, }, }, }) } func (this *exmo) ModifyMarginHelper(symbol interface{}, amount interface{}, typeVar 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 retRes3088 := (<-this.LoadMarkets()) PanicOnError(retRes3088) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "position_id": GetValue(market, "id"), "quantity": amount, } var response interface{} = nil if IsTrue(IsEqual(typeVar, "add")) { response = (<-this.PrivatePostMarginUserPositionMarginAdd(this.Extend(request, params))) PanicOnError(response) } else if IsTrue(IsEqual(typeVar, "reduce")) { response = (<-this.PrivatePostMarginUserPositionMarginRemove(this.Extend(request, params))) PanicOnError(response) } // // {} // var margin interface{} = this.ParseMarginModification(response, market) var options interface{} = this.SafeValue(this.Options, "margin", map[string]interface{} {}) var fillResponseFromRequest interface{} = this.SafeBool(options, "fillResponseFromRequest", true) if IsTrue(fillResponseFromRequest) { AddElementToObject(margin, "type", typeVar) AddElementToObject(margin, "amount", amount) } ch <- margin return nil }() return ch } func (this *exmo) ParseMarginModification(data interface{}, optionalArgs ...interface{}) interface{} { // // {} // market := GetArg(optionalArgs, 0, nil) _ = market return map[string]interface{} { "info": data, "symbol": this.SafeSymbol(nil, market), "type": nil, "marginMode": "isolated", "amount": nil, "total": nil, "code": this.SafeValue(market, "quote"), "status": "ok", "timestamp": nil, "datetime": nil, } } /** * @method * @name exmo#reduceMargin * @description remove margin from a position * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#eebf9f25-0289-4946-9482-89872c738449 * @param {string} symbol unified market symbol * @param {float} amount the amount of margin to remove * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=reduce-margin-structure} */ func (this *exmo) ReduceMargin(symbol interface{}, amount 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 retRes36215 := (<-this.ModifyMarginHelper(symbol, amount, "reduce", params)) PanicOnError(retRes36215) ch <- retRes36215 return nil }() return ch } /** * @method * @name exmo#addMargin * @description add margin * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#143ef808-79ca-4e49-9e79-a60ea4d8c0e3 * @param {string} symbol unified market symbol * @param {float} amount amount of margin to add * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure} */ func (this *exmo) AddMargin(symbol interface{}, amount 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 retRes37615 := (<-this.ModifyMarginHelper(symbol, amount, "add", params)) PanicOnError(retRes37615) ch <- retRes37615 return nil }() return ch } /** * @method * @name exmo#fetchTradingFees * @description fetch the trading fees for multiple markets * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#90927062-256c-4b03-900f-2b99131f9a54 * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#7de7e75c-5833-45a8-b937-c2276d235aaa * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols */ func (this *exmo) FetchTradingFees(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 options interface{} = this.SafeValue(this.Options, "fetchTradingFees", map[string]interface{} {}) var defaultMethod interface{} = this.SafeString(options, "method", "fetchPrivateTradingFees") var method interface{} = this.SafeString(params, "method", defaultMethod) params = this.Omit(params, "method") if IsTrue(IsEqual(method, "fetchPrivateTradingFees")) { retRes39419 := (<-this.FetchPrivateTradingFees(params)) PanicOnError(retRes39419) ch <- retRes39419 return nil } else { retRes39619 := (<-this.FetchPublicTradingFees(params)) PanicOnError(retRes39619) ch <- retRes39619 return nil } return nil }() return ch } func (this *exmo) FetchPrivateTradingFees(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 retRes4018 := (<-this.LoadMarkets()) PanicOnError(retRes4018) response:= (<-this.PrivatePostMarginPairList(params)) PanicOnError(response) // // { // "pairs": [{ // "name": "EXM_USD", // "buy_price": "0.02728391", // "sell_price": "0.0276", // "last_trade_price": "0.0276", // "ticker_updated": "1646956050056696046", // "is_fair_price": true, // "max_price_precision": "8", // "min_order_quantity": "1", // "max_order_quantity": "50000", // "min_order_price": "0.00000001", // "max_order_price": "1000", // "max_position_quantity": "50000", // "trade_taker_fee": "0.05", // "trade_maker_fee": "0", // "liquidation_fee": "0.5", // "max_leverage": "3", // "default_leverage": "3", // "liquidation_level": "5", // "margin_call_level": "7.5", // "position": "1", // "updated": "1638976144797807397" // } // ... // ] // } // var pairs interface{} = this.SafeValue(response, "pairs", []interface{}{}) var result interface{} = map[string]interface{} {} for i := 0; IsLessThan(i, GetArrayLength(pairs)); i++ { var pair interface{} = GetValue(pairs, i) var marketId interface{} = this.SafeString(pair, "name") var symbol interface{} = this.SafeSymbol(marketId, nil, "_") var makerString interface{} = this.SafeString(pair, "trade_maker_fee") var takerString interface{} = this.SafeString(pair, "trade_taker_fee") var maker interface{} = this.ParseNumber(Precise.StringDiv(makerString, "100")) var taker interface{} = this.ParseNumber(Precise.StringDiv(takerString, "100")) AddElementToObject(result, symbol, map[string]interface{} { "info": pair, "symbol": symbol, "maker": maker, "taker": taker, "percentage": true, "tierBased": true, }) } ch <- result return nil }() return ch } func (this *exmo) FetchPublicTradingFees(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 retRes4558 := (<-this.LoadMarkets()) PanicOnError(retRes4558) response:= (<-this.PublicGetPairSettings(params)) PanicOnError(response) // // { // "BTC_USD": { // "min_quantity": "0.00002", // "max_quantity": "1000", // "min_price": "1", // "max_price": "150000", // "max_amount": "500000", // "min_amount": "1", // "price_precision": "2", // "commission_taker_percent": "0.3", // "commission_maker_percent": "0.3" // }, // } // var result interface{} = map[string]interface{} {} for i := 0; IsLessThan(i, GetArrayLength(this.Symbols)); i++ { var symbol interface{} = GetValue(this.Symbols, i) var market interface{} = this.Market(symbol) var fee interface{} = this.SafeValue(response, GetValue(market, "id"), map[string]interface{} {}) var makerString interface{} = this.SafeString(fee, "commission_maker_percent") var takerString interface{} = this.SafeString(fee, "commission_taker_percent") var maker interface{} = this.ParseNumber(Precise.StringDiv(makerString, "100")) var taker interface{} = this.ParseNumber(Precise.StringDiv(takerString, "100")) AddElementToObject(result, symbol, map[string]interface{} { "info": fee, "symbol": symbol, "maker": maker, "taker": taker, "percentage": true, "tierBased": true, }) } ch <- result return nil }() return ch } func (this *exmo) ParseFixedFloatValue(input interface{}) interface{} { if IsTrue(IsTrue((IsEqual(input, nil))) || IsTrue((IsEqual(input, "-")))) { return nil } if IsTrue(IsEqual(input, "")) { return 0 } var isPercentage interface{} = (IsGreaterThanOrEqual(GetIndexOf(input, "%"), 0)) var parts interface{} = Split(input, " ") var value interface{} = Replace(GetValue(parts, 0), "%", "") var result interface{} = ParseFloat(value) if IsTrue(IsTrue((IsGreaterThan(result, 0))) && IsTrue(isPercentage)) { panic(ExchangeError(Add(Add(this.Id, " parseFixedFloatValue() detected an unsupported non-zero percentage-based fee "), input))) } return result } /** * @method * @name exmo#fetchTransactionFees * @deprecated * @description please use fetchDepositWithdrawFees instead * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2 * @param {string[]|undefined} codes list of unified currency codes * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a list of [transaction fees structures]{@link https://docs.ccxt.com/#/?id=fees-structure} */ func (this *exmo) FetchTransactionFees(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) codes := GetArg(optionalArgs, 0, nil) _ = codes params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes5218 := (<-this.LoadMarkets()) PanicOnError(retRes5218) cryptoList:= (<-this.PublicGetPaymentsProvidersCryptoList(params)) PanicOnError(cryptoList) // // { // "BTC":[ // { "type":"deposit", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.001 BTC. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 }, // { "type":"withdraw", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"350", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.0005 BTC", "currency_confirmations":6 } // ], // "ETH":[ // { "type":"withdraw", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"500", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.004 ETH", "currency_confirmations":4 }, // { "type":"deposit", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.01 ETH. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 } // ], // "USDT":[ // { "type":"deposit", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":false,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 }, // { "type":"withdraw", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":false,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"5 USDT", "currency_confirmations":6 }, // { "type":"deposit", "name":"USDT (ERC20)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 }, // { // "type":"withdraw", // "name":"USDT (ERC20)", // "currency_name":"USDT", // "min":"55", // "max":"200000", // "enabled":true, // "comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Recommendation: Due to the high load of ERC20 network, using TRC20 address for withdrawal is recommended.", // "commission_desc":"10 USDT", // "currency_confirmations":6 // }, // { "type":"deposit", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":true,"comment":"Minimum deposit amount is 10 USDT. Only TRON main network supported", "commission_desc":"0%", "currency_confirmations":2 }, // { "type":"withdraw", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"150000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Only TRON main network supported.", "commission_desc":"1 USDT", "currency_confirmations":6 } // ], // "XLM":[ // { "type":"deposit", "name":"XLM", "currency_name":"XLM", "min":"1", "max":"1000000", "enabled":true,"comment":"Attention! A deposit without memo(invoice) will not be credited. Minimum deposit amount is 1 XLM. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 }, // { "type":"withdraw", "name":"XLM", "currency_name":"XLM", "min":"21", "max":"1000000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales.", "commission_desc":"0.01 XLM", "currency_confirmations":1 } // ], // } // var result interface{} = map[string]interface{} {} var cryptoListKeys interface{} = ObjectKeys(cryptoList) for i := 0; IsLessThan(i, GetArrayLength(cryptoListKeys)); i++ { var code interface{} = GetValue(cryptoListKeys, i) if IsTrue(IsTrue(!IsEqual(codes, nil)) && !IsTrue(this.InArray(code, codes))) { continue } AddElementToObject(result, code, map[string]interface{} { "deposit": nil, "withdraw": nil, }) var currency interface{} = this.Currency(code) var currencyId interface{} = this.SafeString(currency, "id") var providers interface{} = this.SafeValue(cryptoList, currencyId, []interface{}{}) for j := 0; IsLessThan(j, GetArrayLength(providers)); j++ { var provider interface{} = GetValue(providers, j) var typeInner interface{} = this.SafeString(provider, "type") var commissionDesc interface{} = this.SafeString(provider, "commission_desc") var fee interface{} = this.ParseFixedFloatValue(commissionDesc) AddElementToObject(GetValue(result, code), typeInner, fee) } AddElementToObject(GetValue(result, code), "info", providers) } // cache them for later use AddElementToObject(this.Options, "transactionFees", result) ch <- result return nil }() return ch } /** * @method * @name exmo#fetchDepositWithdrawFees * @description fetch deposit and withdraw fees * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2 * @param {string[]|undefined} codes list of unified currency codes * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a list of [transaction fees structures]{@link https://docs.ccxt.com/#/?id=fees-structure} */ func (this *exmo) FetchDepositWithdrawFees(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) codes := GetArg(optionalArgs, 0, nil) _ = codes params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes5958 := (<-this.LoadMarkets()) PanicOnError(retRes5958) response:= (<-this.PublicGetPaymentsProvidersCryptoList(params)) PanicOnError(response) // // { // "USDT": [ // { // "type": "deposit", // or "withdraw" // "name": "USDT (ERC20)", // "currency_name": "USDT", // "min": "10", // "max": "0", // "enabled": true, // "comment": "Minimum deposit amount is 10 USDT", // "commission_desc": "0%", // "currency_confirmations": 2 // }, // ... // ], // ... // } // var result interface{} = this.ParseDepositWithdrawFees(response, codes) // cache them for later use AddElementToObject(this.Options, "transactionFees", result) ch <- result return nil }() return ch } func (this *exmo) ParseDepositWithdrawFee(fee interface{}, optionalArgs ...interface{}) interface{} { // // [ // { // "type": "deposit", // or "withdraw" // "name": "BTC", // "currency_name": "BTC", // "min": "0.001", // "max": "0", // "enabled": true, // "comment": "Minimum deposit amount is 0.001 BTC. We do not support BSC and BEP20 network, please consider this when sending funds", // "commission_desc": "0%", // "currency_confirmations": 1 // }, // ... // ] // currency := GetArg(optionalArgs, 0, nil) _ = currency var result interface{} = this.DepositWithdrawFee(fee) for i := 0; IsLessThan(i, GetArrayLength(fee)); i++ { var provider interface{} = GetValue(fee, i) var typeVar interface{} = this.SafeString(provider, "type") var networkId interface{} = this.SafeString(provider, "name") var networkCode interface{} = this.NetworkIdToCode(networkId, this.SafeString(currency, "code")) var commissionDesc interface{} = this.SafeString(provider, "commission_desc") var splitCommissionDesc interface{} = []interface{}{} var percentage interface{} = nil if IsTrue(!IsEqual(commissionDesc, nil)) { splitCommissionDesc = Split(commissionDesc, "%") var splitCommissionDescLength interface{} = GetArrayLength(splitCommissionDesc) percentage = IsGreaterThanOrEqual(splitCommissionDescLength, 2) } var network interface{} = this.SafeValue(GetValue(result, "networks"), networkCode) if IsTrue(IsEqual(network, nil)) { AddElementToObject(GetValue(result, "networks"), networkCode, map[string]interface{} { "withdraw": map[string]interface{} { "fee": nil, "percentage": nil, }, "deposit": map[string]interface{} { "fee": nil, "percentage": nil, }, }) } AddElementToObject(GetValue(GetValue(result, "networks"), networkCode), typeVar, map[string]interface{} { "fee": this.ParseFixedFloatValue(this.SafeString(splitCommissionDesc, 0)), "percentage": percentage, }) } return this.AssignDefaultDepositWithdrawFees(result) } /** * @method * @name exmo#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#7cdf0ca8-9ff6-4cf3-aa33-bcec83155c49 * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2 * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ func (this *exmo) FetchCurrencies(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 currencyList:= (<-this.PublicGetCurrencyListExtended(params)) PanicOnError(currencyList) // // [ // {"name":"VLX","description":"Velas"}, // {"name":"RUB","description":"Russian Ruble"}, // {"name":"BTC","description":"Bitcoin"}, // {"name":"USD","description":"US Dollar"} // ] // cryptoList:= (<-this.PublicGetPaymentsProvidersCryptoList(params)) PanicOnError(cryptoList) // // { // "BTC":[ // { "type":"deposit", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.001 BTC. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 }, // { "type":"withdraw", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"350", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.0005 BTC", "currency_confirmations":6 } // ], // "ETH":[ // { "type":"withdraw", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"500", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.004 ETH", "currency_confirmations":4 }, // { "type":"deposit", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.01 ETH. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 } // ], // "USDT":[ // { "type":"deposit", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":false,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 }, // { "type":"withdraw", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":false,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"5 USDT", "currency_confirmations":6 }, // { "type":"deposit", "name":"USDT (ERC20)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 }, // { "type":"withdraw", "name":"USDT (ERC20)", "currency_name":"USDT", "min":"55", "max":"200000", "enabled":true, "comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Recommendation: Due to the high load of ERC20 network, using TRC20 address for withdrawal is recommended.", "commission_desc":"10 USDT", "currency_confirmations":6 }, // { "type":"deposit", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":true,"comment":"Minimum deposit amount is 10 USDT. Only TRON main network supported", "commission_desc":"0%", "currency_confirmations":2 }, // { "type":"withdraw", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"150000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Only TRON main network supported.", "commission_desc":"1 USDT", "currency_confirmations":6 } // ], // "XLM":[ // { "type":"deposit", "name":"XLM", "currency_name":"XLM", "min":"1", "max":"1000000", "enabled":true,"comment":"Attention! A deposit without memo(invoice) will not be credited. Minimum deposit amount is 1 XLM. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 }, // { "type":"withdraw", "name":"XLM", "currency_name":"XLM", "min":"21", "max":"1000000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales.", "commission_desc":"0.01 XLM", "currency_confirmations":1 } // ], // } // var result interface{} = map[string]interface{} {} for i := 0; IsLessThan(i, GetArrayLength(currencyList)); i++ { var currency interface{} = GetValue(currencyList, i) var currencyId interface{} = this.SafeString(currency, "name") var name interface{} = this.SafeString(currency, "description") var providers interface{} = this.SafeValue(cryptoList, currencyId) var active interface{} = false var typeVar interface{} = "crypto" var limits interface{} = map[string]interface{} { "deposit": map[string]interface{} { "min": nil, "max": nil, }, "withdraw": map[string]interface{} { "min": nil, "max": nil, }, } var fee interface{} = nil var depositEnabled interface{} = nil var withdrawEnabled interface{} = nil if IsTrue(IsEqual(providers, nil)) { active = true typeVar = "fiat" } else { for j := 0; IsLessThan(j, GetArrayLength(providers)); j++ { var provider interface{} = GetValue(providers, j) var typeInner interface{} = this.SafeString(provider, "type") var minValue interface{} = this.SafeString(provider, "min") var maxValue interface{} = this.SafeString(provider, "max") if IsTrue(Precise.StringEq(maxValue, "0.0")) { maxValue = nil } var activeProvider interface{} = this.SafeValue(provider, "enabled") if IsTrue(IsEqual(typeInner, "deposit")) { if IsTrue(IsTrue(activeProvider) && !IsTrue(depositEnabled)) { depositEnabled = true } else if !IsTrue(activeProvider) { depositEnabled = false } } else if IsTrue(IsEqual(typeInner, "withdraw")) { if IsTrue(IsTrue(activeProvider) && !IsTrue(withdrawEnabled)) { withdrawEnabled = true } else if !IsTrue(activeProvider) { withdrawEnabled = false } } if IsTrue(activeProvider) { active = true var limitMin interface{} = this.NumberToString(GetValue(GetValue(limits, typeInner), "min")) if IsTrue(IsTrue((IsEqual(GetValue(GetValue(limits, typeInner), "min"), nil))) || IsTrue((Precise.StringLt(minValue, limitMin)))) { AddElementToObject(GetValue(limits, typeInner), "min", minValue) AddElementToObject(GetValue(limits, typeInner), "max", maxValue) if IsTrue(IsEqual(typeInner, "withdraw")) { var commissionDesc interface{} = this.SafeString(provider, "commission_desc") fee = this.ParseFixedFloatValue(commissionDesc) } } } } } var code interface{} = this.SafeCurrencyCode(currencyId) AddElementToObject(result, code, map[string]interface{} { "id": currencyId, "code": code, "name": name, "type": typeVar, "active": active, "deposit": depositEnabled, "withdraw": withdrawEnabled, "fee": fee, "precision": this.ParseNumber("1e-8"), "limits": limits, "info": providers, "networks": map[string]interface{} {}, }) } ch <- result return nil }() return ch } /** * @method * @name exmo#fetchMarkets * @description retrieves data on all markets for exmo * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#7de7e75c-5833-45a8-b937-c2276d235aaa * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ func (this *exmo) 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 response:= (<-this.PublicGetPairSettings(params)) PanicOnError(response) // // { // "BTC_USD":{ // "min_quantity":"0.0001", // "max_quantity":"1000", // "min_price":"1", // "max_price":"30000", // "max_amount":"500000", // "min_amount":"1", // "price_precision":8, // "commission_taker_percent":"0.4", // "commission_maker_percent":"0.4" // }, // } // var marginPairsDict interface{} = map[string]interface{} {} if IsTrue(this.CheckRequiredCredentials(false)) { marginPairs:= (<-this.PrivatePostMarginPairList(params)) PanicOnError(marginPairs) // // { // "pairs": [ // { // "buy_price": "55978.85", // "default_leverage": "3", // "is_fair_price": true, // "last_trade_price": "55999.23", // "liquidation_fee": "2", // "liquidation_level": "10", // "margin_call_level": "15", // "max_leverage": "3", // "max_order_price": "150000", // "max_order_quantity": "1", // "max_position_quantity": "1", // "max_price_precision": 2, // "min_order_price": "1", // "min_order_quantity": "0.00002", // "name": "BTC_USD", // "position": 1, // "sell_price": "55985.51", // "ticker_updated": "1619019818936107989", // "trade_maker_fee": "0", // "trade_taker_fee": "0.05", // "updated": "1619008608955599013" // } // ] // } // var pairs interface{} = this.SafeValue(marginPairs, "pairs") marginPairsDict = this.IndexBy(pairs, "name") } var keys interface{} = ObjectKeys(response) var result interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(keys)); i++ { var id interface{} = GetValue(keys, i) var market interface{} = GetValue(response, id) var marginMarket interface{} = this.SafeValue(marginPairsDict, id) var symbol interface{} = Replace(id, "_", "/") baseIdquoteIdVariable := Split(symbol, "/"); baseId := GetValue(baseIdquoteIdVariable,0); quoteId := GetValue(baseIdquoteIdVariable,1) var base interface{} = this.SafeCurrencyCode(baseId) var quote interface{} = this.SafeCurrencyCode(quoteId) var takerString interface{} = this.SafeString(market, "commission_taker_percent") var makerString interface{} = this.SafeString(market, "commission_maker_percent") var maxQuantity interface{} = this.SafeString(market, "max_quantity") var marginMaxQuantity interface{} = this.SafeString(marginMarket, "max_order_quantity") AppendToArray(&result,map[string]interface{} { "id": id, "symbol": symbol, "base": base, "quote": quote, "settle": nil, "baseId": baseId, "quoteId": quoteId, "settleId": nil, "type": "spot", "spot": true, "margin": !IsEqual(marginMarket, nil), "swap": false, "future": false, "option": false, "active": nil, "contract": false, "linear": nil, "inverse": nil, "taker": this.ParseNumber(Precise.StringDiv(takerString, "100")), "maker": this.ParseNumber(Precise.StringDiv(makerString, "100")), "contractSize": nil, "expiry": nil, "expiryDatetime": nil, "strike": nil, "optionType": nil, "precision": map[string]interface{} { "amount": this.ParseNumber("1e-8"), "price": this.ParseNumber(this.ParsePrecision(this.SafeString(market, "price_precision"))), }, "limits": map[string]interface{} { "leverage": map[string]interface{} { "min": nil, "max": this.SafeNumber(market, "leverage"), }, "amount": map[string]interface{} { "min": this.SafeNumber(market, "min_quantity"), "max": this.ParseNumber(Precise.StringMax(maxQuantity, marginMaxQuantity)), }, "price": map[string]interface{} { "min": this.SafeNumber(market, "min_price"), "max": this.SafeNumber(market, "max_price"), }, "cost": map[string]interface{} { "min": this.SafeNumber(market, "min_amount"), "max": this.SafeNumber(market, "max_amount"), }, }, "created": nil, "info": market, }) } ch <- result return nil }() return ch } /** * @method * @name exmo#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#65eeb949-74e5-4631-9184-c38387fe53e8 * @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 * @param {int} [params.until] timestamp in ms of the latest candle to fetch * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume */ func (this *exmo) 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 retRes9428 := (<-this.LoadMarkets()) PanicOnError(retRes9428) var market interface{} = this.Market(symbol) var until interface{} = this.SafeIntegerProduct(params, "until", 0.001) var untilIsDefined interface{} = (!IsEqual(until, nil)) var request interface{} = map[string]interface{} { "symbol": GetValue(market, "id"), "resolution": this.SafeString(this.Timeframes, timeframe, timeframe), } var maxLimit interface{} = 3000 var duration interface{} = this.ParseTimeframe(timeframe) var now interface{} = this.ParseToInt(Divide(this.Milliseconds(), 1000)) if IsTrue(IsEqual(since, nil)) { var to interface{} = Ternary(IsTrue(untilIsDefined), mathMin(until, now), now) if IsTrue(IsEqual(limit, nil)) { limit = 1000 // cap default at generous amount } else { limit = mathMin(limit, maxLimit) } AddElementToObject(request, "from", Subtract(Subtract(to, (Multiply(limit, duration))), 1)) AddElementToObject(request, "to", to) } else { AddElementToObject(request, "from", Subtract(this.ParseToInt(Divide(since, 1000)), 1)) if IsTrue(untilIsDefined) { AddElementToObject(request, "to", mathMin(until, now)) } else { if IsTrue(IsEqual(limit, nil)) { limit = maxLimit } else { limit = mathMin(limit, maxLimit) } var to interface{} = this.Sum(since, Multiply(limit, duration)) AddElementToObject(request, "to", mathMin(to, now)) } } params = this.Omit(params, "until") response:= (<-this.PublicGetCandlesHistory(this.Extend(request, params))) PanicOnError(response) // // { // "candles":[ // {"t":1584057600000,"o":0.02235144,"c":0.02400233,"h":0.025171,"l":0.02221,"v":5988.34031761}, // {"t":1584144000000,"o":0.0240373,"c":0.02367413,"h":0.024399,"l":0.0235,"v":2027.82522329}, // {"t":1584230400000,"o":0.02363458,"c":0.02319242,"h":0.0237948,"l":0.02223196,"v":1707.96944997}, // ] // } // var candles interface{} = this.SafeList(response, "candles", []interface{}{}) ch <- this.ParseOHLCVs(candles, market, timeframe, since, limit) return nil }() return ch } func (this *exmo) ParseOHLCV(ohlcv interface{}, optionalArgs ...interface{}) interface{} { // // { // "t":1584057600000, // "o":0.02235144, // "c":0.02400233, // "h":0.025171, // "l":0.02221, // "v":5988.34031761 // } // market := GetArg(optionalArgs, 0, nil) _ = market return []interface{}{this.SafeInteger(ohlcv, "t"), this.SafeNumber(ohlcv, "o"), this.SafeNumber(ohlcv, "h"), this.SafeNumber(ohlcv, "l"), this.SafeNumber(ohlcv, "c"), this.SafeNumber(ohlcv, "v")} } func (this *exmo) ParseBalance(response interface{}) interface{} { var result interface{} = map[string]interface{} { "info": response, } var wallets interface{} = this.SafeValue(response, "wallets") if IsTrue(!IsEqual(wallets, nil)) { var currencyIds interface{} = ObjectKeys(wallets) for i := 0; IsLessThan(i, GetArrayLength(currencyIds)); i++ { var currencyId interface{} = GetValue(currencyIds, i) var item interface{} = GetValue(wallets, currencyId) var currency interface{} = this.SafeCurrencyCode(currencyId) var account interface{} = this.Account() AddElementToObject(account, "used", this.SafeString(item, "used")) AddElementToObject(account, "free", this.SafeString(item, "free")) AddElementToObject(account, "total", this.SafeString(item, "balance")) AddElementToObject(result, currency, account) } } else { var free interface{} = this.SafeValue(response, "balances", map[string]interface{} {}) var used interface{} = this.SafeValue(response, "reserved", map[string]interface{} {}) var currencyIds interface{} = ObjectKeys(free) for i := 0; IsLessThan(i, GetArrayLength(currencyIds)); i++ { var currencyId interface{} = GetValue(currencyIds, i) var code interface{} = this.SafeCurrencyCode(currencyId) var account interface{} = this.Account() if IsTrue(InOp(free, currencyId)) { AddElementToObject(account, "free", this.SafeString(free, currencyId)) } if IsTrue(InOp(used, currencyId)) { AddElementToObject(account, "used", this.SafeString(used, currencyId)) } AddElementToObject(result, code, account) } } return this.SafeBalance(result) } /** * @method * @name exmo#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#59c5160f-27a1-4d9a-8cfb-7979c7ffaac6 * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#c8388df7-1f9f-4d41-81c4-5a387d171dc6 * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.marginMode] *isolated* fetches the isolated margin balance * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure} */ func (this *exmo) 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 retRes10588 := (<-this.LoadMarkets()) PanicOnError(retRes10588) var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("fetchBalance", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) if IsTrue(IsEqual(marginMode, "cross")) { panic(BadRequest(Add(this.Id, " does not support cross margin"))) } var response interface{} = nil if IsTrue(IsEqual(marginMode, "isolated")) { response = (<-this.PrivatePostMarginUserWalletList(params)) PanicOnError(response) } else { response = (<-this.PrivatePostUserInfo(params)) PanicOnError(response) } ch <- this.ParseBalance(response) return nil }() return ch } /** * @method * @name exmo#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#c60c51a8-e683-4f45-a000-820723d37871 * @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 *exmo) 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 retRes11078 := (<-this.LoadMarkets()) PanicOnError(retRes11078) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "limit", limit) } response:= (<-this.PublicGetOrderBook(this.Extend(request, params))) PanicOnError(response) var result interface{} = this.SafeDict(response, GetValue(market, "id")) ch <- this.ParseOrderBook(result, GetValue(market, "symbol"), nil, "bid", "ask") return nil }() return ch } /** * @method * @name exmo#fetchOrderBooks * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data for multiple markets * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#c60c51a8-e683-4f45-a000-820723d37871 * @param {string[]|undefined} symbols list of unified market symbols, all symbols fetched if undefined, default is undefined * @param {int} [limit] max number of entries per orderbook to return, default is undefined * @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 symbol */ func (this *exmo) FetchOrderBooks(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) symbols := GetArg(optionalArgs, 0, nil) _ = symbols limit := GetArg(optionalArgs, 1, nil) _ = limit params := GetArg(optionalArgs, 2, map[string]interface{} {}) _ = params retRes11318 := (<-this.LoadMarkets()) PanicOnError(retRes11318) var ids interface{} = nil if IsTrue(IsEqual(symbols, nil)) { ids = Join(this.Ids, ",") // max URL length is 2083 symbols, including http schema, hostname, tld, etc... if IsTrue(IsGreaterThan(GetArrayLength(ids), 2048)) { var numIds interface{} = GetArrayLength(this.Ids) panic(ExchangeError(Add(Add(Add(this.Id, " fetchOrderBooks() has "), ToString(numIds)), " symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchOrderBooks"))) } } else { ids = this.MarketIds(symbols) ids = Join(ids, ",") } var request interface{} = map[string]interface{} { "pair": ids, } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "limit", limit) } response:= (<-this.PublicGetOrderBook(this.Extend(request, params))) PanicOnError(response) var result interface{} = map[string]interface{} {} var marketIds interface{} = ObjectKeys(response) for i := 0; IsLessThan(i, GetArrayLength(marketIds)); i++ { var marketId interface{} = GetValue(marketIds, i) var symbol interface{} = this.SafeSymbol(marketId) AddElementToObject(result, symbol, this.ParseOrderBook(GetValue(response, marketId), symbol, nil, "bid", "ask")) } ch <- result return nil }() return ch } func (this *exmo) ParseTicker(ticker interface{}, optionalArgs ...interface{}) interface{} { // // { // "buy_price":"0.00002996", // "sell_price":"0.00003002", // "last_trade":"0.00002992", // "high":"0.00003028", // "low":"0.00002935", // "avg":"0.00002963", // "vol":"1196546.3163222", // "vol_curr":"35.80066578", // "updated":1642291733 // } // market := GetArg(optionalArgs, 0, nil) _ = market var timestamp interface{} = this.SafeTimestamp(ticker, "updated") market = this.SafeMarket(nil, market) var last interface{} = this.SafeString(ticker, "last_trade") return this.SafeTicker(map[string]interface{} { "symbol": GetValue(market, "symbol"), "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "high": this.SafeString(ticker, "high"), "low": this.SafeString(ticker, "low"), "bid": this.SafeString(ticker, "buy_price"), "bidVolume": nil, "ask": this.SafeString(ticker, "sell_price"), "askVolume": nil, "vwap": nil, "open": nil, "close": last, "last": last, "previousClose": nil, "change": nil, "percentage": nil, "average": this.SafeString(ticker, "avg"), "baseVolume": this.SafeString(ticker, "vol"), "quoteVolume": this.SafeString(ticker, "vol_curr"), "info": ticker, }, market) } /** * @method * @name exmo#fetchTickers * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#4c8e6459-3503-4361-b012-c34bb9f7e385 * @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 *exmo) 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 retRes12128 := (<-this.LoadMarkets()) PanicOnError(retRes12128) symbols = this.MarketSymbols(symbols) response:= (<-this.PublicGetTicker(params)) PanicOnError(response) // // { // "ADA_BTC":{ // "buy_price":"0.00002996", // "sell_price":"0.00003002", // "last_trade":"0.00002992", // "high":"0.00003028", // "low":"0.00002935", // "avg":"0.00002963", // "vol":"1196546.3163222", // "vol_curr":"35.80066578", // "updated":1642291733 // } // } // var result interface{} = map[string]interface{} {} var marketIds interface{} = ObjectKeys(response) for i := 0; IsLessThan(i, GetArrayLength(marketIds)); i++ { var marketId interface{} = GetValue(marketIds, i) var market interface{} = this.SafeMarket(marketId, nil, "_") var symbol interface{} = GetValue(market, "symbol") var ticker interface{} = this.SafeValue(response, marketId) AddElementToObject(result, symbol, this.ParseTicker(ticker, market)) } ch <- this.FilterByArrayTickers(result, "symbol", symbols) return nil }() return ch } /** * @method * @name exmo#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#4c8e6459-3503-4361-b012-c34bb9f7e385 * @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 *exmo) 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 retRes12528 := (<-this.LoadMarkets()) PanicOnError(retRes12528) response:= (<-this.PublicGetTicker(params)) PanicOnError(response) var market interface{} = this.Market(symbol) ch <- this.ParseTicker(GetValue(response, GetValue(market, "id")), market) return nil }() return ch } func (this *exmo) ParseTrade(trade interface{}, optionalArgs ...interface{}) interface{} { // // fetchTrades (public) // // { // "trade_id":165087520, // "date":1587470005, // "type":"buy", // "quantity":"1.004", // "price":"0.02491461", // "amount":"0.02501426" // }, // // fetchMyTrades, fetchOrderTrades // // { // "trade_id": 3, // "date": 1435488248, // "type": "buy", // "pair": "BTC_USD", // "order_id": 12345, // "quantity": 1, // "price": 100, // "amount": 100, // "exec_type": "taker", // "commission_amount": "0.02", // "commission_currency": "BTC", // "commission_percent": "0.2" // } // // fetchMyTrades (margin) // // { // "trade_id": "692861757015952517", // "trade_dt": "1693951853197811824", // "trade_type": "buy", // "pair": "ADA_USDT", // "quantity": "1.96607879", // "price": "0.2568", // "amount": "0.50488903" // } // market := GetArg(optionalArgs, 0, nil) _ = market var timestamp interface{} = this.SafeTimestamp(trade, "date") var id interface{} = this.SafeString(trade, "trade_id") var orderId interface{} = this.SafeString(trade, "order_id") var priceString interface{} = this.SafeString(trade, "price") var amountString interface{} = this.SafeString(trade, "quantity") var costString interface{} = this.SafeString(trade, "amount") var side interface{} = this.SafeString2(trade, "type", "trade_type") var typeVar interface{} = nil var marketId interface{} = this.SafeString(trade, "pair") market = this.SafeMarket(marketId, market, "_") var symbol interface{} = GetValue(market, "symbol") var isMaker interface{} = this.SafeValue(trade, "is_maker") var takerOrMakerDefault interface{} = nil if IsTrue(!IsEqual(isMaker, nil)) { takerOrMakerDefault = Ternary(IsTrue(isMaker), "maker", "taker") } var takerOrMaker interface{} = this.SafeString(trade, "exec_type", takerOrMakerDefault) var fee interface{} = nil var feeCostString interface{} = this.SafeString(trade, "commission_amount") if IsTrue(!IsEqual(feeCostString, nil)) { var feeCurrencyId interface{} = this.SafeString(trade, "commission_currency") var feeCurrencyCode interface{} = this.SafeCurrencyCode(feeCurrencyId) var feeRateString interface{} = this.SafeString(trade, "commission_percent") if IsTrue(!IsEqual(feeRateString, nil)) { feeRateString = Precise.StringDiv(feeRateString, "1000", 18) } fee = map[string]interface{} { "cost": feeCostString, "currency": feeCurrencyCode, "rate": feeRateString, } } return this.SafeTrade(map[string]interface{} { "id": id, "info": trade, "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "symbol": symbol, "order": orderId, "type": typeVar, "side": side, "takerOrMaker": takerOrMaker, "price": priceString, "amount": amountString, "cost": costString, "fee": fee, }, market) } /** * @method * @name exmo#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#5a5a9c0d-cf17-47f6-9d62-6d4404ebd5ac * @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 *exmo) 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 retRes13618 := (<-this.LoadMarkets()) PanicOnError(retRes13618) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), } response:= (<-this.PublicGetTrades(this.Extend(request, params))) PanicOnError(response) // // { // "ETH_BTC":[ // { // "trade_id":165087520, // "date":1587470005, // "type":"buy", // "quantity":"1.004", // "price":"0.02491461", // "amount":"0.02501426" // }, // { // "trade_id":165087369, // "date":1587469938, // "type":"buy", // "quantity":"0.94", // "price":"0.02492348", // "amount":"0.02342807" // } // ] // } // var data interface{} = this.SafeList(response, GetValue(market, "id"), []interface{}{}) ch <- this.ParseTrades(data, market, since, limit) return nil }() return ch } /** * @method * @name exmo#fetchMyTrades * @description fetch all trades made by the user * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#b8d8d9af-4f46-46a1-939b-ad261d79f452 // spot * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#f4b1aaf8-399f-403b-ab5e-4926d967a106 // margin * @param {string} symbol a symbol is required but it can be a single string, or a non-empty array * @param {int} [since] the earliest time in ms to fetch trades for * @param {int} [limit] *required for margin orders* the maximum number of trades structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * * EXCHANGE SPECIFIC PARAMETERS * @param {int} [params.offset] last deal offset, default = 0 * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure} */ func (this *exmo) FetchMyTrades(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, " fetchMyTrades() requires a symbol argument"))) } var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("fetchMyTrades", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) if IsTrue(IsEqual(marginMode, "cross")) { panic(BadRequest(Add(this.Id, " only isolated margin is supported"))) } retRes14178 := (<-this.LoadMarkets()) PanicOnError(retRes14178) var market interface{} = this.Market(symbol) var pair interface{} = GetValue(market, "id") var isSpot interface{} = !IsEqual(marginMode, "isolated") if IsTrue(IsEqual(limit, nil)) { limit = 100 } var request interface{} = map[string]interface{} {} if IsTrue(isSpot) { AddElementToObject(request, "pair", pair) } else { AddElementToObject(request, "pair_name", pair) } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "limit", limit) } var offset interface{} = this.SafeInteger(params, "offset", 0) AddElementToObject(request, "offset", offset) var response interface{} = nil if IsTrue(isSpot) { response = (<-this.PrivatePostUserTrades(this.Extend(request, params))) PanicOnError(response) } else { responseFromExchange:= (<-this.PrivatePostMarginTrades(this.Extend(request, params))) PanicOnError(responseFromExchange) // // { // "trades": { // "ADA_USDT": [ // { // "trade_id": "692861757015952517", // "trade_dt": "1693951853197811824", // "trade_type": "buy", // "pair": "ADA_USDT", // "quantity": "1.96607879", // "price": "0.2568", // "amount": "0.50488903" // }, // ] // ... // } // } // response = this.SafeValue(responseFromExchange, "trades") } var result interface{} = []interface{}{} var marketIdsInner interface{} = ObjectKeys(response) for i := 0; IsLessThan(i, GetArrayLength(marketIdsInner)); i++ { var marketId interface{} = GetValue(marketIdsInner, i) var resultMarket interface{} = this.SafeMarket(marketId, nil, "_") var items interface{} = GetValue(response, marketId) var trades interface{} = this.ParseTrades(items, resultMarket, since, limit) result = this.ArrayConcat(result, trades) } ch <- this.FilterBySinceLimit(result, since, limit) return nil }() return ch } /** * @method * @name exmo#createMarketOrderWithCost * @description create a market order by providing the symbol, side and cost * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd * @param {string} symbol unified symbol of the market to create an order in * @param {string} side 'buy' or 'sell' * @param {float} cost how much you want to trade in units of the quote currency * @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 *exmo) CreateMarketOrderWithCost(symbol interface{}, side interface{}, cost 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 retRes15078 := (<-this.LoadMarkets()) PanicOnError(retRes15078) params = this.Extend(params, map[string]interface{} { "cost": cost, }) retRes150915 := (<-this.CreateOrder(symbol, "market", side, cost, nil, params)) PanicOnError(retRes150915) ch <- retRes150915 return nil }() return ch } /** * @method * @name exmo#createMarketBuyOrderWithCost * @description create a market buy order by providing the symbol and cost * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd * @param {string} symbol unified symbol of the market to create an order in * @param {float} cost how much you want to trade in units of the quote currency * @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 *exmo) CreateMarketBuyOrderWithCost(symbol interface{}, cost 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 retRes15238 := (<-this.LoadMarkets()) PanicOnError(retRes15238) params = this.Extend(params, map[string]interface{} { "cost": cost, }) retRes152515 := (<-this.CreateOrder(symbol, "market", "buy", cost, nil, params)) PanicOnError(retRes152515) ch <- retRes152515 return nil }() return ch } /** * @method * @name exmo#createMarketSellOrderWithCost * @description create a market sell order by providing the symbol and cost * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd * @param {string} symbol unified symbol of the market to create an order in * @param {float} cost how much you want to trade in units of the quote currency * @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 *exmo) CreateMarketSellOrderWithCost(symbol interface{}, cost 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 retRes15398 := (<-this.LoadMarkets()) PanicOnError(retRes15398) params = this.Extend(params, map[string]interface{} { "cost": cost, }) retRes154115 := (<-this.CreateOrder(symbol, "market", "sell", cost, nil, params)) PanicOnError(retRes154115) ch <- retRes154115 return nil }() return ch } /** * @method * @name exmo#createOrder * @description create a trade order * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#de6f4321-eeac-468c-87f7-c4ad7062e265 // stop market * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#3561b86c-9ff1-436e-8e68-ac926b7eb523 // margin * @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 * @param {float} [params.triggerPrice] the price at which a trigger order is triggered at * @param {string} [params.timeInForce] *spot only* 'fok', 'ioc' or 'post_only' * @param {boolean} [params.postOnly] *spot only* true for post only orders * @param {float} [params.cost] *spot only* *market orders only* the cost of the order in the quote currency for market orders * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *exmo) 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 retRes15648 := (<-this.LoadMarkets()) PanicOnError(retRes15648) var market interface{} = this.Market(symbol) var isMarket interface{} = IsTrue((IsEqual(typeVar, "market"))) && IsTrue((IsEqual(price, nil))) var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("createOrder", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) if IsTrue(IsEqual(marginMode, "cross")) { panic(BadRequest(Add(this.Id, " only supports isolated margin"))) } var isSpot interface{} = (!IsEqual(marginMode, "isolated")) var triggerPrice interface{} = this.SafeStringN(params, []interface{}{"triggerPrice", "stopPrice", "stop_price"}) var cost interface{} = this.SafeString(params, "cost") var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), } if IsTrue(IsEqual(cost, nil)) { AddElementToObject(request, "quantity", this.AmountToPrecision(GetValue(market, "symbol"), amount)) } else { AddElementToObject(request, "quantity", this.CostToPrecision(GetValue(market, "symbol"), cost)) } var clientOrderId interface{} = this.SafeValue2(params, "client_id", "clientOrderId") if IsTrue(!IsEqual(clientOrderId, nil)) { clientOrderId = this.SafeInteger2(params, "client_id", "clientOrderId") if IsTrue(IsEqual(clientOrderId, nil)) { panic(BadRequest(Add(this.Id, " createOrder() client order id must be an integer / numeric literal"))) } else { AddElementToObject(request, "client_id", clientOrderId) } } var leverage interface{} = this.SafeNumber(params, "leverage") if IsTrue(!IsTrue(isSpot) && IsTrue((IsEqual(leverage, nil)))) { panic(ArgumentsRequired(Add(this.Id, " createOrder requires an extra param params[\"leverage\"] for margin orders"))) } params = this.Omit(params, []interface{}{"stopPrice", "stop_price", "triggerPrice", "timeInForce", "client_id", "clientOrderId", "cost"}) if IsTrue(!IsEqual(price, nil)) { AddElementToObject(request, "price", this.PriceToPrecision(GetValue(market, "symbol"), price)) } var response interface{} = nil if IsTrue(isSpot) { if IsTrue(!IsEqual(triggerPrice, nil)) { if IsTrue(IsEqual(typeVar, "limit")) { panic(BadRequest(Add(this.Id, " createOrder () cannot create stop limit orders for spot, only stop market"))) } else { AddElementToObject(request, "type", side) AddElementToObject(request, "trigger_price", this.PriceToPrecision(symbol, triggerPrice)) } response = (<-this.PrivatePostStopMarketOrderCreate(this.Extend(request, params))) PanicOnError(response) } else { var execType interface{} = this.SafeString(params, "exec_type") var isPostOnly interface{} = nil isPostOnlyparamsVariable := this.HandlePostOnly(IsEqual(typeVar, "market"), IsEqual(execType, "post_only"), params); isPostOnly = GetValue(isPostOnlyparamsVariable,0); params = GetValue(isPostOnlyparamsVariable,1) var timeInForce interface{} = this.SafeString(params, "timeInForce") AddElementToObject(request, "price", Ternary(IsTrue(isMarket), 0, this.PriceToPrecision(GetValue(market, "symbol"), price))) if IsTrue(IsEqual(typeVar, "limit")) { AddElementToObject(request, "type", side) } else if IsTrue(IsEqual(typeVar, "market")) { var marketSuffix interface{} = Ternary(IsTrue((!IsEqual(cost, nil))), "_total", "") AddElementToObject(request, "type", Add(Add("market_", side), marketSuffix)) } if IsTrue(isPostOnly) { AddElementToObject(request, "exec_type", "post_only") } else if IsTrue(!IsEqual(timeInForce, nil)) { AddElementToObject(request, "exec_type", timeInForce) } response = (<-this.PrivatePostOrderCreate(this.Extend(request, params))) PanicOnError(response) } } else { if IsTrue(!IsEqual(triggerPrice, nil)) { AddElementToObject(request, "stop_price", this.PriceToPrecision(symbol, triggerPrice)) if IsTrue(IsEqual(typeVar, "limit")) { AddElementToObject(request, "type", Add("stop_limit_", side)) } else if IsTrue(IsEqual(typeVar, "market")) { AddElementToObject(request, "type", Add("stop_", side)) } else { AddElementToObject(request, "type", typeVar) } } else { if IsTrue(IsTrue(IsEqual(typeVar, "limit")) || IsTrue(IsEqual(typeVar, "market"))) { AddElementToObject(request, "type", Add(Add(typeVar, "_"), side)) } else { AddElementToObject(request, "type", typeVar) } } response = (<-this.PrivatePostMarginUserOrderCreate(this.Extend(request, params))) PanicOnError(response) } ch <- this.ParseOrder(response, market) return nil }() return ch } /** * @method * @name exmo#cancelOrder * @description cancels an open order * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#1f710d4b-75bc-4b65-ad68-006f863a3f26 * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#a4d0aae8-28f7-41ac-94fd-c4030130453d // stop market * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#705dfec5-2b35-4667-862b-faf54eca6209 // margin * @param {string} id order id * @param {string} symbol not used by exmo cancelOrder () * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {boolean} [params.trigger] true to cancel a trigger order * @param {string} [params.marginMode] set to 'cross' or 'isolated' to cancel a margin order * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *exmo) 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 retRes16758 := (<-this.LoadMarkets()) PanicOnError(retRes16758) var request interface{} = map[string]interface{} {} var trigger interface{} = this.SafeValue2(params, "trigger", "stop") params = this.Omit(params, []interface{}{"trigger", "stop"}) var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("cancelOrder", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) if IsTrue(IsEqual(marginMode, "cross")) { panic(BadRequest(Add(this.Id, " only supports isolated margin"))) } var response interface{} = nil if IsTrue((IsEqual(marginMode, "isolated"))) { AddElementToObject(request, "order_id", id) response = (<-this.PrivatePostMarginUserOrderCancel(this.Extend(request, params))) PanicOnError(response) } else { if IsTrue(trigger) { AddElementToObject(request, "parent_order_id", id) response = (<-this.PrivatePostStopMarketOrderCancel(this.Extend(request, params))) PanicOnError(response) } else { AddElementToObject(request, "order_id", id) response = (<-this.PrivatePostOrderCancel(this.Extend(request, params))) PanicOnError(response) } } ch <- this.ParseOrder(response) return nil }() return ch } /** * @method * @name exmo#fetchOrder * @description *spot only* fetches information on an order made by the user * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 // spot * @param {string} id order id * @param {string} symbol not used by exmo fetchOrder * @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 *exmo) 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 retRes17238 := (<-this.LoadMarkets()) PanicOnError(retRes17238) var request interface{} = map[string]interface{} { "order_id": ToString(id), } response:= (<-this.PrivatePostOrderTrades(this.Extend(request, params))) PanicOnError(response) // // { // "type": "buy", // "in_currency": "BTC", // "in_amount": "1", // "out_currency": "USD", // "out_amount": "100", // "trades": [ // { // "trade_id": 3, // "date": 1435488248, // "type": "buy", // "pair": "BTC_USD", // "order_id": 12345, // "quantity": 1, // "price": 100, // "amount": 100 // } // ] // } // var order interface{} = this.ParseOrder(response) AddElementToObject(order, "id", ToString(id)) ch <- order return nil }() return ch } /** * @method * @name exmo#fetchOrderTrades * @description fetch all the trades made from a single order * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 // spot * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#00810661-9119-46c5-aec5-55abe9cb42c7 // margin * @param {string} id order id * @param {string} symbol unified market symbol * @param {int} [since] the earliest time in ms to fetch trades for * @param {int} [limit] the maximum number of trades to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.marginMode] set to "isolated" to fetch trades for a margin order * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure} */ func (this *exmo) FetchOrderTrades(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 since := GetArg(optionalArgs, 1, nil) _ = since limit := GetArg(optionalArgs, 2, nil) _ = limit params := GetArg(optionalArgs, 3, map[string]interface{} {}) _ = params var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("fetchOrderTrades", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) if IsTrue(IsEqual(marginMode, "cross")) { panic(BadRequest(Add(this.Id, " only supports isolated margin"))) } var market interface{} = nil if IsTrue(!IsEqual(symbol, nil)) { market = this.Market(symbol) } var request interface{} = map[string]interface{} { "order_id": ToString(id), } var response interface{} = nil if IsTrue(IsEqual(marginMode, "isolated")) { response = (<-this.PrivatePostMarginUserOrderTrades(this.Extend(request, params))) PanicOnError(response) } else { response = (<-this.PrivatePostOrderTrades(this.Extend(request, params))) PanicOnError(response) } var trades interface{} = this.SafeList(response, "trades") ch <- this.ParseTrades(trades, market, since, limit) return nil }() return ch } /** * @method * @name exmo#fetchOpenOrders * @description fetch all unfilled currently open orders * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#0e135370-daa4-4689-8acd-b6876dee9ba1 // spot open orders * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#a7cfd4f0-476e-4675-b33f-22a46902f245 // margin * @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 orders structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.marginMode] set to "isolated" for margin orders * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *exmo) 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 retRes18468 := (<-this.LoadMarkets()) PanicOnError(retRes18468) var market interface{} = nil if IsTrue(!IsEqual(symbol, nil)) { market = this.Market(symbol) symbol = GetValue(market, "symbol") } var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("fetchOpenOrders", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) var isMargin interface{} = (IsTrue((IsEqual(marginMode, "cross"))) || IsTrue((IsEqual(marginMode, "isolated")))) var response interface{} = nil var orders interface{} = []interface{}{} if IsTrue(isMargin) { response = (<-this.PrivatePostMarginUserOrderList(params)) PanicOnError(response) // // { // "orders": [ // { // "client_id": "0", // "comment": "", // "created": "1619068707985325495", // "distance": "0", // "expire": 0, // "funding_currency": "BTC", // "funding_quantity": "0.01", // "funding_rate": "0.02", // "leverage": "2", // "order_id": "123", // "pair": "BTC_USD", // "previous_type": "limit_sell", // "price": "58000", // "quantity": "0.01", // "src": 0, // "stop_price": "0", // "trigger_price": "58000", // "type": "limit_sell", // "updated": 1619068707989411800 // } // ] // } // params = this.Extend(params, map[string]interface{} { "status": "open", }) var responseOrders interface{} = this.SafeValue(response, "orders") orders = this.ParseOrders(responseOrders, market, since, limit, params) } else { response = (<-this.PrivatePostUserOpenOrders(params)) PanicOnError(response) // // { // "USDT_USD": [ // { // "parent_order_id": "507061384740151010", // "client_id": "100500", // "created": "1589547391", // "type": "stop_market_buy", // "pair": "USDT_USD", // "quantity": "1", // "trigger_price": "5", // "amount": "5" // } // ], // ... // } // var marketIds interface{} = ObjectKeys(response) for i := 0; IsLessThan(i, GetArrayLength(marketIds)); i++ { var marketId interface{} = GetValue(marketIds, i) var marketInner interface{} = this.SafeMarket(marketId) params = this.Extend(params, map[string]interface{} { "status": "open", }) var parsedOrders interface{} = this.ParseOrders(GetValue(response, marketId), marketInner, since, limit, params) orders = this.ArrayConcat(orders, parsedOrders) } } ch <- orders return nil }() return ch } func (this *exmo) ParseStatus(status interface{}) interface{} { if IsTrue(IsEqual(status, nil)) { return nil } var statuses interface{} = map[string]interface{} { "cancel_started": "canceled", } if IsTrue(IsGreaterThanOrEqual(GetIndexOf(status, "cancel"), 0)) { status = "canceled" } return this.SafeString(statuses, status, status) } func (this *exmo) ParseSide(orderType interface{}) interface{} { var side interface{} = map[string]interface{} { "limit_buy": "buy", "limit_sell": "sell", "market_buy": "buy", "market_sell": "sell", "stop_buy": "buy", "stop_sell": "sell", "stop_limit_buy": "buy", "stop_limit_sell": "sell", "trailing_stop_buy": "buy", "trailing_stop_sell": "sell", "stop_market_sell": "sell", "stop_market_buy": "buy", "buy": "buy", "sell": "sell", } return this.SafeString(side, orderType, orderType) } func (this *exmo) ParseOrder(order interface{}, optionalArgs ...interface{}) interface{} { // // fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders // // { // "order_id": "14", // "created": "1435517311", // "type": "buy", // "pair": "BTC_USD", // "price": "100", // "quantity": "1", // "amount": "100" // } // // fetchOrder // // { // "type": "buy", // "in_currency": "BTC", // "in_amount": "1", // "out_currency": "USD", // "out_amount": "100", // "trades": [ // { // "trade_id": 3, // "date": 1435488248, // "type": "buy", // "pair": "BTC_USD", // "order_id": 12345, // "quantity": 1, // "price": 100, // "amount": 100 // } // ] // } // // Margin fetchOpenOrders // // { // "client_id": "0", // "comment": "", // "created": "1619068707985325495", // "distance": "0", // "expire": 0, // "funding_currency": "BTC", // "funding_quantity": "0.01", // "funding_rate": "0.02", // "leverage": "2", // "order_id": "123", // "pair": "BTC_USD", // "previous_type": "limit_sell", // "price": "58000", // "quantity": "0.01", // "src": 0, // "stop_price": "0", // "trigger_price": "58000", // "type": "limit_sell", // "updated": 1619068707989411800 // } // // Margin fetchClosedOrders // // { // "distance": "0", // "event_id": "692842802860022508", // "event_time": "1619069531190173720", // "event_type": "OrderCancelStarted", // "order_id": "123", // "order_status": "cancel_started", // "order_type": "limit_sell", // "pair": "BTC_USD", // "price": "54115", // "quantity": "0.001", // "stop_price": "0", // "trade_id": "0", // "trade_price": "0", // "trade_quantity": "0", // "trade_type": "" // }, // market := GetArg(optionalArgs, 0, nil) _ = market var id interface{} = this.SafeString2(order, "order_id", "parent_order_id") var eventTime interface{} = this.SafeIntegerProduct2(order, "event_time", "created", 0.000001) var timestamp interface{} = this.SafeTimestamp(order, "created", eventTime) var orderType interface{} = this.SafeString2(order, "type", "order_type") var side interface{} = this.ParseSide(orderType) var marketId interface{} = nil if IsTrue(InOp(order, "pair")) { marketId = GetValue(order, "pair") } else if IsTrue(IsTrue((InOp(order, "in_currency"))) && IsTrue((InOp(order, "out_currency")))) { if IsTrue(IsEqual(side, "buy")) { marketId = Add(Add(GetValue(order, "in_currency"), "_"), GetValue(order, "out_currency")) } else { marketId = Add(Add(GetValue(order, "out_currency"), "_"), GetValue(order, "in_currency")) } } market = this.SafeMarket(marketId, market) var symbol interface{} = GetValue(market, "symbol") var amount interface{} = this.SafeString(order, "quantity") if IsTrue(IsEqual(amount, nil)) { var amountField interface{} = Ternary(IsTrue((IsEqual(side, "buy"))), "in_amount", "out_amount") amount = this.SafeString(order, amountField) } var price interface{} = this.SafeString(order, "price") var cost interface{} = this.SafeString(order, "amount") var transactions interface{} = this.SafeValue(order, "trades", []interface{}{}) var clientOrderId interface{} = this.SafeInteger(order, "client_id") var triggerPrice interface{} = this.SafeString(order, "stop_price") if IsTrue(IsEqual(triggerPrice, "0")) { triggerPrice = nil } var typeVar interface{} = nil if IsTrue(IsTrue((!IsEqual(orderType, "buy"))) && IsTrue((!IsEqual(orderType, "sell")))) { typeVar = orderType } return this.SafeOrder(map[string]interface{} { "id": id, "clientOrderId": clientOrderId, "datetime": this.Iso8601(timestamp), "timestamp": timestamp, "lastTradeTimestamp": this.SafeIntegerProduct(order, "updated", 0.000001), "status": this.ParseStatus(this.SafeString(order, "order_status")), "symbol": symbol, "type": typeVar, "timeInForce": nil, "postOnly": nil, "side": side, "price": price, "triggerPrice": triggerPrice, "cost": cost, "amount": amount, "filled": nil, "remaining": nil, "average": nil, "trades": transactions, "fee": nil, "info": order, }, market) } /** * @method * @name exmo#fetchCanceledOrders * @description fetches information on multiple canceled orders made by the user * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#1d2524dd-ae6d-403a-a067-77b50d13fbe5 // margin * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#a51be1d0-af5f-44e4-99d7-f7b04c6067d0 // spot canceled orders * @param {string} symbol unified market symbol of the market orders were made in * @param {int} [since] timestamp in ms of the earliest order, default is undefined * @param {int} [limit] max number of orders to return, default is undefined * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.marginMode] set to "isolated" for margin orders * @returns {object} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *exmo) FetchCanceledOrders(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 retRes21108 := (<-this.LoadMarkets()) PanicOnError(retRes21108) var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("fetchOrders", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) if IsTrue(IsEqual(marginMode, "cross")) { panic(BadRequest(Add(this.Id, " only supports isolated margin"))) } if IsTrue(IsEqual(limit, nil)) { limit = 100 } var isSpot interface{} = (!IsEqual(marginMode, "isolated")) if IsTrue(!IsEqual(symbol, nil)) { var marketInner interface{} = this.Market(symbol) symbol = GetValue(marketInner, "symbol") } var request interface{} = map[string]interface{} { "limit": limit, } AddElementToObject(request, "offset", Ternary(IsTrue((!IsEqual(since, nil))), limit, 0)) AddElementToObject(request, "limit", limit) var market interface{} = nil if IsTrue(!IsEqual(symbol, nil)) { market = this.Market(symbol) } var response interface{} = nil if IsTrue(isSpot) { response = (<-this.PrivatePostUserCancelledOrders(this.Extend(request, params))) PanicOnError(response) // // [ // { // "order_id": "27056153840", // "client_id": "0", // "created": "1653428646", // "type": "buy", // "pair": "BTC_USDT", // "quantity": "0.1", // "price": "10", // "amount": "1" // } // ] // params = this.Extend(params, map[string]interface{} { "status": "canceled", }) ch <- this.ParseOrders(response, market, since, limit, params) return nil } else { responseSwap:= (<-this.PrivatePostMarginUserOrderHistory(this.Extend(request, params))) PanicOnError(responseSwap) // // { // "items": [ // { // "event_id": "692862104574106858", // "event_time": "1694116400173489405", // "event_type": "OrderCancelStarted", // "order_id": "692862104561289319", // "order_type": "stop_limit_sell", // "order_status": "cancel_started", // "trade_id": "0", // "trade_type":"", // "trade_quantity": "0", // "trade_price": "0", // "pair": "ADA_USDT", // "quantity": "12", // "price": "0.23", // "stop_price": "0.22", // "distance": "0" // } // ... // ] // } // var items interface{} = this.SafeValue(responseSwap, "items") var orders interface{} = this.ParseOrders(items, market, since, limit, params) var result interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(orders)); i++ { var order interface{} = GetValue(orders, i) if IsTrue(IsEqual(GetValue(order, "status"), "canceled")) { AppendToArray(&result,order) } } ch <- result return nil } return nil }() return ch } /** * @method * @name exmo#editOrder * @description *margin only* edit a trade order * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#f27ee040-c75f-4b59-b608-d05bd45b7899 // margin * @param {string} id order id * @param {string} symbol unified CCXT market symbol * @param {string} type not used by exmo editOrder * @param {string} side not used by exmo editOrder * @param {float} [amount] how much of the currency you want to trade in units of the 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 * @param {float} [params.triggerPrice] stop price for stop-market and stop-limit orders * @param {string} params.marginMode must be set to isolated * * EXCHANGE SPECIFIC PARAMETERS * @param {int} [params.distance] distance for trailing stop orders * @param {int} [params.expire] expiration timestamp in UTC timezone for the order. order will not be expired if expire is 0 * @param {string} [params.comment] optional comment for order. up to 50 latin symbols, whitespaces, underscores * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *exmo) EditOrder(id interface{}, symbol interface{}, typeVar interface{}, side interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) amount := GetArg(optionalArgs, 0, nil) _ = amount price := GetArg(optionalArgs, 1, nil) _ = price params := GetArg(optionalArgs, 2, map[string]interface{} {}) _ = params retRes22158 := (<-this.LoadMarkets()) PanicOnError(retRes22158) var market interface{} = this.Market(symbol) var marginMode interface{} = nil marginModeparamsVariable := this.HandleMarginModeAndParams("editOrder", params); marginMode = GetValue(marginModeparamsVariable,0); params = GetValue(marginModeparamsVariable,1) if IsTrue(!IsEqual(marginMode, "isolated")) { panic(BadRequest(Add(this.Id, " editOrder() can only be used for isolated margin orders"))) } var triggerPrice interface{} = this.SafeNumberN(params, []interface{}{"triggerPrice", "stopPrice", "stop_price"}) params = this.Omit(params, []interface{}{"triggerPrice", "stopPrice"}) var request interface{} = map[string]interface{} { "order_id": id, } if IsTrue(!IsEqual(amount, nil)) { AddElementToObject(request, "quantity", amount) } if IsTrue(!IsEqual(price, nil)) { AddElementToObject(request, "price", this.PriceToPrecision(GetValue(market, "symbol"), price)) } if IsTrue(!IsEqual(triggerPrice, nil)) { AddElementToObject(request, "stop_price", this.PriceToPrecision(GetValue(market, "symbol"), triggerPrice)) } response:= (<-this.PrivatePostMarginUserOrderUpdate(this.Extend(request, params))) PanicOnError(response) ch <- this.ParseOrder(response) return nil }() return ch } /** * @method * @name exmo#fetchDepositAddress * @description fetch the deposit address for a currency associated with this account * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#c8f9ced9-7ab6-4383-a6a4-bc54469ba60e * @param {string} code unified currency code * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure} */ func (this *exmo) FetchDepositAddress(code 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 retRes22508 := (<-this.LoadMarkets()) PanicOnError(retRes22508) response:= (<-this.PrivatePostDepositAddress(params)) PanicOnError(response) // // { // "TRX":"TBnwrf4ZdoYXE3C8L2KMs7YPSL3fg6q6V9", // "USDTTRC20":"TBnwrf4ZdoYXE3C8L2KMs7YPSL3fg6q6V9" // } // var depositAddress interface{} = this.SafeString(response, code) var address interface{} = nil var tag interface{} = nil if IsTrue(depositAddress) { var addressAndTag interface{} = Split(depositAddress, ",") address = GetValue(addressAndTag, 0) var numParts interface{} = GetArrayLength(addressAndTag) if IsTrue(IsGreaterThan(numParts, 1)) { tag = GetValue(addressAndTag, 1) } } this.CheckAddress(address) ch <- map[string]interface{} { "info": response, "currency": code, "network": nil, "address": address, "tag": tag, } return nil }() return ch } func (this *exmo) GetMarketFromTrades(trades interface{}) interface{} { var tradesBySymbol interface{} = this.IndexBy(trades, "pair") var symbols interface{} = ObjectKeys(tradesBySymbol) var numSymbols interface{} = GetArrayLength(symbols) if IsTrue(IsEqual(numSymbols, 1)) { return GetValue(this.Markets, GetValue(symbols, 0)) } return nil } /** * @method * @name exmo#withdraw * @description make a withdrawal * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#3ab9c34d-ad58-4f87-9c57-2e2ea88a8325 * @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 *exmo) 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) retRes23038 := (<-this.LoadMarkets()) PanicOnError(retRes23038) var currency interface{} = this.Currency(code) var request interface{} = map[string]interface{} { "amount": amount, "currency": GetValue(currency, "id"), "address": address, } if IsTrue(!IsEqual(tag, nil)) { AddElementToObject(request, "invoice", tag) } var networks interface{} = this.SafeValue(this.Options, "networks", map[string]interface{} {}) var network interface{} = this.SafeStringUpper(params, "network") // this line allows the user to specify either ERC20 or ETH network = this.SafeString(networks, network, network) // handle ERC20>ETH alias if IsTrue(!IsEqual(network, nil)) { AddElementToObject(request, "transport", network) params = this.Omit(params, "network") } response:= (<-this.PrivatePostWithdrawCrypt(this.Extend(request, params))) PanicOnError(response) ch <- this.ParseTransaction(response, currency) return nil }() return ch } func (this *exmo) ParseTransactionStatus(status interface{}) interface{} { var statuses interface{} = map[string]interface{} { "transferred": "ok", "paid": "ok", "pending": "pending", "processing": "pending", "verifying": "pending", } return this.SafeString(statuses, status, status) } func (this *exmo) ParseTransaction(transaction interface{}, optionalArgs ...interface{}) interface{} { // // fetchDepositsWithdrawals // // { // "dt": 1461841192, // "type": "deposit", // "curr": "RUB", // "status": "processing", // "provider": "Qiwi (LA) [12345]", // "amount": "1", // "account": "", // "txid": "ec46f784ad976fd7f7539089d1a129fe46...", // } // // fetchWithdrawals // // { // "operation_id": 47412538520634344, // "created": 1573760013, // "updated": 1573760013, // "type": "withdraw", // "currency": "DOGE", // "status": "Paid", // "amount": "300", // "provider": "DOGE", // "commission": "0", // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS", // "order_id": 69670170, // "provider_type": "crypto", // "crypto_address": "DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS", // "card_number": "", // "wallet_address": "", // "email": "", // "phone": "", // "extra": { // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792", // "confirmations": null, // "excode": "", // "invoice": "" // }, // "error": "" // } // // withdraw // // { // "result": true, // "error": "", // "task_id": 11775077 // } // currency := GetArg(optionalArgs, 0, nil) _ = currency var timestamp interface{} = this.SafeTimestamp2(transaction, "dt", "created") var amountString interface{} = this.SafeString(transaction, "amount") if IsTrue(!IsEqual(amountString, nil)) { amountString = Precise.StringAbs(amountString) } var txid interface{} = this.SafeString(transaction, "txid") if IsTrue(IsEqual(txid, nil)) { var extra interface{} = this.SafeValue(transaction, "extra", map[string]interface{} {}) var extraTxid interface{} = this.SafeString(extra, "txid") if IsTrue(!IsEqual(extraTxid, "")) { txid = extraTxid } } var typeVar interface{} = this.SafeString(transaction, "type") var currencyId interface{} = this.SafeString2(transaction, "curr", "currency") var code interface{} = this.SafeCurrencyCode(currencyId, currency) var address interface{} = nil var comment interface{} = nil var account interface{} = this.SafeString(transaction, "account") if IsTrue(IsEqual(typeVar, "deposit")) { comment = account } else if IsTrue(IsEqual(typeVar, "withdrawal")) { address = account if IsTrue(!IsEqual(address, nil)) { var parts interface{} = Split(address, ":") var numParts interface{} = GetArrayLength(parts) if IsTrue(IsEqual(numParts, 2)) { address = this.SafeString(parts, 1) address = Replace(address, " ", "") } } } var fee interface{} = map[string]interface{} { "currency": nil, "cost": nil, "rate": nil, } // fixed funding fees only (for now) if !IsTrue(GetValue(GetValue(this.Fees, "transaction"), "percentage")) { var key interface{} = Ternary(IsTrue((IsEqual(typeVar, "withdrawal"))), "withdraw", "deposit") var feeCost interface{} = this.SafeString(transaction, "commission") if IsTrue(IsEqual(feeCost, nil)) { var transactionFees interface{} = this.SafeValue(this.Options, "transactionFees", map[string]interface{} {}) var codeFees interface{} = this.SafeValue(transactionFees, code, map[string]interface{} {}) feeCost = this.SafeString(codeFees, key) } // users don't pay for cashbacks, no fees for that var provider interface{} = this.SafeString(transaction, "provider") if IsTrue(IsEqual(provider, "cashback")) { feeCost = "0" } if IsTrue(!IsEqual(feeCost, nil)) { // withdrawal amount includes the fee if IsTrue(IsEqual(typeVar, "withdrawal")) { amountString = Precise.StringSub(amountString, feeCost) } AddElementToObject(fee, "cost", this.ParseNumber(feeCost)) AddElementToObject(fee, "currency", code) } } return map[string]interface{} { "info": transaction, "id": this.SafeString2(transaction, "order_id", "task_id"), "txid": txid, "type": typeVar, "currency": code, "network": this.SafeString(transaction, "provider"), "amount": this.ParseNumber(amountString), "status": this.ParseTransactionStatus(this.SafeStringLower(transaction, "status")), "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "address": address, "addressFrom": nil, "addressTo": address, "tag": nil, "tagFrom": nil, "tagTo": nil, "updated": this.SafeTimestamp(transaction, "updated"), "comment": comment, "internal": nil, "fee": fee, } } /** * @method * @name exmo#fetchDepositsWithdrawals * @description fetch history of deposits and withdrawals * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#31e69a33-4849-4e6a-b4b4-6d574238f6a7 * @param {string} [code] unified currency code for the currency of the deposit/withdrawals, default is undefined * @param {int} [since] timestamp in ms of the earliest deposit/withdrawal, default is undefined * @param {int} [limit] max number of deposit/withdrawals to return, default is undefined * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ func (this *exmo) FetchDepositsWithdrawals(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) code := GetArg(optionalArgs, 0, nil) _ = code since := GetArg(optionalArgs, 1, nil) _ = since limit := GetArg(optionalArgs, 2, nil) _ = limit params := GetArg(optionalArgs, 3, map[string]interface{} {}) _ = params retRes24838 := (<-this.LoadMarkets()) PanicOnError(retRes24838) var request interface{} = map[string]interface{} {} if IsTrue(!IsEqual(since, nil)) { AddElementToObject(request, "date", this.ParseToInt(Divide(since, 1000))) } var currency interface{} = nil if IsTrue(!IsEqual(code, nil)) { currency = this.Currency(code) } response:= (<-this.PrivatePostWalletHistory(this.Extend(request, params))) PanicOnError(response) // // { // "result": true, // "error": "", // "begin": "1493942400", // "end": "1494028800", // "history": [ // { // "dt": 1461841192, // "type": "deposit", // "curr": "RUB", // "status": "processing", // "provider": "Qiwi (LA) [12345]", // "amount": "1", // "account": "", // "txid": "ec46f784ad976fd7f7539089d1a129fe46...", // }, // { // "dt": 1463414785, // "type": "withdrawal", // "curr": "USD", // "status": "paid", // "provider": "EXCODE", // "amount": "-1", // "account": "EX-CODE_19371_USDda...", // "txid": "", // }, // ], // } // ch <- this.ParseTransactions(GetValue(response, "history"), currency, since, limit) return nil }() return ch } /** * @method * @name exmo#fetchWithdrawals * @description fetch all withdrawals made from an account * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706 * @param {string} code unified currency code * @param {int} [since] the earliest time in ms to fetch withdrawals for * @param {int} [limit] the maximum number of withdrawals structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ func (this *exmo) FetchWithdrawals(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) code := GetArg(optionalArgs, 0, nil) _ = code since := GetArg(optionalArgs, 1, nil) _ = since limit := GetArg(optionalArgs, 2, nil) _ = limit params := GetArg(optionalArgs, 3, map[string]interface{} {}) _ = params retRes25388 := (<-this.LoadMarkets()) PanicOnError(retRes25388) var currency interface{} = nil var request interface{} = map[string]interface{} { "type": "withdraw", } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "limit", limit) // default: 100, maximum: 100 } if IsTrue(!IsEqual(code, nil)) { currency = this.Currency(code) AddElementToObject(request, "currency", GetValue(currency, "id")) } response:= (<-this.PrivatePostWalletOperations(this.Extend(request, params))) PanicOnError(response) // // { // "items": [ // { // "operation_id": 47412538520634344, // "created": 1573760013, // "updated": 1573760013, // "type": "withdraw", // "currency": "DOGE", // "status": "Paid", // "amount": "300", // "provider": "DOGE", // "commission": "0", // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS", // "order_id": 69670170, // "extra": { // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792", // "excode": "", // "invoice": "" // }, // "error": "" // }, // ], // "count": 23 // } // var items interface{} = this.SafeList(response, "items", []interface{}{}) ch <- this.ParseTransactions(items, currency, since, limit) return nil }() return ch } /** * @method * @name exmo#fetchWithdrawal * @description fetch data on a currency withdrawal via the withdrawal id * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706 * @param {string} id withdrawal id * @param {string} code unified currency code of the currency withdrawn, default is undefined * @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 *exmo) FetchWithdrawal(id interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) code := GetArg(optionalArgs, 0, nil) _ = code params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes25928 := (<-this.LoadMarkets()) PanicOnError(retRes25928) var currency interface{} = nil var request interface{} = map[string]interface{} { "order_id": id, "type": "withdraw", } if IsTrue(!IsEqual(code, nil)) { currency = this.Currency(code) AddElementToObject(request, "currency", GetValue(currency, "id")) } response:= (<-this.PrivatePostWalletOperations(this.Extend(request, params))) PanicOnError(response) // // { // "items": [ // { // "operation_id": 47412538520634344, // "created": 1573760013, // "updated": 1573760013, // "type": "deposit", // "currency": "DOGE", // "status": "Paid", // "amount": "300", // "provider": "DOGE", // "commission": "0", // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS", // "order_id": 69670170, // "extra": { // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792", // "excode": "", // "invoice": "" // }, // "error": "" // }, // ], // "count": 23 // } // var items interface{} = this.SafeValue(response, "items", []interface{}{}) var first interface{} = this.SafeDict(items, 0, map[string]interface{} {}) ch <- this.ParseTransaction(first, currency) return nil }() return ch } /** * @method * @name exmo#fetchDeposit * @description fetch information on a deposit * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706 * @param {string} id deposit id * @param {string} code unified currency code, default is undefined * @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 *exmo) FetchDeposit(id interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) code := GetArg(optionalArgs, 0, nil) _ = code params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes26458 := (<-this.LoadMarkets()) PanicOnError(retRes26458) var currency interface{} = nil var request interface{} = map[string]interface{} { "order_id": id, "type": "deposit", } if IsTrue(!IsEqual(code, nil)) { currency = this.Currency(code) AddElementToObject(request, "currency", GetValue(currency, "id")) } response:= (<-this.PrivatePostWalletOperations(this.Extend(request, params))) PanicOnError(response) // // { // "items": [ // { // "operation_id": 47412538520634344, // "created": 1573760013, // "updated": 1573760013, // "type": "deposit", // "currency": "DOGE", // "status": "Paid", // "amount": "300", // "provider": "DOGE", // "commission": "0", // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS", // "order_id": 69670170, // "extra": { // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792", // "excode": "", // "invoice": "" // }, // "error": "" // }, // ], // "count": 23 // } // var items interface{} = this.SafeValue(response, "items", []interface{}{}) var first interface{} = this.SafeDict(items, 0, map[string]interface{} {}) ch <- this.ParseTransaction(first, currency) return nil }() return ch } /** * @method * @name exmo#fetchDeposits * @description fetch all deposits made to an account * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706 * @param {string} code unified currency code * @param {int} [since] the earliest time in ms to fetch deposits for * @param {int} [limit] the maximum number of deposits structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ func (this *exmo) FetchDeposits(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) code := GetArg(optionalArgs, 0, nil) _ = code since := GetArg(optionalArgs, 1, nil) _ = since limit := GetArg(optionalArgs, 2, nil) _ = limit params := GetArg(optionalArgs, 3, map[string]interface{} {}) _ = params retRes26998 := (<-this.LoadMarkets()) PanicOnError(retRes26998) var currency interface{} = nil var request interface{} = map[string]interface{} { "type": "deposit", } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "limit", limit) // default: 100, maximum: 100 } if IsTrue(!IsEqual(code, nil)) { currency = this.Currency(code) AddElementToObject(request, "currency", GetValue(currency, "id")) } response:= (<-this.PrivatePostWalletOperations(this.Extend(request, params))) PanicOnError(response) // // { // "items": [ // { // "operation_id": 47412538520634344, // "created": 1573760013, // "updated": 1573760013, // "type": "deposit", // "currency": "DOGE", // "status": "Paid", // "amount": "300", // "provider": "DOGE", // "commission": "0", // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS", // "order_id": 69670170, // "extra": { // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792", // "excode": "", // "invoice": "" // }, // "error": "" // }, // ], // "count": 23 // } // var items interface{} = this.SafeList(response, "items", []interface{}{}) ch <- this.ParseTransactions(items, currency, since, limit) return nil }() return ch } func (this *exmo) 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 url interface{} = Add(GetValue(GetValue(this.Urls, "api"), api), "/") if IsTrue(!IsEqual(api, "web")) { url = Add(url, Add(this.Version, "/")) } url = Add(url, path) if IsTrue(IsTrue((IsEqual(api, "public"))) || IsTrue((IsEqual(api, "web")))) { if IsTrue(GetArrayLength(ObjectKeys(params))) { url = Add(url, Add("?", this.Urlencode(params))) } } else if IsTrue(IsEqual(api, "private")) { this.CheckRequiredCredentials() var nonce interface{} = this.Nonce() body = this.Urlencode(this.Extend(map[string]interface{} { "nonce": nonce, }, params)) headers = map[string]interface{} { "Content-Type": "application/x-www-form-urlencoded", "Key": this.ApiKey, "Sign": this.Hmac(this.Encode(body), this.Encode(this.Secret), sha512), } } return map[string]interface{} { "url": url, "method": method, "body": body, "headers": headers, } } func (this *exmo) Nonce() interface{} { return this.Milliseconds() } func (this *exmo) 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(IsTrue((InOp(response, "error"))) && !IsTrue((InOp(response, "result")))) { // error: { // "code": "140434", // "msg": "Your margin balance is not sufficient to place the order for '5 TON'. Please top up your margin wallet by "2.5 USDT"." // } // var errorCode interface{} = this.SafeValue(response, "error", map[string]interface{} {}) var messageError interface{} = this.SafeString(errorCode, "msg") var code interface{} = this.SafeString(errorCode, "code") var feedback interface{} = Add(Add(this.Id, " "), body) this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), code, feedback) this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), messageError, feedback) panic(ExchangeError(feedback)) } if IsTrue(IsTrue((InOp(response, "result"))) || IsTrue((InOp(response, "errmsg")))) { // // {"result":false,"error":"Error 50052: Insufficient funds"} // {"s":"error","errmsg":"strconv.ParseInt: parsing \"\": invalid syntax"} // var success interface{} = this.SafeBool(response, "result", false) if IsTrue(IsString(success)) { if IsTrue(IsTrue((IsEqual(success, "true"))) || IsTrue((IsEqual(success, "1")))) { success = true } else { success = false } } if !IsTrue(success) { var code interface{} = nil var message interface{} = this.SafeString2(response, "error", "errmsg") var errorParts interface{} = Split(message, ":") var numParts interface{} = GetArrayLength(errorParts) if IsTrue(IsGreaterThan(numParts, 1)) { var errorSubParts interface{} = Split(GetValue(errorParts, 0), " ") var numSubParts interface{} = GetArrayLength(errorSubParts) code = Ternary(IsTrue((IsGreaterThan(numSubParts, 1))), GetValue(errorSubParts, 1), GetValue(errorSubParts, 0)) } var feedback interface{} = Add(Add(this.Id, " "), body) this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), code, feedback) this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), message, feedback) panic(ExchangeError(feedback)) } } return nil } func (this *exmo) Init(userConfig map[string]interface{}) { this.Exchange = Exchange{} this.Exchange.InitParent(userConfig, this.Describe().(map[string]interface{}), this) this.Exchange.DerivedExchange = this }