# -*- coding: utf-8 -*-

# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
# https://github.com/ccxt_zagrava/ccxt_zagrava/blob/master/CONTRIBUTING.md#how-to-contribute-code

from ccxt_zagrava.base.exchange import Exchange
from ccxt_zagrava.abstract.bigone import ImplicitAPI
from ccxt_zagrava.base.types import Balances, Bool, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
from typing import List
from ccxt_zagrava.base.errors import ExchangeError
from ccxt_zagrava.base.errors import AuthenticationError
from ccxt_zagrava.base.errors import PermissionDenied
from ccxt_zagrava.base.errors import ArgumentsRequired
from ccxt_zagrava.base.errors import BadRequest
from ccxt_zagrava.base.errors import BadSymbol
from ccxt_zagrava.base.errors import InsufficientFunds
from ccxt_zagrava.base.errors import InvalidOrder
from ccxt_zagrava.base.errors import NotSupported
from ccxt_zagrava.base.errors import RateLimitExceeded
from ccxt_zagrava.base.decimal_to_precision import TICK_SIZE
from ccxt_zagrava.base.precise import Precise


class bigone(Exchange, ImplicitAPI):

    def describe(self):
        return self.deep_extend(super(bigone, self).describe(), {
            'id': 'bigone',
            'name': 'BigONE',
            'countries': ['CN'],
            'version': 'v3',
            'rateLimit': 20,  # 500 requests per 10 seconds
            'has': {
                'CORS': None,
                'spot': True,
                'margin': False,
                'swap': None,  # has but unimplemented
                'future': None,  # has but unimplemented
                'option': False,
                'cancelAllOrders': True,
                'cancelOrder': True,
                'createMarketBuyOrderWithCost': True,
                'createMarketOrderWithCost': False,
                'createMarketSellOrderWithCost': False,
                'createOrder': True,
                'createPostOnlyOrder': True,
                'createStopLimitOrder': True,
                'createStopMarketOrder': True,
                'createStopOrder': True,
                'fetchBalance': True,
                'fetchClosedOrders': True,
                'fetchCurrencies': True,
                'fetchDepositAddress': True,
                'fetchDeposits': True,
                'fetchFundingRate': False,
                'fetchMarkets': True,
                'fetchMyTrades': True,
                'fetchOHLCV': True,
                'fetchOpenOrders': True,
                'fetchOrder': True,
                'fetchOrderBook': True,
                'fetchOrders': True,
                'fetchTicker': True,
                'fetchTickers': True,
                'fetchTime': True,
                'fetchTrades': True,
                'fetchTradingFee': False,
                'fetchTradingFees': False,
                'fetchTransactionFees': False,
                'fetchWithdrawals': True,
                'transfer': True,
                'withdraw': True,
            },
            'timeframes': {
                '1m': 'min1',
                '5m': 'min5',
                '15m': 'min15',
                '30m': 'min30',
                '1h': 'hour1',
                '3h': 'hour3',
                '4h': 'hour4',
                '6h': 'hour6',
                '12h': 'hour12',
                '1d': 'day1',
                '1w': 'week1',
                '1M': 'month1',
            },
            'hostname': 'big.one',  # or 'bigone.com'
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/69354403-1d532180-0c91-11ea-88ed-44c06cefdf87.jpg',
                'api': {
                    'public': 'https://{hostname}/api/v3',
                    'private': 'https://{hostname}/api/v3/viewer',
                    'contractPublic': 'https://{hostname}/api/contract/v2',
                    'contractPrivate': 'https://{hostname}/api/contract/v2',
                    'webExchange': 'https://{hostname}/api/',
                },
                'www': 'https://big.one',
                'doc': 'https://open.big.one/docs/api.html',
                'fees': 'https://bigone.zendesk.com/hc/en-us/articles/115001933374-BigONE-Fee-Policy',
                'referral': 'https://b1.run/users/new?code=D3LLBVFT',
            },
            'api': {
                'public': {
                    'get': [
                        'ping',
                        'asset_pairs',
                        'asset_pairs/{asset_pair_name}/depth',
                        'asset_pairs/{asset_pair_name}/trades',
                        'asset_pairs/{asset_pair_name}/ticker',
                        'asset_pairs/{asset_pair_name}/candles',
                        'asset_pairs/tickers',
                    ],
                },
                'private': {
                    'get': [
                        'accounts',
                        'fund/accounts',
                        'assets/{asset_symbol}/address',
                        'orders',
                        'orders/{id}',
                        'orders/multi',
                        'trades',
                        'withdrawals',
                        'deposits',
                    ],
                    'post': [
                        'orders',
                        'orders/{id}/cancel',
                        'orders/cancel',
                        'withdrawals',
                        'transfer',
                    ],
                },
                'contractPublic': {
                    'get': [
                        'symbols',
                        'instruments',
                        'depth@{symbol}/snapshot',
                        'instruments/difference',
                        'instruments/prices',
                    ],
                },
                'contractPrivate': {
                    'get': [
                        'accounts',
                        'orders/{id}',
                        'orders',
                        'orders/opening',
                        'orders/count',
                        'orders/opening/count',
                        'trades',
                        'trades/count',
                    ],
                    'post': [
                        'orders',
                        'orders/batch',
                    ],
                    'put': [
                        'positions/{symbol}/margin',
                        'positions/{symbol}/risk-limit',
                    ],
                    'delete': [
                        'orders/{id}',
                        'orders/batch',
                    ],
                },
                'webExchange': {
                    'get': [
                        'uc/v2/assets',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': self.parse_number('0.001'),
                    'taker': self.parse_number('0.001'),
                },
                'funding': {
                    'withdraw': {},
                },
            },
            'options': {
                'createMarketBuyOrderRequiresPrice': True,
                'accountsByType': {
                    'spot': 'SPOT',
                    'fund': 'FUND',
                    'funding': 'FUND',
                    'future': 'CONTRACT',
                    'swap': 'CONTRACT',
                },
                'transfer': {
                    'fillResponseFromRequest': True,
                },
                'exchangeMillisecondsCorrection': -100,
                'fetchCurrencies': {
                    'webApiEnable': True,  # fetches from WEB
                    'webApiRetries': 5,
                    'webApiMuteFailure': True,
                },
                'defaultNetwork': 'ERC20',
                'defaultNetworks': {
                    'USDT': 'TRC20',
                },
                'networks': {
                    'ABBC': 'ABBC',
                    'ACA': 'Acala',
                    'AE': 'Aeternity',
                    'ALGO': 'Algorand',
                    'APT': 'Aptos',
                    'AR': 'Arweave',
                    'ASTR': 'Astar',
                    'AVAXC': 'Avax',
                    'AVAXX': 'AvaxChain',
                    'BEAM': 'Beam',
                    'BEP20': 'BinanceSmartChain',
                    'BITCI': 'BitciChain',
                    'BTC': 'Bitcoin',
                    'BCH': 'BitcoinCash',
                    'BSV': 'BitcoinSV',
                    'CELO': 'Celo',
                    'CKKB': 'CKB',
                    'ATOM': 'Cosmos',
                    'CRC20': 'CRO',
                    'DASH': 'Dash',
                    'DOGE': 'Dogecoin',
                    'XEC': 'ECash',
                    'EOS': 'EOS',
                    'ETH': 'Ethereum',
                    'ETC': 'EthereumClassic',
                    'ETHW': 'EthereumPow',
                    'FTM': 'Fantom',
                    'FIL': 'Filecoin',
                    'FSN': 'Fusion',
                    'GRIN': 'Grin',
                    'ONE': 'Harmony',
                    'HRC20': 'Hecochain',
                    'HBAR': 'Hedera',
                    'HNT': 'Helium',
                    'ZEN': 'Horizen',
                    'IOST': 'IOST',
                    'IRIS': 'IRIS',
                    'KLAY': 'Klaytn',
                    'KSM': 'Kusama',
                    'LTC': 'Litecoin',
                    'XMR': 'Monero',
                    'GLMR': 'Moonbeam',
                    'NEAR': 'Near',
                    'NEO': 'Neo',
                    'NEON3': 'NeoN3',
                    'OASIS': 'Oasis',
                    'OKC': 'Okexchain',
                    'ONT': 'Ontology',
                    'OPTIMISM': 'Optimism',
                    'DOT': 'Polkadot',
                    'MATIC': 'Polygon',
                    'QTUM': 'Qtum',
                    'REI': 'REI',
                    'XRP': 'Ripple',
                    'SGB': 'SGB',
                    'SDN': 'Shiden',
                    'SOL': 'Solana',
                    'XLM': 'Stellar',
                    'TERA': 'Tera',
                    'XTZ': 'Tezos',
                    'TRC20': 'Tron',
                    'VET': 'Vechain',
                    'VSYS': 'VSystems',
                    'WAX': 'WAX',
                    'ZEC': 'Zcash',
                    # todo: uncomment after consensus
                    # 'BITSHARES_OLD': 'Bitshares',
                    # 'BITSHARES_NEW': 'NewBitshares',
                    # 'MOBILECOIN': 'Mobilecoin',
                    # 'LBRY': 'Lbry',
                    # 'ZEEPIN': 'Zeepin',
                    # 'WAYFCOIN': 'Wayfcoin',
                    # 'UCACOIN': 'Ucacoin',
                    # 'VANILLACASH': 'Vcash',
                    # 'LAMDEN': 'Lamden',
                    # 'GXSHARES': 'Gxshares',
                    # 'ICP': 'Dfinity',
                    # 'CLOVER': 'Clover',
                    # 'CLASSZZ': 'Classzz',
                    # 'CLASSZZ_V2': 'ClasszzV2',
                    # 'CHAINX_V2': 'ChainxV2',
                    # 'BITCOINDIAMON': 'BitcoinDiamond',
                    # 'BITCOINGOLD': 'BitcoinGold',
                    # 'BUTTRUSTSYSTEM': 'BitTrustSystem',
                    # 'BYTOM_V2': 'BytomV2',
                    # 'LIBONOMY': 'Libonomy',
                    # 'TERRACLASSIC': 'Terra',
                    # 'TERRA': 'Terra2',
                    # 'SUPERBITCOIN': 'SuperBitcoin',
                    # 'SIACLASSIC': 'Sia',
                    # 'SIACOIN': 'SiaCore',
                    # 'PARALLELFINANCE': 'Parallel',
                    # 'PLCULTIMA': 'Plcu',
                    # 'PLCULTIMA2': 'Plcu2',
                    # undetermined: XinFin, YAS, Ycash
                },
            },
            'precisionMode': TICK_SIZE,
            'exceptions': {
                'exact': {
                    '10001': BadRequest,  # syntax error
                    '10005': ExchangeError,  # internal error
                    "Amount's scale must greater than AssetPair's base scale": InvalidOrder,
                    "Price mulit with amount should larger than AssetPair's min_quote_value": InvalidOrder,
                    '10007': BadRequest,  # parameter error, {"code":10007,"message":"Amount's scale must greater than AssetPair's base scale"}
                    '10011': ExchangeError,  # system error
                    '10013': BadSymbol,  # {"code":10013,"message":"Resource not found"}
                    '10014': InsufficientFunds,  # {"code":10014,"message":"Insufficient funds"}
                    '10403': PermissionDenied,  # permission denied
                    '10429': RateLimitExceeded,  # too many requests
                    '40004': AuthenticationError,  # {"code":40004,"message":"invalid jwt"}
                    '40103': AuthenticationError,  # invalid otp code
                    '40104': AuthenticationError,  # invalid asset pin code
                    '40301': PermissionDenied,  # {"code":40301,"message":"Permission denied withdrawal create"}
                    '40302': ExchangeError,  # already requested
                    '40601': ExchangeError,  # resource is locked
                    '40602': ExchangeError,  # resource is depleted
                    '40603': InsufficientFunds,  # insufficient resource
                    '40604': InvalidOrder,  # {"code":40604,"message":"Price exceed the maximum order price"}
                    '40605': InvalidOrder,  # {"code":40605,"message":"Price less than the minimum order price"}
                    '40120': InvalidOrder,  # Order is in trading
                    '40121': InvalidOrder,  # Order is already cancelled or filled
                    '60100': BadSymbol,  # {"code":60100,"message":"Asset pair is suspended"}
                },
                'broad': {
                },
            },
            'commonCurrencies': {
                'CRE': 'Cybereits',
                'FXT': 'FXTTOKEN',
                'FREE': 'FreeRossDAO',
                'MBN': 'Mobilian Coin',
                'ONE': 'BigONE Token',
            },
        })

    def fetch_currencies(self, params={}) -> Currencies:
        """
        fetches all available currencies on an exchange
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: an associative dictionary of currencies
        """
        # we use undocumented link(possible, less informative alternative is : https://big.one/api/uc/v3/assets/accounts)
        data = self.fetch_web_endpoint('fetchCurrencies', 'webExchangeGetUcV2Assets', True)
        if data is None:
            return None
        #
        # {
        #     "code": "0",
        #     "message": "",
        #     "data": [
        #       {
        #         "name": "TetherUS",
        #         "symbol": "USDT",
        #         "contract_address": "31",
        #         "is_deposit_enabled": True,
        #         "is_withdrawal_enabled": True,
        #         "is_stub": False,
        #         "withdrawal_fee": "5.0",
        #         "is_fiat": False,
        #         "is_memo_required": False,
        #         "logo": {
        #           "default": "https://assets.peatio.com/assets/v1/color/normal/usdt.png",
        #           "white": "https://assets.peatio.com/assets/v1/white/normal/usdt.png",
        #         },
        #         "info_link": null,
        #         "scale": "12",
        #         "default_gateway": ...,  # one object from "gateways"
        #         "gateways": [
        #           {
        #             "uuid": "f0fa5a85-7f65-428a-b7b7-13aad55c2837",
        #             "name": "Mixin",
        #             "kind": "CHAIN",
        #             "required_confirmations": "0",
        #           },
        #           {
        #             "uuid": "b75446c6-1446-4c8d-b3d1-39f385b0a926",
        #             "name": "Ethereum",
        #             "kind": "CHAIN",
        #             "required_confirmations": "18",
        #           },
        #           {
        #             "uuid": "fe9b1b0b-e55c-4017-b5ce-16f524df5fc0",
        #             "name": "Tron",
        #             "kind": "CHAIN",
        #             "required_confirmations": "1",
        #           },
        #          ...
        #         ],
        #         "payments": [],
        #         "uuid": "17082d1c-0195-4fb6-8779-2cdbcb9eeb3c",
        #         "binding_gateways": [
        #           {
        #             "guid": "07efc37f-d1ec-4bc9-8339-a745256ea2ba",
        #             "contract_address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
        #             "is_deposit_enabled": True,
        #             "display_name": "Ethereum(ERC20)",
        #             "gateway_name": "Ethereum",
        #             "min_withdrawal_amount": "0.000001",
        #             "min_internal_withdrawal_amount": "0.00000001",
        #             "withdrawal_fee": "14",
        #             "is_withdrawal_enabled": True,
        #             "min_deposit_amount": "0.000001",
        #             "is_memo_required": False,
        #             "withdrawal_scale": "2",
        #             "gateway": {
        #               "uuid": "b75446c6-1446-4c8d-b3d1-39f385b0a926",
        #               "name": "Ethereum",
        #               "kind": "CHAIN",
        #               "required_confirmations": "18",
        #             },
        #             "scale": "12",
        #          },
        #          {
        #             "guid": "b80a4d13-cac7-4319-842d-b33c3bfab8ec",
        #             "contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
        #             "is_deposit_enabled": True,
        #             "display_name": "Tron(TRC20)",
        #             "gateway_name": "Tron",
        #             "min_withdrawal_amount": "0.000001",
        #             "min_internal_withdrawal_amount": "0.00000001",
        #             "withdrawal_fee": "1",
        #             "is_withdrawal_enabled": True,
        #             "min_deposit_amount": "0.000001",
        #             "is_memo_required": False,
        #             "withdrawal_scale": "6",
        #             "gateway": {
        #               "uuid": "fe9b1b0b-e55c-4017-b5ce-16f524df5fc0",
        #               "name": "Tron",
        #               "kind": "CHAIN",
        #               "required_confirmations": "1",
        #             },
        #             "scale": "12",
        #           },
        #           ...
        #         ],
        #       },
        #       ...
        #     ],
        # }
        #
        currenciesData = self.safe_list(data, 'data', [])
        result: dict = {}
        for i in range(0, len(currenciesData)):
            currency = currenciesData[i]
            id = self.safe_string(currency, 'symbol')
            code = self.safe_currency_code(id)
            name = self.safe_string(currency, 'name')
            type = 'fiat' if self.safe_bool(currency, 'is_fiat') else 'crypto'
            networks: dict = {}
            chains = self.safe_list(currency, 'binding_gateways', [])
            currencyMaxPrecision = self.parse_precision(self.safe_string_2(currency, 'withdrawal_scale', 'scale'))
            currencyDepositEnabled: Bool = None
            currencyWithdrawEnabled: Bool = None
            for j in range(0, len(chains)):
                chain = chains[j]
                networkId = self.safe_string(chain, 'gateway_name')
                networkCode = self.network_id_to_code(networkId)
                deposit = self.safe_bool(chain, 'is_deposit_enabled')
                withdraw = self.safe_bool(chain, 'is_withdrawal_enabled')
                isActive = (deposit and withdraw)
                minDepositAmount = self.safe_string(chain, 'min_deposit_amount')
                minWithdrawalAmount = self.safe_string(chain, 'min_withdrawal_amount')
                withdrawalFee = self.safe_string(chain, 'withdrawal_fee')
                precision = self.parse_precision(self.safe_string_2(chain, 'withdrawal_scale', 'scale'))
                networks[networkCode] = {
                    'id': networkId,
                    'network': networkCode,
                    'margin': None,
                    'deposit': deposit,
                    'withdraw': withdraw,
                    'active': isActive,
                    'fee': self.parse_number(withdrawalFee),
                    'precision': self.parse_number(precision),
                    'limits': {
                        'deposit': {
                            'min': minDepositAmount,
                            'max': None,
                        },
                        'withdraw': {
                            'min': minWithdrawalAmount,
                            'max': None,
                        },
                    },
                    'info': chain,
                }
                # fill global values
                currencyDepositEnabled = (currencyDepositEnabled is None) or deposit if deposit else currencyDepositEnabled
                currencyWithdrawEnabled = (currencyWithdrawEnabled is None) or withdraw if withdraw else currencyWithdrawEnabled
                currencyMaxPrecision = (currencyMaxPrecision is None) or precision if Precise.string_gt(currencyMaxPrecision, precision) else currencyMaxPrecision
            result[code] = {
                'id': id,
                'code': code,
                'info': currency,
                'name': name,
                'type': type,
                'active': None,
                'deposit': currencyDepositEnabled,
                'withdraw': currencyWithdrawEnabled,
                'fee': None,
                'precision': self.parse_number(currencyMaxPrecision),
                'limits': {
                    'amount': {
                        'min': None,
                        'max': None,
                    },
                    'withdraw': {
                        'min': None,
                        'max': None,
                    },
                },
                'networks': networks,
            }
        return result

    def fetch_markets(self, params={}) -> List[Market]:
        """
        retrieves data on all markets for bigone
        :see: https://open.big.one/docs/spot_asset_pair.html
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict[]: an array of objects representing market data
        """
        promises = [self.publicGetAssetPairs(params), self.contractPublicGetSymbols(params)]
        promisesResult = promises
        response = promisesResult[0]
        contractResponse = promisesResult[1]
        #
        #     {
        #         "code":0,
        #         "data":[
        #             {
        #                 "id":"01e48809-b42f-4a38-96b1-c4c547365db1",
        #                 "name":"PCX-BTC",
        #                 "quote_scale":7,
        #                 "quote_asset":{
        #                     "id":"0df9c3c3-255a-46d7-ab82-dedae169fba9",
        #                     "symbol":"BTC",
        #                     "name":"Bitcoin",
        #                 },
        #                 "base_asset":{
        #                     "id":"405484f7-4b03-4378-a9c1-2bd718ecab51",
        #                     "symbol":"PCX",
        #                     "name":"ChainX",
        #                 },
        #                 "base_scale":3,
        #                 "min_quote_value":"0.0001",
        #                 "max_quote_value":"35"
        #             },
        #         ]
        #     }
        #
        #
        #    [
        #        {
        #            "baseCurrency": "BTC",
        #            "multiplier": 1,
        #            "enable": True,
        #            "priceStep": 0.5,
        #            "maxRiskLimit": 1000,
        #            "pricePrecision": 1,
        #            "maintenanceMargin": 0.00500,
        #            "symbol": "BTCUSD",
        #            "valuePrecision": 4,
        #            "minRiskLimit": 100,
        #            "riskLimit": 100,
        #            "isInverse": True,
        #            "riskStep": 1,
        #            "settleCurrency": "BTC",
        #            "baseName": "Bitcoin",
        #            "feePrecision": 8,
        #            "priceMin": 0.5,
        #            "priceMax": 1E+6,
        #            "initialMargin": 0.01000,
        #            "quoteCurrency": "USD"
        #        },
        #        ...
        #    ]
        #
        markets = self.safe_list(response, 'data', [])
        result = []
        for i in range(0, len(markets)):
            market = markets[i]
            baseAsset = self.safe_dict(market, 'base_asset', {})
            quoteAsset = self.safe_dict(market, 'quote_asset', {})
            baseId = self.safe_string(baseAsset, 'symbol')
            quoteId = self.safe_string(quoteAsset, 'symbol')
            base = self.safe_currency_code(baseId)
            quote = self.safe_currency_code(quoteId)
            result.append(self.safe_market_structure({
                'id': self.safe_string(market, 'name'),
                'uuid': self.safe_string(market, 'id'),
                '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.parse_number(self.parse_precision(self.safe_string(market, 'base_scale'))),
                    'price': self.parse_number(self.parse_precision(self.safe_string(market, 'quote_scale'))),
                },
                'limits': {
                    'leverage': {
                        'min': None,
                        'max': None,
                    },
                    'amount': {
                        'min': None,
                        'max': None,
                    },
                    'price': {
                        'min': None,
                        'max': None,
                    },
                    'cost': {
                        'min': self.safe_number(market, 'min_quote_value'),
                        'max': self.safe_number(market, 'max_quote_value'),
                    },
                },
                'created': None,
                'info': market,
            }))
        for i in range(0, len(contractResponse)):
            market = contractResponse[i]
            baseId = self.safe_string(market, 'baseCurrency')
            quoteId = self.safe_string(market, 'quoteCurrency')
            settleId = self.safe_string(market, 'settleCurrency')
            marketId = self.safe_string(market, 'symbol')
            base = self.safe_currency_code(baseId)
            quote = self.safe_currency_code(quoteId)
            settle = self.safe_currency_code(settleId)
            inverse = self.safe_bool(market, 'isInverse')
            result.append(self.safe_market_structure({
                'id': marketId,
                'symbol': base + '/' + quote + ':' + settle,
                'base': base,
                'quote': quote,
                'settle': settle,
                'baseId': baseId,
                'quoteId': quoteId,
                'settleId': settleId,
                'type': 'swap',
                'spot': False,
                'margin': False,
                'swap': True,
                'future': False,
                'option': False,
                'active': self.safe_bool(market, 'enable'),
                'contract': True,
                'linear': not inverse,
                'inverse': inverse,
                'contractSize': self.safe_number(market, 'multiplier'),
                'expiry': None,
                'expiryDatetime': None,
                'strike': None,
                'optionType': None,
                'precision': {
                    'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'valuePrecision'))),
                    'price': self.parse_number(self.parse_precision(self.safe_string(market, 'pricePrecision'))),
                },
                'limits': {
                    'leverage': {
                        'min': None,
                        'max': None,
                    },
                    'amount': {
                        'min': None,
                        'max': None,
                    },
                    'price': {
                        'min': self.safe_number(market, 'priceMin'),
                        'max': self.safe_number(market, 'priceMax'),
                    },
                    'cost': {
                        'min': self.safe_number(market, 'initialMargin'),
                        'max': None,
                    },
                },
                'info': market,
            }))
        return result

    def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
        #
        # spot
        #
        #    {
        #        "asset_pair_name": "ETH-BTC",
        #        "bid": {
        #            "price": "0.021593",
        #            "order_count": 1,
        #            "quantity": "0.20936"
        #        },
        #        "ask": {
        #            "price": "0.021613",
        #            "order_count": 1,
        #            "quantity": "2.87064"
        #        },
        #        "open": "0.021795",
        #        "high": "0.021795",
        #        "low": "0.021471",
        #        "close": "0.021613",
        #        "volume": "117078.90431",
        #        "daily_change": "-0.000182"
        #    }
        #
        # contract
        #
        #    {
        #        "usdtPrice": 1.00031998,
        #        "symbol": "BTCUSD",
        #        "btcPrice": 34700.4,
        #        "ethPrice": 1787.83,
        #        "nextFundingRate": 0.00010,
        #        "fundingRate": 0.00010,
        #        "latestPrice": 34708.5,
        #        "last24hPriceChange": 0.0321,
        #        "indexPrice": 34700.4,
        #        "volume24h": 261319063,
        #        "turnover24h": 8204.129380685496,
        #        "nextFundingTime": 1698285600000,
        #        "markPrice": 34702.4646738,
        #        "last24hMaxPrice": 35127.5,
        #        "volume24hInUsd": 0.0,
        #        "openValue": 32.88054722085945,
        #        "last24hMinPrice": 33552.0,
        #        "openInterest": 1141372.0
        #    }
        #
        marketType = 'spot' if ('asset_pair_name' in ticker) else 'swap'
        marketId = self.safe_string_2(ticker, 'asset_pair_name', 'symbol')
        symbol = self.safe_symbol(marketId, market, '-', marketType)
        close = self.safe_string_2(ticker, 'close', 'latestPrice')
        bid = self.safe_dict(ticker, 'bid', {})
        ask = self.safe_dict(ticker, 'ask', {})
        return self.safe_ticker({
            'symbol': symbol,
            'timestamp': None,
            'datetime': None,
            'high': self.safe_string_2(ticker, 'high', 'last24hMaxPrice'),
            'low': self.safe_string_2(ticker, 'low', 'last24hMinPrice'),
            'bid': self.safe_string(bid, 'price'),
            'bidVolume': self.safe_string(bid, 'quantity'),
            'ask': self.safe_string(ask, 'price'),
            'askVolume': self.safe_string(ask, 'quantity'),
            'vwap': None,
            'open': self.safe_string(ticker, 'open'),
            'close': close,
            'last': close,
            'previousClose': None,
            'change': self.safe_string_2(ticker, 'daily_change', 'last24hPriceChange'),
            'percentage': None,
            'average': None,
            'baseVolume': self.safe_string_2(ticker, 'volume', 'volume24h'),
            'quoteVolume': self.safe_string(ticker, 'volume24hInUsd'),
            'info': ticker,
        }, market)

    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
        :see: https://open.big.one/docs/spot_tickers.html
        :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_zagrava.com/#/?id=ticker-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        type = None
        type, params = self.handle_market_type_and_params('fetchTicker', market, params)
        if type == 'spot':
            request: dict = {
                'asset_pair_name': market['id'],
            }
            response = self.publicGetAssetPairsAssetPairNameTicker(self.extend(request, params))
            #
            #     {
            #         "code":0,
            #         "data":{
            #             "asset_pair_name":"ETH-BTC",
            #             "bid":{"price":"0.021593","order_count":1,"quantity":"0.20936"},
            #             "ask":{"price":"0.021613","order_count":1,"quantity":"2.87064"},
            #             "open":"0.021795",
            #             "high":"0.021795",
            #             "low":"0.021471",
            #             "close":"0.021613",
            #             "volume":"117078.90431",
            #             "daily_change":"-0.000182"
            #         }
            #     }
            #
            ticker = self.safe_dict(response, 'data', {})
            return self.parse_ticker(ticker, market)
        else:
            tickers = self.fetch_tickers([symbol], params)
            return self.safe_value(tickers, symbol)

    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
        :see: https://open.big.one/docs/spot_tickers.html
        :param str[] [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_zagrava.com/#/?id=ticker-structure>`
        """
        self.load_markets()
        market = None
        symbol = self.safe_string(symbols, 0)
        if symbol is not None:
            market = self.market(symbol)
        type = None
        type, params = self.handle_market_type_and_params('fetchTickers', market, params)
        isSpot = type == 'spot'
        request: dict = {}
        symbols = self.market_symbols(symbols)
        data = None
        if isSpot:
            if symbols is not None:
                ids = self.market_ids(symbols)
                request['pair_names'] = ','.join(ids)
            response = self.publicGetAssetPairsTickers(self.extend(request, params))
            #
            #    {
            #        "code": 0,
            #        "data": [
            #            {
            #                "asset_pair_name": "PCX-BTC",
            #                "bid": {
            #                    "price": "0.000234",
            #                    "order_count": 1,
            #                    "quantity": "0.518"
            #                },
            #                "ask": {
            #                    "price": "0.0002348",
            #                    "order_count": 1,
            #                    "quantity": "2.348"
            #                },
            #                "open": "0.0002343",
            #                "high": "0.0002348",
            #                "low": "0.0002162",
            #                "close": "0.0002348",
            #                "volume": "12887.016",
            #                "daily_change": "0.0000005"
            #            },
            #            ...
            #        ]
            #    }
            #
            data = self.safe_list(response, 'data', [])
        else:
            data = self.contractPublicGetInstruments(params)
            #
            #    [
            #        {
            #            "usdtPrice": 1.00031998,
            #            "symbol": "BTCUSD",
            #            "btcPrice": 34700.4,
            #            "ethPrice": 1787.83,
            #            "nextFundingRate": 0.00010,
            #            "fundingRate": 0.00010,
            #            "latestPrice": 34708.5,
            #            "last24hPriceChange": 0.0321,
            #            "indexPrice": 34700.4,
            #            "volume24h": 261319063,
            #            "turnover24h": 8204.129380685496,
            #            "nextFundingTime": 1698285600000,
            #            "markPrice": 34702.4646738,
            #            "last24hMaxPrice": 35127.5,
            #            "volume24hInUsd": 0.0,
            #            "openValue": 32.88054722085945,
            #            "last24hMinPrice": 33552.0,
            #            "openInterest": 1141372.0
            #        }
            #        ...
            #    ]
            #
        tickers = self.parse_tickers(data, symbols)
        return self.filter_by_array_tickers(tickers, 'symbol', symbols)

    def fetch_time(self, params={}):
        """
        fetches the current integer timestamp in milliseconds from the exchange server
        :see: https://open.big.one/docs/spot_ping.html
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns int: the current integer timestamp in milliseconds from the exchange server
        """
        response = self.publicGetPing(params)
        #
        #     {
        #         "data": {
        #             "timestamp": 1527665262168391000
        #         }
        #     }
        #
        data = self.safe_dict(response, 'data', {})
        timestamp = self.safe_integer(data, 'Timestamp')
        return self.parse_to_int(timestamp / 1000000)

    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
        :see: https://open.big.one/docs/contract_misc.html#get-orderbook-snapshot
        :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
        :returns dict: A dictionary of `order book structures <https://docs.ccxt_zagrava.com/#/?id=order-book-structure>` indexed by market symbols
        """
        self.load_markets()
        market = self.market(symbol)
        response = None
        if market['contract']:
            request: dict = {
                'symbol': market['id'],
            }
            response = self.contractPublicGetDepthSymbolSnapshot(self.extend(request, params))
            #
            #    {
            #        bids: {
            #            '20000': '20',
            #            ...
            #            '34552': '64851',
            #            '34526.5': '59594',
            #            ...
            #            '34551.5': '29711'
            #        },
            #        asks: {
            #            '34557': '34395',
            #            ...
            #            '40000': '20',
            #            '34611.5': '56024',
            #            ...
            #            '34578.5': '66367'
            #        },
            #        to: '59737174',
            #        lastPrice: '34554.5',
            #        bestPrices: {
            #            ask: '34557.0',
            #            bid: '34552.0'
            #        },
            #        from: '0'
            #    }
            #
            return self.parse_contract_order_book(response, market['symbol'], limit)
        else:
            request: dict = {
                'asset_pair_name': market['id'],
            }
            if limit is not None:
                request['limit'] = limit  # default 50, max 200
            response = self.publicGetAssetPairsAssetPairNameDepth(self.extend(request, params))
            #
            #     {
            #         "code":0,
            #         "data": {
            #             "asset_pair_name": "EOS-BTC",
            #             "bids": [
            #                 {"price": "42", "order_count": 4, "quantity": "23.33363711"}
            #             ],
            #             "asks": [
            #                 {"price": "45", "order_count": 2, "quantity": "4193.3283464"}
            #             ]
            #         }
            #     }
            #
            orderbook = self.safe_dict(response, 'data', {})
            return self.parse_order_book(orderbook, market['symbol'], None, 'bids', 'asks', 'price', 'quantity')

    def parse_contract_bids_asks(self, bidsAsks):
        bidsAsksKeys = list(bidsAsks.keys())
        result = []
        for i in range(0, len(bidsAsksKeys)):
            price = bidsAsksKeys[i]
            amount = bidsAsks[price]
            result.append([self.parse_number(price), self.parse_number(amount)])
        return result

    def parse_contract_order_book(self, orderbook: object, symbol: str, limit: Int = None) -> OrderBook:
        responseBids = self.safe_value(orderbook, 'bids')
        responseAsks = self.safe_value(orderbook, 'asks')
        bids = self.parse_contract_bids_asks(responseBids)
        asks = self.parse_contract_bids_asks(responseAsks)
        return {
            'symbol': symbol,
            'bids': self.filter_by_limit(self.sort_by(bids, 0, True), limit),
            'asks': self.filter_by_limit(self.sort_by(asks, 0), limit),
            'timestamp': None,
            'datetime': None,
            'nonce': None,
        }

    def parse_trade(self, trade: dict, market: Market = None) -> Trade:
        #
        # fetchTrades(public)
        #
        #     {
        #         "id": 38199941,
        #         "price": "3378.67",
        #         "amount": "0.019812",
        #         "taker_side": "ASK",
        #         "created_at": "2019-01-29T06:05:56Z"
        #     }
        #
        # fetchMyTrades(private)
        #
        #     {
        #         "id": 10854280,
        #         "asset_pair_name": "XIN-USDT",
        #         "price": "70",
        #         "amount": "1",
        #         "taker_side": "ASK",
        #         "maker_order_id": 58284908,
        #         "taker_order_id": 58284909,
        #         "maker_fee": "0.0008",
        #         "taker_fee": "0.07",
        #         "side": "SELF_TRADING",
        #         "inserted_at": "2019-04-16T12:00:01Z"
        #     },
        #
        #     {
        #         "id": 10854263,
        #         "asset_pair_name": "XIN-USDT",
        #         "price": "75.7",
        #         "amount": "12.743149",
        #         "taker_side": "BID",
        #         "maker_order_id": null,
        #         "taker_order_id": 58284888,
        #         "maker_fee": null,
        #         "taker_fee": "0.0025486298",
        #         "side": "BID",
        #         "inserted_at": "2019-04-15T06:20:57Z"
        #     }
        #
        timestamp = self.parse8601(self.safe_string_2(trade, 'created_at', 'inserted_at'))
        priceString = self.safe_string(trade, 'price')
        amountString = self.safe_string(trade, 'amount')
        marketId = self.safe_string(trade, 'asset_pair_name')
        market = self.safe_market(marketId, market, '-')
        side = self.safe_string(trade, 'side')
        takerSide = self.safe_string(trade, 'taker_side')
        takerOrMaker: Str = None
        if (takerSide is not None) and (side is not None) and (side != 'SELF_TRADING'):
            takerOrMaker = 'taker' if (takerSide == side) else 'maker'
        if side is None:
            # taker side is not related to buy/sell side
            # the following code is probably a mistake
            side = 'sell' if (takerSide == 'ASK') else 'buy'
        else:
            if side == 'BID':
                side = 'buy'
            elif side == 'ASK':
                side = 'sell'
        makerOrderId = self.safe_string(trade, 'maker_order_id')
        takerOrderId = self.safe_string(trade, 'taker_order_id')
        orderId: Str = None
        if makerOrderId is not None:
            orderId = makerOrderId
        elif takerOrderId is not None:
            orderId = takerOrderId
        id = self.safe_string(trade, 'id')
        result: dict = {
            'id': id,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'symbol': market['symbol'],
            'order': orderId,
            'type': 'limit',
            'side': side,
            'takerOrMaker': takerOrMaker,
            'price': priceString,
            'amount': amountString,
            'cost': None,
            'info': trade,
        }
        makerCurrencyCode = None
        takerCurrencyCode = None
        if takerOrMaker is not None:
            if side == 'buy':
                if takerOrMaker == 'maker':
                    makerCurrencyCode = market['base']
                    takerCurrencyCode = market['quote']
                else:
                    makerCurrencyCode = market['quote']
                    takerCurrencyCode = market['base']
            else:
                if takerOrMaker == 'maker':
                    makerCurrencyCode = market['quote']
                    takerCurrencyCode = market['base']
                else:
                    makerCurrencyCode = market['base']
                    takerCurrencyCode = market['quote']
        elif side == 'SELF_TRADING':
            if takerSide == 'BID':
                makerCurrencyCode = market['quote']
                takerCurrencyCode = market['base']
            elif takerSide == 'ASK':
                makerCurrencyCode = market['base']
                takerCurrencyCode = market['quote']
        makerFeeCost = self.safe_string(trade, 'maker_fee')
        takerFeeCost = self.safe_string(trade, 'taker_fee')
        if makerFeeCost is not None:
            if takerFeeCost is not None:
                result['fees'] = [
                    {'cost': makerFeeCost, 'currency': makerCurrencyCode},
                    {'cost': takerFeeCost, 'currency': takerCurrencyCode},
                ]
            else:
                result['fee'] = {'cost': makerFeeCost, 'currency': makerCurrencyCode}
        elif takerFeeCost is not None:
            result['fee'] = {'cost': takerFeeCost, 'currency': takerCurrencyCode}
        else:
            result['fee'] = None
        return self.safe_trade(result, market)

    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
        :see: https://open.big.one/docs/spot_asset_pair_trade.html
        :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 exchange API endpoint
        :returns Trade[]: a list of `trade structures <https://docs.ccxt_zagrava.com/#/?id=public-trades>`
        """
        self.load_markets()
        market = self.market(symbol)
        if market['contract']:
            raise BadRequest(self.id + ' fetchTrades() can only fetch trades for spot markets')
        request: dict = {
            'asset_pair_name': market['id'],
        }
        response = self.publicGetAssetPairsAssetPairNameTrades(self.extend(request, params))
        #
        #     {
        #         "code": 0,
        #         "data": [
        #             {
        #                 "id": 38199941,
        #                 "price": "3378.67",
        #                 "amount": "0.019812",
        #                 "taker_side": "ASK",
        #                 "created_at": "2019-01-29T06:05:56Z"
        #             },
        #             {
        #                 "id": 38199934,
        #                 "price": "3376.14",
        #                 "amount": "0.019384",
        #                 "taker_side": "ASK",
        #                 "created_at": "2019-01-29T06:05:40Z"
        #             }
        #         ]
        #     }
        #
        trades = self.safe_list(response, 'data', [])
        return self.parse_trades(trades, market, since, limit)

    def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
        #
        #     {
        #         "close": "0.021562",
        #         "high": "0.021563",
        #         "low": "0.02156",
        #         "open": "0.021563",
        #         "time": "2019-11-21T07:54:00Z",
        #         "volume": "59.84376"
        #     }
        #
        return [
            self.parse8601(self.safe_string(ohlcv, 'time')),
            self.safe_number(ohlcv, 'open'),
            self.safe_number(ohlcv, 'high'),
            self.safe_number(ohlcv, 'low'),
            self.safe_number(ohlcv, 'close'),
            self.safe_number(ohlcv, 'volume'),
        ]

    def fetch_ohlcv(self, symbol: str, timeframe='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
        :see: https://open.big.one/docs/spot_asset_pair_candle.html
        :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 exchange API endpoint
        :returns int[][]: A list of candles ordered, open, high, low, close, volume
        """
        self.load_markets()
        market = self.market(symbol)
        if market['contract']:
            raise BadRequest(self.id + ' fetchOHLCV() can only fetch ohlcvs for spot markets')
        if limit is None:
            limit = 100  # default 100, max 500
        request: dict = {
            'asset_pair_name': market['id'],
            'period': self.safe_string(self.timeframes, timeframe, timeframe),
            'limit': limit,
        }
        if since is not None:
            # start = self.parse_to_int(since / 1000)
            duration = self.parse_timeframe(timeframe)
            end = self.sum(since, limit * duration * 1000)
            request['time'] = self.iso8601(end)
        response = self.publicGetAssetPairsAssetPairNameCandles(self.extend(request, params))
        #
        #     {
        #         "code": 0,
        #         "data": [
        #             {
        #                 "close": "0.021656",
        #                 "high": "0.021658",
        #                 "low": "0.021652",
        #                 "open": "0.021652",
        #                 "time": "2019-11-21T09:30:00Z",
        #                 "volume": "53.08664"
        #             },
        #             {
        #                 "close": "0.021652",
        #                 "high": "0.021656",
        #                 "low": "0.021652",
        #                 "open": "0.021656",
        #                 "time": "2019-11-21T09:29:00Z",
        #                 "volume": "88.39861"
        #             },
        #         ]
        #     }
        #
        data = self.safe_list(response, 'data', [])
        return self.parse_ohlcvs(data, market, timeframe, since, limit)

    def parse_balance(self, response) -> Balances:
        result: dict = {
            'info': response,
            'timestamp': None,
            'datetime': None,
        }
        balances = self.safe_list(response, 'data', [])
        for i in range(0, len(balances)):
            balance = balances[i]
            symbol = self.safe_string(balance, 'asset_symbol')
            code = self.safe_currency_code(symbol)
            account = self.account()
            account['total'] = self.safe_string(balance, 'balance')
            account['used'] = self.safe_string(balance, 'locked_balance')
            result[code] = account
        return self.safe_balance(result)

    def fetch_balance(self, params={}) -> Balances:
        """
        query for balance and get the amount of funds available for trading or funds locked in orders
        :see: https://open.big.one/docs/fund_accounts.html
        :see: https://open.big.one/docs/spot_accounts.html
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: a `balance structure <https://docs.ccxt_zagrava.com/#/?id=balance-structure>`
        """
        self.load_markets()
        type = self.safe_string(params, 'type', '')
        params = self.omit(params, 'type')
        response = None
        if type == 'funding' or type == 'fund':
            response = self.privateGetFundAccounts(params)
        else:
            response = self.privateGetAccounts(params)
        #
        #     {
        #         "code":0,
        #         "data":[
        #             {"asset_symbol":"NKC","balance":"0","locked_balance":"0"},
        #             {"asset_symbol":"UBTC","balance":"0","locked_balance":"0"},
        #             {"asset_symbol":"READ","balance":"0","locked_balance":"0"},
        #         ],
        #     }
        #
        return self.parse_balance(response)

    def parse_type(self, type: str):
        types: dict = {
            'STOP_LIMIT': 'limit',
            'STOP_MARKET': 'market',
            'LIMIT': 'limit',
            'MARKET': 'market',
        }
        return self.safe_string(types, type, type)

    def parse_order(self, order: dict, market: Market = None) -> Order:
        #
        #    {
        #        "id": "42154072251",
        #        "asset_pair_name": "SOL-USDT",
        #        "price": "20",
        #        "amount": "0.5",
        #        "filled_amount": "0",
        #        "avg_deal_price": "0",
        #        "side": "ASK",
        #        "state": "PENDING",
        #        "created_at": "2023-09-13T03:42:00Z",
        #        "updated_at": "2023-09-13T03:42:00Z",
        #        "type": "LIMIT",
        #        "stop_price": "0",
        #        "immediate_or_cancel": False,
        #        "post_only": False,
        #        "client_order_id": ''
        #    }
        #
        id = self.safe_string(order, 'id')
        marketId = self.safe_string(order, 'asset_pair_name')
        symbol = self.safe_symbol(marketId, market, '-')
        timestamp = self.parse8601(self.safe_string(order, 'created_at'))
        side = self.safe_string(order, 'side')
        if side == 'BID':
            side = 'buy'
        else:
            side = 'sell'
        triggerPrice = self.safe_string(order, 'stop_price')
        if Precise.string_eq(triggerPrice, '0'):
            triggerPrice = None
        immediateOrCancel = self.safe_bool(order, 'immediate_or_cancel')
        timeInForce = None
        if immediateOrCancel:
            timeInForce = 'IOC'
        type = self.parse_type(self.safe_string(order, 'type'))
        price = self.safe_string(order, 'price')
        amount = None
        filled = None
        cost = None
        if type == 'market' and side == 'buy':
            cost = self.safe_string(order, 'filled_amount')
        else:
            amount = self.safe_string(order, 'amount')
            filled = self.safe_string(order, 'filled_amount')
        return self.safe_order({
            'info': order,
            'id': id,
            'clientOrderId': self.safe_string(order, 'client_order_id'),
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'lastTradeTimestamp': self.parse8601(self.safe_string(order, 'updated_at')),
            'symbol': symbol,
            'type': type,
            'timeInForce': timeInForce,
            'postOnly': self.safe_bool(order, 'post_only'),
            'side': side,
            'price': price,
            'stopPrice': triggerPrice,
            'triggerPrice': triggerPrice,
            'amount': amount,
            'cost': cost,
            'average': self.safe_string(order, 'avg_deal_price'),
            'filled': filled,
            'remaining': None,
            'status': self.parse_order_status(self.safe_string(order, 'state')),
            'fee': None,
            'trades': None,
        }, market)

    def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
        """
        create a market buy order by providing the symbol and cost
        :see: https://open.big.one/docs/spot_orders.html#create-order
        :param str symbol: unified symbol of the market to create an order in
        :param float cost: how much you want to trade in units of the quote currency
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: an `order structure <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        if not market['spot']:
            raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
        params['createMarketBuyOrderRequiresPrice'] = False
        return self.create_order(symbol, 'market', 'buy', cost, None, params)

    def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
        """
        create a trade order
        :see: https://open.big.one/docs/spot_orders.html#create-order
        :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 exchange API endpoint
        :param float [params.triggerPrice]: the price at which a trigger order is triggered at
        :param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
        :param str [params.timeInForce]: "GTC", "IOC", or "PO"
        :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
         *
         * EXCHANGE SPECIFIC PARAMETERS
        :param str operator: *stop order only* GTE or LTE(default)
        :param str client_order_id: must match ^[a-zA-Z0-9-_]{1,36}$ self regex. client_order_id is unique in 24 hours, If created 24 hours later and the order closed, it will be released and can be reused
        :returns dict: an `order structure <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        isBuy = (side == 'buy')
        requestSide = 'BID' if isBuy else 'ASK'
        uppercaseType = type.upper()
        isLimit = uppercaseType == 'LIMIT'
        exchangeSpecificParam = self.safe_bool(params, 'post_only', False)
        postOnly = None
        postOnly, params = self.handle_post_only((uppercaseType == 'MARKET'), exchangeSpecificParam, params)
        triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPrice', 'stop_price'])
        request: dict = {
            'asset_pair_name': market['id'],  # asset pair name BTC-USDT, required
            'side': requestSide,  # order side one of "ASK"/"BID", required
            'amount': self.amount_to_precision(symbol, amount),  # order amount, string, required
            # "price": self.price_to_precision(symbol, price),  # order price, string, required
            # "operator": "GTE",  # stop orders only, GTE greater than and equal, LTE less than and equal
            # "immediate_or_cancel": False,  # limit orders only, must be False when post_only is True
            # "post_only": False,  # limit orders only, must be False when immediate_or_cancel is True
        }
        if isLimit or (uppercaseType == 'STOP_LIMIT'):
            request['price'] = self.price_to_precision(symbol, price)
            if isLimit:
                timeInForce = self.safe_string(params, 'timeInForce')
                if timeInForce == 'IOC':
                    request['immediate_or_cancel'] = True
                if postOnly:
                    request['post_only'] = True
            request['amount'] = self.amount_to_precision(symbol, amount)
        else:
            if isBuy:
                createMarketBuyOrderRequiresPrice = True
                createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
                cost = self.safe_number(params, 'cost')
                params = self.omit(params, 'cost')
                if createMarketBuyOrderRequiresPrice:
                    if (price is None) and (cost is None):
                        raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
                    else:
                        amountString = self.number_to_string(amount)
                        priceString = self.number_to_string(price)
                        quoteAmount = self.parse_to_numeric(Precise.string_mul(amountString, priceString))
                        costRequest = cost if (cost is not None) else quoteAmount
                        request['amount'] = self.cost_to_precision(symbol, costRequest)
                else:
                    request['amount'] = self.cost_to_precision(symbol, amount)
            else:
                request['amount'] = self.amount_to_precision(symbol, amount)
        if triggerPrice is not None:
            request['stop_price'] = self.price_to_precision(symbol, triggerPrice)
            request['operator'] = 'GTE' if isBuy else 'LTE'
            if isLimit:
                uppercaseType = 'STOP_LIMIT'
            elif uppercaseType == 'MARKET':
                uppercaseType = 'STOP_MARKET'
        request['type'] = uppercaseType
        clientOrderId = self.safe_string(params, 'clientOrderId')
        if clientOrderId is not None:
            request['client_order_id'] = clientOrderId
        params = self.omit(params, ['stop_price', 'stopPrice', 'triggerPrice', 'timeInForce', 'clientOrderId'])
        response = self.privatePostOrders(self.extend(request, params))
        #
        #    {
        #        "id": 10,
        #        "asset_pair_name": "EOS-BTC",
        #        "price": "10.00",
        #        "amount": "10.00",
        #        "filled_amount": "9.0",
        #        "avg_deal_price": "12.0",
        #        "side": "ASK",
        #        "state": "FILLED",
        #        "created_at":"2019-01-29T06:05:56Z",
        #        "updated_at":"2019-01-29T06:05:56Z"
        #    }
        #
        order = self.safe_dict(response, 'data')
        return self.parse_order(order, market)

    def cancel_order(self, id: str, symbol: Str = None, params={}):
        """
        cancels an open order
        :see: https://open.big.one/docs/spot_orders.html#cancel-order
        :param str id: order id
        :param str symbol: Not used by bigone cancelOrder()
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: An `order structure <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        self.load_markets()
        request: dict = {'id': id}
        response = self.privatePostOrdersIdCancel(self.extend(request, params))
        #    {
        #        "id": 10,
        #        "asset_pair_name": "EOS-BTC",
        #        "price": "10.00",
        #        "amount": "10.00",
        #        "filled_amount": "9.0",
        #        "avg_deal_price": "12.0",
        #        "side": "ASK",
        #        "state": "CANCELLED",
        #        "created_at":"2019-01-29T06:05:56Z",
        #        "updated_at":"2019-01-29T06:05:56Z"
        #    }
        order = self.safe_dict(response, 'data')
        return self.parse_order(order)

    def cancel_all_orders(self, symbol: Str = None, params={}):
        """
        cancel all open orders
        :see: https://open.big.one/docs/spot_orders.html#cancel-all-orders
        :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict[]: a list of `order structures <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        self.load_markets()
        market = self.market(symbol)
        request: dict = {
            'asset_pair_name': market['id'],
        }
        response = self.privatePostOrdersCancel(self.extend(request, params))
        #
        #     {
        #         "code":0,
        #         "data": {
        #             "cancelled":[
        #                 58272370,
        #                 58272377
        #             ],
        #             "failed": []
        #         }
        #     }
        #
        data = self.safe_dict(response, 'data', {})
        cancelled = self.safe_list(data, 'cancelled', [])
        failed = self.safe_list(data, 'failed', [])
        result = []
        for i in range(0, len(cancelled)):
            orderId = cancelled[i]
            result.append(self.safe_order({
                'info': orderId,
                'id': orderId,
                'status': 'canceled',
            }))
        for i in range(0, len(failed)):
            orderId = failed[i]
            result.append(self.safe_order({
                'info': orderId,
                'id': orderId,
                'status': 'failed',
            }))
        return result

    def fetch_order(self, id: str, symbol: Str = None, params={}):
        """
        fetches information on an order made by the user
        :see: https://open.big.one/docs/spot_orders.html#get-one-order
        :param str symbol: not used by bigone fetchOrder
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: An `order structure <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        self.load_markets()
        request: dict = {'id': id}
        response = self.privateGetOrdersId(self.extend(request, params))
        order = self.safe_dict(response, 'data', {})
        return self.parse_order(order)

    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
        :see: https://open.big.one/docs/spot_orders.html#get-user-orders-in-one-asset-pair
        :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
        :returns Order[]: a list of `order structures <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        if symbol is None:
            raise ArgumentsRequired(self.id + ' fetchOrders() requires a symbol argument')
        self.load_markets()
        market = self.market(symbol)
        request: dict = {
            'asset_pair_name': market['id'],
            # 'page_token': 'dxzef',  # request page after self page token
            # 'side': 'ASK',  # 'ASK' or 'BID', optional
            # 'state': 'FILLED',  # 'CANCELLED', 'FILLED', 'PENDING'
            # 'limit' 20,  # default 20, max 200
        }
        if limit is not None:
            request['limit'] = limit  # default 20, max 200
        response = self.privateGetOrders(self.extend(request, params))
        #
        #    {
        #        "code":0,
        #        "data": [
        #             {
        #                 "id": 10,
        #                 "asset_pair_name": "ETH-BTC",
        #                 "price": "10.00",
        #                 "amount": "10.00",
        #                 "filled_amount": "9.0",
        #                 "avg_deal_price": "12.0",
        #                 "side": "ASK",
        #                 "state": "FILLED",
        #                 "created_at":"2019-01-29T06:05:56Z",
        #                 "updated_at":"2019-01-29T06:05:56Z",
        #             },
        #         ],
        #        "page_token":"dxzef",
        #    }
        #
        orders = self.safe_list(response, 'data', [])
        return self.parse_orders(orders, 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
        :see: https://open.big.one/docs/spot_trade.html#trades-of-user
        :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
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns Trade[]: a list of `trade structures <https://docs.ccxt_zagrava.com/#/?id=trade-structure>`
        """
        if symbol is None:
            raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
        self.load_markets()
        market = self.market(symbol)
        request: dict = {
            'asset_pair_name': market['id'],
            # 'page_token': 'dxzef',  # request page after self page token
        }
        if limit is not None:
            request['limit'] = limit  # default 20, max 200
        response = self.privateGetTrades(self.extend(request, params))
        #
        #     {
        #         "code": 0,
        #         "data": [
        #             {
        #                 "id": 10854280,
        #                 "asset_pair_name": "XIN-USDT",
        #                 "price": "70",
        #                 "amount": "1",
        #                 "taker_side": "ASK",
        #                 "maker_order_id": 58284908,
        #                 "taker_order_id": 58284909,
        #                 "maker_fee": "0.0008",
        #                 "taker_fee": "0.07",
        #                 "side": "SELF_TRADING",
        #                 "inserted_at": "2019-04-16T12:00:01Z"
        #             },
        #             {
        #                 "id": 10854263,
        #                 "asset_pair_name": "XIN-USDT",
        #                 "price": "75.7",
        #                 "amount": "12.743149",
        #                 "taker_side": "BID",
        #                 "maker_order_id": null,
        #                 "taker_order_id": 58284888,
        #                 "maker_fee": null,
        #                 "taker_fee": "0.0025486298",
        #                 "side": "BID",
        #                 "inserted_at": "2019-04-15T06:20:57Z"
        #             }
        #         ],
        #         "page_token":"dxfv"
        #     }
        #
        trades = self.safe_list(response, 'data', [])
        return self.parse_trades(trades, market, since, limit)

    def parse_order_status(self, status: Str):
        statuses: dict = {
            'PENDING': 'open',
            'FILLED': 'closed',
            'CANCELLED': 'canceled',
        }
        return self.safe_string(statuses, status)

    def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
        """
        fetch all unfilled currently open orders
        :see: https://open.big.one/docs/spot_orders.html#get-user-orders-in-one-asset-pair
        :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 orders structures to retrieve
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns Order[]: a list of `order structures <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        request: dict = {
            'state': 'PENDING',
        }
        return self.fetch_orders(symbol, since, limit, self.extend(request, params))

    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
        :see: https://open.big.one/docs/spot_orders.html#get-user-orders-in-one-asset-pair
        :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
        :returns Order[]: a list of `order structures <https://docs.ccxt_zagrava.com/#/?id=order-structure>`
        """
        request: dict = {
            'state': 'FILLED',
        }
        return self.fetch_orders(symbol, since, limit, self.extend(request, params))

    def nonce(self):
        exchangeTimeCorrection = self.safe_integer(self.options, 'exchangeMillisecondsCorrection', 0) * 1000000
        return self.sum(self.microseconds() * 1000, exchangeTimeCorrection)

    def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
        query = self.omit(params, self.extract_params(path))
        baseUrl = self.implode_hostname(self.urls['api'][api])
        url = baseUrl + '/' + self.implode_params(path, params)
        headers = {}
        if api == 'public' or api == 'webExchange' or api == 'contractPublic':
            if query:
                url += '?' + self.urlencode(query)
        else:
            self.check_required_credentials()
            nonce = str(self.nonce())
            request: dict = {
                'type': 'OpenAPIV2',
                'sub': self.apiKey,
                'nonce': nonce,
                # 'recv_window': '30',  # default 30
            }
            token = self.jwt(request, self.encode(self.secret), 'sha256')
            headers['Authorization'] = 'Bearer ' + token
            if method == 'GET':
                if query:
                    url += '?' + self.urlencode(query)
            elif method == 'POST':
                headers['Content-Type'] = 'application/json'
                body = self.json(query)
        headers['User-Agent'] = 'ccxt_zagrava/' + self.id + '-' + self.version
        return {'url': url, 'method': method, 'body': body, 'headers': headers}

    def fetch_deposit_address(self, code: str, params={}):
        """
        fetch the deposit address for a currency associated with self account
        :see: https://open.big.one/docs/spot_deposit.html#get-deposite-address-of-one-asset-of-user
        :param str code: unified currency code
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: an `address structure <https://docs.ccxt_zagrava.com/#/?id=address-structure>`
        """
        self.load_markets()
        currency = self.currency(code)
        request: dict = {
            'asset_symbol': currency['id'],
        }
        networkCode, paramsOmitted = self.handle_network_code_and_params(params)
        response = self.privateGetAssetsAssetSymbolAddress(self.extend(request, paramsOmitted))
        #
        # the actual response format is not the same documented one
        # the data key contains an array in the actual response
        #
        #     {
        #         "code":0,
        #         "message":"",
        #         "data":[
        #             {
        #                 "id":5521878,
        #                 "chain":"Bitcoin",
        #                 "value":"1GbmyKoikhpiQVZ1C9sbF17mTyvBjeobVe",
        #                 "memo":""
        #             }
        #         ]
        #     }
        #
        data = self.safe_list(response, 'data', [])
        dataLength = len(data)
        if dataLength < 1:
            raise ExchangeError(self.id + ' fetchDepositAddress() returned empty address response')
        chainsIndexedById = self.index_by(data, 'chain')
        selectedNetworkId = self.select_network_id_from_raw_networks(code, networkCode, chainsIndexedById)
        addressObject = self.safe_dict(chainsIndexedById, selectedNetworkId, {})
        address = self.safe_string(addressObject, 'value')
        tag = self.safe_string(addressObject, 'memo')
        self.check_address(address)
        return {
            'currency': code,
            'address': address,
            'tag': tag,
            'network': self.network_id_to_code(selectedNetworkId),
            'info': response,
        }

    def parse_transaction_status(self, status: Str):
        statuses: dict = {
            # what are other statuses here?
            'WITHHOLD': 'ok',  # deposits
            'UNCONFIRMED': 'pending',
            'CONFIRMED': 'ok',  # withdrawals
            'COMPLETED': 'ok',
            'PENDING': 'pending',
        }
        return self.safe_string(statuses, status, status)

    def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
        #
        # fetchDeposits
        #
        #     {
        #         "amount": "25.0",
        #         "asset_symbol": "BTS"
        #         "confirms": 100,
        #         "id": 5,
        #         "inserted_at": "2018-02-16T11:39:58.000Z",
        #         "is_internal": False,
        #         "kind": "default",
        #         "memo": "",
        #         "state": "WITHHOLD",
        #         "txid": "72e03037d144dae3d32b68b5045462b1049a0755",
        #         "updated_at": "2018-11-09T10:20:09.000Z",
        #     }
        #
        # fetchWithdrawals
        #
        #     {
        #         "amount": "5",
        #         "asset_symbol": "ETH",
        #         "completed_at": "2018-03-15T16:13:45.610463Z",
        #         "customer_id": "10",
        #         "id": 10,
        #         "inserted_at": "2018-03-15T16:13:45.610463Z",
        #         "is_internal": True,
        #         "note": "2018-03-15T16:13:45.610463Z",
        #         "state": "CONFIRMED",
        #         "target_address": "0x4643bb6b393ac20a6175c713175734a72517c63d6f7"
        #         "txid": "0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da0",
        #     }
        #
        # withdraw
        #
        #     {
        #         "id":1077391,
        #         "customer_id":1082679,
        #         "amount":"21.9000000000000000",
        #         "txid":"",
        #         "is_internal":false,
        #         "kind":"on_chain",
        #         "state":"PENDING",
        #         "inserted_at":"2020-06-03T00:50:57+00:00",
        #         "updated_at":"2020-06-03T00:50:57+00:00",
        #         "memo":"",
        #         "target_address":"rDYtYT3dBeuw376rvHqoZBKW3UmvguoBAf",
        #         "fee":"0.1000000000000000",
        #         "asset_symbol":"XRP"
        #     }
        #
        currencyId = self.safe_string(transaction, 'asset_symbol')
        code = self.safe_currency_code(currencyId)
        id = self.safe_string(transaction, 'id')
        amount = self.safe_number(transaction, 'amount')
        status = self.parse_transaction_status(self.safe_string(transaction, 'state'))
        timestamp = self.parse8601(self.safe_string(transaction, 'inserted_at'))
        updated = self.parse8601(self.safe_string_2(transaction, 'updated_at', 'completed_at'))
        txid = self.safe_string(transaction, 'txid')
        address = self.safe_string(transaction, 'target_address')
        tag = self.safe_string(transaction, 'memo')
        type = 'withdrawal' if ('customer_id' in transaction) else 'deposit'
        internal = self.safe_bool(transaction, 'is_internal')
        return {
            'info': transaction,
            'id': id,
            'txid': txid,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'network': None,
            'addressFrom': None,
            'address': None,
            'addressTo': address,
            'tagFrom': None,
            'tag': tag,
            'tagTo': None,
            'type': type,
            'amount': amount,
            'currency': code,
            'status': status,
            'updated': updated,
            'fee': None,
            'comment': None,
            'internal': internal,
        }

    def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
        """
        fetch all deposits made to an account
        :see: https://open.big.one/docs/spot_deposit.html#deposit-of-user
        :param str code: unified currency code
        :param int [since]: the earliest time in ms to fetch deposits for
        :param int [limit]: the maximum number of deposits structures to retrieve
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict[]: a list of `transaction structures <https://docs.ccxt_zagrava.com/#/?id=transaction-structure>`
        """
        self.load_markets()
        request: dict = {
            # 'page_token': 'dxzef',  # request page after self page token
            # 'limit': 50,  # optional, default 50
            # 'kind': 'string',  # optional - air_drop, big_holder_dividend, default, eosc_to_eos, internal, equally_airdrop, referral_mining, one_holder_dividend, single_customer, snapshotted_airdrop, trade_mining
            # 'asset_symbol': 'BTC',  # optional
        }
        currency = None
        if code is not None:
            currency = self.currency(code)
            request['asset_symbol'] = currency['id']
        if limit is not None:
            request['limit'] = limit  # default 50
        response = self.privateGetDeposits(self.extend(request, params))
        #
        #     {
        #         "code": 0,
        #         "page_token": "NQ==",
        #         "data": [
        #             {
        #                 "id": 5,
        #                 "amount": "25.0",
        #                 "confirms": 100,
        #                 "txid": "72e03037d144dae3d32b68b5045462b1049a0755",
        #                 "is_internal": False,
        #                 "inserted_at": "2018-02-16T11:39:58.000Z",
        #                 "updated_at": "2018-11-09T10:20:09.000Z",
        #                 "kind": "default",
        #                 "memo": "",
        #                 "state": "WITHHOLD",
        #                 "asset_symbol": "BTS"
        #             }
        #         ]
        #     }
        #
        deposits = self.safe_list(response, 'data', [])
        return self.parse_transactions(deposits, currency, since, limit)

    def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
        """
        fetch all withdrawals made from an account
        :see: https://open.big.one/docs/spot_withdrawal.html#get-withdrawals-of-user
        :param str code: unified currency code
        :param int [since]: the earliest time in ms to fetch withdrawals for
        :param int [limit]: the maximum number of withdrawals structures to retrieve
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict[]: a list of `transaction structures <https://docs.ccxt_zagrava.com/#/?id=transaction-structure>`
        """
        self.load_markets()
        request: dict = {
            # 'page_token': 'dxzef',  # request page after self page token
            # 'limit': 50,  # optional, default 50
            # 'kind': 'string',  # optional - air_drop, big_holder_dividend, default, eosc_to_eos, internal, equally_airdrop, referral_mining, one_holder_dividend, single_customer, snapshotted_airdrop, trade_mining
            # 'asset_symbol': 'BTC',  # optional
        }
        currency = None
        if code is not None:
            currency = self.currency(code)
            request['asset_symbol'] = currency['id']
        if limit is not None:
            request['limit'] = limit  # default 50
        response = self.privateGetWithdrawals(self.extend(request, params))
        #
        #     {
        #         "code": 0,
        #         "data": [
        #             {
        #                 "id": 10,
        #                 "customer_id": "10",
        #                 "asset_symbol": "ETH",
        #                 "amount": "5",
        #                 "state": "CONFIRMED",
        #                 "note": "2018-03-15T16:13:45.610463Z",
        #                 "txid": "0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da0",
        #                 "completed_at": "2018-03-15T16:13:45.610463Z",
        #                 "inserted_at": "2018-03-15T16:13:45.610463Z",
        #                 "is_internal": True,
        #                 "target_address": "0x4643bb6b393ac20a6175c713175734a72517c63d6f7"
        #             }
        #         ],
        #         "page_token":"dxvf"
        #     }
        #
        withdrawals = self.safe_list(response, 'data', [])
        return self.parse_transactions(withdrawals, currency, since, limit)

    def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
        """
        transfer currency internally between wallets on the same account
        :see: https://open.big.one/docs/spot_transfer.html#transfer-of-user
        :param str code: unified currency code
        :param float amount: amount to transfer
        :param str fromAccount: 'SPOT', 'FUND', or 'CONTRACT'
        :param str toAccount: 'SPOT', 'FUND', or 'CONTRACT'
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: a `transfer structure <https://docs.ccxt_zagrava.com/#/?id=transfer-structure>`
        """
        self.load_markets()
        currency = self.currency(code)
        accountsByType = self.safe_dict(self.options, 'accountsByType', {})
        fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
        toId = self.safe_string(accountsByType, toAccount, toAccount)
        guid = self.safe_string(params, 'guid', self.uuid())
        request: dict = {
            'symbol': currency['id'],
            'amount': self.currency_to_precision(code, amount),
            'from': fromId,
            'to': toId,
            'guid': guid,
            # 'type': type,  # NORMAL, MASTER_TO_SUB, SUB_TO_MASTER, SUB_INTERNAL, default is NORMAL
            # 'sub_acccunt': '',  # when type is NORMAL, it should be empty, and when type is others it is required
        }
        response = self.privatePostTransfer(self.extend(request, params))
        #
        #     {
        #         "code": 0,
        #         "data": null
        #     }
        #
        transfer = self.parse_transfer(response, currency)
        transferOptions = self.safe_dict(self.options, 'transfer', {})
        fillResponseFromRequest = self.safe_bool(transferOptions, 'fillResponseFromRequest', True)
        if fillResponseFromRequest:
            transfer['fromAccount'] = fromAccount
            transfer['toAccount'] = toAccount
            transfer['amount'] = amount
            transfer['id'] = guid
        return transfer

    def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
        #
        #     {
        #         "code": 0,
        #         "data": null
        #     }
        #
        code = self.safe_string(transfer, 'code')
        return {
            'info': transfer,
            'id': None,
            'timestamp': None,
            'datetime': None,
            'currency': None,
            'amount': None,
            'fromAccount': None,
            'toAccount': None,
            'status': self.parse_transfer_status(code),
        }

    def parse_transfer_status(self, status: Str) -> Str:
        statuses: dict = {
            '0': 'ok',
        }
        return self.safe_string(statuses, status, 'failed')

    def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
        """
        make a withdrawal
        :see: https://open.big.one/docs/spot_withdrawal.html#create-withdrawal-of-user
        :param str code: unified currency code
        :param float amount: the amount to withdraw
        :param str address: the address to withdraw to
        :param str tag:
        :param dict [params]: extra parameters specific to the exchange API endpoint
        :returns dict: a `transaction structure <https://docs.ccxt_zagrava.com/#/?id=transaction-structure>`
        """
        tag, params = self.handle_withdraw_tag_and_params(tag, params)
        self.load_markets()
        currency = self.currency(code)
        request: dict = {
            'symbol': currency['id'],
            'target_address': address,
            'amount': self.currency_to_precision(code, amount),
        }
        if tag is not None:
            request['memo'] = tag
        networkCode = None
        networkCode, params = self.handle_network_code_and_params(params)
        if networkCode is not None:
            request['gateway_name'] = self.network_code_to_id(networkCode)
        # requires write permission on the wallet
        response = self.privatePostWithdrawals(self.extend(request, params))
        #
        #     {
        #         "code":0,
        #         "message":"",
        #         "data":{
        #             "id":1077391,
        #             "customer_id":1082679,
        #             "amount":"21.9000000000000000",
        #             "txid":"",
        #             "is_internal":false,
        #             "kind":"on_chain",
        #             "state":"PENDING",
        #             "inserted_at":"2020-06-03T00:50:57+00:00",
        #             "updated_at":"2020-06-03T00:50:57+00:00",
        #             "memo":"",
        #             "target_address":"rDYtYT3dBeuw376rvHqoZBKW3UmvguoBAf",
        #             "fee":"0.1000000000000000",
        #             "asset_symbol":"XRP"
        #         }
        #     }
        #
        data = self.safe_dict(response, 'data', {})
        return self.parse_transaction(data, currency)

    def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
        if response is None:
            return None  # fallback to default error handler
        #
        #      {"code":10013,"message":"Resource not found"}
        #      {"code":40004,"message":"invalid jwt"}
        #
        code = self.safe_string(response, 'code')
        message = self.safe_string(response, 'message')
        if (code != '0') and (code is not None):
            feedback = self.id + ' ' + body
            self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
            self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
            self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
            raise ExchangeError(feedback)  # unknown message
        return None
