2382 lines
105 KiB
Python
2382 lines
105 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# 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
|
|
|
|
from ccxt.async_support.base.exchange import Exchange
|
|
from ccxt.abstract.bitteam import ImplicitAPI
|
|
from ccxt.base.types import Any, Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
|
from typing import List
|
|
from ccxt.base.errors import ExchangeError
|
|
from ccxt.base.errors import AuthenticationError
|
|
from ccxt.base.errors import ArgumentsRequired
|
|
from ccxt.base.errors import BadRequest
|
|
from ccxt.base.errors import BadSymbol
|
|
from ccxt.base.errors import InsufficientFunds
|
|
from ccxt.base.errors import OrderNotFound
|
|
from ccxt.base.errors import ExchangeNotAvailable
|
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
|
from ccxt.base.precise import Precise
|
|
|
|
|
|
class bitteam(Exchange, ImplicitAPI):
|
|
|
|
def describe(self) -> Any:
|
|
return self.deep_extend(super(bitteam, self).describe(), {
|
|
'id': 'bitteam',
|
|
'name': 'BIT.TEAM',
|
|
'countries': ['UK'],
|
|
'version': 'v2.0.6',
|
|
'rateLimit': 1, # the exchange has no rate limit
|
|
'certified': False,
|
|
'pro': False,
|
|
'has': {
|
|
'CORS': None,
|
|
'spot': True,
|
|
'margin': False,
|
|
'swap': False,
|
|
'future': False,
|
|
'option': False,
|
|
'addMargin': False,
|
|
'borrowCrossMargin': False,
|
|
'borrowIsolatedMargin': False,
|
|
'borrowMargin': False,
|
|
'cancelAllOrders': True,
|
|
'cancelOrder': True,
|
|
'cancelOrders': False,
|
|
'closeAllPositions': False,
|
|
'closePosition': False,
|
|
'createDepositAddress': False,
|
|
'createOrder': True,
|
|
'createOrderWithTakeProfitAndStopLoss': False,
|
|
'createOrderWithTakeProfitAndStopLossWs': False,
|
|
'createPostOnlyOrder': False,
|
|
'createReduceOnlyOrder': False,
|
|
'createStopLimitOrder': False,
|
|
'createStopMarketOrder': False,
|
|
'createStopOrder': False,
|
|
'deposit': False,
|
|
'editOrder': False,
|
|
'fetchAccounts': False,
|
|
'fetchBalance': True,
|
|
'fetchBidsAsks': False,
|
|
'fetchBorrowInterest': False,
|
|
'fetchBorrowRate': False,
|
|
'fetchBorrowRateHistories': False,
|
|
'fetchBorrowRateHistory': False,
|
|
'fetchBorrowRates': False,
|
|
'fetchBorrowRatesPerSymbol': False,
|
|
'fetchCanceledOrders': True,
|
|
'fetchClosedOrder': False,
|
|
'fetchClosedOrders': True,
|
|
'fetchCrossBorrowRate': False,
|
|
'fetchCrossBorrowRates': False,
|
|
'fetchCurrencies': True,
|
|
'fetchDeposit': False,
|
|
'fetchDepositAddress': False,
|
|
'fetchDepositAddresses': False,
|
|
'fetchDepositAddressesByNetwork': False,
|
|
'fetchDeposits': False,
|
|
'fetchDepositsWithdrawals': True,
|
|
'fetchDepositWithdrawFee': False,
|
|
'fetchDepositWithdrawFees': False,
|
|
'fetchFundingHistory': False,
|
|
'fetchFundingInterval': False,
|
|
'fetchFundingIntervals': False,
|
|
'fetchFundingRate': False,
|
|
'fetchFundingRateHistory': False,
|
|
'fetchFundingRates': False,
|
|
'fetchGreeks': False,
|
|
'fetchIndexOHLCV': False,
|
|
'fetchIsolatedBorrowRate': False,
|
|
'fetchIsolatedBorrowRates': False,
|
|
'fetchIsolatedPositions': False,
|
|
'fetchL3OrderBook': False,
|
|
'fetchLedger': False,
|
|
'fetchLeverage': False,
|
|
'fetchLeverages': False,
|
|
'fetchLeverageTiers': False,
|
|
'fetchLiquidations': False,
|
|
'fetchLongShortRatio': False,
|
|
'fetchLongShortRatioHistory': False,
|
|
'fetchMarginAdjustmentHistory': False,
|
|
'fetchMarginMode': False,
|
|
'fetchMarginModes': False,
|
|
'fetchMarketLeverageTiers': False,
|
|
'fetchMarkets': True,
|
|
'fetchMarkOHLCV': False,
|
|
'fetchMarkPrices': False,
|
|
'fetchMyLiquidations': False,
|
|
'fetchMySettlementHistory': False,
|
|
'fetchMyTrades': True,
|
|
'fetchOHLCV': True,
|
|
'fetchOpenInterest': False,
|
|
'fetchOpenInterestHistory': False,
|
|
'fetchOpenInterests': False,
|
|
'fetchOpenOrder': False,
|
|
'fetchOpenOrders': True,
|
|
'fetchOption': False,
|
|
'fetchOptionChain': False,
|
|
'fetchOrder': True,
|
|
'fetchOrderBook': True,
|
|
'fetchOrderBooks': False,
|
|
'fetchOrders': True,
|
|
'fetchOrderTrades': False,
|
|
'fetchPosition': False,
|
|
'fetchPositionHistory': False,
|
|
'fetchPositionMode': False,
|
|
'fetchPositions': False,
|
|
'fetchPositionsForSymbol': False,
|
|
'fetchPositionsHistory': 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': True,
|
|
'fetchTransfers': False,
|
|
'fetchVolatilityHistory': False,
|
|
'fetchWithdrawal': False,
|
|
'fetchWithdrawals': False,
|
|
'fetchWithdrawalWhitelist': False,
|
|
'reduceMargin': False,
|
|
'repayCrossMargin': False,
|
|
'repayIsolatedMargin': False,
|
|
'repayMargin': False,
|
|
'setLeverage': False,
|
|
'setMargin': False,
|
|
'setMarginMode': False,
|
|
'setPositionMode': False,
|
|
'signIn': False,
|
|
'transfer': False,
|
|
'withdraw': False,
|
|
'ws': False,
|
|
},
|
|
'timeframes': {
|
|
'1m': '1',
|
|
'5m': '5',
|
|
'15m': '15',
|
|
'1h': '60',
|
|
'1d': '1D',
|
|
},
|
|
'urls': {
|
|
'logo': 'https://github.com/user-attachments/assets/b41b5e0d-98e5-4bd3-8a6e-aeb230a4a135',
|
|
'api': {
|
|
'history': 'https://history.bit.team',
|
|
'public': 'https://bit.team',
|
|
'private': 'https://bit.team',
|
|
},
|
|
'www': 'https://bit.team/',
|
|
'referral': 'https://bit.team/auth/sign-up?ref=bitboy2023',
|
|
'doc': [
|
|
'https://bit.team/trade/api/documentation',
|
|
],
|
|
},
|
|
'api': {
|
|
'history': {
|
|
'get': {
|
|
'api/tw/history/{pairName}/{resolution}': 1,
|
|
},
|
|
},
|
|
'public': {
|
|
'get': {
|
|
'trade/api/asset': 1, # not unified
|
|
'trade/api/currencies': 1,
|
|
'trade/api/orderbooks/{symbol}': 1, # not unified
|
|
'trade/api/orders': 1, # not unified
|
|
'trade/api/pair/{name}': 1,
|
|
'trade/api/pairs': 1, # not unified
|
|
'trade/api/pairs/precisions': 1, # not unified
|
|
'trade/api/rates': 1, # not unified
|
|
'trade/api/trade/{id}': 1, # not unified
|
|
'trade/api/trades': 1, # not unified
|
|
'trade/api/ccxt/pairs': 1,
|
|
'trade/api/cmc/assets': 1,
|
|
'trade/api/cmc/orderbook/{pair}': 1,
|
|
'trade/api/cmc/summary': 1,
|
|
'trade/api/cmc/ticker': 1, # not unified
|
|
'trade/api/cmc/trades/{pair}': 1,
|
|
},
|
|
},
|
|
'private': {
|
|
'get': {
|
|
'trade/api/ccxt/balance': 1,
|
|
'trade/api/ccxt/order/{id}': 1,
|
|
'trade/api/ccxt/ordersOfUser': 1,
|
|
'trade/api/ccxt/tradesOfUser': 1,
|
|
'trade/api/transactionsOfUser': 1,
|
|
},
|
|
'post': {
|
|
'trade/api/ccxt/cancel-all-order': 1,
|
|
'trade/api/ccxt/cancelorder': 1,
|
|
'trade/api/ccxt/ordercreate': 1,
|
|
},
|
|
},
|
|
},
|
|
'fees': {
|
|
'trading': {
|
|
'feeSide': 'get',
|
|
'tierBased': False,
|
|
'percentage': True,
|
|
'taker': self.parse_number('0.002'),
|
|
'maker': self.parse_number('0.002'),
|
|
},
|
|
},
|
|
'precisionMode': TICK_SIZE,
|
|
# exchange-specific options
|
|
'options': {
|
|
'networksById': {
|
|
'Ethereum': 'ERC20',
|
|
'ethereum': 'ERC20',
|
|
'Tron': 'TRC20',
|
|
'tron': 'TRC20',
|
|
'Binance': 'BSC',
|
|
'binance': 'BSC',
|
|
'Binance Smart Chain': 'BSC',
|
|
'bscscan': 'BSC',
|
|
'Bitcoin': 'BTC',
|
|
'bitcoin': 'BTC',
|
|
'Litecoin': 'LTC',
|
|
'litecoin': 'LTC',
|
|
'Polygon': 'POLYGON',
|
|
'polygon': 'POLYGON',
|
|
'PRIZM': 'PRIZM',
|
|
'Decimal': 'Decimal',
|
|
'ufobject': 'ufobject',
|
|
'tonchain': 'tonchain',
|
|
},
|
|
'currenciesValuedInUsd': {
|
|
'USDT': True,
|
|
'BUSD': True,
|
|
},
|
|
},
|
|
'features': {
|
|
'spot': {
|
|
'sandbox': False,
|
|
'createOrder': {
|
|
'marginMode': False,
|
|
'triggerPrice': False,
|
|
'triggerPriceType': None,
|
|
'triggerDirection': None,
|
|
'stopLossPrice': False,
|
|
'takeProfitPrice': False,
|
|
'attachedStopLossTakeProfit': None,
|
|
'timeInForce': {
|
|
'IOC': False,
|
|
'FOK': False,
|
|
'PO': False,
|
|
'GTD': False,
|
|
},
|
|
'hedged': False,
|
|
'trailing': False,
|
|
'leverage': False,
|
|
'marketBuyRequiresPrice': False,
|
|
'marketBuyByCost': False,
|
|
'selfTradePrevention': False,
|
|
'iceberg': False,
|
|
},
|
|
'createOrders': None,
|
|
'fetchMyTrades': {
|
|
'marginMode': False,
|
|
'limit': 100,
|
|
'daysBack': 100000,
|
|
'untilDays': 100000,
|
|
'symbolRequired': False,
|
|
},
|
|
'fetchOrder': {
|
|
'marginMode': False,
|
|
'trigger': False,
|
|
'trailing': False,
|
|
'symbolRequired': False,
|
|
},
|
|
'fetchOpenOrders': {
|
|
'marginMode': False,
|
|
'limit': 100,
|
|
'trigger': False,
|
|
'trailing': False,
|
|
'symbolRequired': False,
|
|
},
|
|
'fetchOrders': {
|
|
'marginMode': True,
|
|
'limit': 100,
|
|
'daysBack': None,
|
|
'untilDays': None,
|
|
'trigger': False,
|
|
'trailing': False,
|
|
'symbolRequired': False,
|
|
},
|
|
'fetchClosedOrders': {
|
|
'marginMode': False,
|
|
'limit': 100,
|
|
'daysBack': None,
|
|
'daysBackCanceled': None,
|
|
'untilDays': None,
|
|
'trigger': False,
|
|
'trailing': False,
|
|
'symbolRequired': False,
|
|
},
|
|
'fetchOHLCV': {
|
|
'limit': 1000,
|
|
},
|
|
},
|
|
'swap': {
|
|
'linear': None,
|
|
'inverse': None,
|
|
},
|
|
'future': {
|
|
'linear': None,
|
|
'inverse': None,
|
|
},
|
|
},
|
|
'exceptions': {
|
|
'exact': {
|
|
'400002': BadSymbol, # {"ok":false,"code":400002,"message":"An order cannot be created on a deactivated pair"}
|
|
'401000': AuthenticationError, # {"ok":false,"code":401000,"data": {},"message": "Missing authentication"}
|
|
'403002': BadRequest, # {"ok":false,"code":403002,"data":{},"message":"Order cannot be deleted, status does not match"}
|
|
'404200': BadSymbol, # {"ok":false,"code":404200,"data":{},"message":"Pair was not found"}
|
|
},
|
|
'broad': {
|
|
'is not allowed': BadRequest, # {"message":"\"createdAt\" is not allowed","path":["createdAt"],"type":"object.unknown","context":{"child":"createdAt","label":"createdAt","value":"DESC","key":"createdAt"}}
|
|
'Insufficient funds': InsufficientFunds, # {"ok":false,"code":450000,"data":null,"message":"Insufficient funds"}
|
|
'Invalid request params input': BadRequest, # {"ok":false,"code":400000,"data":{},"message":"Invalid request params input"}
|
|
'must be a number': BadRequest, # [ExchangeError] bitteam {"message":"\"currency\" must be a number","path":["currency"],"type":"number.base","context":{"label":"currency","value":"adsf","key":"currency"}}
|
|
'must be a string': BadRequest, # {"message":"\"pairId\" must be a string","path":["pairId"],"type":"string.base","context":{"label":"pairId","value":87,"key":"pairId"}}
|
|
'must be of type': BadRequest, # {"message":"\"order\" must be of type object","path":["order"],"type":"object.base","context":{"type":"object","label":"order","value":"107218781","key":"order"}}
|
|
'must be one of': BadRequest, # {"message":"\"resolution\" must be one of [1, 5, 15, 60, 1D]","path":["resolution"],"type":"any.only","context":{"valids":["1","5","15","60","1D"],"label":"resolution","value":"1d","key":"resolution"}}
|
|
'Order not found': OrderNotFound, # {"ok":false,"code":404300,"data":{},"message":"Order not found"}
|
|
'Pair with pair name': BadSymbol, # {"ok":false,"code":404000,"data":{"pairName":"ETH_USasdf"},"msg":"Pair with pair name ETH_USasdf was not found"}
|
|
'pairName': BadSymbol, # {"message":"\"pairName\" length must be at least 7 characters long","path":["pairName"],"type":"string.min","context":{"limit":7,"value":"ETH_US","label":"pairName","key":"pairName"}}
|
|
'Service Unavailable': ExchangeNotAvailable, # {"message":"Service Unavailable","code":403000,"ok":false}
|
|
'Symbol ': BadSymbol, # {"ok":false,"code":404000,"data":{},"message":"Symbol asdfasdfas was not found"}
|
|
},
|
|
},
|
|
})
|
|
|
|
async def fetch_markets(self, params={}) -> List[Market]:
|
|
"""
|
|
retrieves data on all markets for bitteam
|
|
|
|
https://bit.team/trade/api/documentation#/CCXT/getTradeApiCcxtPairs
|
|
|
|
:param dict [params]: extra parameters specific to the exchange api endpoint
|
|
:returns dict[]: an array of objects representing market data
|
|
"""
|
|
response = await self.publicGetTradeApiCcxtPairs(params)
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "count": 28,
|
|
# "pairs": [
|
|
# {
|
|
# "id": 2,
|
|
# "name": "eth_usdt",
|
|
# "baseAssetId": 2,
|
|
# "quoteAssetId": 3,
|
|
# "fullName": "ETH USDT",
|
|
# "description": "ETH USDT",
|
|
# "lastBuy": 1964.665001,
|
|
# "lastSell": 1959.835005,
|
|
# "lastPrice": 1964.665001,
|
|
# "change24": 1.41,
|
|
# "volume24": 28.22627543,
|
|
# "volume24USD": 55662.35636401598,
|
|
# "active": True,
|
|
# "baseStep": 8,
|
|
# "quoteStep": 6,
|
|
# "status": 1,
|
|
# "settings": {
|
|
# "limit_usd": "0.1",
|
|
# "price_max": "10000000000000",
|
|
# "price_min": "1",
|
|
# "price_tick": "1",
|
|
# "pricescale": 10000,
|
|
# "lot_size_max": "1000000000000000",
|
|
# "lot_size_min": "1",
|
|
# "lot_size_tick": "1",
|
|
# "price_view_min": 6,
|
|
# "default_slippage": 10,
|
|
# "lot_size_view_min": 6
|
|
# },
|
|
# "updateId": "50620",
|
|
# "timeStart": "2021-01-28T09:19:30.706Z",
|
|
# "makerFee": 200,
|
|
# "takerFee": 200,
|
|
# "quoteVolume24": 54921.93404134529,
|
|
# "lowPrice24": 1919.355,
|
|
# "highPrice24": 1971.204995
|
|
# },
|
|
# {
|
|
# "id": 27,
|
|
# "name": "ltc_usdt",
|
|
# "baseAssetId": 13,
|
|
# "quoteAssetId": 3,
|
|
# "fullName": "LTC USDT",
|
|
# "description": "This is LTC USDT",
|
|
# "lastBuy": 53.14,
|
|
# "lastSell": 53.58,
|
|
# "lastPrice": 53.58,
|
|
# "change24": -6.72,
|
|
# "volume24": 0,
|
|
# "volume24USD": null,
|
|
# "active": True,
|
|
# "baseStep": 8,
|
|
# "quoteStep": 6,
|
|
# "status": 0,
|
|
# "settings": {
|
|
# "limit_usd": "0.1",
|
|
# "price_max": "1000000000000",
|
|
# "price_min": "1",
|
|
# "price_tick": "1",
|
|
# "pricescale": 10000,
|
|
# "lot_size_max": "1000000000000",
|
|
# "lot_size_min": "1",
|
|
# "lot_size_tick": "1",
|
|
# "price_view_min": 6,
|
|
# "default_slippage": 10,
|
|
# "lot_size_view_min": 6
|
|
# },
|
|
# "updateId": "30",
|
|
# "timeStart": "2021-10-13T12:11:05.359Z",
|
|
# "makerFee": 200,
|
|
# "takerFee": 200,
|
|
# "quoteVolume24": 0,
|
|
# "lowPrice24": null,
|
|
# "highPrice24": null
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
markets = self.safe_value(result, 'pairs', [])
|
|
return self.parse_markets(markets)
|
|
|
|
def parse_market(self, market: dict) -> Market:
|
|
id = self.safe_string(market, 'name')
|
|
numericId = self.safe_integer(market, 'id')
|
|
parts = id.split('_')
|
|
baseId = self.safe_string(parts, 0)
|
|
quoteId = self.safe_string(parts, 1)
|
|
base = self.safe_currency_code(baseId)
|
|
quote = self.safe_currency_code(quoteId)
|
|
active = self.safe_value(market, 'active')
|
|
timeStart = self.safe_string(market, 'timeStart')
|
|
created = self.parse8601(timeStart)
|
|
minCost = None
|
|
currenciesValuedInUsd = self.safe_value(self.options, 'currenciesValuedInUsd', {})
|
|
quoteInUsd = self.safe_bool(currenciesValuedInUsd, quote, False)
|
|
if quoteInUsd:
|
|
settings = self.safe_value(market, 'settings', {})
|
|
minCost = self.safe_number(settings, 'limit_usd')
|
|
return self.safe_market_structure({
|
|
'id': id,
|
|
'numericId': numericId,
|
|
'symbol': base + '/' + quote,
|
|
'base': base,
|
|
'quote': quote,
|
|
'settle': None,
|
|
'baseId': baseId,
|
|
'quoteId': quoteId,
|
|
'settleId': None,
|
|
'type': 'spot',
|
|
'spot': True,
|
|
'margin': False,
|
|
'swap': False,
|
|
'future': False,
|
|
'option': False,
|
|
'active': active,
|
|
'contract': False,
|
|
'linear': None,
|
|
'inverse': None,
|
|
'contractSize': None,
|
|
'expiry': None,
|
|
'expiryDatetime': None,
|
|
'strike': None,
|
|
'optionType': None,
|
|
'precision': {
|
|
'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'baseStep'))),
|
|
'price': self.parse_number(self.parse_precision(self.safe_string(market, 'quoteStep'))),
|
|
},
|
|
'limits': {
|
|
'leverage': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'amount': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'price': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'cost': {
|
|
'min': minCost,
|
|
'max': None,
|
|
},
|
|
},
|
|
'created': created,
|
|
'info': market,
|
|
})
|
|
|
|
async def fetch_currencies(self, params={}) -> Currencies:
|
|
"""
|
|
fetches all available currencies on an exchange
|
|
|
|
https://bit.team/trade/api/documentation#/PUBLIC/getTradeApiCurrencies
|
|
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: an associative dictionary of currencies
|
|
"""
|
|
response = await self.publicGetTradeApiCurrencies(params)
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "count": 24,
|
|
# "currencies": [
|
|
# {
|
|
# "txLimits": {
|
|
# "minDeposit": "0.0001",
|
|
# "minWithdraw": "0.02",
|
|
# "maxWithdraw": "10000",
|
|
# "withdrawCommissionPercentage": "NaN",
|
|
# "withdrawCommissionFixed": "0.005"
|
|
# },
|
|
# "id": 2,
|
|
# "status": 1,
|
|
# "symbol": "eth",
|
|
# "title": "Ethereum",
|
|
# "logoURL": "https://ethereum.org/static/6b935ac0e6194247347855dc3d328e83/34ca5/eth-diamond-black.png",
|
|
# "isDiscount": False,
|
|
# "address": "https://ethereum.org/",
|
|
# "description": "Ethereum ETH",
|
|
# "decimals": 18,
|
|
# "blockChain": "Ethereum",
|
|
# "precision": 8,
|
|
# "currentRate": null,
|
|
# "active": True,
|
|
# "timeStart": "2021-01-28T08:57:41.719Z",
|
|
# "type": "crypto",
|
|
# "typeNetwork": "internalGW",
|
|
# "idSorting": 2,
|
|
# "links": [
|
|
# {
|
|
# "tx": "https://etherscan.io/tx/",
|
|
# "address": "https://etherscan.io/address/",
|
|
# "blockChain": "Ethereum"
|
|
# }
|
|
# ]
|
|
# },
|
|
# {
|
|
# "txLimits": {
|
|
# "minDeposit": "0.001",
|
|
# "minWithdraw": "1",
|
|
# "maxWithdraw": "100000",
|
|
# "withdrawCommissionPercentage": "NaN",
|
|
# "withdrawCommissionFixed": {
|
|
# "Tron": "2",
|
|
# "Binance": "2",
|
|
# "Ethereum": "20"
|
|
# }
|
|
# },
|
|
# "id": 3,
|
|
# "status": 1,
|
|
# "symbol": "usdt",
|
|
# "title": "Tether USD",
|
|
# "logoURL": "https://cryptologos.cc/logos/tether-usdt-logo.png?v=010",
|
|
# "isDiscount": False,
|
|
# "address": "https://tether.to/",
|
|
# "description": "Tether USD",
|
|
# "decimals": 6,
|
|
# "blockChain": "",
|
|
# "precision": 6,
|
|
# "currentRate": null,
|
|
# "active": True,
|
|
# "timeStart": "2021-01-28T09:04:17.170Z",
|
|
# "type": "crypto",
|
|
# "typeNetwork": "internalGW",
|
|
# "idSorting": 0,
|
|
# "links": [
|
|
# {
|
|
# "tx": "https://etherscan.io/tx/",
|
|
# "address": "https://etherscan.io/address/",
|
|
# "blockChain": "Ethereum"
|
|
# },
|
|
# {
|
|
# "tx": "https://tronscan.org/#/transaction/",
|
|
# "address": "https://tronscan.org/#/address/",
|
|
# "blockChain": "Tron"
|
|
# },
|
|
# {
|
|
# "tx": "https://bscscan.com/tx/",
|
|
# "address": "https://bscscan.com/address/",
|
|
# "blockChain": "Binance"
|
|
# }
|
|
# ]
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
responseResult = self.safe_value(response, 'result', {})
|
|
currencies = self.safe_value(responseResult, 'currencies', [])
|
|
# usding another endpoint to fetch statuses of deposits and withdrawals
|
|
statusesResponse = await self.publicGetTradeApiCmcAssets()
|
|
#
|
|
# {
|
|
# "ZNX": {
|
|
# "name": "ZeNeX Coin",
|
|
# "unified_cryptoasset_id": 30,
|
|
# "withdrawStatus": True,
|
|
# "depositStatus": True,
|
|
# "min_withdraw": 0.00001,
|
|
# "max_withdraw": 10000
|
|
# },
|
|
# "USDT": {
|
|
# "name": "Tether USD",
|
|
# "unified_cryptoasset_id": 3,
|
|
# "withdrawStatus": True,
|
|
# "depositStatus": True,
|
|
# "min_withdraw": 1,
|
|
# "max_withdraw": 100000
|
|
# },
|
|
# }
|
|
#
|
|
statusesResponse = self.index_by(statusesResponse, 'unified_cryptoasset_id')
|
|
result: dict = {}
|
|
for i in range(0, len(currencies)):
|
|
currency = currencies[i]
|
|
id = self.safe_string(currency, 'symbol')
|
|
numericId = self.safe_integer(currency, 'id')
|
|
code = self.safe_currency_code(id)
|
|
active = self.safe_bool(currency, 'active', False)
|
|
precision = self.parse_number(self.parse_precision(self.safe_string(currency, 'precision')))
|
|
txLimits = self.safe_value(currency, 'txLimits', {})
|
|
minWithdraw = self.safe_string(txLimits, 'minWithdraw')
|
|
maxWithdraw = self.safe_string(txLimits, 'maxWithdraw')
|
|
minDeposit = self.safe_string(txLimits, 'minDeposit')
|
|
fee = None
|
|
withdrawCommissionFixed = self.safe_value(txLimits, 'withdrawCommissionFixed', {})
|
|
feesByNetworkId: dict = {}
|
|
blockChain = self.safe_string(currency, 'blockChain')
|
|
# if only one blockChain
|
|
if (blockChain is not None) and (blockChain != ''):
|
|
fee = self.parse_number(withdrawCommissionFixed)
|
|
feesByNetworkId[blockChain] = fee
|
|
else:
|
|
feesByNetworkId = withdrawCommissionFixed
|
|
statuses = self.safe_value(statusesResponse, numericId, {})
|
|
deposit = self.safe_value(statuses, 'depositStatus')
|
|
withdraw = self.safe_value(statuses, 'withdrawStatus')
|
|
networkIds = list(feesByNetworkId.keys())
|
|
networks: dict = {}
|
|
networkPrecision = self.parse_number(self.parse_precision(self.safe_string(currency, 'decimals')))
|
|
typeRaw = self.safe_string(currency, 'type')
|
|
for j in range(0, len(networkIds)):
|
|
networkId = networkIds[j]
|
|
networkCode = self.network_id_to_code(networkId, code)
|
|
networkFee = self.safe_number(feesByNetworkId, networkId)
|
|
networks[networkCode] = {
|
|
'id': networkId,
|
|
'network': networkCode,
|
|
'deposit': deposit,
|
|
'withdraw': withdraw,
|
|
'active': active,
|
|
'fee': networkFee,
|
|
'precision': networkPrecision,
|
|
'limits': {
|
|
'amount': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'withdraw': {
|
|
'min': self.parse_number(minWithdraw),
|
|
'max': self.parse_number(maxWithdraw),
|
|
},
|
|
'deposit': {
|
|
'min': self.parse_number(minDeposit),
|
|
'max': None,
|
|
},
|
|
},
|
|
'info': currency,
|
|
}
|
|
result[code] = {
|
|
'id': id,
|
|
'numericId': numericId,
|
|
'code': code,
|
|
'name': code,
|
|
'info': currency,
|
|
'active': active,
|
|
'deposit': deposit,
|
|
'withdraw': withdraw,
|
|
'fee': fee,
|
|
'precision': precision,
|
|
'limits': {
|
|
'amount': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'withdraw': {
|
|
'min': self.parse_number(minWithdraw),
|
|
'max': self.parse_number(maxWithdraw),
|
|
},
|
|
'deposit': {
|
|
'min': self.parse_number(minDeposit),
|
|
'max': None,
|
|
},
|
|
},
|
|
'type': typeRaw, # 'crypto' or 'fiat'
|
|
'networks': networks,
|
|
}
|
|
return result
|
|
|
|
async def fetch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
|
"""
|
|
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
:param str 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 dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
resolution = self.safe_string(self.timeframes, timeframe, timeframe)
|
|
request: dict = {
|
|
'pairName': market['id'],
|
|
'resolution': resolution,
|
|
}
|
|
response = await self.historyGetApiTwHistoryPairNameResolution(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "count": 364,
|
|
# "data": [
|
|
# {
|
|
# "t": 1669593600,
|
|
# "o": 16211.259266,
|
|
# "h": 16476.985001,
|
|
# "l": 16023.714999,
|
|
# "c": 16430.636894,
|
|
# "v": 2.60150368999999
|
|
# },
|
|
# {
|
|
# "t": 1669680000,
|
|
# "o": 16430.636894,
|
|
# "h": 17065.229582,
|
|
# "l": 16346.114155,
|
|
# "c": 16882.297736,
|
|
# "v": 3.0872548400000115
|
|
# },
|
|
# ...
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
data = self.safe_list(result, 'data', [])
|
|
return self.parse_ohlcvs(data, market, timeframe, since, limit)
|
|
|
|
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
|
#
|
|
# {
|
|
# "t": 1669680000,
|
|
# "o": 16430.636894,
|
|
# "h": 17065.229582,
|
|
# "l": 16346.114155,
|
|
# "c": 16882.297736,
|
|
# "v": 3.0872548400000115
|
|
# },
|
|
#
|
|
return [
|
|
self.safe_timestamp(ohlcv, 't'),
|
|
self.safe_number(ohlcv, 'o'),
|
|
self.safe_number(ohlcv, 'h'),
|
|
self.safe_number(ohlcv, 'l'),
|
|
self.safe_number(ohlcv, 'c'),
|
|
self.safe_number(ohlcv, 'v'),
|
|
]
|
|
|
|
async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
"""
|
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
|
|
https://bit.team/trade/api/documentation#/CMC/getTradeApiCmcOrderbookPair
|
|
|
|
:param str symbol: unified symbol of the market to fetch the order book for
|
|
:param int [limit]: the maximum amount of order book entries to return(default 100, max 200)
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: A dictionary of `order book structures <https://github.com/ccxt/ccxt/wiki/Manual#order-book-structure>` indexed by market symbols
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'pair': market['id'],
|
|
}
|
|
response = await self.publicGetTradeApiCmcOrderbookPair(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "timestamp": 1701166703285,
|
|
# "bids": [
|
|
# [
|
|
# 2019.334988,
|
|
# 0.09048525
|
|
# ],
|
|
# [
|
|
# 1999.860002,
|
|
# 0.0225
|
|
# ],
|
|
# ...
|
|
# ],
|
|
# "asks": [
|
|
# [
|
|
# 2019.334995,
|
|
# 0.00899078
|
|
# ],
|
|
# [
|
|
# 2019.335013,
|
|
# 0.09833052
|
|
# ],
|
|
# ...
|
|
# ]
|
|
# }
|
|
#
|
|
timestamp = self.safe_integer(response, 'timestamp')
|
|
orderbook = self.parse_order_book(response, symbol, timestamp)
|
|
return orderbook
|
|
|
|
async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
"""
|
|
fetches information on multiple orders made by the user
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiCcxtOrdersofuser
|
|
|
|
:param str 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(default 10)
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:param str [params.type]: the status of the order - 'active', 'closed', 'cancelled', 'all', 'history'(default 'all')
|
|
:returns Order[]: a list of `order structures <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
type = self.safe_string(params, 'type', 'all')
|
|
request: dict = {
|
|
'type': type,
|
|
}
|
|
market = None
|
|
if symbol is not None:
|
|
market = self.market(symbol)
|
|
request['pair'] = market['id']
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = await self.privateGetTradeApiCcxtOrdersOfUser(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "count": 3,
|
|
# "orders": [
|
|
# {
|
|
# "id": 106733026,
|
|
# "orderId": null,
|
|
# "userId": 21639,
|
|
# "pair": "btc_usdt",
|
|
# "pairId": 22,
|
|
# "quantity": "0.00001",
|
|
# "price": "40",
|
|
# "executedPrice": "0",
|
|
# "fee": null,
|
|
# "orderCid": null,
|
|
# "executed": "0",
|
|
# "expires": null,
|
|
# "baseDecimals": 8,
|
|
# "quoteDecimals": 6,
|
|
# "timestamp": 1700594804,
|
|
# "status": "inactive",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "createdAt": "2023-11-21T19:26:43.868Z",
|
|
# "updatedAt": "2023-11-21T19:26:43.868Z"
|
|
# },
|
|
# {
|
|
# "id": 106733308,
|
|
# "orderId": "13074362",
|
|
# "userId": 21639,
|
|
# "pair": "btc_usdt",
|
|
# "pairId": 22,
|
|
# "quantity": "0.00001",
|
|
# "price": "50000",
|
|
# "executedPrice": "37017.495008",
|
|
# "fee": {
|
|
# "amount": "0.00000002",
|
|
# "symbol": "btc",
|
|
# "userId": 21639,
|
|
# "decimals": 8,
|
|
# "symbolId": 11
|
|
# },
|
|
# "orderCid": null,
|
|
# "executed": "0.00001",
|
|
# "expires": null,
|
|
# "baseDecimals": 8,
|
|
# "quoteDecimals": 6,
|
|
# "timestamp": 1700594959,
|
|
# "status": "executed",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "createdAt": "2023-11-21T19:29:19.946Z",
|
|
# "updatedAt": "2023-11-21T19:29:19.946Z"
|
|
# },
|
|
# {
|
|
# "id": 106734455,
|
|
# "orderId": "13248984",
|
|
# "userId": 21639,
|
|
# "pair": "eth_usdt",
|
|
# "pairId": 2,
|
|
# "quantity": "0.001",
|
|
# "price": "1750",
|
|
# "executedPrice": "0",
|
|
# "fee": null,
|
|
# "orderCid": null,
|
|
# "executed": "0",
|
|
# "expires": null,
|
|
# "baseDecimals": 18,
|
|
# "quoteDecimals": 6,
|
|
# "timestamp": 1700595523,
|
|
# "status": "accepted",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "createdAt": "2023-11-21T19:38:43.530Z",
|
|
# "updatedAt": "2023-11-21T19:38:43.530Z"
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
orders = self.safe_list(result, 'orders', [])
|
|
return self.parse_orders(orders, market, since, limit)
|
|
|
|
async def fetch_order(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
"""
|
|
fetches information on an order
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiCcxtOrderId
|
|
|
|
:param int|str id: order id
|
|
:param str symbol: not used by bitteam fetchOrder()
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: An `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
request: dict = {
|
|
'id': id,
|
|
}
|
|
market = None
|
|
if symbol is not None:
|
|
market = self.market(symbol)
|
|
response = await self.privateGetTradeApiCcxtOrderId(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "id": 106494347,
|
|
# "orderId": "13214332",
|
|
# "userId": 15912,
|
|
# "pair": "eth_usdt",
|
|
# "pairId": 2,
|
|
# "quantity": "0.00448598",
|
|
# "price": "2015.644995",
|
|
# "executedPrice": "2015.644995",
|
|
# "fee": {
|
|
# "amount": "0",
|
|
# "symbol": "eth",
|
|
# "userId": 15912,
|
|
# "decimals": 18,
|
|
# "symbolId": 2,
|
|
# "discountAmount": "0",
|
|
# "discountSymbol": "btt",
|
|
# "discountDecimals": 18,
|
|
# "discountSymbolId": 5
|
|
# },
|
|
# "orderCid": null,
|
|
# "executed": "0.00448598",
|
|
# "expires": null,
|
|
# "baseDecimals": 18,
|
|
# "quoteDecimals": 6,
|
|
# "timestamp": 1700470476,
|
|
# "status": "executed",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "stopPrice": null,
|
|
# "slippage": null
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_dict(response, 'result')
|
|
return self.parse_order(result, market)
|
|
|
|
async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
"""
|
|
fetch all unfilled currently open orders
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiCcxtOrdersofuser
|
|
|
|
:param str symbol: unified market symbol
|
|
:param int [since]: the earliest time in ms to fetch open orders for
|
|
:param int [limit]: the maximum number of open order structures to retrieve(default 10)
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns Order[]: a list of `order structures <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
request: dict = {
|
|
'type': 'active',
|
|
}
|
|
return await self.fetch_orders(symbol, since, limit, self.extend(request, params))
|
|
|
|
async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
"""
|
|
fetches information on multiple closed orders made by the user
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiCcxtOrdersofuser
|
|
|
|
:param str 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 closed order structures to retrieve(default 10)
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns Order[]: a list of `order structures <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
request: dict = {
|
|
'type': 'closed',
|
|
}
|
|
return await self.fetch_orders(symbol, since, limit, self.extend(request, params))
|
|
|
|
async def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
"""
|
|
fetches information on multiple canceled orders made by the user
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiCcxtOrdersofuser
|
|
|
|
:param str 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 canceled order structures to retrieve(default 10)
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: a list of `order structures <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
request: dict = {
|
|
'type': 'cancelled',
|
|
}
|
|
return await self.fetch_orders(symbol, since, limit, self.extend(request, params))
|
|
|
|
async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
|
"""
|
|
create a trade order
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/postTradeApiCcxtOrdercreate
|
|
|
|
:param str symbol: unified symbol of the market to create an order in
|
|
:param str type: 'market' or 'limit'
|
|
:param str 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 dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: an `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'pairId': str(market['numericId']),
|
|
'type': type,
|
|
'side': side,
|
|
'amount': self.amount_to_precision(symbol, amount),
|
|
}
|
|
if type == 'limit':
|
|
if price is None:
|
|
raise ArgumentsRequired(self.id + ' createOrder() requires a price argument for a ' + type + ' order')
|
|
else:
|
|
request['price'] = self.price_to_precision(symbol, price)
|
|
response = await self.privatePostTradeApiCcxtOrdercreate(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "id": 106733308,
|
|
# "userId": 21639,
|
|
# "quantity": "0.00001",
|
|
# "pair": "btc_usdt",
|
|
# "side": "buy",
|
|
# "price": "50000",
|
|
# "executed": "0",
|
|
# "executedPrice": "0",
|
|
# "status": "created",
|
|
# "baseDecimals": 8,
|
|
# "quoteDecimals": 6,
|
|
# "pairId": 22,
|
|
# "type": "limit",
|
|
# "stopPrice": null,
|
|
# "slippage": null,
|
|
# "timestamp": "1700594959"
|
|
# }
|
|
# }
|
|
#
|
|
order = self.safe_dict(response, 'result', {})
|
|
return self.parse_order(order, market)
|
|
|
|
async def cancel_order(self, id: str, symbol: Str = None, params={}):
|
|
"""
|
|
cancels an open order
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/postTradeApiCcxtCancelorder
|
|
|
|
:param str id: order id
|
|
:param str symbol: not used by bitteam cancelOrder()
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: An `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
request: dict = {
|
|
'id': id,
|
|
}
|
|
response = await self.privatePostTradeApiCcxtCancelorder(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "message": "The request to cancel your order was received"
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_dict(response, 'result', {})
|
|
return self.parse_order(result)
|
|
|
|
async def cancel_all_orders(self, symbol: Str = None, params={}):
|
|
"""
|
|
cancel open orders of market
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/postTradeApiCcxtCancelallorder
|
|
|
|
:param str symbol: unified market symbol
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict[]: a list of `order structures <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
market = None
|
|
request: dict = {}
|
|
if symbol is not None:
|
|
market = self.market(symbol)
|
|
request['pairId'] = str(market['numericId'])
|
|
else:
|
|
request['pairId'] = '0' # '0' for all markets
|
|
response = await self.privatePostTradeApiCcxtCancelAllOrder(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "message":"The request to cancel all your orders was received"
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
orders = [result]
|
|
return self.parse_orders(orders, market)
|
|
|
|
def parse_order(self, order: dict, market: Market = None) -> Order:
|
|
#
|
|
# fetchOrders
|
|
# {
|
|
# "id": 106733308,
|
|
# "orderId": "13074362",
|
|
# "userId": 21639,
|
|
# "pair": "btc_usdt",
|
|
# "pairId": 22,
|
|
# "quantity": "0.00001",
|
|
# "price": "50000",
|
|
# "executedPrice": "37017.495008",
|
|
# "fee": {
|
|
# "amount": "0.00000002",
|
|
# "symbol": "btc",
|
|
# "userId": 21639,
|
|
# "decimals": 8,
|
|
# "symbolId": 11
|
|
# },
|
|
# "orderCid": null,
|
|
# "executed": "0.00001",
|
|
# "expires": null,
|
|
# "baseDecimals": 8,
|
|
# "quoteDecimals": 6,
|
|
# "timestamp": 1700594959,
|
|
# "status": "executed",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "createdAt": "2023-11-21T19:29:19.946Z",
|
|
# "updatedAt": "2023-11-21T19:29:19.946Z"
|
|
# },
|
|
#
|
|
# fetchOrder
|
|
# {
|
|
# "id": 106494347,
|
|
# "orderId": "13214332",
|
|
# "userId": 15912,
|
|
# "pair": "eth_usdt",
|
|
# "pairId": 2,
|
|
# "quantity": "0.00448598",
|
|
# "price": "2015.644995",
|
|
# "executedPrice": "2015.644995",
|
|
# "fee": {
|
|
# "amount": "0",
|
|
# "symbol": "eth",
|
|
# "userId": 15912,
|
|
# "decimals": 18,
|
|
# "symbolId": 2,
|
|
# "discountAmount": "0",
|
|
# "discountSymbol": "btt",
|
|
# "discountDecimals": 18,
|
|
# "discountSymbolId": 5
|
|
# },
|
|
# "orderCid": null,
|
|
# "executed": "0.00448598",
|
|
# "expires": null,
|
|
# "baseDecimals": 18,
|
|
# "quoteDecimals": 6,
|
|
# "timestamp": 1700470476,
|
|
# "status": "executed",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "stopPrice": null,
|
|
# "slippage": null
|
|
# }
|
|
#
|
|
# createOrder
|
|
# {
|
|
# "id": 106733308,
|
|
# "userId": 21639,
|
|
# "quantity": "0.00001",
|
|
# "pair": "btc_usdt",
|
|
# "side": "buy",
|
|
# "price": "50000",
|
|
# "executed": "0",
|
|
# "executedPrice": "0",
|
|
# "status": "created",
|
|
# "baseDecimals": 8,
|
|
# "quoteDecimals": 6,
|
|
# "pairId": 22,
|
|
# "type": "limit",
|
|
# "stopPrice": null,
|
|
# "slippage": null,
|
|
# "timestamp": "1700594959"
|
|
# }
|
|
#
|
|
id = self.safe_string(order, 'id')
|
|
marketId = self.safe_string(order, 'pair')
|
|
market = self.safe_market(marketId, market)
|
|
clientOrderId = self.safe_string(order, 'orderCid')
|
|
timestamp = None
|
|
createdAt = self.safe_string(order, 'createdAt')
|
|
if createdAt is not None:
|
|
timestamp = self.parse8601(createdAt)
|
|
else:
|
|
timestamp = self.safe_timestamp(order, 'timestamp')
|
|
updatedAt = self.safe_string(order, 'updatedAt')
|
|
lastUpdateTimestamp = self.parse8601(updatedAt)
|
|
status = self.parse_order_status(self.safe_string(order, 'status'))
|
|
type = self.parse_order_type(self.safe_string(order, 'type'))
|
|
side = self.safe_string(order, 'side')
|
|
feeRaw = self.safe_value(order, 'fee')
|
|
price = self.safe_string(order, 'price')
|
|
amount = self.safe_string(order, 'quantity')
|
|
filled = self.safe_string(order, 'executed')
|
|
fee = None
|
|
if feeRaw is not None:
|
|
feeCost = self.safe_string(feeRaw, 'amount')
|
|
feeCurrencyId = self.safe_string(feeRaw, 'symbol')
|
|
fee = {
|
|
'currency': self.safe_currency_code(feeCurrencyId),
|
|
'cost': feeCost,
|
|
'rate': None,
|
|
}
|
|
return self.safe_order({
|
|
'id': id,
|
|
'clientOrderId': clientOrderId,
|
|
'timestamp': timestamp,
|
|
'datetime': self.iso8601(timestamp),
|
|
'lastTradeTimestamp': None,
|
|
'lastUpdateTimestamp': lastUpdateTimestamp,
|
|
'status': status,
|
|
'symbol': market['symbol'],
|
|
'type': type,
|
|
'timeInForce': 'GTC',
|
|
'side': side,
|
|
'price': price,
|
|
'triggerPrice': self.safe_string(order, 'stopPrice'),
|
|
'average': None,
|
|
'amount': amount,
|
|
'cost': None,
|
|
'filled': filled,
|
|
'remaining': None,
|
|
'fee': fee,
|
|
'trades': None,
|
|
'info': order,
|
|
'postOnly': False,
|
|
}, market)
|
|
|
|
def parse_order_status(self, status: Str):
|
|
statuses: dict = {
|
|
'accepted': 'open',
|
|
'executed': 'closed',
|
|
'cancelled': 'canceled',
|
|
'partiallyCancelled': 'canceled',
|
|
'delete': 'rejected',
|
|
'inactive': 'rejected',
|
|
'executing': 'open',
|
|
'created': 'open',
|
|
}
|
|
return self.safe_string(statuses, status, status)
|
|
|
|
def parse_order_type(self, status):
|
|
statuses: dict = {
|
|
'market': 'market',
|
|
'limit': 'limit',
|
|
}
|
|
return self.safe_string(statuses, status, status)
|
|
|
|
def parse_value_to_pricision(self, valueObject, valueKey, preciseObject, precisionKey):
|
|
valueRawString = self.safe_string(valueObject, valueKey)
|
|
precisionRawString = self.safe_string(preciseObject, precisionKey)
|
|
if valueRawString is None or precisionRawString is None:
|
|
return None
|
|
precisionString = self.parse_precision(precisionRawString)
|
|
return Precise.string_mul(valueRawString, precisionString)
|
|
|
|
async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
|
"""
|
|
fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
|
|
|
|
https://bit.team/trade/api/documentation#/CMC/getTradeApiCmcSummary
|
|
|
|
:param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: a dictionary of `ticker structures <https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
response = await self.publicGetTradeApiCmcSummary()
|
|
#
|
|
# [
|
|
# {
|
|
# "trading_pairs": "BTC_USDT",
|
|
# "base_currency": "BTC",
|
|
# "quote_currency": "USDT",
|
|
# "last_price": 37669.955001,
|
|
# "lowest_ask": 37670.055,
|
|
# "highest_bid": 37669.955,
|
|
# "base_volume": 6.81156888,
|
|
# "quote_volume": 257400.516878529,
|
|
# "price_change_percent_24h": -0.29,
|
|
# "highest_price_24h": 38389.994463,
|
|
# "lowest_price_24h": 37574.894999
|
|
# },
|
|
# {
|
|
# "trading_pairs": "BNB_USDT",
|
|
# "base_currency": "BNB",
|
|
# "quote_currency": "USDT",
|
|
# "last_price": 233.525142,
|
|
# "lowest_ask": 233.675,
|
|
# "highest_bid": 233.425,
|
|
# "base_volume": 245.0199339,
|
|
# "quote_volume": 57356.91823827642,
|
|
# "price_change_percent_24h": -0.32,
|
|
# "highest_price_24h": 236.171123,
|
|
# "lowest_price_24h": 231.634637
|
|
# },
|
|
# ...
|
|
# ]
|
|
#
|
|
tickers = []
|
|
if not isinstance(response, list):
|
|
response = []
|
|
for i in range(0, len(response)):
|
|
rawTicker = response[i]
|
|
ticker = self.parse_ticker(rawTicker)
|
|
tickers.append(ticker)
|
|
return self.filter_by_array_tickers(tickers, 'symbol', symbols)
|
|
|
|
async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
"""
|
|
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
|
|
https://bit.team/trade/api/documentation#/PUBLIC/getTradeApiPairName
|
|
|
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: a `ticker structure <https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'name': market['id'],
|
|
}
|
|
response = await self.publicGetTradeApiPairName(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "pair": {
|
|
# "id": 2,
|
|
# "name": "eth_usdt",
|
|
# "baseAssetId": 2,
|
|
# "quoteAssetId": 3,
|
|
# "fullName": "ETH USDT",
|
|
# "description": "ETH USDT",
|
|
# "lastBuy": "1976.715012",
|
|
# "lastSell": "1971.995006",
|
|
# "lastPrice": "1976.715012",
|
|
# "change24": "1.02",
|
|
# "volume24": 24.0796457,
|
|
# "volume24USD": 44282.347995912205,
|
|
# "active": True,
|
|
# "baseStep": 8,
|
|
# "quoteStep": 6,
|
|
# "status": 1,
|
|
# "settings": {
|
|
# "limit_usd": "0.1",
|
|
# "price_max": "10000000000000",
|
|
# "price_min": "1",
|
|
# "price_tick": "1",
|
|
# "pricescale": 10000,
|
|
# "lot_size_max": "1000000000000000",
|
|
# "lot_size_min": "1",
|
|
# "lot_size_tick": "1",
|
|
# "price_view_min": 6,
|
|
# "default_slippage": 10,
|
|
# "lot_size_view_min": 6
|
|
# },
|
|
# "asks": [
|
|
# {
|
|
# "price": "1976.405003",
|
|
# "quantity": "0.0051171",
|
|
# "amount": "10.1134620408513"
|
|
# },
|
|
# {
|
|
# "price": "1976.405013",
|
|
# "quantity": "0.09001559",
|
|
# "amount": "177.90726332415267"
|
|
# },
|
|
# {
|
|
# "price": "2010.704988",
|
|
# "quantity": "0.00127892",
|
|
# "amount": "2.57153082325296"
|
|
# }
|
|
# ],
|
|
# "bids": [
|
|
# {
|
|
# "price": "1976.404988",
|
|
# "quantity": "0.09875861",
|
|
# "amount": "195.18700941194668"
|
|
# },
|
|
# {
|
|
# "price": "1905.472973",
|
|
# "quantity": "0.00263591",
|
|
# "amount": "5.02265526426043"
|
|
# },
|
|
# {
|
|
# "price": "1904.274973",
|
|
# "quantity": "0.09425304",
|
|
# "amount": "179.48370520116792"
|
|
# }
|
|
# ],
|
|
# "updateId": "78",
|
|
# "timeStart": "2021-01-28T09:19:30.706Z",
|
|
# "makerFee": 200,
|
|
# "takerFee": 200,
|
|
# "quoteVolume24": 49125.1374009045,
|
|
# "lowPrice24": 1966.704999,
|
|
# "highPrice24": 2080.354997,
|
|
# "baseCurrency": {
|
|
# "id": 2,
|
|
# "status": 1,
|
|
# "symbol": "eth",
|
|
# "title": "Ethereum",
|
|
# "logoURL": "https://ethereum.org/static/6b935ac0e6194247347855dc3d328e83/34ca5/eth-diamond-black.png",
|
|
# "isDiscount": False,
|
|
# "address": "https://ethereum.org/",
|
|
# "description": "Ethereum ETH",
|
|
# "decimals": 18,
|
|
# "blockChain": "Ethereum",
|
|
# "precision": 8,
|
|
# "currentRate": null,
|
|
# "active": True,
|
|
# "timeStart": "2021-01-28T08:57:41.719Z",
|
|
# "txLimits": {
|
|
# "minDeposit": "100000000000000",
|
|
# "maxWithdraw": "10000000000000000000000",
|
|
# "minWithdraw": "20000000000000000",
|
|
# "withdrawCommissionFixed": "5000000000000000",
|
|
# "withdrawCommissionPercentage": "NaN"
|
|
# },
|
|
# "type": "crypto",
|
|
# "typeNetwork": "internalGW",
|
|
# "icon": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMzAiIHZpZXdCb3g9IjAgMCAzMCAzMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgMTVDMCA2LjcxNTczIDYuNzE1NzMgMCAxNSAwVjBDMjMuMjg0MyAwIDMwIDYuNzE1NzMgMzAgMTVWMTVDMzAgMjMuMjg0MyAyMy4yODQzIDMwIDE1IDMwVjMwQzYuNzE1NzMgMzAgMCAyMy4yODQzIDAgMTVWMTVaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNMTQuOTU1NyAxOS45NzM5TDkgMTYuMzUwOUwxNC45NTIxIDI1TDIwLjkxMDkgMTYuMzUwOUwxNC45NTIxIDE5Ljk3MzlIMTQuOTU1N1pNMTUuMDQ0MyA1TDkuMDkwOTUgMTUuMTg1M0wxNS4wNDQzIDE4LjgxNDZMMjEgMTUuMTg5MUwxNS4wNDQzIDVaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K",
|
|
# "idSorting": 2,
|
|
# "links": [
|
|
# {
|
|
# "tx": "https://etherscan.io/tx/",
|
|
# "address": "https://etherscan.io/address/",
|
|
# "blockChain": "Ethereum"
|
|
# }
|
|
# ],
|
|
# "clientTxLimits": {
|
|
# "minDeposit": "0.0001",
|
|
# "minWithdraw": "0.02",
|
|
# "maxWithdraw": "10000",
|
|
# "withdrawCommissionPercentage": "NaN",
|
|
# "withdrawCommissionFixed": "0.005"
|
|
# }
|
|
# },
|
|
# "quoteCurrency": {
|
|
# "id": 3,
|
|
# "status": 1,
|
|
# "symbol": "usdt",
|
|
# "title": "Tether USD",
|
|
# "logoURL": "https://cryptologos.cc/logos/tether-usdt-logo.png?v=010",
|
|
# "isDiscount": False,
|
|
# "address": "https://tether.to/",
|
|
# "description": "Tether USD",
|
|
# "decimals": 6,
|
|
# "blockChain": "",
|
|
# "precision": 6,
|
|
# "currentRate": null,
|
|
# "active": True,
|
|
# "timeStart": "2021-01-28T09:04:17.170Z",
|
|
# "txLimits": {
|
|
# "minDeposit": "1000",
|
|
# "maxWithdraw": "100000000000",
|
|
# "minWithdraw": "1000000",
|
|
# "withdrawCommissionFixed": {
|
|
# "Tron": "2000000",
|
|
# "Binance": "2000000000000000000",
|
|
# "Ethereum": "20000000"
|
|
# },
|
|
# "withdrawCommissionPercentage": "NaN"
|
|
# },
|
|
# "type": "crypto",
|
|
# "typeNetwork": "internalGW",
|
|
# "icon": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMzAiIHZpZXdCb3g9IjAgMCAzMCAzMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTAgMTVDMCA2LjcxNTczIDYuNzE1NzMgMCAxNSAwVjBDMjMuMjg0MyAwIDMwIDYuNzE1NzMgMzAgMTVWMTVDMzAgMjMuMjg0MyAyMy4yODQzIDMwIDE1IDMwVjMwQzYuNzE1NzMgMzAgMCAyMy4yODQzIDAgMTVWMTVaIiBmaWxsPSIjNkZBNjg4Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjMgN0g3VjExSDEzVjEyLjA2MkM4Ljk5MjAyIDEyLjMxNDYgNiAxMy4zMTAyIDYgMTQuNUM2IDE1LjY4OTggOC45OTIwMiAxNi42ODU0IDEzIDE2LjkzOFYyM0gxN1YxNi45MzhDMjEuMDA4IDE2LjY4NTQgMjQgMTUuNjg5OCAyNCAxNC41QzI0IDEzLjMxMDIgMjEuMDA4IDEyLjMxNDYgMTcgMTIuMDYyVjExSDIzVjdaTTcuNSAxNC41QzcuNSAxMy40NjA2IDkuMzMzMzMgMTIuMzY4IDEzIDEyLjA3NTZWMTUuNUgxN1YxMi4wNzU5QzIwLjkzODQgMTIuMzkyNyAyMi41IDEzLjYzMzkgMjIuNSAxNC41QzIyLjUgMTUuMzIyIDIwLjAwMDggMTUuODA2MSAxNyAxNS45NTI1QzE1LjcwODIgMTYuMDQ2MiAxMy43OTUxIDE1Ljk4MjYgMTMgMTUuOTM5MUM5Ljk5OTIxIDE1Ljc1NTkgNy41IDE1LjE4MDkgNy41IDE0LjVaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K",
|
|
# "idSorting": 0,
|
|
# "links": [
|
|
# {
|
|
# "tx": "https://etherscan.io/tx/",
|
|
# "address": "https://etherscan.io/address/",
|
|
# "blockChain": "Ethereum"
|
|
# },
|
|
# {
|
|
# "tx": "https://tronscan.org/#/transaction/",
|
|
# "address": "https://tronscan.org/#/address/",
|
|
# "blockChain": "Tron"
|
|
# },
|
|
# {
|
|
# "tx": "https://bscscan.com/tx/",
|
|
# "address": "https://bscscan.com/address/",
|
|
# "blockChain": "Binance"
|
|
# }
|
|
# ],
|
|
# "clientTxLimits": {
|
|
# "minDeposit": "0.001",
|
|
# "minWithdraw": "1",
|
|
# "maxWithdraw": "100000",
|
|
# "withdrawCommissionPercentage": "NaN",
|
|
# "withdrawCommissionFixed": {
|
|
# "Tron": "2",
|
|
# "Binance": "2",
|
|
# "Ethereum": "20"
|
|
# }
|
|
# }
|
|
# },
|
|
# "quantities": {
|
|
# "asks": "5.58760757",
|
|
# "bids": "2226.98663823032198"
|
|
# }
|
|
# }
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
pair = self.safe_dict(result, 'pair', {})
|
|
return self.parse_ticker(pair, market)
|
|
|
|
def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
|
|
#
|
|
# fetchTicker
|
|
# {
|
|
# "id": 2,
|
|
# "name": "eth_usdt",
|
|
# "baseAssetId": 2,
|
|
# "quoteAssetId": 3,
|
|
# "fullName": "ETH USDT",
|
|
# "description": "ETH USDT",
|
|
# "lastBuy": "1976.715012",
|
|
# "lastSell": "1971.995006",
|
|
# "lastPrice": "1976.715012",
|
|
# "change24": "1.02",
|
|
# "volume24": 24.0796457,
|
|
# "volume24USD": 44282.347995912205,
|
|
# "active": True,
|
|
# "baseStep": 8,
|
|
# "quoteStep": 6,
|
|
# "status": 1,
|
|
# "asks": [
|
|
# {
|
|
# "price": "1976.405003",
|
|
# "quantity": "0.0051171",
|
|
# "amount": "10.1134620408513"
|
|
# },
|
|
# {
|
|
# "price": "1976.405013",
|
|
# "quantity": "0.09001559",
|
|
# "amount": "177.90726332415267"
|
|
# },
|
|
# {
|
|
# "price": "2010.704988",
|
|
# "quantity": "0.00127892",
|
|
# "amount": "2.57153082325296"
|
|
# }
|
|
# ...
|
|
# ],
|
|
# "bids": [
|
|
# {
|
|
# "price": "1976.404988",
|
|
# "quantity": "0.09875861",
|
|
# "amount": "195.18700941194668"
|
|
# },
|
|
# {
|
|
# "price": "1905.472973",
|
|
# "quantity": "0.00263591",
|
|
# "amount": "5.02265526426043"
|
|
# },
|
|
# {
|
|
# "price": "1904.274973",
|
|
# "quantity": "0.09425304",
|
|
# "amount": "179.48370520116792"
|
|
# }
|
|
# ...
|
|
# ],
|
|
# "updateId": "78",
|
|
# "timeStart": "2021-01-28T09:19:30.706Z",
|
|
# "makerFee": 200,
|
|
# "takerFee": 200,
|
|
# "quoteVolume24": 49125.1374009045,
|
|
# "lowPrice24": 1966.704999,
|
|
# "highPrice24": 2080.354997,
|
|
# ...
|
|
# }
|
|
#
|
|
# fetchTickers
|
|
# {
|
|
# "trading_pairs": "BTC_USDT",
|
|
# "base_currency": "BTC",
|
|
# "quote_currency": "USDT",
|
|
# "last_price": 37669.955001,
|
|
# "lowest_ask": 37670.055,
|
|
# "highest_bid": 37669.955,
|
|
# "base_volume": 6.81156888,
|
|
# "quote_volume": 257400.516878529,
|
|
# "price_change_percent_24h": -0.29,
|
|
# "highest_price_24h": 38389.994463,
|
|
# "lowest_price_24h": 37574.894999
|
|
# }
|
|
marketId = self.safe_string_lower(ticker, 'trading_pairs')
|
|
market = self.safe_market(marketId, market)
|
|
bestBidPrice = None
|
|
bestAskPrice = None
|
|
bestBidVolume = None
|
|
bestAskVolume = None
|
|
bids = self.safe_value(ticker, 'bids')
|
|
asks = self.safe_value(ticker, 'asks')
|
|
if (bids is not None) and (isinstance(bids, list)) and (asks is not None) and (isinstance(asks, list)):
|
|
bestBid = self.safe_value(bids, 0, {})
|
|
bestBidPrice = self.safe_string(bestBid, 'price')
|
|
bestBidVolume = self.safe_string(bestBid, 'quantity')
|
|
bestAsk = self.safe_value(asks, 0, {})
|
|
bestAskPrice = self.safe_string(bestAsk, 'price')
|
|
bestAskVolume = self.safe_string(bestAsk, 'quantity')
|
|
else:
|
|
bestBidPrice = self.safe_string(ticker, 'highest_bid')
|
|
bestAskPrice = self.safe_string(ticker, 'lowest_ask')
|
|
baseVolume = self.safe_string_2(ticker, 'volume24', 'base_volume')
|
|
quoteVolume = self.safe_string_2(ticker, 'quoteVolume24', 'quote_volume')
|
|
high = self.safe_string_2(ticker, 'highPrice24', 'highest_price_24h')
|
|
low = self.safe_string_2(ticker, 'lowPrice24', 'lowest_price_24h')
|
|
close = self.safe_string_2(ticker, 'lastPrice', 'last_price')
|
|
changePcnt = self.safe_string_2(ticker, 'change24', 'price_change_percent_24h')
|
|
return self.safe_ticker({
|
|
'symbol': market['symbol'],
|
|
'timestamp': None,
|
|
'datetime': None,
|
|
'open': None,
|
|
'high': high,
|
|
'low': low,
|
|
'close': close,
|
|
'bid': bestBidPrice,
|
|
'bidVolume': bestBidVolume,
|
|
'ask': bestAskPrice,
|
|
'askVolume': bestAskVolume,
|
|
'vwap': None,
|
|
'previousClose': None,
|
|
'change': None,
|
|
'percentage': changePcnt,
|
|
'average': None,
|
|
'baseVolume': baseVolume,
|
|
'quoteVolume': quoteVolume,
|
|
'info': ticker,
|
|
}, market)
|
|
|
|
async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
"""
|
|
get the list of most recent trades for a particular symbol
|
|
|
|
https://bit.team/trade/api/documentation#/CMC/getTradeApiCmcTradesPair
|
|
|
|
:param str 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 dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns Trade[]: a list of `trade structures <https://github.com/ccxt/ccxt/wiki/Manual#public-trades>`
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'pair': market['id'],
|
|
}
|
|
response = await self.publicGetTradeApiCmcTradesPair(self.extend(request, params))
|
|
#
|
|
# [
|
|
# {
|
|
# "trade_id": 34970337,
|
|
# "price": 37769.994793,
|
|
# "base_volume": 0.00119062,
|
|
# "quote_volume": 44.96971120044166,
|
|
# "timestamp": 1700827234000,
|
|
# "type": "buy"
|
|
# },
|
|
# {
|
|
# "trade_id": 34970347,
|
|
# "price": 37769.634497,
|
|
# "base_volume": 0.00104009,
|
|
# "quote_volume": 39.28381914398473,
|
|
# "timestamp": 1700827248000,
|
|
# "type": "buy"
|
|
# },
|
|
# ...
|
|
# ]
|
|
#
|
|
return self.parse_trades(response, market, since, limit)
|
|
|
|
async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
"""
|
|
fetch all trades made by the user
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiCcxtTradesofuser
|
|
|
|
:param str 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(default 10)
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns Trade[]: a list of `trade structures <https://github.com/ccxt/ccxt/wiki/Manual#trade-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
request: dict = {}
|
|
market = None
|
|
if symbol is not None:
|
|
market = self.market(symbol)
|
|
request['pairId'] = market['numericId']
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = await self.privateGetTradeApiCcxtTradesOfUser(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "count": 3,
|
|
# "trades": [
|
|
# {
|
|
# "id": 34880724,
|
|
# "tradeId": "4368041",
|
|
# "makerOrderId": 106742914,
|
|
# "takerOrderId": 106761614,
|
|
# "pairId": 2,
|
|
# "quantity": "0.00955449",
|
|
# "price": "1993.674994",
|
|
# "isBuyerMaker": True,
|
|
# "baseDecimals": 18,
|
|
# "quoteDecimals": 6,
|
|
# "side": "sell",
|
|
# "timestamp": 1700615250,
|
|
# "rewarded": True,
|
|
# "makerUserId": 21639,
|
|
# "takerUserId": 15913,
|
|
# "baseCurrencyId": 2,
|
|
# "quoteCurrencyId": 3,
|
|
# "feeMaker": {
|
|
# "amount": "0.0000191",
|
|
# "symbol": "eth",
|
|
# "userId": 21639,
|
|
# "decimals": 18,
|
|
# "symbolId": 2
|
|
# },
|
|
# "feeTaker": {
|
|
# "amount": "0",
|
|
# "symbol": "usdt",
|
|
# "userId": 15913,
|
|
# "decimals": 6,
|
|
# "symbolId": 3,
|
|
# "discountAmount": "0",
|
|
# "discountSymbol": "btt",
|
|
# "discountDecimals": 18,
|
|
# "discountSymbolId": 5
|
|
# },
|
|
# "pair": "eth_usdt",
|
|
# "createdAt": "2023-11-22T01:07:30.593Z",
|
|
# "updatedAt": "2023-11-22T01:10:00.117Z",
|
|
# "isCurrentSide": "maker"
|
|
# },
|
|
# {
|
|
# "id": 34875793,
|
|
# "tradeId": "4368010",
|
|
# "makerOrderId": 106742914,
|
|
# "takerOrderId": 106745926,
|
|
# "pairId": 2,
|
|
# "quantity": "0.0027193",
|
|
# "price": "1993.674994",
|
|
# "isBuyerMaker": True,
|
|
# "baseDecimals": 18,
|
|
# "quoteDecimals": 6,
|
|
# "side": "sell",
|
|
# "timestamp": 1700602983,
|
|
# "rewarded": True,
|
|
# "makerUserId": 21639,
|
|
# "takerUserId": 15912,
|
|
# "baseCurrencyId": 2,
|
|
# "quoteCurrencyId": 3,
|
|
# "feeMaker": {
|
|
# "amount": "0.00000543",
|
|
# "symbol": "eth",
|
|
# "userId": 21639,
|
|
# "decimals": 18,
|
|
# "symbolId": 2
|
|
# },
|
|
# "feeTaker": {
|
|
# "amount": "0",
|
|
# "symbol": "usdt",
|
|
# "userId": 15912,
|
|
# "decimals": 6,
|
|
# "symbolId": 3,
|
|
# "discountAmount": "0",
|
|
# "discountSymbol": "btt",
|
|
# "discountDecimals": 18,
|
|
# "discountSymbolId": 5
|
|
# },
|
|
# "pair": "eth_usdt",
|
|
# "createdAt": "2023-11-21T21:43:02.758Z",
|
|
# "updatedAt": "2023-11-21T21:45:00.147Z",
|
|
# "isCurrentSide": "maker"
|
|
# },
|
|
# {
|
|
# "id": 34871727,
|
|
# "tradeId": "3441840",
|
|
# "makerOrderId": 106733299,
|
|
# "takerOrderId": 106733308,
|
|
# "pairId": 22,
|
|
# "quantity": "0.00001",
|
|
# "price": "37017.495008",
|
|
# "isBuyerMaker": False,
|
|
# "baseDecimals": 8,
|
|
# "quoteDecimals": 6,
|
|
# "side": "buy",
|
|
# "timestamp": 1700594960,
|
|
# "rewarded": True,
|
|
# "makerUserId": 15909,
|
|
# "takerUserId": 21639,
|
|
# "baseCurrencyId": 11,
|
|
# "quoteCurrencyId": 3,
|
|
# "feeMaker": {
|
|
# "amount": "0",
|
|
# "symbol": "usdt",
|
|
# "userId": 15909,
|
|
# "decimals": 6,
|
|
# "symbolId": 3,
|
|
# "discountAmount": "0",
|
|
# "discountSymbol": "btt",
|
|
# "discountDecimals": 18,
|
|
# "discountSymbolId": 5
|
|
# },
|
|
# "feeTaker": {
|
|
# "amount": "0.00000002",
|
|
# "symbol": "btc",
|
|
# "userId": 21639,
|
|
# "decimals": 8,
|
|
# "symbolId": 11
|
|
# },
|
|
# "pair": "btc_usdt",
|
|
# "createdAt": "2023-11-21T19:29:20.092Z",
|
|
# "updatedAt": "2023-11-21T19:30:00.159Z"
|
|
# "isCurrentSide": "taker"
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
trades = self.safe_list(result, 'trades', [])
|
|
return self.parse_trades(trades, market, since, limit)
|
|
|
|
def parse_trade(self, trade: dict, market: Market = None) -> Trade:
|
|
#
|
|
# fetchTrades
|
|
# {
|
|
# "trade_id": 34970337,
|
|
# "price": 37769.994793,
|
|
# "base_volume": 0.00119062,
|
|
# "quote_volume": 44.96971120044166,
|
|
# "timestamp": 1700827234000,
|
|
# "type": "buy"
|
|
# },
|
|
#
|
|
# fetchMyTrades
|
|
# {
|
|
# "id": 34875793,
|
|
# "tradeId": "4368010",
|
|
# "makerOrderId": 106742914,
|
|
# "takerOrderId": 106745926,
|
|
# "pairId": 2,
|
|
# "quantity": "0.0027193",
|
|
# "price": "1993.674994",
|
|
# "isBuyerMaker": True,
|
|
# "baseDecimals": 18,
|
|
# "quoteDecimals": 6,
|
|
# "side": "sell",
|
|
# "timestamp": 1700602983,
|
|
# "rewarded": True,
|
|
# "makerUserId": 21639,
|
|
# "takerUserId": 15912,
|
|
# "baseCurrencyId": 2,
|
|
# "quoteCurrencyId": 3,
|
|
# "feeMaker": {
|
|
# "amount": "0.00000543",
|
|
# "symbol": "eth",
|
|
# "userId": 21639,
|
|
# "decimals": 18,
|
|
# "symbolId": 2
|
|
# },
|
|
# "feeTaker": {
|
|
# "amount": "0",
|
|
# "symbol": "usdt",
|
|
# "userId": 15912,
|
|
# "decimals": 6,
|
|
# "symbolId": 3,
|
|
# "discountAmount": "0",
|
|
# "discountSymbol": "btt",
|
|
# "discountDecimals": 18,
|
|
# "discountSymbolId": 5
|
|
# },
|
|
# "pair": "eth_usdt",
|
|
# "createdAt": "2023-11-21T21:43:02.758Z",
|
|
# "updatedAt": "2023-11-21T21:45:00.147Z",
|
|
# "isCurrentSide": "maker"
|
|
# }
|
|
#
|
|
marketId = self.safe_string(trade, 'pair')
|
|
market = self.safe_market(marketId, market)
|
|
symbol = market['symbol']
|
|
id = self.safe_string_2(trade, 'id', 'trade_id')
|
|
price = self.safe_string(trade, 'price')
|
|
amount = self.safe_string_2(trade, 'quantity', 'base_volume')
|
|
cost = self.safe_string(trade, 'quote_volume')
|
|
takerOrMaker = self.safe_string(trade, 'isCurrentSide')
|
|
timestamp = self.safe_string(trade, 'timestamp')
|
|
if takerOrMaker is not None:
|
|
timestamp = Precise.string_mul(timestamp, '1000')
|
|
# the exchange returns the side of the taker
|
|
side = self.safe_string_2(trade, 'side', 'type')
|
|
feeInfo = None
|
|
order = None
|
|
if takerOrMaker == 'maker':
|
|
if side == 'sell':
|
|
side = 'buy'
|
|
elif side == 'buy':
|
|
side = 'sell'
|
|
order = self.safe_string(trade, 'makerOrderId')
|
|
feeInfo = self.safe_value(trade, 'feeMaker', {})
|
|
elif takerOrMaker == 'taker':
|
|
order = self.safe_string(trade, 'takerOrderId')
|
|
feeInfo = self.safe_value(trade, 'feeTaker', {})
|
|
feeCurrencyId = self.safe_string(feeInfo, 'symbol')
|
|
feeCost = self.safe_string(feeInfo, 'amount')
|
|
fee = {
|
|
'currency': self.safe_currency_code(feeCurrencyId),
|
|
'cost': feeCost,
|
|
}
|
|
intTs = self.parse_to_int(timestamp)
|
|
return self.safe_trade({
|
|
'id': id,
|
|
'order': order,
|
|
'timestamp': intTs,
|
|
'datetime': self.iso8601(intTs),
|
|
'symbol': symbol,
|
|
'type': None,
|
|
'side': side,
|
|
'takerOrMaker': takerOrMaker,
|
|
'price': price,
|
|
'amount': amount,
|
|
'cost': cost,
|
|
'fee': fee,
|
|
'info': trade,
|
|
}, market)
|
|
|
|
async def fetch_balance(self, params={}) -> Balances:
|
|
"""
|
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiCcxtBalance
|
|
|
|
:param dict [params]: extra parameters specific to the betteam api endpoint
|
|
:returns dict: a `balance structure <https://github.com/ccxt/ccxt/wiki/Manual#balance-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
response = await self.privateGetTradeApiCcxtBalance(params)
|
|
return self.parse_balance(response)
|
|
|
|
def parse_balance(self, response) -> Balances:
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "free": {
|
|
# "USDT": "0",
|
|
# "DEL": "0",
|
|
# "BTC": "0",
|
|
# ...
|
|
# },
|
|
# "used": {
|
|
# "USDT": "0",
|
|
# "DEL": "0",
|
|
# "BTC": "0",
|
|
# ...
|
|
# },
|
|
# "total": {
|
|
# "USDT": "0",
|
|
# "DEL": "0",
|
|
# "BTC": "0",
|
|
# ...
|
|
# },
|
|
# "USDT": {
|
|
# "free": "0",
|
|
# "used": "0",
|
|
# "total": "0",
|
|
# },
|
|
# "DEL": {
|
|
# "free": "0",
|
|
# "used": "0",
|
|
# "total": "0",
|
|
# },
|
|
# "BTC": {
|
|
# "free": "0",
|
|
# "used": "0",
|
|
# "total": "0",
|
|
# }
|
|
# ...
|
|
# }
|
|
# }
|
|
#
|
|
timestamp = self.milliseconds()
|
|
balance: dict = {
|
|
'info': response,
|
|
'timestamp': timestamp,
|
|
'datetime': self.iso8601(timestamp),
|
|
}
|
|
result = self.safe_value(response, 'result', {})
|
|
balanceByCurrencies = self.omit(result, ['free', 'used', 'total'])
|
|
rawCurrencyIds = list(balanceByCurrencies.keys())
|
|
for i in range(0, len(rawCurrencyIds)):
|
|
rawCurrencyId = rawCurrencyIds[i]
|
|
currencyBalance = self.safe_value(result, rawCurrencyId)
|
|
free = self.safe_string(currencyBalance, 'free')
|
|
used = self.safe_string(currencyBalance, 'used')
|
|
total = self.safe_string(currencyBalance, 'total')
|
|
currencyCode = self.safe_currency_code(rawCurrencyId.lower())
|
|
balance[currencyCode] = {
|
|
'free': free,
|
|
'used': used,
|
|
'total': total,
|
|
}
|
|
return self.safe_balance(balance)
|
|
|
|
async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
|
"""
|
|
fetch history of deposits and withdrawals from external wallets and between CoinList Pro trading account and CoinList wallet
|
|
|
|
https://bit.team/trade/api/documentation#/PRIVATE/getTradeApiTransactionsofuser
|
|
|
|
:param str [code]: unified currency code for the currency of the deposit/withdrawals
|
|
:param int [since]: timestamp in ms of the earliest deposit/withdrawal
|
|
:param int [limit]: max number of deposit/withdrawals to return(default 10)
|
|
:param dict [params]: extra parameters specific to the bitteam api endpoint
|
|
:returns dict: a list of `transaction structure <https://github.com/ccxt/ccxt/wiki/Manual#transaction-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
currency = None
|
|
request: dict = {}
|
|
if code is not None:
|
|
currency = self.currency(code)
|
|
request['currency'] = currency['numericId']
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = await self.privateGetTradeApiTransactionsOfUser(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "ok": True,
|
|
# "result": {
|
|
# "count": 2,
|
|
# "transactions": [
|
|
# {
|
|
# "id": 1329686,
|
|
# "orderId": "2f060ad5-30f7-4f2b-ac5f-1bb8f5fd34dc",
|
|
# "transactionCoreId": "561863",
|
|
# "userId": 21639,
|
|
# "recipient": "0x9050dfA063D1bE7cA711c750b18D51fDD13e90Ee",
|
|
# "sender": "0x6894a93B6fea044584649278621723cac51443Cd",
|
|
# "symbolId": 2,
|
|
# "CommissionId": 17571,
|
|
# "amount": "44000000000000000",
|
|
# "params": {},
|
|
# "reason": null,
|
|
# "timestamp": 1700715341743,
|
|
# "status": "approving",
|
|
# "statusDescription": null,
|
|
# "type": "withdraw",
|
|
# "message": null,
|
|
# "blockChain": "",
|
|
# "before": null,
|
|
# "after": null,
|
|
# "currency": {
|
|
# "symbol": "eth",
|
|
# "decimals": 18,
|
|
# "blockChain": "Ethereum",
|
|
# "links": [
|
|
# {
|
|
# "tx": "https://etherscan.io/tx/",
|
|
# "address": "https://etherscan.io/address/",
|
|
# "blockChain": "Ethereum"
|
|
# }
|
|
# ]
|
|
# }
|
|
# },
|
|
# {
|
|
# "id": 1329229,
|
|
# "orderId": null,
|
|
# "transactionCoreId": "561418",
|
|
# "userId": 21639,
|
|
# "recipient": "0x7d6a797f2406e06b2f9b41d067df324affa315dd",
|
|
# "sender": null,
|
|
# "symbolId": 3,
|
|
# "CommissionId": null,
|
|
# "amount": "100000000",
|
|
# "params": {
|
|
# "tx_id": "0x2253823c828d838acd983fe6a348fb0e034efe3874b081871d8b80da76ec758b"
|
|
# },
|
|
# "reason": null,
|
|
# "timestamp": 1700594180417,
|
|
# "status": "success",
|
|
# "statusDescription": null,
|
|
# "type": "deposit",
|
|
# "message": null,
|
|
# "blockChain": "Ethereum",
|
|
# "before": 0,
|
|
# "after": 100000000,
|
|
# "currency": {
|
|
# "symbol": "usdt",
|
|
# "decimals": 6,
|
|
# "blockChain": "",
|
|
# "links": [
|
|
# {
|
|
# "tx": "https://etherscan.io/tx/",
|
|
# "address": "https://etherscan.io/address/",
|
|
# "blockChain": "Ethereum"
|
|
# },
|
|
# {
|
|
# "tx": "https://tronscan.org/#/transaction/",
|
|
# "address": "https://tronscan.org/#/address/",
|
|
# "blockChain": "Tron"
|
|
# },
|
|
# {
|
|
# "tx": "https://bscscan.com/tx/",
|
|
# "address": "https://bscscan.com/address/",
|
|
# "blockChain": "Binance"
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
transactions = self.safe_list(result, 'transactions', [])
|
|
return self.parse_transactions(transactions, currency, since, limit)
|
|
|
|
def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
|
|
#
|
|
# {
|
|
# "id": 1329229,
|
|
# "orderId": null,
|
|
# "transactionCoreId": "561418",
|
|
# "userId": 21639,
|
|
# "recipient": "0x7d6a797f2406e06b2f9b41d067df324affa315dd",
|
|
# "sender": null,
|
|
# "symbolId": 3,
|
|
# "CommissionId": null,
|
|
# "amount": "100000000",
|
|
# "params": {
|
|
# "tx_id": "0x2253823c828d838acd983fe6a348fb0e034efe3874b081871d8b80da76ec758b"
|
|
# },
|
|
# "reason": null,
|
|
# "timestamp": 1700594180417,
|
|
# "status": "success",
|
|
# "statusDescription": null,
|
|
# "type": "deposit",
|
|
# "message": null,
|
|
# "blockChain": "Ethereum",
|
|
# "before": 0,
|
|
# "after": 100000000,
|
|
# "currency": {
|
|
# "symbol": "usdt",
|
|
# "decimals": 6,
|
|
# "blockChain": "",
|
|
# "links": [
|
|
# {
|
|
# "tx": "https://etherscan.io/tx/",
|
|
# "address": "https://etherscan.io/address/",
|
|
# "blockChain": "Ethereum"
|
|
# },
|
|
# {
|
|
# "tx": "https://tronscan.org/#/transaction/",
|
|
# "address": "https://tronscan.org/#/address/",
|
|
# "blockChain": "Tron"
|
|
# },
|
|
# {
|
|
# "tx": "https://bscscan.com/tx/",
|
|
# "address": "https://bscscan.com/address/",
|
|
# "blockChain": "Binance"
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
currencyObject = self.safe_value(transaction, 'currency')
|
|
currencyId = self.safe_string(currencyObject, 'symbol')
|
|
code = self.safe_currency_code(currencyId, currency)
|
|
id = self.safe_string(transaction, 'id')
|
|
params = self.safe_value(transaction, 'params')
|
|
txid = self.safe_string(params, 'tx_id')
|
|
timestamp = self.safe_integer(transaction, 'timestamp')
|
|
networkId = self.safe_string(transaction, 'blockChain')
|
|
if networkId is None:
|
|
links = self.safe_value(currencyObject, 'links', [])
|
|
blockChain = self.safe_value(links, 0, {})
|
|
networkId = self.safe_string(blockChain, 'blockChain')
|
|
addressFrom = self.safe_string(transaction, 'sender')
|
|
addressTo = self.safe_string(transaction, 'recipient')
|
|
tag = self.safe_string(transaction, 'message')
|
|
type = self.parse_transaction_type(self.safe_string(transaction, 'type'))
|
|
amount = self.parse_value_to_pricision(transaction, 'amount', currencyObject, 'decimals')
|
|
status = self.parse_transaction_status(self.safe_value(transaction, 'status'))
|
|
return {
|
|
'info': transaction,
|
|
'id': id,
|
|
'txid': txid,
|
|
'timestamp': timestamp,
|
|
'datetime': self.iso8601(timestamp),
|
|
'network': self.network_id_to_code(networkId),
|
|
'addressFrom': addressFrom,
|
|
'address': None,
|
|
'addressTo': addressTo,
|
|
'tagFrom': None,
|
|
'tag': tag,
|
|
'tagTo': None,
|
|
'type': type,
|
|
'amount': self.parse_number(amount),
|
|
'currency': code,
|
|
'status': status,
|
|
'updated': None,
|
|
'fee': None,
|
|
'comment': self.safe_string(transaction, 'description'),
|
|
'internal': False,
|
|
}
|
|
|
|
def parse_transaction_type(self, type):
|
|
types: dict = {
|
|
'deposit': 'deposit',
|
|
'withdraw': 'withdrawal',
|
|
}
|
|
return self.safe_string(types, type, type)
|
|
|
|
def parse_transaction_status(self, status: Str):
|
|
statuses: dict = {
|
|
'approving': 'pending',
|
|
'success': 'ok',
|
|
}
|
|
return self.safe_string(statuses, status, status)
|
|
|
|
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
|
request = self.omit(params, self.extract_params(path))
|
|
endpoint = '/' + self.implode_params(path, params)
|
|
url = self.urls['api'][api] + endpoint
|
|
query = self.urlencode(request)
|
|
if api == 'private':
|
|
self.check_required_credentials()
|
|
if method == 'POST':
|
|
body = self.json(request)
|
|
elif len(query) != 0:
|
|
url += '?' + query
|
|
auth = self.apiKey + ':' + self.secret
|
|
auth64 = self.string_to_base64(auth)
|
|
signature = 'Basic ' + auth64
|
|
headers = {
|
|
'Authorization': signature,
|
|
'Content-Type': 'application/json',
|
|
}
|
|
elif len(query) != 0:
|
|
url += '?' + query
|
|
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
|
|
|
def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
|
if response is None:
|
|
return None
|
|
if code != 200:
|
|
if code == 404:
|
|
if (url.find('/ccxt/order/') >= 0) and (method == 'GET'):
|
|
parts = url.split('/order/')
|
|
orderId = self.safe_string(parts, 1)
|
|
raise OrderNotFound(self.id + ' order ' + orderId + ' not found')
|
|
if url.find('/cmc/orderbook/') >= 0:
|
|
parts = url.split('/cmc/orderbook/')
|
|
symbolId = self.safe_string(parts, 1)
|
|
raise BadSymbol(self.id + ' symbolId ' + symbolId + ' not found')
|
|
feedback = self.id + ' ' + body
|
|
message = self.safe_string(response, 'message')
|
|
responseCode = self.safe_string(response, 'code')
|
|
self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
|
|
self.throw_exactly_matched_exception(self.exceptions['exact'], responseCode, feedback)
|
|
raise ExchangeError(feedback)
|
|
return None
|