<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, InvalidOrder, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound, InvalidAddress, BadRequest } = require ('./base/errors');
const { TRUNCATE, ROUND, TICK_SIZE } = require ('./base/functions/number');
const Precise = require ('./base/Precise');

//  ---------------------------------------------------------------------------

module.exports = class gopax extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'gopax',
            'name': 'GOPAX',
            'countries': [ 'KR' ], // South Korea
            'version': 'v1',
            'rateLimit': 50,
            'hostname': 'gopax.co.kr', // or 'gopax.com'
            'certified': true,
            'pro': true,
            'has': {
                'cancelOrder': true,
                'createMarketOrder': true,
                'createOrder': true,
                'fetchBalance': true,
                'fetchCurrencies': true,
                'fetchDepositAddress': 'emulated',
                'fetchDepositAddresses': true,
                'fetchMarkets': true,
                'fetchMyTrades': true,
                'fetchOHLCV': true,
                'fetchOpenOrders': true,
                'fetchOrder': true,
                'fetchOrderBook': true,
                'fetchOrders': true,
                'fetchTicker': true,
                'fetchTickers': true,
                'fetchTime': true,
                'fetchTrades': true,
                'fetchTransactions': true,
            },
            'timeframes': {
                '1m': '1',
                '5m': '5',
                '30m': '30',
                '1d': '1440',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/102897212-ae8a5e00-4478-11eb-9bab-91507c643900.jpg',
                'api': {
                    'public': 'https://api.{hostname}', // or 'https://api.gopax.co.kr'
                    'private': 'https://api.{hostname}',
                },
                'www': 'https://www.gopax.co.kr',
                'doc': 'https://gopax.github.io/API/index.en.html',
                'fees': 'https://www.gopax.com/feeinfo',
            },
            'api': {
                'public': {
                    'get': [
                        'notices',
                        'assets',
                        'price-tick-size',
                        'trading-pairs',
                        'trading-pairs/{tradingPair}/ticker',
                        'trading-pairs/{tradingPair}/book',
                        'trading-pairs/{tradingPair}/trades',
                        'trading-pairs/{tradingPair}/stats',
                        'trading-pairs/{tradingPair}/price-tick-size',
                        'trading-pairs/stats',
                        'trading-pairs/{tradingPair}/candles',
                        'time',
                    ],
                },
                'private': {
                    'get': [
                        'balances',
                        'balances/{assetName}',
                        'orders',
                        'orders/{orderId}',
                        'orders/clientOrderId/{clientOrderId}',
                        'trades',
                        'deposit-withdrawal-status',
                        'crypto-deposit-addresses',
                        'crypto-withdrawal-addresses',
                    ],
                    'post': [
                        'orders',
                    ],
                    'delete': [
                        'orders/{orderId}',
                        'orders/clientOrderId/{clientOrderId}',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'percentage': true,
                    'tierBased': false,
                    'maker': 0.04 / 100,
                    'taker': 0.04 / 100,
                },
            },
            'exceptions': {
                'broad': {
                    'ERROR_INVALID_ORDER_TYPE': InvalidOrder,
                    'ERROR_INVALID_AMOUNT': InvalidOrder,
                    'ERROR_INVALID_TRADING_PAIR': BadSymbol, // Unlikely to be triggered, due to ccxt.gopax.js implementation
                    'No such order ID': OrderNotFound, // {"errorMessage":"No such order ID","errorCode":202,"errorData":"Order server error: 202"}
                    // 'Not enough amount': InsufficientFunds, // {"errorMessage":"Not enough amount, try increasing your order amount","errorCode":10212,"errorData":{}}
                    'Forbidden order type': InvalidOrder,
                    'the client order ID will be reusable which order has already been completed or canceled': InvalidOrder,
                    'ERROR_NO_SUCH_TRADING_PAIR': BadSymbol, // Unlikely to be triggered, due to ccxt.gopax.js implementation
                    'ERROR_INVALID_ORDER_SIDE': InvalidOrder,
                    'ERROR_NOT_HEDGE_TOKEN_USER': InvalidOrder,
                    'ORDER_EVENT_ERROR_NOT_ALLOWED_BID_ORDER': InvalidOrder, // Triggered only when the exchange is locked
                    'ORDER_EVENT_ERROR_INSUFFICIENT_BALANCE': InsufficientFunds,
                    'Invalid option combination': InvalidOrder,
                    'No such client order ID': OrderNotFound,
                },
                'exact': {
                    '100': BadSymbol, // Invalid asset name
                    '101': BadSymbol, // Invalid trading pair
                    '103': InvalidOrder, // Invalid order type
                    '104': BadSymbol, // Invalid trading pair
                    '105': BadSymbol, // Trading pair temporarily disabled
                    '106': BadSymbol, // Invalid asset name
                    '107': InvalidOrder, // Invalid order amount
                    '108': InvalidOrder, // Invalid order price
                    '111': InvalidOrder, // Invalid event type
                    '201': InsufficientFunds, // Not enough balance
                    '202': InvalidOrder, // Invalid order ID
                    '203': InvalidOrder, // Order amount X order price too large
                    '204': InvalidOrder, // Bid order temporarily unavailable
                    '205': InvalidOrder, // Invalid side
                    '206': InvalidOrder, // Invalid order option combination
                    '10004': AuthenticationError, // Not authorized
                    // '10004': ExchangeError, // API key not exist
                    // '10004': ExchangeError, // User KYC not approved
                    // '10004': ExchangeError, // User account is frozen
                    // '10004': ExchangeError, // User is under deactivation process
                    // '10004': ExchangeError, // 2FA is not enabled
                    // '10004': ExchangeError, // Invalid signature
                    '10041': BadRequest, // Invalid exchange
                    '10056': BadRequest, // No registered asset
                    '10057': BadSymbol, // No registered trading pair
                    '10059': BadSymbol, // Invalid trading pair
                    '10062': BadRequest, // Invalid chart interval
                    '10069': OrderNotFound, // {"errorMessage":"No such order ID: 73152094","errorCode":10069,"errorData":"73152094"}
                    '10155': AuthenticationError, // {"errorMessage":"Invalid API key","errorCode":10155}
                    '10166': BadRequest, // Invalid chart range
                    '10212': InvalidOrder, // {"errorMessage":"Not enough amount, try increasing your order amount","errorCode":10212,"errorData":{}}
                    '10221': OrderNotFound, // No such client order ID
                    '10222': InvalidOrder, // Client order ID being used
                    '10223': InvalidOrder, // Soon the client order ID will be reusable which order has already been completed or canceled
                    '10227': InvalidOrder, // Invalid client order ID format
                    '10319': BadRequest, // Pagination is required as you have too many orders
                    '10358': InvalidOrder, // Invalid order type
                    '10359': InvalidOrder, // Invalid order side
                    '10360': InvalidOrder, // Invalid order status
                    '10361': InvalidOrder, // Invalid order time in force
                    '10362': InvalidOrder, // Invalid order protection
                    '10363': InvalidOrder, // Invalid forced completion reason
                },
            },
            'options': {
                'createMarketBuyOrderRequiresPrice': true,
            },
        });
    }

    async fetchTime (params = {}) {
        const response = await this.publicGetTime (params);
        //
        //     {"serverTime":1608327726656}
        //
        return this.safeInteger (response, 'serverTime');
    }

    async fetchMarkets (params = {}) {
        const response = await this.publicGetTradingPairs (params);
        //
        //     [
        //         {
        //             "id":1,
        //             "name":"ETH-KRW",
        //             "baseAsset":"ETH",
        //             "quoteAsset":"KRW",
        //             "baseAssetScale":8,
        //             "quoteAssetScale":0,
        //             "priceMin":1,
        //             "restApiOrderAmountMin":{
        //                 "limitAsk":{"amount":10000,"unit":"KRW"},
        //                 "limitBid":{"amount":10000,"unit":"KRW"},
        //                 "marketAsk":{"amount":0.001,"unit":"ETH"},
        //                 "marketBid":{"amount":10000,"unit":"KRW"},
        //             },
        //             "makerFeePercent":0.2,
        //             "takerFeePercent":0.2,
        //         },
        //     ]
        //
        const result = [];
        for (let i = 0; i < response.length; i++) {
            const market = response[i];
            const id = this.safeString (market, 'name');
            const numericId = this.safeInteger (market, 'id');
            const baseId = this.safeString (market, 'baseAsset');
            const quoteId = this.safeString (market, 'quoteAsset');
            const base = this.safeCurrencyCode (baseId);
            const quote = this.safeCurrencyCode (quoteId);
            const symbol = base + '/' + quote;
            const precision = {
                'price': this.safeInteger (market, 'quoteAssetScale'),
                'amount': this.safeInteger (market, 'baseAssetScale'),
            };
            const minimums = this.safeValue (market, 'restApiOrderAmountMin', {});
            const marketAsk = this.safeValue (minimums, 'marketAsk', {});
            const marketBid = this.safeValue (minimums, 'marketBid', {});
            const takerFeePercent = this.safeNumber (market, 'takerFeePercent');
            const makerFeePercent = this.safeNumber (market, 'makerFeePercent');
            const taker = parseFloat (this.decimalToPrecision (takerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE));
            const maker = parseFloat (this.decimalToPrecision (makerFeePercent / 100, ROUND, 0.00000001, TICK_SIZE));
            result.push ({
                'id': id,
                'info': market,
                'numericId': numericId,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': this.safeString (market, 'baseAsset'),
                'quoteId': this.safeString (market, 'quoteAsset'),
                'active': true,
                'taker': taker,
                'maker': maker,
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': this.safeNumber (marketAsk, 'amount'),
                        'max': undefined,
                    },
                    'price': {
                        'min': this.safeNumber (market, 'priceMin'),
                        'max': undefined,<commit_msg>gopax-fetchMarkets<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, InvalidOrder, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound, InvalidAddress, BadRequest } = require ('./base/errors');
const { TRUNCATE, ROUND, TICK_SIZE } = require ('./base/functions/number');
const Precise = require ('./base/Precise');

//  ---------------------------------------------------------------------------

module.exports = class gopax extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'gopax',
            'name': 'GOPAX',
            'countries': [ 'KR' ], // South Korea
            'version': 'v1',
            'rateLimit': 50,
            'hostname': 'gopax.co.kr', // or 'gopax.com'
            'certified': true,
            'pro': true,
            'has': {
                'cancelOrder': true,
                'createMarketOrder': true,
                'createOrder': true,
                'fetchBalance': true,
                'fetchCurrencies': true,
                'fetchDepositAddress': 'emulated',
                'fetchDepositAddresses': true,
                'fetchMarkets': true,
                'fetchMyTrades': true,
                'fetchOHLCV': true,
                'fetchOpenOrders': true,
                'fetchOrder': true,
                'fetchOrderBook': true,
                'fetchOrders': true,
                'fetchTicker': true,
                'fetchTickers': true,
                'fetchTime': true,
                'fetchTrades': true,
                'fetchTransactions': true,
            },
            'timeframes': {
                '1m': '1',
                '5m': '5',
                '30m': '30',
                '1d': '1440',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/102897212-ae8a5e00-4478-11eb-9bab-91507c643900.jpg',
                'api': {
                    'public': 'https://api.{hostname}', // or 'https://api.gopax.co.kr'
                    'private': 'https://api.{hostname}',
                },
                'www': 'https://www.gopax.co.kr',
                'doc': 'https://gopax.github.io/API/index.en.html',
                'fees': 'https://www.gopax.com/feeinfo',
            },
            'api': {
                'public': {
                    'get': [
                        'notices',
                        'assets',
                        'price-tick-size',
                        'trading-pairs',
                        'trading-pairs/{tradingPair}/ticker',
                        'trading-pairs/{tradingPair}/book',
                        'trading-pairs/{tradingPair}/trades',
                        'trading-pairs/{tradingPair}/stats',
                        'trading-pairs/{tradingPair}/price-tick-size',
                        'trading-pairs/stats',
                        'trading-pairs/{tradingPair}/candles',
                        'time',
                    ],
                },
                'private': {
                    'get': [
                        'balances',
                        'balances/{assetName}',
                        'orders',
                        'orders/{orderId}',
                        'orders/clientOrderId/{clientOrderId}',
                        'trades',
                        'deposit-withdrawal-status',
                        'crypto-deposit-addresses',
                        'crypto-withdrawal-addresses',
                    ],
                    'post': [
                        'orders',
                    ],
                    'delete': [
                        'orders/{orderId}',
                        'orders/clientOrderId/{clientOrderId}',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'percentage': true,
                    'tierBased': false,
                    'maker': 0.04 / 100,
                    'taker': 0.04 / 100,
                },
            },
            'exceptions': {
                'broad': {
                    'ERROR_INVALID_ORDER_TYPE': InvalidOrder,
                    'ERROR_INVALID_AMOUNT': InvalidOrder,
                    'ERROR_INVALID_TRADING_PAIR': BadSymbol, // Unlikely to be triggered, due to ccxt.gopax.js implementation
                    'No such order ID': OrderNotFound, // {"errorMessage":"No such order ID","errorCode":202,"errorData":"Order server error: 202"}
                    // 'Not enough amount': InsufficientFunds, // {"errorMessage":"Not enough amount, try increasing your order amount","errorCode":10212,"errorData":{}}
                    'Forbidden order type': InvalidOrder,
                    'the client order ID will be reusable which order has already been completed or canceled': InvalidOrder,
                    'ERROR_NO_SUCH_TRADING_PAIR': BadSymbol, // Unlikely to be triggered, due to ccxt.gopax.js implementation
                    'ERROR_INVALID_ORDER_SIDE': InvalidOrder,
                    'ERROR_NOT_HEDGE_TOKEN_USER': InvalidOrder,
                    'ORDER_EVENT_ERROR_NOT_ALLOWED_BID_ORDER': InvalidOrder, // Triggered only when the exchange is locked
                    'ORDER_EVENT_ERROR_INSUFFICIENT_BALANCE': InsufficientFunds,
                    'Invalid option combination': InvalidOrder,
                    'No such client order ID': OrderNotFound,
                },
                'exact': {
                    '100': BadSymbol, // Invalid asset name
                    '101': BadSymbol, // Invalid trading pair
                    '103': InvalidOrder, // Invalid order type
                    '104': BadSymbol, // Invalid trading pair
                    '105': BadSymbol, // Trading pair temporarily disabled
                    '106': BadSymbol, // Invalid asset name
                    '107': InvalidOrder, // Invalid order amount
                    '108': InvalidOrder, // Invalid order price
                    '111': InvalidOrder, // Invalid event type
                    '201': InsufficientFunds, // Not enough balance
                    '202': InvalidOrder, // Invalid order ID
                    '203': InvalidOrder, // Order amount X order price too large
                    '204': InvalidOrder, // Bid order temporarily unavailable
                    '205': InvalidOrder, // Invalid side
                    '206': InvalidOrder, // Invalid order option combination
                    '10004': AuthenticationError, // Not authorized
                    // '10004': ExchangeError, // API key not exist
                    // '10004': ExchangeError, // User KYC not approved
                    // '10004': ExchangeError, // User account is frozen
                    // '10004': ExchangeError, // User is under deactivation process
                    // '10004': ExchangeError, // 2FA is not enabled
                    // '10004': ExchangeError, // Invalid signature
                    '10041': BadRequest, // Invalid exchange
                    '10056': BadRequest, // No registered asset
                    '10057': BadSymbol, // No registered trading pair
                    '10059': BadSymbol, // Invalid trading pair
                    '10062': BadRequest, // Invalid chart interval
                    '10069': OrderNotFound, // {"errorMessage":"No such order ID: 73152094","errorCode":10069,"errorData":"73152094"}
                    '10155': AuthenticationError, // {"errorMessage":"Invalid API key","errorCode":10155}
                    '10166': BadRequest, // Invalid chart range
                    '10212': InvalidOrder, // {"errorMessage":"Not enough amount, try increasing your order amount","errorCode":10212,"errorData":{}}
                    '10221': OrderNotFound, // No such client order ID
                    '10222': InvalidOrder, // Client order ID being used
                    '10223': InvalidOrder, // Soon the client order ID will be reusable which order has already been completed or canceled
                    '10227': InvalidOrder, // Invalid client order ID format
                    '10319': BadRequest, // Pagination is required as you have too many orders
                    '10358': InvalidOrder, // Invalid order type
                    '10359': InvalidOrder, // Invalid order side
                    '10360': InvalidOrder, // Invalid order status
                    '10361': InvalidOrder, // Invalid order time in force
                    '10362': InvalidOrder, // Invalid order protection
                    '10363': InvalidOrder, // Invalid forced completion reason
                },
            },
            'options': {
                'createMarketBuyOrderRequiresPrice': true,
            },
        });
    }

    async fetchTime (params = {}) {
        const response = await this.publicGetTime (params);
        //
        //     {"serverTime":1608327726656}
        //
        return this.safeInteger (response, 'serverTime');
    }

    async fetchMarkets (params = {}) {
        const response = await this.publicGetTradingPairs (params);
        //
        //     [
        //         {
        //             "id":1,
        //             "name":"ETH-KRW",
        //             "baseAsset":"ETH",
        //             "quoteAsset":"KRW",
        //             "baseAssetScale":8,
        //             "quoteAssetScale":0,
        //             "priceMin":1,
        //             "restApiOrderAmountMin":{
        //                 "limitAsk":{"amount":10000,"unit":"KRW"},
        //                 "limitBid":{"amount":10000,"unit":"KRW"},
        //                 "marketAsk":{"amount":0.001,"unit":"ETH"},
        //                 "marketBid":{"amount":10000,"unit":"KRW"},
        //             },
        //             "makerFeePercent":0.2,
        //             "takerFeePercent":0.2,
        //         },
        //     ]
        //
        const result = [];
        for (let i = 0; i < response.length; i++) {
            const market = response[i];
            const id = this.safeString (market, 'name');
            const numericId = this.safeInteger (market, 'id');
            const baseId = this.safeString (market, 'baseAsset');
            const quoteId = this.safeString (market, 'quoteAsset');
            const base = this.safeCurrencyCode (baseId);
            const quote = this.safeCurrencyCode (quoteId);
            const symbol = base + '/' + quote;
            const precision = {
                'price': this.safeInteger (market, 'quoteAssetScale'),
                'amount': this.safeInteger (market, 'baseAssetScale'),
            };
            const minimums = this.safeValue (market, 'restApiOrderAmountMin', {});
            const marketAsk = this.safeValue (minimums, 'marketAsk', {});
            const marketBid = this.safeValue (minimums, 'marketBid', {});
            const takerFeePercentString = this.safeString (market, 'takerFeePercent');
            const makerFeePercentString = this.safeString (market, 'makerFeePercent');
            const taker = this.parseNumber (Precise.stringDiv (takerFeePercentString, '100'));
            const maker = this.parseNumber (Precise.stringDiv (makerFeePercentString, '100'));
            result.push ({
                'id': id,
                'info': market,
                'numericId': numericId,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': this.safeString (market, 'baseAsset'),
                'quoteId': this.safeString (market, 'quoteAsset'),
                'active': true,
                'taker': taker,
                'maker': maker,
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': this.safeNumber (marketAsk, 'amount'),
                        'max': undefined,
                    },
                    'price': {
                        'min': this.safeNumber (market, 'priceMin'),
                        'max': undefined,
{'fraction_non_alphanumeric': 0.132736123041682, 'fraction_numerical': 0.02822432200269972, 'mean_word_length': 1.295586854460094, 'pattern_counts': {'":': 74, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 14, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1814281', 'n_tokens_mistral': 6563, 'n_tokens_neox': 5770, 'n_words': 1379}