1317 lines
57 KiB
Python
1317 lines
57 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.base.exchange import Exchange
|
|
from ccxt.abstract.p2b import ImplicitAPI
|
|
import hashlib
|
|
from ccxt.base.types import Any, Int, Market, Num, Order, OrderSide, OrderType, Str, Strings, Ticker, Tickers
|
|
from typing import List
|
|
from ccxt.base.errors import AuthenticationError
|
|
from ccxt.base.errors import ArgumentsRequired
|
|
from ccxt.base.errors import BadRequest
|
|
from ccxt.base.errors import InsufficientFunds
|
|
from ccxt.base.errors import ExchangeNotAvailable
|
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
|
|
|
|
|
class p2b(Exchange, ImplicitAPI):
|
|
|
|
def describe(self) -> Any:
|
|
return self.deep_extend(super(p2b, self).describe(), {
|
|
'id': 'p2b',
|
|
'name': 'p2b',
|
|
'countries': ['LT'],
|
|
'rateLimit': 100,
|
|
'version': 'v2',
|
|
'pro': True,
|
|
'has': {
|
|
'CORS': None,
|
|
'spot': True,
|
|
'margin': False,
|
|
'swap': False,
|
|
'future': False,
|
|
'option': False,
|
|
'addMargin': False,
|
|
'borrowCrossMargin': False,
|
|
'borrowIsolatedMargin': False,
|
|
'borrowMargin': False,
|
|
'cancelAllOrders': False,
|
|
'cancelOrder': True,
|
|
'cancelOrders': False,
|
|
'closeAllPositions': False,
|
|
'closePosition': False,
|
|
'createDepositAddress': False,
|
|
'createMarketOrder': False,
|
|
'createOrder': True,
|
|
'createOrders': False,
|
|
'createPostOnlyOrder': False,
|
|
'createReduceOnlyOrder': False,
|
|
'createStopLimitOrder': False,
|
|
'createStopMarketOrder': False,
|
|
'createStopOrder': False,
|
|
'fetchAccounts': False,
|
|
'fetchAllGreeks': False,
|
|
'fetchBalance': True,
|
|
'fetchBorrowInterest': False,
|
|
'fetchBorrowRate': False,
|
|
'fetchBorrowRateHistories': False,
|
|
'fetchBorrowRateHistory': False,
|
|
'fetchBorrowRates': False,
|
|
'fetchBorrowRatesPerSymbol': False,
|
|
'fetchClosedOrders': True,
|
|
'fetchCrossBorrowRate': False,
|
|
'fetchCrossBorrowRates': False,
|
|
'fetchDeposit': False,
|
|
'fetchDepositAddress': False,
|
|
'fetchDepositAddresses': False,
|
|
'fetchDepositAddressesByNetwork': False,
|
|
'fetchDeposits': False,
|
|
'fetchDepositsWithdrawals': False,
|
|
'fetchFundingHistory': False,
|
|
'fetchFundingInterval': False,
|
|
'fetchFundingIntervals': False,
|
|
'fetchFundingRate': False,
|
|
'fetchFundingRateHistory': False,
|
|
'fetchFundingRates': False,
|
|
'fetchGreeks': False,
|
|
'fetchIndexOHLCV': False,
|
|
'fetchIsolatedBorrowRate': False,
|
|
'fetchIsolatedBorrowRates': False,
|
|
'fetchIsolatedPositions': False,
|
|
'fetchLedger': False,
|
|
'fetchLedgerEntry': 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,
|
|
'fetchMarkPrice': False,
|
|
'fetchMarkPrices': False,
|
|
'fetchMyLiquidations': False,
|
|
'fetchMySettlementHistory': False,
|
|
'fetchMyTrades': True,
|
|
'fetchOHLCV': True,
|
|
'fetchOpenInterest': False,
|
|
'fetchOpenInterestHistory': False,
|
|
'fetchOpenInterests': False,
|
|
'fetchOpenOrders': True,
|
|
'fetchOption': False,
|
|
'fetchOptionChain': False,
|
|
'fetchOrderBook': True,
|
|
'fetchOrderBooks': False,
|
|
'fetchOrders': False,
|
|
'fetchOrderTrades': True,
|
|
'fetchPosition': False,
|
|
'fetchPositionHistory': False,
|
|
'fetchPositionMode': False,
|
|
'fetchPositions': False,
|
|
'fetchPositionsForSymbol': False,
|
|
'fetchPositionsHistory': False,
|
|
'fetchPositionsRisk': False,
|
|
'fetchPremiumIndexOHLCV': False,
|
|
'fetchSettlementHistory': False,
|
|
'fetchTicker': True,
|
|
'fetchTickers': True,
|
|
'fetchTrades': True,
|
|
'fetchTradingLimits': False,
|
|
'fetchTransactionFee': False,
|
|
'fetchTransactionFees': False,
|
|
'fetchTransactions': False,
|
|
'fetchTransfers': False,
|
|
'fetchUnderlyingAssets': False,
|
|
'fetchVolatilityHistory': False,
|
|
'fetchWithdrawAddresses': False,
|
|
'fetchWithdrawal': False,
|
|
'fetchWithdrawals': False,
|
|
'reduceMargin': False,
|
|
'repayCrossMargin': False,
|
|
'repayIsolatedMargin': False,
|
|
'setLeverage': False,
|
|
'setMargin': False,
|
|
'setMarginMode': False,
|
|
'setPositionMode': False,
|
|
'signIn': False,
|
|
'transfer': False,
|
|
'withdraw': False,
|
|
},
|
|
'timeframes': {
|
|
'1m': '1m',
|
|
'1h': '1h',
|
|
'1d': '1d',
|
|
},
|
|
'urls': {
|
|
'extension': '.json',
|
|
'referral': 'https://p2pb2b.com?referral=ee784c53',
|
|
'logo': 'https://github.com/ccxt/ccxt/assets/43336371/8da13a80-1f0a-49be-bb90-ff8b25164755',
|
|
'api': {
|
|
'public': 'https://api.p2pb2b.com/api/v2/public',
|
|
'private': 'https://api.p2pb2b.com/api/v2',
|
|
},
|
|
'www': 'https://p2pb2b.com/',
|
|
'doc': 'https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md',
|
|
'fees': 'https://p2pb2b.com/fee-schedule/',
|
|
},
|
|
'api': {
|
|
'public': {
|
|
'get': {
|
|
'markets': 1,
|
|
'market': 1,
|
|
'tickers': 1,
|
|
'ticker': 1,
|
|
'book': 1,
|
|
'history': 1,
|
|
'depth/result': 1,
|
|
'market/kline': 1,
|
|
},
|
|
},
|
|
'private': {
|
|
'post': {
|
|
'account/balances': 1,
|
|
'account/balance': 1,
|
|
'order/new': 1,
|
|
'order/cancel': 1,
|
|
'orders': 1,
|
|
'account/market_order_history': 1,
|
|
'account/market_deal_history': 1,
|
|
'account/order': 1,
|
|
'account/order_history': 1,
|
|
'account/executed_history': 1,
|
|
},
|
|
},
|
|
},
|
|
'fees': {
|
|
'trading': {
|
|
'tierBased': True,
|
|
'percentage': True,
|
|
'taker': [
|
|
[self.parse_number('0'), self.parse_number('0.2')],
|
|
[self.parse_number('1'), self.parse_number('0.19')],
|
|
[self.parse_number('5'), self.parse_number('0.18')],
|
|
[self.parse_number('10'), self.parse_number('0.17')],
|
|
[self.parse_number('25'), self.parse_number('0.16')],
|
|
[self.parse_number('75'), self.parse_number('0.15')],
|
|
[self.parse_number('100'), self.parse_number('0.14')],
|
|
[self.parse_number('150'), self.parse_number('0.13')],
|
|
[self.parse_number('300'), self.parse_number('0.12')],
|
|
[self.parse_number('450'), self.parse_number('0.11')],
|
|
[self.parse_number('500'), self.parse_number('0.1')],
|
|
],
|
|
'maker': [
|
|
[self.parse_number('0'), self.parse_number('0.2')],
|
|
[self.parse_number('1'), self.parse_number('0.18')],
|
|
[self.parse_number('5'), self.parse_number('0.16')],
|
|
[self.parse_number('10'), self.parse_number('0.14')],
|
|
[self.parse_number('25'), self.parse_number('0.12')],
|
|
[self.parse_number('75'), self.parse_number('0.1')],
|
|
[self.parse_number('100'), self.parse_number('0.08')],
|
|
[self.parse_number('150'), self.parse_number('0.06')],
|
|
[self.parse_number('300'), self.parse_number('0.04')],
|
|
[self.parse_number('450'), self.parse_number('0.02')],
|
|
[self.parse_number('500'), self.parse_number('0.01')],
|
|
],
|
|
},
|
|
},
|
|
'features': {
|
|
'spot': {
|
|
'sandbox': False,
|
|
'createOrder': {
|
|
'marginMode': False,
|
|
'triggerPrice': False,
|
|
'triggerDirection': False,
|
|
'triggerPriceType': None,
|
|
'stopLossPrice': False,
|
|
'takeProfitPrice': False,
|
|
'attachedStopLossTakeProfit': None,
|
|
'timeInForce': {
|
|
'IOC': True,
|
|
'FOK': True,
|
|
'PO': True,
|
|
'GTD': False,
|
|
},
|
|
'hedged': False,
|
|
'trailing': False,
|
|
'leverage': False,
|
|
'marketBuyByCost': False,
|
|
'marketBuyRequiresPrice': False,
|
|
'selfTradePrevention': False,
|
|
'iceberg': False,
|
|
},
|
|
'createOrders': None,
|
|
'fetchMyTrades': {
|
|
'marginMode': False,
|
|
'limit': 100,
|
|
'daysBack': 100000, # todo
|
|
'untilDays': 1,
|
|
'symbolRequired': True,
|
|
},
|
|
'fetchOrder': None, # todo
|
|
'fetchOpenOrders': {
|
|
'marginMode': False,
|
|
'limit': 100,
|
|
'trigger': False,
|
|
'trailing': False,
|
|
'symbolRequired': True,
|
|
},
|
|
'fetchOrders': None, # todo
|
|
'fetchClosedOrders': {
|
|
'marginMode': False,
|
|
'limit': 100,
|
|
'daysBack': 100000, # todo
|
|
'daysBackCanceled': 1 / 12, # todo
|
|
'untilDays': 1,
|
|
'trigger': False,
|
|
'trailing': False,
|
|
'symbolRequired': False,
|
|
},
|
|
'fetchOHLCV': {
|
|
'limit': 500,
|
|
},
|
|
},
|
|
'swap': {
|
|
'linear': None,
|
|
'inverse': None,
|
|
},
|
|
'future': {
|
|
'linear': None,
|
|
'inverse': None,
|
|
},
|
|
},
|
|
'commonCurrencies': {
|
|
},
|
|
'precisionMode': TICK_SIZE,
|
|
'exceptions': {
|
|
'1001': AuthenticationError, # Key not provided. X-TXC-APIKEY header is missing in the request or empty.
|
|
'1002': AuthenticationError, # Payload not provided. X-TXC-PAYLOAD header is missing in the request or empty.
|
|
'1003': AuthenticationError, # Signature not provided. X-TXC-SIGNATURE header is missing in the request or empty.
|
|
'1004': AuthenticationError, # Nonce and url not provided. Request body is empty. Missing required parameters "request", "nonce".
|
|
'1005': AuthenticationError, # Invalid body data. Invalid request body
|
|
'1006': AuthenticationError, # Nonce not provided. Request body missing required parameter "nonce".
|
|
'1007': AuthenticationError, # Request not provided. Request body missing required parameter "request".
|
|
'1008': AuthenticationError, # Invalid request in body. The passed request parameter does not match the URL of self request.
|
|
'1009': AuthenticationError, # Invalid payload. The transmitted payload value(X-TXC-PAYLOAD header) does not match the request body.
|
|
'1010': AuthenticationError, # This action is unauthorized. - API key passed in the X-TXC-APIKEY header does not exist. - Access to API is not activated. Go to profile and activate access.
|
|
'1011': AuthenticationError, # This action is unauthorized. Please, enable two-factor authentication. Two-factor authentication is not activated for the user.
|
|
'1012': AuthenticationError, # Invalid nonce. Parameter "nonce" is not a number.
|
|
'1013': AuthenticationError, # Too many requests. - A request came with a repeated value of nonce. - Received more than the limited value of requests(10) within one second.
|
|
'1014': AuthenticationError, # Unauthorized request. Signature value passed(in the X-TXC-SIGNATURE header) does not match the request body.
|
|
'1015': AuthenticationError, # Temporary block. Temporary blocking. There is a cancellation of orders.
|
|
'1016': AuthenticationError, # Not unique nonce. The request was sent with a repeated parameter "nonce" within 10 seconds.
|
|
'2010': BadRequest, # Currency not found. Currency not found.
|
|
'2020': BadRequest, # Market is not available. Market is not available.
|
|
'2021': BadRequest, # Unknown market. Unknown market.
|
|
'2030': BadRequest, # Order not found. Order not found.
|
|
'2040': InsufficientFunds, # Balance not enough. Insufficient balance.
|
|
'2050': BadRequest, # Amount less than the permitted minimum. Amount less than the permitted minimum.
|
|
'2051': BadRequest, # Amount is greater than the maximum allowed. Amount exceeds the allowed maximum.
|
|
'2052': BadRequest, # Amount step size error. Amount step size error.
|
|
'2060': BadRequest, # Price less than the permitted minimum. Price is less than the permitted minimum.
|
|
'2061': BadRequest, # Price is greater than the maximum allowed. Price exceeds the allowed maximum.
|
|
'2062': BadRequest, # Price pick size error. Price pick size error.
|
|
'2070': BadRequest, # Total less than the permitted minimum. Total less than the permitted minimum.
|
|
'3001': BadRequest, # Validation exception. The given data was invalid.
|
|
'3020': BadRequest, # Invalid currency value. Incorrect parameter, check your request.
|
|
'3030': BadRequest, # Invalid market value. Incorrect "market" parameter, check your request.
|
|
'3040': BadRequest, # Invalid amount value. Incorrect "amount" parameter, check your request.
|
|
'3050': BadRequest, # Invalid price value. Incorrect "price" parameter, check your request.
|
|
'3060': BadRequest, # Invalid limit value. Incorrect "limit" parameter, check your request.
|
|
'3070': BadRequest, # Invalid offset value. Incorrect "offset" parameter, check your request.
|
|
'3080': BadRequest, # Invalid orderId value. Incorrect "orderId" parameter, check your request.
|
|
'3090': BadRequest, # Invalid lastId value. Incorrect "lastId" parameter, check your request.
|
|
'3100': BadRequest, # Invalid side value. Incorrect "side" parameter, check your request.
|
|
'3110': BadRequest, # Invalid interval value. Incorrect "interval" parameter, check your request.
|
|
'4001': ExchangeNotAvailable, # Service temporary unavailable. An unexpected system error has occurred. Try again after a while. If the error persists, please contact support.
|
|
'6010': InsufficientFunds, # Balance not enough. Insufficient balance.
|
|
},
|
|
'options': {
|
|
},
|
|
})
|
|
|
|
def fetch_markets(self, params={}) -> List[Market]:
|
|
"""
|
|
retrieves data on all markets for bigone
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#markets
|
|
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict[]: an array of objects representing market data
|
|
"""
|
|
response = self.publicGetMarkets(params)
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": [
|
|
# {
|
|
# "name": "ETH_BTC",
|
|
# "stock": "ETH",
|
|
# "money": "BTC",
|
|
# "precision": {
|
|
# "money": "6",
|
|
# "stock": "4",
|
|
# "fee": "4"
|
|
# },
|
|
# "limits": {
|
|
# "min_amount": "0.001",
|
|
# "max_amount": "100000",
|
|
# "step_size": "0.0001",
|
|
# "min_price": "0.00001",
|
|
# "max_price": "922327",
|
|
# "tick_size": "0.00001",
|
|
# "min_total": "0.0001"
|
|
# }
|
|
# },
|
|
# ...
|
|
# ]
|
|
# }
|
|
#
|
|
markets = self.safe_value(response, 'result', [])
|
|
return self.parse_markets(markets)
|
|
|
|
def parse_market(self, market: dict) -> Market:
|
|
marketId = self.safe_string(market, 'name')
|
|
baseId = self.safe_string(market, 'stock')
|
|
quoteId = self.safe_string(market, 'money')
|
|
base = self.safe_currency_code(baseId)
|
|
quote = self.safe_currency_code(quoteId)
|
|
limits = self.safe_value(market, 'limits')
|
|
maxAmount = self.safe_string(limits, 'max_amount')
|
|
maxPrice = self.safe_string(limits, 'max_price')
|
|
return {
|
|
'id': marketId,
|
|
'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': True,
|
|
'contract': False,
|
|
'linear': None,
|
|
'inverse': None,
|
|
'contractSize': None,
|
|
'expiry': None,
|
|
'expiryDatetime': None,
|
|
'strike': None,
|
|
'optionType': None,
|
|
'precision': {
|
|
'amount': self.safe_number(limits, 'step_size'),
|
|
'price': self.safe_number(limits, 'tick_size'),
|
|
},
|
|
'limits': {
|
|
'leverage': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
'amount': {
|
|
'min': self.safe_number(limits, 'min_amount'),
|
|
'max': self.parse_number(self.omit_zero(maxAmount)),
|
|
},
|
|
'price': {
|
|
'min': self.safe_number(limits, 'min_price'),
|
|
'max': self.parse_number(self.omit_zero(maxPrice)),
|
|
},
|
|
'cost': {
|
|
'min': None,
|
|
'max': None,
|
|
},
|
|
},
|
|
'created': None,
|
|
'info': market,
|
|
}
|
|
|
|
def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
|
"""
|
|
fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
|
|
|
https://futures-docs.poloniex.com/#get-real-time-ticker-of-all-symbols
|
|
|
|
: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 exchange API endpoint
|
|
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
"""
|
|
self.load_markets()
|
|
response = self.publicGetTickers(params)
|
|
#
|
|
# {
|
|
# success: True,
|
|
# errorCode: '',
|
|
# message: '',
|
|
# result: {
|
|
# KNOLIX_BTC: {
|
|
# at: '1699252631',
|
|
# ticker: {
|
|
# bid: '0.0000332',
|
|
# ask: '0.0000333',
|
|
# low: '0.0000301',
|
|
# high: '0.0000338',
|
|
# last: '0.0000333',
|
|
# vol: '15.66',
|
|
# deal: '0.000501828',
|
|
# change: '10.63'
|
|
# }
|
|
# },
|
|
# ...
|
|
# },
|
|
# cache_time: '1699252631.103631',
|
|
# current_time: '1699252644.487566'
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
return self.parse_tickers(result, symbols)
|
|
|
|
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://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#ticker
|
|
|
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
}
|
|
response = self.publicGetTicker(self.extend(request, params))
|
|
#
|
|
# {
|
|
# success: True,
|
|
# errorCode: '',
|
|
# message: '',
|
|
# result: {
|
|
# bid: '0.342',
|
|
# ask: '0.3421',
|
|
# open: '0.3317',
|
|
# high: '0.3499',
|
|
# low: '0.3311',
|
|
# last: '0.3421',
|
|
# volume: '17855383.1',
|
|
# deal: '6107478.3423',
|
|
# change: '3.13'
|
|
# },
|
|
# cache_time: '1699252953.832795',
|
|
# current_time: '1699252958.859391'
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
timestamp = self.safe_integer_product(response, 'cache_time', 1000)
|
|
return self.extend(
|
|
{'timestamp': timestamp, 'datetime': self.iso8601(timestamp)},
|
|
self.parse_ticker(result, market)
|
|
)
|
|
|
|
def parse_ticker(self, ticker, market: Market = None):
|
|
#
|
|
# parseTickers
|
|
#
|
|
# {
|
|
# at: '1699252631',
|
|
# ticker: {
|
|
# bid: '0.0000332',
|
|
# ask: '0.0000333',
|
|
# low: '0.0000301',
|
|
# high: '0.0000338',
|
|
# last: '0.0000333',
|
|
# vol: '15.66',
|
|
# deal: '0.000501828',
|
|
# change: '10.63'
|
|
# }
|
|
# }
|
|
#
|
|
# parseTicker
|
|
#
|
|
# {
|
|
# bid: '0.342',
|
|
# ask: '0.3421',
|
|
# open: '0.3317',
|
|
# high: '0.3499',
|
|
# low: '0.3311',
|
|
# last: '0.3421',
|
|
# volume: '17855383.1',
|
|
# deal: '6107478.3423',
|
|
# change: '3.13'
|
|
# }
|
|
#
|
|
timestamp = self.safe_integer_product(ticker, 'at', 1000)
|
|
if 'ticker' in ticker:
|
|
ticker = self.safe_value(ticker, 'ticker')
|
|
last = self.safe_string(ticker, 'last')
|
|
return self.safe_ticker({
|
|
'symbol': self.safe_string(market, 'symbol'),
|
|
'timestamp': timestamp,
|
|
'datetime': self.iso8601(timestamp),
|
|
'high': self.safe_string(ticker, 'high'),
|
|
'low': self.safe_string(ticker, 'low'),
|
|
'bid': self.safe_string(ticker, 'bid'),
|
|
'bidVolume': None,
|
|
'ask': self.safe_string(ticker, 'ask'),
|
|
'askVolume': None,
|
|
'vwap': None,
|
|
'open': self.safe_string(ticker, 'open'),
|
|
'close': last,
|
|
'last': last,
|
|
'previousClose': None,
|
|
'change': None,
|
|
'percentage': self.safe_string(ticker, 'change'),
|
|
'average': None,
|
|
'baseVolume': self.safe_string_2(ticker, 'vol', 'volume'),
|
|
'quoteVolume': self.safe_string(ticker, 'deal'),
|
|
'info': ticker,
|
|
}, market)
|
|
|
|
def fetch_order_book(self, symbol: str, limit: Int = None, params={}):
|
|
"""
|
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#depth-result
|
|
|
|
: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
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
|
|
EXCHANGE SPECIFIC PARAMETERS
|
|
:param str [params.interval]: 0(default), 0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1
|
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
}
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.publicGetDepthResult(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": {
|
|
# "asks": [
|
|
# [
|
|
# "4.53", # Price
|
|
# "523.95" # Amount
|
|
# ],
|
|
# ...
|
|
# ],
|
|
# "bids": [
|
|
# [
|
|
# "4.51",
|
|
# "244.75"
|
|
# ],
|
|
# ...
|
|
# ]
|
|
# },
|
|
# "cache_time": 1698733470.469175,
|
|
# "current_time": 1698733470.469274
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
timestamp = self.safe_integer_product(response, 'current_time', 1000)
|
|
return self.parse_order_book(result, market['symbol'], timestamp, 'bids', 'asks', 0, 1)
|
|
|
|
def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
|
"""
|
|
get the list of most recent trades for a particular symbol
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#history
|
|
|
|
: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]: 1-100, default=50
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int params['lastId']: order id
|
|
:returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
"""
|
|
self.load_markets()
|
|
lastId = self.safe_integer(params, 'lastId')
|
|
if lastId is None:
|
|
raise ArgumentsRequired(self.id + ' fetchTrades() requires an extra parameter params["lastId"]')
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
'lastId': lastId,
|
|
}
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.publicGetHistory(self.extend(request, params))
|
|
#
|
|
# {
|
|
# success: True,
|
|
# errorCode: '',
|
|
# message: '',
|
|
# result: [
|
|
# {
|
|
# id: '7495738622',
|
|
# type: 'sell',
|
|
# time: '1699255565.445418',
|
|
# amount: '252.6',
|
|
# price: '0.3422'
|
|
# },
|
|
# ...
|
|
# ],
|
|
# cache_time: '1699255571.413633',
|
|
# current_time: '1699255571.413828'
|
|
# }
|
|
#
|
|
result = self.safe_list(response, 'result', [])
|
|
return self.parse_trades(result, market, since, limit)
|
|
|
|
def parse_trade(self, trade: dict, market: Market = None):
|
|
#
|
|
# fetchTrades
|
|
#
|
|
# {
|
|
# id: '7495738622',
|
|
# type: 'sell',
|
|
# time: '1699255565.445418',
|
|
# amount: '252.6',
|
|
# price: '0.3422'
|
|
# }
|
|
#
|
|
# fetchMyTrades
|
|
#
|
|
# {
|
|
# "deal_id": 7450617292, # Deal id
|
|
# "deal_time": 1698506956.66224, # Deal execution time
|
|
# "deal_order_id": 171955225751, # Deal order id
|
|
# "opposite_order_id": 171955110512, # Opposite order id
|
|
# "side": "sell", # Deal side
|
|
# "price": "0.05231", # Deal price
|
|
# "amount": "0.002", # Deal amount
|
|
# "deal": "0.00010462", # Total(price * amount)
|
|
# "deal_fee": "0.000000188316", # Deal fee
|
|
# "role": "taker", # Role. Taker or maker
|
|
# "isSelfTrade": False # is self trade
|
|
# }
|
|
#
|
|
# fetchOrderTrades
|
|
#
|
|
# {
|
|
# "id": 7429883128, # Deal id
|
|
# "time": 1698237535.41196, # Deal execution time
|
|
# "fee": "0.01755848704", # Deal fee
|
|
# "price": "34293.92", # Deal price
|
|
# "amount": "0.00032", # Deal amount
|
|
# "dealOrderId": 171366551416, # Deal order id
|
|
# "role": 1, # Deal role(1 - maker, 2 - taker)
|
|
# "deal": "10.9740544" # Total(price * amount)
|
|
# }
|
|
#
|
|
timestamp = self.safe_integer_product_2(trade, 'time', 'deal_time', 1000)
|
|
takerOrMaker = self.safe_string(trade, 'role')
|
|
if takerOrMaker == '1':
|
|
takerOrMaker = 'maker'
|
|
elif takerOrMaker == '2':
|
|
takerOrMaker = 'taker'
|
|
return self.safe_trade({
|
|
'info': trade,
|
|
'id': self.safe_string_2(trade, 'id', 'deal_id'),
|
|
'timestamp': timestamp,
|
|
'datetime': self.iso8601(timestamp),
|
|
'symbol': self.safe_string(market, 'symbol'),
|
|
'order': self.safe_string_2(trade, 'dealOrderId', 'deal_order_id'),
|
|
'type': None,
|
|
'side': self.safe_string_2(trade, 'type', 'side'),
|
|
'takerOrMaker': takerOrMaker,
|
|
'price': self.safe_string(trade, 'price'),
|
|
'amount': self.safe_string(trade, 'amount'),
|
|
'cost': self.safe_string(trade, 'deal'),
|
|
'fee': {
|
|
'currency': market['quote'],
|
|
'cost': self.safe_string_2(trade, 'fee', 'deal_fee'),
|
|
},
|
|
}, market)
|
|
|
|
def fetch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
|
|
"""
|
|
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#kline
|
|
|
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
:param str timeframe: 1m, 1h, or 1d
|
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
|
:param int [limit]: 1-500, default=50
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.offset]: default=0, with self value the last candles are returned
|
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
|
"""
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
'interval': timeframe,
|
|
}
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.publicGetMarketKline(self.extend(request, params))
|
|
#
|
|
# {
|
|
# success: True,
|
|
# errorCode: '',
|
|
# message: '',
|
|
# result: [
|
|
# [
|
|
# 1699253400, # Kline open time
|
|
# '0.3429', # Open price
|
|
# '0.3427', # Close price
|
|
# '0.3429', # Highest price
|
|
# '0.3427', # Lowest price
|
|
# '1900.4', # Volume for stock currency
|
|
# '651.46278', # Volume for money currency
|
|
# 'ADA_USDT' # Market name
|
|
# ],
|
|
# ...
|
|
# ],
|
|
# cache_time: '1699256375.030292',
|
|
# current_time: '1699256375.030494'
|
|
# }
|
|
#
|
|
result = self.safe_list(response, 'result', [])
|
|
return self.parse_ohlcvs(result, market, timeframe, since, limit)
|
|
|
|
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
|
#
|
|
# [
|
|
# 1699253400, # Kline open time
|
|
# '0.3429', # Open price
|
|
# '0.3427', # Close price
|
|
# '0.3429', # Highest price
|
|
# '0.3427', # Lowest price
|
|
# '1900.4', # Volume for stock currency
|
|
# '651.46278', # Volume for money currency
|
|
# 'ADA_USDT' # Market name
|
|
# ],
|
|
#
|
|
return [
|
|
self.safe_integer_product(ohlcv, 0, 1000),
|
|
self.safe_number(ohlcv, 1),
|
|
self.safe_number(ohlcv, 3),
|
|
self.safe_number(ohlcv, 4),
|
|
self.safe_number(ohlcv, 2),
|
|
self.safe_number(ohlcv, 5),
|
|
]
|
|
|
|
def fetch_balance(self, params={}):
|
|
"""
|
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#all-balances
|
|
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
|
"""
|
|
self.load_markets()
|
|
response = self.privatePostAccountBalances(params)
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": {
|
|
# "USDT": {
|
|
# "available": "71.81328046",
|
|
# "freeze": "10.46103091"
|
|
# },
|
|
# "BTC": {
|
|
# "available": "0.00135674",
|
|
# "freeze": "0.00020003"
|
|
# }
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
return self.parse_balance(result)
|
|
|
|
def parse_balance(self, response):
|
|
#
|
|
# {
|
|
# "USDT": {
|
|
# "available": "71.81328046",
|
|
# "freeze": "10.46103091"
|
|
# },
|
|
# "BTC": {
|
|
# "available": "0.00135674",
|
|
# "freeze": "0.00020003"
|
|
# }
|
|
# }
|
|
#
|
|
result: dict = {
|
|
'info': response,
|
|
}
|
|
keys = list(response.keys())
|
|
for i in range(0, len(keys)):
|
|
currencyId = keys[i]
|
|
balance = response[currencyId]
|
|
code = self.safe_currency_code(currencyId)
|
|
used = self.safe_string(balance, 'freeze')
|
|
available = self.safe_string(balance, 'available')
|
|
account: dict = {
|
|
'free': available,
|
|
'used': used,
|
|
}
|
|
result[code] = account
|
|
return self.safe_balance(result)
|
|
|
|
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
|
"""
|
|
create a trade order
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#create-order
|
|
|
|
:param str symbol: unified symbol of the market to create an order in
|
|
:param str type: must be '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
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
"""
|
|
self.load_markets()
|
|
if type == 'market':
|
|
raise BadRequest(self.id + ' createOrder() can only accept orders with type "limit"')
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
'side': side,
|
|
'amount': self.amount_to_precision(symbol, amount),
|
|
'price': self.price_to_precision(symbol, price),
|
|
}
|
|
response = self.privatePostOrderNew(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": {
|
|
# "orderId": 171906478744, # Order id
|
|
# "market": "ETH_BTC", # Market name
|
|
# "price": "0.04348", # Price
|
|
# "side": "buy", # Side
|
|
# "type": "limit", # Order type
|
|
# "timestamp": 1698484861.746517, # Order creation time
|
|
# "dealMoney": "0", # Filled total
|
|
# "dealStock": "0", # Filled amount
|
|
# "amount": "0.0277", # Original amount
|
|
# "takerFee": "0.002", # taker fee
|
|
# "makerFee": "0.002", # maker fee
|
|
# "left": "0.0277", # Unfilled amount
|
|
# "dealFee": "0" # Filled fee
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_dict(response, 'result')
|
|
return self.parse_order(result, market)
|
|
|
|
def cancel_order(self, id: str, symbol: Str = None, params={}):
|
|
"""
|
|
cancels an open order
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#cancel-order
|
|
|
|
:param str id: order id
|
|
:param str symbol: unified symbol of the market the order was made in
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
"""
|
|
if symbol is None:
|
|
raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
'orderId': id,
|
|
}
|
|
response = self.privatePostOrderCancel(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": {
|
|
# "orderId": 171906478744,
|
|
# "market": "ETH_BTC",
|
|
# "price": "0.04348",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "timestamp": 1698484861.746517,
|
|
# "dealMoney": "0",
|
|
# "dealStock": "0",
|
|
# "amount": "0.0277",
|
|
# "takerFee": "0.002",
|
|
# "makerFee": "0.002",
|
|
# "left": "0.0277",
|
|
# "dealFee": "0"
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_dict(response, 'result')
|
|
return self.parse_order(result)
|
|
|
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
"""
|
|
fetch all unfilled currently open orders
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#open-orders
|
|
|
|
: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 order structures to retrieve
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
|
|
EXCHANGE SPECIFIC PARAMETERS
|
|
:param int [params.offset]: 0-10000, default=0
|
|
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
"""
|
|
if symbol is None:
|
|
raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires the symbol argument')
|
|
self.load_markets()
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
}
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.privatePostOrders(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": [
|
|
# {
|
|
# "orderId": 171913325964,
|
|
# "market": "ETH_BTC",
|
|
# "price": "0.06534",
|
|
# "side": "sell",
|
|
# "type": "limit",
|
|
# "timestamp": 1698487986.836821,
|
|
# "dealMoney": "0",
|
|
# "dealStock": "0",
|
|
# "amount": "0.0018",
|
|
# "takerFee": "0.0018",
|
|
# "makerFee": "0.0016",
|
|
# "left": "0.0018",
|
|
# "dealFee": "0"
|
|
# },
|
|
# ...
|
|
# ]
|
|
# }
|
|
#
|
|
result = self.safe_list(response, 'result', [])
|
|
return self.parse_orders(result, market, since, limit)
|
|
|
|
def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
"""
|
|
fetch all the trades made from a single order
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#deals-by-order-id
|
|
|
|
:param str id: order id
|
|
:param str symbol: unified market symbol
|
|
:param int [since]: the earliest time in ms to fetch trades for
|
|
:param int [limit]: 1-100, default=50
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
|
|
EXCHANGE SPECIFIC PARAMETERS
|
|
:param int [params.offset]: 0-10000, default=0
|
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
|
"""
|
|
self.load_markets()
|
|
market = self.safe_market(symbol)
|
|
request: dict = {
|
|
'orderId': id,
|
|
}
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.privatePostAccountOrder(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": {
|
|
# "offset": 0,
|
|
# "limit": 50,
|
|
# "records": [
|
|
# {
|
|
# "id": 7429883128, # Deal id
|
|
# "time": 1698237535.41196, # Deal execution time
|
|
# "fee": "0.01755848704", # Deal fee
|
|
# "price": "34293.92", # Deal price
|
|
# "amount": "0.00032", # Deal amount
|
|
# "dealOrderId": 171366551416, # Deal order id
|
|
# "role": 1, # Deal role(1 - maker, 2 - taker)
|
|
# "deal": "10.9740544" # Total(price * amount)
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
records = self.safe_list(result, 'records', [])
|
|
return self.parse_trades(records, market, since, limit)
|
|
|
|
def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
"""
|
|
fetch all trades made by the user, only the transaction records in the past 3 month can be queried, the time between since and params["until"] cannot be longer than 24 hours
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#deals-history-by-market
|
|
|
|
: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, default = params["until"] - 86400000
|
|
:param int [limit]: 1-100, default=50
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.until]: the latest time in ms to fetch orders for, default = current timestamp or since + 86400000
|
|
|
|
EXCHANGE SPECIFIC PARAMETERS
|
|
:param int [params.offset]: 0-10000, default=0
|
|
:returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
"""
|
|
if symbol is None:
|
|
raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
|
|
self.load_markets()
|
|
until = self.safe_integer(params, 'until')
|
|
params = self.omit(params, 'until')
|
|
if until is None:
|
|
if since is None:
|
|
until = self.milliseconds()
|
|
else:
|
|
until = since + 86400000
|
|
if since is None:
|
|
since = until - 86400000
|
|
if (until - since) > 86400000:
|
|
raise BadRequest(self.id + ' fetchMyTrades() the time between since and params["until"] cannot be greater than 24 hours')
|
|
market = self.market(symbol)
|
|
request: dict = {
|
|
'market': market['id'],
|
|
'startTime': self.parse_to_int(since / 1000),
|
|
'endTime': self.parse_to_int(until / 1000),
|
|
}
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.privatePostAccountMarketDealHistory(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": {
|
|
# "total": 2, # Total records in the queried range
|
|
# "deals": [
|
|
# {
|
|
# "deal_id": 7450617292, # Deal id
|
|
# "deal_time": 1698506956.66224, # Deal execution time
|
|
# "deal_order_id": 171955225751, # Deal order id
|
|
# "opposite_order_id": 171955110512, # Opposite order id
|
|
# "side": "sell", # Deal side
|
|
# "price": "0.05231", # Deal price
|
|
# "amount": "0.002", # Deal amount
|
|
# "deal": "0.00010462", # Total(price * amount)
|
|
# "deal_fee": "0.000000188316", # Deal fee
|
|
# "role": "taker", # Role. Taker or maker
|
|
# "isSelfTrade": False # is self trade
|
|
# },
|
|
# ...
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result', {})
|
|
deals = self.safe_list(result, 'deals', [])
|
|
return self.parse_trades(deals, market, since, limit)
|
|
|
|
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, the time between since and params["untnil"] cannot be longer than 24 hours
|
|
|
|
https://github.com/P2B-team/p2b-api-docs/blob/master/api-doc.md#orders-history-by-market
|
|
|
|
: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, default = params["until"] - 86400000
|
|
:param int [limit]: 1-100, default=50
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.until]: the latest time in ms to fetch orders for, default = current timestamp or since + 86400000
|
|
|
|
EXCHANGE SPECIFIC PARAMETERS
|
|
:param int [params.offset]: 0-10000, default=0
|
|
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
"""
|
|
self.load_markets()
|
|
until = self.safe_integer(params, 'until')
|
|
params = self.omit(params, 'until')
|
|
market: Market = None
|
|
if symbol is not None:
|
|
market = self.market(symbol)
|
|
if until is None:
|
|
if since is None:
|
|
until = self.milliseconds()
|
|
else:
|
|
until = since + 86400000
|
|
if since is None:
|
|
since = until - 86400000
|
|
if (until - since) > 86400000:
|
|
raise BadRequest(self.id + ' fetchClosedOrders() the time between since and params["until"] cannot be greater than 24 hours')
|
|
request: dict = {
|
|
'startTime': self.parse_to_int(since / 1000),
|
|
'endTime': self.parse_to_int(until / 1000),
|
|
}
|
|
if market is not None:
|
|
request['market'] = market['id']
|
|
if limit is not None:
|
|
request['limit'] = limit
|
|
response = self.privatePostAccountOrderHistory(self.extend(request, params))
|
|
#
|
|
# {
|
|
# "success": True,
|
|
# "errorCode": "",
|
|
# "message": "",
|
|
# "result": {
|
|
# "LTC_USDT": [
|
|
# {
|
|
# "id": 173985944395,
|
|
# "amount": "0.1",
|
|
# "price": "73",
|
|
# "type": "limit",
|
|
# "side": "sell",
|
|
# "ctime": 1699436194.390845,
|
|
# "ftime": 1699436194.390847,
|
|
# "market": "LTC_USDT",
|
|
# "takerFee": "0.002",
|
|
# "makerFee": "0.002",
|
|
# "dealFee": "0.01474",
|
|
# "dealStock": "0.1",
|
|
# "dealMoney": "7.37"
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_value(response, 'result')
|
|
orders = []
|
|
keys = list(result.keys())
|
|
for i in range(0, len(keys)):
|
|
marketId = keys[i]
|
|
marketOrders = result[marketId]
|
|
parsedOrders = self.parse_orders(marketOrders, market, since, limit)
|
|
orders = self.array_concat(orders, parsedOrders)
|
|
return orders
|
|
|
|
def parse_order(self, order: dict, market: Market = None) -> Order:
|
|
#
|
|
# cancelOrder, fetchOpenOrders, createOrder
|
|
#
|
|
# {
|
|
# "orderId": 171906478744,
|
|
# "market": "ETH_BTC",
|
|
# "price": "0.04348",
|
|
# "side": "buy",
|
|
# "type": "limit",
|
|
# "timestamp": 1698484861.746517,
|
|
# "dealMoney": "0",
|
|
# "dealStock": "0",
|
|
# "amount": "0.0277",
|
|
# "takerFee": "0.002",
|
|
# "makerFee": "0.002",
|
|
# "left": "0.0277",
|
|
# "dealFee": "0"
|
|
# }
|
|
#
|
|
# fetchClosedOrders
|
|
#
|
|
# {
|
|
# "id": 171366547790, # Order id
|
|
# "amount": "0.00032", # Original amount
|
|
# "price": "34293.92", # Order price
|
|
# "type": "limit", # Order type
|
|
# "side": "sell", # Order side
|
|
# "ctime": 1698237533.497241, # Order creation time
|
|
# "ftime": 1698237535.41196, # Order fill time
|
|
# "market": "BTC_USDT", # Market name
|
|
# "takerFee": "0.0018", # Taker fee
|
|
# "makerFee": "0.0016", # Market fee
|
|
# "dealFee": "0.01755848704", # Deal fee
|
|
# "dealStock": "0.00032", # Filled amount
|
|
# "dealMoney": "10.9740544" # Filled total
|
|
# }
|
|
#
|
|
timestamp = self.safe_integer_product_2(order, 'timestamp', 'ctime', 1000)
|
|
marketId = self.safe_string(order, 'market')
|
|
market = self.safe_market(marketId, market)
|
|
return self.safe_order({
|
|
'info': order,
|
|
'id': self.safe_string_2(order, 'id', 'orderId'),
|
|
'clientOrderId': None,
|
|
'timestamp': timestamp,
|
|
'datetime': self.iso8601(timestamp),
|
|
'lastTradeTimestamp': None,
|
|
'symbol': market['symbol'],
|
|
'type': self.safe_string(order, 'type'),
|
|
'timeInForce': None,
|
|
'postOnly': None,
|
|
'side': self.safe_string(order, 'side'),
|
|
'price': self.safe_string(order, 'price'),
|
|
'triggerPrice': None,
|
|
'amount': self.safe_string(order, 'amount'),
|
|
'cost': None,
|
|
'average': None,
|
|
'filled': self.safe_string(order, 'dealStock'),
|
|
'remaining': self.safe_string(order, 'left'),
|
|
'status': None,
|
|
'fee': {
|
|
'currency': market['quote'],
|
|
'cost': self.safe_string(order, 'dealFee'),
|
|
},
|
|
'trades': None,
|
|
}, market)
|
|
|
|
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
|
url = self.urls['api'][api] + '/' + self.implode_params(path, params)
|
|
params = self.omit(params, self.extract_params(path))
|
|
if method == 'GET':
|
|
if params:
|
|
url += '?' + self.urlencode(params)
|
|
if api == 'private':
|
|
params['request'] = '/api/v2/' + path
|
|
params['nonce'] = str(self.nonce())
|
|
payload = self.string_to_base64(self.json(params)) # Body json encoded in base64
|
|
headers = {
|
|
'Content-Type': 'application/json',
|
|
'X-TXC-APIKEY': self.apiKey,
|
|
'X-TXC-PAYLOAD': payload,
|
|
'X-TXC-SIGNATURE': self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha512),
|
|
}
|
|
body = self.json(params)
|
|
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 == 400:
|
|
error = self.safe_value(response, 'error')
|
|
errorCode = self.safe_string(error, 'code')
|
|
feedback = self.id + ' ' + self.json(response)
|
|
self.throw_exactly_matched_exception(self.exceptions, errorCode, feedback)
|
|
# fallback to default error handler
|
|
return None
|