ccxt-go/blofin.go

3037 lines
134 KiB
Go
Raw Permalink Normal View History

2025-02-28 10:33:20 +08:00
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 blofin struct {
Exchange
}
func NewBlofinCore() blofin {
p := blofin{}
setDefaults(&p)
return p
}
func (this *blofin) Describe() interface{} {
return this.DeepExtend(this.Exchange.Describe(), map[string]interface{} {
"id": "blofin",
"name": "BloFin",
"countries": []interface{}{"US"},
"version": "v1",
"rateLimit": 100,
"pro": true,
"has": map[string]interface{} {
"CORS": nil,
"spot": false,
"margin": false,
"swap": true,
"future": false,
"option": false,
"addMargin": false,
"borrowMargin": false,
"cancelAllOrders": false,
"cancelOrder": true,
"cancelOrders": true,
"closeAllPositions": false,
"closePosition": true,
"createDepositAddress": false,
"createMarketBuyOrderWithCost": false,
"createMarketSellOrderWithCost": false,
"createOrder": true,
"createOrders": true,
"createOrderWithTakeProfitAndStopLoss": true,
"createPostOnlyOrder": false,
"createReduceOnlyOrder": false,
"createStopLimitOrder": false,
"createStopLossOrder": true,
"createStopMarketOrder": false,
"createStopOrder": false,
"createTakeProfitOrder": true,
"editOrder": false,
"fetchAccounts": false,
"fetchBalance": true,
"fetchBidsAsks": nil,
"fetchBorrowInterest": false,
"fetchBorrowRateHistories": false,
"fetchBorrowRateHistory": false,
"fetchCanceledOrders": false,
"fetchClosedOrder": false,
"fetchClosedOrders": false,
"fetchCrossBorrowRate": false,
"fetchCrossBorrowRates": false,
"fetchCurrencies": false,
"fetchDeposit": false,
"fetchDepositAddress": false,
"fetchDepositAddresses": false,
"fetchDepositAddressesByNetwork": false,
"fetchDeposits": true,
"fetchDepositsWithdrawals": false,
"fetchDepositWithdrawFee": "emulated",
"fetchDepositWithdrawFees": false,
"fetchFundingHistory": true,
"fetchFundingRate": true,
"fetchFundingRateHistory": true,
"fetchFundingRates": false,
"fetchGreeks": false,
"fetchIndexOHLCV": false,
"fetchIsolatedBorrowRate": false,
"fetchIsolatedBorrowRates": false,
"fetchL3OrderBook": false,
"fetchLedger": true,
"fetchLedgerEntry": nil,
"fetchLeverage": true,
"fetchLeverages": true,
"fetchLeverageTiers": false,
"fetchMarginMode": true,
"fetchMarginModes": false,
"fetchMarketLeverageTiers": false,
"fetchMarkets": true,
"fetchMarkOHLCV": false,
"fetchMySettlementHistory": false,
"fetchMyTrades": true,
"fetchOHLCV": true,
"fetchOpenInterest": false,
"fetchOpenInterestHistory": false,
"fetchOpenOrder": nil,
"fetchOpenOrders": true,
"fetchOrder": nil,
"fetchOrderBook": true,
"fetchOrderBooks": false,
"fetchOrders": false,
"fetchOrderTrades": true,
"fetchPosition": true,
"fetchPositions": true,
"fetchPositionsForSymbol": false,
"fetchPositionsRisk": false,
"fetchPremiumIndexOHLCV": false,
"fetchSettlementHistory": false,
"fetchStatus": false,
"fetchTicker": true,
"fetchTickers": true,
"fetchTime": false,
"fetchTrades": true,
"fetchTradingFee": false,
"fetchTradingFees": false,
"fetchTradingLimits": false,
"fetchTransactionFee": false,
"fetchTransactionFees": false,
"fetchTransactions": false,
"fetchTransfer": false,
"fetchTransfers": false,
"fetchUnderlyingAssets": false,
"fetchVolatilityHistory": false,
"fetchWithdrawal": false,
"fetchWithdrawals": true,
"fetchWithdrawalWhitelist": false,
"reduceMargin": false,
"repayCrossMargin": false,
"setLeverage": true,
"setMargin": false,
"setMarginMode": false,
"setPositionMode": false,
"signIn": false,
"transfer": true,
"withdraw": false,
},
"timeframes": map[string]interface{} {
"1m": "1m",
"3m": "3m",
"5m": "5m",
"15m": "15m",
"30m": "30m",
"1h": "1H",
"2h": "2H",
"4h": "4H",
"6h": "6H",
"8h": "8H",
"12h": "12H",
"1d": "1D",
"3d": "3D",
"1w": "1W",
"1M": "1M",
},
"hostname": "www.blofin.com",
"urls": map[string]interface{} {
"logo": "https://github.com/user-attachments/assets/518cdf80-f05d-4821-a3e3-d48ceb41d73b",
"api": map[string]interface{} {
"rest": "https://openapi.blofin.com",
},
"test": map[string]interface{} {
"rest": "https://demo-trading-openapi.blofin.com",
},
"referral": map[string]interface{} {
"url": "https://blofin.com/register?referral_code=f79EsS",
"discount": 0.05,
},
"www": "https://www.blofin.com",
"doc": "https://blofin.com/docs",
},
"api": map[string]interface{} {
"public": map[string]interface{} {
"get": map[string]interface{} {
"market/instruments": 1,
"market/tickers": 1,
"market/books": 1,
"market/trades": 1,
"market/candles": 1,
"market/mark-price": 1,
"market/funding-rate": 1,
"market/funding-rate-history": 1,
},
},
"private": map[string]interface{} {
"get": map[string]interface{} {
"asset/balances": 1,
"trade/orders-pending": 1,
"trade/fills-history": 1,
"asset/deposit-history": 1,
"asset/withdrawal-history": 1,
"asset/bills": 1,
"account/balance": 1,
"account/positions": 1,
"account/leverage-info": 1,
"account/margin-mode": 1,
"account/batch-leverage-info": 1,
"trade/orders-tpsl-pending": 1,
"trade/orders-history": 1,
"trade/orders-tpsl-history": 1,
"user/query-apikey": 1,
"affiliate/basic": 1,
"copytrading/instruments": 1,
"copytrading/account/balance": 1,
"copytrading/account/positions-by-order": 1,
"copytrading/account/positions-details-by-order": 1,
"copytrading/account/positions-by-contract": 1,
"copytrading/account/position-mode": 1,
"copytrading/account/leverage-info": 1,
"copytrading/trade/orders-pending": 1,
"copytrading/trade/pending-tpsl-by-contract": 1,
"copytrading/trade/position-history-by-order": 1,
"copytrading/trade/orders-history": 1,
"copytrading/trade/pending-tpsl-by-order": 1,
},
"post": map[string]interface{} {
"trade/order": 1,
"trade/cancel-order": 1,
"account/set-leverage": 1,
"trade/batch-orders": 1,
"trade/order-tpsl": 1,
"trade/cancel-batch-orders": 1,
"trade/cancel-tpsl": 1,
"trade/close-position": 1,
"asset/transfer": 1,
"copytrading/account/set-position-mode": 1,
"copytrading/account/set-leverage": 1,
"copytrading/trade/place-order": 1,
"copytrading/trade/cancel-order": 1,
"copytrading/trade/place-tpsl-by-contract": 1,
"copytrading/trade/cancel-tpsl-by-contract": 1,
"copytrading/trade/place-tpsl-by-order": 1,
"copytrading/trade/cancel-tpsl-by-order": 1,
"copytrading/trade/close-position-by-order": 1,
"copytrading/trade/close-position-by-contract": 1,
},
},
},
"fees": map[string]interface{} {
"swap": map[string]interface{} {
"taker": this.ParseNumber("0.00060"),
"maker": this.ParseNumber("0.00020"),
},
},
"requiredCredentials": map[string]interface{} {
"apiKey": true,
"secret": true,
"password": true,
},
"features": map[string]interface{} {
"default": map[string]interface{} {
"sandbox": false,
"createOrder": map[string]interface{} {
"timeInForce": map[string]interface{} {
"IOC": true,
"FOK": true,
"PO": true,
"GTD": false,
},
"leverage": false,
"marketBuyRequiresPrice": false,
"marketBuyByCost": false,
"selfTradePrevention": false,
"trailing": false,
"iceberg": false,
},
"createOrders": map[string]interface{} {
"max": 10,
},
"fetchMyTrades": map[string]interface{} {
"marginMode": false,
"limit": 100,
"daysBack": 100000,
"untilDays": 100000,
"symbolRequired": false,
},
"fetchOrder": nil,
"fetchOpenOrders": map[string]interface{} {
"marginMode": false,
"limit": 100,
"trigger": true,
"trailing": false,
"symbolRequired": false,
},
"fetchOrders": nil,
"fetchClosedOrders": map[string]interface{} {
"marginMode": false,
"limit": 1000,
"daysBack": 100000,
"daysBackCanceled": 1,
"untilDays": 100000,
"trigger": true,
"trailing": false,
"symbolRequired": false,
},
"fetchOHLCV": map[string]interface{} {
"limit": 1440,
},
},
"spot": map[string]interface{} {
"extends": "default",
"createOrder": map[string]interface{} {
"marginMode": false,
"triggerPrice": false,
"triggerPriceType": nil,
"triggerDirection": false,
"stopLossPrice": false,
"takeProfitPrice": false,
"attachedStopLossTakeProfit": nil,
"hedged": false,
},
},
"forDerivatives": map[string]interface{} {
"extends": "default",
"createOrder": map[string]interface{} {
"marginMode": true,
"triggerPrice": false,
"triggerPriceType": nil,
"triggerDirection": false,
"stopLossPrice": true,
"takeProfitPrice": true,
"attachedStopLossTakeProfit": map[string]interface{} {
"triggerPriceType": nil,
"price": true,
},
"hedged": true,
},
},
"swap": map[string]interface{} {
"linear": map[string]interface{} {
"extends": "forDerivatives",
},
"inverse": nil,
},
"future": map[string]interface{} {
"linear": nil,
"inverse": nil,
},
},
"exceptions": map[string]interface{} {
"exact": map[string]interface{} {
"400": BadRequest,
"401": AuthenticationError,
"500": ExchangeError,
"404": BadRequest,
"405": BadRequest,
"406": BadRequest,
"429": RateLimitExceeded,
"152001": BadRequest,
"152002": BadRequest,
"152003": BadRequest,
"152004": BadRequest,
"152005": BadRequest,
"152006": InvalidOrder,
"152007": InvalidOrder,
"152008": InvalidOrder,
"152009": InvalidOrder,
"150003": InvalidOrder,
"150004": InvalidOrder,
"542": InvalidOrder,
"102002": InvalidOrder,
"102005": InvalidOrder,
"102014": InvalidOrder,
"102015": InvalidOrder,
"102022": InvalidOrder,
"102037": InvalidOrder,
"102038": InvalidOrder,
"102039": InvalidOrder,
"102040": InvalidOrder,
"102047": InvalidOrder,
"102048": InvalidOrder,
"102049": InvalidOrder,
"102050": InvalidOrder,
"102051": InvalidOrder,
"102052": InvalidOrder,
"102053": InvalidOrder,
"102054": InvalidOrder,
"102055": InvalidOrder,
"102064": BadRequest,
"102065": BadRequest,
"102068": BadRequest,
"103013": ExchangeError,
"Order failed. Insufficient USDT margin in account": InsufficientFunds,
},
"broad": map[string]interface{} {
"Internal Server Error": ExchangeNotAvailable,
"server error": ExchangeNotAvailable,
},
},
"httpExceptions": map[string]interface{} {
"429": ExchangeNotAvailable,
},
"precisionMode": TICK_SIZE,
"options": map[string]interface{} {
"brokerId": "ec6dd3a7dd982d0b",
"accountsByType": map[string]interface{} {
"swap": "futures",
"funding": "funding",
"future": "futures",
"copy_trading": "copy_trading",
"earn": "earn",
"spot": "spot",
},
"accountsById": map[string]interface{} {
"funding": "funding",
"futures": "swap",
"copy_trading": "copy_trading",
"earn": "earn",
"spot": "spot",
},
"defaultNetwork": "ERC20",
"defaultNetworks": map[string]interface{} {
"ETH": "ERC20",
"BTC": "BTC",
"USDT": "TRC20",
},
"networks": map[string]interface{} {
"BTC": "Bitcoin",
"BEP20": "BSC",
"ERC20": "ERC20",
"TRC20": "TRC20",
},
"fetchOpenInterestHistory": map[string]interface{} {
"timeframes": map[string]interface{} {
"5m": "5m",
"1h": "1H",
"8h": "8H",
"1d": "1D",
"5M": "5m",
"1H": "1H",
"8H": "8H",
"1D": "1D",
},
},
"fetchOHLCV": map[string]interface{} {
"timezone": "UTC",
},
"fetchPositions": map[string]interface{} {
"method": "privateGetAccountPositions",
},
"createOrder": "privatePostTradeOrder",
"createMarketBuyOrderRequiresPrice": false,
"fetchMarkets": []interface{}{"swap"},
"defaultType": "swap",
"fetchLedger": map[string]interface{} {
"method": "privateGetAssetBills",
},
"fetchOpenOrders": map[string]interface{} {
"method": "privateGetTradeOrdersPending",
},
"cancelOrders": map[string]interface{} {
"method": "privatePostTradeCancelBatchOrders",
},
"fetchCanceledOrders": map[string]interface{} {
"method": "privateGetTradeOrdersHistory",
},
"fetchClosedOrders": map[string]interface{} {
"method": "privateGetTradeOrdersHistory",
},
"withdraw": map[string]interface{} {
"password": nil,
"pwd": nil,
},
"exchangeType": map[string]interface{} {
"spot": "SPOT",
"swap": "SWAP",
"SPOT": "SPOT",
"SWAP": "SWAP",
},
},
})
}
/**
* @method
* @name blofin#fetchMarkets
* @description retrieves data on all markets for blofin
* @see https://blofin.com/docs#get-instruments
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} an array of objects representing market data
*/
func (this *blofin) FetchMarkets(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
response:= (<-this.PublicGetMarketInstruments(params))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseMarkets(data)
return nil
}()
return ch
}
func (this *blofin) ParseMarket(market interface{}) interface{} {
var id interface{} = this.SafeString(market, "instId")
var typeVar interface{} = this.SafeStringLower(market, "instType")
var spot interface{} = (IsEqual(typeVar, "spot"))
var future interface{} = (IsEqual(typeVar, "future"))
var swap interface{} = (IsEqual(typeVar, "swap"))
var option interface{} = (IsEqual(typeVar, "option"))
var contract interface{} = IsTrue(swap) || IsTrue(future)
var baseId interface{} = this.SafeString(market, "baseCurrency")
var quoteId interface{} = this.SafeString(market, "quoteCurrency")
var settleId interface{} = this.SafeString(market, "quoteCurrency")
var settle interface{} = this.SafeCurrencyCode(settleId)
var base interface{} = this.SafeCurrencyCode(baseId)
var quote interface{} = this.SafeCurrencyCode(quoteId)
var symbol interface{} = Add(Add(base, "/"), quote)
if IsTrue(swap) {
symbol = Add(Add(symbol, ":"), settle)
}
var expiry interface{} = nil
var strikePrice interface{} = nil
var optionType interface{} = nil
var tickSize interface{} = this.SafeString(market, "tickSize")
var fees interface{} = this.SafeDict2(this.Fees, typeVar, "trading", map[string]interface{} {})
var taker interface{} = this.SafeNumber(fees, "taker")
var maker interface{} = this.SafeNumber(fees, "maker")
var maxLeverage interface{} = this.SafeString(market, "maxLeverage", "100")
maxLeverage = Precise.StringMax(maxLeverage, "1")
var isActive interface{} = (IsEqual(this.SafeString(market, "state"), "live"))
return this.SafeMarketStructure(map[string]interface{} {
"id": id,
"symbol": symbol,
"base": base,
"quote": quote,
"baseId": baseId,
"quoteId": quoteId,
"settle": settle,
"settleId": settleId,
"type": typeVar,
"spot": spot,
"option": option,
"margin": IsTrue(spot) && IsTrue((Precise.StringGt(maxLeverage, "1"))),
"swap": swap,
"future": future,
"active": isActive,
"taker": taker,
"maker": maker,
"contract": contract,
"linear": Ternary(IsTrue(contract), (IsEqual(quoteId, settleId)), nil),
"inverse": Ternary(IsTrue(contract), (IsEqual(baseId, settleId)), nil),
"contractSize": Ternary(IsTrue(contract), this.SafeNumber(market, "contractValue"), nil),
"expiry": expiry,
"expiryDatetime": expiry,
"strike": strikePrice,
"optionType": optionType,
"created": this.SafeInteger(market, "listTime"),
"precision": map[string]interface{} {
"amount": this.SafeNumber(market, "lotSize"),
"price": this.ParseNumber(tickSize),
},
"limits": map[string]interface{} {
"leverage": map[string]interface{} {
"min": this.ParseNumber("1"),
"max": this.ParseNumber(maxLeverage),
},
"amount": map[string]interface{} {
"min": this.SafeNumber(market, "minSize"),
"max": nil,
},
"price": map[string]interface{} {
"min": nil,
"max": nil,
},
"cost": map[string]interface{} {
"min": nil,
"max": nil,
},
},
"info": market,
})
}
/**
* @method
* @name blofin#fetchOrderBook
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @see https://blofin.com/docs#get-order-book
* @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 *blofin) 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
retRes5828 := (<-this.LoadMarkets())
PanicOnError(retRes5828)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
}
limit = Ternary(IsTrue((IsEqual(limit, nil))), 50, limit)
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "size", limit) // max 100
}
response:= (<-this.PublicGetMarketBooks(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "code": "0",
// "msg": "",
// "data": [
// {
// "asks": [
// ["0.07228","4.211619","0","2"], // price, amount, liquidated orders, total open orders
// ["0.0723","299.880364","0","2"],
// ["0.07231","3.72832","0","1"],
// ],
// "bids": [
// ["0.07221","18.5","0","1"],
// ["0.0722","18.5","0","1"],
// ["0.07219","0.505407","0","1"],
// ],
// "ts": "1621438475342"
// }
// ]
// }
//
var data interface{} = this.SafeList(response, "data", []interface{}{})
var first interface{} = this.SafeDict(data, 0, map[string]interface{} {})
var timestamp interface{} = this.SafeInteger(first, "ts")
ch <- this.ParseOrderBook(first, symbol, timestamp)
return nil
}()
return ch
}
func (this *blofin) ParseTicker(ticker interface{}, optionalArgs ...interface{}) interface{} {
//
// response similar for REST & WS
//
// {
// instId: "ADA-USDT",
// ts: "1707736811486",
// last: "0.5315",
// lastSize: "4",
// askPrice: "0.5318",
// askSize: "248",
// bidPrice: "0.5315",
// bidSize: "63",
// open24h: "0.5555",
// high24h: "0.5563",
// low24h: "0.5315",
// volCurrency24h: "198560100",
// vol24h: "1985601",
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var timestamp interface{} = this.SafeInteger(ticker, "ts")
var marketId interface{} = this.SafeString(ticker, "instId")
market = this.SafeMarket(marketId, market, "-")
var symbol interface{} = GetValue(market, "symbol")
var last interface{} = this.SafeString(ticker, "last")
var open interface{} = this.SafeString(ticker, "open24h")
var spot interface{} = this.SafeBool(market, "spot", false)
var quoteVolume interface{} = Ternary(IsTrue(spot), this.SafeString(ticker, "volCurrency24h"), nil)
var baseVolume interface{} = this.SafeString(ticker, "vol24h")
var high interface{} = this.SafeString(ticker, "high24h")
var low interface{} = this.SafeString(ticker, "low24h")
return this.SafeTicker(map[string]interface{} {
"symbol": symbol,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"high": high,
"low": low,
"bid": this.SafeString(ticker, "bidPrice"),
"bidVolume": this.SafeString(ticker, "bidSize"),
"ask": this.SafeString(ticker, "askPrice"),
"askVolume": this.SafeString(ticker, "askSize"),
"vwap": nil,
"open": open,
"close": last,
"last": last,
"previousClose": nil,
"change": nil,
"percentage": nil,
"average": nil,
"baseVolume": baseVolume,
"quoteVolume": quoteVolume,
"indexPrice": this.SafeString(ticker, "indexPrice"),
"markPrice": this.SafeString(ticker, "markPrice"),
"info": ticker,
}, market)
}
/**
* @method
* @name blofin#fetchTicker
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @see https://blofin.com/docs#get-tickers
* @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 *blofin) 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
retRes6868 := (<-this.LoadMarkets())
PanicOnError(retRes6868)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
}
response:= (<-this.PublicGetMarketTickers(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
var first interface{} = this.SafeDict(data, 0, map[string]interface{} {})
ch <- this.ParseTicker(first, market)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchMarkPrice
* @description fetches mark price for the market
* @see https://docs.blofin.com/index.html#get-mark-price
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.subType] "linear" or "inverse"
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
func (this *blofin) FetchMarkPrice(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
retRes7088 := (<-this.LoadMarkets())
PanicOnError(retRes7088)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"symbol": GetValue(market, "id"),
}
response:= (<-this.PublicGetMarketMarkPrice(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
var first interface{} = this.SafeDict(data, 0, map[string]interface{} {})
ch <- this.ParseTicker(first, market)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchTickers
* @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
* @see https://blofin.com/docs#get-tickers
* @param {string[]} [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 *blofin) 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
retRes7298 := (<-this.LoadMarkets())
PanicOnError(retRes7298)
symbols = this.MarketSymbols(symbols)
response:= (<-this.PublicGetMarketTickers(params))
PanicOnError(response)
var tickers interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseTickers(tickers, symbols)
return nil
}()
return ch
}
func (this *blofin) ParseTrade(trade interface{}, optionalArgs ...interface{}) interface{} {
//
// fetch trades (response similar for REST & WS)
//
// {
// "tradeId": "3263934920",
// "instId": "LTC-USDT",
// "price": "67.87",
// "size": "1",
// "side": "buy",
// "ts": "1707232020854"
// }
//
// my trades
// {
// "instId": "LTC-USDT",
// "tradeId": "1440847",
// "orderId": "2075705202",
// "fillPrice": "67.850000000000000000",
// "fillSize": "1.000000000000000000",
// "fillPnl": "0.000000000000000000",
// "side": "buy",
// "positionSide": "net",
// "fee": "0.040710000000000000",
// "ts": "1707224678878",
// "brokerId": ""
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var id interface{} = this.SafeString(trade, "tradeId")
var marketId interface{} = this.SafeString(trade, "instId")
market = this.SafeMarket(marketId, market, "-")
var symbol interface{} = GetValue(market, "symbol")
var timestamp interface{} = this.SafeInteger(trade, "ts")
var price interface{} = this.SafeString2(trade, "price", "fillPrice")
var amount interface{} = this.SafeString2(trade, "size", "fillSize")
var side interface{} = this.SafeString(trade, "side")
var orderId interface{} = this.SafeString(trade, "orderId")
var feeCost interface{} = this.SafeString(trade, "fee")
var fee interface{} = nil
if IsTrue(!IsEqual(feeCost, nil)) {
fee = map[string]interface{} {
"cost": feeCost,
"currency": GetValue(market, "settle"),
}
}
return this.SafeTrade(map[string]interface{} {
"info": trade,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"symbol": symbol,
"id": id,
"order": orderId,
"type": nil,
"takerOrMaker": nil,
"side": side,
"price": price,
"amount": amount,
"cost": nil,
"fee": fee,
}, market)
}
/**
* @method
* @name blofin#fetchTrades
* @description get the list of most recent trades for a particular symbol
* @see https://blofin.com/docs#get-trades
* @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
* @param {boolean} [params.paginate] *only applies to publicGetMarketHistoryTrades* default false, when true will automatically paginate by calling this endpoint multiple times
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
*/
func (this *blofin) 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
retRes8118 := (<-this.LoadMarkets())
PanicOnError(retRes8118)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchTrades", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes81519 := (<-this.FetchPaginatedCallCursor("fetchTrades", symbol, since, limit, params, "tradeId", "after", nil, 100))
PanicOnError(retRes81519)
ch <- retRes81519
return nil
}
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
}
var response interface{} = nil
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit) // default 100
}
var method interface{} = nil
methodparamsVariable := this.HandleOptionAndParams(params, "fetchTrades", "method", "publicGetMarketTrades");
method = GetValue(methodparamsVariable,0);
params = GetValue(methodparamsVariable,1)
if IsTrue(IsEqual(method, "publicGetMarketTrades")) {
response = (<-this.PublicGetMarketTrades(this.Extend(request, params)))
PanicOnError(response)
}
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseTrades(data, market, since, limit)
return nil
}()
return ch
}
func (this *blofin) ParseOHLCV(ohlcv interface{}, optionalArgs ...interface{}) interface{} {
//
// [
// "1678928760000", // timestamp
// "24341.4", // open
// "24344", // high
// "24313.2", // low
// "24323", // close
// "628", // contract volume
// "2.5819", // base volume
// "62800", // quote volume
// "0" // candlestick state
// ]
//
market := GetArg(optionalArgs, 0, nil)
_ = market
return []interface{}{this.SafeInteger(ohlcv, 0), this.SafeNumber(ohlcv, 1), this.SafeNumber(ohlcv, 2), this.SafeNumber(ohlcv, 3), this.SafeNumber(ohlcv, 4), this.SafeNumber(ohlcv, 6)}
}
/**
* @method
* @name blofin#fetchOHLCV
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://blofin.com/docs#get-candlesticks
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] timestamp in ms of the latest candle to fetch
* @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 *blofin) 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
retRes8738 := (<-this.LoadMarkets())
PanicOnError(retRes8738)
var market interface{} = this.Market(symbol)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchOHLCV", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes87819 := (<-this.FetchPaginatedCallDeterministic("fetchOHLCV", symbol, since, limit, timeframe, params, 100))
PanicOnError(retRes87819)
ch <- retRes87819
return nil
}
if IsTrue(IsEqual(limit, nil)) {
limit = 100 // default 100, max 100
}
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
"bar": this.SafeString(this.Timeframes, timeframe, timeframe),
"limit": limit,
}
var until interface{} = this.SafeInteger(params, "until")
if IsTrue(!IsEqual(until, nil)) {
AddElementToObject(request, "after", until)
params = this.Omit(params, "until")
}
var response interface{} = nil
response = (<-this.PublicGetMarketCandles(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseOHLCVs(data, market, timeframe, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchFundingRateHistory
* @description fetches historical funding rate prices
* @see https://blofin.com/docs#get-funding-rate-history
* @param {string} symbol unified symbol of the market to fetch the funding rate history for
* @param {int} [since] timestamp in ms of the earliest funding rate to fetch
* @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} 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 {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
*/
func (this *blofin) FetchFundingRateHistory(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchFundingRateHistory() requires a symbol argument")))
}
retRes9158 := (<-this.LoadMarkets())
PanicOnError(retRes9158)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchFundingRateHistory", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes91919 := (<-this.FetchPaginatedCallDeterministic("fetchFundingRateHistory", symbol, since, limit, "8h", params))
PanicOnError(retRes91919)
ch <- retRes91919
return nil
}
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "before", mathMax(Subtract(since, 1), 0))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit)
}
response:= (<-this.PublicGetMarketFundingRateHistory(this.Extend(request, params)))
PanicOnError(response)
var rates interface{} = []interface{}{}
var data interface{} = this.SafeList(response, "data", []interface{}{})
for i := 0; IsLessThan(i, GetArrayLength(data)); i++ {
var rate interface{} = GetValue(data, i)
var timestamp interface{} = this.SafeInteger(rate, "fundingTime")
AppendToArray(&rates,map[string]interface{} {
"info": rate,
"symbol": GetValue(market, "symbol"),
"fundingRate": this.SafeNumber(rate, "fundingRate"),
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
})
}
var sorted interface{} = this.SortBy(rates, "timestamp")
ch <- this.FilterBySymbolSinceLimit(sorted, GetValue(market, "symbol"), since, limit)
return nil
}()
return ch
}
func (this *blofin) ParseFundingRate(contract interface{}, optionalArgs ...interface{}) interface{} {
//
// {
// "fundingRate": "0.00027815",
// "fundingTime": "1634256000000",
// "instId": "BTC-USD-SWAP",
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var marketId interface{} = this.SafeString(contract, "instId")
var symbol interface{} = this.SafeSymbol(marketId, market)
var fundingTime interface{} = this.SafeInteger(contract, "fundingTime")
// > The current interest is 0.
return map[string]interface{} {
"info": contract,
"symbol": symbol,
"markPrice": nil,
"indexPrice": nil,
"interestRate": this.ParseNumber("0"),
"estimatedSettlePrice": nil,
"timestamp": nil,
"datetime": nil,
"fundingRate": this.SafeNumber(contract, "fundingRate"),
"fundingTimestamp": fundingTime,
"fundingDatetime": this.Iso8601(fundingTime),
"nextFundingRate": nil,
"nextFundingTimestamp": nil,
"nextFundingDatetime": nil,
"previousFundingRate": nil,
"previousFundingTimestamp": nil,
"previousFundingDatetime": nil,
"interval": nil,
}
}
/**
* @method
* @name blofin#fetchFundingRate
* @description fetch the current funding rate
* @see https://blofin.com/docs#get-funding-rate
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
*/
func (this *blofin) FetchFundingRate(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
retRes9938 := (<-this.LoadMarkets())
PanicOnError(retRes9938)
var market interface{} = this.Market(symbol)
if !IsTrue(GetValue(market, "swap")) {
panic(ExchangeError(Add(this.Id, " fetchFundingRate() is only valid for swap markets")))
}
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
}
response:= (<-this.PublicGetMarketFundingRate(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "code": "0",
// "data": [
// {
// "fundingRate": "0.00027815",
// "fundingTime": "1634256000000",
// "instId": "BTC-USD-SWAP",
// }
// ],
// "msg": ""
// }
//
var data interface{} = this.SafeList(response, "data", []interface{}{})
var entry interface{} = this.SafeDict(data, 0, map[string]interface{} {})
ch <- this.ParseFundingRate(entry, market)
return nil
}()
return ch
}
func (this *blofin) ParseBalanceByType(response interface{}) interface{} {
var data interface{} = this.SafeList(response, "data")
if IsTrue(IsTrue((!IsEqual(data, nil))) && IsTrue(IsArray(data))) {
return this.ParseFundingBalance(response)
} else {
return this.ParseBalance(response)
}
}
func (this *blofin) ParseBalance(response interface{}) interface{} {
//
// "data" similar for REST & WS
//
// {
// "code": "0",
// "msg": "success",
// "data": {
// "ts": "1697021343571",
// "totalEquity": "10011254.077985990315787910",
// "isolatedEquity": "861.763132108800000000",
// "details": [
// {
// "currency": "USDT",
// "equity": "10014042.988958415234430699548",
// "balance": "10013119.885958415234430699",
// "ts": "1697021343571",
// "isolatedEquity": "862.003200000000000000048",
// "available": "9996399.4708691159703362725",
// "availableEquity": "9996399.4708691159703362725",
// "frozen": "15805.149672632597427761",
// "orderFrozen": "14920.994472632597427761",
// "equityUsd": "10011254.077985990315787910",
// "isolatedUnrealizedPnl": "-22.151999999999999999952",
// "bonus": "0" // present only in REST
// "unrealizedPnl": "0" // present only in WS
// }
// ]
// }
// }
//
var result interface{} = map[string]interface{} {
"info": response,
}
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
var timestamp interface{} = this.SafeInteger(data, "ts")
var details interface{} = this.SafeList(data, "details", []interface{}{})
for i := 0; IsLessThan(i, GetArrayLength(details)); i++ {
var balance interface{} = GetValue(details, i)
var currencyId interface{} = this.SafeString(balance, "currency")
var code interface{} = this.SafeCurrencyCode(currencyId)
var account interface{} = this.Account()
// it may be incorrect to use total, free and used for swap accounts
var eq interface{} = this.SafeString(balance, "equity")
var availEq interface{} = this.SafeString(balance, "available")
if IsTrue(IsTrue((IsEqual(eq, nil))) || IsTrue((IsEqual(availEq, nil)))) {
AddElementToObject(account, "free", this.SafeString(balance, "availableEquity"))
AddElementToObject(account, "used", this.SafeString(balance, "frozen"))
} else {
AddElementToObject(account, "total", eq)
AddElementToObject(account, "free", availEq)
}
AddElementToObject(result, code, account)
}
AddElementToObject(result, "timestamp", timestamp)
AddElementToObject(result, "datetime", this.Iso8601(timestamp))
return this.SafeBalance(result)
}
func (this *blofin) ParseFundingBalance(response interface{}) interface{} {
//
// {
// "code": "0",
// "msg": "success",
// "data": [
// {
// "currency": "USDT",
// "balance": "10012514.919418081548717298",
// "available": "9872132.414278782284622898",
// "frozen": "138556.471805965930761067",
// "bonus": "0"
// }
// ]
// }
//
var result interface{} = map[string]interface{} {
"info": response,
}
var data interface{} = this.SafeList(response, "data", []interface{}{})
for i := 0; IsLessThan(i, GetArrayLength(data)); i++ {
var balance interface{} = GetValue(data, i)
var currencyId interface{} = this.SafeString(balance, "currency")
var code interface{} = this.SafeCurrencyCode(currencyId)
var account interface{} = this.Account()
// it may be incorrect to use total, free and used for swap accounts
AddElementToObject(account, "total", this.SafeString(balance, "balance"))
AddElementToObject(account, "free", this.SafeString(balance, "available"))
AddElementToObject(account, "used", this.SafeString(balance, "frozen"))
AddElementToObject(result, code, account)
}
return this.SafeBalance(result)
}
func (this *blofin) ParseTradingFee(fee interface{}, optionalArgs ...interface{}) interface{} {
market := GetArg(optionalArgs, 0, nil)
_ = market
return map[string]interface{} {
"info": fee,
"symbol": this.SafeSymbol(nil, market),
"maker": this.ParseNumber(Precise.StringNeg(this.SafeString2(fee, "maker", "makerU"))),
"taker": this.ParseNumber(Precise.StringNeg(this.SafeString2(fee, "taker", "takerU"))),
"percentage": nil,
"tierBased": nil,
}
}
/**
* @method
* @name blofin#fetchBalance
* @description query for balance and get the amount of funds available for trading or funds locked in orders
* @see https://blofin.com/docs#get-balance
* @see https://blofin.com/docs#get-futures-account-balance
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.accountType] the type of account to fetch the balance for, either 'funding' or 'futures' or 'copy_trading' or 'earn'
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
*/
func (this *blofin) 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
retRes11418 := (<-this.LoadMarkets())
PanicOnError(retRes11418)
var accountType interface{} = nil
accountTypeparamsVariable := this.HandleOptionAndParams2(params, "fetchBalance", "accountType", "type");
accountType = GetValue(accountTypeparamsVariable,0);
params = GetValue(accountTypeparamsVariable,1)
var request interface{} = map[string]interface{} {}
var response interface{} = nil
if IsTrue(IsTrue(!IsEqual(accountType, nil)) && IsTrue(!IsEqual(accountType, "swap"))) {
var options interface{} = this.SafeDict(this.Options, "accountsByType", map[string]interface{} {})
var parsedAccountType interface{} = this.SafeString(options, accountType, accountType)
AddElementToObject(request, "accountType", parsedAccountType)
response = (<-this.PrivateGetAssetBalances(this.Extend(request, params)))
PanicOnError(response)
} else {
response = (<-this.PrivateGetAccountBalance(this.Extend(request, params)))
PanicOnError(response)
}
ch <- this.ParseBalanceByType(response)
return nil
}()
return ch
}
func (this *blofin) CreateOrderRequest(symbol interface{}, typeVar interface{}, side interface{}, amount interface{}, optionalArgs ...interface{}) interface{} {
price := GetArg(optionalArgs, 0, nil)
_ = price
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
"side": side,
"orderType": typeVar,
"size": this.AmountToPrecision(symbol, amount),
"brokerId": this.SafeString(this.Options, "brokerId", "ec6dd3a7dd982d0b"),
}
var marginMode interface{} = nil
marginModeparamsVariable := this.HandleMarginModeAndParams("createOrder", params, "cross");
marginMode = GetValue(marginModeparamsVariable,0);
params = GetValue(marginModeparamsVariable,1)
AddElementToObject(request, "marginMode", marginMode)
var timeInForce interface{} = this.SafeString(params, "timeInForce", "GTC")
var isMarketOrder interface{} = IsEqual(typeVar, "market")
params = this.Omit(params, []interface{}{"timeInForce"})
var ioc interface{} = IsTrue((IsEqual(timeInForce, "IOC"))) || IsTrue((IsEqual(typeVar, "ioc")))
var marketIOC interface{} = (IsTrue(isMarketOrder) && IsTrue(ioc))
if IsTrue(IsTrue(isMarketOrder) || IsTrue(marketIOC)) {
AddElementToObject(request, "orderType", "market")
} else {
AddElementToObject(request, "price", this.PriceToPrecision(symbol, price))
}
var postOnly interface{} = false
postOnlyparamsVariable := this.HandlePostOnly(isMarketOrder, IsEqual(typeVar, "post_only"), params);
postOnly = GetValue(postOnlyparamsVariable,0);
params = GetValue(postOnlyparamsVariable,1)
if IsTrue(postOnly) {
AddElementToObject(request, "type", "post_only")
}
var stopLoss interface{} = this.SafeDict(params, "stopLoss")
var takeProfit interface{} = this.SafeDict(params, "takeProfit")
params = this.Omit(params, []interface{}{"stopLoss", "takeProfit"})
var isStopLoss interface{} = !IsEqual(stopLoss, nil)
var isTakeProfit interface{} = !IsEqual(takeProfit, nil)
if IsTrue(IsTrue(isStopLoss) || IsTrue(isTakeProfit)) {
if IsTrue(isStopLoss) {
var slTriggerPrice interface{} = this.SafeString2(stopLoss, "triggerPrice", "stopPrice")
AddElementToObject(request, "slTriggerPrice", this.PriceToPrecision(symbol, slTriggerPrice))
var slOrderPrice interface{} = this.SafeString(stopLoss, "price", "-1")
AddElementToObject(request, "slOrderPrice", this.PriceToPrecision(symbol, slOrderPrice))
}
if IsTrue(isTakeProfit) {
var tpTriggerPrice interface{} = this.SafeString2(takeProfit, "triggerPrice", "stopPrice")
AddElementToObject(request, "tpTriggerPrice", this.PriceToPrecision(symbol, tpTriggerPrice))
var tpPrice interface{} = this.SafeString(takeProfit, "price", "-1")
AddElementToObject(request, "tpOrderPrice", this.PriceToPrecision(symbol, tpPrice))
}
}
return this.Extend(request, params)
}
func (this *blofin) ParseOrderStatus(status interface{}) interface{} {
var statuses interface{} = map[string]interface{} {
"canceled": "canceled",
"order_failed": "canceled",
"live": "open",
"partially_filled": "open",
"filled": "closed",
"effective": "closed",
}
return this.SafeString(statuses, status, status)
}
func (this *blofin) ParseOrder(order interface{}, optionalArgs ...interface{}) interface{} {
//
// response similar for REST & WS
//
// {
// "orderId": "2075628533",
// "clientOrderId": "",
// "instId": "LTC-USDT",
// "marginMode": "cross",
// "positionSide": "net",
// "side": "buy",
// "orderType": "market",
// "price": "0.000000000000000000",
// "size": "1.000000000000000000",
// "reduceOnly": "true",
// "leverage": "3",
// "state": "filled",
// "filledSize": "1.000000000000000000",
// "pnl": "-0.050000000000000000",
// "averagePrice": "68.110000000000000000",
// "fee": "0.040866000000000000",
// "createTime": "1706891359010",
// "updateTime": "1706891359098",
// "orderCategory": "normal",
// "tpTriggerPrice": null,
// "tpOrderPrice": null,
// "slTriggerPrice": null,
// "slOrderPrice": null,
// "cancelSource": "not_canceled",
// "cancelSourceReason": null,
// "brokerId": "ec6dd3a7dd982d0b"
// "filled_amount": "1.000000000000000000", // filledAmount in "ws" watchOrders
// "cancelSource": "", // only in WS
// "instType": "SWAP", // only in WS
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var id interface{} = this.SafeString2(order, "tpslId", "orderId")
var timestamp interface{} = this.SafeInteger(order, "createTime")
var lastUpdateTimestamp interface{} = this.SafeInteger(order, "updateTime")
var lastTradeTimestamp interface{} = this.SafeInteger(order, "fillTime")
var side interface{} = this.SafeString(order, "side")
var typeVar interface{} = this.SafeString(order, "orderType")
var postOnly interface{} = nil
var timeInForce interface{} = nil
if IsTrue(IsEqual(typeVar, "post_only")) {
postOnly = true
typeVar = "limit"
} else if IsTrue(IsEqual(typeVar, "fok")) {
timeInForce = "FOK"
typeVar = "limit"
} else if IsTrue(IsEqual(typeVar, "ioc")) {
timeInForce = "IOC"
typeVar = "limit"
}
var marketId interface{} = this.SafeString(order, "instId")
market = this.SafeMarket(marketId, market)
var symbol interface{} = this.SafeSymbol(marketId, market, "-")
var filled interface{} = this.SafeString(order, "filledSize")
var price interface{} = this.SafeString2(order, "px", "price")
var average interface{} = this.SafeString(order, "averagePrice")
var status interface{} = this.ParseOrderStatus(this.SafeString(order, "state"))
var feeCostString interface{} = this.SafeString(order, "fee")
var amount interface{} = this.SafeString(order, "size")
var leverage interface{} = this.SafeString(order, "leverage", "1")
var contractSize interface{} = this.SafeString(market, "contractSize")
var baseAmount interface{} = Precise.StringMul(contractSize, filled)
var cost interface{} = nil
if IsTrue(!IsEqual(average, nil)) {
cost = Precise.StringMul(average, baseAmount)
cost = Precise.StringDiv(cost, leverage)
}
// spot market buy: "sz" can refer either to base currency units or to quote currency units
var fee interface{} = nil
if IsTrue(!IsEqual(feeCostString, nil)) {
var feeCostSigned interface{} = Precise.StringAbs(feeCostString)
var feeCurrencyId interface{} = this.SafeString(order, "feeCcy", "USDT")
var feeCurrencyCode interface{} = this.SafeCurrencyCode(feeCurrencyId)
fee = map[string]interface{} {
"cost": this.ParseNumber(feeCostSigned),
"currency": feeCurrencyCode,
}
}
var clientOrderId interface{} = this.SafeString(order, "clientOrderId")
if IsTrue(IsTrue((!IsEqual(clientOrderId, nil))) && IsTrue((IsLessThan(GetLength(clientOrderId), 1)))) {
clientOrderId = nil // fix empty clientOrderId string
}
var stopLossTriggerPrice interface{} = this.SafeNumber(order, "slTriggerPrice")
var stopLossPrice interface{} = this.SafeNumber(order, "slOrderPrice")
var takeProfitTriggerPrice interface{} = this.SafeNumber(order, "tpTriggerPrice")
var takeProfitPrice interface{} = this.SafeNumber(order, "tpOrderPrice")
var reduceOnlyRaw interface{} = this.SafeString(order, "reduceOnly")
var reduceOnly interface{} = (IsEqual(reduceOnlyRaw, "true"))
return this.SafeOrder(map[string]interface{} {
"info": order,
"id": id,
"clientOrderId": clientOrderId,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"lastTradeTimestamp": lastTradeTimestamp,
"lastUpdateTimestamp": lastUpdateTimestamp,
"symbol": symbol,
"type": typeVar,
"timeInForce": timeInForce,
"postOnly": postOnly,
"side": side,
"price": price,
"stopLossTriggerPrice": stopLossTriggerPrice,
"takeProfitTriggerPrice": takeProfitTriggerPrice,
"stopLossPrice": stopLossPrice,
"takeProfitPrice": takeProfitPrice,
"average": average,
"cost": cost,
"amount": amount,
"filled": filled,
"remaining": nil,
"status": status,
"fee": fee,
"trades": nil,
"reduceOnly": reduceOnly,
}, market)
}
/**
* @method
* @name blofin#createOrder
* @description create a trade order
* @see https://blofin.com/docs#place-order
* @see https://blofin.com/docs#place-tpsl-order
* @param {string} symbol unified symbol of the market to create an order in
* @param {string} type 'market' or 'limit' or 'post_only' or 'ioc' or 'fok'
* @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.reduceOnly] a mark to reduce the position size for margin, swap and future orders
* @param {bool} [params.postOnly] true to place a post only order
* @param {string} [params.marginMode] 'cross' or 'isolated', default is 'cross'
* @param {float} [params.stopLossPrice] stop loss trigger price (will use privatePostTradeOrderTpsl)
* @param {float} [params.takeProfitPrice] take profit trigger price (will use privatePostTradeOrderTpsl)
* @param {string} [params.positionSide] *stopLossPrice/takeProfitPrice orders only* 'long' or 'short' or 'net' default is 'net'
* @param {string} [params.clientOrderId] a unique id for the order
* @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
* @param {float} [params.takeProfit.triggerPrice] take profit trigger price
* @param {float} [params.takeProfit.price] take profit order price (if not provided the order will be a market order)
* @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered
* @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
* @param {float} [params.stopLoss.price] stop loss order price (if not provided the order will be a market order)
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *blofin) 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
retRes13698 := (<-this.LoadMarkets())
PanicOnError(retRes13698)
var market interface{} = this.Market(symbol)
var tpsl interface{} = this.SafeBool(params, "tpsl", false)
params = this.Omit(params, "tpsl")
var method interface{} = nil
methodparamsVariable := this.HandleOptionAndParams(params, "createOrder", "method", "privatePostTradeOrder");
method = GetValue(methodparamsVariable,0);
params = GetValue(methodparamsVariable,1)
var isStopLossPriceDefined interface{} = !IsEqual(this.SafeString(params, "stopLossPrice"), nil)
var isTakeProfitPriceDefined interface{} = !IsEqual(this.SafeString(params, "takeProfitPrice"), nil)
var isType2Order interface{} = (IsTrue(isStopLossPriceDefined) || IsTrue(isTakeProfitPriceDefined))
var response interface{} = nil
if IsTrue(IsTrue(IsTrue(tpsl) || IsTrue((IsEqual(method, "privatePostTradeOrderTpsl")))) || IsTrue(isType2Order)) {
var tpslRequest interface{} = this.CreateTpslOrderRequest(symbol, typeVar, side, amount, price, params)
response = (<-this.PrivatePostTradeOrderTpsl(tpslRequest))
PanicOnError(response)
} else {
var request interface{} = this.CreateOrderRequest(symbol, typeVar, side, amount, price, params)
response = (<-this.PrivatePostTradeOrder(request))
PanicOnError(response)
}
var data interface{} = this.SafeList(response, "data", []interface{}{})
var first interface{} = this.SafeDict(data, 0)
var order interface{} = this.ParseOrder(first, market)
AddElementToObject(order, "type", typeVar)
AddElementToObject(order, "side", side)
ch <- order
return nil
}()
return ch
}
func (this *blofin) CreateTpslOrderRequest(symbol interface{}, typeVar interface{}, side interface{}, optionalArgs ...interface{}) interface{} {
amount := GetArg(optionalArgs, 0, nil)
_ = amount
price := GetArg(optionalArgs, 1, nil)
_ = price
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
var market interface{} = this.Market(symbol)
var positionSide interface{} = this.SafeString(params, "positionSide", "net")
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
"side": side,
"positionSide": positionSide,
"brokerId": this.SafeString(this.Options, "brokerId", "ec6dd3a7dd982d0b"),
}
if IsTrue(!IsEqual(amount, nil)) {
AddElementToObject(request, "size", this.AmountToPrecision(symbol, amount))
}
var marginMode interface{} = this.SafeString(params, "marginMode", "cross") // cross or isolated
if IsTrue(IsTrue(!IsEqual(marginMode, "cross")) && IsTrue(!IsEqual(marginMode, "isolated"))) {
panic(BadRequest(Add(this.Id, " createTpslOrder() requires a marginMode parameter that must be either cross or isolated")))
}
var stopLossPrice interface{} = this.SafeString(params, "stopLossPrice")
var takeProfitPrice interface{} = this.SafeString(params, "takeProfitPrice")
if IsTrue(!IsEqual(stopLossPrice, nil)) {
AddElementToObject(request, "slTriggerPrice", this.PriceToPrecision(symbol, stopLossPrice))
if IsTrue(IsEqual(typeVar, "market")) {
AddElementToObject(request, "slOrderPrice", "-1")
} else {
AddElementToObject(request, "slOrderPrice", this.PriceToPrecision(symbol, price))
}
} else if IsTrue(!IsEqual(takeProfitPrice, nil)) {
AddElementToObject(request, "tpTriggerPrice", this.PriceToPrecision(symbol, takeProfitPrice))
if IsTrue(IsEqual(typeVar, "market")) {
AddElementToObject(request, "tpOrderPrice", "-1")
} else {
AddElementToObject(request, "tpOrderPrice", this.PriceToPrecision(symbol, price))
}
}
AddElementToObject(request, "marginMode", marginMode)
params = this.Omit(params, []interface{}{"stopLossPrice", "takeProfitPrice"})
return this.Extend(request, params)
}
/**
* @method
* @name blofin#cancelOrder
* @description cancels an open order
* @see https://blofin.com/docs#cancel-order
* @see https://blofin.com/docs#cancel-tpsl-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 {boolean} [params.trigger] True if cancelling a trigger/conditional order/tp sl orders
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *blofin) CancelOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " cancelOrder() requires a symbol argument")))
}
retRes14488 := (<-this.LoadMarkets())
PanicOnError(retRes14488)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
}
var isTrigger interface{} = this.SafeBoolN(params, []interface{}{"stop", "trigger", "tpsl"}, false)
var clientOrderId interface{} = this.SafeString(params, "clientOrderId")
if IsTrue(!IsEqual(clientOrderId, nil)) {
AddElementToObject(request, "clientOrderId", clientOrderId)
} else {
if !IsTrue(isTrigger) {
AddElementToObject(request, "orderId", ToString(id))
} else {
AddElementToObject(request, "tpslId", ToString(id))
}
}
var query interface{} = this.Omit(params, []interface{}{"orderId", "clientOrderId", "stop", "trigger", "tpsl"})
if IsTrue(isTrigger) {
tpslResponse:= (<-this.CancelOrders([]interface{}{id}, symbol, params))
PanicOnError(tpslResponse)
var first interface{} = this.SafeDict(tpslResponse, 0)
ch <- first
return nil
}
response:= (<-this.PrivatePostTradeCancelOrder(this.Extend(request, query)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
var order interface{} = this.SafeDict(data, 0)
ch <- this.ParseOrder(order, market)
return nil
}()
return ch
}
/**
* @method
* @name blofin#createOrders
* @description create a list of trade orders
* @see https://blofin.com/docs#place-multiple-orders
* @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
* @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 *blofin) CreateOrders(orders 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
retRes14868 := (<-this.LoadMarkets())
PanicOnError(retRes14868)
var ordersRequests interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(orders)); i++ {
var rawOrder interface{} = GetValue(orders, i)
var marketId interface{} = this.SafeString(rawOrder, "symbol")
var typeVar interface{} = this.SafeString(rawOrder, "type")
var side interface{} = this.SafeString(rawOrder, "side")
var amount interface{} = this.SafeValue(rawOrder, "amount")
var price interface{} = this.SafeValue(rawOrder, "price")
var orderParams interface{} = this.SafeDict(rawOrder, "params", map[string]interface{} {})
var extendedParams interface{} = this.Extend(orderParams, params) // the request does not accept extra params since it's a list, so we're extending each order with the common params
var orderRequest interface{} = this.CreateOrderRequest(marketId, typeVar, side, amount, price, extendedParams)
AppendToArray(&ordersRequests,orderRequest)
}
response:= (<-this.PrivatePostTradeBatchOrders(ordersRequests))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseOrders(data)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchOpenOrders
* @description Fetch orders that are still open
* @see https://blofin.com/docs#get-active-orders
* @see https://blofin.com/docs#get-active-tpsl-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 {bool} [params.trigger] True if fetching trigger or conditional orders
* @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 {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *blofin) 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
retRes15208 := (<-this.LoadMarkets())
PanicOnError(retRes15208)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchOpenOrders", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes152419 := (<-this.FetchPaginatedCallDynamic("fetchOpenOrders", symbol, since, limit, params))
PanicOnError(retRes152419)
ch <- retRes152419
return nil
}
var request interface{} = map[string]interface{} {}
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
AddElementToObject(request, "instId", GetValue(market, "id"))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit) // default 100, max 100
}
var isTrigger interface{} = this.SafeBoolN(params, []interface{}{"stop", "trigger", "tpsl", "TPSL"}, false)
var method interface{} = nil
methodparamsVariable := this.HandleOptionAndParams(params, "fetchOpenOrders", "method", "privateGetTradeOrdersPending");
method = GetValue(methodparamsVariable,0);
params = GetValue(methodparamsVariable,1)
var query interface{} = this.Omit(params, []interface{}{"method", "stop", "trigger", "tpsl", "TPSL"})
var response interface{} = nil
if IsTrue(IsTrue(isTrigger) || IsTrue((IsEqual(method, "privateGetTradeOrdersTpslPending")))) {
response = (<-this.PrivateGetTradeOrdersTpslPending(this.Extend(request, query)))
PanicOnError(response)
} else {
response = (<-this.PrivateGetTradeOrdersPending(this.Extend(request, query)))
PanicOnError(response)
}
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseOrders(data, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchMyTrades
* @description fetch all trades made by the user
* @see https://blofin.com/docs#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 time to retrieve trades for
* @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 {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
func (this *blofin) 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
retRes15648 := (<-this.LoadMarkets())
PanicOnError(retRes15648)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchMyTrades", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes156819 := (<-this.FetchPaginatedCallDynamic("fetchMyTrades", symbol, since, limit, params))
PanicOnError(retRes156819)
ch <- retRes156819
return nil
}
var request interface{} = map[string]interface{} {}
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
AddElementToObject(request, "instId", GetValue(market, "id"))
}
requestparamsVariable := this.HandleUntilOption("end", request, params);
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit) // default 100, max 100
}
response:= (<-this.PrivateGetTradeFillsHistory(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseTrades(data, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchDeposits
* @description fetch all deposits made to an account
* @see https://blofin.com/docs#get-deposite-history
* @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] the latest time in ms to fetch entries for
* @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 {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *blofin) FetchDeposits(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
code := GetArg(optionalArgs, 0, nil)
_ = code
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes16008 := (<-this.LoadMarkets())
PanicOnError(retRes16008)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchDeposits", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes160419 := (<-this.FetchPaginatedCallDynamic("fetchDeposits", code, since, limit, params))
PanicOnError(retRes160419)
ch <- retRes160419
return nil
}
var request interface{} = map[string]interface{} {}
var currency interface{} = nil
if IsTrue(!IsEqual(code, nil)) {
currency = this.Currency(code)
AddElementToObject(request, "currency", GetValue(currency, "id"))
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "before", mathMax(Subtract(since, 1), 0))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit) // default 100, max 100
}
requestparamsVariable := this.HandleUntilOption("after", request, params);
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
response:= (<-this.PrivateGetAssetDepositHistory(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseTransactions(data, currency, since, limit, params)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchWithdrawals
* @description fetch all withdrawals made from an account
* @see https://blofin.com/docs#get-withdraw-history
* @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] the latest time in ms to fetch entries for
* @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 {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
*/
func (this *blofin) 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
retRes16398 := (<-this.LoadMarkets())
PanicOnError(retRes16398)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchWithdrawals", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes164319 := (<-this.FetchPaginatedCallDynamic("fetchWithdrawals", code, since, limit, params))
PanicOnError(retRes164319)
ch <- retRes164319
return nil
}
var request interface{} = map[string]interface{} {}
var currency interface{} = nil
if IsTrue(!IsEqual(code, nil)) {
currency = this.Currency(code)
AddElementToObject(request, "currency", GetValue(currency, "id"))
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "before", mathMax(Subtract(since, 1), 0))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit) // default 100, max 100
}
requestparamsVariable := this.HandleUntilOption("after", request, params);
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
response:= (<-this.PrivateGetAssetWithdrawalHistory(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseTransactions(data, currency, since, limit, params)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchLedger
* @description fetch the history of changes, actions done by the user or operations that altered the balance of the user
* @see https://blofin.com/docs#get-funds-transfer-history
* @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 {string} [params.marginMode] 'cross' or 'isolated'
* @param {int} [params.until] the latest time in ms to fetch entries for
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger}
*/
func (this *blofin) FetchLedger(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
retRes16798 := (<-this.LoadMarkets())
PanicOnError(retRes16798)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchLedger", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes168319 := (<-this.FetchPaginatedCallDynamic("fetchLedger", code, since, limit, params))
PanicOnError(retRes168319)
ch <- retRes168319
return nil
}
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit)
}
var currency interface{} = nil
if IsTrue(!IsEqual(code, nil)) {
currency = this.Currency(code)
AddElementToObject(request, "currency", GetValue(currency, "id"))
}
requestparamsVariable := this.HandleUntilOption("end", request, params);
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
var response interface{} = nil
response = (<-this.PrivateGetAssetBills(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseLedger(data, currency, since, limit)
return nil
}()
return ch
}
func (this *blofin) ParseTransaction(transaction interface{}, optionalArgs ...interface{}) interface{} {
//
//
// fetchDeposits
//
// {
// "currency": "USDT",
// "chain": "TRC20",
// "address": "TGfJLtnsh3B9EqekFEBZ1nR14QanBUf5Bi",
// "txId": "892f4e0c32268b29b2e541ef30d32a30bbf10f902adcc4b1428319ed7c3758fd",
// "type": "0",
// "amount": "86.975843",
// "state": "1",
// "ts": "1703163304153",
// "tag": null,
// "confirm": "16",
// "depositId": "36c8e2a7ea184a219de72215a696acaf"
// }
// fetchWithdrawals
// {
// "currency": "USDT",
// "chain": "TRC20",
// "address": "TYgB3sVXHPEDQUu288EG1uMFh9Pk2swLgW",
// "txId": "1fd5ac52df414d7ea66194cadd9a5b4d2422c2b9720037f66d98207f9858fd96",
// "type": "0",
// "amount": "9",
// "fee": "1",
// "feeCurrency": "USDT",
// "state": "3",
// "clientId": null,
// "ts": "1707217439351",
// "tag": null,
// "memo": null,
// "withdrawId": "e0768698cfdf4aee8e54654c3775914b"
// }
//
currency := GetArg(optionalArgs, 0, nil)
_ = currency
var typeVar interface{} = nil
var id interface{} = nil
var withdrawalId interface{} = this.SafeString(transaction, "withdrawId")
var depositId interface{} = this.SafeString(transaction, "depositId")
var addressTo interface{} = this.SafeString(transaction, "address")
var address interface{} = addressTo
var tagTo interface{} = this.SafeString(transaction, "tag")
if IsTrue(!IsEqual(withdrawalId, nil)) {
typeVar = "withdrawal"
id = withdrawalId
} else {
id = depositId
typeVar = "deposit"
}
var currencyId interface{} = this.SafeString(transaction, "currency")
var code interface{} = this.SafeCurrencyCode(currencyId)
var amount interface{} = this.SafeNumber(transaction, "amount")
var status interface{} = this.ParseTransactionStatus(this.SafeString(transaction, "state"))
var txid interface{} = this.SafeString(transaction, "txId")
var timestamp interface{} = this.SafeInteger(transaction, "ts")
var feeCurrencyId interface{} = this.SafeString(transaction, "feeCurrency")
var feeCode interface{} = this.SafeCurrencyCode(feeCurrencyId)
var feeCost interface{} = this.SafeNumber(transaction, "fee")
return map[string]interface{} {
"info": transaction,
"id": id,
"currency": code,
"amount": amount,
"network": nil,
"addressFrom": nil,
"addressTo": addressTo,
"address": address,
"tagFrom": nil,
"tagTo": tagTo,
"tag": tagTo,
"status": status,
"type": typeVar,
"updated": nil,
"txid": txid,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"internal": nil,
"comment": nil,
"fee": map[string]interface{} {
"currency": feeCode,
"cost": feeCost,
},
}
}
func (this *blofin) ParseTransactionStatus(status interface{}) interface{} {
var statuses interface{} = map[string]interface{} {
"0": "pending",
"1": "ok",
"2": "failed",
"3": "pending",
}
return this.SafeString(statuses, status, status)
}
func (this *blofin) ParseLedgerEntryType(typeVar interface{}) interface{} {
var types interface{} = map[string]interface{} {
"1": "transfer",
"2": "trade",
"3": "trade",
"4": "rebate",
"5": "trade",
"6": "transfer",
"7": "trade",
"8": "fee",
"9": "trade",
"10": "trade",
"11": "trade",
}
return this.SafeString(types, typeVar, typeVar)
}
func (this *blofin) ParseLedgerEntry(item interface{}, optionalArgs ...interface{}) interface{} {
currency := GetArg(optionalArgs, 0, nil)
_ = currency
var currencyId interface{} = this.SafeString(item, "currency")
var code interface{} = this.SafeCurrencyCode(currencyId, currency)
currency = this.SafeCurrency(currencyId, currency)
var timestamp interface{} = this.SafeInteger(item, "ts")
return this.SafeLedgerEntry(map[string]interface{} {
"info": item,
"id": this.SafeString(item, "transferId"),
"direction": nil,
"account": nil,
"referenceId": this.SafeString(item, "clientId"),
"referenceAccount": nil,
"type": this.ParseLedgerEntryType(this.SafeString(item, "type")),
"currency": code,
"amount": this.SafeNumber(item, "amount"),
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"before": nil,
"after": nil,
"status": "ok",
"fee": nil,
}, currency)
}
func (this *blofin) ParseIds(ids interface{}) interface{} {
/**
* @ignore
* @method
* @name blofin#parseIds
* @param {string[]|string} ids order ids
* @returns {string[]} list of order ids
*/
if IsTrue(IsString(ids)) {
return Split(ids, ",")
} else {
return ids
}
}
/**
* @method
* @name blofin#cancelOrders
* @description cancel multiple orders
* @see https://blofin.com/docs#cancel-multiple-orders
* @param {string[]} ids order ids
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.trigger] whether the order is a stop/trigger order
* @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *blofin) CancelOrders(ids interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
// TODO : the original endpoint signature differs, according to that you can skip individual symbol and assign ids in batch. At this moment, `params` is not being used too.
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " cancelOrders() requires a symbol argument")))
}
retRes18708 := (<-this.LoadMarkets())
PanicOnError(retRes18708)
var market interface{} = this.Market(symbol)
var request interface{} = []interface{}{}
var options interface{} = this.SafeDict(this.Options, "cancelOrders", map[string]interface{} {})
var defaultMethod interface{} = this.SafeString(options, "method", "privatePostTradeCancelBatchOrders")
var method interface{} = this.SafeString(params, "method", defaultMethod)
var clientOrderIds interface{} = this.ParseIds(this.SafeValue(params, "clientOrderId"))
var tpslIds interface{} = this.ParseIds(this.SafeValue(params, "tpslId"))
var trigger interface{} = this.SafeBoolN(params, []interface{}{"stop", "trigger", "tpsl"})
if IsTrue(trigger) {
method = "privatePostTradeCancelTpsl"
}
if IsTrue(IsEqual(clientOrderIds, nil)) {
ids = this.ParseIds(ids)
if IsTrue(!IsEqual(tpslIds, nil)) {
for i := 0; IsLessThan(i, GetArrayLength(tpslIds)); i++ {
AppendToArray(&request,map[string]interface{} {
"tpslId": GetValue(tpslIds, i),
"instId": GetValue(market, "id"),
})
}
}
for i := 0; IsLessThan(i, GetArrayLength(ids)); i++ {
if IsTrue(trigger) {
AppendToArray(&request,map[string]interface{} {
"tpslId": GetValue(ids, i),
"instId": GetValue(market, "id"),
})
} else {
AppendToArray(&request,map[string]interface{} {
"orderId": GetValue(ids, i),
"instId": GetValue(market, "id"),
})
}
}
} else {
for i := 0; IsLessThan(i, GetArrayLength(clientOrderIds)); i++ {
AppendToArray(&request,map[string]interface{} {
"instId": GetValue(market, "id"),
"clientOrderId": GetValue(clientOrderIds, i),
})
}
}
var response interface{} = nil
if IsTrue(IsEqual(method, "privatePostTradeCancelTpsl")) {
response = (<-this.PrivatePostTradeCancelTpsl(request))
PanicOnError(response) // * dont extend with params, otherwise ARRAY will be turned into OBJECT
} else {
response = (<-this.PrivatePostTradeCancelBatchOrders(request))
PanicOnError(response) // * dont extend with params, otherwise ARRAY will be turned into OBJECT
}
var ordersData interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseOrders(ordersData, market, nil, nil, params)
return nil
}()
return ch
}
/**
* @method
* @name blofin#transfer
* @description transfer currency internally between wallets on the same account
* @see https://blofin.com/docs#funds-transfer
* @param {string} code unified currency code
* @param {float} amount amount to transfer
* @param {string} fromAccount account to transfer from (funding, swap, copy_trading, earn)
* @param {string} toAccount account to transfer to (funding, swap, copy_trading, earn)
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
*/
func (this *blofin) 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
retRes19368 := (<-this.LoadMarkets())
PanicOnError(retRes19368)
var currency interface{} = this.Currency(code)
var accountsByType interface{} = this.SafeDict(this.Options, "accountsByType", map[string]interface{} {})
var fromId interface{} = this.SafeString(accountsByType, fromAccount, fromAccount)
var toId interface{} = this.SafeString(accountsByType, toAccount, toAccount)
var request interface{} = map[string]interface{} {
"currency": GetValue(currency, "id"),
"amount": this.CurrencyToPrecision(code, amount),
"fromAccount": fromId,
"toAccount": toId,
}
response:= (<-this.PrivatePostAssetTransfer(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
ch <- this.ParseTransfer(data, currency)
return nil
}()
return ch
}
func (this *blofin) ParseTransfer(transfer interface{}, optionalArgs ...interface{}) interface{} {
currency := GetArg(optionalArgs, 0, nil)
_ = currency
var id interface{} = this.SafeString(transfer, "transferId")
return map[string]interface{} {
"info": transfer,
"id": id,
"timestamp": nil,
"datetime": nil,
"currency": nil,
"amount": nil,
"fromAccount": nil,
"toAccount": nil,
"status": nil,
}
}
/**
* @method
* @name blofin#fetchPosition
* @description fetch data on a single open contract trade position
* @see https://blofin.com/docs#get-positions
* @param {string} symbol unified market symbol of the market the position is held in, default is undefined
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.instType] MARGIN, SWAP, FUTURES, OPTION
* @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
func (this *blofin) FetchPosition(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
retRes19788 := (<-this.LoadMarkets())
PanicOnError(retRes19788)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
}
response:= (<-this.PrivateGetAccountPositions(this.Extend(request, params)))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
var position interface{} = this.SafeDict(data, 0)
if IsTrue(IsEqual(position, nil)) {
return nil
}
ch <- this.ParsePosition(position, market)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchPositions
* @description fetch data on a single open contract trade position
* @see https://blofin.com/docs#get-positions
* @param {string[]} [symbols] list of unified market symbols
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.instType] MARGIN, SWAP, FUTURES, OPTION
* @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
func (this *blofin) 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
retRes20038 := (<-this.LoadMarkets())
PanicOnError(retRes20038)
symbols = this.MarketSymbols(symbols)
response:= (<-this.PrivateGetAccountPositions(params))
PanicOnError(response)
var data interface{} = this.SafeList(response, "data", []interface{}{})
var result interface{} = this.ParsePositions(data)
ch <- this.FilterByArrayPositions(result, "symbol", symbols, false)
return nil
}()
return ch
}
func (this *blofin) ParsePosition(position interface{}, optionalArgs ...interface{}) interface{} {
//
// response similar for REST & WS
//
// {
// instType: 'SWAP',
// instId: 'LTC-USDT',
// marginMode: 'cross',
// positionId: '644159',
// positionSide: 'net',
// positions: '1',
// availablePositions: '1',
// averagePrice: '68.16',
// unrealizedPnl: '0.80631223',
// unrealizedPnlRatio: '0.03548909463028169',
// leverage: '3',
// liquidationPrice: '10.116655172370356435',
// markPrice: '68.96',
// initialMargin: '22.988770743333333333',
// margin: '', // this field might not exist in rest response
// marginRatio: '152.523509620342499273',
// maintenanceMargin: '0.34483156115',
// adl: '4',
// createTime: '1707235776528',
// updateTime: '1707235776528'
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var marketId interface{} = this.SafeString(position, "instId")
market = this.SafeMarket(marketId, market)
var symbol interface{} = GetValue(market, "symbol")
var pos interface{} = this.SafeString(position, "positions")
var contractsAbs interface{} = Precise.StringAbs(pos)
var side interface{} = this.SafeString(position, "positionSide")
var hedged interface{} = !IsEqual(side, "net")
var contracts interface{} = this.ParseNumber(contractsAbs)
if IsTrue(!IsEqual(pos, nil)) {
if IsTrue(IsEqual(side, "net")) {
if IsTrue(Precise.StringGt(pos, "0")) {
side = "long"
} else if IsTrue(Precise.StringLt(pos, "0")) {
side = "short"
} else {
side = nil
}
}
}
var contractSize interface{} = this.SafeNumber(market, "contractSize")
var contractSizeString interface{} = this.NumberToString(contractSize)
var markPriceString interface{} = this.SafeString(position, "markPrice")
var notionalString interface{} = this.SafeString(position, "notionalUsd")
if IsTrue(GetValue(market, "inverse")) {
notionalString = Precise.StringDiv(Precise.StringMul(contractsAbs, contractSizeString), markPriceString)
}
var notional interface{} = this.ParseNumber(notionalString)
var marginMode interface{} = this.SafeString(position, "marginMode")
var initialMarginString interface{} = nil
var entryPriceString interface{} = this.SafeString(position, "averagePrice")
var unrealizedPnlString interface{} = this.SafeString(position, "unrealizedPnl")
var leverageString interface{} = this.SafeString(position, "leverage")
var initialMarginPercentage interface{} = nil
var collateralString interface{} = nil
if IsTrue(IsEqual(marginMode, "cross")) {
initialMarginString = this.SafeString(position, "initialMargin")
collateralString = Precise.StringAdd(initialMarginString, unrealizedPnlString)
} else if IsTrue(IsEqual(marginMode, "isolated")) {
initialMarginPercentage = Precise.StringDiv("1", leverageString)
collateralString = this.SafeString(position, "margin")
}
var maintenanceMarginString interface{} = this.SafeString(position, "maintenanceMargin")
var maintenanceMargin interface{} = this.ParseNumber(maintenanceMarginString)
var maintenanceMarginPercentageString interface{} = Precise.StringDiv(maintenanceMarginString, notionalString)
if IsTrue(IsEqual(initialMarginPercentage, nil)) {
initialMarginPercentage = this.ParseNumber(Precise.StringDiv(initialMarginString, notionalString, 4))
} else if IsTrue(IsEqual(initialMarginString, nil)) {
initialMarginString = Precise.StringMul(initialMarginPercentage, notionalString)
}
var rounder interface{} = "0.00005" // round to closest 0.01%
var maintenanceMarginPercentage interface{} = this.ParseNumber(Precise.StringDiv(Precise.StringAdd(maintenanceMarginPercentageString, rounder), "1", 4))
var liquidationPrice interface{} = this.SafeNumber(position, "liquidationPrice")
var percentageString interface{} = this.SafeString(position, "unrealizedPnlRatio")
var percentage interface{} = this.ParseNumber(Precise.StringMul(percentageString, "100"))
var timestamp interface{} = this.SafeInteger(position, "updateTime")
var marginRatio interface{} = this.ParseNumber(Precise.StringDiv(maintenanceMarginString, collateralString, 4))
return this.SafePosition(map[string]interface{} {
"info": position,
"id": nil,
"symbol": symbol,
"notional": notional,
"marginMode": marginMode,
"liquidationPrice": liquidationPrice,
"entryPrice": this.ParseNumber(entryPriceString),
"unrealizedPnl": this.ParseNumber(unrealizedPnlString),
"percentage": percentage,
"contracts": contracts,
"contractSize": contractSize,
"markPrice": this.ParseNumber(markPriceString),
"lastPrice": nil,
"side": side,
"hedged": hedged,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"lastUpdateTimestamp": nil,
"maintenanceMargin": maintenanceMargin,
"maintenanceMarginPercentage": maintenanceMarginPercentage,
"collateral": this.ParseNumber(collateralString),
"initialMargin": this.ParseNumber(initialMarginString),
"initialMarginPercentage": this.ParseNumber(initialMarginPercentage),
"leverage": this.ParseNumber(leverageString),
"marginRatio": marginRatio,
"stopLossPrice": nil,
"takeProfitPrice": nil,
})
}
/**
* @method
* @name blofin#fetchLeverages
* @description fetch the set leverage for all contract markets
* @see https://docs.blofin.com/index.html#get-multiple-leverage
* @param {string[]} symbols a list of unified market symbols, required on blofin
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.marginMode] 'cross' or 'isolated'
* @returns {object} a list of [leverage structures]{@link https://docs.ccxt.com/#/?id=leverage-structure}
*/
func (this *blofin) FetchLeverages(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
retRes21368 := (<-this.LoadMarkets())
PanicOnError(retRes21368)
if IsTrue(IsEqual(symbols, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchLeverages() requires a symbols argument")))
}
var marginMode interface{} = nil
marginModeparamsVariable := this.HandleMarginModeAndParams("fetchLeverages", params);
marginMode = GetValue(marginModeparamsVariable,0);
params = GetValue(marginModeparamsVariable,1)
if IsTrue(IsEqual(marginMode, nil)) {
marginMode = this.SafeString(params, "marginMode", "cross") // cross as default marginMode
}
if IsTrue(IsTrue((!IsEqual(marginMode, "cross"))) && IsTrue((!IsEqual(marginMode, "isolated")))) {
panic(BadRequest(Add(this.Id, " fetchLeverages() requires a marginMode parameter that must be either cross or isolated")))
}
symbols = this.MarketSymbols(symbols)
var instIds interface{} = ""
for i := 0; IsLessThan(i, GetArrayLength(symbols)); i++ {
var entry interface{} = GetValue(symbols, i)
var entryMarket interface{} = this.Market(entry)
if IsTrue(IsGreaterThan(i, 0)) {
instIds = Add(Add(instIds, ","), GetValue(entryMarket, "id"))
} else {
instIds = Add(instIds, GetValue(entryMarket, "id"))
}
}
var request interface{} = map[string]interface{} {
"instId": instIds,
"marginMode": marginMode,
}
response:= (<-this.PrivateGetAccountBatchLeverageInfo(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "code": "0",
// "msg": "success",
// "data": [
// {
// "leverage": "3",
// "marginMode": "cross",
// "instId": "BTC-USDT"
// },
// ]
// }
//
var leverages interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseLeverages(leverages, symbols, "instId")
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchLeverage
* @description fetch the set leverage for a market
* @see https://docs.blofin.com/index.html#get-leverage
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.marginMode] 'cross' or 'isolated'
* @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
*/
func (this *blofin) FetchLeverage(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
retRes21928 := (<-this.LoadMarkets())
PanicOnError(retRes21928)
var marginMode interface{} = nil
marginModeparamsVariable := this.HandleMarginModeAndParams("fetchLeverage", params);
marginMode = GetValue(marginModeparamsVariable,0);
params = GetValue(marginModeparamsVariable,1)
if IsTrue(IsEqual(marginMode, nil)) {
marginMode = this.SafeString(params, "marginMode", "cross") // cross as default marginMode
}
if IsTrue(IsTrue((!IsEqual(marginMode, "cross"))) && IsTrue((!IsEqual(marginMode, "isolated")))) {
panic(BadRequest(Add(this.Id, " fetchLeverage() requires a marginMode parameter that must be either cross or isolated")))
}
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
"marginMode": marginMode,
}
response:= (<-this.PrivateGetAccountLeverageInfo(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "code": "0",
// "msg": "success",
// "data": {
// "leverage": "3",
// "marginMode": "cross",
// "instId": "BTC-USDT"
// }
// }
//
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
ch <- this.ParseLeverage(data, market)
return nil
}()
return ch
}
func (this *blofin) ParseLeverage(leverage interface{}, optionalArgs ...interface{}) interface{} {
market := GetArg(optionalArgs, 0, nil)
_ = market
var marketId interface{} = this.SafeString(leverage, "instId")
var leverageValue interface{} = this.SafeInteger(leverage, "leverage")
return map[string]interface{} {
"info": leverage,
"symbol": this.SafeSymbol(marketId, market),
"marginMode": this.SafeStringLower(leverage, "marginMode"),
"longLeverage": leverageValue,
"shortLeverage": leverageValue,
}
}
/**
* @method
* @name blofin#setLeverage
* @description set the level of leverage for a market
* @see https://blofin.com/docs#set-leverage
* @param {int} leverage the rate of leverage
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.marginMode] 'cross' or 'isolated'
* @returns {object} response from the exchange
*/
func (this *blofin) SetLeverage(leverage interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " setLeverage() requires a symbol argument")))
}
// WARNING: THIS WILL INCREASE LIQUIDATION PRICE FOR OPEN ISOLATED LONG POSITIONS
// AND DECREASE LIQUIDATION PRICE FOR OPEN ISOLATED SHORT POSITIONS
if IsTrue(IsTrue((IsLessThan(leverage, 1))) || IsTrue((IsGreaterThan(leverage, 125)))) {
panic(BadRequest(Add(this.Id, " setLeverage() leverage should be between 1 and 125")))
}
retRes22548 := (<-this.LoadMarkets())
PanicOnError(retRes22548)
var market interface{} = this.Market(symbol)
var marginMode interface{} = nil
marginModeparamsVariable := this.HandleMarginModeAndParams("setLeverage", params, "cross");
marginMode = GetValue(marginModeparamsVariable,0);
params = GetValue(marginModeparamsVariable,1)
if IsTrue(IsTrue((!IsEqual(marginMode, "cross"))) && IsTrue((!IsEqual(marginMode, "isolated")))) {
panic(BadRequest(Add(this.Id, " setLeverage() requires a marginMode parameter that must be either cross or isolated")))
}
var request interface{} = map[string]interface{} {
"leverage": leverage,
"marginMode": marginMode,
"instId": GetValue(market, "id"),
}
response:= (<-this.PrivatePostAccountSetLeverage(this.Extend(request, params)))
PanicOnError(response)
ch <- response
return nil
}()
return ch
}
/**
* @method
* @name blofin#closePosition
* @description closes open positions for a market
* @see https://blofin.com/docs#close-positions
* @param {string} symbol Unified CCXT market symbol
* @param {string} [side] 'buy' or 'sell', leave as undefined in net mode
* @param {object} [params] extra parameters specific to the blofin api endpoint
* @param {string} [params.clientOrderId] a unique identifier for the order
* @param {string} [params.marginMode] 'cross' or 'isolated', default is 'cross;
* @param {string} [params.code] *required in the case of closing cross MARGIN position for Single-currency margin* margin currency
*
* EXCHANGE SPECIFIC PARAMETERS
* @param {boolean} [params.autoCxl] whether any pending orders for closing out needs to be automatically canceled when close position via a market order. false or true, the default is false
* @param {string} [params.tag] order tag a combination of case-sensitive alphanumerics, all numbers, or all letters of up to 16 characters
* @returns {object[]} [A list of position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
*/
func (this *blofin) ClosePosition(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
side := GetArg(optionalArgs, 0, nil)
_ = side
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes22888 := (<-this.LoadMarkets())
PanicOnError(retRes22888)
var market interface{} = this.Market(symbol)
var clientOrderId interface{} = this.SafeString(params, "clientOrderId")
var marginMode interface{} = nil
marginModeparamsVariable := this.HandleMarginModeAndParams("closePosition", params, "cross");
marginMode = GetValue(marginModeparamsVariable,0);
params = GetValue(marginModeparamsVariable,1)
var request interface{} = map[string]interface{} {
"instId": GetValue(market, "id"),
"marginMode": marginMode,
}
if IsTrue(!IsEqual(clientOrderId, nil)) {
AddElementToObject(request, "clientOrderId", clientOrderId)
}
response:= (<-this.PrivatePostTradeClosePosition(this.Extend(request, params)))
PanicOnError(response)
ch <- this.SafeDict(response, "data")
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchClosedOrders
* @description fetches information on multiple closed orders made by the user
* @see https://blofin.com/docs#get-order-history
* @see https://blofin.com/docs#get-tpsl-order-history
* @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 orde structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {bool} [params.trigger] True if fetching trigger or conditional orders
* @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 {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *blofin) 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
retRes23198 := (<-this.LoadMarkets())
PanicOnError(retRes23198)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchClosedOrders", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes232319 := (<-this.FetchPaginatedCallDynamic("fetchClosedOrders", symbol, since, limit, params))
PanicOnError(retRes232319)
ch <- retRes232319
return nil
}
var request interface{} = map[string]interface{} {}
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
AddElementToObject(request, "instId", GetValue(market, "id"))
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "limit", limit) // default 100, max 100
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "begin", since)
}
var isTrigger interface{} = this.SafeBoolN(params, []interface{}{"stop", "trigger", "tpsl", "TPSL"}, false)
var method interface{} = nil
methodparamsVariable := this.HandleOptionAndParams(params, "fetchOpenOrders", "method", "privateGetTradeOrdersHistory");
method = GetValue(methodparamsVariable,0);
params = GetValue(methodparamsVariable,1)
var query interface{} = this.Omit(params, []interface{}{"method", "stop", "trigger", "tpsl", "TPSL"})
var response interface{} = nil
if IsTrue(IsTrue((isTrigger)) || IsTrue((IsEqual(method, "privateGetTradeOrdersTpslHistory")))) {
response = (<-this.PrivateGetTradeOrdersTpslHistory(this.Extend(request, query)))
PanicOnError(response)
} else {
response = (<-this.PrivateGetTradeOrdersHistory(this.Extend(request, query)))
PanicOnError(response)
}
var data interface{} = this.SafeList(response, "data", []interface{}{})
ch <- this.ParseOrders(data, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name blofin#fetchMarginMode
* @description fetches the margin mode of a trading pair
* @see https://docs.blofin.com/index.html#get-margin-mode
* @param {string} symbol unified symbol of the market to fetch the margin mode for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [margin mode structure]{@link https://docs.ccxt.com/#/?id=margin-mode-structure}
*/
func (this *blofin) FetchMarginMode(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
retRes23628 := (<-this.LoadMarkets())
PanicOnError(retRes23628)
var market interface{} = this.Market(symbol)
response:= (<-this.PrivateGetAccountMarginMode(params))
PanicOnError(response)
//
// {
// "code": "0",
// "msg": "success",
// "data": {
// "marginMode": "cross"
// }
// }
//
var data interface{} = this.SafeDict(response, "data", map[string]interface{} {})
ch <- this.ParseMarginMode(data, market)
return nil
}()
return ch
}
func (this *blofin) ParseMarginMode(marginMode interface{}, optionalArgs ...interface{}) interface{} {
market := GetArg(optionalArgs, 0, nil)
_ = market
return map[string]interface{} {
"info": marginMode,
"symbol": GetValue(market, "symbol"),
"marginMode": this.SafeString(marginMode, "marginMode"),
}
}
func (this *blofin) HandleErrors(httpCode interface{}, reason interface{}, url interface{}, method interface{}, headers interface{}, body interface{}, response interface{}, requestHeaders interface{}, requestBody interface{}) interface{} {
if IsTrue(IsEqual(response, nil)) {
return nil // fallback to default error handler
}
//
// {"code":"152002","msg":"Parameter bar error."}
//
var code interface{} = this.SafeString(response, "code")
var message interface{} = this.SafeString(response, "msg")
var feedback interface{} = Add(Add(this.Id, " "), body)
if IsTrue(IsTrue(!IsEqual(code, nil)) && IsTrue(!IsEqual(code, "0"))) {
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), message, feedback)
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), code, feedback)
this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), message, feedback)
panic(ExchangeError(feedback))
}
//
// {
// orderId: null,
// clientOrderId: '',
// msg: 'Order failed. Insufficient USDT margin in account',
// code: '103003'
// }
//
var data interface{} = this.SafeList(response, "data")
var first interface{} = this.SafeDict(data, 0)
var insideMsg interface{} = this.SafeString(first, "msg")
var insideCode interface{} = this.SafeString(first, "code")
if IsTrue(IsTrue(!IsEqual(insideCode, nil)) && IsTrue(!IsEqual(insideCode, "0"))) {
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), insideCode, feedback)
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), insideMsg, feedback)
this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), insideMsg, feedback)
}
return nil
}
func (this *blofin) 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 request interface{} = Add(Add(Add("/api/", this.Version), "/"), this.ImplodeParams(path, params))
var query interface{} = this.Omit(params, this.ExtractParams(path))
var url interface{} = Add(this.ImplodeHostname(GetValue(GetValue(this.Urls, "api"), "rest")), request)
// const type = this.getPathAuthenticationType (path);
if IsTrue(IsEqual(api, "public")) {
if !IsTrue(this.IsEmpty(query)) {
url = Add(url, Add("?", this.Urlencode(query)))
}
} else if IsTrue(IsEqual(api, "private")) {
this.CheckRequiredCredentials()
var timestamp interface{} = ToString(this.Milliseconds())
headers = map[string]interface{} {
"ACCESS-KEY": this.ApiKey,
"ACCESS-PASSPHRASE": this.Password,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-NONCE": timestamp,
}
var sign_body interface{} = ""
if IsTrue(IsEqual(method, "GET")) {
if !IsTrue(this.IsEmpty(query)) {
var urlencodedQuery interface{} = Add("?", this.Urlencode(query))
url = Add(url, urlencodedQuery)
request = Add(request, urlencodedQuery)
}
} else {
if !IsTrue(this.IsEmpty(query)) {
body = this.Json(query)
sign_body = body
}
AddElementToObject(headers, "Content-Type", "application/json")
}
var auth interface{} = Add(Add(Add(Add(request, method), timestamp), timestamp), sign_body)
var signature interface{} = this.StringToBase64(this.Hmac(this.Encode(auth), this.Encode(this.Secret), sha256))
AddElementToObject(headers, "ACCESS-SIGN", signature)
}
return map[string]interface{} {
"url": url,
"method": method,
"body": body,
"headers": headers,
}
}
func (this *blofin) Init(userConfig map[string]interface{}) {
this.Exchange = Exchange{}
this.Exchange.InitParent(userConfig, this.Describe().(map[string]interface{}), this)
this.Exchange.DerivedExchange = this
}