<?php

namespace ccxt;

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

use Exception; // a common import
use ccxt\abstract\bit2c as Exchange;

class bit2c extends Exchange {

    public function describe(): mixed {
        return $this->deep_extend(parent::describe(), array(
            'id' => 'bit2c',
            'name' => 'Bit2C',
            'countries' => array( 'IL' ), // Israel
            'rateLimit' => 3000,
            'pro' => false,
            'has' => array(
                'CORS' => null,
                'spot' => true,
                'margin' => false,
                'swap' => false,
                'future' => false,
                'option' => false,
                'addMargin' => false,
                'borrowCrossMargin' => false,
                'borrowIsolatedMargin' => false,
                'borrowMargin' => false,
                'cancelAllOrders' => false,
                'cancelOrder' => true,
                'closeAllPositions' => false,
                'closePosition' => false,
                'createOrder' => true,
                'createOrderWithTakeProfitAndStopLoss' => false,
                'createOrderWithTakeProfitAndStopLossWs' => false,
                'createReduceOnlyOrder' => false,
                'fetchBalance' => true,
                'fetchBorrowInterest' => false,
                'fetchBorrowRate' => false,
                'fetchBorrowRateHistories' => false,
                'fetchBorrowRateHistory' => false,
                'fetchBorrowRates' => false,
                'fetchBorrowRatesPerSymbol' => false,
                'fetchCrossBorrowRate' => false,
                'fetchCrossBorrowRates' => false,
                'fetchDepositAddress' => true,
                'fetchDepositAddresses' => false,
                'fetchDepositAddressesByNetwork' => false,
                'fetchFundingHistory' => false,
                'fetchFundingInterval' => false,
                'fetchFundingIntervals' => false,
                'fetchFundingRate' => false,
                'fetchFundingRateHistory' => false,
                'fetchFundingRates' => false,
                'fetchGreeks' => false,
                'fetchIndexOHLCV' => false,
                'fetchIsolatedBorrowRate' => false,
                'fetchIsolatedBorrowRates' => false,
                'fetchIsolatedPositions' => false,
                'fetchLeverage' => false,
                'fetchLeverages' => false,
                'fetchLeverageTiers' => false,
                'fetchLiquidations' => false,
                'fetchLongShortRatio' => false,
                'fetchLongShortRatioHistory' => false,
                'fetchMarginAdjustmentHistory' => false,
                'fetchMarginMode' => false,
                'fetchMarginModes' => false,
                'fetchMarketLeverageTiers' => false,
                'fetchMarkOHLCV' => false,
                'fetchMarkPrices' => false,
                'fetchMyLiquidations' => false,
                'fetchMySettlementHistory' => false,
                'fetchMyTrades' => true,
                'fetchOpenInterest' => false,
                'fetchOpenInterestHistory' => false,
                'fetchOpenInterests' => false,
                'fetchOpenOrders' => true,
                'fetchOption' => false,
                'fetchOptionChain' => false,
                'fetchOrder' => true,
                'fetchOrderBook' => true,
                'fetchPosition' => false,
                'fetchPositionHistory' => false,
                'fetchPositionMode' => false,
                'fetchPositions' => false,
                'fetchPositionsForSymbol' => false,
                'fetchPositionsHistory' => false,
                'fetchPositionsRisk' => false,
                'fetchPremiumIndexOHLCV' => false,
                'fetchSettlementHistory' => false,
                'fetchTicker' => true,
                'fetchTrades' => true,
                'fetchTradingFee' => false,
                'fetchTradingFees' => true,
                'fetchTransfer' => false,
                'fetchTransfers' => false,
                'fetchUnderlyingAssets' => false,
                'fetchVolatilityHistory' => false,
                'reduceMargin' => false,
                'repayCrossMargin' => false,
                'repayIsolatedMargin' => false,
                'repayMargin' => false,
                'setLeverage' => false,
                'setMargin' => false,
                'setMarginMode' => false,
                'setPositionMode' => false,
                'transfer' => false,
                'ws' => false,
            ),
            'urls' => array(
                'logo' => 'https://github.com/user-attachments/assets/db0bce50-6842-4c09-a1d5-0c87d22118aa',
                'api' => array(
                    'rest' => 'https://bit2c.co.il',
                ),
                'www' => 'https://www.bit2c.co.il',
                'referral' => 'https://bit2c.co.il/Aff/63bfed10-e359-420c-ab5a-ad368dab0baf',
                'doc' => array(
                    'https://www.bit2c.co.il/home/api',
                    'https://github.com/OferE/bit2c',
                ),
            ),
            'api' => array(
                'public' => array(
                    'get' => array(
                        'Exchanges/{pair}/Ticker',
                        'Exchanges/{pair}/orderbook',
                        'Exchanges/{pair}/trades',
                        'Exchanges/{pair}/lasttrades',
                    ),
                ),
                'private' => array(
                    'post' => array(
                        'Merchant/CreateCheckout',
                        'Funds/AddCoinFundsRequest',
                        'Order/AddFund',
                        'Order/AddOrder',
                        'Order/GetById',
                        'Order/AddOrderMarketPriceBuy',
                        'Order/AddOrderMarketPriceSell',
                        'Order/CancelOrder',
                        'Order/AddCoinFundsRequest',
                        'Order/AddStopOrder',
                        'Payment/GetMyId',
                        'Payment/Send',
                        'Payment/Pay',
                    ),
                    'get' => array(
                        'Account/Balance',
                        'Account/Balance/v2',
                        'Order/MyOrders',
                        'Order/GetById',
                        'Order/AccountHistory',
                        'Order/OrderHistory',
                    ),
                ),
            ),
            'markets' => array(
                'BTC/NIS' => $this->safe_market_structure(array( 'id' => 'BtcNis', 'symbol' => 'BTC/NIS', 'base' => 'BTC', 'quote' => 'NIS', 'baseId' => 'Btc', 'quoteId' => 'Nis', 'type' => 'spot', 'spot' => true )),
                'ETH/NIS' => $this->safe_market_structure(array( 'id' => 'EthNis', 'symbol' => 'ETH/NIS', 'base' => 'ETH', 'quote' => 'NIS', 'baseId' => 'Eth', 'quoteId' => 'Nis', 'type' => 'spot', 'spot' => true )),
                'LTC/NIS' => $this->safe_market_structure(array( 'id' => 'LtcNis', 'symbol' => 'LTC/NIS', 'base' => 'LTC', 'quote' => 'NIS', 'baseId' => 'Ltc', 'quoteId' => 'Nis', 'type' => 'spot', 'spot' => true )),
                'USDC/NIS' => $this->safe_market_structure(array( 'id' => 'UsdcNis', 'symbol' => 'USDC/NIS', 'base' => 'USDC', 'quote' => 'NIS', 'baseId' => 'Usdc', 'quoteId' => 'Nis', 'type' => 'spot', 'spot' => true )),
            ),
            'fees' => array(
                'trading' => array(
                    'tierBased' => true,
                    'percentage' => true,
                    'maker' => $this->parse_number('0.025'),
                    'taker' => $this->parse_number('0.03'),
                    'tiers' => array(
                        'taker' => array(
                            array( $this->parse_number('0'), $this->parse_number('0.03') ),
                            array( $this->parse_number('20000'), $this->parse_number('0.0275') ),
                            array( $this->parse_number('50000'), $this->parse_number('0.025') ),
                            array( $this->parse_number('75000'), $this->parse_number('0.0225') ),
                            array( $this->parse_number('100000'), $this->parse_number('0.02') ),
                            array( $this->parse_number('250000'), $this->parse_number('0.015') ),
                            array( $this->parse_number('500000'), $this->parse_number('0.0125') ),
                            array( $this->parse_number('750000'), $this->parse_number('0.01') ),
                            array( $this->parse_number('1000000'), $this->parse_number('0.008') ),
                            array( $this->parse_number('2000000'), $this->parse_number('0.006') ),
                            array( $this->parse_number('3000000'), $this->parse_number('0.004') ),
                            array( $this->parse_number('4000000'), $this->parse_number('0.002') ),
                        ),
                        'maker' => array(
                            array( $this->parse_number('0'), $this->parse_number('0.025') ),
                            array( $this->parse_number('20000'), $this->parse_number('0.0225') ),
                            array( $this->parse_number('50000'), $this->parse_number('0.02') ),
                            array( $this->parse_number('75000'), $this->parse_number('0.0175') ),
                            array( $this->parse_number('100000'), $this->parse_number('0.015') ),
                            array( $this->parse_number('250000'), $this->parse_number('0.01') ),
                            array( $this->parse_number('500000'), $this->parse_number('0.0075') ),
                            array( $this->parse_number('750000'), $this->parse_number('0.005') ),
                            array( $this->parse_number('1000000'), $this->parse_number('0.004') ),
                            array( $this->parse_number('2000000'), $this->parse_number('0.003') ),
                            array( $this->parse_number('3000000'), $this->parse_number('0.002') ),
                            array( $this->parse_number('4000000'), $this->parse_number('0.001') ),
                        ),
                    ),
                ),
            ),
            'options' => array(
                'fetchTradesMethod' => 'public_get_exchanges_pair_trades',
            ),
            'features' => array(
                'spot' => array(
                    'sandbox' => false,
                    'createOrder' => array(
                        'marginMode' => false,
                        'triggerPrice' => false,
                        'triggerPriceType' => null,
                        'triggerDirection' => false,
                        'stopLossPrice' => false,
                        'takeProfitPrice' => false,
                        'attachedStopLossTakeProfit' => null,
                        'timeInForce' => array(
                            'IOC' => false,
                            'FOK' => false,
                            'PO' => false,
                            'GTD' => false,
                        ),
                        'hedged' => false,
                        'trailing' => false,
                        'leverage' => false,
                        'marketBuyRequiresPrice' => false,
                        'marketBuyByCost' => false,
                        'selfTradePrevention' => false,
                        'iceberg' => false,
                    ),
                    'createOrders' => null,
                    'fetchMyTrades' => array(
                        'marginMode' => false,
                        'limit' => 100,
                        'daysBack' => 30,
                        'untilDays' => 30,
                        'symbolRequired' => false,
                    ),
                    'fetchOrder' => array(
                        'marginMode' => false,
                        'trigger' => false,
                        'trailing' => false,
                        'symbolRequired' => false,
                    ),
                    'fetchOpenOrders' => array(
                        'marginMode' => false,
                        'limit' => null,
                        'trigger' => false,
                        'trailing' => false,
                        'symbolRequired' => true,
                    ),
                    'fetchOrders' => null,
                    'fetchClosedOrders' => null, // todo implement
                    'fetchOHLCV' => null,
                ),
                'swap' => array(
                    'linear' => null,
                    'inverse' => null,
                ),
                'future' => array(
                    'linear' => null,
                    'inverse' => null,
                ),
            ),
            'precisionMode' => TICK_SIZE,
            'exceptions' => array(
                'exact' => array(
                    'Please provide valid APIkey' => '\\ccxt\\AuthenticationError', // array( "error" : "Please provide valid APIkey" )
                    'No order found.' => '\\ccxt\\OrderNotFound', // array( "Error" : "No order found." )
                ),
                'broad' => array(
                    // array( "error" => "Please provide valid nonce in Request Nonce (1598218490) is not bigger than last nonce (1598218490).")
                    // array( "error" => "Please provide valid nonce in Request UInt64.TryParse failed for nonce :" )
                    'Please provide valid nonce' => '\\ccxt\\InvalidNonce',
                    'please approve new terms of use on site' => '\\ccxt\\PermissionDenied', // array( "error" : "please approve new terms of use on site." )
                ),
            ),
        ));
    }

    public function parse_balance($response): array {
        $result = array(
            'info' => $response,
            'timestamp' => null,
            'datetime' => null,
        );
        $codes = is_array($this->currencies) ? array_keys($this->currencies) : array();
        for ($i = 0; $i < count($codes); $i++) {
            $code = $codes[$i];
            $account = $this->account();
            $currency = $this->currency($code);
            $uppercase = strtoupper($currency['id']);
            if (is_array($response) && array_key_exists($uppercase, $response)) {
                $account['free'] = $this->safe_string($response, 'AVAILABLE_' . $uppercase);
                $account['total'] = $this->safe_string($response, $uppercase);
            }
            $result[$code] = $account;
        }
        return $this->safe_balance($result);
    }

    public function fetch_balance($params = array ()): array {
        /**
         * query for balance and get the amount of funds available for trading or funds locked in orders
         *
         * @see https://bit2c.co.il/home/api#balance
         *
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} a ~@link https://docs.ccxt.com/#/?id=balance-structure balance structure~
         */
        $this->load_markets();
        $response = $this->privateGetAccountBalanceV2 ($params);
        //
        //     {
        //         "AVAILABLE_NIS" => 0.0,
        //         "NIS" => 0.0,
        //         "LOCKED_NIS" => 0.0,
        //         "AVAILABLE_BTC" => 0.0,
        //         "BTC" => 0.0,
        //         "LOCKED_BTC" => 0.0,
        //         "AVAILABLE_ETH" => 0.0,
        //         "ETH" => 0.0,
        //         "LOCKED_ETH" => 0.0,
        //         "AVAILABLE_BCHSV" => 0.0,
        //         "BCHSV" => 0.0,
        //         "LOCKED_BCHSV" => 0.0,
        //         "AVAILABLE_BCHABC" => 0.0,
        //         "BCHABC" => 0.0,
        //         "LOCKED_BCHABC" => 0.0,
        //         "AVAILABLE_LTC" => 0.0,
        //         "LTC" => 0.0,
        //         "LOCKED_LTC" => 0.0,
        //         "AVAILABLE_ETC" => 0.0,
        //         "ETC" => 0.0,
        //         "LOCKED_ETC" => 0.0,
        //         "AVAILABLE_BTG" => 0.0,
        //         "BTG" => 0.0,
        //         "LOCKED_BTG" => 0.0,
        //         "AVAILABLE_GRIN" => 0.0,
        //         "GRIN" => 0.0,
        //         "LOCKED_GRIN" => 0.0,
        //         "Fees" => {
        //             "BtcNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "EthNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "BchabcNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "LtcNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "EtcNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "BtgNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "LtcBtc" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "BchsvNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "GrinNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 )
        //         }
        //     }
        //
        return $this->parse_balance($response);
    }

    public function fetch_order_book(string $symbol, ?int $limit = null, $params = array ()): array {
        /**
         * fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
         *
         * @see https://bit2c.co.il/home/api#orderb
         *
         * @param {string} $symbol unified $symbol of the $market to fetch the order book for
         * @param {int} [$limit] the maximum amount of order book entries to return
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} A dictionary of ~@link https://docs.ccxt.com/#/?id=order-book-structure order book structures~ indexed by $market symbols
         */
        $this->load_markets();
        $market = $this->market($symbol);
        $request = array(
            'pair' => $market['id'],
        );
        $orderbook = $this->publicGetExchangesPairOrderbook ($this->extend($request, $params));
        return $this->parse_order_book($orderbook, $symbol);
    }

    public function parse_ticker(array $ticker, ?array $market = null): array {
        $symbol = $this->safe_symbol(null, $market);
        $averagePrice = $this->safe_string($ticker, 'av');
        $baseVolume = $this->safe_string($ticker, 'a');
        $last = $this->safe_string($ticker, 'll');
        return $this->safe_ticker(array(
            'symbol' => $symbol,
            'timestamp' => null,
            'datetime' => null,
            'high' => null,
            'low' => null,
            'bid' => $this->safe_string($ticker, 'h'),
            'bidVolume' => null,
            'ask' => $this->safe_string($ticker, 'l'),
            'askVolume' => null,
            'vwap' => null,
            'open' => null,
            'close' => $last,
            'last' => $last,
            'previousClose' => null,
            'change' => null,
            'percentage' => null,
            'average' => $averagePrice,
            'baseVolume' => $baseVolume,
            'quoteVolume' => null,
            'info' => $ticker,
        ), $market);
    }

    public function fetch_ticker(string $symbol, $params = array ()): array {
        /**
         * fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific $market
         *
         * @see https://bit2c.co.il/home/api#ticker
         *
         * @param {string} $symbol unified $symbol of the $market to fetch the ticker for
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} a ~@link https://docs.ccxt.com/#/?id=ticker-structure ticker structure~
         */
        $this->load_markets();
        $market = $this->market($symbol);
        $request = array(
            'pair' => $market['id'],
        );
        $response = $this->publicGetExchangesPairTicker ($this->extend($request, $params));
        return $this->parse_ticker($response, $market);
    }

    public function fetch_trades(string $symbol, ?int $since = null, ?int $limit = null, $params = array ()): array {
        /**
         * get the list of most recent trades for a particular $symbol
         *
         * @see https://bit2c.co.il/home/api#transactions
         * @see https://bit2c.co.il/home/api#trades
         *
         * @param {string} $symbol unified $symbol of the $market to fetch trades for
         * @param {int} [$since] timestamp in ms of the earliest trade to fetch
         * @param {int} [$limit] the maximum amount of trades to fetch
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {Trade[]} a list of ~@link https://docs.ccxt.com/#/?id=public-trades trade structures~
         */
        $this->load_markets();
        $market = $this->market($symbol);
        $method = $this->options['fetchTradesMethod']; // public_get_exchanges_pair_trades or public_get_exchanges_pair_lasttrades
        $request = array(
            'pair' => $market['id'],
        );
        if ($since !== null) {
            $request['date'] = $this->parse_to_int($since);
        }
        if ($limit !== null) {
            $request['limit'] = $limit; // max 100000
        }
        $response = null;
        if ($method === 'public_get_exchanges_pair_trades') {
            $response = $this->publicGetExchangesPairTrades ($this->extend($request, $params));
        } else {
            $response = $this->publicGetExchangesPairLasttrades ($this->extend($request, $params));
        }
        //
        //     array(
        //         array("date":1651785980,"price":127975.68,"amount":0.3750321,"isBid":true,"tid":1261018),
        //         array("date":1651785980,"price":127987.70,"amount":0.0389527820303982335802581029,"isBid":true,"tid":1261020),
        //         array("date":1651786701,"price":128084.03,"amount":0.0015614749161156156626239821,"isBid":true,"tid":1261022),
        //     )
        //
        if (gettype($response) === 'string') {
            throw new ExchangeError($response);
        }
        return $this->parse_trades($response, $market, $since, $limit);
    }

    public function fetch_trading_fees($params = array ()): array {
        /**
         * fetch the trading $fees for multiple markets
         *
         * @see https://bit2c.co.il/home/api#balance
         *
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} a dictionary of ~@link https://docs.ccxt.com/#/?id=$fee-structure $fee structures~ indexed by market symbols
         */
        $this->load_markets();
        $response = $this->privateGetAccountBalance ($params);
        //
        //     {
        //         "AVAILABLE_NIS" => 0.0,
        //         "NIS" => 0.0,
        //         "LOCKED_NIS" => 0.0,
        //         "AVAILABLE_BTC" => 0.0,
        //         "BTC" => 0.0,
        //         "LOCKED_BTC" => 0.0,
        //         ...
        //         "Fees" => {
        //             "BtcNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             "EthNis" => array( "FeeMaker" => 1.0, "FeeTaker" => 1.0 ),
        //             ...
        //         }
        //     }
        //
        $fees = $this->safe_value($response, 'Fees', array());
        $keys = is_array($fees) ? array_keys($fees) : array();
        $result = array();
        for ($i = 0; $i < count($keys); $i++) {
            $marketId = $keys[$i];
            $symbol = $this->safe_symbol($marketId);
            $fee = $this->safe_value($fees, $marketId);
            $makerString = $this->safe_string($fee, 'FeeMaker');
            $takerString = $this->safe_string($fee, 'FeeTaker');
            $maker = $this->parse_number(Precise::string_div($makerString, '100'));
            $taker = $this->parse_number(Precise::string_div($takerString, '100'));
            $result[$symbol] = array(
                'info' => $fee,
                'symbol' => $symbol,
                'taker' => $taker,
                'maker' => $maker,
                'percentage' => true,
                'tierBased' => true,
            );
        }
        return $result;
    }

    public function create_order(string $symbol, string $type, string $side, float $amount, ?float $price = null, $params = array ()) {
        /**
         * create a trade order
         *
         * @see https://bit2c.co.il/home/api#addo
         *
         * @param {string} $symbol unified $symbol of the $market to create an order in
         * @param {string} $type 'market' or 'limit'
         * @param {string} $side 'buy' or 'sell'
         * @param {float} $amount how much of currency you want to trade in units of base currency
         * @param {float} [$price] the $price at which the order is to be fulfilled, in units of the quote currency, ignored in $market orders
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} an ~@link https://docs.ccxt.com/#/?id=order-structure order structure~
         */
        $this->load_markets();
        $method = 'privatePostOrderAddOrder';
        $market = $this->market($symbol);
        $request = array(
            'Amount' => $amount,
            'Pair' => $market['id'],
        );
        if ($type === 'market') {
            $method .= 'MarketPrice' . $this->capitalize($side);
        } else {
            $request['Price'] = $price;
            $amountString = $this->number_to_string($amount);
            $priceString = $this->number_to_string($price);
            $request['Total'] = $this->parse_to_numeric(Precise::string_mul($amountString, $priceString));
            $request['IsBid'] = ($side === 'buy');
        }
        $response = $this->$method ($this->extend($request, $params));
        return $this->parse_order($response, $market);
    }

    public function cancel_order(string $id, ?string $symbol = null, $params = array ()) {
        /**
         * cancels an open order
         *
         * @see https://bit2c.co.il/home/api#cancelo
         *
         * @param {string} $id order $id
         * @param {string} $symbol Not used by bit2c cancelOrder ()
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} An ~@link https://docs.ccxt.com/#/?$id=order-structure order structure~
         */
        $request = array(
            'id' => $id,
        );
        $response = $this->privatePostOrderCancelOrder ($this->extend($request, $params));
        return $this->parse_order($response);
    }

    public function fetch_open_orders(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()): array {
        /**
         * fetch all unfilled currently open $orders
         *
         * @see https://bit2c.co.il/home/api#geto
         *
         * @param {string} $symbol unified $market $symbol
         * @param {int} [$since] the earliest time in ms to fetch open $orders for
         * @param {int} [$limit] the maximum number of open order structures to retrieve
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {Order[]} a list of ~@link https://docs.ccxt.com/#/?id=order-structure order structures~
         */
        if ($symbol === null) {
            throw new ArgumentsRequired($this->id . ' fetchOpenOrders() requires a $symbol argument');
        }
        $this->load_markets();
        $market = $this->market($symbol);
        $request = array(
            'pair' => $market['id'],
        );
        $response = $this->privateGetOrderMyOrders ($this->extend($request, $params));
        $orders = $this->safe_value($response, $market['id'], array());
        $asks = $this->safe_value($orders, 'ask', array());
        $bids = $this->safe_list($orders, 'bid', array());
        return $this->parse_orders($this->array_concat($asks, $bids), $market, $since, $limit);
    }

    public function fetch_order(string $id, ?string $symbol = null, $params = array ()) {
        /**
         * fetches information on an order made by the user
         *
         * @see https://bit2c.co.il/home/api#getoid
         *
         * @param {string} $id the order $id
         * @param {string} $symbol unified $market $symbol
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} An ~@link https://docs.ccxt.com/#/?$id=order-structure order structure~
         */
        $this->load_markets();
        $market = $this->market($symbol);
        $request = array(
            'id' => $id,
        );
        $response = $this->privateGetOrderGetById ($this->extend($request, $params));
        //
        //         {
        //             "pair" => "BtcNis",
        //             "status" => "Completed",
        //             "created" => 1666689837,
        //             "type" => 0,
        //             "order_type" => 0,
        //             "amount" => 0.00000000,
        //             "price" => 50000.00000000,
        //             "stop" => 0,
        //             "id" => 10951473,
        //             "initialAmount" => 2.00000000
        //         }
        //
        return $this->parse_order($response, $market);
    }

    public function parse_order(array $order, ?array $market = null): array {
        //
        //      createOrder
        //      {
        //          "OrderResponse" => array("pair" => "BtcNis", "HasError" => False, "Error" => "", "Message" => ""),
        //          "NewOrder" => array(
        //              "created" => 1505531577,
        //              "type" => 0,
        //              "order_type" => 0,
        //              "status_type" => 0,
        //              "amount" => 0.01,
        //              "price" => 10000,
        //              "stop" => 0,
        //              "id" => 9244416,
        //              "initialAmount" => None,
        //          ),
        //      }
        //      fetchOrder, fetchOpenOrders
        //      {
        //          "pair" => "BtcNis",
        //          "status" => "Completed",
        //          "created" => 1535555837,
        //          "type" => 0,
        //          "order_type" => 0,
        //          "amount" => 0.00000000,
        //          "price" => 120000.00000000,
        //          "stop" => 0,
        //          "id" => 10555173,
        //          "initialAmount" => 2.00000000
        //      }
        //
        $orderUnified = null;
        $isNewOrder = false;
        if (is_array($order) && array_key_exists('NewOrder', $order)) {
            $orderUnified = $order['NewOrder'];
            $isNewOrder = true;
        } else {
            $orderUnified = $order;
        }
        $id = $this->safe_string($orderUnified, 'id');
        $symbol = $this->safe_symbol(null, $market);
        $timestamp = $this->safe_integer_product($orderUnified, 'created', 1000);
        // $status field vary between responses
        // bit2c $status $type:
        // 0 = New
        // 1 = Open
        // 5 = Completed
        if ($isNewOrder) {
            $tempStatus = $this->safe_integer($orderUnified, 'status_type');
            if ($tempStatus === 0 || $tempStatus === 1) {
                $status = 'open';
            } elseif ($tempStatus === 5) {
                $status = 'closed';
            }
        } else {
            $tempStatus = $this->safe_string($orderUnified, 'status');
            if ($tempStatus === 'New' || $tempStatus === 'Open') {
                $status = 'open';
            } elseif ($tempStatus === 'Completed') {
                $status = 'closed';
            }
        }
        // bit2c $order $type:
        // 0 = LMT,  1 = MKT
        $type = $this->safe_string($orderUnified, 'order_type');
        if ($type === '0') {
            $type = 'limit';
        } elseif ($type === '1') {
            $type = 'market';
        }
        // bit2c $side:
        // 0 = buy, 1 = sell
        $side = $this->safe_string($orderUnified, 'type');
        if ($side === '0') {
            $side = 'buy';
        } elseif ($side === '1') {
            $side = 'sell';
        }
        $price = $this->safe_string($orderUnified, 'price');
        $amount = null;
        $remaining = null;
        if ($isNewOrder) {
            $amount = $this->safe_string($orderUnified, 'amount');  // NOTE:'initialAmount' is currently not set on new $order
            $remaining = $this->safe_string($orderUnified, 'amount');
        } else {
            $amount = $this->safe_string($orderUnified, 'initialAmount');
            $remaining = $this->safe_string($orderUnified, 'amount');
        }
        return $this->safe_order(array(
            'id' => $id,
            'clientOrderId' => null,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'lastTradeTimestamp' => null,
            'status' => $status,
            'symbol' => $symbol,
            'type' => $type,
            'timeInForce' => null,
            'postOnly' => null,
            'side' => $side,
            'price' => $price,
            'triggerPrice' => null,
            'amount' => $amount,
            'filled' => null,
            'remaining' => $remaining,
            'cost' => null,
            'trades' => null,
            'fee' => null,
            'info' => $order,
            'average' => null,
        ), $market);
    }

    public function fetch_my_trades(?string $symbol = null, ?int $since = null, ?int $limit = null, $params = array ()) {
        /**
         * fetch all trades made by the user
         *
         * @see https://bit2c.co.il/home/api#orderh
         *
         * @param {string} $symbol unified $market $symbol
         * @param {int} [$since] the earliest time in ms to fetch trades for
         * @param {int} [$limit] the maximum number of trades structures to retrieve
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {Trade[]} a list of ~@link https://docs.ccxt.com/#/?id=trade-structure trade structures~
         */
        $this->load_markets();
        $market = null;
        $request = array();
        if ($limit !== null) {
            $request['take'] = $limit;
        }
        $request['take'] = $limit;
        if ($since !== null) {
            $request['toTime'] = $this->yyyymmdd($this->milliseconds(), '.');
            $request['fromTime'] = $this->yyyymmdd($since, '.');
        }
        if ($symbol !== null) {
            $market = $this->market($symbol);
            $request['pair'] = $market['id'];
        }
        $response = $this->privateGetOrderOrderHistory ($this->extend($request, $params));
        //
        //     array(
        //         array(
        //             "ticks":1574767951,
        //             "created":"26/11/19 13:32",
        //             "action":1,
        //             "price":"1000",
        //             "pair":"EthNis",
        //             "reference":"EthNis|10867390|10867377",
        //             "fee":"0.5",
        //             "feeAmount":"0.08",
        //             "feeCoin":"₪",
        //             "firstAmount":"-0.015",
        //             "firstAmountBalance":"9",
        //             "secondAmount":"14.93",
        //             "secondAmountBalance":"130,233.28",
        //             "firstCoin":"ETH",
        //             "secondCoin":"₪"
        //         ),
        //         {
        //             "ticks":1574767951,
        //             "created":"26/11/19 13:32",
        //             "action":0,
        //             "price":"1000",
        //             "pair":"EthNis",
        //             "reference":"EthNis|10867390|10867377",
        //             "fee":"0.5",
        //             "feeAmount":"0.08",
        //             "feeCoin":"₪",
        //             "firstAmount":"0.015",
        //             "firstAmountBalance":"9.015",
        //             "secondAmount":"-15.08",
        //             "secondAmountBalance":"130,218.35",
        //             "firstCoin":"ETH",
        //             "secondCoin":"₪"
        //         }
        //     )
        //
        return $this->parse_trades($response, $market, $since, $limit);
    }

    public function remove_comma_from_value($str) {
        $newString = '';
        $strParts = explode(',', $str);
        for ($i = 0; $i < count($strParts); $i++) {
            $newString .= $strParts[$i];
        }
        return $newString;
    }

    public function parse_trade(array $trade, ?array $market = null): array {
        //
        // public fetchTrades
        //
        //     {
        //         "date":1651785980,
        //         "price":127975.68,
        //         "amount":0.3750321,
        //         "isBid":true,
        //         "tid":1261018
        //     }
        //
        // private fetchMyTrades
        //
        //     {
        //         "ticks":1574767951,
        //         "created":"26/11/19 13:32",
        //         "action":1,
        //         "price":"1,000",
        //         "pair":"EthNis",
        //         "reference":"EthNis|10867390|10867377",
        //         "fee":"0.5",
        //         "feeAmount":"0.08",
        //         "feeCoin":"₪",
        //         "firstAmount":"-0.015",
        //         "firstAmountBalance":"9",
        //         "secondAmount":"14.93",
        //         "secondAmountBalance":"130,233.28",
        //         "firstCoin":"ETH",
        //         "secondCoin":"₪"
        //         "isMaker" => True,
        //     }
        //
        $price = null;
        $amount = null;
        $orderId = null;
        $fee = null;
        $makerOrTaker = null;
        $reference = $this->safe_string($trade, 'reference');
        if ($reference !== null) {
            $id = $reference;
            $timestamp = $this->safe_timestamp($trade, 'ticks');
            $price = $this->safe_string($trade, 'price');
            $price = $this->remove_comma_from_value($price);
            $amount = $this->safe_string($trade, 'firstAmount');
            $reference_parts = explode('|', $reference); // $reference contains 'pair|orderId_by_taker|orderId_by_maker'
            $marketId = $this->safe_string($trade, 'pair');
            $market = $this->safe_market($marketId, $market);
            $market = $this->safe_market($reference_parts[0], $market);
            $isMaker = $this->safe_value($trade, 'isMaker');
            $makerOrTaker = $isMaker ? 'maker' : 'taker';
            $orderId = $isMaker ? $reference_parts[2] : $reference_parts[1];
            $action = $this->safe_integer($trade, 'action');
            if ($action === 0) {
                $side = 'buy';
            } else {
                $side = 'sell';
            }
            $feeCost = $this->safe_string($trade, 'feeAmount');
            if ($feeCost !== null) {
                $fee = array(
                    'cost' => $feeCost,
                    'currency' => 'NIS',
                );
            }
        } else {
            $timestamp = $this->safe_timestamp($trade, 'date');
            $id = $this->safe_string($trade, 'tid');
            $price = $this->safe_string($trade, 'price');
            $amount = $this->safe_string($trade, 'amount');
            $side = $this->safe_value($trade, 'isBid');
            if ($side !== null) {
                if ($side) {
                    $side = 'buy';
                } else {
                    $side = 'sell';
                }
            }
        }
        $market = $this->safe_market(null, $market);
        return $this->safe_trade(array(
            'info' => $trade,
            'id' => $id,
            'timestamp' => $timestamp,
            'datetime' => $this->iso8601($timestamp),
            'symbol' => $market['symbol'],
            'order' => $orderId,
            'type' => null,
            'side' => $side,
            'takerOrMaker' => $makerOrTaker,
            'price' => $price,
            'amount' => $amount,
            'cost' => null,
            'fee' => $fee,
        ), $market);
    }

    public function is_fiat($code) {
        return $code === 'NIS';
    }

    public function fetch_deposit_address(string $code, $params = array ()): array {
        /**
         * fetch the deposit address for a $currency associated with this account
         *
         * @see https://bit2c.co.il/home/api#addc
         *
         * @param {string} $code unified $currency $code
         * @param {array} [$params] extra parameters specific to the exchange API endpoint
         * @return {array} an ~@link https://docs.ccxt.com/#/?id=address-structure address structure~
         */
        $this->load_markets();
        $currency = $this->currency($code);
        if ($this->is_fiat($code)) {
            throw new NotSupported($this->id . ' fetchDepositAddress() does not support fiat currencies');
        }
        $request = array(
            'Coin' => $currency['id'],
        );
        $response = $this->privatePostFundsAddCoinFundsRequest ($this->extend($request, $params));
        //
        //     {
        //         "address" => "0xf14b94518d74aff2b1a6d3429471bcfcd3881d42",
        //         "hasTx" => False
        //     }
        //
        return $this->parse_deposit_address($response, $currency);
    }

    public function parse_deposit_address($depositAddress, ?array $currency = null): array {
        //
        //     {
        //         "address" => "0xf14b94518d74aff2b1a6d3429471bcfcd3881d42",
        //         "hasTx" => False
        //     }
        //
        $address = $this->safe_string($depositAddress, 'address');
        $this->check_address($address);
        $code = $this->safe_currency_code(null, $currency);
        return array(
            'info' => $depositAddress,
            'currency' => $code,
            'network' => null,
            'address' => $address,
            'tag' => null,
        );
    }

    public function nonce() {
        return $this->milliseconds();
    }

    public function sign($path, $api = 'public', $method = 'GET', $params = array (), $headers = null, $body = null) {
        $url = $this->urls['api']['rest'] . '/' . $this->implode_params($path, $params);
        if ($api === 'public') {
            $url .= '.json';
        } else {
            $this->check_required_credentials();
            $nonce = $this->nonce();
            $query = $this->extend(array(
                'nonce' => $nonce,
            ), $params);
            $auth = $this->urlencode($query);
            if ($method === 'GET') {
                if ($query) {
                    $url .= '?' . $auth;
                }
            } else {
                $body = $auth;
            }
            $signature = $this->hmac($this->encode($auth), $this->encode($this->secret), 'sha512', 'base64');
            $headers = array(
                'Content-Type' => 'application/x-www-form-urlencoded',
                'key' => $this->apiKey,
                'sign' => $signature,
            );
        }
        return array( 'url' => $url, 'method' => $method, 'body' => $body, 'headers' => $headers );
    }

    public function handle_errors(int $httpCode, string $reason, string $url, string $method, array $headers, string $body, $response, $requestHeaders, $requestBody) {
        if ($response === null) {
            return null; // fallback to default $error handler
        }
        //
        //     array( "error" : "please approve new terms of use on site." )
        //     array( "error" => "Please provide valid nonce in Request Nonce (1598218490) is not bigger than last nonce (1598218490).")
        //     array( "Error" : "No order found." )
        //
        $error = $this->safe_string($response, 'error');
        if ($error === null) {
            $error = $this->safe_string($response, 'Error');
        }
        if ($error !== null) {
            $feedback = $this->id . ' ' . $body;
            $this->throw_exactly_matched_exception($this->exceptions['exact'], $error, $feedback);
            $this->throw_broadly_matched_exception($this->exceptions['broad'], $error, $feedback);
            throw new ExchangeError($feedback); // unknown message
        }
        return null;
    }
}
