3037 lines
134 KiB
Go
3037 lines
134 KiB
Go
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
|
|
}
|