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 kraken struct { Exchange } func NewKrakenCore() kraken { p := kraken{} setDefaults(&p) return p } func (this *kraken) Describe() interface{} { return this.DeepExtend(this.Exchange.Describe(), map[string]interface{} { "id": "kraken", "name": "Kraken", "countries": []interface{}{"US"}, "version": "0", "rateLimit": 1000, "certified": false, "pro": true, "has": map[string]interface{} { "CORS": nil, "spot": true, "margin": true, "swap": false, "future": false, "option": false, "addMargin": false, "cancelAllOrders": true, "cancelAllOrdersAfter": true, "cancelOrder": true, "cancelOrders": true, "createDepositAddress": true, "createMarketBuyOrderWithCost": true, "createMarketOrderWithCost": false, "createMarketSellOrderWithCost": false, "createOrder": true, "createStopLimitOrder": true, "createStopMarketOrder": true, "createStopOrder": true, "createTrailingAmountOrder": true, "createTrailingPercentOrder": true, "editOrder": true, "fetchBalance": true, "fetchBorrowInterest": false, "fetchBorrowRateHistories": false, "fetchBorrowRateHistory": false, "fetchClosedOrders": true, "fetchCrossBorrowRate": false, "fetchCrossBorrowRates": false, "fetchCurrencies": true, "fetchDepositAddress": true, "fetchDepositAddresses": false, "fetchDepositAddressesByNetwork": false, "fetchDeposits": true, "fetchFundingHistory": false, "fetchFundingRate": false, "fetchFundingRateHistory": false, "fetchFundingRates": false, "fetchIndexOHLCV": false, "fetchIsolatedBorrowRate": false, "fetchIsolatedBorrowRates": false, "fetchLedger": true, "fetchLedgerEntry": true, "fetchLeverageTiers": false, "fetchMarkets": true, "fetchMarkOHLCV": false, "fetchMyTrades": true, "fetchOHLCV": true, "fetchOpenInterestHistory": false, "fetchOpenOrders": true, "fetchOrder": true, "fetchOrderBook": true, "fetchOrderTrades": "emulated", "fetchPositions": true, "fetchPremiumIndexOHLCV": false, "fetchStatus": true, "fetchTicker": true, "fetchTickers": true, "fetchTime": true, "fetchTrades": true, "fetchTradingFee": true, "fetchTradingFees": false, "fetchWithdrawals": true, "setLeverage": false, "setMarginMode": false, "transfer": true, "withdraw": true, }, "timeframes": map[string]interface{} { "1m": 1, "5m": 5, "15m": 15, "30m": 30, "1h": 60, "4h": 240, "1d": 1440, "1w": 10080, "2w": 21600, }, "urls": map[string]interface{} { "logo": "https://user-images.githubusercontent.com/51840849/76173629-fc67fb00-61b1-11ea-84fe-f2de582f58a3.jpg", "api": map[string]interface{} { "public": "https://api.kraken.com", "private": "https://api.kraken.com", "zendesk": "https://kraken.zendesk.com/api/v2/help_center/en-us/articles", }, "www": "https://www.kraken.com", "doc": "https://docs.kraken.com/rest/", "fees": "https://www.kraken.com/en-us/features/fee-schedule", }, "fees": map[string]interface{} { "trading": map[string]interface{} { "tierBased": true, "percentage": true, "taker": this.ParseNumber("0.0026"), "maker": this.ParseNumber("0.0016"), "tiers": map[string]interface{} { "taker": []interface{}{[]interface{}{this.ParseNumber("0"), this.ParseNumber("0.0026")}, []interface{}{this.ParseNumber("50000"), this.ParseNumber("0.0024")}, []interface{}{this.ParseNumber("100000"), this.ParseNumber("0.0022")}, []interface{}{this.ParseNumber("250000"), this.ParseNumber("0.0020")}, []interface{}{this.ParseNumber("500000"), this.ParseNumber("0.0018")}, []interface{}{this.ParseNumber("1000000"), this.ParseNumber("0.0016")}, []interface{}{this.ParseNumber("2500000"), this.ParseNumber("0.0014")}, []interface{}{this.ParseNumber("5000000"), this.ParseNumber("0.0012")}, []interface{}{this.ParseNumber("10000000"), this.ParseNumber("0.0001")}}, "maker": []interface{}{[]interface{}{this.ParseNumber("0"), this.ParseNumber("0.0016")}, []interface{}{this.ParseNumber("50000"), this.ParseNumber("0.0014")}, []interface{}{this.ParseNumber("100000"), this.ParseNumber("0.0012")}, []interface{}{this.ParseNumber("250000"), this.ParseNumber("0.0010")}, []interface{}{this.ParseNumber("500000"), this.ParseNumber("0.0008")}, []interface{}{this.ParseNumber("1000000"), this.ParseNumber("0.0006")}, []interface{}{this.ParseNumber("2500000"), this.ParseNumber("0.0004")}, []interface{}{this.ParseNumber("5000000"), this.ParseNumber("0.0002")}, []interface{}{this.ParseNumber("10000000"), this.ParseNumber("0.0")}}, }, }, }, "handleContentTypeApplicationZip": true, "api": map[string]interface{} { "zendesk": map[string]interface{} { "get": []interface{}{"360000292886", "201893608"}, }, "public": map[string]interface{} { "get": map[string]interface{} { "Assets": 1, "AssetPairs": 1, "Depth": 1.2, "OHLC": 1.2, "Spread": 1, "SystemStatus": 1, "Ticker": 1, "Time": 1, "Trades": 1.2, }, }, "private": map[string]interface{} { "post": map[string]interface{} { "AddOrder": 0, "AddOrderBatch": 0, "AddExport": 3, "AmendOrder": 0, "Balance": 3, "CancelAll": 3, "CancelAllOrdersAfter": 3, "CancelOrder": 0, "CancelOrderBatch": 0, "ClosedOrders": 3, "DepositAddresses": 3, "DepositMethods": 3, "DepositStatus": 3, "EditOrder": 0, "ExportStatus": 3, "GetWebSocketsToken": 3, "Ledgers": 6, "OpenOrders": 3, "OpenPositions": 3, "QueryLedgers": 3, "QueryOrders": 3, "QueryTrades": 3, "RetrieveExport": 3, "RemoveExport": 3, "BalanceEx": 3, "TradeBalance": 3, "TradesHistory": 6, "TradeVolume": 3, "Withdraw": 3, "WithdrawCancel": 3, "WithdrawInfo": 3, "WithdrawMethods": 3, "WithdrawAddresses": 3, "WithdrawStatus": 3, "WalletTransfer": 3, "CreateSubaccount": 3, "AccountTransfer": 3, "Earn/Allocate": 3, "Earn/Deallocate": 3, "Earn/AllocateStatus": 3, "Earn/DeallocateStatus": 3, "Earn/Strategies": 3, "Earn/Allocations": 3, }, }, }, "commonCurrencies": map[string]interface{} { "LUNA": "LUNC", "LUNA2": "LUNA", "REPV2": "REP", "REP": "REPV1", "UST": "USTC", "XBT": "BTC", "XBT.M": "BTC.M", "XDG": "DOGE", }, "options": map[string]interface{} { "timeDifference": 0, "adjustForTimeDifference": false, "marketsByAltname": map[string]interface{} {}, "delistedMarketsById": map[string]interface{} {}, "inactiveCurrencies": []interface{}{"CAD", "USD", "JPY", "GBP"}, "networks": map[string]interface{} { "ETH": "ERC20", "TRX": "TRC20", }, "depositMethods": map[string]interface{} { "1INCH": Add(Add("1inch", " "), "(1INCH)"), "AAVE": "Aave", "ADA": "ADA", "ALGO": "Algorand", "ANKR": Add(Add("ANKR", " "), "(ANKR)"), "ANT": Add(Add("Aragon", " "), "(ANT)"), "ATOM": "Cosmos", "AXS": Add(Add("Axie Infinity Shards", " "), "(AXS)"), "BADGER": Add(Add("Bager DAO", " "), "(BADGER)"), "BAL": Add(Add("Balancer", " "), "(BAL)"), "BAND": Add(Add("Band Protocol", " "), "(BAND)"), "BAT": "BAT", "BCH": "Bitcoin Cash", "BNC": Add(Add("Bifrost", " "), "(BNC)"), "BNT": Add(Add("Bancor", " "), "(BNT)"), "BTC": "Bitcoin", "CHZ": Add(Add("Chiliz", " "), "(CHZ)"), "COMP": Add(Add("Compound", " "), "(COMP)"), "CQT": Add(Add(" Covalent Query Token", " "), "(CQT)"), "CRV": Add(Add("Curve DAO Token", " "), "(CRV)"), "CTSI": Add(Add("Cartesi", " "), "(CTSI)"), "DAI": "Dai", "DASH": "Dash", "DOGE": "Dogecoin", "DOT": "Polkadot", "DYDX": Add(Add("dYdX", " "), "(DYDX)"), "ENJ": Add(Add("Enjin Coin", " "), "(ENJ)"), "EOS": "EOS", "ETC": Add(Add("Ether Classic", " "), "(Hex)"), "ETH": Add(Add("Ether", " "), "(Hex)"), "EWT": "Energy Web Token", "FEE": "Kraken Fee Credit", "FIL": "Filecoin", "FLOW": "Flow", "GHST": Add(Add("Aavegotchi", " "), "(GHST)"), "GNO": "GNO", "GRT": "GRT", "ICX": "Icon", "INJ": Add(Add("Injective Protocol", " "), "(INJ)"), "KAR": Add(Add("Karura", " "), "(KAR)"), "KAVA": "Kava", "KEEP": Add(Add("Keep Token", " "), "(KEEP)"), "KNC": Add(Add("Kyber Network", " "), "(KNC)"), "KSM": "Kusama", "LINK": "Link", "LPT": Add(Add("Livepeer Token", " "), "(LPT)"), "LRC": Add(Add("Loopring", " "), "(LRC)"), "LSK": "Lisk", "LTC": "Litecoin", "MANA": "MANA", "MATIC": Add(Add("Polygon", " "), "(MATIC)"), "MINA": "Mina", "MIR": Add(Add("Mirror Protocol", " "), "(MIR)"), "MKR": Add(Add("Maker", " "), "(MKR)"), "MLN": "MLN", "MOVR": Add(Add("Moonriver", " "), "(MOVR)"), "NANO": "NANO", "OCEAN": "OCEAN", "OGN": Add(Add("Origin Protocol", " "), "(OGN)"), "OMG": "OMG", "OXT": Add(Add("Orchid", " "), "(OXT)"), "OXY": Add(Add("Oxygen", " "), "(OXY)"), "PAXG": Add(Add("PAX", " "), "(Gold)"), "PERP": Add(Add("Perpetual Protocol", " "), "(PERP)"), "PHA": Add(Add("Phala", " "), "(PHA)"), "QTUM": "QTUM", "RARI": Add(Add("Rarible", " "), "(RARI)"), "RAY": Add(Add("Raydium", " "), "(RAY)"), "REN": Add(Add("Ren Protocol", " "), "(REN)"), "REP": "REPv2", "REPV1": "REP", "SAND": Add(Add("The Sandbox", " "), "(SAND)"), "SC": "Siacoin", "SDN": Add(Add("Shiden", " "), "(SDN)"), "SOL": "Solana", "SNX": Add(Add("Synthetix Network", " "), "(SNX)"), "SRM": "Serum", "STORJ": Add(Add("Storj", " "), "(STORJ)"), "SUSHI": Add(Add("Sushiswap", " "), "(SUSHI)"), "TBTC": "tBTC", "TRX": "Tron", "UNI": "UNI", "USDC": "USDC", "USDT": Add(Add("Tether USD", " "), "(ERC20)"), "USDT-TRC20": Add(Add("Tether USD", " "), "(TRC20)"), "WAVES": "Waves", "WBTC": Add(Add("Wrapped Bitcoin", " "), "(WBTC)"), "XLM": "Stellar XLM", "XMR": "Monero", "XRP": "Ripple XRP", "XTZ": "XTZ", "YFI": "YFI", "ZEC": Add(Add("Zcash", " "), "(Transparent)"), "ZRX": Add(Add("0x", " "), "(ZRX)"), }, "withdrawMethods": map[string]interface{} { "Lightning": "Lightning", "Bitcoin": "BTC", "Ripple": "XRP", "Litecoin": "LTC", "Dogecoin": "DOGE", "Stellar": "XLM", "Ethereum": "ERC20", "Arbitrum One": "Arbitrum", "Polygon": "MATIC", "Arbitrum Nova": "Arbitrum", "Optimism": "Optimism", "zkSync Era": "zkSync", "Ethereum Classic": "ETC", "Zcash": "ZEC", "Monero": "XMR", "Tron": "TRC20", "Solana": "SOL", "EOS": "EOS", "Bitcoin Cash": "BCH", "Cardano": "ADA", "Qtum": "QTUM", "Tezos": "XTZ", "Cosmos": "ATOM", "Nano": "NANO", "Siacoin": "SC", "Lisk": "LSK", "Waves": "WAVES", "ICON": "ICX", "Algorand": "ALGO", "Polygon - USDC.e": "MATIC", "Arbitrum One - USDC.e": "Arbitrum", "Polkadot": "DOT", "Kava": "KAVA", "Filecoin": "FIL", "Kusama": "KSM", "Flow": "FLOW", "Energy Web": "EW", "Mina": "MINA", "Centrifuge": "CFG", "Karura": "KAR", "Moonriver": "MOVR", "Shiden": "SDN", "Khala": "PHA", "Bifrost Kusama": "BNC", "Songbird": "SGB", "Terra classic": "LUNC", "KILT": "KILT", "Basilisk": "BSX", "Flare": "FLR", "Avalanche C-Chain": "AVAX", "Kintsugi": "KINT", "Altair": "AIR", "Moonbeam": "GLMR", "Acala": "ACA", "Astar": "ASTR", "Akash": "AKT", "Robonomics": "XRT", "Fantom": "FTM", "Elrond": "EGLD", "THORchain": "RUNE", "Secret": "SCRT", "Near": "NEAR", "Internet Computer Protocol": "ICP", "Picasso": "PICA", "Crust Shadow": "CSM", "Integritee": "TEER", "Parallel Finance": "PARA", "HydraDX": "HDX", "Interlay": "INTR", "Fetch.ai": "FET", "NYM": "NYM", "Terra 2.0": "LUNA2", "Juno": "JUNO", "Nodle": "NODL", "Stacks": "STX", "Ethereum PoW": "ETHW", "Aptos": "APT", "Sui": "SUI", "Genshiro": "GENS", "Aventus": "AVT", "Sei": "SEI", "OriginTrail": "OTP", "Celestia": "TIA", }, }, "features": map[string]interface{} { "spot": map[string]interface{} { "sandbox": false, "createOrder": map[string]interface{} { "marginMode": false, "triggerPrice": false, "triggerPriceType": nil, "triggerDirection": false, "stopLossPrice": true, "takeProfitPrice": true, "attachedStopLossTakeProfit": nil, "timeInForce": map[string]interface{} { "IOC": true, "FOK": true, "PO": true, "GTD": false, }, "hedged": false, "trailing": true, "leverage": false, "marketBuyByCost": true, "marketBuyRequiresPrice": false, "selfTradePrevention": true, "iceberg": true, }, "createOrders": nil, "fetchMyTrades": map[string]interface{} { "marginMode": false, "limit": nil, "daysBack": nil, "untilDays": nil, "symbolRequired": false, }, "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": map[string]interface{} { "marginMode": false, "limit": nil, "daysBack": nil, "daysBackCanceled": nil, "untilDays": 100000, "trigger": false, "trailing": false, "symbolRequired": false, }, "fetchOHLCV": map[string]interface{} { "limit": 720, }, }, "swap": map[string]interface{} { "linear": nil, "inverse": nil, }, "future": map[string]interface{} { "linear": nil, "inverse": nil, }, }, "precisionMode": TICK_SIZE, "exceptions": map[string]interface{} { "exact": map[string]interface{} { "EQuery:Invalid asset pair": BadSymbol, "EAPI:Invalid key": AuthenticationError, "EFunding:Unknown withdraw key": InvalidAddress, "EFunding:Invalid amount": InsufficientFunds, "EService:Unavailable": ExchangeNotAvailable, "EDatabase:Internal error": ExchangeNotAvailable, "EService:Busy": ExchangeNotAvailable, "EQuery:Unknown asset": BadSymbol, "EAPI:Rate limit exceeded": DDoSProtection, "EOrder:Rate limit exceeded": DDoSProtection, "EGeneral:Internal error": ExchangeNotAvailable, "EGeneral:Temporary lockout": DDoSProtection, "EGeneral:Permission denied": PermissionDenied, "EGeneral:Invalid arguments:price": InvalidOrder, "EOrder:Unknown order": InvalidOrder, "EOrder:Invalid price:Invalid price argument": InvalidOrder, "EOrder:Order minimum not met": InvalidOrder, "EOrder:Insufficient funds": InsufficientFunds, "EGeneral:Invalid arguments": BadRequest, "ESession:Invalid session": AuthenticationError, "EAPI:Invalid nonce": InvalidNonce, "EFunding:No funding method": BadRequest, "EFunding:Unknown asset": BadSymbol, "EService:Market in post_only mode": OnMaintenance, "EGeneral:Too many requests": DDoSProtection, "ETrade:User Locked": AccountSuspended, }, "broad": map[string]interface{} { ":Invalid order": InvalidOrder, ":Invalid arguments:volume": InvalidOrder, ":Invalid arguments:viqc": InvalidOrder, ":Invalid nonce": InvalidNonce, ":IInsufficient funds": InsufficientFunds, ":Cancel pending": CancelPending, ":Rate limit exceeded": RateLimitExceeded, }, }, }) } func (this *kraken) FeeToPrecision(symbol interface{}, fee interface{}) interface{} { return this.DecimalToPrecision(fee, TRUNCATE, GetValue(GetValue(GetValue(this.Markets, symbol), "precision"), "amount"), this.PrecisionMode) } /** * @method * @name kraken#fetchMarkets * @description retrieves data on all markets for kraken * @see https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getTradableAssetPairs * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ func (this *kraken) 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 if IsTrue(GetValue(this.Options, "adjustForTimeDifference")) { retRes55812 := (<-this.LoadTimeDifference()) PanicOnError(retRes55812) } response:= (<-this.PublicGetAssetPairs(params)) PanicOnError(response) // // { // "error": [], // "result": { // "ADAETH": { // "altname": "ADAETH", // "wsname": "ADA\/ETH", // "aclass_base": "currency", // "base": "ADA", // "aclass_quote": "currency", // "quote": "XETH", // "lot": "unit", // "pair_decimals": 7, // "lot_decimals": 8, // "lot_multiplier": 1, // "leverage_buy": [], // "leverage_sell": [], // "fees": [ // [0, 0.26], // [50000, 0.24], // [100000, 0.22], // [250000, 0.2], // [500000, 0.18], // [1000000, 0.16], // [2500000, 0.14], // [5000000, 0.12], // [10000000, 0.1] // ], // "fees_maker": [ // [0, 0.16], // [50000, 0.14], // [100000, 0.12], // [250000, 0.1], // [500000, 0.08], // [1000000, 0.06], // [2500000, 0.04], // [5000000, 0.02], // [10000000, 0] // ], // "fee_volume_currency": "ZUSD", // "margin_call": 80, // "margin_stop": 40, // "ordermin": "1" // }, // } // } // var markets interface{} = this.SafeValue(response, "result", map[string]interface{} {}) var keys interface{} = ObjectKeys(markets) var result interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(keys)); i++ { var id interface{} = GetValue(keys, i) var market interface{} = GetValue(markets, id) var baseId interface{} = this.SafeString(market, "base") var quoteId interface{} = this.SafeString(market, "quote") var base interface{} = this.SafeCurrencyCode(baseId) var quote interface{} = this.SafeCurrencyCode(quoteId) var darkpool interface{} = IsGreaterThanOrEqual(GetIndexOf(id, ".d"), 0) var altname interface{} = this.SafeString(market, "altname") var makerFees interface{} = this.SafeValue(market, "fees_maker", []interface{}{}) var firstMakerFee interface{} = this.SafeValue(makerFees, 0, []interface{}{}) var firstMakerFeeRate interface{} = this.SafeString(firstMakerFee, 1) var maker interface{} = nil if IsTrue(!IsEqual(firstMakerFeeRate, nil)) { maker = this.ParseNumber(Precise.StringDiv(firstMakerFeeRate, "100")) } var takerFees interface{} = this.SafeValue(market, "fees", []interface{}{}) var firstTakerFee interface{} = this.SafeValue(takerFees, 0, []interface{}{}) var firstTakerFeeRate interface{} = this.SafeString(firstTakerFee, 1) var taker interface{} = nil if IsTrue(!IsEqual(firstTakerFeeRate, nil)) { taker = this.ParseNumber(Precise.StringDiv(firstTakerFeeRate, "100")) } var leverageBuy interface{} = this.SafeValue(market, "leverage_buy", []interface{}{}) var leverageBuyLength interface{} = GetArrayLength(leverageBuy) var precisionPrice interface{} = this.ParseNumber(this.ParsePrecision(this.SafeString(market, "pair_decimals"))) var status interface{} = this.SafeString(market, "status") var isActive interface{} = IsEqual(status, "online") AppendToArray(&result,map[string]interface{} { "id": id, "wsId": this.SafeString(market, "wsname"), "symbol": Ternary(IsTrue(darkpool), altname, (Add(Add(base, "/"), quote))), "base": base, "quote": quote, "settle": nil, "baseId": baseId, "quoteId": quoteId, "settleId": nil, "darkpool": darkpool, "altname": GetValue(market, "altname"), "type": "spot", "spot": true, "margin": (IsGreaterThan(leverageBuyLength, 0)), "swap": false, "future": false, "option": false, "active": isActive, "contract": false, "linear": nil, "inverse": nil, "taker": taker, "maker": maker, "contractSize": nil, "expiry": nil, "expiryDatetime": nil, "strike": nil, "optionType": nil, "precision": map[string]interface{} { "amount": this.ParseNumber(this.ParsePrecision(this.SafeString(market, "lot_decimals"))), "price": precisionPrice, }, "limits": map[string]interface{} { "leverage": map[string]interface{} { "min": this.ParseNumber("1"), "max": this.SafeNumber(leverageBuy, Subtract(leverageBuyLength, 1), 1), }, "amount": map[string]interface{} { "min": this.SafeNumber(market, "ordermin"), "max": nil, }, "price": map[string]interface{} { "min": precisionPrice, "max": nil, }, "cost": map[string]interface{} { "min": this.SafeNumber(market, "costmin"), "max": nil, }, }, "created": nil, "info": market, }) } result = this.AppendInactiveMarkets(result) AddElementToObject(this.Options, "marketsByAltname", this.IndexBy(result, "altname")) ch <- result return nil }() return ch } func (this *kraken) SafeCurrency(currencyId interface{}, optionalArgs ...interface{}) interface{} { currency := GetArg(optionalArgs, 0, nil) _ = currency if IsTrue(!IsEqual(currencyId, nil)) { if IsTrue(IsGreaterThan(GetArrayLength(currencyId), 3)) { if IsTrue(IsTrue((IsEqual(GetIndexOf(currencyId, "X"), 0))) || IsTrue((IsEqual(GetIndexOf(currencyId, "Z"), 0)))) { if IsTrue(!IsTrue((IsGreaterThan(GetIndexOf(currencyId, "."), 0))) && IsTrue((!IsEqual(currencyId, "ZEUS")))) { currencyId = Slice(currencyId, 1, nil) } } } } return this.Exchange.SafeCurrency(currencyId, currency) } func (this *kraken) AppendInactiveMarkets(result interface{}) interface{} { // result should be an array to append to var precision interface{} = map[string]interface{} { "amount": this.ParseNumber("1e-8"), "price": this.ParseNumber("1e-8"), } var costLimits interface{} = map[string]interface{} { "min": nil, "max": nil, } var priceLimits interface{} = map[string]interface{} { "min": GetValue(precision, "price"), "max": nil, } var amountLimits interface{} = map[string]interface{} { "min": GetValue(precision, "amount"), "max": nil, } var limits interface{} = map[string]interface{} { "amount": amountLimits, "price": priceLimits, "cost": costLimits, } var defaults interface{} = map[string]interface{} { "darkpool": false, "info": nil, "maker": nil, "taker": nil, "active": false, "precision": precision, "limits": limits, } var markets interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(markets)); i++ { AppendToArray(&result,this.Extend(defaults, GetValue(markets, i))) } return result } /** * @method * @name kraken#fetchStatus * @description the latest known information on the availability of the exchange API * @see https://docs.kraken.com/api/docs/rest-api/get-system-status/ * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure} */ func (this *kraken) FetchStatus(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.PublicGetSystemStatus(params)) PanicOnError(response) // // { // error: [], // result: { status: 'online', timestamp: '2024-07-22T16:34:44Z' } // } // var result interface{} = this.SafeDict(response, "result") var statusRaw interface{} = this.SafeString(result, "status") ch <- map[string]interface{} { "status": Ternary(IsTrue((IsEqual(statusRaw, "online"))), "ok", "maintenance"), "updated": nil, "eta": nil, "url": nil, "info": response, } return nil }() return ch } /** * @method * @name kraken#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getAssetInfo * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ func (this *kraken) 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 response:= (<-this.PublicGetAssets(params)) PanicOnError(response) // // { // "error": [], // "result": { // "BCH": { // "aclass": "currency", // "altname": "BCH", // "decimals": 10, // "display_decimals": 5 // "status": "enabled", // }, // ... // }, // } // var currencies interface{} = this.SafeValue(response, "result", map[string]interface{} {}) var ids interface{} = ObjectKeys(currencies) var result interface{} = map[string]interface{} {} for i := 0; IsLessThan(i, GetArrayLength(ids)); i++ { var id interface{} = GetValue(ids, i) var currency interface{} = GetValue(currencies, id) // todo: will need to rethink the fees // see: https://support.kraken.com/hc/en-us/articles/201893608-What-are-the-withdrawal-fees- // to add support for multiple withdrawal/deposit methods and // differentiated fees for each particular method var code interface{} = this.SafeCurrencyCode(id) var precision interface{} = this.ParseNumber(this.ParsePrecision(this.SafeString(currency, "decimals"))) // assumes all currencies are active except those listed above var active interface{} = IsEqual(this.SafeString(currency, "status"), "enabled") AddElementToObject(result, code, map[string]interface{} { "id": id, "code": code, "info": currency, "name": this.SafeString(currency, "altname"), "active": active, "deposit": nil, "withdraw": nil, "fee": nil, "precision": precision, "limits": map[string]interface{} { "amount": map[string]interface{} { "min": precision, "max": nil, }, "withdraw": map[string]interface{} { "min": nil, "max": nil, }, }, "networks": map[string]interface{} {}, }) } ch <- result return nil }() return ch } /** * @method * @name kraken#fetchTradingFee * @description fetch the trading fees for a market * @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getTradeVolume * @param {string} symbol unified market symbol * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure} */ func (this *kraken) FetchTradingFee(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 retRes8428 := (<-this.LoadMarkets()) PanicOnError(retRes8428) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), "fee-info": true, } response:= (<-this.PrivatePostTradeVolume(this.Extend(request, params))) PanicOnError(response) // // { // "error": [], // "result": { // "currency": 'ZUSD', // "volume": '0.0000', // "fees": { // "XXBTZUSD": { // "fee": '0.2600', // "minfee": '0.1000', // "maxfee": '0.2600', // "nextfee": '0.2400', // "tiervolume": '0.0000', // "nextvolume": '50000.0000' // } // }, // "fees_maker": { // "XXBTZUSD": { // "fee": '0.1600', // "minfee": '0.0000', // "maxfee": '0.1600', // "nextfee": '0.1400', // "tiervolume": '0.0000', // "nextvolume": '50000.0000' // } // } // } // } // var result interface{} = this.SafeValue(response, "result", map[string]interface{} {}) ch <- this.ParseTradingFee(result, market) return nil }() return ch } func (this *kraken) ParseTradingFee(response interface{}, market interface{}) interface{} { var makerFees interface{} = this.SafeValue(response, "fees_maker", map[string]interface{} {}) var takerFees interface{} = this.SafeValue(response, "fees", map[string]interface{} {}) var symbolMakerFee interface{} = this.SafeValue(makerFees, GetValue(market, "id"), map[string]interface{} {}) var symbolTakerFee interface{} = this.SafeValue(takerFees, GetValue(market, "id"), map[string]interface{} {}) return map[string]interface{} { "info": response, "symbol": GetValue(market, "symbol"), "maker": this.ParseNumber(Precise.StringDiv(this.SafeString(symbolMakerFee, "fee"), "100")), "taker": this.ParseNumber(Precise.StringDiv(this.SafeString(symbolTakerFee, "fee"), "100")), "percentage": true, "tierBased": true, } } func (this *kraken) ParseBidAsk(bidask interface{}, optionalArgs ...interface{}) interface{} { priceKey := GetArg(optionalArgs, 0, 0) _ = priceKey amountKey := GetArg(optionalArgs, 1, 1) _ = amountKey countOrIdKey := GetArg(optionalArgs, 2, 2) _ = countOrIdKey var price interface{} = this.SafeNumber(bidask, priceKey) var amount interface{} = this.SafeNumber(bidask, amountKey) var timestamp interface{} = this.SafeInteger(bidask, 2) return []interface{}{price, amount, timestamp} } /** * @method * @name kraken#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getOrderBook * @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 *kraken) 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 retRes9158 := (<-this.LoadMarkets()) PanicOnError(retRes9158) var market interface{} = this.Market(symbol) if IsTrue(GetValue(market, "darkpool")) { panic(ExchangeError(Add(Add(this.Id, " fetchOrderBook() does not provide an order book for darkpool symbol "), symbol))) } var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "count", limit) // 100 } response:= (<-this.PublicGetDepth(this.Extend(request, params))) PanicOnError(response) // // { // "error":[], // "result":{ // "XETHXXBT":{ // "asks":[ // ["0.023480","4.000",1586321307], // ["0.023490","50.095",1586321306], // ["0.023500","28.535",1586321302], // ], // "bids":[ // ["0.023470","59.580",1586321307], // ["0.023460","20.000",1586321301], // ["0.023440","67.832",1586321306], // ] // } // } // } // var result interface{} = this.SafeValue(response, "result", map[string]interface{} {}) var orderbook interface{} = this.SafeValue(result, GetValue(market, "id")) // sometimes kraken returns wsname instead of market id // https://github.com/ccxt/ccxt/issues/8662 var marketInfo interface{} = this.SafeValue(market, "info", map[string]interface{} {}) var wsName interface{} = this.SafeValue(marketInfo, "wsname") if IsTrue(!IsEqual(wsName, nil)) { orderbook = this.SafeValue(result, wsName, orderbook) } ch <- this.ParseOrderBook(orderbook, symbol) return nil }() return ch } func (this *kraken) ParseTicker(ticker interface{}, optionalArgs ...interface{}) interface{} { // // { // "a":["2432.77000","1","1.000"], // "b":["2431.37000","2","2.000"], // "c":["2430.58000","0.04408910"], // "v":["4147.94474901","8896.96086304"], // "p":["2456.22239","2568.63032"], // "t":[3907,10056], // "l":["2302.18000","2302.18000"], // "h":["2621.14000","2860.01000"], // "o":"2571.56000" // } // market := GetArg(optionalArgs, 0, nil) _ = market var symbol interface{} = this.SafeSymbol(nil, market) var v interface{} = this.SafeValue(ticker, "v", []interface{}{}) var baseVolume interface{} = this.SafeString(v, 1) var p interface{} = this.SafeValue(ticker, "p", []interface{}{}) var vwap interface{} = this.SafeString(p, 1) var quoteVolume interface{} = Precise.StringMul(baseVolume, vwap) var c interface{} = this.SafeValue(ticker, "c", []interface{}{}) var last interface{} = this.SafeString(c, 0) var high interface{} = this.SafeValue(ticker, "h", []interface{}{}) var low interface{} = this.SafeValue(ticker, "l", []interface{}{}) var bid interface{} = this.SafeValue(ticker, "b", []interface{}{}) var ask interface{} = this.SafeValue(ticker, "a", []interface{}{}) return this.SafeTicker(map[string]interface{} { "symbol": symbol, "timestamp": nil, "datetime": nil, "high": this.SafeString(high, 1), "low": this.SafeString(low, 1), "bid": this.SafeString(bid, 0), "bidVolume": this.SafeString(bid, 2), "ask": this.SafeString(ask, 0), "askVolume": this.SafeString(ask, 2), "vwap": vwap, "open": this.SafeString(ticker, "o"), "close": last, "last": last, "previousClose": nil, "change": nil, "percentage": nil, "average": nil, "baseVolume": baseVolume, "quoteVolume": quoteVolume, "info": ticker, }, market) } /** * @method * @name kraken#fetchTickers * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market * @see https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getTickerInformation * @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 *kraken) 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 retRes10188 := (<-this.LoadMarkets()) PanicOnError(retRes10188) var request interface{} = map[string]interface{} {} if IsTrue(!IsEqual(symbols, nil)) { symbols = this.MarketSymbols(symbols) var marketIds interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(symbols)); i++ { var symbol interface{} = GetValue(symbols, i) var market interface{} = GetValue(this.Markets, symbol) if IsTrue(IsTrue(GetValue(market, "active")) && !IsTrue(GetValue(market, "darkpool"))) { AppendToArray(&marketIds,GetValue(market, "id")) } } AddElementToObject(request, "pair", Join(marketIds, ",")) } response:= (<-this.PublicGetTicker(this.Extend(request, params))) PanicOnError(response) var tickers interface{} = GetValue(response, "result") var ids interface{} = ObjectKeys(tickers) var result interface{} = map[string]interface{} {} for i := 0; IsLessThan(i, GetArrayLength(ids)); i++ { var id interface{} = GetValue(ids, i) var market interface{} = this.SafeMarket(id) var symbol interface{} = GetValue(market, "symbol") var ticker interface{} = GetValue(tickers, id) AddElementToObject(result, symbol, this.ParseTicker(ticker, market)) } ch <- this.FilterByArrayTickers(result, "symbol", symbols) return nil }() return ch } /** * @method * @name kraken#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getTickerInformation * @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 *kraken) 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 retRes10568 := (<-this.LoadMarkets()) PanicOnError(retRes10568) var darkpool interface{} = IsGreaterThanOrEqual(GetIndexOf(symbol, ".d"), 0) if IsTrue(darkpool) { panic(ExchangeError(Add(Add(this.Id, " fetchTicker() does not provide a ticker for darkpool symbol "), symbol))) } var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), } response:= (<-this.PublicGetTicker(this.Extend(request, params))) PanicOnError(response) var ticker interface{} = GetValue(GetValue(response, "result"), GetValue(market, "id")) ch <- this.ParseTicker(ticker, market) return nil }() return ch } func (this *kraken) ParseOHLCV(ohlcv interface{}, optionalArgs ...interface{}) interface{} { // // [ // 1591475640, // "0.02500", // "0.02500", // "0.02500", // "0.02500", // "0.02500", // "9.12201000", // 5 // ] // market := GetArg(optionalArgs, 0, nil) _ = market return []interface{}{this.SafeTimestamp(ohlcv, 0), this.SafeNumber(ohlcv, 1), this.SafeNumber(ohlcv, 2), this.SafeNumber(ohlcv, 3), this.SafeNumber(ohlcv, 4), this.SafeNumber(ohlcv, 6)} } /** * @method * @name kraken#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @see https://docs.kraken.com/api/docs/rest-api/get-ohlc-data * @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 {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params) * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume */ func (this *kraken) 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 retRes11078 := (<-this.LoadMarkets()) PanicOnError(retRes11078) var paginate interface{} = false paginateparamsVariable := this.HandleOptionAndParams(params, "fetchOHLCV", "paginate"); paginate = GetValue(paginateparamsVariable,0); params = GetValue(paginateparamsVariable,1) if IsTrue(paginate) { retRes111119 := (<-this.FetchPaginatedCallDeterministic("fetchOHLCV", symbol, since, limit, timeframe, params, 720)) PanicOnError(retRes111119) ch <- retRes111119 return nil } var market interface{} = this.Market(symbol) var parsedTimeframe interface{} = this.SafeInteger(this.Timeframes, timeframe) var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), } if IsTrue(!IsEqual(parsedTimeframe, nil)) { AddElementToObject(request, "interval", parsedTimeframe) } else { AddElementToObject(request, "interval", timeframe) } if IsTrue(!IsEqual(since, nil)) { var scaledSince interface{} = this.ParseToInt(Divide(since, 1000)) var timeFrameInSeconds interface{} = Multiply(parsedTimeframe, 60) AddElementToObject(request, "since", this.NumberToString(Subtract(scaledSince, timeFrameInSeconds))) // expected to be in seconds } response:= (<-this.PublicGetOHLC(this.Extend(request, params))) PanicOnError(response) // // { // "error":[], // "result":{ // "XETHXXBT":[ // [1591475580,"0.02499","0.02499","0.02499","0.02499","0.00000","0.00000000",0], // [1591475640,"0.02500","0.02500","0.02500","0.02500","0.02500","9.12201000",5], // [1591475700,"0.02499","0.02499","0.02499","0.02499","0.02499","1.28681415",2], // [1591475760,"0.02499","0.02499","0.02499","0.02499","0.02499","0.08800000",1], // ], // "last":1591517580 // } // } var result interface{} = this.SafeValue(response, "result", map[string]interface{} {}) var ohlcvs interface{} = this.SafeList(result, GetValue(market, "id"), []interface{}{}) ch <- this.ParseOHLCVs(ohlcvs, market, timeframe, since, limit) return nil }() return ch } func (this *kraken) ParseLedgerEntryType(typeVar interface{}) interface{} { var types interface{} = map[string]interface{} { "trade": "trade", "withdrawal": "transaction", "deposit": "transaction", "transfer": "transfer", "margin": "margin", } return this.SafeString(types, typeVar, typeVar) } func (this *kraken) ParseLedgerEntry(item interface{}, optionalArgs ...interface{}) interface{} { // // { // 'LTFK7F-N2CUX-PNY4SX': { // "refid": "TSJTGT-DT7WN-GPPQMJ", // "time": 1520102320.555, // "type": "trade", // "aclass": "currency", // "asset": "XETH", // "amount": "0.1087194600", // "fee": "0.0000000000", // "balance": "0.2855851000" // }, // ... // } // currency := GetArg(optionalArgs, 0, nil) _ = currency var id interface{} = this.SafeString(item, "id") var direction interface{} = nil var account interface{} = nil var referenceId interface{} = this.SafeString(item, "refid") var referenceAccount interface{} = nil var typeVar interface{} = this.ParseLedgerEntryType(this.SafeString(item, "type")) var currencyId interface{} = this.SafeString(item, "asset") var code interface{} = this.SafeCurrencyCode(currencyId, currency) currency = this.SafeCurrency(currencyId, currency) var amount interface{} = this.SafeString(item, "amount") if IsTrue(Precise.StringLt(amount, "0")) { direction = "out" amount = Precise.StringAbs(amount) } else { direction = "in" } var timestamp interface{} = this.SafeIntegerProduct(item, "time", 1000) return this.SafeLedgerEntry(map[string]interface{} { "info": item, "id": id, "direction": direction, "account": account, "referenceId": referenceId, "referenceAccount": referenceAccount, "type": typeVar, "currency": code, "amount": this.ParseNumber(amount), "before": nil, "after": this.SafeNumber(item, "balance"), "status": "ok", "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "fee": map[string]interface{} { "cost": this.SafeNumber(item, "fee"), "currency": code, }, }, currency) } /** * @method * @name kraken#fetchLedger * @description fetch the history of changes, actions done by the user or operations that altered the balance of the user * @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getLedgers * @param {string} [code] unified currency code, default is undefined * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined * @param {int} [limit] max number of ledger entries to return, default is undefined * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {int} [params.until] timestamp in ms of the latest ledger entry * @param {int} [params.end] timestamp in seconds of the latest ledger entry * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger} */ func (this *kraken) FetchLedger(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) // https://www.kraken.com/features/api#get-ledgers-info 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 retRes12288 := (<-this.LoadMarkets()) PanicOnError(retRes12288) var request interface{} = map[string]interface{} {} var currency interface{} = nil if IsTrue(!IsEqual(code, nil)) { currency = this.Currency(code) AddElementToObject(request, "asset", GetValue(currency, "id")) } if IsTrue(!IsEqual(since, nil)) { AddElementToObject(request, "start", this.ParseToInt(Divide(since, 1000))) } var until interface{} = this.SafeStringN(params, []interface{}{"until", "till"}) if IsTrue(!IsEqual(until, nil)) { params = this.Omit(params, []interface{}{"until", "till"}) var untilDivided interface{} = Precise.StringDiv(until, "1000") AddElementToObject(request, "end", this.ParseToInt(Precise.StringAdd(untilDivided, "1"))) } response:= (<-this.PrivatePostLedgers(this.Extend(request, params))) PanicOnError(response) // { error: [], // "result": { ledger: { 'LPUAIB-TS774-UKHP7X': { refid: "A2B4HBV-L4MDIE-JU4N3N", // "time": 1520103488.314, // "type": "withdrawal", // "aclass": "currency", // "asset": "XETH", // "amount": "-0.2805800000", // "fee": "0.0050000000", // "balance": "0.0000051000" }, var result interface{} = this.SafeValue(response, "result", map[string]interface{} {}) var ledger interface{} = this.SafeValue(result, "ledger", map[string]interface{} {}) var keys interface{} = ObjectKeys(ledger) var items interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(keys)); i++ { var key interface{} = GetValue(keys, i) var value interface{} = GetValue(ledger, key) AddElementToObject(value, "id", key) AppendToArray(&items,value) } ch <- this.ParseLedger(items, currency, since, limit) return nil }() return ch } func (this *kraken) FetchLedgerEntriesByIds(ids interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) // https://www.kraken.com/features/api#query-ledgers code := GetArg(optionalArgs, 0, nil) _ = code params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params retRes12698 := (<-this.LoadMarkets()) PanicOnError(retRes12698) ids = Join(ids, ",") var request interface{} = this.Extend(map[string]interface{} { "id": ids, }, params) response:= (<-this.PrivatePostQueryLedgers(request)) PanicOnError(response) // { error: [], // "result": { 'LPUAIB-TS774-UKHP7X': { refid: "A2B4HBV-L4MDIE-JU4N3N", // "time": 1520103488.314, // "type": "withdrawal", // "aclass": "currency", // "asset": "XETH", // "amount": "-0.2805800000", // "fee": "0.0050000000", // "balance": "0.0000051000" } } } var result interface{} = GetValue(response, "result") var keys interface{} = ObjectKeys(result) var items interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(keys)); i++ { var key interface{} = GetValue(keys, i) var value interface{} = GetValue(result, key) AddElementToObject(value, "id", key) AppendToArray(&items,value) } ch <- this.ParseLedger(items) return nil }() return ch } func (this *kraken) FetchLedgerEntry(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 items:= (<-this.FetchLedgerEntriesByIds([]interface{}{id}, code, params)) PanicOnError(items) ch <- GetValue(items, 0) return nil }() return ch } func (this *kraken) ParseTrade(trade interface{}, optionalArgs ...interface{}) interface{} { // // fetchTrades (public) // // [ // "0.032310", // price // "4.28169434", // amount // 1541390792.763, // timestamp // "s", // sell or buy // "l", // limit or market // "" // ] // // fetchOrderTrades (private) // // { // "id": 'TIMIRG-WUNNE-RRJ6GT', // injected from outside // "ordertxid": 'OQRPN2-LRHFY-HIFA7D', // "postxid": 'TKH2SE-M7IF5-CFI7LT', // "pair": 'USDCUSDT', // "time": 1586340086.457, // "type": 'sell', // "ordertype": 'market', // "price": '0.99860000', // "cost": '22.16892001', // "fee": '0.04433784', // "vol": '22.20000000', // "margin": '0.00000000', // "misc": '' // } // // fetchMyTrades // // { // "ordertxid": "OSJVN7-A2AE-63WZV", // "postxid": "TBP7O6-PNXI-CONU", // "pair": "XXBTZUSD", // "time": 1710429248.3052235, // "type": "sell", // "ordertype": "liquidation market", // "price": "72026.50000", // "cost": "7.20265", // "fee": "0.01873", // "vol": "0.00010000", // "margin": "1.44053", // "leverage": "5", // "misc": "closing", // "trade_id": 68230622, // "maker": false // } // market := GetArg(optionalArgs, 0, nil) _ = market var timestamp interface{} = nil var side interface{} = nil var typeVar interface{} = nil var price interface{} = nil var amount interface{} = nil var id interface{} = nil var orderId interface{} = nil var fee interface{} = nil var symbol interface{} = nil if IsTrue(IsArray(trade)) { timestamp = this.SafeTimestamp(trade, 2) side = Ternary(IsTrue((IsEqual(GetValue(trade, 3), "s"))), "sell", "buy") typeVar = Ternary(IsTrue((IsEqual(GetValue(trade, 4), "l"))), "limit", "market") price = this.SafeString(trade, 0) amount = this.SafeString(trade, 1) var tradeLength interface{} = GetArrayLength(trade) if IsTrue(IsGreaterThan(tradeLength, 6)) { id = this.SafeString(trade, 6) // artificially added as per #1794 } } else if IsTrue(IsString(trade)) { id = trade } else if IsTrue(InOp(trade, "ordertxid")) { var marketId interface{} = this.SafeString(trade, "pair") var foundMarket interface{} = this.FindMarketByAltnameOrId(marketId) if IsTrue(!IsEqual(foundMarket, nil)) { market = foundMarket } else if IsTrue(!IsEqual(marketId, nil)) { // delisted market ids go here market = this.GetDelistedMarketById(marketId) } orderId = this.SafeString(trade, "ordertxid") id = this.SafeString2(trade, "id", "postxid") timestamp = this.SafeTimestamp(trade, "time") side = this.SafeString(trade, "type") typeVar = this.SafeString(trade, "ordertype") price = this.SafeString(trade, "price") amount = this.SafeString(trade, "vol") if IsTrue(InOp(trade, "fee")) { var currency interface{} = nil if IsTrue(!IsEqual(market, nil)) { currency = GetValue(market, "quote") } fee = map[string]interface{} { "cost": this.SafeString(trade, "fee"), "currency": currency, } } } if IsTrue(!IsEqual(market, nil)) { symbol = GetValue(market, "symbol") } var cost interface{} = this.SafeString(trade, "cost") var maker interface{} = this.SafeBool(trade, "maker") var takerOrMaker interface{} = nil if IsTrue(!IsEqual(maker, nil)) { takerOrMaker = Ternary(IsTrue(maker), "maker", "taker") } return this.SafeTrade(map[string]interface{} { "id": id, "order": orderId, "info": trade, "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "symbol": symbol, "type": typeVar, "side": side, "takerOrMaker": takerOrMaker, "price": price, "amount": amount, "cost": cost, "fee": fee, }, market) } /** * @method * @name kraken#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getRecentTrades * @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 *kraken) 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 retRes14388 := (<-this.LoadMarkets()) PanicOnError(retRes14388) var market interface{} = this.Market(symbol) var id interface{} = GetValue(market, "id") var request interface{} = map[string]interface{} { "pair": id, } // https://support.kraken.com/hc/en-us/articles/218198197-How-to-pull-all-trade-data-using-the-Kraken-REST-API // https://github.com/ccxt/ccxt/issues/5677 if IsTrue(!IsEqual(since, nil)) { AddElementToObject(request, "since", this.NumberToString(this.ParseToInt(Divide(since, 1000)))) // expected to be in seconds } if IsTrue(!IsEqual(limit, nil)) { AddElementToObject(request, "count", limit) } response:= (<-this.PublicGetTrades(this.Extend(request, params))) PanicOnError(response) // // { // "error": [], // "result": { // "XETHXXBT": [ // ["0.032310","4.28169434",1541390792.763,"s","l",""] // ], // "last": "1541439421200678657" // } // } // var result interface{} = GetValue(response, "result") var trades interface{} = GetValue(result, id) // trades is a sorted array: last (most recent trade) goes last var length interface{} = GetArrayLength(trades) if IsTrue(IsLessThanOrEqual(length, 0)) { ch <- []interface{}{} return nil } var lastTrade interface{} = GetValue(trades, Subtract(length, 1)) var lastTradeId interface{} = this.SafeString(result, "last") AppendToArray(&lastTrade,lastTradeId) AddElementToObject(trades, Subtract(length, 1), lastTrade) ch <- this.ParseTrades(trades, market, since, limit) return nil }() return ch } func (this *kraken) ParseBalance(response interface{}) interface{} { var balances interface{} = this.SafeValue(response, "result", map[string]interface{} {}) var result interface{} = map[string]interface{} { "info": response, "timestamp": nil, "datetime": nil, } var currencyIds interface{} = ObjectKeys(balances) for i := 0; IsLessThan(i, GetArrayLength(currencyIds)); i++ { var currencyId interface{} = GetValue(currencyIds, i) var code interface{} = this.SafeCurrencyCode(currencyId) var balance interface{} = this.SafeValue(balances, currencyId, map[string]interface{} {}) var account interface{} = this.Account() AddElementToObject(account, "used", this.SafeString(balance, "hold_trade")) AddElementToObject(account, "total", this.SafeString(balance, "balance")) AddElementToObject(result, code, account) } return this.SafeBalance(result) } /** * @method * @name kraken#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getExtendedBalance * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure} */ func (this *kraken) 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 retRes15078 := (<-this.LoadMarkets()) PanicOnError(retRes15078) response:= (<-this.PrivatePostBalanceEx(params)) PanicOnError(response) // // { // "error": [], // "result": { // "ZUSD": { // "balance": 25435.21, // "hold_trade": 8249.76 // }, // "XXBT": { // "balance": 1.2435, // "hold_trade": 0.8423 // } // } // } // ch <- this.ParseBalance(response) return nil }() return ch } /** * @method * @name kraken#createMarketOrderWithCost * @description create a market order by providing the symbol, side and cost * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/addOrder * @param {string} symbol unified symbol of the market to create an order in (only USD markets are supported) * @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 *kraken) 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 retRes15398 := (<-this.LoadMarkets()) PanicOnError(retRes15398) // only buy orders are supported by the endpoint AddElementToObject(params, "cost", cost) retRes154215 := (<-this.CreateOrder(symbol, "market", side, cost, nil, params)) PanicOnError(retRes154215) ch <- retRes154215 return nil }() return ch } /** * @method * @name kraken#createMarketBuyOrderWithCost * @description create a market buy order by providing the symbol, side and cost * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/addOrder * @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 *kraken) 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 retRes15568 := (<-this.LoadMarkets()) PanicOnError(retRes15568) retRes155715 := (<-this.CreateMarketOrderWithCost(symbol, "buy", cost, params)) PanicOnError(retRes155715) ch <- retRes155715 return nil }() return ch } /** * @method * @name kraken#createOrder * @description create a trade order * @see https://docs.kraken.com/api/docs/rest-api/add-order * @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 {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately * @param {bool} [params.reduceOnly] *margin only* indicates if this order is to reduce the size of a position * @param {float} [params.stopLossPrice] *margin only* the price that a stop loss order is triggered at * @param {float} [params.takeProfitPrice] *margin only* the price that a take profit order is triggered at * @param {string} [params.trailingAmount] *margin only* the quote amount to trail away from the current market price * @param {string} [params.trailingPercent] *margin only* the percent to trail away from the current market price * @param {string} [params.trailingLimitAmount] *margin only* the quote amount away from the trailingAmount * @param {string} [params.trailingLimitPercent] *margin only* the percent away from the trailingAmount * @param {string} [params.offset] *margin only* '+' or '-' whether you want the trailingLimitAmount value to be positive or negative, default is negative '-' * @param {string} [params.trigger] *margin only* the activation price type, 'last' or 'index', default is 'last' * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) 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 retRes15848 := (<-this.LoadMarkets()) PanicOnError(retRes15848) var market interface{} = this.Market(symbol) var request interface{} = map[string]interface{} { "pair": GetValue(market, "id"), "type": side, "ordertype": typeVar, "volume": this.AmountToPrecision(symbol, amount), } var orderRequest interface{} = this.OrderRequest("createOrder", symbol, typeVar, request, amount, price, params) response:= (<-this.PrivatePostAddOrder(this.Extend(GetValue(orderRequest, 0), GetValue(orderRequest, 1)))) PanicOnError(response) // // { // "error": [], // "result": { // "descr": { order: 'buy 0.02100000 ETHUSDT @ limit 330.00' }, // see more examples in "parseOrder" // "txid": [ 'OEKVV2-IH52O-TPL6GZ' ] // } // } // var result interface{} = this.SafeDict(response, "result") ch <- this.ParseOrder(result) return nil }() return ch } func (this *kraken) FindMarketByAltnameOrId(id interface{}) interface{} { var marketsByAltname interface{} = this.SafeValue(this.Options, "marketsByAltname", map[string]interface{} {}) if IsTrue(InOp(marketsByAltname, id)) { return GetValue(marketsByAltname, id) } else { return this.SafeMarket(id) } } func (this *kraken) GetDelistedMarketById(id interface{}) interface{} { if IsTrue(IsEqual(id, nil)) { return id } var market interface{} = this.SafeValue(GetValue(this.Options, "delistedMarketsById"), id) if IsTrue(!IsEqual(market, nil)) { return market } var baseIdStart interface{} = 0 var baseIdEnd interface{} = 3 var quoteIdStart interface{} = 3 var quoteIdEnd interface{} = 6 if IsTrue(IsEqual(GetArrayLength(id), 8)) { baseIdEnd = 4 quoteIdStart = 4 quoteIdEnd = 8 } else if IsTrue(IsEqual(GetArrayLength(id), 7)) { baseIdEnd = 4 quoteIdStart = 4 quoteIdEnd = 7 } var baseId interface{} = Slice(id, baseIdStart, baseIdEnd) var quoteId interface{} = Slice(id, quoteIdStart, quoteIdEnd) var base interface{} = this.SafeCurrencyCode(baseId) var quote interface{} = this.SafeCurrencyCode(quoteId) var symbol interface{} = Add(Add(base, "/"), quote) market = map[string]interface{} { "symbol": symbol, "base": base, "quote": quote, "baseId": baseId, "quoteId": quoteId, } AddElementToObject(GetValue(this.Options, "delistedMarketsById"), id, market) return market } func (this *kraken) ParseOrderStatus(status interface{}) interface{} { var statuses interface{} = map[string]interface{} { "pending": "open", "open": "open", "closed": "closed", "canceled": "canceled", "expired": "expired", } return this.SafeString(statuses, status, status) } func (this *kraken) ParseOrderType(status interface{}) interface{} { var statuses interface{} = map[string]interface{} { "take-profit": "market", "stop-loss": "market", "stop-loss-limit": "limit", "take-profit-limit": "limit", "trailing-stop-limit": "limit", } return this.SafeString(statuses, status, status) } func (this *kraken) ParseOrder(order interface{}, optionalArgs ...interface{}) interface{} { // // createOrder // // { // "descr": { // "order": "buy 0.02100000 ETHUSDT @ limit 330.00" // limit orders // "buy 0.12345678 ETHUSDT @ market" // market order // "sell 0.28002676 ETHUSDT @ stop loss 0.0123 -> limit 0.0.1222" // stop order // "sell 0.00100000 ETHUSDT @ stop loss 2677.00 -> limit 2577.00 with 5:1 leverage" // "buy 0.10000000 LTCUSDT @ take profit 75.00000 -> limit 74.00000" // "sell 10.00000000 XRPEUR @ trailing stop +50.0000%" // trailing stop // }, // "txid": [ 'OEKVV2-IH52O-TPL6GZ' ] // } // // editOrder // // { // "amend_id": "TJSMEH-AA67V-YUSQ6O" // } // // ws - createOrder // { // "descr": 'sell 0.00010000 XBTUSDT @ market', // "event": 'addOrderStatus', // "reqid": 1, // "status": 'ok', // "txid": 'OAVXZH-XIE54-JCYYDG' // } // ws - editOrder // { // "descr": "order edited price = 9000.00000000", // "event": "editOrderStatus", // "originaltxid": "O65KZW-J4AW3-VFS74A", // "reqid": 3, // "status": "ok", // "txid": "OTI672-HJFAO-XOIPPK" // } // // { // "error": [], // "result": { // "open": { // "OXVPSU-Q726F-L3SDEP": { // "refid": null, // "userref": 0, // "status": "open", // "opentm": 1706893367.4656649, // "starttm": 0, // "expiretm": 0, // "descr": { // "pair": "XRPEUR", // "type": "sell", // "ordertype": "trailing-stop", // "price": "+50.0000%", // "price2": "0", // "leverage": "none", // "order": "sell 10.00000000 XRPEUR @ trailing stop +50.0000%", // "close": "" // }, // "vol": "10.00000000", // "vol_exec": "0.00000000", // "cost": "0.00000000", // "fee": "0.00000000", // "price": "0.00000000", // "stopprice": "0.23424000", // "limitprice": "0.46847000", // "misc": "", // "oflags": "fciq", // "trigger": "index" // } // } // } // // fetchOpenOrders // // { // "refid": null, // "userref": null, // "cl_ord_id": "1234", // "status": "open", // "opentm": 1733815269.370054, // "starttm": 0, // "expiretm": 0, // "descr": { // "pair": "XBTUSD", // "type": "buy", // "ordertype": "limit", // "price": "70000.0", // "price2": "0", // "leverage": "none", // "order": "buy 0.00010000 XBTUSD @ limit 70000.0", // "close": "" // }, // "vol": "0.00010000", // "vol_exec": "0.00000000", // "cost": "0.00000", // "fee": "0.00000", // "price": "0.00000", // "stopprice": "0.00000", // "limitprice": "0.00000", // "misc": "", // "oflags": "fciq" // } // market := GetArg(optionalArgs, 0, nil) _ = market var description interface{} = this.SafeDict(order, "descr", map[string]interface{} {}) var orderDescriptionObj interface{} = this.SafeDict(order, "descr") // can be null var orderDescription interface{} = nil if IsTrue(!IsEqual(orderDescriptionObj, nil)) { orderDescription = this.SafeString(orderDescriptionObj, "order") } else { orderDescription = this.SafeString(order, "descr") } var side interface{} = nil var rawType interface{} = nil var marketId interface{} = nil var price interface{} = nil var amount interface{} = nil var triggerPrice interface{} = nil if IsTrue(!IsEqual(orderDescription, nil)) { var parts interface{} = Split(orderDescription, " ") side = this.SafeString(parts, 0) amount = this.SafeString(parts, 1) marketId = this.SafeString(parts, 2) var part4 interface{} = this.SafeString(parts, 4) var part5 interface{} = this.SafeString(parts, 5) if IsTrue(IsTrue(IsEqual(part4, "limit")) || IsTrue(IsEqual(part4, "market"))) { rawType = part4 // eg, limit, market } else { rawType = Add(Add(part4, " "), part5) // eg. stop loss, take profit, trailing stop } if IsTrue(IsTrue(IsEqual(rawType, "stop loss")) || IsTrue(IsEqual(rawType, "take profit"))) { triggerPrice = this.SafeString(parts, 6) price = this.SafeString(parts, 9) } else if IsTrue(IsEqual(rawType, "limit")) { price = this.SafeString(parts, 5) } } side = this.SafeString(description, "type", side) rawType = this.SafeString(description, "ordertype", rawType) // orderType has dash, e.g. trailing-stop marketId = this.SafeString(description, "pair", marketId) var foundMarket interface{} = this.FindMarketByAltnameOrId(marketId) var symbol interface{} = nil if IsTrue(!IsEqual(foundMarket, nil)) { market = foundMarket } else if IsTrue(!IsEqual(marketId, nil)) { // delisted market ids go here market = this.GetDelistedMarketById(marketId) } var timestamp interface{} = this.SafeTimestamp(order, "opentm") amount = this.SafeString(order, "vol", amount) var filled interface{} = this.SafeString(order, "vol_exec") var fee interface{} = nil // kraken truncates the cost in the api response so we will ignore it and calculate it from average & filled // const cost = this.safeString (order, 'cost'); price = this.SafeString(description, "price", price) // when type = trailling stop returns price = '+50.0000%' if IsTrue(IsTrue((!IsEqual(price, nil))) && IsTrue(EndsWith(price, "%"))) { price = nil // this is not the price we want } if IsTrue(IsTrue((IsEqual(price, nil))) || IsTrue(Precise.StringEquals(price, "0"))) { price = this.SafeString(description, "price2") } if IsTrue(IsTrue((IsEqual(price, nil))) || IsTrue(Precise.StringEquals(price, "0"))) { price = this.SafeString(order, "price", price) } var flags interface{} = this.SafeString(order, "oflags", "") var isPostOnly interface{} = IsGreaterThan(GetIndexOf(flags, "post"), OpNeg(1)) var average interface{} = this.SafeNumber(order, "price") if IsTrue(!IsEqual(market, nil)) { symbol = GetValue(market, "symbol") if IsTrue(InOp(order, "fee")) { var feeCost interface{} = this.SafeString(order, "fee") fee = map[string]interface{} { "cost": feeCost, "rate": nil, } if IsTrue(IsGreaterThanOrEqual(GetIndexOf(flags, "fciq"), 0)) { AddElementToObject(fee, "currency", GetValue(market, "quote")) } else if IsTrue(IsGreaterThanOrEqual(GetIndexOf(flags, "fcib"), 0)) { AddElementToObject(fee, "currency", GetValue(market, "base")) } } } var status interface{} = this.ParseOrderStatus(this.SafeString(order, "status")) var id interface{} = this.SafeStringN(order, []interface{}{"id", "txid", "amend_id"}) if IsTrue(IsTrue((IsEqual(id, nil))) || IsTrue((StartsWith(id, "[")))) { var txid interface{} = this.SafeList(order, "txid") id = this.SafeString(txid, 0) } var userref interface{} = this.SafeString(order, "userref") var clientOrderId interface{} = this.SafeString(order, "cl_ord_id", userref) var rawTrades interface{} = this.SafeValue(order, "trades", []interface{}{}) var trades interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(rawTrades)); i++ { var rawTrade interface{} = GetValue(rawTrades, i) if IsTrue(IsString(rawTrade)) { AppendToArray(&trades,this.SafeTrade(map[string]interface{} { "id": rawTrade, "orderId": id, "symbol": symbol, "info": map[string]interface{} {}, })) } else { AppendToArray(&trades,rawTrade) } } // as mentioned in #24192 PR, this field is not something consistent/actual // triggerPrice = this.omitZero (this.safeString (order, 'stopprice', triggerPrice)); var stopLossPrice interface{} = nil var takeProfitPrice interface{} = nil // the dashed strings are not provided from fields (eg. fetch order) // while spaced strings from "order" sentence (when other fields not available) if IsTrue(!IsEqual(rawType, nil)) { if IsTrue(StartsWith(rawType, "take-profit")) { takeProfitPrice = this.SafeString(description, "price") price = this.OmitZero(this.SafeString(description, "price2")) } else if IsTrue(StartsWith(rawType, "stop-loss")) { stopLossPrice = this.SafeString(description, "price") price = this.OmitZero(this.SafeString(description, "price2")) } else if IsTrue(IsEqual(rawType, "take profit")) { takeProfitPrice = triggerPrice } else if IsTrue(IsEqual(rawType, "stop loss")) { stopLossPrice = triggerPrice } } var finalType interface{} = this.ParseOrderType(rawType) // unlike from endpoints which provide eg: "take-profit-limit" // for "space-delimited" orders we dont have market/limit suffixes, their format is // eg: `stop loss > limit 123`, so we need to parse them manually if IsTrue(this.InArray(finalType, []interface{}{"stop loss", "take profit"})) { finalType = Ternary(IsTrue((IsEqual(price, nil))), "market", "limit") } var amendId interface{} = this.SafeString(order, "amend_id") if IsTrue(!IsEqual(amendId, nil)) { isPostOnly = nil } return this.SafeOrder(map[string]interface{} { "id": id, "clientOrderId": clientOrderId, "info": order, "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "lastTradeTimestamp": nil, "status": status, "symbol": symbol, "type": finalType, "timeInForce": nil, "postOnly": isPostOnly, "side": side, "price": price, "triggerPrice": triggerPrice, "takeProfitPrice": takeProfitPrice, "stopLossPrice": stopLossPrice, "cost": nil, "amount": amount, "filled": filled, "average": average, "remaining": nil, "reduceOnly": this.SafeBool2(order, "reduceOnly", "reduce_only"), "fee": fee, "trades": trades, }, market) } func (this *kraken) OrderRequest(method interface{}, symbol interface{}, typeVar interface{}, request interface{}, amount interface{}, optionalArgs ...interface{}) interface{} { price := GetArg(optionalArgs, 0, nil) _ = price params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params var clientOrderId interface{} = this.SafeString(params, "clientOrderId") params = this.Omit(params, []interface{}{"clientOrderId"}) if IsTrue(!IsEqual(clientOrderId, nil)) { AddElementToObject(request, "cl_ord_id", clientOrderId) } var stopLossTriggerPrice interface{} = this.SafeString(params, "stopLossPrice") var takeProfitTriggerPrice interface{} = this.SafeString(params, "takeProfitPrice") var isStopLossTriggerOrder interface{} = !IsEqual(stopLossTriggerPrice, nil) var isTakeProfitTriggerOrder interface{} = !IsEqual(takeProfitTriggerPrice, nil) var isStopLossOrTakeProfitTrigger interface{} = IsTrue(isStopLossTriggerOrder) || IsTrue(isTakeProfitTriggerOrder) var trailingAmount interface{} = this.SafeString(params, "trailingAmount") var trailingPercent interface{} = this.SafeString(params, "trailingPercent") var trailingLimitAmount interface{} = this.SafeString(params, "trailingLimitAmount") var trailingLimitPercent interface{} = this.SafeString(params, "trailingLimitPercent") var isTrailingAmountOrder interface{} = !IsEqual(trailingAmount, nil) var isTrailingPercentOrder interface{} = !IsEqual(trailingPercent, nil) var isLimitOrder interface{} = EndsWith(typeVar, "limit") // supporting limit, stop-loss-limit, take-profit-limit, etc var isMarketOrder interface{} = IsEqual(typeVar, "market") var cost interface{} = this.SafeString(params, "cost") var flags interface{} = this.SafeString(params, "oflags") params = this.Omit(params, []interface{}{"cost", "oflags"}) var isViqcOrder interface{} = IsTrue((!IsEqual(flags, nil))) && IsTrue((IsGreaterThan(GetIndexOf(flags, "viqc"), OpNeg(1)))) // volume in quote currency if IsTrue(IsTrue(isMarketOrder) && IsTrue((IsTrue(!IsEqual(cost, nil)) || IsTrue(isViqcOrder)))) { if IsTrue(IsTrue(IsEqual(cost, nil)) && IsTrue((!IsEqual(amount, nil)))) { AddElementToObject(request, "volume", this.CostToPrecision(symbol, this.NumberToString(amount))) } else { AddElementToObject(request, "volume", this.CostToPrecision(symbol, cost)) } var extendedOflags interface{} = Ternary(IsTrue((!IsEqual(flags, nil))), Add(flags, ",viqc"), "viqc") AddElementToObject(request, "oflags", extendedOflags) } else if IsTrue(IsTrue(IsTrue(isLimitOrder) && !IsTrue(isTrailingAmountOrder)) && !IsTrue(isTrailingPercentOrder)) { AddElementToObject(request, "price", this.PriceToPrecision(symbol, price)) } var reduceOnly interface{} = this.SafeBool2(params, "reduceOnly", "reduce_only") if IsTrue(isStopLossOrTakeProfitTrigger) { if IsTrue(isStopLossTriggerOrder) { AddElementToObject(request, "price", this.PriceToPrecision(symbol, stopLossTriggerPrice)) if IsTrue(isLimitOrder) { AddElementToObject(request, "ordertype", "stop-loss-limit") } else { AddElementToObject(request, "ordertype", "stop-loss") } } else if IsTrue(isTakeProfitTriggerOrder) { AddElementToObject(request, "price", this.PriceToPrecision(symbol, takeProfitTriggerPrice)) if IsTrue(isLimitOrder) { AddElementToObject(request, "ordertype", "take-profit-limit") } else { AddElementToObject(request, "ordertype", "take-profit") } } if IsTrue(isLimitOrder) { AddElementToObject(request, "price2", this.PriceToPrecision(symbol, price)) } } else if IsTrue(IsTrue(isTrailingAmountOrder) || IsTrue(isTrailingPercentOrder)) { var trailingPercentString interface{} = nil if IsTrue(!IsEqual(trailingPercent, nil)) { trailingPercentString = Ternary(IsTrue((EndsWith(trailingPercent, "%"))), (Add("+", trailingPercent)), (Add(Add("+", trailingPercent), "%"))) } var trailingAmountString interface{} = Ternary(IsTrue((!IsEqual(trailingAmount, nil))), Add("+", trailingAmount), nil) // must use + for this var offset interface{} = this.SafeString(params, "offset", "-") // can use + or - for this var trailingLimitAmountString interface{} = Ternary(IsTrue((!IsEqual(trailingLimitAmount, nil))), Add(offset, this.NumberToString(trailingLimitAmount)), nil) var trailingActivationPriceType interface{} = this.SafeString(params, "trigger", "last") AddElementToObject(request, "trigger", trailingActivationPriceType) if IsTrue(IsTrue(IsTrue(isLimitOrder) || IsTrue((!IsEqual(trailingLimitAmount, nil)))) || IsTrue((!IsEqual(trailingLimitPercent, nil)))) { AddElementToObject(request, "ordertype", "trailing-stop-limit") if IsTrue(!IsEqual(trailingLimitPercent, nil)) { var trailingLimitPercentString interface{} = Ternary(IsTrue((EndsWith(trailingLimitPercent, "%"))), (Add(offset, trailingLimitPercent)), (Add(Add(offset, trailingLimitPercent), "%"))) AddElementToObject(request, "price", trailingPercentString) AddElementToObject(request, "price2", trailingLimitPercentString) } else if IsTrue(!IsEqual(trailingLimitAmount, nil)) { AddElementToObject(request, "price", trailingAmountString) AddElementToObject(request, "price2", trailingLimitAmountString) } } else { AddElementToObject(request, "ordertype", "trailing-stop") if IsTrue(!IsEqual(trailingPercent, nil)) { AddElementToObject(request, "price", trailingPercentString) } else { AddElementToObject(request, "price", trailingAmountString) } } } if IsTrue(reduceOnly) { if IsTrue(IsEqual(method, "createOrderWs")) { AddElementToObject(request, "reduce_only", true) // ws request can't have stringified bool } else { AddElementToObject(request, "reduce_only", "true") // not using boolean in this case, because the urlencodedNested transforms it into 'True' string } } var close interface{} = this.SafeDict(params, "close") if IsTrue(!IsEqual(close, nil)) { close = this.Extend(map[string]interface{} {}, close) var closePrice interface{} = this.SafeValue(close, "price") if IsTrue(!IsEqual(closePrice, nil)) { AddElementToObject(close, "price", this.PriceToPrecision(symbol, closePrice)) } var closePrice2 interface{} = this.SafeValue(close, "price2") // stopPrice if IsTrue(!IsEqual(closePrice2, nil)) { AddElementToObject(close, "price2", this.PriceToPrecision(symbol, closePrice2)) } AddElementToObject(request, "close", close) } var timeInForce interface{} = this.SafeString2(params, "timeInForce", "timeinforce") if IsTrue(!IsEqual(timeInForce, nil)) { AddElementToObject(request, "timeinforce", timeInForce) } var isMarket interface{} = (IsEqual(typeVar, "market")) var postOnly interface{} = nil postOnlyparamsVariable := this.HandlePostOnly(isMarket, false, params); postOnly = GetValue(postOnlyparamsVariable,0); params = GetValue(postOnlyparamsVariable,1) if IsTrue(postOnly) { var extendedPostFlags interface{} = Ternary(IsTrue((!IsEqual(flags, nil))), Add(flags, ",post"), "post") AddElementToObject(request, "oflags", extendedPostFlags) } if IsTrue(IsTrue((!IsEqual(flags, nil))) && !IsTrue((InOp(request, "oflags")))) { AddElementToObject(request, "oflags", flags) } params = this.Omit(params, []interface{}{"timeInForce", "reduceOnly", "stopLossPrice", "takeProfitPrice", "trailingAmount", "trailingPercent", "trailingLimitAmount", "trailingLimitPercent", "offset"}) return []interface{}{request, params} } /** * @method * @name kraken#editOrder * @description edit a trade order * @see https://docs.kraken.com/api/docs/rest-api/amend-order * @param {string} id order id * @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 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.stopLossPrice] the price that a stop loss order is triggered at * @param {float} [params.takeProfitPrice] the price that a take profit order is triggered at * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price * @param {string} [params.trailingPercent] the percent to trail away from the current market price * @param {string} [params.trailingLimitAmount] the quote amount away from the trailingAmount * @param {string} [params.trailingLimitPercent] the percent away from the trailingAmount * @param {string} [params.offset] '+' or '-' whether you want the trailingLimitAmount value to be positive or negative * @param {boolean} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately * @param {string} [params.clientOrderId] the orders client order id * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) 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 retRes20828 := (<-this.LoadMarkets()) PanicOnError(retRes20828) var market interface{} = this.Market(symbol) if !IsTrue(GetValue(market, "spot")) { panic(NotSupported(Add(Add(Add(this.Id, " editOrder() does not support "), GetValue(market, "type")), " orders, only spot orders are accepted"))) } var request interface{} = map[string]interface{} { "txid": id, } var clientOrderId interface{} = this.SafeString2(params, "clientOrderId", "cl_ord_id") if IsTrue(!IsEqual(clientOrderId, nil)) { AddElementToObject(request, "cl_ord_id", clientOrderId) params = this.Omit(params, []interface{}{"clientOrderId", "cl_ord_id"}) request = this.Omit(request, "txid") } var isMarket interface{} = (IsEqual(typeVar, "market")) var postOnly interface{} = nil postOnlyparamsVariable := this.HandlePostOnly(isMarket, false, params); postOnly = GetValue(postOnlyparamsVariable,0); params = GetValue(postOnlyparamsVariable,1) if IsTrue(postOnly) { AddElementToObject(request, "post_only", "true") // not using boolean in this case, because the urlencodedNested transforms it into 'True' string } if IsTrue(!IsEqual(amount, nil)) { AddElementToObject(request, "order_qty", this.AmountToPrecision(symbol, amount)) } if IsTrue(!IsEqual(price, nil)) { AddElementToObject(request, "limit_price", this.PriceToPrecision(symbol, price)) } var allTriggerPrices interface{} = this.SafeStringN(params, []interface{}{"stopLossPrice", "takeProfitPrice", "trailingAmount", "trailingPercent", "trailingLimitAmount", "trailingLimitPercent"}) if IsTrue(!IsEqual(allTriggerPrices, nil)) { var offset interface{} = this.SafeString(params, "offset") params = this.Omit(params, []interface{}{"stopLossPrice", "takeProfitPrice", "trailingAmount", "trailingPercent", "trailingLimitAmount", "trailingLimitPercent", "offset"}) if IsTrue(!IsEqual(offset, nil)) { allTriggerPrices = Add(offset, allTriggerPrices) AddElementToObject(request, "trigger_price", allTriggerPrices) } else { AddElementToObject(request, "trigger_price", this.PriceToPrecision(symbol, allTriggerPrices)) } } response:= (<-this.PrivatePostAmendOrder(this.Extend(request, params))) PanicOnError(response) // // { // "error": [], // "result": { // "amend_id": "TJSMEH-AA67V-YUSQ6O" // } // } // var result interface{} = this.SafeDict(response, "result", map[string]interface{} {}) ch <- this.ParseOrder(result, market) return nil }() return ch } /** * @method * @name kraken#fetchOrder * @description fetches information on an order made by the user * @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getOrdersInfo * @param {string} id order id * @param {string} symbol not used by kraken 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 *kraken) 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 retRes21438 := (<-this.LoadMarkets()) PanicOnError(retRes21438) var clientOrderId interface{} = this.SafeValue2(params, "userref", "clientOrderId") var request interface{} = map[string]interface{} { "trades": true, "txid": id, } var query interface{} = params if IsTrue(!IsEqual(clientOrderId, nil)) { AddElementToObject(request, "userref", clientOrderId) query = this.Omit(params, []interface{}{"userref", "clientOrderId"}) } response:= (<-this.PrivatePostQueryOrders(this.Extend(request, query))) PanicOnError(response) // // { // "error":[], // "result":{ // "OTLAS3-RRHUF-NDWH5A":{ // "refid":null, // "userref":null, // "status":"closed", // "reason":null, // "opentm":1586822919.3342, // "closetm":1586822919.365, // "starttm":0, // "expiretm":0, // "descr":{ // "pair":"XBTUSDT", // "type":"sell", // "ordertype":"market", // "price":"0", // "price2":"0", // "leverage":"none", // "order":"sell 0.21804000 XBTUSDT @ market", // "close":"" // }, // "vol":"0.21804000", // "vol_exec":"0.21804000", // "cost":"1493.9", // "fee":"3.8", // "price":"6851.5", // "stopprice":"0.00000", // "limitprice":"0.00000", // "misc":"", // "oflags":"fciq", // "trades":["TT5UC3-GOIRW-6AZZ6R"] // } // } // } // var result interface{} = this.SafeValue(response, "result", []interface{}{}) if !IsTrue((InOp(result, id))) { panic(OrderNotFound(Add(Add(this.Id, " fetchOrder() could not find order id "), id))) } ch <- this.ParseOrder(this.Extend(map[string]interface{} { "id": id, }, GetValue(result, id))) return nil }() return ch } /** * @method * @name kraken#fetchOrderTrades * @description fetch all the trades made from a single order * @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getTradesInfo * @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 * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure} */ func (this *kraken) 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 orderTrades interface{} = this.SafeValue(params, "trades") var tradeIds interface{} = []interface{}{} if IsTrue(IsEqual(orderTrades, nil)) { panic(ArgumentsRequired(Add(this.Id, " fetchOrderTrades() requires a unified order structure in the params argument or a \\'trades\\' param (an array of trade id strings)"))) } else { for i := 0; IsLessThan(i, GetArrayLength(orderTrades)); i++ { var orderTrade interface{} = GetValue(orderTrades, i) if IsTrue(IsString(orderTrade)) { AppendToArray(&tradeIds,orderTrade) } else { AppendToArray(&tradeIds,GetValue(orderTrade, "id")) } } } retRes22278 := (<-this.LoadMarkets()) PanicOnError(retRes22278) if IsTrue(!IsEqual(symbol, nil)) { symbol = this.Symbol(symbol) } var options interface{} = this.SafeValue(this.Options, "fetchOrderTrades", map[string]interface{} {}) var batchSize interface{} = this.SafeInteger(options, "batchSize", 20) var numTradeIds interface{} = GetArrayLength(tradeIds) var numBatches interface{} = this.ParseToInt(Divide(numTradeIds, batchSize)) numBatches = this.Sum(numBatches, 1) var result interface{} = []interface{}{} for j := 0; IsLessThan(j, numBatches); j++ { var requestIds interface{} = []interface{}{} for k := 0; IsLessThan(k, batchSize); k++ { var index interface{} = this.Sum(Multiply(j, batchSize), k) if IsTrue(IsLessThan(index, numTradeIds)) { AppendToArray(&requestIds,GetValue(tradeIds, index)) } } var request interface{} = map[string]interface{} { "txid": Join(requestIds, ","), } response:= (<-this.PrivatePostQueryTrades(request)) PanicOnError(response) // // { // "error": [], // "result": { // 'TIMIRG-WUNNE-RRJ6GT': { // "ordertxid": 'OQRPN2-LRHFY-HIFA7D', // "postxid": 'TKH2SE-M7IF5-CFI7LT', // "pair": 'USDCUSDT', // "time": 1586340086.457, // "type": 'sell', // "ordertype": 'market', // "price": '0.99860000', // "cost": '22.16892001', // "fee": '0.04433784', // "vol": '22.20000000', // "margin": '0.00000000', // "misc": '' // } // } // } // var rawTrades interface{} = this.SafeValue(response, "result") var ids interface{} = ObjectKeys(rawTrades) for i := 0; IsLessThan(i, GetArrayLength(ids)); i++ { AddElementToObject(GetValue(rawTrades, GetValue(ids, i)), "id", GetValue(ids, i)) } var trades interface{} = this.ParseTrades(rawTrades, nil, since, limit) var tradesFilteredBySymbol interface{} = this.FilterBySymbol(trades, symbol) result = this.ArrayConcat(result, tradesFilteredBySymbol) } ch <- result return nil }() return ch } /** * @method * @name kraken#fetchOrdersByIds * @description fetch orders by the list of order id * @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getClosedOrders * @param {string[]} [ids] list of order id * @param {string} [symbol] unified ccxt market symbol * @param {object} [params] extra parameters specific to the kraken api endpoint * @returns {object[]} a list of [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) FetchOrdersByIds(ids 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 retRes22938 := (<-this.LoadMarkets()) PanicOnError(retRes22938) response:= (<-this.PrivatePostQueryOrders(this.Extend(map[string]interface{} { "trades": true, "txid": Join(ids, ","), }, params))) PanicOnError(response) var result interface{} = this.SafeValue(response, "result", map[string]interface{} {}) var orders interface{} = []interface{}{} var orderIds interface{} = ObjectKeys(result) for i := 0; IsLessThan(i, GetArrayLength(orderIds)); i++ { var id interface{} = GetValue(orderIds, i) var item interface{} = GetValue(result, id) var order interface{} = this.ParseOrder(this.Extend(map[string]interface{} { "id": id, }, item)) AppendToArray(&orders,order) } ch <- orders return nil }() return ch } /** * @method * @name kraken#fetchMyTrades * @description fetch all trades made by the user * @see https://docs.kraken.com/api/docs/rest-api/get-trade-history * @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 structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {int} [params.until] timestamp in ms of the latest trade entry * @param {int} [params.end] timestamp in seconds of the latest trade entry * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure} */ func (this *kraken) 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 retRes23248 := (<-this.LoadMarkets()) PanicOnError(retRes23248) var request interface{} = map[string]interface{} {} if IsTrue(!IsEqual(since, nil)) { AddElementToObject(request, "start", this.ParseToInt(Divide(since, 1000))) } var until interface{} = this.SafeStringN(params, []interface{}{"until", "till"}) if IsTrue(!IsEqual(until, nil)) { params = this.Omit(params, []interface{}{"until", "till"}) var untilDivided interface{} = Precise.StringDiv(until, "1000") AddElementToObject(request, "end", this.ParseToInt(Precise.StringAdd(untilDivided, "1"))) } response:= (<-this.PrivatePostTradesHistory(this.Extend(request, params))) PanicOnError(response) // // { // "error": [], // "result": { // "trades": { // "GJ3NYQ-XJRTF-THZABF": { // "ordertxid": "TKH2SE-ZIF5E-CFI7LT", // "postxid": "OEN3VX-M7IF5-JNBJAM", // "pair": "XICNXETH", // "time": 1527213229.4491, // "type": "sell", // "ordertype": "limit", // "price": "0.001612", // "cost": "0.025792", // "fee": "0.000026", // "vol": "16.00000000", // "margin": "0.000000", // "leverage": "5", // "misc": "" // "trade_id": 68230622, // "maker": false // }, // ... // }, // "count": 9760, // }, // } // var trades interface{} = GetValue(GetValue(response, "result"), "trades") var ids interface{} = ObjectKeys(trades) for i := 0; IsLessThan(i, GetArrayLength(ids)); i++ { AddElementToObject(GetValue(trades, GetValue(ids, i)), "id", GetValue(ids, i)) } var market interface{} = nil if IsTrue(!IsEqual(symbol, nil)) { market = this.Market(symbol) } ch <- this.ParseTrades(trades, market, since, limit) return nil }() return ch } /** * @method * @name kraken#cancelOrder * @description cancels an open order * @see https://docs.kraken.com/api/docs/rest-api/cancel-order * @param {string} id order id * @param {string} [symbol] unified symbol of the market the order was made in * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.clientOrderId] the orders client order id * @param {int} [params.userref] the orders user reference id * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) 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 retRes23958 := (<-this.LoadMarkets()) PanicOnError(retRes23958) var response interface{} = nil var requestId interface{} = this.SafeValue(params, "userref", id) // string or integer params = this.Omit(params, "userref") var request interface{} = map[string]interface{} { "txid": requestId, } var clientOrderId interface{} = this.SafeString2(params, "clientOrderId", "cl_ord_id") if IsTrue(!IsEqual(clientOrderId, nil)) { AddElementToObject(request, "cl_ord_id", clientOrderId) params = this.Omit(params, []interface{}{"clientOrderId", "cl_ord_id"}) request = this.Omit(request, "txid") } { ret__ := func(this *kraken) (ret_ interface{}) { defer func() { if e := recover(); e != nil { if e == "break" { return } ret_ = func(this *kraken) interface{} { // catch block: if IsTrue(this.Last_http_response) { if IsTrue(IsGreaterThanOrEqual(GetIndexOf(this.Last_http_response, "EOrder:Unknown order"), 0)) { panic(OrderNotFound(Add(Add(this.Id, " cancelOrder() error "), this.Last_http_response))) } } panic(e) return nil }(this) } }() // try block: response = (<-this.PrivatePostCancelOrder(this.Extend(request, params))) PanicOnError(response) return nil }(this) if ret__ != nil { return ret__ } } ch <- this.SafeOrder(map[string]interface{} { "info": response, }) return nil }() return ch } /** * @method * @name kraken#cancelOrders * @description cancel multiple orders * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/cancelOrderBatch * @param {string[]} ids open orders transaction ID (txid) or user reference (userref) * @param {string} symbol unified market symbol * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) CancelOrders(ids 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 var request interface{} = map[string]interface{} { "orders": ids, } response:= (<-this.PrivatePostCancelOrderBatch(this.Extend(request, params))) PanicOnError(response) // // { // "error": [], // "result": { // "count": 2 // } // } // ch <- []interface{}{this.SafeOrder(map[string]interface{} { "info": response, })} return nil }() return ch } /** * @method * @name kraken#cancelAllOrders * @description cancel all open orders * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/cancelAllOrders * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) CancelAllOrders(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 retRes24718 := (<-this.LoadMarkets()) PanicOnError(retRes24718) response:= (<-this.PrivatePostCancelAll(params)) PanicOnError(response) // // { // error: [], // result: { // count: '1' // } // } // ch <- []interface{}{this.SafeOrder(map[string]interface{} { "info": response, })} return nil }() return ch } /** * @method * @name kraken#cancelAllOrdersAfter * @description dead man's switch, cancel all orders after the given timeout * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/cancelAllOrdersAfter * @param {number} timeout time in milliseconds, 0 represents cancel the timer * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} the api result */ func (this *kraken) CancelAllOrdersAfter(timeout 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 if IsTrue(IsGreaterThan(timeout, 86400000)) { panic(BadRequest(Add(this.Id, " cancelAllOrdersAfter timeout should be less than 86400000 milliseconds"))) } retRes25018 := (<-this.LoadMarkets()) PanicOnError(retRes25018) var request interface{} = map[string]interface{} { "timeout": Ternary(IsTrue((IsGreaterThan(timeout, 0))), (this.ParseToInt(Divide(timeout, 1000))), 0), } response:= (<-this.PrivatePostCancelAllOrdersAfter(this.Extend(request, params))) PanicOnError(response) // // { // "error": [ ], // "result": { // "currentTime": "2023-03-24T17:41:56Z", // "triggerTime": "2023-03-24T17:42:56Z" // } // } // ch <- response return nil }() return ch } /** * @method * @name kraken#fetchOpenOrders * @description fetch all unfilled currently open orders * @see https://docs.kraken.com/api/docs/rest-api/get-open-orders * @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.clientOrderId] the orders client order id * @param {int} [params.userref] the orders user reference id * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) 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 retRes25328 := (<-this.LoadMarkets()) PanicOnError(retRes25328) var request interface{} = map[string]interface{} {} if IsTrue(!IsEqual(since, nil)) { AddElementToObject(request, "start", this.ParseToInt(Divide(since, 1000))) } var userref interface{} = this.SafeInteger(params, "userref") if IsTrue(!IsEqual(userref, nil)) { AddElementToObject(request, "userref", userref) params = this.Omit(params, "userref") } var clientOrderId interface{} = this.SafeString(params, "clientOrderId") if IsTrue(!IsEqual(clientOrderId, nil)) { AddElementToObject(request, "cl_ord_id", clientOrderId) params = this.Omit(params, "clientOrderId") } response:= (<-this.PrivatePostOpenOrders(this.Extend(request, params))) PanicOnError(response) // // { // "error": [], // "result": { // "open": { // "O45M52-BFD5S-YXKQOU": { // "refid": null, // "userref": null, // "cl_ord_id": "1234", // "status": "open", // "opentm": 1733815269.370054, // "starttm": 0, // "expiretm": 0, // "descr": { // "pair": "XBTUSD", // "type": "buy", // "ordertype": "limit", // "price": "70000.0", // "price2": "0", // "leverage": "none", // "order": "buy 0.00010000 XBTUSD @ limit 70000.0", // "close": "" // }, // "vol": "0.00010000", // "vol_exec": "0.00000000", // "cost": "0.00000", // "fee": "0.00000", // "price": "0.00000", // "stopprice": "0.00000", // "limitprice": "0.00000", // "misc": "", // "oflags": "fciq" // } // } // } // } // var market interface{} = nil if IsTrue(!IsEqual(symbol, nil)) { market = this.Market(symbol) } var result interface{} = this.SafeDict(response, "result", map[string]interface{} {}) var open interface{} = this.SafeDict(result, "open", map[string]interface{} {}) var orders interface{} = []interface{}{} var orderIds interface{} = ObjectKeys(open) for i := 0; IsLessThan(i, GetArrayLength(orderIds)); i++ { var id interface{} = GetValue(orderIds, i) var item interface{} = GetValue(open, id) AppendToArray(&orders,this.Extend(map[string]interface{} { "id": id, }, item)) } ch <- this.ParseOrders(orders, market, since, limit) return nil }() return ch } /** * @method * @name kraken#fetchClosedOrders * @description fetches information on multiple closed orders made by the user * @see https://docs.kraken.com/api/docs/rest-api/get-closed-orders * @param {string} [symbol] unified market symbol of the market orders were made in * @param {int} [since] the earliest time in ms to fetch orders for * @param {int} [limit] the maximum number of order structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {int} [params.until] timestamp in ms of the latest entry * @param {string} [params.clientOrderId] the orders client order id * @param {int} [params.userref] the orders user reference id * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ func (this *kraken) FetchClosedOrders(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 retRes26168 := (<-this.LoadMarkets()) PanicOnError(retRes26168) var request interface{} = map[string]interface{} {} if IsTrue(!IsEqual(since, nil)) { AddElementToObject(request, "start", this.ParseToInt(Divide(since, 1000))) } var userref interface{} = this.SafeInteger(params, "userref") if IsTrue(!IsEqual(userref, nil)) { AddElementToObject(request, "userref", userref) params = this.Omit(params, "userref") } var clientOrderId interface{} = this.SafeString(params, "clientOrderId") if IsTrue(!IsEqual(clientOrderId, nil)) { AddElementToObject(request, "cl_ord_id", clientOrderId) params = this.Omit(params, "clientOrderId") } requestparamsVariable := this.HandleUntilOption("end", request, params); request = GetValue(requestparamsVariable,0); params = GetValue(requestparamsVariable,1) response:= (<-this.PrivatePostClosedOrders(this.Extend(request, params))) PanicOnError(response) // // { // "error":[], // "result":{ // "closed":{ // "OETZYO-UL524-QJMXCT":{ // "refid":null, // "userref":null, // "status":"canceled", // "reason":"User requested", // "opentm":1601489313.3898, // "closetm":1601489346.5507, // "starttm":0, // "expiretm":0, // "descr":{ // "pair":"ETHUSDT", // "type":"buy", // "ordertype":"limit", // "price":"330.00", // "price2":"0", // "leverage":"none", // "order":"buy 0.02100000 ETHUSDT @ limit 330.00", // "close":"" // }, // "vol":"0.02100000", // "vol_exec":"0.00000000", // "cost":"0.00000", // "fee":"0.00000", // "price":"0.00000", // "stopprice":"0.00000", // "limitprice":"0.00000", // "misc":"", // "oflags":"fciq" // }, // }, // "count":16 // } // } // var market interface{} = nil if IsTrue(!IsEqual(symbol, nil)) { market = this.Market(symbol) } var result interface{} = this.SafeDict(response, "result", map[string]interface{} {}) var closed interface{} = this.SafeDict(result, "closed", map[string]interface{} {}) var orders interface{} = []interface{}{} var orderIds interface{} = ObjectKeys(closed) for i := 0; IsLessThan(i, GetArrayLength(orderIds)); i++ { var id interface{} = GetValue(orderIds, i) var item interface{} = GetValue(closed, id) AppendToArray(&orders,this.Extend(map[string]interface{} { "id": id, }, item)) } ch <- this.ParseOrders(orders, market, since, limit) return nil }() return ch } func (this *kraken) ParseTransactionStatus(status interface{}) interface{} { // IFEX transaction states var statuses interface{} = map[string]interface{} { "Initial": "pending", "Pending": "pending", "Success": "ok", "Settled": "pending", "Failure": "failed", "Partial": "ok", } return this.SafeString(statuses, status, status) } func (this *kraken) ParseNetwork(network interface{}) interface{} { var withdrawMethods interface{} = this.SafeValue(this.Options, "withdrawMethods", map[string]interface{} {}) return this.SafeString(withdrawMethods, network, network) } func (this *kraken) ParseTransaction(transaction interface{}, optionalArgs ...interface{}) interface{} { // // fetchDeposits // // { // "method": "Ether (Hex)", // "aclass": "currency", // "asset": "XETH", // "refid": "Q2CANKL-LBFVEE-U4Y2WQ", // "txid": "0x57fd704dab1a73c20e24c8696099b695d596924b401b261513cfdab23…", // "info": "0x615f9ba7a9575b0ab4d571b2b36b1b324bd83290", // "amount": "7.9999257900", // "fee": "0.0000000000", // "time": 1529223212, // "status": "Success" // } // // there can be an additional 'status-prop' field present // deposit pending review by exchange => 'on-hold' // the deposit is initiated by the exchange => 'return' // // { // "type": 'deposit', // "method": 'Fidor Bank AG (Wire Transfer)', // "aclass": 'currency', // "asset": 'ZEUR', // "refid": 'xxx-xxx-xxx', // "txid": '12341234', // "info": 'BANKCODEXXX', // "amount": '38769.08', // "fee": '0.0000', // "time": 1644306552, // "status": 'Success', // status-prop: 'on-hold' // } // // // fetchWithdrawals // // { // "method": "Ether", // "aclass": "currency", // "asset": "XETH", // "refid": "A2BF34S-O7LBNQ-UE4Y4O", // "txid": "0x288b83c6b0904d8400ef44e1c9e2187b5c8f7ea3d838222d53f701a15b5c274d", // "info": "0x7cb275a5e07ba943fee972e165d80daa67cb2dd0", // "amount": "9.9950000000", // "fee": "0.0050000000", // "time": 1530481750, // "status": "Success" // "key":"Huobi wallet", // "network":"Tron" // status-prop: 'on-hold' // this field might not be present in some cases // } // // withdraw // // { // "refid": "AGBSO6T-UFMTTQ-I7KGS6" // } // currency := GetArg(optionalArgs, 0, nil) _ = currency var id interface{} = this.SafeString(transaction, "refid") var txid interface{} = this.SafeString(transaction, "txid") var timestamp interface{} = this.SafeTimestamp(transaction, "time") var currencyId interface{} = this.SafeString(transaction, "asset") var code interface{} = this.SafeCurrencyCode(currencyId, currency) var address interface{} = this.SafeString(transaction, "info") var amount interface{} = this.SafeNumber(transaction, "amount") var status interface{} = this.ParseTransactionStatus(this.SafeString(transaction, "status")) var statusProp interface{} = this.SafeString(transaction, "status-prop") var isOnHoldDeposit interface{} = IsEqual(statusProp, "on-hold") var isCancellationRequest interface{} = IsEqual(statusProp, "cancel-pending") var isOnHoldWithdrawal interface{} = IsEqual(statusProp, "onhold") if IsTrue(IsTrue(IsTrue(isOnHoldDeposit) || IsTrue(isCancellationRequest)) || IsTrue(isOnHoldWithdrawal)) { status = "pending" } var typeVar interface{} = this.SafeString(transaction, "type") // injected from the outside var feeCost interface{} = this.SafeNumber(transaction, "fee") if IsTrue(IsEqual(feeCost, nil)) { if IsTrue(IsEqual(typeVar, "deposit")) { feeCost = 0 } } return map[string]interface{} { "info": transaction, "id": id, "currency": code, "amount": amount, "network": this.ParseNetwork(this.SafeString(transaction, "network")), "address": address, "addressTo": nil, "addressFrom": nil, "tag": nil, "tagTo": nil, "tagFrom": nil, "status": status, "type": typeVar, "updated": nil, "txid": txid, "timestamp": timestamp, "datetime": this.Iso8601(timestamp), "comment": nil, "internal": nil, "fee": map[string]interface{} { "currency": code, "cost": feeCost, }, } } func (this *kraken) ParseTransactionsByType(typeVar interface{}, transactions interface{}, optionalArgs ...interface{}) interface{} { code := GetArg(optionalArgs, 0, nil) _ = code since := GetArg(optionalArgs, 1, nil) _ = since limit := GetArg(optionalArgs, 2, nil) _ = limit var result interface{} = []interface{}{} for i := 0; IsLessThan(i, GetArrayLength(transactions)); i++ { var transaction interface{} = this.ParseTransaction(this.Extend(map[string]interface{} { "type": typeVar, }, GetValue(transactions, i))) AppendToArray(&result,transaction) } return this.FilterByCurrencySinceLimit(result, code, since, limit) } /** * @method * @name kraken#fetchDeposits * @description fetch all deposits made to an account * @see https://docs.kraken.com/rest/#tag/Funding/operation/getStatusRecentDeposits * @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 * @param {int} [params.until] timestamp in ms of the latest transaction entry * @param {int} [params.end] timestamp in seconds of the latest transaction entry * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ func (this *kraken) FetchDeposits(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) // https://www.kraken.com/en-us/help/api#deposit-status 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 retRes28428 := (<-this.LoadMarkets()) PanicOnError(retRes28428) var request interface{} = map[string]interface{} {} if IsTrue(!IsEqual(code, nil)) { var currency interface{} = this.Currency(code) AddElementToObject(request, "asset", GetValue(currency, "id")) } if IsTrue(!IsEqual(since, nil)) { var sinceString interface{} = this.NumberToString(since) AddElementToObject(request, "start", Precise.StringDiv(sinceString, "1000")) } var until interface{} = this.SafeStringN(params, []interface{}{"until", "till"}) if IsTrue(!IsEqual(until, nil)) { params = this.Omit(params, []interface{}{"until", "till"}) var untilDivided interface{} = Precise.StringDiv(until, "1000") AddElementToObject(request, "end", Precise.StringAdd(untilDivided, "1")) } response:= (<-this.PrivatePostDepositStatus(this.Extend(request, params))) PanicOnError(response) // // { error: [], // "result": [ { "method": "Ether (Hex)", // "aclass": "currency", // "asset": "XETH", // "refid": "Q2CANKL-LBFVEE-U4Y2WQ", // "txid": "0x57fd704dab1a73c20e24c8696099b695d596924b401b261513cfdab23…", // "info": "0x615f9ba7a9575b0ab4d571b2b36b1b324bd83290", // "amount": "7.9999257900", // "fee": "0.0000000000", // "time": 1529223212, // "status": "Success" } ] } // ch <- this.ParseTransactionsByType("deposit", GetValue(response, "result"), code, since, limit) return nil }() return ch } /** * @method * @name kraken#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @see https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getServerTime * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ func (this *kraken) FetchTime(optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) // https://www.kraken.com/en-us/features/api#get-server-time params := GetArg(optionalArgs, 0, map[string]interface{} {}) _ = params response:= (<-this.PublicGetTime(params)) PanicOnError(response) // // { // "error": [], // "result": { // "unixtime": 1591502873, // "rfc1123": "Sun, 7 Jun 20 04:07:53 +0000" // } // } // var result interface{} = this.SafeValue(response, "result", map[string]interface{} {}) ch <- this.SafeTimestamp(result, "unixtime") return nil }() return ch } /** * @method * @name kraken#fetchWithdrawals * @description fetch all withdrawals made from an account * @see https://docs.kraken.com/rest/#tag/Funding/operation/getStatusRecentWithdrawals * @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 * @param {int} [params.until] timestamp in ms of the latest transaction entry * @param {int} [params.end] timestamp in seconds of the latest transaction entry * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure} */ func (this *kraken) 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 retRes29148 := (<-this.LoadMarkets()) PanicOnError(retRes29148) var paginate interface{} = false paginateparamsVariable := this.HandleOptionAndParams(params, "fetchWithdrawals", "paginate"); paginate = GetValue(paginateparamsVariable,0); params = GetValue(paginateparamsVariable,1) if IsTrue(paginate) { AddElementToObject(params, "cursor", true) retRes291919 := (<-this.FetchPaginatedCallCursor("fetchWithdrawals", code, since, limit, params, "next_cursor", "cursor")) PanicOnError(retRes291919) ch <- retRes291919 return nil } var request interface{} = map[string]interface{} {} if IsTrue(!IsEqual(code, nil)) { var currency interface{} = this.Currency(code) AddElementToObject(request, "asset", GetValue(currency, "id")) } if IsTrue(!IsEqual(since, nil)) { var sinceString interface{} = this.NumberToString(since) AddElementToObject(request, "start", Precise.StringDiv(sinceString, "1000")) } var until interface{} = this.SafeStringN(params, []interface{}{"until", "till"}) if IsTrue(!IsEqual(until, nil)) { params = this.Omit(params, []interface{}{"until", "till"}) var untilDivided interface{} = Precise.StringDiv(until, "1000") AddElementToObject(request, "end", Precise.StringAdd(untilDivided, "1")) } response:= (<-this.PrivatePostWithdrawStatus(this.Extend(request, params))) PanicOnError(response) // // with no pagination // { error: [], // "result": [ { "method": "Ether", // "aclass": "currency", // "asset": "XETH", // "refid": "A2BF34S-O7LBNQ-UE4Y4O", // "txid": "0x298c83c7b0904d8400ef43e1c9e2287b518f7ea3d838822d53f704a1565c274d", // "info": "0x7cb275a5e07ba943fee972e165d80daa67cb2dd0", // "amount": "9.9950000000", // "fee": "0.0050000000", // "time": 1530481750, // "status": "Success" } ] } // with pagination // { // "error":[], // "result":{ // "withdrawals":[ // { // "method":"Tether USD (TRC20)", // "aclass":"currency", // "asset":"USDT", // "refid":"BSNFZU2-MEFN4G-J3NEZV", // "txid":"1c7a642fb7387bbc2c6a2c509fd1ae146937f4cf793b4079a4f0715e3a02615a", // "info":"TQmdxSuC16EhFg8FZWtYgrfFRosoRF7bCp", // "amount":"1996.50000000", // "fee":"2.50000000", // "time":1669126657, // "status":"Success", // "key":"poloniex", // "network":"Tron" // }, // ... // ], // "next_cursor":"HgAAAAAAAABGVFRSd3k1LVF4Y0JQY05Gd0xRY0NxenFndHpybkwBAQH2AwEBAAAAAQAAAAAAAAABAAAAAAAZAAAAAAAAAA==" // } // } // var rawWithdrawals interface{} = nil var result interface{} = this.SafeValue(response, "result") if !IsTrue(IsArray(result)) { rawWithdrawals = this.AddPaginationCursorToResult(result) } else { rawWithdrawals = result } ch <- this.ParseTransactionsByType("withdrawal", rawWithdrawals, code, since, limit) return nil }() return ch } func (this *kraken) AddPaginationCursorToResult(result interface{}) interface{} { var cursor interface{} = this.SafeString(result, "next_cursor") var data interface{} = this.SafeValue(result, "withdrawals") var dataLength interface{} = GetArrayLength(data) if IsTrue(IsTrue(!IsEqual(cursor, nil)) && IsTrue(IsGreaterThan(dataLength, 0))) { var last interface{} = GetValue(data, Subtract(dataLength, 1)) AddElementToObject(last, "next_cursor", cursor) AddElementToObject(data, Subtract(dataLength, 1), last) } return data } /** * @method * @name kraken#createDepositAddress * @description create a currency deposit address * @see https://docs.kraken.com/rest/#tag/Funding/operation/getDepositAddresses * @param {string} code unified currency code of the currency for the deposit address * @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 *kraken) CreateDepositAddress(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 var request interface{} = map[string]interface{} { "new": "true", } retRes301015 := (<-this.FetchDepositAddress(code, this.Extend(request, params))) PanicOnError(retRes301015) ch <- retRes301015 return nil }() return ch } /** * @method * @name kraken#fetchDepositMethods * @description fetch deposit methods for a currency associated with this account * @see https://docs.kraken.com/rest/#tag/Funding/operation/getDepositMethods * @param {string} code unified currency code * @param {object} [params] extra parameters specific to the kraken api endpoint * @returns {object} of deposit methods */ func (this *kraken) FetchDepositMethods(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 retRes30238 := (<-this.LoadMarkets()) PanicOnError(retRes30238) var currency interface{} = this.Currency(code) var request interface{} = map[string]interface{} { "asset": GetValue(currency, "id"), } response:= (<-this.PrivatePostDepositMethods(this.Extend(request, params))) PanicOnError(response) // // { // "error":[], // "result":[ // {"method":"Ether (Hex)","limit":false,"gen-address":true} // ] // } // // { // "error":[], // "result":[ // {"method":"Tether USD (ERC20)","limit":false,"address-setup-fee":"0.00000000","gen-address":true}, // {"method":"Tether USD (TRC20)","limit":false,"address-setup-fee":"0.00000000","gen-address":true} // ] // } // // { // "error":[], // "result":[ // {"method":"Bitcoin","limit":false,"fee":"0.0000000000","gen-address":true} // ] // } // ch <- this.SafeValue(response, "result") return nil }() return ch } /** * @method * @name kraken#fetchDepositAddress * @description fetch the deposit address for a currency associated with this account * @see https://docs.kraken.com/rest/#tag/Funding/operation/getDepositAddresses * @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 *kraken) 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 retRes30658 := (<-this.LoadMarkets()) PanicOnError(retRes30658) var currency interface{} = this.Currency(code) var network interface{} = this.SafeStringUpper(params, "network") var networks interface{} = this.SafeValue(this.Options, "networks", map[string]interface{} {}) network = this.SafeString(networks, network, network) // support ETH > ERC20 aliases params = this.Omit(params, "network") if IsTrue(IsTrue((IsEqual(code, "USDT"))) && IsTrue((IsEqual(network, "TRC20")))) { code = Add(Add(code, "-"), network) } var defaultDepositMethods interface{} = this.SafeValue(this.Options, "depositMethods", map[string]interface{} {}) var defaultDepositMethod interface{} = this.SafeString(defaultDepositMethods, code) var depositMethod interface{} = this.SafeString(params, "method", defaultDepositMethod) // if the user has specified an exchange-specific method in params // we pass it as is, otherwise we take the 'network' unified param if IsTrue(IsEqual(depositMethod, nil)) { depositMethods:= (<-this.FetchDepositMethods(code)) PanicOnError(depositMethods) if IsTrue(!IsEqual(network, nil)) { // find best matching deposit method, or fallback to the first one for i := 0; IsLessThan(i, GetArrayLength(depositMethods)); i++ { var entry interface{} = this.SafeString(GetValue(depositMethods, i), "method") if IsTrue(IsGreaterThanOrEqual(GetIndexOf(entry, network), 0)) { depositMethod = entry break } } } // if depositMethod was not specified, fallback to the first available deposit method if IsTrue(IsEqual(depositMethod, nil)) { var firstDepositMethod interface{} = this.SafeValue(depositMethods, 0, map[string]interface{} {}) depositMethod = this.SafeString(firstDepositMethod, "method") } } var request interface{} = map[string]interface{} { "asset": GetValue(currency, "id"), "method": depositMethod, } response:= (<-this.PrivatePostDepositAddresses(this.Extend(request, params))) PanicOnError(response) // // { // "error":[], // "result":[ // {"address":"0x77b5051f97efa9cc52c9ad5b023a53fc15c200d3","expiretm":"0"} // ] // } // var result interface{} = this.SafeValue(response, "result", []interface{}{}) var firstResult interface{} = this.SafeValue(result, 0, map[string]interface{} {}) if IsTrue(IsEqual(firstResult, nil)) { panic(InvalidAddress(Add(Add(this.Id, " privatePostDepositAddresses() returned no addresses for "), code))) } ch <- this.ParseDepositAddress(firstResult, currency) return nil }() return ch } func (this *kraken) ParseDepositAddress(depositAddress interface{}, optionalArgs ...interface{}) interface{} { // // { // "address":"0x77b5051f97efa9cc52c9ad5b023a53fc15c200d3", // "expiretm":"0" // } // currency := GetArg(optionalArgs, 0, nil) _ = currency var address interface{} = this.SafeString(depositAddress, "address") var tag interface{} = this.SafeString(depositAddress, "tag") currency = this.SafeCurrency(nil, currency) var code interface{} = GetValue(currency, "code") this.CheckAddress(address) return map[string]interface{} { "info": depositAddress, "currency": code, "network": nil, "address": address, "tag": tag, } } /** * @method * @name kraken#withdraw * @description make a withdrawal * @see https://docs.kraken.com/rest/#tag/Funding/operation/withdrawFunds * @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 *kraken) Withdraw(code interface{}, amount interface{}, address interface{}, optionalArgs ...interface{}) <- chan interface{} { ch := make(chan interface{}) go func() interface{} { defer close(ch) defer ReturnPanicError(ch) tag := GetArg(optionalArgs, 0, nil) _ = tag params := GetArg(optionalArgs, 1, map[string]interface{} {}) _ = params tagparamsVariable := this.HandleWithdrawTagAndParams(tag, params); tag = GetValue(tagparamsVariable,0); params = GetValue(tagparamsVariable,1) this.CheckAddress(address) if IsTrue(InOp(params, "key")) { retRes315512 := (<-this.LoadMarkets()) PanicOnError(retRes315512) var currency interface{} = this.Currency(code) var request interface{} = map[string]interface{} { "asset": GetValue(currency, "id"), "amount": amount, "address": address, } response:= (<-this.PrivatePostWithdraw(this.Extend(request, params))) PanicOnError(response) // // { // "error": [], // "result": { // "refid": "AGBSO6T-UFMTTQ-I7KGS6" // } // } // var result interface{} = this.SafeDict(response, "result", map[string]interface{} {}) ch <- this.ParseTransaction(result, currency) return nil } panic(ExchangeError(Add(this.Id, " withdraw() requires a \\'key\\' parameter (withdrawal key name, as set up on your account)"))) }() return ch } /** * @method * @name kraken#fetchPositions * @description fetch all open positions * @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getOpenPositions * @param {string[]} [symbols] not used by kraken fetchPositions () * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure} */ func (this *kraken) FetchPositions(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 retRes31878 := (<-this.LoadMarkets()) PanicOnError(retRes31878) var request interface{} = map[string]interface{} { "docalcs": "true", "consolidation": "market", } response:= (<-this.PrivatePostOpenPositions(this.Extend(request, params))) PanicOnError(response) // // no consolidation // // { // "error": [], // "result": { // 'TGUFMY-FLESJ-VYIX3J': { // "ordertxid": "O3LRNU-ZKDG5-XNCDFR", // "posstatus": "open", // "pair": "ETHUSDT", // "time": 1611557231.4584, // "type": "buy", // "ordertype": "market", // "cost": "28.49800", // "fee": "0.07979", // "vol": "0.02000000", // "vol_closed": "0.00000000", // "margin": "14.24900", // "terms": "0.0200% per 4 hours", // "rollovertm": "1611571631", // "misc": "", // "oflags": "" // } // } // } // // consolidation by market // // { // "error": [], // "result": [ // { // "pair": "ETHUSDT", // "positions": "1", // "type": "buy", // "leverage": "2.00000", // "cost": "28.49800", // "fee": "0.07979", // "vol": "0.02000000", // "vol_closed": "0.00000000", // "margin": "14.24900" // } // ] // } // symbols = this.MarketSymbols(symbols) var result interface{} = this.SafeList(response, "result") var results interface{} = this.ParsePositions(result, symbols) ch <- this.FilterByArrayPositions(results, "symbol", symbols, false) return nil }() return ch } func (this *kraken) ParsePosition(position interface{}, optionalArgs ...interface{}) interface{} { // // { // "pair": "ETHUSDT", // "positions": "1", // "type": "buy", // "leverage": "2.00000", // "cost": "28.49800", // "fee": "0.07979", // "vol": "0.02000000", // "vol_closed": "0.00000000", // "margin": "14.24900" // } // market := GetArg(optionalArgs, 0, nil) _ = market var marketId interface{} = this.SafeString(position, "pair") var rawSide interface{} = this.SafeString(position, "type") var side interface{} = Ternary(IsTrue((IsEqual(rawSide, "buy"))), "long", "short") return this.SafePosition(map[string]interface{} { "info": position, "id": nil, "symbol": this.SafeSymbol(marketId, market), "notional": nil, "marginMode": nil, "liquidationPrice": nil, "entryPrice": nil, "unrealizedPnl": this.SafeNumber(position, "net"), "realizedPnl": nil, "percentage": nil, "contracts": this.SafeNumber(position, "vol"), "contractSize": nil, "markPrice": nil, "lastPrice": nil, "side": side, "hedged": nil, "timestamp": nil, "datetime": nil, "lastUpdateTimestamp": nil, "maintenanceMargin": nil, "maintenanceMarginPercentage": nil, "collateral": nil, "initialMargin": this.SafeNumber(position, "margin"), "initialMarginPercentage": nil, "leverage": this.SafeNumber(position, "leverage"), "marginRatio": nil, "stopLossPrice": nil, "takeProfitPrice": nil, }) } func (this *kraken) ParseAccountType(account interface{}) interface{} { var accountByType interface{} = map[string]interface{} { "spot": "Spot Wallet", "swap": "Futures Wallet", "future": "Futures Wallet", } return this.SafeString(accountByType, account, account) } /** * @method * @name kraken#transferOut * @description transfer from spot wallet to futures wallet * @see https://docs.kraken.com/rest/#tag/User-Funding/operation/walletTransfer * @param {str} code Unified currency code * @param {float} amount Size of the transfer * @param {dict} [params] Exchange specific parameters * @returns a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure} */ func (this *kraken) TransferOut(code 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 retRes331415 := (<-this.Transfer(code, amount, "spot", "swap", params)) PanicOnError(retRes331415) ch <- retRes331415 return nil }() return ch } /** * @method * @name kraken#transfer * @see https://docs.kraken.com/rest/#tag/User-Funding/operation/walletTransfer * @description transfers currencies between sub-accounts (only spot->swap direction is supported) * @param {string} code Unified currency code * @param {float} amount Size of the transfer * @param {string} fromAccount 'spot' or 'Spot Wallet' * @param {string} toAccount 'swap' or 'Futures Wallet' * @param {object} [params] Exchange specific parameters * @returns a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure} */ func (this *kraken) Transfer(code interface{}, amount interface{}, fromAccount interface{}, toAccount 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 retRes33308 := (<-this.LoadMarkets()) PanicOnError(retRes33308) var currency interface{} = this.Currency(code) fromAccount = this.ParseAccountType(fromAccount) toAccount = this.ParseAccountType(toAccount) var request interface{} = map[string]interface{} { "amount": this.CurrencyToPrecision(code, amount), "from": fromAccount, "to": toAccount, "asset": GetValue(currency, "id"), } if IsTrue(!IsEqual(fromAccount, "Spot Wallet")) { panic(BadRequest(Add(Add(Add(Add(Add(this.Id, " transfer cannot transfer from "), fromAccount), " to "), toAccount), ". Use krakenfutures instead to transfer from the futures account."))) } response:= (<-this.PrivatePostWalletTransfer(this.Extend(request, params))) PanicOnError(response) // // { // "error":[ // ], // "result":{ // "refid":"BOIUSIF-M7DLMN-UXZ3P5" // } // } // var transfer interface{} = this.ParseTransfer(response, currency) ch <- this.Extend(transfer, map[string]interface{} { "amount": amount, "fromAccount": fromAccount, "toAccount": toAccount, }) return nil }() return ch } func (this *kraken) ParseTransfer(transfer interface{}, optionalArgs ...interface{}) interface{} { // // transfer // // { // "error":[ // ], // "result":{ // "refid":"BOIUSIF-M7DLMN-UXZ3P5" // } // } // currency := GetArg(optionalArgs, 0, nil) _ = currency var result interface{} = this.SafeValue(transfer, "result", map[string]interface{} {}) var refid interface{} = this.SafeString(result, "refid") return map[string]interface{} { "info": transfer, "id": refid, "timestamp": nil, "datetime": nil, "currency": this.SafeString(currency, "code"), "amount": nil, "fromAccount": nil, "toAccount": nil, "status": "sucess", } } func (this *kraken) 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(Add(Add(Add(Add("/", this.Version), "/"), api), "/"), path) if IsTrue(IsEqual(api, "public")) { if IsTrue(GetArrayLength(ObjectKeys(params))) { // urlencodeNested is used to address https://github.com/ccxt/ccxt/issues/12872 url = Add(url, Add("?", this.UrlencodeNested(params))) } } else if IsTrue(IsEqual(api, "private")) { var price interface{} = this.SafeString(params, "price") var isTriggerPercent interface{} = false if IsTrue(!IsEqual(price, nil)) { isTriggerPercent = Ternary(IsTrue((EndsWith(price, "%"))), true, false) } var isCancelOrderBatch interface{} = (IsEqual(path, "CancelOrderBatch")) this.CheckRequiredCredentials() var nonce interface{} = ToString(this.Nonce()) // urlencodeNested is used to address https://github.com/ccxt/ccxt/issues/12872 if IsTrue(IsTrue(isCancelOrderBatch) || IsTrue(isTriggerPercent)) { body = this.Json(this.Extend(map[string]interface{} { "nonce": nonce, }, params)) } else { body = this.UrlencodeNested(this.Extend(map[string]interface{} { "nonce": nonce, }, params)) } var auth interface{} = this.Encode(Add(nonce, body)) var hash interface{} = this.Hash(auth, sha256, "binary") var binary interface{} = this.Encode(url) var binhash interface{} = this.BinaryConcat(binary, hash) var secret interface{} = this.Base64ToBinary(this.Secret) var signature interface{} = this.Hmac(binhash, secret, sha512, "base64") headers = map[string]interface{} { "API-Key": this.ApiKey, "API-Sign": signature, } if IsTrue(IsTrue(isCancelOrderBatch) || IsTrue(isTriggerPercent)) { AddElementToObject(headers, "Content-Type", "application/json") } else { AddElementToObject(headers, "Content-Type", "application/x-www-form-urlencoded") } } else { url = Add("/", path) } url = Add(GetValue(GetValue(this.Urls, "api"), api), url) return map[string]interface{} { "url": url, "method": method, "body": body, "headers": headers, } } func (this *kraken) Nonce() interface{} { return Subtract(this.Milliseconds(), GetValue(this.Options, "timeDifference")) } func (this *kraken) HandleErrors(code interface{}, reason interface{}, url interface{}, method interface{}, headers interface{}, body interface{}, response interface{}, requestHeaders interface{}, requestBody interface{}) interface{} { if IsTrue(IsEqual(code, 520)) { panic(ExchangeNotAvailable(Add(Add(Add(Add(this.Id, " "), ToString(code)), " "), reason))) } if IsTrue(IsEqual(response, nil)) { return nil } if IsTrue(IsEqual(GetValue(body, 0), "{")) { if IsTrue(!IsString(response)) { if IsTrue(InOp(response, "error")) { var numErrors interface{} = GetArrayLength(GetValue(response, "error")) if IsTrue(numErrors) { var message interface{} = Add(Add(this.Id, " "), body) for i := 0; IsLessThan(i, GetArrayLength(GetValue(response, "error"))); i++ { var error interface{} = GetValue(GetValue(response, "error"), i) this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), error, message) this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "broad"), error, message) } panic(ExchangeError(message)) } } } } return nil } func (this *kraken) Init(userConfig map[string]interface{}) { this.Exchange = Exchange{} this.Exchange.InitParent(userConfig, this.Describe().(map[string]interface{}), this) this.Exchange.DerivedExchange = this }